diff --git a/docs/html/about/about_toc.cs b/docs/html/about/about_toc.cs new file mode 100644 index 0000000000000000000000000000000000000000..04cc5a39f661047cab65e3b33e3cf621b922a146 --- /dev/null +++ b/docs/html/about/about_toc.cs @@ -0,0 +1,44 @@ + \ No newline at end of file diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..c18d398b22ce8ee696af6ea04edbc74d460624bb --- /dev/null +++ b/docs/html/about/dashboards/index.jd @@ -0,0 +1,235 @@ +page.title=Dashboards +header.hide=1 +@jd:body + + + +

Platform Versions

+ +

This page provides data about the relative number of active devices +running a given version of the Android platform. This can help you +understand the landscape of device distribution and decide how to prioritize +the development of your application features for the devices currently in +the hands of users. For information about how to target your application to devices based on +platform version, read about API levels.

+ + +

Current Distribution

+ +

The following pie chart and table is based on the number of Android devices that have accessed +Google Play within a 14-day period ending on the data collection date noted below.

+ +
+ + + + + + + + + + + + + + + + + + + + + +
VersionCodenameAPI LevelDistribution
1.5Cupcake 30.3%
1.6Donut 40.6%
2.1Eclair 75.2%
2.2Froyo 819.1%
2.3 - 2.3.2 + Gingerbread 90.4%
2.3.3 - 2.3.7 + 1064.6%
3.1Honeycomb 120.7%
3.2132%
4.0 - 4.0.2Ice Cream Sandwich140.4%
4.0.3 - 4.0.4 156.7%
+ + +
+ +
+ + +
+ +

Data collected during a 14-day period ending on June 1, 2012

+ + +

Historical Distribution

+ +

The following stacked line graph provides a history of the relative number of +active Android devices running different versions of the Android platform. It also provides a +valuable perspective of how many devices your application is compatible with, based on the +platform version.

+ +

Notice that the platform versions are stacked on top of each other with the oldest active +version at the top. This format indicates the total percent of active devices that are compatible +with a given version of Android. For example, if you develop your application for +the version that is at the very top of the chart, then your application is +compatible with 100% of active devices (and all future versions), because all Android APIs are +forward compatible. Or, if you develop your application for a version lower on the chart, +then it is currently compatible with the percentage of devices indicated on the y-axis, where the +line for that version meets the y-axis on the right.

+ +

Each dataset in the timeline is based on the number of Android devices that accessed +Google Play within a 14-day period ending on the date indicated on the x-axis.

+ + + +

Last historical dataset collected during a 14-day period ending on June 1, 2012

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

Screen Sizes and Densities

+ +

This section provides data about the relative number of active devices that have a particular +screen configuration, defined by a combination of screen size and density. To simplify the way that +you design your user interfaces for different screen configurations, Android divides the range of +actual screen sizes and densities into:

+ + + +

For information about how you can support multiple screen configurations in your +application, see Supporting Multiple +Screens.

+ +

Note: This data is based on the number +of Android devices that have accessed Google Play within a 7-day period +ending on the data collection date noted below.

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ldpimdpihdpixhdpi
small2.3% 2.4%
normal0.7% 26.2% 57.8% 0.9%
large0.3% 2%
xlarge 7.4%
+ + +
+ +
+ + +
+ +

Data collected during a 7-day period ending on May 1, 2012

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

Open GL Version

+ +

This section provides data about the relative number of active devices that support a particular +version of OpenGL ES. Note that support for one particular version of OpenGL ES also implies +support for any lower version (for example, support for version 2.0 also implies support for +1.1).

+ +

To declare which version of OpenGL ES your application requires, you should use the {@code +android:glEsVersion} attribute of the {@code <uses-feature>} +element. You can also use the {@code +<supports-gl-texture>} element to declare the GL compression formats that your application +uses.

+ +

Note: This data is based on the number +of Android devices that have accessed Google Play within a 7-day period +ending on the data collection date noted below.

+ + +
+ + + + + + + + + + + +
OpenGL ES VersionDistribution
1.1 only +9.9%
2.0 & 1.1 +90.1%
+
+ +
+ + +
+ + +

Data collected during a 7-day period ending on June 4, 2012

diff --git a/docs/html/about/flexible.jd b/docs/html/about/flexible.jd new file mode 100644 index 0000000000000000000000000000000000000000..ec3a44ccd2a24aadb2a951a4d779c6c0ef7dcbef --- /dev/null +++ b/docs/html/about/flexible.jd @@ -0,0 +1,34 @@ +page.title=Flexible Framework +walkthru=1 + +@jd:body + + + +
Android's flexible framework means it runs on more devices and reaches more +users
+ +

Android powers millions of devices around the world and in a variety of form-factors. The Android +framework is specially built to run apps on more than just one screen size and hardware +configuration. As an app developer, Android's scale and variety offers you the potential to quickly +reach millions of users.

+ +

Android apps are flexible and easily adapt to the device on which they are running. Although the +system scales your assets when necessary, you can provide alternative app resources that are +optimized for specific device categories, such as the screen size and density. Android applies the +appropriate resources when running your app, based on the current device’s configuration.

+ +
You're in control of which devices can install your app
+ +

Some devices provide a different user experience when using apps, but you’re always in control of +how your app behaves on each device. If you publish your app on Google Play, you also have +control over which kinds of devices are allowed to install your app and you can closely control how +your app is distributed.

+ +

Every device that includes Google Play has been certified compatible. This means that +the device has passed a rigorous test suite to ensure that the device uses a version of Android that +supports all the platform APIs and will successfully run your app.

\ No newline at end of file diff --git a/docs/html/about/index.jd b/docs/html/about/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..c2d642628c7153970bc410ec959d17ae30f93b57 --- /dev/null +++ b/docs/html/about/index.jd @@ -0,0 +1,157 @@ +page.title=Android, the world's most popular mobile platform +walkthru=0 +header.hide=0 + +@jd:body + +
+

Android powers hundreds of millions of mobile devices in more than 190 +countries around the world. It's the largest installed base of any mobile platform +and growing fast—every day another 900,000 users power up their +Android devices for the first time and start looking for apps, games, +and other digital content.

+ +
+

Android gives you a world-class platform for creating apps and games for +Android users everywhere, as well as an open marketplace for distributing +to them instantly.

+
+
+ + +
+ Android growth in device activations
+ + +

Global partnerships and large installed base

+ +

Building on the contributions of the open-source Linux community and more +than 300 hardware, software, and carrier partners, Android has rapidly become +the fastest-growing mobile OS.

+ +
Every day more than 900,000 new Android devices are activated worldwide.
+ +

Android’s openness has made it a favorite for consumers and developers alike, +driving strong growth in app consumption. Android users download more than +1 billion apps and games from Google Play each month.

+ +

With it's partners, Android is continuously pushing the boundaries of hardware and software +forward to bring new capabilities to users and developers. For developers, +Android innovation lets you build powerful, differentiated applications +that use the latest mobile technologies.

+ + + +

Powerful development framework

+ +
Easily optimize a single binary for phones, tablets, and other devices.
+ +

Android gives you everything you need to build best-in-class app experiences. +It gives you a single application model that lets you deploy +your apps broadly to hundreds of millions of users across a wide range of +devices—from phones to tablets and beyond.

+ +

Android also gives you tools for creating apps that look great and take +advantage of the hardware capabilities available on each device. It +automatically adapts your UI to look it's best on each device, while giving you +as much control as you want over your UI on different device +types.

+ +

For example, you can create a single app binary that's optimized for +both phone and tablet form factors. You declare your UI in lightweight sets of XML +resources, one set for parts of the UI that are common to all form factors and +other sets for optimzations specific to phones or tablets. +At runtime, Android applies the correct resource sets based on its screen size, +density, locale, +and so on.

+ + +

To help you develop efficiently, the Android + Developer Tools +offers a full Java IDE with advanced features for developing, debugging, and +packaging Android apps. Using the IDE, you can develop on any available Android +device or create virtual devices that emulate any hardware configuration.

+ +
A billion downloads a month and growing. Get your apps in front +of millions of users at Google's scale.
+ +

Open marketplace for distributing your apps

+ +

Google Play is the premier marketplace for selling and distributing Android apps. +When you publish an app on Google Play, you reach the huge installed base of +Android.

+ +
+ +
+ +

As an open marketplace, Google Play puts you in control of how you sell your +products. You can publish whenever you want, as often as you want, and to the +customers you want. You can distribute broadly to all markets and +devices or focus on specific segments, devices, or ranges of hardware +capabilities.

+ +

You can monetize in the way that works best for your business—priced or +free, with in-app products or subscriptions—for highest engagement and +revenues. You also have complete control of the pricing for your apps +and in-app products and can set or change prices in any supported currency at +any time.

+ +

Beyond growing your customer base, Google Play helps you build visibility and +engagement across your apps and brand. As your apps rise in popularity, Google +Play gives them higher placement in weekly "top" charts and rankings, and for +the best apps promotional slots in curated collections. +

+ +

Preinstalled on hundreds of millions of Android devices around the world, +Google Play can be a growth engine for your business.

+ +

GET STARTED

+ +
+
+

Developer Story: Robot Invader

+ +
+

Robot Invader chose + Android as the launch platform for their first game, + Wind-up + Knight. +

+

+ Hear from the developers themselves how Android helped them reach more + than 100 devices with a single app binary, then iterate rapidly to ensure + a great experience for users. +

+
+ +
+
\ No newline at end of file diff --git a/docs/html/about/marketplace.jd b/docs/html/about/marketplace.jd new file mode 100644 index 0000000000000000000000000000000000000000..34f57a5588b557f5648ad675fc0769149c6db659 --- /dev/null +++ b/docs/html/about/marketplace.jd @@ -0,0 +1,62 @@ +page.title=Open Marketplace +walkthru=1 + +@jd:body + + + +

Android offers an open distribution model, not a walled garden. Once you’ve developed an +app for Android and want to distribute it, you have choice.

+ +

Your final application is contained in an APK file that you can make available to users any +way you want. For example, you can upload it to your own web site to allow visitors to +install it onto their devices. More often, you’ll want to use a trusted +marketplace where users can discover and search for your apps.

+ +

How you choose to distribute your app affects precisely how many users your app will reach. Which +distribution provider you choose also affects the kinds of services available to you as a publisher, +such as licensing and in-app billing APIs, user bug reports, installation analytics, marketing +services, and more.

+ +

Among your choices is Google Play, the premier marketplace for selling and distributing apps +to Android users around the world. When you publish an app on Google Play, you reach hundreds of +millions of customers in over 130 countries.

+ + +

Your business, your customers

+ +
Google Play makes your apps available to your customers +immediately
+ +

As an open marketplace, Google Play puts you in control of your business and makes it easy for +you to manage how you sell your products. You can publish whenever you want, as often as you want, +and to the exact set of customers you want.

+ + +

Visibility for your apps

+ +

Beyond growing your customer base, Google Play helps you build visibility and engagement across +your apps and brand. As your apps rise in popularity, Google Play gives you higher placement in +weekly "top" lists and offers promotional slots in curated collections. You can engage customers +using rich, colorful product pages that feature app screenshots, videos, and user reviews, as well +as cross-marketing links to your other products.

+ +

Flexible monetizing and distribution

+ +
You can distribute +your apps free or priced and you can sell in-app products for additional revenue
+ +

Google Play offers a choice of monetizing options to meet your business needs. You control the +pricing of your apps and in-app products—you can set and change prices at any time, even +individually in local currencies around the world. On purchase, Google Play handles transactions in +the buyer’s currency and makes payouts in your own currency.

+ + +

After publishing, you can manage the distribution of your app. You can distribute broadly to all +markets and devices or focus on specific segments, devices, or ranges of hardware capabilities. +Google Play provides the tools for controlling distribution and ensures that your app is available +only to the users who you are targeting.

diff --git a/docs/html/about/start.jd b/docs/html/about/start.jd new file mode 100644 index 0000000000000000000000000000000000000000..af8344d0bb729139032874354e52385a7cee3f38 --- /dev/null +++ b/docs/html/about/start.jd @@ -0,0 +1,63 @@ +page.title=Get Started +walkthru=0 + +@jd:body + +

Everything you need to start developing apps for Android is available here on +developer.android.com. You'll find everything from the developer SDK, API documentation, and design +guidelines, to information about the current device landscape and how you can distribute and +monetize your app.

+ +

No two apps are built in the same way, but we've structured the information you need to build an +app into the following three sections that represent the general order for app development. + + + + +

+

1. Design

+ +

Before you write a single line of code, you need to design the user interface and make it fit +the Android user experience. Although you may know what a user will do with your app, you +should pause to focus on how a user will interact with it. Your design should be sleek, +simple, powereful, and tailored to the Android experience.

+ +

So whether your a one-man shop or a large team, you should study the Design guidelines first.

+
+ +
+

2. Develop

+

Once your design is finalized, all you need are the tools to turn your app ideas into reality. +Android's framework provides you the APIs to build apps that take full advantage of +device hardware, connected accessory devices, the Internet, software features, and more. +With the power of Android, there's no limit to the power of your apps.

+ +

Everything you need to learn about the app framework and developer tools is in the Develop documentation.

+ +
+ + +
+

3. Distribute

+

Now your app is complete. You've built it to support a variety of screen sizes and +densities, and tested it on the Android emulator and on real devices. You're ready to ship your app.

+ +

How you proceed depends on a variety of factors, such as your monetization strategy and which +types of devices your app supports. Everything you need to get started with this process is +available in the Distribute section.

+
+ + +

Now that you know what's available, get started by installing the Android SDK.

\ No newline at end of file diff --git a/docs/html/sdk/android-1.1.jd b/docs/html/about/versions/android-1.1.jd similarity index 100% rename from docs/html/sdk/android-1.1.jd rename to docs/html/about/versions/android-1.1.jd diff --git a/docs/html/sdk/android-1.5-highlights.jd b/docs/html/about/versions/android-1.5-highlights.jd similarity index 100% rename from docs/html/sdk/android-1.5-highlights.jd rename to docs/html/about/versions/android-1.5-highlights.jd diff --git a/docs/html/sdk/android-1.5.jd b/docs/html/about/versions/android-1.5.jd similarity index 97% rename from docs/html/sdk/android-1.5.jd rename to docs/html/about/versions/android-1.5.jd index 9ed798c2a8f8fd4307c8170d3d5f33700461ad82..78dcbd7610404309b888fc816712b275c55c5540 100644 --- a/docs/html/sdk/android-1.5.jd +++ b/docs/html/about/versions/android-1.5.jd @@ -31,7 +31,7 @@ Differences Report »

See Also

    -
  1. Adding SDK Components
  2. +
  3. Exploring the SDK
@@ -54,14 +54,14 @@ compliant and includes no external libraries.

To get started developing or testing against the Android {@sdkPlatformVersion} platform, use the Android SDK and AVD Manager tool to download the platform into your Android 1.6 or later SDK. For more information, -see Adding SDK -Components.

+see Exploring the +SDK.

Platform Highlights

For a list of new user features and platform highlights, see the Android +href="http://developer.android.com/about/versions/android-{@sdkPlatformVersion}-highlights.html">Android {@sdkPlatformVersion} Platform Highlights document.

Revisions

@@ -184,7 +184,7 @@ application, you need to set the proper value, "{@sdkPlatformApiLevel}", in the element in your application's manifest.

For more information about how to use API Level, see the API Levels document.

+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Levels document.

Framework API Changes

diff --git a/docs/html/sdk/android-1.6-highlights.jd b/docs/html/about/versions/android-1.6-highlights.jd similarity index 98% rename from docs/html/sdk/android-1.6-highlights.jd rename to docs/html/about/versions/android-1.6-highlights.jd index f0a50fb090b0666c5e54ffc5cfc7033ac687b32a..2ee1d807029b8931938e6f22994ea733f52250c5 100644 --- a/docs/html/sdk/android-1.6-highlights.jd +++ b/docs/html/about/versions/android-1.6-highlights.jd @@ -208,6 +208,6 @@ application.

New Framework APIs

For a detailed overview of new APIs, see the -Version Notes. +Version Notes. For a complete report of all API changes, see the API Differences Report. diff --git a/docs/html/sdk/android-1.6.jd b/docs/html/about/versions/android-1.6.jd similarity index 98% rename from docs/html/sdk/android-1.6.jd rename to docs/html/about/versions/android-1.6.jd index a01a5f69643ea9203589d0a9088d8306b9744921..2a66cd3e7e5a2a76d0333d4ab1c2f86b6fab2cba 100644 --- a/docs/html/sdk/android-1.6.jd +++ b/docs/html/about/versions/android-1.6.jd @@ -31,7 +31,7 @@ Differences Report »

See Also

    -
  1. Adding SDK Components
  2. +
  3. Exploring the SDK
@@ -55,14 +55,14 @@ and includes no external libraries.

To get started developing or testing against the Android {@sdkPlatformVersion} platform, use the Android SDK and AVD Manager tool to download the latest Android 1.6 platform into your Android 1.6 or later SDK. For -more information, see Adding SDK -Components.

+more information, see Exploring the +SDK.

Platform Highlights

For a list of new user features and platform highlights, see the Android +href="http://developer.android.com/about/versions/android-{@sdkPlatformVersion}-highlights.html">Android {@sdkPlatformVersion} Platform Highlights document.

@@ -208,7 +208,7 @@ application, you need to set the proper value, "{@sdkPlatformApiLevel}", in the element in your application's manifest.

For more information about how to use API Level, see the API Levels document.

+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Levels document.

Framework API Changes

diff --git a/docs/html/sdk/android-2.0-highlights.jd b/docs/html/about/versions/android-2.0-highlights.jd similarity index 98% rename from docs/html/sdk/android-2.0-highlights.jd rename to docs/html/about/versions/android-2.0-highlights.jd index d4d13fcc78a7609b7091ad4682f85553f0d319a4..2ba9ac76f6f9d8fb527fe3fbfd20cc9409752167 100644 --- a/docs/html/sdk/android-2.0-highlights.jd +++ b/docs/html/about/versions/android-2.0-highlights.jd @@ -192,7 +192,7 @@ hardware acceleration.

Android 2.0 includes several new developer APIs. For an overview of new APIs, see the -Android 2.0 version notes.

+Android 2.0 version notes.

For a complete report of all API changes, see the API Differences Report.

diff --git a/docs/html/sdk/android-2.0.1.jd b/docs/html/about/versions/android-2.0.1.jd similarity index 96% rename from docs/html/sdk/android-2.0.1.jd rename to docs/html/about/versions/android-2.0.1.jd index 0c8afb61fb8fdb3cbd0e7e9a70497104a2afbdb1..bcba7177b684a1ed519e78fe9909827875f67342 100644 --- a/docs/html/sdk/android-2.0.1.jd +++ b/docs/html/about/versions/android-2.0.1.jd @@ -31,7 +31,7 @@ differences report »

See Also

    -
  1. Adding SDK Components
  2. +
  3. Exploring the SDK
@@ -56,14 +56,14 @@ includes no external libraries.

To get started developing or testing against the Android {@sdkPlatformVersion} platform, use the Android SDK and AVD Manager tool to download the platform into your Android 1.6 or later SDK. For more information, -see Adding SDK -Components.

+see Exploring the +SDK.

Platform Highlights

For a list of new user features and platform highlights, see the Android +href="http://developer.android.com/about/versions/android-2.0-highlights.html">Android 2.0 Platform Highlights document.

Revisions

@@ -246,7 +246,7 @@ through Settings.

Ant Support

@@ -257,7 +257,7 @@ through Settings.

framework API provided by the Android {@sdkPlatformVersion} platform. Note, however, that Android 2.0.1 is a minor release to Android 2.0, so for more information about the changes made to in Android 2.0, please refer to the -Android 2.0 version notes.

+Android 2.0 version notes.

API level

@@ -274,7 +274,7 @@ set the proper value, "{@sdkPlatformApiLevel}", in the attributes of the & element in your application's manifest.

For more information about how to use API Level, see the API Levels document.

+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Levels document.

API changes summary

diff --git a/docs/html/sdk/android-2.0.jd b/docs/html/about/versions/android-2.0.jd similarity index 97% rename from docs/html/sdk/android-2.0.jd rename to docs/html/about/versions/android-2.0.jd index 2c319236297b7c0955314d4bd51178800c81a67e..7a12e48672e3a45a27df9a6bf0e2e909502cec12 100644 --- a/docs/html/sdk/android-2.0.jd +++ b/docs/html/about/versions/android-2.0.jd @@ -26,7 +26,7 @@ sdk.platform.majorMinor=major

See Also

    -
  1. Adding SDK Components
  2. +
  3. Exploring the SDK
@@ -49,14 +49,14 @@ compliant and includes no external libraries.

To get started developing or testing against the Android {@sdkPlatformVersion} platform, use the Android SDK and AVD Manager tool to download the platform into your SDK. For more information, -see Adding SDK -Components.

+see Exploring the +SDK.

Platform Highlights

For a list of new user features and platform highlights, see the Android +href="http://developer.android.com/about/versions/android-{@sdkPlatformVersion}-highlights.html">Android {@sdkPlatformVersion} Platform Highlights document.

Revisions

@@ -235,7 +235,7 @@ through Settings.

Ant Support

@@ -259,7 +259,7 @@ set the proper value, "{@sdkPlatformApiLevel}", in the attributes of the & element in your application's manifest.

For more information about how to use API Level, see the API Levels document.

+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Levels document.

API changes summary

diff --git a/docs/html/sdk/android-2.1.jd b/docs/html/about/versions/android-2.1.jd similarity index 96% rename from docs/html/sdk/android-2.1.jd rename to docs/html/about/versions/android-2.1.jd index 1ee833c0094c9bfe751d3a4cb048da9046e041a3..3cb0708ec42abd3606b2321634c03790899b2c73 100644 --- a/docs/html/sdk/android-2.1.jd +++ b/docs/html/about/versions/android-2.1.jd @@ -31,7 +31,7 @@ Differences Report »

See Also

    -
  1. Adding SDK Components
  2. +
  3. Exploring the SDK
@@ -55,14 +55,14 @@ includes no external libraries.

To get started developing or testing against the Android {@sdkPlatformVersion} platform, use the Android SDK and AVD Manager tool to download the platform into your SDK. For more information, -see Adding SDK -Components.

+see Exploring the +SDK.

Platform Highlights

Android {@sdkPlatformVersion} does not add significant user features, see the Android +href="http://developer.android.com/about/versions/android-2.0-highlights.html">Android 2.0 Platform Highlights document for the latest user features.

Revisions

@@ -87,7 +87,7 @@ class="toggle-content-img" alt="" />
Dependencies:
-

Requires SDK Tools r12 or +

Requires SDK Tools r12 or higher.

Notes:
@@ -164,7 +164,7 @@ application, you need to set the proper value, "{@sdkPlatformApiLevel}", in the element in your application's manifest.

For more information about how to use API Level, see the API Levels document.

+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Levels document.

Framework API Changes

diff --git a/docs/html/sdk/android-2.2-highlights.jd b/docs/html/about/versions/android-2.2-highlights.jd similarity index 100% rename from docs/html/sdk/android-2.2-highlights.jd rename to docs/html/about/versions/android-2.2-highlights.jd diff --git a/docs/html/sdk/android-2.2.jd b/docs/html/about/versions/android-2.2.jd similarity index 63% rename from docs/html/sdk/android-2.2.jd rename to docs/html/about/versions/android-2.2.jd index c22220cf7262f352c95a30ed3fb9075af909629c..361e8b695d55019610c860e0b7bd0328fccaadbd 100644 --- a/docs/html/sdk/android-2.2.jd +++ b/docs/html/about/versions/android-2.2.jd @@ -11,12 +11,8 @@ sdk.platform.majorMinor=minor

In this document

  1. Platform Highlights
  2. -
  3. Revisions
  4. API Level
  5. Framework API Changes -
  6. Built-in Applications
  7. -
  8. Locales
  9. -
  10. Emulator Skins
@@ -31,7 +27,7 @@ Differences Report »

See Also

    -
  1. Adding SDK Components
  2. +
  3. Exploring the SDK
@@ -46,113 +42,18 @@ fixes. For information on developer features and API changes, see the Framework API section.

For developers, the Android {@sdkPlatformVersion} platform is available as a -downloadable component for the Android SDK. The downloadable platform includes a -fully compliant Android library and system image, as well as a set of emulator -skins, sample applications, and more. The downloadable platform -includes no external libraries.

- -

To get started developing or testing against the Android -{@sdkPlatformVersion} platform, use the Android SDK and AVD Manager tool to -download the platform into your SDK. For more information, -see Adding SDK -Components. If you are new to Android, download the SDK Starter Package -first.

+downloadable component for the Android SDK. The downloadable platform includes +an Android library and system image, as well as a set of emulator skins and +more. To get started developing or testing against Android {@sdkPlatformVersion}, +use the Android SDK Manager to download the platform into your SDK.

Platform Highlights

For a list of new user features and platform highlights, see the Android +href="http://developer.android.com/about/versions/android-2.2-highlights.html">Android 2.2 Platform Highlights document.

-

Revisions

- -

The sections below provide notes about successive releases of -the Android {@sdkPlatformVersion} platform component for the Android SDK, as denoted by -revision number. To determine what revision(s) of the Android -{@sdkPlatformVersion} platforms are installed in your SDK environment, refer to -the "Installed Packages" listing in the Android SDK and AVD Manager.

- - -
- -

- - Android {@sdkPlatformVersion}, Revision 3 (July 2011) -

- -
- -
-
Dependencies:
-
-

Requires SDK Tools r12 or -higher.

-
-
Notes:
-
-

Improvements to the platform's rendering library to support the visual layout editor in the ADT -Eclipse plugin. This revision allows for more drawing features in ADT and fixes several -bugs in the previous rendering library. It also unlocks several editor features that were added in -ADT 12.

-
-
- -
-
- -
- -

- - Android {@sdkPlatformVersion}, Revision 2 (July 2010) -

- -
-
Dependencies:
-
-

Requires SDK Tools r6 or higher.

-
- -
System Image:
-
-
    -
  • Adds default Search Widget.
  • -
  • Includes proper provisioning for the platform's Backup Manager. For more information about how to use the Backup Manager, see Data Backup.
  • -
  • Updates the Android 2.2 system image to FRF91.
  • -
-
- -
- - - -
- -

- - Android {@sdkPlatformVersion}, Revision 1 (May 2010) -

- -
-
-
Dependencies:
-
-

Requires SDK Tools r6 or higher.

-
- -
Tools:
-
-

Adds support for building with Android library projects. See SDK Tools, r6 for information.

-
- -
-
-

API Level

@@ -170,7 +71,7 @@ application, you need to set the proper value, "{@sdkPlatformApiLevel}", in the element in your application's manifest.

For more information about how to use API Level, see the API Levels document.

+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Levels document.

Framework API Changes

@@ -348,123 +249,4 @@ href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API Differences Report.

-

Built-in Applications

- -

The system image included in the downloadable platform provides these -built-in applications:

- - - - - - -
-
    -
  • Alarm Clock
  • -
  • Browser
  • -
  • Calculator
  • -
  • Camera
  • -
  • Contacts
  • -
  • Custom Locale (developer app)
  • -
  • Dev Tools (developer app)
  • -
  • Email
  • -
-
-
    - -
  • Gallery
  • -
  • IMEs for Japanese, Chinese, and Latin text input
  • -
  • Messaging
  • -
  • Music
  • -
  • Phone
  • -
  • Settings
  • -
  • Spare Parts (developer app)
  • -
-
- - -

Locales

- -

The system image included in the downloadable platform provides a variety of -built-in locales. In some cases, region-specific strings are available for the -locales. In other cases, a default version of the language is used. The -languages that are available in the Android {@sdkPlatformVersion} system -image are listed below (with language_country/region locale -descriptor).

- - - - - - -
-
    -
  • Chinese, PRC (zh_CN)
  • -
  • Chinese, Taiwan (zh_TW)
  • -
  • Czech (cs_CZ)
  • -
  • Dutch, Netherlands (nl_NL)
  • -
  • Dutch, Belgium (nl_BE)
  • -
  • English, US (en_US)
  • -
  • English, Britain (en_GB)
  • -
  • English, Canada (en_CA)
  • -
  • English, Australia (en_AU)
  • -
  • English, New Zealand (en_NZ)
  • -
  • English, Singapore(en_SG)
  • -
  • French, France (fr_FR)
  • -
  • French, Belgium (fr_BE)
  • -
-
-
  • French, Canada (fr_CA)
  • -
  • French, Switzerland (fr_CH)
  • -
  • German, Germany (de_DE)
  • -
  • German, Austria (de_AT)
  • -
  • German, Switzerland (de_CH)
  • -
  • German, Liechtenstein (de_LI)
  • -
  • Italian, Italy (it_IT)
  • -
  • Italian, Switzerland (it_CH)
  • -
  • Japanese (ja_JP)
  • -
  • Korean (ko_KR)
  • -
  • Polish (pl_PL)
  • -
  • Russian (ru_RU)
  • -
  • Spanish (es_ES)
  • -
    - -

    Localized UI strings match the locales that are accessible -through Settings.

    - -

    Note: Android supports more locales than are listed above. However, -the entire collection of locale strings cannot fit on a single system image, so the above list is -only what's included in the system image for the SDK. All of Android's supported locales are -available in the Android Open Source Project.

    - -

    Emulator Skins

    - -

    The downloadable platform includes a set of emulator skins that you can use -for modeling your application in different screen sizes and resolutions. The -emulator skins are:

    - - -

    For more information about how to develop an application that displays -and functions properly on all Android-powered devices, see Supporting Multiple -Screens.

    diff --git a/docs/html/sdk/android-2.3-highlights.jd b/docs/html/about/versions/android-2.3-highlights.jd similarity index 92% rename from docs/html/sdk/android-2.3-highlights.jd rename to docs/html/about/versions/android-2.3-highlights.jd index b076b3de191cb4828042b26d4c2b927ddd17bd76..582bce9f81fd81114b723cf8af522ef3138b3216 100644 --- a/docs/html/sdk/android-2.3-highlights.jd +++ b/docs/html/about/versions/android-2.3-highlights.jd @@ -1,4 +1,4 @@ -page.title=Android 2.3 Platform Highlights +page.title=Gingerbread @jd:body @@ -14,8 +14,7 @@ page.title=Android 2.3 Platform Highlights } #jd-content div.video { float:right; - padding:0 60px 40px; - margin-top:-15px; + padding:0 0 0 40px; } #jd-content table.columns { margin:0 0 1em 0; @@ -38,16 +37,6 @@ page.title=Android 2.3 Platform Highlights } -
    - - - - - -
    -

    The Android 2.3 platform introduces many new and exciting features for users and developers. This document provides a glimpse at some of the new features and technologies in Android 2.3. For detailed information about the new developer APIs, see the Android 2.3 version notes.

    New User Features

    - - + +

    UI refinements for simplicity and speed

    @@ -98,8 +89,10 @@ the key and sliding to select a character.

    -
    -
    +
    +

    One-touch word selection and copy/paste

    @@ -116,8 +109,10 @@ modes, no use of a trackball is needed.

    -
    -
    +
    +

    Improved power management

    @@ -147,8 +142,10 @@ necessary stop an application or report feedback to its developer.

    managing information and relationships.

    -

    -
    +

    +

    Internet calling

    @@ -162,7 +159,8 @@ Additionally, support for the platform's SIP and internet calling features on specific devices is determined by their manufacturers and associated carriers.

    -
    +

    Near-field communications

    diff --git a/docs/html/sdk/android-2.3.3.jd b/docs/html/about/versions/android-2.3.3.jd similarity index 53% rename from docs/html/sdk/android-2.3.3.jd rename to docs/html/about/versions/android-2.3.3.jd index 405c063fa857a7e5e21ed40d271396f8e723f352..55ff346ac242b9363cbd81d5ba280a1c3168831d 100644 --- a/docs/html/sdk/android-2.3.3.jd +++ b/docs/html/about/versions/android-2.3.3.jd @@ -10,12 +10,8 @@ sdk.platform.apiLevel=10

    In this document

      -
    1. Revisions
    2. API Overview
    3. API Level
    4. -
    5. Built-in Applications
    6. -
    7. Locales
    8. -
    9. Emulator Skins

    Reference

    @@ -25,11 +21,6 @@ href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API Differences Report » -

    See Also

    -
      -
    1. Adding SDK Components
    2. -
    -
    @@ -40,78 +31,11 @@ Differences Report » and APIs to the Android 2.3 platform.

    For developers, the Android {@sdkPlatformVersion} platform is available as a -downloadable component for the Android SDK. The downloadable platform includes -an Android library and system image, as well as a set of emulator -skins and more. The downloadable platform -includes no external libraries.

    - -

    To get started developing or testing against Android -{@sdkPlatformVersion}, use the Android SDK Manager to -download the platform into your SDK. For more information, -see Adding SDK -Components. If you are new to Android, download the SDK Starter Package -first.

    - -

    For a high-level introduction to Android 2.3, see the Platform Highlights.

    - - -

    Revisions

    - -

    The sections below provide notes about successive releases of -the Android {@sdkPlatformVersion} platform component for the Android SDK, as denoted by -revision number. To determine what revision(s) of the Android -{@sdkPlatformVersion} platforms are installed in your SDK environment, refer to -the "Installed Packages" listing in the Android SDK and AVD Manager.

    - - -
    - -

    - - Android {@sdkPlatformVersion}, Revision 2 (July 2011) -

    - -
    - -
    -
    Dependencies:
    -
    -

    Requires SDK Tools r12 or -higher.

    -
    -
    Notes:
    -
    -

    Improvements to the platform's rendering library to support the visual layout editor in the ADT -Eclipse plugin. This revision allows for more drawing features in ADT and fixes several -bugs in the previous rendering library. It also unlocks several editor features that were added in -ADT 12.

    -
    -
    - -
    -
    - -
    +downloadable component for the Android SDK. The downloadable platform includes +an Android library and system image, as well as a set of emulator skins and +more. To get started developing or testing against Android {@sdkPlatformVersion}, +use the Android SDK Manager to download the platform into your SDK.

    -

    - - Android {@sdkPlatformVersion}, Revision 1 (February 2011) -

    - -
    -
    -
    Dependencies:
    -
    -

    Requires SDK Tools r9 or higher.

    -
    -
    - -
    -

    API Overview

    @@ -264,156 +188,5 @@ manifest. If your application is designed to run only on Android 2.3 and higher, declaring the attribute prevents the application from being installed on earlier versions of the platform.

    -

    For more information about how to use API Level, see the API Levels document.

    - -

    Built-in Applications

    - -

    The system image included in the downloadable platform provides these -built-in applications:

    - - - - - - -
    -
      -
    • Browser
    • -
    • Calculator
    • -
    • Camera
    • -
    • Clock
    • -
    • Contacts
    • -
    • Cusom Locale
    • -
    • Dev Tools
    • -
    • Downloads
    • -
    • Email
    • -
    -
    -
      -
    • Gallery
    • -
    • IMEs for Japanese, Chinese, and Latin text input
    • -
    • Messaging
    • -
    • Music
    • -
    • Phone
    • -
    • Search
    • -
    • Settings
    • -
    • Spare Parts (developer app)
    • -
    • Speech Recorder
    • -
    -
    - - -

    Locales

    - -

    The system image included in the downloadable SDK platform provides a variety of -built-in locales. In some cases, region-specific strings are available for the -locales. In other cases, a default version of the language is used. The -languages that are available in the Android {@sdkPlatformVersion} system -image are listed below (with language_country/region locale -descriptor).

    - - - - - - -
    -
      -
    • Arabic, Egypt (ar_EG)
    • -
    • Arabic, Israel (ar_IL)
    • -
    • Bulgarian, Bulgaria (bg_BG)
    • -
    • Catalan, Spain (ca_ES)
    • -
    • Czech, Czech Republic (cs_CZ)
    • -
    • Danish, Denmark(da_DK)
    • -
    • German, Austria (de_AT)
    • -
    • German, Switzerland (de_CH)
    • -
    • German, Germany (de_DE)
    • -
    • German, Liechtenstein (de_LI)
    • -
    • Greek, Greece (el_GR)
    • -
    • English, Australia (en_AU)
    • -
    • English, Canada (en_CA)
    • -
    • English, Britain (en_GB)
    • -
    • English, Ireland (en_IE)
    • -
    • English, India (en_IN)
    • -
    • English, New Zealand (en_NZ)
    • -
    • English, Singapore(en_SG)
    • -
    • English, US (en_US)
    • -
    • English, South Africa (en_ZA)
    • -
    • Spanish (es_ES)
    • -
    • Spanish, US (es_US)
    • -
    • Finnish, Finland (fi_FI)
    • -
    • French, Belgium (fr_BE)
    • -
    • French, Canada (fr_CA)
    • -
    • French, Switzerland (fr_CH)
    • -
    • French, France (fr_FR)
    • -
    • Hebrew, Israel (he_IL)
    • -
    • Hindi, India (hi_IN)
    • -
    -
    -
  • Croatian, Croatia (hr_HR)
  • -
  • Hungarian, Hungary (hu_HU)
  • -
  • Indonesian, Indonesia (id_ID)
  • -
  • Italian, Switzerland (it_CH)
  • -
  • Italian, Italy (it_IT)
  • -
  • Japanese (ja_JP)
  • -
  • Korean (ko_KR)
  • -
  • Lithuanian, Lithuania (lt_LT)
  • -
  • Latvian, Latvia (lv_LV)
  • -
  • Norwegian-Bokmol, Norway(nb_NO)
  • -
  • Dutch, Belgium (nl_BE)
  • -
  • Dutch, Netherlands (nl_NL)
  • -
  • Polish (pl_PL)
  • -
  • Portuguese, Brazil (pt_BR)
  • -
  • Portuguese, Portugal (pt_PT)
  • -
  • Romanian, Romania (ro_RO)
  • -
  • Russian (ru_RU)
  • -
  • Slovak, Slovakia (sk_SK)
  • -
  • Slovenian, Slovenia (sl_SI)
  • -
  • Serbian (sr_RS)
  • -
  • Swedish, Sweden (sv_SE)
  • -
  • Thai, Thailand (th_TH)
  • -
  • Tagalog, Philippines (tl_PH)
  • -
  • Turkish, Turkey (tr_TR)
  • -
  • Ukrainian, Ukraine (uk_UA)
  • -
  • Vietnamese, Vietnam (vi_VN)
  • -
  • Chinese, PRC (zh_CN)
  • -
  • Chinese, Taiwan (zh_TW)
  • -
    - -

    Note: The Android platform may support more -locales than are included in the SDK system image. All of the supported locales -are available in the Android Open Source -Project.

    - -

    Emulator Skins

    - -

    The downloadable platform includes a set of emulator skins that you can use -for modeling your application in different screen sizes and resolutions. The -emulator skins are:

    - -
      -
    • - QVGA (240x320, low density, small screen) -
    • -
    • - WQVGA400 (240x400, low density, normal screen) -
    • -
    • - WQVGA432 (240x432, low density, normal screen) -
    • -
    • - HVGA (320x480, medium density, normal screen) -
    • -
    • - WVGA800 (480x800, high density, normal screen) -
    • -
    • - WVGA854 (480x854 high density, normal screen) -
    • -
    - -

    For more information about how to develop an application that displays -and functions properly on all Android-powered devices, see Supporting Multiple -Screens.

    +

    For more information, read What is API +Level?

    \ No newline at end of file diff --git a/docs/html/about/versions/android-2.3.4.jd b/docs/html/about/versions/android-2.3.4.jd new file mode 100644 index 0000000000000000000000000000000000000000..bb4feecae287112be1c8a85e56e8a8fce6d609d3 --- /dev/null +++ b/docs/html/about/versions/android-2.3.4.jd @@ -0,0 +1,148 @@ +page.title=Android 2.3.4 Platform +sdk.platform.version=2.3.4 +sdk.platform.apiLevel=10 + + +@jd:body + +
    +
    + +

    In this document

    +
      +
    1. API Overview
    2. +
    3. Open Accessory Library
    4. +
    5. API Level
    6. +
    + +

    Reference

    +
      +
    1. API +Differences Report »
    2. +
    + +
    +
    + +

    +API Level: {@sdkPlatformApiLevel}

    + +

    Android 2.3.4 is a maintenance release that adds several bug fixes and patches +to the Android 2.3 platform, without any API changes from Android 2.3.3. Additionally, +Android 2.3.4 brings support for the Open Accessory API to mobile devices, +through the optional Open Accessory Library.

    + +

    For developers, the Android {@sdkPlatformVersion} platform is available as a +downloadable component for the Android SDK. The downloadable platform includes +an Android library and system image, as well as a set of emulator skins and +more. To get started developing or testing against Android {@sdkPlatformVersion}, +use the Android SDK Manager to download the platform into your SDK.

    + + + +

    API Overview

    + +

    Android 2.3.4 provides the same framework API to applications as Android 2.3.3 +(API level 10). For a summary of the API, see the +Android 2.3.3 version notes.

    + + +

    Open Accessory Library

    + +

    Open Accessory is a new capability for integrating +connected peripherals with applications running on the platform. The capability +is based on a USB (Universal Serial Bus) stack built into the platform and an +API exposed to applications. Peripherals that attach to Android-powered devices +as accessories connect as USB hosts.

    + +

    Open Accessory is introduced in Android 3.1 (API level 12), but is +made available to devices running Android 2.3.4 by means of an optional external +library, the Open Accessory Library. The library exposes a framework API that +lets applications discover, communicate with, and manage a variety of device +types connected over USB. It also provides the implementation of the API against +parts of the Android platform that are not directly exposed to applications in +Android 2.3.4.

    + +

    The Open Accessory Library is optional on any given device. Device +manufacturers may choose whether to include the Open Accessory Library in their +products or exclude it. The library is forward-compatible with Android 3.1, so +applications developed against Android 2.3.4 will run properly on devices +running Android 3.1, if those devices support USB accessories.

    + +

    The API provided by the Open Accessory Library is based on the Open Accessory +API provided in Android 3.1. In most areas, you can use the same techniques and +APIs. However, developing for the Open Accessory Library on Android 2.3.4 differs +from the standard USB API in these ways: + +

      +
    • Obtaining a {@link android.hardware.usb.UsbManager} object — To obtain +a {@link android.hardware.usb.UsbManager} object when using the add-on library, +use the helper method getInstance() rather than {@link +android.content.Context#getSystemService(java.lang.String) getSystemService()} +For example: + +
      UsbManager manager = UsbManager.getInstance(this);
    • + +
    • Obtaining a {@link android.hardware.usb.UsbAccessory} from a filtered intent +— When you filter for a connected device or accessory with an intent +filter, the {@link android.hardware.usb.UsbAccessory} object is contained +inside the intent that is passed to your application. If you are using the +add-on library, you can get the {@link android.hardware.usb.UsbAccessory} object +in the following manner: + +
      UsbAccessory accessory = UsbManager.getAccessory(intent)
    • + +
    • No USB host support — Android 2.3.4 and the Open Accessory Library do +not support USB host mode (for example, through {@link +android.hardware.usb.UsbDevice}), although USB host mode is supported in Android +3.1. An Android-powered device running Android 2.3.4 can not function as a USB +host. The library enables the Android-powered device to function as +a peripheral only, with the connected accessory functioning as USB host +(through {@link android.hardware.usb.UsbAccessory}).
    • +
    + +

    To develop apps using the Open Accessory Library, you need:

    + +
      +
    • The latest version of the Android SDK tools
    • +
    • The latest version of the Google APIs add-on, which includes the library +itself (for linking)
    • +
    • An actual hardware device running Android 2.3.4 (or Android 3.1) with USB +accessories support, for runtime testing against connected devices
    • +
    + +

    For a full discussion of how to develop applications that interact with USB +accessories, please see the related developer documentation.

    + +

    Additionally, developers can request filtering on Google Play, such that +their applications are not available to users whose devices do not provide the +appropriate accessory support. To request filtering, add the element below +to the application manifest:

    + +
    <uses-feature
    +  android:name="android.hardware.usb.accessory"
    +  android:required="true">
    + + +

    API Level

    + +

    The Android 2.3.4 platform does not increment the API level — +it uses the same API level as Android 2.3.3, API level 10. + +

    To use APIs introduced in API level 10 in your application, +you need compile the application against the Android library that is provided in +the latest version of the Google APIs Add-On, which also includes the Open +Accessory Library.

    + +

    Depending on your needs, you might +also need to add an android:minSdkVersion="{@sdkPlatformApiLevel}" +attribute to the <uses-sdk> element in the application's +manifest. If your application is designed to run only on Android 2.3.3 and higher, +declaring the attribute prevents the application from being installed on earlier +versions of the platform.

    + +

    For more information, read What is API +Level?

    diff --git a/docs/html/sdk/android-2.3.jd b/docs/html/about/versions/android-2.3.jd similarity index 82% rename from docs/html/sdk/android-2.3.jd rename to docs/html/about/versions/android-2.3.jd index b466913098916edac519f7b519d00c10d5bedc3d..2afa564ffc20aa1809df15d0c3643e1c93b60985 100644 --- a/docs/html/sdk/android-2.3.jd +++ b/docs/html/about/versions/android-2.3.jd @@ -10,12 +10,8 @@ sdk.platform.apiLevel=9

    In this document

      -
    1. Revisions
    2. API Overview
    3. API Level
    4. -
    5. Built-in Applications
    6. -
    7. Locales
    8. -
    9. Emulator Skins

    Reference

    @@ -25,11 +21,6 @@ href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API Differences Report » -

    See Also

    -
      -
    1. Adding SDK Components
    2. -
    -
    @@ -37,85 +28,13 @@ Differences Report » API Level: {@sdkPlatformApiLevel}

    For developers, the Android {@sdkPlatformVersion} platform is available as a -downloadable component for the Android SDK. The downloadable platform includes -an Android library and system image, as well as a set of emulator -skins and more. The downloadable platform -includes no external libraries.

    - -

    To get started developing or testing against Android -{@sdkPlatformVersion}, use the Android SDK Manager to -download the platform into your SDK. For more information, -see Adding SDK -Components. If you are new to Android, download the SDK Starter Package -first.

    - -

    For a high-level introduction to Android {@sdkPlatformVersion}, see the Platform Highlights.

    - - -

    Revisions

    - -

    The sections below provide notes about successive releases of -the Android {@sdkPlatformVersion} platform component for the Android SDK, as denoted by -revision number. To determine what revision(s) of the Android -{@sdkPlatformVersion} platforms are installed in your SDK environment, refer to -the "Installed Packages" listing in the Android SDK and AVD Manager.

    - - - - -
    - - - Android {@sdkPlatformVersion}, Revision 1 (December 2010) -
    -
    -
    Dependencies:
    -
    -

    Requires SDK Tools r8 or higher.

    -
    - -
    -
    -
    +downloadable component for the Android SDK. The downloadable platform includes +an Android library and system image, as well as a set of emulator skins and +more. To get started developing or testing against Android {@sdkPlatformVersion}, +use the Android SDK Manager to download the platform into your SDK.

    + + +

    API Overview

    @@ -648,7 +567,7 @@ events and surfaces.

    For full information on working with native code or to download the NDK, -see the Android NDK page.

    +see the Android NDK page.

    Dalvik Runtime

    @@ -787,156 +706,5 @@ manifest. If your application is designed to run only on Android 2.3 and higher, declaring the attribute prevents the application from being installed on earlier versions of the platform.

    -

    For more information about how to use API Level, see the API Levels document.

    - -

    Built-in Applications

    - -

    The system image included in the downloadable platform provides these -built-in applications:

    - - - - - - -
    -
      -
    • Browser
    • -
    • Calculator
    • -
    • Camera
    • -
    • Clock
    • -
    • Contacts
    • -
    • Cusom Locale
    • -
    • Dev Tools
    • -
    • Downloads
    • -
    • Email
    • -
    -
    -
      -
    • Gallery
    • -
    • IMEs for Japanese, Chinese, and Latin text input
    • -
    • Messaging
    • -
    • Music
    • -
    • Phone
    • -
    • Search
    • -
    • Settings
    • -
    • Spare Parts (developer app)
    • -
    • Speech Recorder
    • -
    -
    - - -

    Locales

    - -

    The system image included in the downloadable SDK platform provides a variety of -built-in locales. In some cases, region-specific strings are available for the -locales. In other cases, a default version of the language is used. The -languages that are available in the Android {@sdkPlatformVersion} system -image are listed below (with language_country/region locale -descriptor).

    - - - - - - -
    -
      -
    • Arabic, Egypt (ar_EG)
    • -
    • Arabic, Israel (ar_IL)
    • -
    • Bulgarian, Bulgaria (bg_BG)
    • -
    • Catalan, Spain (ca_ES)
    • -
    • Czech, Czech Republic (cs_CZ)
    • -
    • Danish, Denmark(da_DK)
    • -
    • German, Austria (de_AT)
    • -
    • German, Switzerland (de_CH)
    • -
    • German, Germany (de_DE)
    • -
    • German, Liechtenstein (de_LI)
    • -
    • Greek, Greece (el_GR)
    • -
    • English, Australia (en_AU)
    • -
    • English, Canada (en_CA)
    • -
    • English, Britain (en_GB)
    • -
    • English, Ireland (en_IE)
    • -
    • English, India (en_IN)
    • -
    • English, New Zealand (en_NZ)
    • -
    • English, Singapore(en_SG)
    • -
    • English, US (en_US)
    • -
    • English, South Africa (en_ZA)
    • -
    • Spanish (es_ES)
    • -
    • Spanish, US (es_US)
    • -
    • Finnish, Finland (fi_FI)
    • -
    • French, Belgium (fr_BE)
    • -
    • French, Canada (fr_CA)
    • -
    • French, Switzerland (fr_CH)
    • -
    • French, France (fr_FR)
    • -
    • Hebrew, Israel (he_IL)
    • -
    • Hindi, India (hi_IN)
    • -
    -
    -
  • Croatian, Croatia (hr_HR)
  • -
  • Hungarian, Hungary (hu_HU)
  • -
  • Indonesian, Indonesia (id_ID)
  • -
  • Italian, Switzerland (it_CH)
  • -
  • Italian, Italy (it_IT)
  • -
  • Japanese (ja_JP)
  • -
  • Korean (ko_KR)
  • -
  • Lithuanian, Lithuania (lt_LT)
  • -
  • Latvian, Latvia (lv_LV)
  • -
  • Norwegian-Bokmol, Norway(nb_NO)
  • -
  • Dutch, Belgium (nl_BE)
  • -
  • Dutch, Netherlands (nl_NL)
  • -
  • Polish (pl_PL)
  • -
  • Portuguese, Brazil (pt_BR)
  • -
  • Portuguese, Portugal (pt_PT)
  • -
  • Romanian, Romania (ro_RO)
  • -
  • Russian (ru_RU)
  • -
  • Slovak, Slovakia (sk_SK)
  • -
  • Slovenian, Slovenia (sl_SI)
  • -
  • Serbian (sr_RS)
  • -
  • Swedish, Sweden (sv_SE)
  • -
  • Thai, Thailand (th_TH)
  • -
  • Tagalog, Philippines (tl_PH)
  • -
  • Turkish, Turkey (tr_TR)
  • -
  • Ukrainian, Ukraine (uk_UA)
  • -
  • Vietnamese, Vietnam (vi_VN)
  • -
  • Chinese, PRC (zh_CN)
  • -
  • Chinese, Taiwan (zh_TW)
  • -
    - -

    Note: The Android platform may support more -locales than are included in the SDK system image. All of the supported locales -are available in the Android Open Source -Project.

    - -

    Emulator Skins

    - -

    The downloadable platform includes a set of emulator skins that you can use -for modeling your application in different screen sizes and resolutions. The -emulator skins are:

    - - - -

    For more information about how to develop an application that displays -and functions properly on all Android-powered devices, see Supporting Multiple -Screens.

    +

    For more information, read What is API +Level?

    \ No newline at end of file diff --git a/docs/html/sdk/android-3.0-highlights.jd b/docs/html/about/versions/android-3.0-highlights.jd similarity index 88% rename from docs/html/sdk/android-3.0-highlights.jd rename to docs/html/about/versions/android-3.0-highlights.jd index 33897de91c6cbbf593d2c8b4a4be692e5dcbfeb7..21dbda6af4ced146ff965cb5b9bf5200090de69f 100644 --- a/docs/html/sdk/android-3.0-highlights.jd +++ b/docs/html/about/versions/android-3.0-highlights.jd @@ -1,4 +1,4 @@ -page.title=Android 3.0 Platform Highlights +page.title=Honeycomb @jd:body @@ -15,7 +15,6 @@ page.title=Android 3.0 Platform Highlights #jd-content div.video { float:right; padding:0 60px 40px; - margin-top:-15px; } #jd-content table.columns { margin:0 0 1em 0; @@ -44,7 +43,7 @@ page.title=Android 3.0 Platform Highlights

    The Android 3.0 platform introduces many new and exciting features for users and developers. This document provides a glimpse of some of the new features and technologies, as delivered in Android 3.0. For a more detailed look at new developer APIs, see the Android 3.0 Platform document.

    +href="{@docRoot}about/versions/android-3.0.html">Android 3.0 Platform document.

    Generally, only a few foreground processes exist at any given time. They are killed only as @@ -131,79 +130,43 @@ visible to the user (its {@link android.app.Activity#onPause onPause()} method h This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it. -

  • Another visible process has a dependency on this one: either bound - to a Service in this process, or using a Content Provider of the process.
  • +
  • It hosts a {@link android.app.Service} that's bound to a visible (or foreground) +activity.
  • A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.

    -
  • Perceptible process -

    A process that doesn't have any foreground or visible components, but is still - doing something that is directly perceptible by the user. A classic example of such - a process would be one doing background music playback. The main way applications - get into this state is through {@link android.app.Service#startForeground} or because - another perceptible process has a dependency on one of its services or content - providers. In addition, as of {@link android.os.Build.VERSION_CODES#HONEYCOMB}, - processes can go into this state when {@link android.app.Activity#onStop - Activity.onStop()} is executing, allowing the process to continue executing - critical code after no longer being visible to the user but before going - fully into the background.

    - -

    Like visible processes, a perceptible process is considered extremely important - and will not be killed unless doing so is required to keep all foreground and - visible processes running.

    -
  • -
  • Service process

    A process that is running a service that has been started with the {@link -android.content.Context#startService startService()} method and does not fall into any of the +android.content.Context#startService startService()} method and does not fall into either of the two higher categories. Although service processes are not directly tied to anything the user sees, they -are generally doing things that the user cares about (such as downloading a file the user has requested), -so the system keeps them running unless there's not enough memory to retain them along with all -foreground and visible processes.

    - -

    Even though Android tries to keep these processes running, it is considered normal - operation for them to temporarily be killed to support the needs of more important - processes. For example, if the user opens a very heavy-weight web page that needs - most of the device's RAM, background services may be temporarily killed to satisfy - those needs. Services in these processes thus must be prepared to deal gracefully - with being killed while doing their work and later restarted.

    - -

    In recent implementations of Android, there are actually a number of sub-divisions - in this area for processes that Android considers more important to the user and so - would like to try harder to keep around. For example, the process hosting the current - home app is generally kept in this area so that the user will not see long delays in - returning home because that process has been killed.

    +are generally doing things that the user cares about (such as playing music in the background or +downloading data on the network), so the system keeps them running unless there's not enough memory +to retain them along with all foreground and visible processes.

  • -
  • Background (cached) process -

    The final importance level is for processes that are not of current significance. - This is basically any process that does not fall into one of the previous levels. - These processes have no direct impact on the user experience, and the system can kill - them at any time to reclaim memory for the other more important processes. - This includes everything from processes holding running activity objects that are not currently - visible to the user (the activity's {@link android.app.Activity#onStop onStop()} - method has been called) to processes that have no active code at all but may be - useful to keep around in case they are needed in the near future.

    - -

    Usually there are many background processes being maintained, so they are kept - in an LRU list to allow older processes to be killed before more recent ones. This - helps reduce the frequency that new processes need to be creating, facilitating things - like more rapid switching between the applications the user has recently visited. - However, processes in this state must deal correctly with being killed and later - restarted when needed. For example, if an activity implements its lifecycle methods +

  • Background process +

    A process holding an activity that's not currently visible to the user (the activity's +{@link android.app.Activity#onStop onStop()} method has been called). These processes have no direct +impact on the user experience, and the system can kill them at any time to reclaim memory for a +foreground, +visible, or service process. Usually there are many background processes running, so they are kept +in an LRU (least recently used) list to ensure that the process with the activity that was most +recently seen by the user is the last to be killed. If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not have a visible effect on the user experience, because when the user navigates back to the activity, the activity restores all of its visible state. See the Activities +href="{@docRoot}guide/components/activities.html#SavingActivityState">Activities document for information about saving and restoring state.

    +
  • -

    Android may also employ other additional policies for killing background processes. For - example, there are typically restrictions on a maximum number of such processes to - keep around, and limits on the amount of time they can spend holding wake locks - or consuming CPU power until they will be removed.

    +
  • Empty process +

    A process that doesn't hold any active application components. The only reason to keep this +kind of process alive is for caching purposes, to improve startup time the next time a component +needs to run in it. The system often kills these processes in order to balance overall system +resources between process caches and the underlying kernel caches.

  • @@ -213,48 +176,23 @@ components currently active in the process. For example, if a process hosts a s activity, the process is ranked as a visible process, not a service process.

    In addition, a process's ranking might be increased because other processes are dependent on -it—a process that is serving another process can not generally be ranked lower than the process it is +it—a process that is serving another process can never be ranked lower than the process it is serving. For example, if a content provider in process A is serving a client in process B, or if a -service in process A has been bound to by a client in process B, process A is always considered at least +service in process A is bound to a component in process B, process A is always considered at least as important as process B.

    Because a process running a service is ranked higher than a process with background activities, -an activity that initiates a long-running operation may sometimes start a service for that operation, rather than -simply create a worker thread—but only when the operation is a specific task that needs -to be accomplished regardless of whether the user returns to the application. +an activity that initiates a long-running operation might do well to start a service for that operation, rather than +simply create a worker thread—particularly if the operation will likely outlast the activity. For example, an activity that's uploading a picture to a web site should start a service to perform the upload so that the upload can continue in the background even if the user leaves the activity. Using a service guarantees that the operation will have at least "service process" priority, -regardless of what happens to the activity. This is not however an approach that should always -be used. It would not be appropriate when simply downloading the data for a web page, since -that can easily be restarted later if the user returns to the web browser. Allowing -such a process to be in the background (instead of running a service) gives Android better -information about how to manage that process in relation to others. - -

    For a similar reason, broadcast receivers will often employ services rather than - simply put time-consuming operations in a thread.

    - -

    Some command line tools are available to help you understand how Android is managing - its processes. The most common command is adb shell dumpsys activity - which provides a summary of various key state, including at the end a list of the - process states, one per line (plus an optional second line for any key dependency - on that process), ordered from higher importance to lowest. The exact - contents of these lines has changed across different versions of Android, but the - typical state for one process in the list would be:

    -
    -Proc # 2: adj=prcp /F  trm= 0 848:com.google.android.inputmethod.latin/u0a32 (service)
    -    com.google.android.inputmethod.latin/com.android.inputmethod.latin.LatinIME<=Proc{417:system/1000}
    -
    +regardless of what happens to the activity. This is the same reason that broadcast receivers should +employ services rather than simply put time-consuming operations in a thread.

    + -

    This is a perceptible process (adj=prcp) that is running with the foreground - scheduling class (/F), and has not recently been told to trim any memory - (trm= 0). Its process id is 848; its name is com.google.android.inputmethod.latin; - its Linux uid is u0a32 (10032), and the key state contributing to its current - importance level is a service.

    -

    The second line provides the name of the service that is important, because another - process has a dependency on it (here the system process).

    Threads

    @@ -283,7 +221,7 @@ database queries will block the whole UI. When the thread is blocked, no events including drawing events. From the user's perspective, the application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not +href="http://developer.android.com/guide/practices/responsiveness.html">application not responding" (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.

    @@ -436,7 +374,7 @@ href="http://code.google.com/p/shelves/">Shelves sample application.

    therefore must be written to be thread-safe.

    This is primarily true for methods that can be called remotely—such as methods in a bound service. When a call on a +href="{@docRoot}guide/components/bound-services.html">bound service. When a call on a method implemented in an {@link android.os.IBinder} originates in the same process in which the {@link android.os.IBinder IBinder} is running, the method is executed in the caller's thread. However, when the call originates in another process, the method is executed in a thread chosen from @@ -474,7 +412,7 @@ transactions, so you can focus on defining and implementing the RPC programming

    To perform IPC, your application must bind to a service, using {@link android.content.Context#bindService bindService()}. For more information, see the Services developer guide.

    +href="{@docRoot}guide/components/services.html">Services developer guide.

    diff --git a/docs/html/guide/topics/fundamentals/services.jd b/docs/html/guide/components/services.jd similarity index 98% rename from docs/html/guide/topics/fundamentals/services.jd rename to docs/html/guide/components/services.jd index 9c38897671c995af0480f22662f404b20dbaf4bd..ba5e1f03b2773e34fb19eb42ca811c0f16c100b7 100644 --- a/docs/html/guide/topics/fundamentals/services.jd +++ b/docs/html/guide/components/services.jd @@ -58,7 +58,7 @@ perform interprocess communication

    See also

      -
    1. Bound Services
    2. +
    3. Bound Services
    @@ -128,7 +128,7 @@ a thread in {@link android.app.Activity#onCreate onCreate()}, start running it i android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread}, instead of the traditional {@link java.lang.Thread} class. See the Processes and +href="{@docRoot}guide/components/processes-and-threads.html#Threads">Processes and Threading document for more information about threads.

    Remember that if you do use a service, it still runs in your application's main thread by default, so you should still create a new thread within the service if it performs intensive or @@ -190,7 +190,7 @@ by the system. If the system kills your service, it restarts it as soon as resou available again (though this also depends on the value you return from {@link android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information about when the system might destroy a service, see the Processes and Threading +href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threading document.

    In the following sections, you'll see how you can create each type of service and how to use @@ -252,7 +252,7 @@ attribute and set it to {@code "false"}. This is effective even if your service filters.

    For more information about creating intent filters for your service, see the Intents and Intent Filters +href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters document.

    @@ -643,7 +643,7 @@ there are no clients bound to the service, the system destroys the service.

    There are multiple ways to implement a bound service and the implementation is more complicated than a started service, so the bound service discussion appears in a separate document about Bound Services.

    +href="{@docRoot}guide/components/bound-services.html">Bound Services.

    @@ -857,10 +857,10 @@ can still receive a call to {@link android.app.Service#onBind onBind()} (when a {@link android.content.Context#bindService bindService()}).

    For more information about creating a service that provides binding, see the Bound Services document, +href="{@docRoot}guide/components/bound-services.html">Bound Services document, which includes more information about the {@link android.app.Service#onRebind onRebind()} callback method in the section about Managing the Lifecycle of +href="{@docRoot}guide/components/bound-services.html#Lifecycle">Managing the Lifecycle of a Bound Service.

    diff --git a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd b/docs/html/guide/components/tasks-and-back-stack.jd similarity index 98% rename from docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd rename to docs/html/guide/components/tasks-and-back-stack.jd index 0880614ae6468c31837803ba26d531d499df2401..8b7041cef826ff300a8adcf5a99effcf7799f5ab 100644 --- a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd +++ b/docs/html/guide/components/tasks-and-back-stack.jd @@ -29,14 +29,13 @@ to perform other tasks without losing their work

    Articles

      -
    1. Multitasking the Android Way
    2. +
    3. Multitasking the Android Way

    See also

    1. Android Design: Navigation
    2. -
    3. Application Lifecycle video
    4. {@code <activity>} manifest element
    5. @@ -46,7 +45,7 @@ element

      An application usually contains multiple activities. Each activity +href="{@docRoot}guide/components/activities.html">activities. Each activity should be designed around a specific kind of action the user can perform and can start other activities. For example, an email application might have one activity to show a list of new email. When the user selects an email, a new activity opens to view that email.

      @@ -210,7 +209,7 @@ android.app.Activity#onSaveInstanceState onSaveInstanceState()} callback methods in your activity.

      For more information about how to save your activity state, see the Activities +href="{@docRoot}guide/components/activities.html#SavingActivityState">Activities document.

      @@ -591,6 +590,6 @@ href="#Clearing">Clearing the stack).

      For more information about how to use intents to activate other application components and publish the intents to which your components respond, continue with the Intents and Intent +href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters document.

      --> diff --git a/docs/html/guide/developing/eclipse-adt.html b/docs/html/guide/developing/eclipse-adt.html deleted file mode 100644 index 879a35635ba71eb5153c60afca8eb241787041c5..0000000000000000000000000000000000000000 --- a/docs/html/guide/developing/eclipse-adt.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting... - - -

      You should be redirected. Please click here.

      - - \ No newline at end of file diff --git a/docs/html/guide/developing/other-ide.html b/docs/html/guide/developing/other-ide.html deleted file mode 100644 index 41dba0529b197abd552ab115f93ad34efa5ea036..0000000000000000000000000000000000000000 --- a/docs/html/guide/developing/other-ide.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting... - - -

      You should be redirected. Please click here.

      - - \ No newline at end of file diff --git a/docs/html/guide/developing/testing/index.jd b/docs/html/guide/developing/testing/index.jd deleted file mode 100644 index 8a089598918209f54f4c23693721a40bd6acdca8..0000000000000000000000000000000000000000 --- a/docs/html/guide/developing/testing/index.jd +++ /dev/null @@ -1,36 +0,0 @@ -page.title=Testing -@jd:body -

      - Android includes powerful tools for setting up and running test applications. - Whether you are working in Eclipse with ADT or working from the command line, these tools - help you set up and run your tests within an emulator or the device you are targeting. - The documents listed below explain how to work with the tools in your development environment. -

      -

      - If you aren't yet familiar with the Android testing framework, please read the topic - Testing Fundamentals - before you get started. - For a step-by-step introduction to Android testing, try the Hello, Testing - tutorial, which introduces basic testing concepts and procedures. - For a more advanced tutorial, try Activity Testing, - which guides you through a more complex testing scenario. -

      -
      -
      Testing from Eclipse, with ADT
      -
      - The ADT plugin lets you quickly set up and manage test projects directly in - the Eclipse UI. Once you have written your tests, you can build and run them and - then see the results in the Eclipse JUnit view. You can also use the SDK command-line - tools to execute your tests if needed. -
      -
      Testing from Other IDEs
      -
      - The SDK command-line tools provide the same capabilities as the ADT plugin. You can - use them to set up and manage test projects, build your test application, - run your tests, and see the results. You use - the android tool to create and manage test projects, the Ant build system - to compile them, and the adb tool to install and run them. -
      -
      diff --git a/docs/html/guide/developing/tools/aapt.html b/docs/html/guide/developing/tools/aapt.html deleted file mode 100644 index e66a2019e49440455c6efc4b700739536ae10ba5..0000000000000000000000000000000000000000 --- a/docs/html/guide/developing/tools/aapt.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting... - - -

      You should be redirected. Please click here.

      - - \ No newline at end of file diff --git a/docs/html/guide/google/index.jd b/docs/html/guide/google/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..95c2816b416ea8ba65fc89e5fd58f7b460affe8b --- /dev/null +++ b/docs/html/guide/google/index.jd @@ -0,0 +1,97 @@ +page.title=Google Services +footer.hide=1 +@jd:body + + +

      Google offers a variety of services that help you build new revenue streams, enhance your app's capabilities, manage distribution and payloads, and track usage and installs. Many of the services use static libraries that you download through the Android SDK Manager and build into your app. Others are configurable directly from Google Play Android Developer Console.

      + +

      The sections below highlight some of the Google Services and link you to more information about how to use them in your Android app.

      + + +

      Monetize Your App

      + +
       
      +
      + +
      +

      In-App Billing

      +

      Keep your users engaged by offering in-app purchases and subscriptions directly in your app. +

      + Learn more » +
      + +
      +

      Google AdMob Ads

      +

      Generate more revenue from your app by + displaying ads from multiple ad networks.

      + Learn more » +
      + +
      +

      Application Licensing

      +

      Protect your revenue streams and integrate policies for usage into your app.

      + Learn more » +
      + +
      + +

      Manage App Distribution

      + +
       
      + +
      + +
      + +

      Google Play Filters

      +

      Make sure your app gets to the right users by +declaring the hardware and software features needed by your app.

      +Learn more » +
      + +
      +

      Multiple APK Support

      +

      Distribute different APKs based on a variety of properties such as platform version, screen size, and GLES texture compression support.

      +Learn more » +
      + +
      + +

      APK Expansion files

      +

      Take load off of your servers and utilize APK expansion files +to deliver up to 4 GB of assets for your Android app, free.

      + +Learn more » +
      + +
      + +

      Enhance Your App's Capabilities

      + +
       
      + +
      + +
      +

      Android Cloud-to-Device Messaging

      +

      Notify your apps of events with push messages that are lightweight + and battery-saving.

      + Learn more » +
      + +
      +

      Google Maps

      +

      The Google Maps library for Android lets you add powerful mapping and geo-location capabilities to your app.

      + Learn more » +
      +
      + + +

      Track Performance with Analytics

      +

      Google Analytics gives you powerful insights into how users find your apps + and how they use them.
      Start integrating analytics to measure + your app's success.

      + + + + \ No newline at end of file diff --git a/docs/html/guide/google/play/billing/billing_about.html b/docs/html/guide/google/play/billing/billing_about.html new file mode 100644 index 0000000000000000000000000000000000000000..9f41fa62e344d3bd5428830987ffd9d2df60fee3 --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_about.html @@ -0,0 +1,12 @@ + + + +Redirecting... + + +

      You should be redirected. Please click +here.

      + + \ No newline at end of file diff --git a/docs/html/guide/market/billing/billing_admin.jd b/docs/html/guide/google/play/billing/billing_admin.jd similarity index 89% rename from docs/html/guide/market/billing/billing_admin.jd rename to docs/html/guide/google/play/billing/billing_admin.jd index 0f869ab78795703ec3cbdc5b745134caffd09bba..cb288a5381d5f4e2ec35515cb0c5251398cb206a 100755 --- a/docs/html/guide/market/billing/billing_admin.jd +++ b/docs/html/guide/google/play/billing/billing_admin.jd @@ -15,20 +15,20 @@ parent.link=index.html

    Downloads

      -
    1. Sample +
    2. Sample Application

    See also

      -
    1. Overview of In-app +
    2. Overview of In-app Billing
    3. -
    4. Implementing In-app +
    5. Implementing In-app Billing
    6. -
    7. Security and +
    8. Security and Design
    9. -
    10. Testing In-app +
    11. Testing In-app Billing
    12. -
    13. In-app Billing +
    14. In-app Billing Reference
    @@ -39,13 +39,13 @@ few administrative tasks, including setting up and maintaining your product list site, registering test accounts, and handling refunds when necessary.

    You must have a Google Play publisher account to register test accounts. And you must have a -Google Checkout merchant account to create a product list and issue refunds to your users. If you +Google Wallet merchant account to create a product list and issue refunds to your users. If you already have a publisher account on Google Play, you can use your existing account. You do not need to register for a new account to support in-app billing. If you do not have a publisher account, you can register as a Google Play developer and set up a publisher account at the Google Play publisher site. If you do not have a -Google Checkout merchant account, you can register for one at the Google Checkout site.

    +Google Wallet merchant account, you can register for one at the Google Wallet site.

    Creating a Product List

    @@ -56,7 +56,7 @@ items that are listed in another application's product list.

    You can access an application's product list by clicking the In-App Products link that appears under each of the applications that are listed for your publisher account (see -figure 1). The In-App Products link appears only if you have a Google Checkout +figure 1). The In-App Products link appears only if you have a Google Wallet merchant account and an application's manifest includes the com.android.vending.BILLING permission.

    @@ -66,7 +66,8 @@ permission.

    In-App Products link.

    -

    A product list contains information about the items you are selling, such as a product id, +

    A product list specifies items you are selling in an application — in-app products, +subscriptions, or a combination of both. For each item, the product list contains information such as a product id, product description, and price (see figure 2). The product list stores only metadata about the items you are selling in your application. It does not store any digital content. You are responsible for storing and delivering the digital content that you sell in your applications.

    @@ -77,17 +78,17 @@ storing and delivering the digital content that you sell in your applications.

    You can create a product list for any published application or any draft application that's been -uploaded and saved to the Google Play site. However, you must have a Google Checkout merchant +uploaded and saved to the Google Play site. However, you must have a Google Wallet merchant account and the application's manifest must include the com.android.vending.BILLING permission. If an application's manifest does not include this permission, you will be able to edit existing items in the product list but you will not be able to add new items to the list. For more information about this permission, see -Updating Your +Updating Your Application's Manifest.

    In addition, an application package can have only one product list. If you create a product list for an application, and you use the multiple APK feature to distribute +href="{@docRoot}guide/google/play/publishing/multiple-apks.html">multiple APK feature to distribute more than one APK for that application, the product list applies to all APK versions that are associated with the application listing. You cannot create individual product lists for each APK if you are using the multiple APK feature.

    @@ -99,6 +100,8 @@ application 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 application has a large number of in-app items.

    +

    Note: Batch upload of product lists containing subscriptions is not yet supported.

    +

    Adding items one at a time to a product list

    To add an item to a product list using the In-app Products UI, follow these steps:

    @@ -129,8 +132,8 @@ number of in-app items.

    a product ID.

  • Purchase Type -

    The purchase type can be Managed per user account or - Unmanaged. You can never change an item's purchase type after you set it. For more +

    The purchase type can be Managed per user account, Unmanaged, + or Subscription. You can never change an item's purchase type after you set it. For more information, see Choosing a purchase type later in this document.

  • @@ -140,7 +143,7 @@ number of in-app items.

    Published and the item's application must be published on Google Play.

    Note: This is not true for test accounts. An item is visible to a test account if the application is not published and the item is published. See Testing In-app + href="{@docRoot}guide/google/play/billing/billing_testing.html#billing-testing-real">Testing In-app Billing for more information.

  • Language @@ -171,6 +174,7 @@ number of in-app items.

    To specify prices in other currencies, you can manually enter the price for each currency or you can click Auto Fill and let Google Play do a one-time conversion from your home currency to the currencies you are targeting (see figure 4).

    +

    For subscription items, note that you can not change the item's price once you have published it.

  • @@ -193,7 +197,16 @@ or modify product IDs after you save them.

    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). The CSV file uses commas (,) and semi-colons (;) to separate data values. +to a product list). + +

    If you are importing and exporting CSV files with in-app products, please +keep tax-inclusive 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 product lists containing subscriptions is not yet supported.

    + +The CSV file uses commas (,) and semi-colons (;) to separate data values. Commas are used to separate primary data values, and semi-colons are used to separate subvalues. For example, the syntax for the CSV file is as follows:

    @@ -419,17 +432,17 @@ times.

    In-app billing does not allow users to send a refund request to Google Play. Refunds for in-app purchases must be directed to you (the application developer). You can then process the -refund through your Google Checkout merchant account. When you do this, Google Play receives a -refund notification from Google Checkout, and Google Play sends a refund message to your +refund through your Google Wallet merchant account. When you do this, Google Play receives a +refund notification from Google Wallet, and Google Play sends a refund message to your application. For more information, see Handling +href="{@docRoot}guide/google/play/billing/billing_overview.html#billing-action-notify">Handling IN_APP_NOTIFY messages and In-app Billing Pricing.

    -

    Important: You cannot use the Google Checkout API to issue +

    Important: You cannot use the Google Wallet API to issue refunds or cancel in-app billing transactions. You must do this manually through your Google -Checkout merchant account. However, you can use the Google Checkout API to retrieve order +Wallet merchant account. However, you can use the Google Wallet API to retrieve order information.

    Setting Up Test Accounts

    diff --git a/docs/html/guide/market/billing/billing_best_practices.jd b/docs/html/guide/google/play/billing/billing_best_practices.jd similarity index 88% rename from docs/html/guide/market/billing/billing_best_practices.jd rename to docs/html/guide/google/play/billing/billing_best_practices.jd index e100ce5813031d0dd26e17f65b5812a63e563eee..49d2a299f5daeff169e0c2c188e3236897958329 100755 --- a/docs/html/guide/market/billing/billing_best_practices.jd +++ b/docs/html/guide/google/play/billing/billing_best_practices.jd @@ -11,20 +11,20 @@ parent.link=index.html

    Downloads

      -
    1. Sample +
    2. Sample Application

    See also

      -
    1. Overview of In-app +
    2. Overview of In-app Billing
    3. -
    4. Implementing In-app +
    5. Implementing In-app Billing
    6. -
    7. Testing In-app +
    8. Testing In-app Billing
    9. -
    10. Administering In-app +
    11. Administering In-app Billing
    12. -
    13. In-app Billing +
    14. In-app Billing Reference
    @@ -58,7 +58,7 @@ sure to encrypt the content and use a device-specific encryption key.

    You should obfuscate your in-app billing code so it is difficult for an attacker to reverse engineer security protocols and other application components. At a minimum, we recommend that you run an obfuscation tool like Proguard on your +href="http://developer.android.com/tools/proguard.html">Proguard on your code.

    In addition to running an obfuscation program, we recommend that you use the following techniques to obfuscate your in-app billing code.

    diff --git a/docs/html/guide/market/billing/billing_integrate.jd b/docs/html/guide/google/play/billing/billing_integrate.jd similarity index 94% rename from docs/html/guide/market/billing/billing_integrate.jd rename to docs/html/guide/google/play/billing/billing_integrate.jd index 4b3650fcc6d5bed3ccc5f265c84da5826dbb7726..2d1582eebb3462e0fe356b897755aba0ae7bdf75 100755 --- a/docs/html/guide/market/billing/billing_integrate.jd +++ b/docs/html/guide/google/play/billing/billing_integrate.jd @@ -21,15 +21,15 @@ parent.link=index.html

    See also

      -
    1. Overview of In-app +
    2. Overview of In-app Billing
    3. -
    4. Security and +
    5. Security and Design
    6. -
    7. Testing In-app +
    8. Testing In-app Billing
    9. -
    10. Administering In-app +
    11. Administering In-app Billing
    12. -
    13. In-app Billing +
    14. In-app Billing Reference
    @@ -41,8 +41,8 @@ you implement in-app billing by stepping through the primary implementation task billing sample application as an example.

    Before you implement in-app billing in your own application, be sure that you read Overview of In-app Billing and Security and Design. These +href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app Billing and Security and Design. These documents provide background information that will make it easier for you to implement in-app billing.

    @@ -214,7 +214,7 @@ following:

  • Build the sample application in release mode and sign it.

    To learn how to build and sign applications, see Building and Running.

    + href="{@docRoot}tools/building/index.html">Building and Running.

  • @@ -238,11 +238,11 @@ how to do this.

    your product list so that sword_001 has a purchase type of "Managed per user account" and potion_001 has a purchase type of "Unmanaged" so you can see how these two purchase types behave. To learn how to set up a product list, see Creating a Product + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-list-setup">Creating a Product List.

    Note: You must publish the items in your product list (sword_001 and potion_001) even though you are not publishing the - sample application. Also, you must have a Google Checkout Merchant account to add items to the + sample application. Also, you must have a Google Wallet Merchant account to add items to the sample application's product list.

    @@ -255,10 +255,10 @@ onto a device to run it. To run the sample application, do the following:

    1. Make sure you have at least one test account registered under your Google Play publisher account. -

      You cannot purchase items from yourself (Google Checkout prohibits this), so you need to +

      You cannot purchase items from yourself (Google Wallet prohibits this), so you need to create at least one test account that you can use to purchase items in the sample application. To learn how to set up a test account, see Setting up Test + href="{@docRoot}guide/google/play/billing/billing_testing.html#billing-testing-setup">Setting up Test Accounts.

    2. Verify that your device is running a supported version of the Google Play @@ -274,12 +274,12 @@ onto a device to run it. To run the sample application, do the following:

      Even though you uploaded the application to Google Play, the application is not published, so you cannot download it from Google Play to a device. Instead, you must install the application onto your device. To learn how to install an application onto a device, see Running on a + href="{@docRoot}tools/building/building-cmdline.html#RunningOnDevice">Running on a device.

    3. Make one of your test accounts the primary account on your device.

      The primary account on your device must be one of the test accounts + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-testing-setup">test accounts that you registered on the Google Play publisher site. If the primary account on your device is not a test account, you must do a factory reset of the device and then sign in with one of your test accounts. To perform a factory reset, do the following:

      @@ -294,7 +294,7 @@ onto a device to run it. To run the sample application, do the following:

    4. Run the application and purchase the sword or the potion.

      When you use a test account to purchase items, the test account is billed through Google - Checkout and your Google Checkout Merchant account receives a payout for the purchase. + Wallet and your Google Wallet Merchant account receives a payout for the purchase. Therefore, you may want to refund purchases that are made with test accounts, otherwise the purchases will show up as actual payouts to your merchant account.

    @@ -466,7 +466,7 @@ indicates the item being purchased, and another identifies your application. The code. However, this is not the complete purchase response; the complete response is delivered with an asynchronous broadcast intent. For more information about the various Bundle keys that are supported by the MarketBillingService, see In-app Billing +href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-interface">In-app Billing Service Interface.

    You can use the sendBillingRequest() method to send five types of billing requests. @@ -475,14 +475,14 @@ key can have the following five values:

    • CHECK_BILLING_SUPPORTED—verifies that the Google Play application - supports in-app billing.
    • + supports in-app billing and the version of the In-app Billing API available.
    • REQUEST_PURCHASE—sends a purchase request for an in-app item.
    • GET_PURCHASE_INFORMATION—retrieves transaction information for a purchase or refund.
    • CONFIRM_NOTIFICATIONS—acknowledges that you received the transaction information for a purchase or refund.
    • RESTORE_TRANSACTIONS—retrieves a user's transaction history for managed + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-purchase-type">managed purchases.
    @@ -511,8 +511,8 @@ application's main thread.

    Verifying that in-app billing is supported (CHECK_BILLING_SUPPPORTED)

    The following code sample shows how to verify whether the Google Play application supports -in-app billing. In the sample, mService is an instance of the -MarketBillingService interface.

    +in-app billing and confirm what version of the API it supports. In the sample, mService +is an instance of the MarketBillingService interface.

     /**
    @@ -523,13 +523,19 @@ in-app billing. In the sample, mService is an instance of the
       // Do something with this response.
     }
     
    +

    The makeRequestBundle() method constructs an initial Bundle, which contains the three keys that are required for all requests: BILLING_REQUEST, -API_VERSION, and PACKAGE_NAME. The request returns a synchronous {@link +API_VERSION, and PACKAGE_NAME. If you are offering subscriptions in +your app, set the API_VERSION key to a value of "2", to confirm that In-app Billing v2 is +available. For an examnple, see +Subscriptions.

    + +

    The CHECK_BILLING_SUPPORTED request returns a synchronous {@link android.os.Bundle} response, which contains only a single key: RESPONSE_CODE. The RESPONSE_CODE key can have the following values:

      -
    • RESULT_OK—in-app billing is supported.
    • +
    • RESULT_OK—the spedified version of in-app billing is supported.
    • RESULT_BILLING_UNAVAILABLE—in-app billing is not available because the API version you specified is not recognized or the user is not eligible to make in-app purchases (for example, the user resides in a country that prohibits in-app purchases).
    • @@ -571,7 +577,7 @@ Help topic.

      You must specify four keys in the request {@link android.os.Bundle}. The following code sample shows how to set these keys and make a purchase request for a single in-app item. In the sample, mProductId is the Google Play product ID of an in-app item (which is listed in the -application's product +application's product list), and mService is an instance of the MarketBillingService interface.

      @@ -581,6 +587,8 @@ interface.

      */ Bundle request = makeRequestBundle("REQUEST_PURCHASE"); request.putString(ITEM_ID, mProductId); + // Request is for a standard in-app product + request.putString(ITEM_TYPE, "inapp"); // Note that the developer payload is optional. if (mDeveloperPayload != null) { request.putString(DEVELOPER_PAYLOAD, mDeveloperPayload); @@ -664,7 +672,7 @@ use to retrieve the transaction details for the REQUEST_PURCHASE re

      Note: The Google Play application also sends an IN_APP_NOTIFY for refunds. For more information, see Handling +href="{@docRoot}guide/google/play/billing/billing_overview.html#billing-action-notify">Handling IN_APP_NOTIFY messages.

      Because the purchase process is not instantaneous and can take several seconds (or more), you @@ -847,7 +855,7 @@ android.content.BroadcastReceiver}. To see an example of how you can send and re messages, see the BillingReceiver.java and BillingService.java files in the sample application. You can use these samples as a basis for your own implementation. However, if you use any of the code from the sample application, be sure you follow the guidelines in Security and Design.

      +href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and Design.

      Creating a BroadcastReceiver

      @@ -860,19 +868,19 @@ android.content.BroadcastReceiver} that can handle the following intents:

      This broadcast intent contains a Google Play response code, and is sent after you make an in-app billing request. For more information about the response codes that are sent with this response, see Google Play Response + href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-codes">Google Play Response Codes for In-app Billing.

    • com.android.vending.billing.IN_APP_NOTIFY

      This response indicates that a purchase has changed state, which means a purchase succeeded, was canceled, or was refunded. For more information about notification messages, see In-app Billing + href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-intents">In-app Billing Broadcast Intents

    • com.android.vending.billing.PURCHASE_STATE_CHANGED

      This broadcast intent contains detailed information about one or more transactions. For more information about purchase state messages, see In-app Billing + href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-intents">In-app Billing Broadcast Intents

    @@ -981,7 +989,7 @@ local service (discussed in the next section). The BillingReceiver.javaSecurity and Design .

    +href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and Design .

    Verifying Signatures and Nonces

    @@ -1020,7 +1028,7 @@ code shows some simple methods you can use to do this.

    PURCHASE_STATE_CHANGED broadcast intent. The Security.java file in the sample application shows you how to do this. If you use this file as a basis for your own security implementation, be sure to follow the guidelines in Security and Design and +href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and Design and obfuscate your code.

    You will need to use your Google Play public key to perform the signature verification. The @@ -1067,7 +1075,7 @@ sample application provides an example database (PurchaseDatabase.java); however database has been simplified for clarity and does not exhibit the security best practices that we recommend. If you have a remote server, we recommend that you store purchase information on your server instead of in a local database on a device. For more information about security best -practices, see Security and +practices, see Security and Design.

    Note: If you store any purchase information on a device, be sure to diff --git a/docs/html/guide/market/billing/billing_overview.jd b/docs/html/guide/google/play/billing/billing_overview.jd similarity index 74% rename from docs/html/guide/market/billing/billing_overview.jd rename to docs/html/guide/google/play/billing/billing_overview.jd index b59381140eca1e7f4160c01829db160ce8e238c5..280b3cf3143e3ca2c04e16bdf5d46aa08091cf42 100755 --- a/docs/html/guide/market/billing/billing_overview.jd +++ b/docs/html/guide/google/play/billing/billing_overview.jd @@ -7,6 +7,7 @@ parent.link=index.html

    @@ -47,15 +48,57 @@ order number, the order date and time, and the price paid. At no point does your handle any financial transactions; that role is provided by Google Play's in-app billing service.

    +

    Product and Purchase Types

    + +

    In-app Billing supports different product types and purchase types to give you flexibility in how you monetize your app. In all cases, you define your products using the Google Play Developer Console, including product type, purchase type, SKU, price, description, and so on. For more information, see Administering In-app Billing.

    + +

    Product Types

    + +

    With In-app Billing, you can sell two types of products — in-app products and subscriptions. The billing characteristics of the two types are very different, but the In-app Billing API lets you handle the two product types in your app using the same communication model, data structures, and user interactions, as described later in this document.

    + +
      +
    • In-app products — Items that a user would purchase one-at-a-time. For example, typical in-app products would let users purchase digital content, unlock functionality in an app, pay for one-time charges, or add almost anything to the application experience. Unlike with priced applications, once the user has purchased an in-app product there is no refund window. Users desiring refunds must contact the developer directly. + +

      In-app products can be sold using either the "managed per user account" or "unmanaged" purchase type. In-app products are always explicitly associated with one and only one app. That is, one app cannot purchase an in-app product published for another app, even if they are from the same developer. In-app products are supported in all versions of In-app Billing.

    • + +
    • Subscriptions — Items that are sold with a developer-specified, recurring billing interval. When a user purchases a subscription, Google Play and its payment processor automatically bill the user's account at the specified interval and price, charging the amount to the original payment method. Once the user purchases a subscription, Google Play continues billing the account indefinitely, without requiring approval or action from the user. The user can cancel the subscription at any time. + +

      Subscriptions can only be sold using the "managed per user account" purchase type. As with in-app products, once the user has purchased an in-app product there is no refund window. Users desiring refunds must contact the developer directly. For more information about subscriptions and how to sell them in your apps, see the Subscriptions document.

    • +
    + +

    Purchase Types

    + +

    In-app Billing offers two purchase types that you can use when selling in-app products, "managed per user account" and "unmanaged". The purchase type controls how Google Play handles and tracks purchases for the products.

    + +
      +
    • Managed per user account — Items that can be purchased only once per user account on Google Play. When a user purchases an item that uses the "managed per user account" purchase type, Google Play permanently stores the transaction information for each item on a per-user basis. This enables you to later query Google Play to restore the state of the items a specific user has purchased. If a user attempts to purchase a managed item that has already been purchased, Google Play prevents the user from purchasing the item again and displays an "Item already purchased" error. + +

      The "managed per user account" purchase type is useful if you are selling items such as game levels or application features. These items are not transient and usually need to be restored whenever a user reinstalls your application, wipes the data on their device, or installs your application on a new device.

      + +
    • Unmanaged — Items that do not have their transaction information stored on Google Play. This means that you cannot later query Google Play to retrieve transaction information for those items. For "unmanaged" purchases, you are responsible for managing the transaction information. Also, Google Play does not attempt to prevent the user from purchasing an item multiple times if it uses the "unmanaged" purchase type. It's up to you to control how many times an unmanaged item can be purchased.

      + +

      The "unmanaged" purchase type is useful if you are selling consumable items, such as fuel or magic spells. These items are consumed within your application and are usually purchased multiple times.

    • +
    +

    In-app Billing Architecture

    -

    In-app billing uses an asynchronous message loop to convey billing requests and billing responses -between your application and the Google Play server. In practice, your application never directly -communicates with the Google Play server (see figure 1). Instead, your application sends billing -requests to the Google Play application over interprocess communication (IPC) and receives -purchase responses from the Google Play application in the form of asynchronous broadcast -intents. Your application does not manage any network connections between itself and the Google -Play server or use any special APIs from the Android platform.

    +

    Your app accesses the In-app Billing service using an API that is exposed by +the Google Play app installed on the device. The Google Play app then uses an +asynchronous message loop to convey billing requests and responses between your +application and the Google Play server. In practice, your application never +directly communicates with the Google Play server (see figure 1). Instead, your +application sends billing requests to the Google Play application over +interprocess communication (IPC) and receives purchase responses from the Google +Play application in the form of asynchronous broadcast intents. Your application +does not manage any network connections between itself and the Google Play +server or use any special APIs from the Android platform.

    + +
    + +

    + Figure 1. Your application sends and receives billing messages through the + Google Play application, which handles all communication with the Google Play server.

    +

    Some in-app billing implementations may also use a private remote server to deliver content or validate transactions, but a remote server is not required to implement in-app billing. A remote @@ -66,13 +109,6 @@ verification. Although you can handle all security-related tasks in your applica those tasks on a remote server is recommended because it helps make your application less vulnerable to security attacks.

    -
    - -

    - Figure 1. Your application sends and receives billing messages through the - Google Play application, which handles all communication with the Google Play server.

    -
    -

    A typical in-app billing implementation relies on three components:

    • A {@link android.app.Service} (named BillingService in the sample application), @@ -118,17 +154,17 @@ messaging that takes place between your application and the Google Play applicat

      Your application sends in-app billing requests by invoking a single IPC method (sendBillingRequest()), which is exposed by the MarketBillingService interface. This interface is defined in an Android Interface Definition Language file +href="{@docRoot}tools/aidl.html">Android Interface Definition Language file (IMarketBillingService.aidl). You can download this AIDL +href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">download this AIDL file with the in-app billing sample application.

      The sendBillingRequest() method has a single {@link android.os.Bundle} parameter. The Bundle that you deliver must include several key-value pairs that specify various parameters for -the request, such as the type of billing request you are making, the item that is being purchased, -and the application that is making the request. For more information about the Bundle keys that are -sent with a request, see In-app Billing +the request, such as the type of billing request you are making, the item that is being purchased and +its type, and the application that is making the request. For more information about the Bundle keys +that are sent with a request, see In-app Billing Service Interface.

      One of the most important keys that every request Bundle must have is the @@ -162,8 +198,10 @@ requests:

    • RESTORE_TRANSACTIONS

      This request retrieves a user's transaction status for managed - purchases. You should send this request only when you need to retrieve a user's transaction + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-purchase-type">managed + purchases and subscriptions. + You should send this request only when you need to retrieve a user's transaction status, which is usually only when your application is reinstalled or installed for the first time on a device.

    • @@ -202,7 +240,7 @@ include the following:

      request. This response is not used to report any purchase state changes (such as refund or purchase information). For more information about the response codes that are sent with this response, see Server Response Codes + href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-codes">Server Response Codes for In-app Billing.

    • com.android.vending.billing.IN_APP_NOTIFY @@ -223,22 +261,22 @@ include the following:

      The JSON string that is returned with the PURCHASE_STATE_CHANGED intent provides your application with the details of one or more billing transactions. An example of this JSON -string is shown below:

      -
      -{ "nonce" : 1836535032137741465,
      +string for a subscription item is shown below:

      +
      { "nonce" : 1836535032137741465,
         "orders" :
      -    { "notificationId" : "android.test.purchased",
      -      "orderId" : "transactionId.android.test.purchased",
      -      "packageName" : "com.example.dungeons",
      -      "productId" : "android.test.purchased",
      -      "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
      -      "purchaseTime" : 1290114783411,
      -      "purchaseState" : 0 }
      +    [{ "notificationId" : "android.test.purchased",
      +       "orderId" : "transactionId.android.test.purchased",
      +       "packageName" : "com.example.dungeons",
      +       "productId" : "android.test.purchased",
      +       "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
      +       "purchaseTime" : 1290114783411,
      +       "purchaseState" : 0,
      +       "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }]
       }
       

      For more information about the fields in this JSON string, see In-app Billing +href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-intents">In-app Billing Broadcast Intents.

      Messaging sequence

      @@ -396,11 +434,11 @@ application can handle this message the same way it handles the response from an application-initiated REQUEST_PURCHASE message, so that ultimately your application receives a PURCHASE_STATE_CHANGED broadcast intent message that includes information about the item that has been purchased. This applies only to items that have their purchase type set +href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-purchase-type">purchase type set to "managed per user account."

      In the second case, your application can receive an IN_APP_NOTIFY broadcast intent -when Google Play receives a refund notification from Google Checkout. In this case, Google +when Google Play receives a refund notification from Google Wallet. In this case, Google Play sends an IN_APP_NOTIFY message to your application. Your application can handle this message the same way it handles responses from an application-initiated REQUEST_PURCHASE message so that ultimately your application receives a @@ -409,9 +447,9 @@ refunded. The refund information is included in the JSON string that accompanies PURCHASE_STATE_CHANGED broadcast intent. Also, the purchaseState field in the JSON string is set to 2.

      -

      Important: You cannot use the Google Checkout API to +

      Important: You cannot use the Google Wallet API to issue refunds or cancel in-app billing transactions. You must do this manually through your -Google Checkout merchant account. However, you can use the Google Checkout API to retrieve order +Google Wallet merchant account. However, you can use the Google Wallet API to retrieve order information.

      Security Controls

      @@ -439,7 +477,7 @@ application. When your application receives the JSON string, you need to verify the signature of the JSON string.

      For more information about best practices for security and design, see Security and Design.

      +href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and Design.

      In-app Billing Requirements and Limitations

      @@ -449,10 +487,10 @@ limitations.

      • In-app billing can be implemented only in applications that you publish through Google Play.
      • -
      • You must have a Google Checkout Merchant account to use Google Play In-app Billing.
      • -
      • If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of - the MyApps application. If your device is running any other version of Android, in-app billing - requires version 2.3.4 (or higher) of the Google Play application.
      • +
      • You must have a Google Wallet Merchant account to use Google Play In-app Billing.
      • +
      • In-app billing requires version 2.3.4 (or higher) of the Android Market application. + To support subscriptions, version 3.5 or higher of the Google Play app is required. On devices + running Android 3.0, version 5.0.12 (or higher) of the MyApps application is required.
      • An application can use in-app billing only if the device is running Android 1.6 (API level 4) or higher.
      • You can use in-app billing to sell only digital content. You cannot use in-app billing to sell @@ -465,5 +503,5 @@ limitations.

      For more information about in-app billing requirements, see In-App Billing Availability -and Policies.

      +href="https://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=1153481">In-App +Billing Availability and Policies.

      diff --git a/docs/html/guide/market/billing/billing_reference.jd b/docs/html/guide/google/play/billing/billing_reference.jd similarity index 78% rename from docs/html/guide/market/billing/billing_reference.jd rename to docs/html/guide/google/play/billing/billing_reference.jd index e8cf2ee86ec99e0bd3ab4cfa9c209c3c2e644e0a..f8c69678bb50f7abb0a1cd6d1d32ab18acef3212 100755 --- a/docs/html/guide/market/billing/billing_reference.jd +++ b/docs/html/guide/google/play/billing/billing_reference.jd @@ -10,24 +10,25 @@ parent.link=index.html
    • Server Response Codes for In-app Billing
    • In-app Billing Service Interface
    • In-app Billing Broadcast Intents
    • - +
    • Other Broadcast Intents
    • +
    • In-app Billing API Versions
    • Downloads

        -
      1. Sample +
      2. Sample Application

      See also

        -
      1. Overview of In-app +
      2. Overview of In-app Billing
      3. -
      4. Implementing In-app +
      5. Implementing In-app Billing
      6. -
      7. Security and +
      8. Security and Design
      9. -
      10. Testing In-app +
      11. Testing In-app Billing
      12. -
      13. Administering In-app +
      14. Administering In-app Billing
      @@ -39,9 +40,11 @@ parent.link=index.html
    • Google Play Server Response Codes for In-app Billing
    • In-app Billing Interface Parameters
    • In-app Billing Broadcast Intents
    • +
    • Other Intents
    • +
    • In-app Billing API Versions
    -

    Google Play Server Response Codes for In-app Billing

    +

    Server Response Codes for In-app Billing

    The following table lists all of the server response codes that are sent from Google Play to your application. Google Play sends these response codes asynchronously as @@ -102,7 +105,7 @@ codes returned by Google Play.

    RESULT_ERROR 6 Indicates an unexpected server error. For example, this error is triggered if you try to -purchase an item from yourself, which is not allowed by Google Checkout. +purchase an item from yourself, which is not allowed by Google Wallet. @@ -111,7 +114,7 @@ purchase an item from yourself, which is not allowed by Google Checkout.

    The following section describes the interface for Google Play's in-app billing service. The interface is defined in the IMarketBillingService.aidl file, which is included with the in-app billing sample +href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">sample application.

    The interface consists of a single request method sendBillingRequest(). This method takes a single {@link android.os.Bundle} parameter. The Bundle parameter includes several key-value @@ -142,10 +145,13 @@ pairs, which are summarized in table 2.

    API_VERSION int - 1 + Yes - The version of Google Play's in-app billing service you are using. The current version is - 1. + The version of Google Play's in-app billing service you want to use. The current version is + 2. PACKAGE_NAME @@ -227,7 +233,7 @@ pairs, which are summarized in table 2.

  • RESTORE_TRANSACTIONS

    This request retrieves a user's transaction status for managed purchases (see Choosing a + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-purchase-type">Choosing a Purchase Type for more information). You should send this message only when you need to retrieve a user's transaction status, which is usually only when your application is reinstalled or installed for the first time on a device.

    @@ -298,7 +304,7 @@ each in-app billing request type.

    Play application. These broadcast intents inform your application about in-app billing actions that have occurred. Your application must implement a {@link android.content.BroadcastReceiver} to receive these broadcast intents, such as the BillingReceiver that's shown in the in-app -billing sample +billing sample application.

    com.android.vending.billing.RESPONSE_CODE

    @@ -388,7 +394,7 @@ a PURCHASE_STATE_CHANGED intent.

    orderId - A unique order identifier for the transaction. This corresponds to the Google Checkout Order + A unique order identifier for the transaction. This corresponds to the Google Wallet Order ID. @@ -407,8 +413,15 @@ a PURCHASE_STATE_CHANGED intent.

    purchaseState - The purchase state of the order. Possible values are 0 (purchased), 1 (canceled), or 2 - (refunded). + The purchase state of the order. Possible values are 0 (purchased), 1 (canceled), 2 + (refunded), or 3 (expired, for subscription purchases only). + + + purchaseToken + A token that uniquely identifies a subscription purchase for a given item and user pair. + You can use the token to specify the subscription when querying for subscription validity. + +


    Supported only in In-app Billing API version 2 and higher.

    developerPayload @@ -416,3 +429,63 @@ a PURCHASE_STATE_CHANGED intent.

    specify a value for this field when you make a REQUEST_PURCHASE request. + + + +

    HTTP API for verification and cancelation

    + +

    Google Play offers an HTTP-based API that you can use to remotely query the +validity of a specific subscription at any time or cancel a subscription. The +API is designed to be used from your backend servers as a way of securely +managing subscriptions, as well as extending and integrating subscriptions with +other services. See +Google Play Android Developer API for more information.

    + +

    In-app Billing API Versions

    + +

    The In-app Billing API is versioned, with each version offering +additional features to your app. At run time, your app can query the Google Play app to determine +what version of the API it supports and what features are available. Typically, the Google Play app +will be updated and will support the latest version of the API. For a summary of versions see +In-app Billing +API Versions.

    + +

    The sections below list the supported versions of the In-app Billing API. +Versions are specified in the API_VERSION key of the Bundle object +passed in the sendBillingRequest(), which is defined in the defined +in the IMarketBillingService.aidl file, which is included with the +in-app billing +sample application. For more information, see In-app Billing Service Interface.

    +

    In-app Billing version 2

    + +

    May 2012

    + +
      +
    • Adds support for subscriptions. +
        +
      • Adds a new supported string value, "2", for the API_VERSION key + of the Bundle object passed in the sendBillingRequest().
      • +
      • Adds a new JSON field, purchaseToken, to the + orders list returned in a PURCHASE_STATE_CHANGED + intent.
      • +
      • Adds a new purchaseState value, 3 (expired), to the + orders list returned in a PURCHASE_STATE_CHANGED + intent. The value indicates that a subscription has expired and is no longer valid.
      • +
      • Requires Google Play (Play Store) version 3.5 or higher.
      • +
      + +

      In-app Billing version 1

      + +

      March 2011

      + +
        +
      • Initial release.
      • +
      • Requires Google Play/Android Market 2.3.4 or higher.
      • +
      + diff --git a/docs/html/guide/google/play/billing/billing_subscriptions.jd b/docs/html/guide/google/play/billing/billing_subscriptions.jd new file mode 100755 index 0000000000000000000000000000000000000000..3cf97777dea8ecd6c5eef931054505e310dab78d --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_subscriptions.jd @@ -0,0 +1,859 @@ +page.title=Subscriptions +parent.title=In-app Billing +parent.link=index.html +@jd:body + + + +

      Subscriptions let you sell content, services, or features in your app with +automated, recurring billing. Adding support for subscriptions is +straightforward and you can easily adapt an existing In-app Billing +implementation to sell subscriptions.

      + +

      If you have already implemented In-app Billing for one-time purchase +products, you will find that you can add support for subscriptions with minimal +impact on your code. If you are new to In-app Billing, you can implement +subscriptions using the standard communication model, data structures, and user +interactions as for other in-app products.subscriptions. Because the +implementation of subscriptions follows the same path as for other in-app +products, details are provided outside of this document, starting with the In-app Billing +Overview.

      + +

      This document is focused on highlighting implementation details that are +specific to subscriptions, along with some strategies for the associated billing +and business models.

      + +

      Overview of Subscriptions

      + +

      A subscription is a new product type offered in In-app Billing that lets you +sell content, services, or features to users from inside your app with recurring +monthly or annual billing. You can sell subscriptions to almost any type of +digital content, from any type of app or game.

      + +

      As with other in-app products, you configure and publish subscriptions using +the Developer Console and then sell them from inside apps installed on an +Android-powered devices. In the Developer console, you create subscription +products and add them to a product list, setting a price for each, choosing a +billing interval of monthly or annually, and then publishing. In your apps, it’s +straightforward to add support for subscription purchases. The implementation +extends the standard In-app Billing API to support a new product type but uses +the same communication model, data structures, and user interactions as for +other in-app products.

      + +

      When users purchase subscriptions in your apps, Google Play handles all +checkout details so your apps never have to directly process any financial +transactions. Google Play processes all payments for subscriptions through +Google Wallet, just as it does for standard in-app products and app purchases. +This ensures a consistent and familiar purchase flow for your users.

      + + + + +

      After users have purchase subscriptions, they can view the subscriptions and +cancel them, if necessary, from the My Apps screen in the Play Store app or +from the app's product details page in the Play Store app.

      + + + +

      Once users have purchased a subscription through In-app Billing, you can +easily give them extended access to additional content on your web site (or +other service) through the use of a server-side API provided for In-app Billing. +The server-side API lets you validate the status of a subscription when users +sign into your other services. For more information about the API, see Google Play Android Developer API, below.

      + +

      You can also build on your existing external subscriber base from inside your +Android apps. If you sell subscriptions on a web site, for example, you can add +your own business logic to your Android app to determine whether the user has +already purchased a subscription elsewhere, then allow access to your content if +so or offer a subscription purchase from Google Play if not.

      + +

      With the flexibility of In-app Billing, you can even implement your own +solution for sharing subscriptions across as many different apps or products as +you want. For example, you could sell a subscription that gives a subscriber +access to an entire collection of apps, games, or other content for a monthly or +annual fee. To implement this solution, you could add your own business logic to +your app to determine whether the user has already purchased a given +subscription and if so, allow access to your content.

      + + + +

      In general the same basic policies and terms apply to subscriptions as to +standard in-app products, however there are some differences. For complete +information about the current policies and terms, please read the policies document.

      + + +

      Subscription publishing and unpublishing

      + +

      To sell a subscription in an app, you use the tools in the Developer Console +to set up a product list for the app and then create and configure a new +subscription. In the subscription, you set the price and billing interval and +define a subscription ID, title, and description. When you are ready, you can +then publish the subscription in the app product list.

      + +

      In the product list, you can add subscriptions, in-app products, or both. You +can add multiple subscriptions that give access to different content or +services, or you can add multiple subscriptions that give access to the same +content but for different intervals or different prices, such as for a +promotion. For example, a news outlet might decide to offer both monthly and +annual subscriptions to the same content, with annual having a discount. You can +also offer in-app purchase equivalents for subscription products, to ensure that +your content is available to users of older devices that do not support +subscriptions.

      + +

      After you add a subscription or in-app product to the product list, you must +publish the product before Google Play can make it available for purchase. Note +that you must also publish the app itself before Google Play will make the +products available for purchase inside the app.

      + +

      Important: At this time, the capability to +unpublish a subscription is not available. Support for unpublishing a +subscription is coming to the Developer Console in the weeks ahead, so this is a +temporary limitation. In the short term, instead of unpublishing, +you can remove the subscription product from the product list offered in your +app to prevent users from seeing or purchasing it.

      + +

      Subscription pricing

      + +

      When you create a subscription in the Developer Console, you can set a price +for it in any available currencies. Each subscription must have a non-zero +price. You can price multiple subscriptions for the same content differently +— for example you could offer a discount on an annual subscription +relative to the monthly equivalent.

      + +

      Important: At this time, once you publish a +subscription product, you cannot change its price in any currency. Support for +changing the price of published subscriptions is coming to the Developer Console +in the weeks ahead. In the short term, you can work around this limitation by +publishing a new subscription product ID at a new price, then offer it in your +app instead of the original product. Users who have already purchased will +continue to be charged at the original price, but new users will be charged at +the new price.

      + +

      User billing

      + +

      You can sell subscription products with automated recurring billing at +either of two intervals:

      + +
        +
      • Monthly — Google Play bills the customer’s Google Wallet account at + the time of purchase and monthly subsequent to the purchase date (exact billing + intervals can vary slightly over time)
      • +
      • Annually — Google Play bills the customer's Google Wallet account at + the time of purchase and again on the same date in subsequent years.
      • +
      + +

      Billing continues indefinitely at the interval and price specified for the +subscription. At each subscription renewal, Google Play charges the user account +automatically, then notifies the user of the charges afterward by email. Billing +cycles will always match subscription cycles, based on the purchase date.

      + +

      Over the life of a subscription, the form of payment billed remains the same +— Google Play always bills the same form of payment (such as credit card, +Direct Carrier Billing) that was originally used to purchase the +subscription.

      + +

      When the subscription payment is approved by Google Wallet, Google Play +provides a purchase token back to the purchasing app through the In-app Billing +API. For details, see Purchase token, below. Your apps can +store the token locally or pass it to your backend servers, which can then use +it to validate or cancel the subscription remotely using the Google Play Android Developer API.

      + +

      In the case of billing errors, such as could happen if the customer’s credit +card becomes invalid, Google Play notifies your app of the change in purchase +state.

      + +

      As a best practice, we recommend that your app includes business logic to +notify your backend servers of subscription purchases, tokens, and any billing +errors that may occur. Your backend servers can use the server-side API to query +and update your records and follow up with customers directly, if needed.

      + +

      Subscription cancellation

      + +

      Users can view the status of all of their subscriptions and cancel them if +necessary from the My Apps screen in the Play Store app. Currently, the In-app +Billing API does not provide support for canceling subscriptions direct from +inside the purchasing app, although your app can broadcast an Intent to launch +the Play Store app directly to the My Apps screen.

      + +

      When the user cancels a subscription, Google Play does not offer a refund for +the current billing cycle. Instead, it allows the user to have access to the +cancelled subscription until the end of the current billing cycle, at which time +it terminates the subscription. For example, if a user purchases a monthly +subscription and cancels it on the 15th day of the cycle, Google Play will +consider the subscription valid until the end of the 30th day (or other day, +depending on the month).

      + +

      In some cases, the user may contact you directly to request cancellation of a +subscription. In this and similar cases, you can use the server-side API to +query and directly cancel the user’s subscription from your servers. + +

      Important: In all cases, you must continue +to offer the content that your subscribers have purchased through their +subscriptions, for as long any users are able to access it. That is, you must +not remove any subscriber’s content while any user still has an active +subscription to it, even if that subscription will terminate at the end of the +current billing cycle. Removing content that a subscriber is entitled to access +will result in penalties. Please see the policies document for more information.

      + +

      App uninstallation

      + +

      When the user uninstalls an app that includes purchased subscriptions, the Play Store app will notify the user that there are active subscriptions. If the user chooses to continue with the uninstalltion, the app is removed and the subscriptions remain active and recurring billing continues. The user can return to cancel the associated subscriptions at any time in the My Apps screen of the Play Store app. If the user chooses to cancel the uninstallation, the app and subscriptions remain as they were.

      + +

      Refunds

      + +

      As with other in-app products, Google Play does not provide a refund window +for subscription purchases. For example, users who purchase an app can ask for a +refund from Google Play within a 15-minute window. With subscriptions, Google +Play does not provide a refund window, so users will need to contact you +directly to request a refund. + +

      If you receive requests for refunds, you can use the server-side API to +cancel the subscription or verify that it is already cancelled. However, keep in +mind that Google Play considers cancelled subscriptions valid until the end of +their current billing cycles, so even if you grant a refund and cancel the +subscription, the user will still have access to the content. + +

      Note: Partial refunds for canceled +subscriptions are not available at this time.

      + +

      Payment processing and policies

      + +

      In general, the terms of Google Play allow you to sell in-app subscriptions +only through the standard payment processor, Google Wallet. For purchases of any +subscription products, just as for other in-app products and apps, the +transaction fee for subscriptions, just as for other in-app purchases, is the +same as the transaction fee for application purchases (30%).

      + +

      Apps published on Google Play that are selling subscriptions must use In-app +Billing to handle the transaction and may not provide links to a purchase flow +outside of the app and Google Play (such as to a web site).

      + +

      For complete details about terms and policies, see the policies +document.

      + +

      System requirements for subscriptions

      + +

      In-app purchases of subscriptions are supported only on devices that meet +these minimum requirements:

      + +
        +
      • Must run Android 2.2 or higher
      • +
      • Google Play Store app, version 3.5 or higher, must be installed
      • +
      + +

      Google Play 3.5 and later versions include support for the In-app Billing +v2 API or higher, which is needed to support handling of subscription +products.

      + +

      Compatibility considerations

      + +

      As noted in the previous section, support for subscriptions is available only +on devices that meet the system requirements. Not all devices will receive or +install Google Play 3.5, so not all users who install your apps will have access +to the In-app Billing API and subscriptions.

      + +

      If you are targeting older devices that run Android 2.1 or earlier, we +recommend that you offer those users an alternative way buy the content that is +available through subscriptions. For example, you could create standard in-app +products (one-time purchases) that give access to similar content as your +subscriptions, possibly for a longer interval such as a year.

      + + +

      Implementing Subscriptions

      + +

      Subscriptions are a standard In-app Billing product type. If you have already +implemented In-app Billing for one-time purchase products, you will find that +adding support for subscriptions is straightforward, with minimal impact on your +code. If you are new to In-app Billing, you can implement subscriptions using +the standard communication model, data structures, and user interactions as for +other in-app products.subscriptions.

      + +

      The full implementation details for In-app Billing are provided outside of +this document, starting with the In-app Billing +Overview. This document is focused on highlighting implementation details +that are specific to subscriptions, along with some strategies for the +associated billing and business models.

      + + +

      Sample application

      + +

      To help you get started with your In-app Billing implementation and +subscriptions, an updated version of the In-app Billing sample app is available. +You can download the sample app from the Android SDK repository using the +Android SDK Manager. For details, see +Downloading the Sample Application.

      + +

      Application model

      + +

      With subscriptions, your app uses the standard In-app Billing application +model, sending billing requests to the Play Store application over interprocess +communication (IPC) and receiving purchase responses from the Play Store app in +the form of asynchronous broadcast intents. Your application does not manage any +network connections between itself and the Google Play server or use any special +APIs from the Android platform.

      + +

      Your app also uses the standard In-app Billing components — a billing +Service for sending requests, a BroadcastReceiver for receiving the responses, +and a security component for verifying that the response was sent by Google +Play. Also recommended are a response Handler for processing notifications, +errors, and status messages, and an observer for sending callbacks to your +application as needed. All of these components and their interactions are +described in full in the In-app Billing +Overview and related documents.

      + +

      To initiate different types of billing communication with Google Play, your +app will use the standard set of in-app billing requests and receive the same +responses. Inside the requests and responses are two new fields described below. +

      + +

      Purchase token

      + +

      Central to the end-to-end architecture for subscriptions is the purchase +token, a string value that uniquely identifies (and associates) a user ID and a +subscription ID. Google Play generates the purchase token when the user +completes the purchase of a subscription product (and payment is approved by +Google Wallet) and then sends it to the purchasing app on the device through the +In-app Billing API.

      + +

      At the conclusion of a PURCHASE_REQUEST message flow, your app +can retrieve the purchase token and other transaction details by initiating a +GET_PURCHASE_INFORMATION request. The Bundle returned by the call +contains an JSON array of order objects. In the order corresponding to the +subscription purchase, the token is available in the purchaseToken +field.

      + +

      An example of a JSON order object that includes a subscription purchase token +is shown below.

      + +
      { "nonce" : 1836535032137741465,
      +  "orders" :
      +    [{ "notificationId" : "android.test.purchased",
      +       "orderId" : "transactionId.android.test.purchased",
      +       "packageName" : "com.example.dungeons",
      +       "productId" : "android.test.purchased",
      +       "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
      +       "purchaseTime" : 1290114783411,
      +       "purchaseState" : 0,
      +       "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }]
      +}
      +
      + +

      After receiving a purchase token, your apps can store the token locally or +pass it to your backend servers, which can then use it to query the billing +status or cancel the subscription remotely. If your app will store the token +locally, please read the Security and +Design document for best practices for maintaining the security of your +data.

      + +

      Checking the In-app Billing API version

      + +

      Subscriptions support is available only in versions of Google Play that +support the In-app Billing v2 API (Google Play 3.5 and higher). For your app, +an essential first step at launch is to check whether the version of Google Play +installed on the device supports the In-app Billing v2 API and +subscriptions.

      + +

      To do this, create a CHECK_BILLING_SUPPORTED request Bundle that includes the +required key-value pairs, together with

      + +
        +
      • The API_VERSION key, assigning a value of 2.
      • +
      • The BILLING_REQUEST_ITEM_TYPE key, assigning a value of “subs”
      • +
      + +

      Send the request using sendBillingRequest(Bundle) and receive +the response Bundle. You can extract the response from the +BILLING_RESPONSE_RESPONSE_CODE key of the response. RESULT_OK +indicates that subscriptions are supported.

      + +

      The sample app declares constants for the accepted +BILLING_REQUEST_ITEM_TYPE values (from Consts.java):

      + +
         // These are the types supported in the IAB v2
      +   public static final String ITEM_TYPE_INAPP = "inapp";
      +   public static final String ITEM_TYPE_SUBSCRIPTION = "subs";
      +
      + +

      It sets up a convenience method for building the request bundle (from BillingService.java):

      + +
             protected Bundle makeRequestBundle(String method) {
      +           Bundle request = new Bundle();
      +           request.putString(Consts.BILLING_REQUEST_METHOD, method);
      +           request.putInt(Consts.BILLING_REQUEST_API_VERSION, 2);
      +           request.putString(Consts.BILLING_REQUEST_PACKAGE_NAME, getPackageName());
      +           return request;
      +       }
      +
      + +

      Here’s an example of how to test support for In-App Billing v2 and subscriptions +(from BillingService.java):

      + +
         /**
      +    * Wrapper class that checks if in-app billing is supported.
      +    */
      +   class CheckBillingSupported extends BillingRequest {
      +       public String mProductType = null;
      +       public CheckBillingSupported() {
      +           // This object is never created as a side effect of starting this
      +           // service so we pass -1 as the startId to indicate that we should
      +           // not stop this service after executing this request.
      +           super(-1);
      +       }
      +
      +       public CheckBillingSupported(String type) {
      +           super(-1);
      +           mProductType = type;
      +       }
      +
      +       @Override
      +       protected long run() throws RemoteException {
      +           Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED");
      +           if (mProductType != null) {
      +               request.putString(Consts.BILLING_REQUEST_ITEM_TYPE, mProductType);
      +           }
      +           Bundle response = mService.sendBillingRequest(request);
      +           int responseCode = response.getInt(Consts.BILLING_RESPONSE_RESPONSE_CODE);
      +           if (Consts.DEBUG) {
      +               Log.i(TAG, "CheckBillingSupported response code: " +
      +                       ResponseCode.valueOf(responseCode));
      +           }
      +           boolean billingSupported = (responseCode == ResponseCode.RESULT_OK.ordinal());
      +           ResponseHandler.checkBillingSupportedResponse(billingSupported, mProductType);
      +           return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID;
      +       }
      +   }
      +
      + +

      Requesting a subscription purchase

      + +

      Once you’ve checked the API version as described above and determined that +subscriptions are supported, you can present subscription products to the user +for purchase. When the user has selected a subscription product and initiated a +purchase, your app handles the purchase just as it would for other in-app +products — by sending a REQUEST_PURCHASE request. You can then launch +Google Play to display the checkout user interface and handle the financial +transaction.. + +

      The REQUEST_PURCHASE includes a Bundle containing the item details, as +described in the In-app Billing +Overview. For a subscription, the Bundle must also specify:

      + +
        +
      • The ITEM_ID key, with a value that specifies a valid, published + subscription product.
      • +
      • The ITEM_TYPE key, with a value of “subs” + (ITEM_TYPE_SUBSCRIPTION in the sample app). If the request does not + specify the subscription's ITEM_TYPE, Google Play attempts to + handle the request as a standard in-app purchase (one-time purchase).
      • +
      + +

      Google Play synchronously returns a response bundle that includes +RESPONSE_CODE, PURCHASE_INTENT, and +REQUEST_ID. Your app uses the PURCHASE_INTENT to +launch the checkout UI and the message flow proceeds exactly as described in Messaging sequence.

      + +

      Here’s how the sample app initiates a purchase for a subscription, where +mProductType is ITEM_TYPE_SUBSCRIPTION (from +BillingService.java).

      + +
         /**
      +    * Wrapper class that requests a purchase.
      +    */
      +   class RequestPurchase extends BillingRequest {
      +       public final String mProductId;
      +       public final String mDeveloperPayload;
      +       public final String mProductType;
      +
      +. . .
      +
      +       @Override
      +       protected long run() throws RemoteException {
      +           Bundle request = makeRequestBundle("REQUEST_PURCHASE");
      +           request.putString(Consts.BILLING_REQUEST_ITEM_ID, mProductId);
      +           request.putString(Consts.BILLING_REQUEST_ITEM_TYPE, mProductType);
      +           // Note that the developer payload is optional.
      +           if (mDeveloperPayload != null) {
      +               request.putString(Consts.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload);
      +           }
      +           Bundle response = mService.sendBillingRequest(request);
      +           PendingIntent pendingIntent
      +                   = response.getParcelable(Consts.BILLING_RESPONSE_PURCHASE_INTENT);
      +           if (pendingIntent == null) {
      +               Log.e(TAG, "Error with requestPurchase");
      +               return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID;
      +           }
      +
      +           Intent intent = new Intent();
      +           ResponseHandler.buyPageIntentResponse(pendingIntent, intent);
      +           return response.getLong(Consts.BILLING_RESPONSE_REQUEST_ID,
      +                   Consts.BILLING_RESPONSE_INVALID_REQUEST_ID);
      +       }
      +
      +       @Override
      +       protected void responseCodeReceived(ResponseCode responseCode) {
      +           ResponseHandler.responseCodeReceived(BillingService.this, this, responseCode);
      +       }
      +   }
      +
      + +

      Restoring transactions

      + +

      Subscriptions always use the managed by user account purchase type, +so that you can restore a record of subscription transactions on the device when +needed. When a user installs your app onto a new device, or when the user +uninstalls/reinstalls the app on the original device, your app should restore +the subscriptions that the user has purchased.

      + +

      The process for restoring subscriptions transactions is the same as described +in Messaging sequence. Your app sends a +RESTORE_TRANSACTIONS request to Google Play. Google Play sends two +broadcast intents as asynchronous responses — a RESPONSE_CODE +intent and a PURCHASE_STATE_CHANGED intent.

      + +

      The PURCHASE_STATE_CHANGED intent contains a notification ID +that your app can use to retrieve the purchase details, including the purchase +token, by sending a standard GET_PURCHASE_INFORMATION request. The +Bundle returned in the call includes an JSON array of order objects +corresponding to subscription (and in-app product) purchases that you can +restore locally.

      + +

      Your app can store the restored purchase state and other transaction details +in the way that best meets your needs. Your app can use it later to check the +subscription validity, although please read the Security and +Design document for best practices for maintaining the security of your +data.

      + +

      Checking subscription validity

      + +

      Subscriptions are time-bound purchases that require successful billing +recurrences over time to remain valid. Your app should check the validity of +purchased subscriptions at launch or prior to granting access to subscriber +content.

      + +

      With In-app Billing, you validate a subscription by keeping track of its +purchase state, such as purchased or cancelled, and then checking the state +whenever needed. Google Play provides two ways to let you know when the purchase +state of a subscription changes:

      + +
        +
      • In-app Billing Notifications. Google Play pushes a notification + to your app whenever the purchase state of a subscription changes. Your app can + store the most recent purchase state for a given purchase token and then check + that state at run time, as needed.
      • +
      • Google Play Android Developer API. You can use this HTTP-based + API to poll Google Play for the current purchase state of a subscription. You + can store the purchased state for each purchaseToken on your + backend servers. For more information, see Google Play + Android Developer API, below.
      • +
      + +

      For most use-cases, especially those where backend servers are already keeping +track of subscribed users, implementing a combination of both methods is the +recommended approach. A typical implementation might work like this:

      + +
        +
      • When the user successfully purchases a new subscription, your app notifies a + backend server, which stores the purchase token, user name, and other + information in a secure location.
      • +
      • Since your app cannot know the expiration date, your server can poll Google + Play to get the expiration and store it with the purchase token and other + data.
      • +
      • Because your server now knows the expiration date, it does not need to poll + Google Play again until after the expiration date, at which time it can confirm + that the subscription was not cancelled.
      • +
      • On the client side, your app can continue to update the server whenever the + purchase state changes, storing the state locally.
      • +
      + +

      If you are using both notifications and the Google Play Android Developer API to validate subscriptions, we recommend the following:

      + +
        +
      • If your app wants to check validity but you can’t reach your server (or +you don’t have a server), use the latest purchase state received by +notification.
      • +
      • If you have a server and it’s reachable, always give preference to the +purchase state obtained from your server over the state received in +notifications.
      • +
      + +

      If necessary, you can also use a RESTORE_TRANSACTIONS request to retrieve a record of all managed and in-app products purchased by the user, which you can then store locally. However, using RESTORE_TRANSACTIONS on a regular basis is not recommended because of performance impacts.

      + +

      Regardless of the approach you choose, your app should check subscriptions +and validity at launch, such as prior to accessing subscriber content, game +levels, and so on.

      + +

      Table 1. Summary of purchaseState +values for subscription purchases, as received with a +PURCHASE_STATE_CHANGED intent.

      + + + + + + + + + + +
      StatepurchaseState ValueComments
      Purchased successfully0Sent at original purchase only (not at recurring billing cycles).
      Cancelled1Sent at original purchase only if the purchase has failed for some reason.
      Refunded2The purchase was refunded.
      Subscription expired3Sent if a subscription expires because of non-payment or user cancelation.
      + + +

      Launching your product page to let the user cancel or view subscriptions

      + +

      In-app Billing does not currently provide an API to let users directly view or cancel +subscriptions from within the purchasing app. Instead, users can launch the Play +Store app on their devices and go to the My Apps screen to manage subscriptions. In My Apps, +users can see a list of their subscriptions organized by application. Tapping one of the +subscriptions loads the app's product page, from which users can see active subscriptions +and billing status and cancel subscriptions as needed.

      + +

      To make it easier for users to find and manage their subscriptions from inside your app, +we recommend that you offer a "View My Subscriptions" or "Manage Subscriptions" option in +your UI that directly loads your app's product page in the Play Store app.

      + +

      To do this, create an intent with the ACTION_VIEW +action and include the market:// URI (rather than the http:// +URI) of your app's details page. Here’s an example:

      + +
      Intent intent = new Intent(Intent.ACTION_VIEW);
      +intent.setData(Uri.parse("market://details?id=com.example.app"));
      +startActivity(intent);
      + +

      For more information, see + Linking to Your Products.

      + +

      Recurring billing and changes in purchase state

      + +

      Google Play notifies your app when the user completes the purchase of a +subscription, but the purchase state does not change over time, provided that +recurring billing takes place successfully. Google Play does not notify your app +of a purchase state change until the subscription expires because of +non-payment or user cancellation.

      + +

      Over the life of a subscription, your app does not need to initiate any +recurring billing events — those are all handled by Google Play and they +are transparent to your application if billing is successful.

      + +

      Modifying your app for subscriptions

      + +

      For subscriptions, you make the same types of modifications to your app as +are described in +Modifying your Application Code.

      + +

      Note that, in your UI that lets users view and select subscriptions for +purchase, you should add logic to check for purchased subscriptions and validate +them. Your UI should not present subscriptions if the user has already purchased +them.

      + +

      Administering Subscriptions

      + +

      To create and manage subscriptions, you use the tools in the Developer +Console, just as for other in-app products.

      + +

      At the Developer Console, you can configure these attributes for each +subscription product:

      + +
        +
      • Purchase Type: always set to “subscription”
      • +
      • Subscription ID: An identifier for the subscription
      • +
      • Publishing State: Unpublished/Published
      • +
      • Language: The default language for displaying the subscription
      • +
      • Title: The title of the subscription product
      • +
      • Description: Details that tell the user about the subscription
      • +
      • Price: USD price of subscription per recurrence
      • +
      • Recurrence: monthly or yearly
      • +
      • Additional currency pricing (can be auto-filled)
      • +
      + +

      For details, please see Administering +In-app Billing.

      + + +

      Google Play Android Developer API

      + +

      Google Play offers an HTTP-based API that you can use to remotely query the +validity of a specific subscription at any time or cancel a subscription. The +API is designed to be used from your backend servers as a way of securely +managing subscriptions, as well as extending and integrating subscriptions with +other services.

      + +

      Using the API

      + +

      To use the API, you must first register a project at the Google APIs Console and receive +a Client ID and shared secret that your app will present when calling the +Google Play Android Developer API. All calls to the API are authenticated with +OAuth 2.0.

      + +

      Once your app is registered, you can access the API directly, using standard +HTTP methods to retrieve and manipulate resources, or you can use the Google +APIs Client Libraries, which are extended to support the API.

      + +

      The Google Play Android Developer API is built on a RESTful design that uses +HTTP and JSON, so any standard web stack can send requests and parse the +responses. However, if you don’t want to send HTTP requests and parse responses +manually, you can access the API using the client libraries, which provide +better language integration, improved security, and support for making calls +that require user authorization.

      + +

      For more information about the API and how to access it through the Google +APIs Client Libraries, see the documentation at:

      + +

      https://developers. +google.com/android-publisher/v1/

      + +

      Quota

      + +

      Applications using the Google Play Android Developer API are limited to an +initial courtesy usage quota of 15000 requests per day (per +application). This should provide enough access for normal +subscription-validation needs, assuming that you follow the recommendation in +this section.

      + +

      If you need to request a higher limit for your application, please use the +“Request more” link in the Google APIs Console. +Also, please read the section below on design best practices for minimizing your +use of the API.

      + +

      Authorization

      + +

      Calls to the Google Play Android Developer API require authorization. Google +uses the OAuth 2.0 protocol to allow authorized applications to access user +data. To learn more, see Authorization +in the Google Play Android Developer API documentation.

      + +

      Using the API efficiently

      + +

      Access to the Google Play Android Developer API is regulated to help ensure a +high-performance environment for all applications that use it. While you can +request a higher daily quota for your application, we highly recommend that you +minimize your access using the technique(s) below.

      + +
        +
      • Store subscription expiry on your servers — your servers + should use the Google Play Android Developer API to query the expiration date + for new subscription tokens, then store the expiration date locally. This allows + you to check the status of subscriptions only at or after the expiration (see + below).
      • +
      • Cache expiration and purchaseState — If your app contacts + your backend servers at runtime to verify subscription validity, your server + should cache the expiration and purchaseState to ensure the fastest possible + response (and best experience) for the user.
      • +
      • Query for subscription status only at expiration — Once your + server has retrieved the expiration date of subscription tokens, it should not + query the Google Play servers for the subscription status again until the + subscription is reaching or has passed the expiration date. Typically, your + servers would run a batch query each day to check the status of + expiring subscriptions, then update the database. Note that: +
          +
        • Your servers should not query all subscriptions every day
        • +
        • Your servers should never query subscription status dynamically, based on + individual requests from your Android application.
        • +
        +
      • +
      + +

      By following those general guidelines, your implementation will offer the +best possible performance for users and minimize use of the Google Play Android +Developer API.

      + diff --git a/docs/html/guide/market/billing/billing_testing.jd b/docs/html/guide/google/play/billing/billing_testing.jd similarity index 86% rename from docs/html/guide/market/billing/billing_testing.jd rename to docs/html/guide/google/play/billing/billing_testing.jd index 77aa3edc51f76af81bde088d10fabc52cd2ab44d..e2d4a014cbbfc1d51f7fdb68381d4840825f5a0c 100755 --- a/docs/html/guide/market/billing/billing_testing.jd +++ b/docs/html/guide/google/play/billing/billing_testing.jd @@ -13,20 +13,20 @@ parent.link=index.html

      Downloads

        -
      1. Sample +
      2. Sample Application

      See also

        -
      1. Overview of In-app +
      2. Overview of In-app Billing
      3. -
      4. Implementing In-app +
      5. Implementing In-app Billing
      6. -
      7. Security and +
      8. Security and Design
      9. -
      10. Administering In-app +
      11. Administering In-app Billing
      12. -
      13. In-app Billing +
      14. In-app Billing Reference
      @@ -42,7 +42,7 @@ must run a standard version of the Android 1.6 or later platform (API level 4 or the most current version of the Google Play application installed. If a device is not running the most current Google Play application, your application won't be able to send in-app billing requests to Google Play. For general information about how to set up a device for use in -developing Android applications, see Using Hardware +developing Android applications, see Using Hardware Devices.

      The following section shows you how to set up and use the in-app billing test tools.

      @@ -62,7 +62,7 @@ product ID android.test.purchased.

      - Figure 1. Checkout flow for the special reserved item android.test.purchased. + Figure 1. Wallet flow for the special reserved item android.test.purchased.

      You do not need to list the reserved products in your application's product list. Google Play @@ -91,10 +91,10 @@ reserved product IDs.

      When you make an in-app billing request with this product ID, Google Play responds as though the purchase was refunded. Refunds cannot be initiated through Google Play's in-app billing service. Refunds must be initiated by you (the merchant). After you process a refund - request through your Google Checkout account, a refund message is sent to your application by - Google Play. This occurs only when Google Play gets notification from Google Checkout that + request through your Google Wallet account, a refund message is sent to your application by + Google Play. This occurs only when Google Play gets notification from Google Wallet that a refund has been made. For more information about refunds, see Handling + href="{@docRoot}guide/google/play/billing/billing_overview.html#billing-action-notify">Handling IN_APP_NOTIFY messages and In-app Billing Pricing.

      @@ -108,7 +108,7 @@ reserved product IDs.

      In some cases, the reserved items may return signed static responses, which lets you test signature verification in your application. To test signature verification with the special reserved product IDs, you may need to set up test accounts or +href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-testing-setup">test accounts or upload your application as a unpublished draft application. Table 1 shows you the conditions under which static responses are signed.

      @@ -178,7 +178,7 @@ application's product list you use one of the reserved product IDs.

      You cannot use the emulator to test in-app billing; you must install your application on a device to test in-app billing.

      To learn how to install an application on a device, see Running on a + href="{@docRoot}tools/building/building-cmdline.html#RunningOnDevice">Running on a device.

    • Sign in to your device with your developer account. @@ -216,16 +216,16 @@ testing.

      To test your in-app billing implementation with actual in-app purchases, you will need to register at least one test account on the Google Play publisher site. You cannot use your -developer account to test the complete in-app purchase process because Google Checkout does not let +developer account to test the complete in-app purchase process because Google Wallet does not let you buy items from yourself. If you have not set up test accounts before, see Setting up test +href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-testing-setup">Setting up test accounts.

      Also, a test account can purchase an item in your product list only if the item is published. The application does not need to be published, but the item does need to be published.

      -

      When you use a test account to purchase items, the test account is billed through Google Checkout -and your Google Checkout Merchant account receives a payout for the purchase. Therefore, you may +

      When you use a test account to purchase items, the test account is billed through Google Wallet +and your Google Wallet Merchant account receives a payout for the purchase. Therefore, you may want to refund purchases that are made with test accounts, otherwise the purchases will show up as actual payouts to your merchant account.

      @@ -243,20 +243,20 @@ actual payouts to your merchant account.

    • Add items to the application's product list.

      Make sure that you publish the items (the application can remain unpublished). See Creating a product + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-catalog">Creating a product list to learn how to do this.

    • Install your application on an Android-powered device.

      You cannot use the emulator to test in-app billing; you must install your application on a device to test in-app billing.

      To learn how to install an application on a device, see Running on a + href="{@docRoot}tools/building/building-cmdline.html#RunningOnDevice">Running on a device.

    • Make one of your test accounts the primary account on your device.

      To perform end-to-end testing of in-app billing, the primary account on your device must be one of the test accounts + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-testing-setup">test accounts that you registered on the Google Play site. If the primary account on your device is not a test account, you must do a factory reset of the device and then sign in with one of your test accounts. To perform a factory reset, do the following:

      @@ -286,8 +286,8 @@ do a factory reset, making sure you log on with your primary account first.

      When you are finished testing your in-app billing implementation, you are ready to publish your application on Google Play. You can follow the normal steps for preparing, signing, and publishing your application. +href="{@docRoot}tools/publishing/preparing.html">preparing, signing, and publishing on Google Play.

      diff --git a/docs/html/guide/google/play/billing/index.jd b/docs/html/guide/google/play/billing/index.jd new file mode 100755 index 0000000000000000000000000000000000000000..a33b19961f130487bcb2ac9a1da3f8835fa79159 --- /dev/null +++ b/docs/html/guide/google/play/billing/index.jd @@ -0,0 +1,116 @@ +page.title=In-app Billing +@jd:body + + + +

      In-app Billing is a Google Play service that lets you sell digital content from inside +your applications. You can use the service to sell a wide range of content, including downloadable +content such as media files or photos, virtual content such as game levels or potions, premium services +and features, and more. You can use In-app Billing to sell products as

      + +
        +
      • Standard in-app products (one-time billing), or
      • +
      • Subscriptions, (recurring, automated billing)
      • +
      + + + +

      When you use the in-app billing service to sell an item, +whether it's an in-app product or a subscription, Google Play +handles all checkout details so your application never has to directly process +any financial transactions. Google Play uses the same checkout backend service as +is used for application purchases, so your users experience a consistent and +familiar purchase flow (see figure 1). Also, the transaction fee for in-app +purchases is the same as the transaction fee for application purchases +(30%).

      + +

      Any application that you publish through Google Play can implement In-app Billing. No special +account or registration is required other than an Android Market publisher account and a Google +Wallet Merchant account. Also, because the service uses no dedicated framework APIs, you can add +in-app billing to any application that uses a minimum API level of 4 or higher.

      + +

      To help you integrate in-app billing into your application, the Android SDK +provides a sample application that demonstrates how to sell standard in-app +products and subscriptions from inside an app. The sample contains examples of +billing-related classes you can use to implement in-app billing in your +application. It also contains examples of the database, user interface, and +business logic you might use to implement in-app billing.

      + +

      Important: Although the sample application is a working example +of how you can implement in-app billing, we strongly recommend that you modify and +obfuscate the sample code before you use it in a production application. For more information, see +Security and Design.

      + + +

      + Figure 1. Applications initiate in-app billing requests through their own UI + (first screen). Google Play responds to the request by providing the checkout user interface + (middle screen). When checkout is complete, the application resumes. +

      + +

      To learn more about Google Play's in-app billing service and start integrating it into your +applications, read the following documents:

      + +
      +
      Overview of In-app + Billing
      +
      Learn how the service works and what a typical in-app billing implementation looks + like.
      +
      Implementing + In-app Billing
      +
      Use this step-by-step guide to start incorporating in-app billing into your + application. The instructions apply to both one-time and subscription purchases.
      + +
      Subscriptions
      +
      Learn how subscriptions work and how to implement support for them in your app.
      +
      Security + and Design
      +
      Review these best practices to help ensure that your in-app billing implementation is + secure and well designed.
      +
      Testing In-app + Billing
      +
      Understand how the in-app billing test tools work and learn how to test your in-app billing + implementation.
      +
      Administering + In-app Billing
      +
      Learn how to set up your product list, register test accounts, and handle refunds.
      +
      In-app Billing + Reference
      +
      Get detailed information about Google Play response codes and the in-app billing + interface.
      +
      + diff --git a/docs/html/guide/market/expansion-files.jd b/docs/html/guide/google/play/expansion-files.jd similarity index 97% rename from docs/html/guide/market/expansion-files.jd rename to docs/html/guide/google/play/expansion-files.jd index 36b8f9ca043e214af7c02fa24f3189677402c1a7..62ca1e2572f81c19aba607837aa547a6c9e8f5de 100644 --- a/docs/html/guide/market/expansion-files.jd +++ b/docs/html/guide/google/play/expansion-files.jd @@ -52,8 +52,8 @@ page.title=APK Expansion Files

      See also

        -
      1. Application Licensing
      2. -
      3. Multiple +
      4. Application Licensing
      5. +
      6. Multiple APK Support
      @@ -215,7 +215,7 @@ already saved on the device.
    • If yes, your app is ready to go.
    • If no, your app must download the expansion files over HTTP from Google Play. Your app must send a request to the Google Play client using the Google Play's Application Licensing service, which +href="{@docRoot}guide/google/play/licensing/index.html">Application Licensing service, which responds with the name, file size, and URL for each expansion file. With this information, you then download the files and save them to the proper storage location.
    • @@ -242,7 +242,7 @@ application:

      Space is precious and you should keep your total application size as small as possible. If your app uses more than 50MB in order to provide multiple versions of your graphic assets for multiple screen densities, consider instead publishing multiple APKs in which each APK +href="{@docRoot}guide/google/play/publishing/multiple-apks.html">multiple APKs in which each APK contains only the assets required for the screens that it targets.
    • Determine which application resources to separate from your APK and package them in a file to use as the main expansion file. @@ -259,7 +259,7 @@ Library.

    • Add logic to your application's main activity that checks whether the expansion files are on the device upon start-up. If the files are not on the device, use Google Play's Application Licensing service to request URLs +href="{@docRoot}guide/google/play/licensing/index.html">Application Licensing service to request URLs for the expansion files, then download and save them.

      To greatly reduce the amount of code you must write and ensure a good user experience during the download, we recommend you use the Downloader @@ -292,16 +292,16 @@ provide the URLs for your expansion files if the application was installed by ot provides for each file is unique for every download and each one expires shortly after it is given to your application.

    • If you update your application with a new APK or upload multiple APKs for the same +href="{@docRoot}guide/google/play/publishing/multiple-apks.html">multiple APKs for the same application, you can select expansion files that you've uploaded for a previous APK. The expansion file's name does not change—it retains the version received by the APK to which the file was originally associated.
    • If you use expansion files in combination with multiple APKs in order to +href="{@docRoot}guide/google/play/publishing/multiple-apks.html">multiple APKs in order to provide different expansion files for different devices, you still must upload separate APKs for each device in order to provide a unique {@code versionCode} -value and declare different filters for +value and declare different filters for each APK.
    • You cannot issue an update to your application by changing the expansion files alone—you must upload a new APK to update your app. If your changes only @@ -333,7 +333,7 @@ time it installs or updates the APK. This way, the expansion files are available application launches for the first time. However, in some cases your app must download the expansion files itself by requesting them from a URL provided to you in a response from Google Play's Application Licensing service.

      +href="{@docRoot}guide/google/play/licensing/index.html">Application Licensing service.

      The basic logic you need to download your expansion files is the following:

      @@ -346,7 +346,7 @@ href="#StorageLocation">shared storage location (in the
    • If the expansion files are not there:
      1. Perform a request using Google Play's Application Licensing to get your +href="{@docRoot}guide/google/play/licensing/index.html">Application Licensing to get your app's expansion file names, sizes, and URLs.
      2. Use the URLs provided by Google Play to download the expansion files and save the expansion files. You must save the files to the

        If your application is free (not a paid app), then you probably haven't used the Application Licensing service. It's primarily +href="{@docRoot}guide/google/play/licensing/index.html">Application Licensing service. It's primarily designed for you to enforce licensing policies for your application and ensure that the user has the right to use your app (he or she rightfully paid for it on Google Play). In order to facilitate the @@ -409,7 +409,7 @@ download your expansion files. The information in the following sections explain the library into your application.

        If you'd rather develop your own solution to download the expansion files using the Google -Play URLs, you must follow the Application +Play URLs, you must follow the Application Licensing documentation to perform a license request, then retrieve the expansion file names, sizes, and URLs from the response extras. You should use the {@code APKExpansionPolicy} class (included in the License Verification Library) as your licensing @@ -447,7 +447,7 @@ receives updates about the download progress.

      3. download two packages from the SDK Manager and add the appropriate libraries to your application.

        -

        First, open the Android SDK Manager, expand +

        First, open the Android SDK Manager, expand Extras and download:

        • Google Market Licensing package
        • @@ -571,11 +571,11 @@ DownloaderService} class and override three methods to provide specific applicat
          {@code getPublicKey()}
          This must return a string that is the Base64-encoded RSA public key for your publisher account, available from the profile page on the Developer Console (see Setting Up for Licensing).
          +href="{@docRoot}guide/google/play/licensing/setting-up.html">Setting Up for Licensing).
          {@code getSALT()}
          This must return an array of random bytes that the licensing {@code Policy} uses to create an {@code +href="{@docRoot}guide/google/play/licensing/adding-licensing.html#impl-Obfuscator">{@code Obfuscator}. The salt ensures that your obfuscated {@link android.content.SharedPreferences} file in which your licensing data is saved will be unique and non-discoverable.
          {@code getAlarmReceiverClassName()}
          @@ -924,7 +924,7 @@ expansion files:

          For more information about how to use the {@code APKExpansionPolicy} when you're not using the Downloader Library, see the documentation for Adding Licensing to Your App, +href="{@docRoot}guide/google/play/licensing/adding-licensing.html">Adding Licensing to Your App, which explains how to implement a license policy such as this one.

          @@ -1200,7 +1200,7 @@ finalize these details before publishing your application. the application as a draft, such that your application is not published for Google Play users, but the expansion files are available for you to test the download process.

        • Install the application on your test device using the Eclipse tools or {@code adb}.
        • +href="{@docRoot}tools/help/adb.html">{@code adb}.
        • Launch the app.
      diff --git a/docs/html/guide/appendix/market-filters.jd b/docs/html/guide/google/play/filters.jd similarity index 99% rename from docs/html/guide/appendix/market-filters.jd rename to docs/html/guide/google/play/filters.jd index 3e502d7d5f19dc10e72da6b7ccdb3c96787950ec..3db9cb634d06906acdcc64ff3316c466c1ae170e 100644 --- a/docs/html/guide/appendix/market-filters.jd +++ b/docs/html/guide/google/play/filters.jd @@ -400,7 +400,7 @@ country (as determined by SIM carrier) in which paid apps are available.

      Native Platform

      An application that includes native libraries that target a specific platform (ARM EABI v7 or x86, for example) are visible only on devices that support that platform. For details about the NDK and using - native libraries, see What is the + native libraries, see What is the Android NDK?

      Copy-Protected Applications

      To copy protect an application, set copy protection to "On" when you configure publishing @@ -451,4 +451,4 @@ requires that you follow specific rules within your filters and that you pay ext version codes for each APK to ensure proper update paths for each configuration.

      If you need more information about how to publish multiple APKs on Google Play, read Multiple APK Support.

      +href="{@docRoot}guide/google/play/publishing/multiple-apks.html">Multiple APK Support.

      diff --git a/docs/html/guide/google/play/index.jd b/docs/html/guide/google/play/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..b11bcdca8001c2e3b5693a303a7b023d70c264b9 --- /dev/null +++ b/docs/html/guide/google/play/index.jd @@ -0,0 +1,16 @@ +page.title=Google Play APIs +page.landing=1 +page.landing.intro=When you ditribute your Android app using Google Play you have the opportunity to enhance your app's capabilities with services such as in-app billing and control your app distribution with advanced device filtering. +@jd:body + + +
      +
        +
      • Monetize with in-app billing
        Lorem ipsum dolor sit amet, soldum +consectetur adipiscing elit. Learn more »
      • +
      • Control your app distribution
        Lorem ipsum dolor sit amet, soldum consectetur +adipiscing elit. Learn more »
      • +
      • Protect from piracy
        Lorem ipsum dolor sit amet, soldum +consectetur adipiscing elit. Learn more »
      • +
      +
      \ No newline at end of file diff --git a/docs/html/guide/market/licensing/adding-licensing.jd b/docs/html/guide/google/play/licensing/adding-licensing.jd similarity index 97% rename from docs/html/guide/market/licensing/adding-licensing.jd rename to docs/html/guide/google/play/licensing/adding-licensing.jd index d4dd008bcf7c23428f0ae9fa05597ab0e43a2728..49375c206b67cecdc9310ee87724bb85cdf9183b 100644 --- a/docs/html/guide/market/licensing/adding-licensing.jd +++ b/docs/html/guide/google/play/licensing/adding-licensing.jd @@ -72,11 +72,11 @@ most applications).
    • The sections below describe these tasks. When you are done with the integration, you should be able to compile your application successfully and you can begin testing, as described in Setting Up the Test +href="{@docRoot}guide/google/play/licensing/setting-up.html#test-env">Setting Up the Test Environment.

      For an overview of the full set of source files included in the LVL, see Summary of LVL Classes +href="{@docRoot}guide/google/play/licensing/licensing-reference.html#lvl-summary">Summary of LVL Classes and Interfaces.

      @@ -224,7 +224,7 @@ in local persistent storage. cached response is valid, rather than making a request to the licensing server. Setting the response validity according to the server-provided VT extra is highly recommended. See Server Response Extras +href="{@docRoot}guide/google/play/licensing/licensing-reference.html#extras">Server Response Extras for more information.
    • Uses an exponential backoff period, if retrying any requests the result in errors. Note that the Google Play client automatically retries failed @@ -247,7 +247,7 @@ server-provided settings is straightforward and making use of them is highly recommended. See the ServerManagedPolicy implementation for an example of how to extract and use the extras. For a list of server settings and information about how to use them, see Server Response +href="{@docRoot}guide/google/play/licensing/licensing-reference.html#extras">Server Response Extras.

      ServerManagedPolicy

      @@ -261,7 +261,7 @@ settings to the responses, to help the application manage licensing effectively.

      See Server Response Extras +href="{@docRoot}guide/google/play/licensing/licensing-reference.html#extras">Server Response Extras for a list of settings and ServerManagedPolicy.java for information about how a {@code Policy} can use the extras.

      @@ -294,7 +294,7 @@ retry count, among others. ServerManagedPolicy extracts the values from the license response in its processServerResponse() method and checks them in its allowAccess() method. For a list of the server-provided settings used by ServerManagedPolicy, see Server Response +href="{@docRoot}guide/google/play/licensing/licensing-reference.html#extras">Server Response Extras.

      For convenience, best performance, and the benefit of using license settings @@ -650,8 +650,7 @@ new license check if the reason supplied is {@code Policy.RETRY}. < deep-links the user to the application's details page on Google Play, from which the use can purchase the application. For more information on how to set up such links, see Linking to your apps -on Google Play.

    • +href="{@docRoot}distribute/googleplay/promote/linking.html">Linking to Your Products.
    • Display a Toast notification that indicates that the features of the application are limited because it is not licensed.
    @@ -698,9 +697,9 @@ private class MyLicenseCheckerCallback implements LicenseCheckerCallback {

    Additionally, you should implement the applicationError() method, which the LVL calls to let your application handle errors that are not retryable. For a list of such errors, see Server +href="{@docRoot}guide/google/play/licensing/licensing-reference.html#server-response-codes">Server Response Codes in the Licensing Reference. You can implement +href="guide/google/play/licensing/licensing-reference.html">Licensing Reference. You can implement the method in any way needed. In most cases, the method should log the error code and call dontAllow().

    @@ -999,9 +998,9 @@ Play Licensing.

    When you are finished testing your license implementation, you are ready to publish the application on Google Play. Follow the normal steps to prepare, sign, and then publish the application. +href="{@docRoot}tools/publishing/preparing.html">prepare, sign, and then publish the application.

    Removing Copy Protection

    diff --git a/docs/html/guide/market/licensing/index.jd b/docs/html/guide/google/play/licensing/index.jd similarity index 86% rename from docs/html/guide/market/licensing/index.jd rename to docs/html/guide/google/play/licensing/index.jd index 1f15303e4e8e8ae19b5cbc48d321affde697a421..d393738bac1786cc4867d534cd09df7f03df3c8c 100644 --- a/docs/html/guide/market/licensing/index.jd +++ b/docs/html/guide/google/play/licensing/index.jd @@ -31,25 +31,25 @@ on Google Play. However, any application (including free apps) may use the licen to initiate the download of an APK expansion file. In which case, the request that your application sends to the licensing service is not to check whether the user paid for the app, but to request the URL of the expansion files. For information about downloading expansion files for your application, -read the guide to APK Expansion Files.

    +read the guide to APK Expansion Files.

    To learn more about Google Play's application licensing service and start integrating it into your applications, read the following documents:

    -
    Licensing +
    Licensing Overview
    Describes how the service works and what a typical licensing implementation looks like.
    -
    Setting Up for +
    Setting Up for Licensing
    Explains how to set up your Google Play account, development environment, and testing environment in order to add licensing to your app.
    -
    Adding +
    Adding Licensing to Your App
    Provides a step-by-step guide to add licensing verification to your application.
    -
    Licensing +
    Licensing Reference
    Provides detailed information about the licensing library's classes and the service response codes.
    diff --git a/docs/html/guide/market/licensing/licensing-reference.jd b/docs/html/guide/google/play/licensing/licensing-reference.jd similarity index 98% rename from docs/html/guide/market/licensing/licensing-reference.jd rename to docs/html/guide/google/play/licensing/licensing-reference.jd index 0a7e03331b8e872ba2be2511960567b71711de38..d3d522460ee30c162f3b6b106e10c7e356853d1f 100644 --- a/docs/html/guide/market/licensing/licensing-reference.jd +++ b/docs/html/guide/google/play/licensing/licensing-reference.jd @@ -230,7 +230,7 @@ implementation.

    Note: As documented in +href="{@docRoot}guide/google/play/licensing/setting-up.html#test-env"> Setting Up The Testing Environment, the response code can be manually overridden for the application developer and any registered test users via the Google Play publisher site. @@ -251,13 +251,13 @@ testing purposes.

    period and provide other information, The licensing server includes several pieces of information in the license responses. Specifically, the service provides recommended values for the application's license validity period, retry grace period, maximum allowable retry count, and other -settings. If your application uses APK +settings. If your application uses APK expansion files, the response also includes the file names, sizes, and URLs. The server appends the settings as key-value pairs in the license response "extras" field.

    Any {@code Policy} implementation can extract the extras settings from the license response and use them as needed. The LVL default {@code Policy} implementation, {@code +href="{@docRoot}guide/google/play/licensing/adding-licensing.html#ServerManagedPolicy">{@code ServerManagedPolicy}, serves as a working implementation and an illustration of how to obtain, store, and use the settings.

    diff --git a/docs/html/guide/market/licensing/overview.jd b/docs/html/guide/google/play/licensing/overview.jd similarity index 98% rename from docs/html/guide/market/licensing/overview.jd rename to docs/html/guide/google/play/licensing/overview.jd index e7e23f877dad7de228fa6ed4cd46d081a8871f6b..467a3a2c151cbc448bb136046fdea370b2861f83 100644 --- a/docs/html/guide/market/licensing/overview.jd +++ b/docs/html/guide/google/play/licensing/overview.jd @@ -206,7 +206,7 @@ secure.
  • functions when run on a device that does not offer Google Play.
  • You can implement licensing controls for a free app, but only if you're using the service to provide APK expansion files.
  • +href="{@docRoot}guide/google/play/expansion-files.html">APK expansion files. @@ -237,7 +237,7 @@ across all compatible devices, locked or unlocked, that run Android 1.5 or higher version of the platform.

    To begin adding application licensing to your application, continue to Setting Up for Licensing.

    +href="{@docRoot}guide/google/play/licensing/setting-up.html">Setting Up for Licensing.

    diff --git a/docs/html/guide/market/licensing/setting-up.jd b/docs/html/guide/google/play/licensing/setting-up.jd similarity index 95% rename from docs/html/guide/market/licensing/setting-up.jd rename to docs/html/guide/google/play/licensing/setting-up.jd index 0de7819b0108e759a2e9974b10f67f5280f2b8a4..80a44192c754b5b81e6874dc17af127d51734d6f 100644 --- a/docs/html/guide/market/licensing/setting-up.jd +++ b/docs/html/guide/google/play/licensing/setting-up.jd @@ -46,7 +46,7 @@ href="http://play.google.com/apps/publish">http://play.google.com/apps/publish

    For more information, see Publishing on Google Play.

    +href="{@docRoot}distribute/googleplay/publish/register.html">Get Started with Publishing.

    If you already have a publisher account on Google Play, use your existing account to set up licensing.

    @@ -102,7 +102,7 @@ responses, see Setting Up a Testing Environment, below.

    The sections below describe these tasks. When you are done with setup, -you can begin Adding +you can begin Adding Licensing to Your App.

    To get started, you need to set up a proper runtime environment on which @@ -146,7 +146,7 @@ be able to communicate with the Google Play licensing server.

    For general information about how to set up a device for use in developing Android applications, see Using Hardware Devices.

    +href="{@docRoot}tools/device.html">Using Hardware Devices.

    Running on an Android emulator

    @@ -199,7 +199,7 @@ Android Virtual Devices.

    If you are not familiar with AVDs or how to use them, see Managing Virtual Devices.

    +href="{@docRoot}tools/devices/index.html">Managing Virtual Devices.

    Updating your project configuration

    @@ -266,7 +266,7 @@ the LVL library project and the example application into these directories:

    application)

    If you aren't familiar with how to download packess into your SDK, see the -Adding SDK Packages +Exploring the SDK document.

    @@ -306,7 +306,7 @@ version of the LVL.

    share its code and resources across multiple applications.

    If you aren't familiar with library projects or how -to use them, see +to use them, see Managing Projects.

    @@ -345,7 +345,7 @@ no further configuration is needed.

    For more information about how to create an application project or work with library projects in Eclipse, see Managing Projects from +href="{@docRoot}tools/projects/projects-eclipse.html">Managing Projects from Eclipse with ADT.

    @@ -358,7 +358,7 @@ LVL's library/src/com directory into your application's

    If you add the LVL sources directly to your application, you can skip the next section and start working with the library, as described in Adding +href="{@docRoot}guide/google/play/licensing/adding-licensing.html">Adding Licensing to Your App.

    @@ -379,7 +379,7 @@ haven't done that already, do it now before continuing.

    Select the "Android" properties group and click Add, then choose the LVL library project (com_android_vending_licensing) and click OK. For more information, see - + Managing Projects from Eclipse with ADT

    . @@ -407,7 +407,7 @@ properties, including the reference to the library project:

    For more information about working with library projects, -see +see Setting up a Library Project.

    @@ -483,9 +483,9 @@ test in your application.

    In general, you should make sure to test your application's licensing implementation with every response code available in the Test Response menu. For a description of the codes, see Server +href="{@docRoot}guide/google/play/licensing/licensing-reference.html#server-response-codes">Server Response Codes in the Licensing Reference.

    +href="{@docRoot}guide/google/play/licensing/licensing-reference.html">Licensing Reference.

    Figure 4. The Licensing @@ -506,7 +506,7 @@ sign using either your publisher account or one of the test accounts that you have set up. For more information about test accounts, see the next section.

    See Server +href="{@docRoot}guide/google/play/licensing/licensing-reference.html#server-response-codes">Server Response Codes for a list of test responses available and their meanings.

    @@ -695,7 +695,7 @@ publisher account or test account each time you wipe data when restarting the emulator.

    Once you've completed the setup procedures, continue to Adding Licensing to Your App.

    +href="{@docRoot}guide/google/play/licensing/adding-licensing.html">Adding Licensing to Your App.

    diff --git a/docs/html/guide/market/publishing/multiple-apks.jd b/docs/html/guide/google/play/publishing/multiple-apks.jd similarity index 96% rename from docs/html/guide/market/publishing/multiple-apks.jd rename to docs/html/guide/google/play/publishing/multiple-apks.jd index e7cfa33dac9553d85d1b85e48711af041c4f2ff9..e41817e4520daf2d9d116d10892c8025c2f2a7b8 100644 --- a/docs/html/guide/market/publishing/multiple-apks.jd +++ b/docs/html/guide/google/play/publishing/multiple-apks.jd @@ -45,11 +45,11 @@ support all desired devices with a single APK

    See also

      -
    1. Filters on Google Play
    2. +
    3. Filters on Google Play
    4. Supporting Multiple Screens
    5. -
    6. Compatibility +
    7. Compatibility Package
    8. -
    9. Android API Levels
    10. +
    11. Android API Levels
    @@ -192,7 +192,7 @@ following sections describe more about how it works.

    Supported filters

    Which devices receive each APK is determined by Google Play filters that are specified by +href="{@docRoot}guide/google/play/filters.html">Google Play filters that are specified by elements in the manifest file of each APK. However, Google Play allows you to publish multiple APKs only when each APK uses filters to support a variation of the following device characteristics:

    @@ -286,7 +286,7 @@ higher, as per the previous note).

    Other manifest elements that enable Google Play filters—but are not +href="{@docRoot}guide/google/play/filters.html">Google Play filters—but are not listed above—are still applied for each APK as usual. However, Google Play does not allow you to publish multiple APKs based on variations of them. Thus, you cannot publish multiple APKs if the above listed filters are the same for each APK (but the APKs differ based on @@ -402,7 +402,7 @@ as textures—based on the build configuration.)

    Tip: One way to avoid duplicating large portions of your application code is to use a library project. A library +href="{@docRoot}tools/projects/index.html#LibraryProjects">library project. A library project holds shared code and resources, which you can include in your actual application projects.

    @@ -523,7 +523,7 @@ APK—by using only one APK, you can simply increase the version code with e be done.

  • You need to manage only a single code base.

    Although you can use a library project +href="{@docRoot}tools/projects/index.html#LibraryProjects">library project to share code between multiple Android projects, it's still likely that you'll reproduce some code across each project and this could become difficult to manage, especially when resolving bugs.

  • @@ -600,8 +600,8 @@ different screen sizes.

    href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens.

    Additionally, you should consider using a support library from the Compatibility Package so that you can add Fragments to your activity designs +href="{@docRoot}tools/extras/support-library.html">Compatibility Package so that you can add Fragments to your activity designs when running on larger screens such as tablets.

    @@ -612,14 +612,14 @@ when running on larger screens such as tablets.

    only APIs available in the lowest reasonable version. For example, your application may not require APIs newer than Android 2.1 (API Level 7), which makes an application available to over 95% of Android-powered devices (as indicated by the Platform Versions dashboard).

    +href="{@docRoot}about/dashboards/index.html">Platform Versions dashboard).

    By using a support library from the Compatibility Package, you can also use APIs +href="{@docRoot}tools/extras/support-library.html">Compatibility Package, you can also use APIs from some of the latest versions (such as Android 3.0) while still supporting versions as low as Android 1.6. The support library includes APIs for Fragments, Loaders, and more. Using the fragment +href="{@docRoot}guide/components/fragments.html">Fragments, Loaders, and more. Using the fragment APIs is particularly valuable so that you can optimize your user interface for large devices such as tablets.

    diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 62d18aee3f9a8f26d83df31e18cb2eb869f5ae70..44b977e327dd0dd3ded83090e6b38d4d5649979d 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -5,236 +5,80 @@ Below are template spans for adding localized doc titles. Please ensure that localized titles are added in the language order specified below. ?> - - - -
  • - - Publishing - - - - - - - - +
  • + + - -
  • - +
  • + + + + + + + + + + + + + diff --git a/docs/html/guide/index.jd b/docs/html/guide/index.jd index 8378472ec62faecfe55a523b023f0d211375a703..fea7027d36844a05d0d483e4b8e3bf458e8aa049 100644 --- a/docs/html/guide/index.jd +++ b/docs/html/guide/index.jd @@ -1,88 +1,56 @@ -page.title=The Developer's Guide -@jd:body - -

    -Welcome to the Android Dev Guide! The Dev Guide provides -a practical introduction to developing applications for Android and documentation about major -platform features. It explores the concepts behind Android, the framework for -constructing an application, and the tools for developing, -testing, and publishing software for the platform. -

    - -

    -The Dev Guide holds most of the documentation for the Android -platform, except for reference material on the framework API. -For API specifications, go to the -Reference. -

    - -

    -As you can see in the panel on the left, the Dev Guide is -divided into several sections: -

    - -

    -
    Android Basics
    -
    An initial orientation to Android — what it is, -what it offers, and how your application fits in.
    - -
    Framework Topics
    -
    Discussions of particular parts of the Android framework -and API. For an introduction to the framework, begin with -Application -Fundamentals. Then explore other topics — from -designing a user interface and setting up resources to storing -data and using permissions — as needed.
    - -
    Google Play Topics
    -
    Documentation for topics that concern publishing and monetizing applications on Google Play, -such as how to enforce licensing policies and implement in-app billing.
    - -
    Developing
    -
    Directions for using Android's development and debugging tools, -and for testing the results.
    +page.title=App Components +page.landing=true +page.landing.intro=Android's application framework lets you create extremely rich and innovative apps using a set of reusable components. This section explains how Android apps work and how you use components to build them. +page.landing.image=images/ui/ui_index.png -
    Publishing
    -
    Instructions on how to prepare your application for deployment -and how to publish it when it's ready.
    - -
    Best Practices
    -
    Recommendations on preferred techniques for writing -applications that perform efficiently and work well for the -user.
    - -
    Web Applications
    -
    Documentation about how to create web applications that work seamlessly on Android-powered -devices and create Android applications that embed web-based content.
    - -
    Appendix
    -
    Reference information and specifications, as well as FAQs, -a glossary of terms, and other information.
    -
    - -

    -The first step in programming for Android is downloading the SDK -(software development kit). For instructions and information, visit the SDK tab. -

    - -

    -After you have the SDK, begin by looking through the Dev Guide. -If you want to start by getting a quick look at some code, the -Hello World -tutorial walks you through a standard "Hello, World" application to introduce some basics of an -Android application. The -Application -Fundamentals document is a good place to start learning the basics about the application -framework. -

    - - -

    -For additional help, consider joining one or more of the Android -discussion groups. Go to the -Developer Forums page -for more information. -

    +@jd:body -

    To return to this page later, just click the "Dev Guide" tab while any Dev Guide page is loaded.

    \ No newline at end of file +
    + + + + + +
    \ No newline at end of file diff --git a/docs/html/guide/market/billing/billing_about.html b/docs/html/guide/market/billing/billing_about.html deleted file mode 100644 index d8395df3bb670f85b1209519f49d56a86644ff12..0000000000000000000000000000000000000000 --- a/docs/html/guide/market/billing/billing_about.html +++ /dev/null @@ -1,12 +0,0 @@ - - - -Redirecting... - - -

    You should be redirected. Please click -here.

    - - \ No newline at end of file diff --git a/docs/html/guide/market/billing/index.jd b/docs/html/guide/market/billing/index.jd deleted file mode 100755 index 036761f4e099881fff1e2a25cd7003a5433885a7..0000000000000000000000000000000000000000 --- a/docs/html/guide/market/billing/index.jd +++ /dev/null @@ -1,94 +0,0 @@ -page.title=In-app Billing -@jd:body - - - -

    Google Play In-app Billing is a Google Play service that lets you sell digital content in -your applications. You can use the service to sell a wide range of content, including downloadable -content such as media files or photos, and virtual content such as game levels or potions.

    - -

    When you use Google Play's in-app billing service to sell an item, Google Play handles all -checkout details so your application never has to directly process any financial transactions. -Google Play uses the same checkout service that is used for application purchases, so your users -experience a consistent and familiar purchase flow (see figure 1). Also, the transaction fee for -in-app purchases is the same as the transaction fee for application purchases (30%).

    - -

    Any application that you publish through Google Play can implement in-app billing. No special -account or registration is required other than a Google Play app publisher account and a Google -Checkout Merchant account. Also, because the service uses no dedicated framework APIs, you can add -in-app billing to any application that uses a minimum API level of 4 or higher.

    - -

    To help you integrate in-app billing into your application, the Android SDK provides a sample -application that demonstrates a simple implementation of in-app billing. The sample application -contains examples of billing-related classes you can use to implement in-app billing in your -application. It also contains examples of the database, user interface, and business logic you might -use to implement in-app billing.

    - -

    Important: Although the sample application is a working example -of how you can implement in-app billing, we strongly recommend that you modify and -obfuscate the sample code before you use it in a production application. For more information, see -Security and Design.

    - - -

    - Figure 1. Applications initiate in-app billing requests through their own UI - (first screen). Google Play responds to the request by providing the checkout user interface - (middle screen). When checkout is complete, the application resumes. -

    - -

    To learn more about Google Play's in-app billing service and start integrating it into your -applications, read the following documents:

    - -
    -
    Overview of In-app - Billing
    -
    Learn how the service works and what a typical in-app billing implementation looks - like.
    -
    Implementing - In-app Billing
    -
    Use this step-by-step guide to start incorporating in-app billing into your - application.
    -
    Security - and Design
    -
    Review these best practices to help ensure that your in-app billing implementation is - secure and well designed.
    -
    Testing In-app - Billing
    -
    Understand how the in-app billing test tools work and learn how to test your in-app billing - implementation.
    -
    Administering - In-app Billing
    -
    Learn how to set up your product list, register test accounts, and handle refunds.
    -
    In-app Billing - Reference
    -
    Get detailed information about Google Play response codes and the in-app billing - interface.
    -
    - diff --git a/docs/html/guide/practices/design/accessibility.html b/docs/html/guide/practices/app-design/accessibility.html similarity index 100% rename from docs/html/guide/practices/design/accessibility.html rename to docs/html/guide/practices/app-design/accessibility.html diff --git a/docs/html/guide/practices/design/index.jd b/docs/html/guide/practices/app-design/index.jd similarity index 100% rename from docs/html/guide/practices/design/index.jd rename to docs/html/guide/practices/app-design/index.jd diff --git a/docs/html/guide/practices/design/jni.jd b/docs/html/guide/practices/app-design/jni.jd similarity index 100% rename from docs/html/guide/practices/design/jni.jd rename to docs/html/guide/practices/app-design/jni.jd diff --git a/docs/html/guide/practices/design/performance.jd b/docs/html/guide/practices/app-design/performance.jd similarity index 99% rename from docs/html/guide/practices/design/performance.jd rename to docs/html/guide/practices/app-design/performance.jd index dd9b55407edd98e7c692a151169b7bb4dabd5dc2..078999becc393c3c23614685b4f1c2d836ebcfdf 100644 --- a/docs/html/guide/practices/design/performance.jd +++ b/docs/html/guide/practices/app-design/performance.jd @@ -379,7 +379,7 @@ code compiled for the ARM in the Nexus One won't run on the ARM in the G1.

    that you want to port to Android, not for "speeding up" parts of a Java app.

    If you do need to use native code, you should read our -JNI Tips.

    +JNI Tips.

    (See also Effective Java item 54.)

    @@ -402,7 +402,7 @@ managed to optimize all your code away). We highly recommend you use Caliper to run your own microbenchmarks.

    You may also find -Traceview useful +Traceview useful for profiling, but it's important to realize that it currently disables the JIT, which may cause it to misattribute time to code that the JIT may be able to win back. It's especially important after making changes suggested by Traceview diff --git a/docs/html/guide/practices/design/responsiveness.jd b/docs/html/guide/practices/app-design/responsiveness.jd similarity index 100% rename from docs/html/guide/practices/design/responsiveness.jd rename to docs/html/guide/practices/app-design/responsiveness.jd diff --git a/docs/html/guide/practices/design/seamlessness.jd b/docs/html/guide/practices/app-design/seamlessness.jd similarity index 99% rename from docs/html/guide/practices/design/seamlessness.jd rename to docs/html/guide/practices/app-design/seamlessness.jd index 6c734264c1a952905bd1f56cdd5bae552077c060..ec6b7fdff73c9326a33616925930f107fa100561 100644 --- a/docs/html/guide/practices/design/seamlessness.jd +++ b/docs/html/guide/practices/app-design/seamlessness.jd @@ -210,7 +210,7 @@ network connection. That's almost guaranteed to be much faster than a cell network, so you'll want to change the settings on the emulator that simulate slower network speeds. You can do this in Eclipse, in the "Emulator Settings" tab of your launch configuration or via a command-line +href="{@docRoot}tools/help/emulator.html#netspeed">command-line option when starting the emulator.

    Don't Assume Touchscreen or Keyboard

    diff --git a/docs/html/guide/practices/compatibility.jd b/docs/html/guide/practices/compatibility.jd index 5e514c4444c197a4a5917e9ffc909d361042cb02..a2284bd0313347ab366e95aa8c2c3423167dfbbe 100644 --- a/docs/html/guide/practices/compatibility.jd +++ b/docs/html/guide/practices/compatibility.jd @@ -7,7 +7,7 @@ page.title=Android Compatibility

    See also

    1. Filtering on Google Play
    2. +href="{@docRoot}guide/google/play/filters.html">Filtering on Google Play
    3. Providing Alternative Resources
    4. .apk file.

      There is exactly one Android API for each API level, and it’s the same +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API level, and it’s the same API no matter what kind of device it’s installed on. No parts of the API are optional, and you never have to worry about parts of the API missing on some devices. Every compatible Android device your app will land on will include @@ -119,7 +119,7 @@ device.

      For information about other filters that you can use to control the availability of your apps, see the -Filters on Google Play +Filters on Google Play document.

      diff --git a/docs/html/guide/practices/index.html b/docs/html/guide/practices/index.html deleted file mode 100644 index 4881acf44581bd625a78990ae7e9b844b2a604c3..0000000000000000000000000000000000000000 --- a/docs/html/guide/practices/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -click here if you are not redirected. - - \ No newline at end of file diff --git a/docs/html/guide/practices/index.jd b/docs/html/guide/practices/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..e218b505159a0f450ea7f62a61f43f5d547111a2 --- /dev/null +++ b/docs/html/guide/practices/index.jd @@ -0,0 +1,52 @@ +page.title=Best Practices +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.image= + +@jd:body + +
      + +
      +

      Blog Articles

      + + +

      Improving App Quality

      +

      One way of improving your app’s visibility in the ecosystem is by deploying well-targeted +mobile advertising campaigns and cross-app promotions. However, there’s another time-tested method +of fueling the impression-install-ranking cycle: improve the product!

      +
      + + +

      Say Goodbye to the Menu Button

      +

      As Ice Cream Sandwich rolls out to more devices, it?s important that you begin to migrate +your designs to the action bar in order to promote a consistent Android user experience.

      +
      + + +

      New Tools For Managing Screen Sizes

      +

      Android 3.2 includes new tools for supporting devices with a wide range of screen sizes. +One important result is better support for a new size of screen; what is typically called a “7-inch” +tablet. This release also offers several new APIs to simplify developers’ work in adjusting to +different screen sizes.

      +
      + + +

      Identifying App Installations

      +

      It is very common, and perfectly reasonable, for a developer to want to track individual +installations of their apps. It sounds plausible just to call TelephonyManager.getDeviceId() and use +that value to identify the installation. There are problems with this

      +
      + + +

      Making Android Games that Play Nice

      +

      Making a game on Android is easy. Making a great game for a mobile, multitasking, +often multi-core, multi-purpose system like Android is trickier. Even the best developers frequently +make mistakes in the way they interact with the Android system and with other applications

      +
      + +
      + + +
      \ No newline at end of file diff --git a/docs/html/guide/practices/jni.jd b/docs/html/guide/practices/jni.jd new file mode 100644 index 0000000000000000000000000000000000000000..ddfa0e3991f52be25274666fe0dba7e4d0ff42b6 --- /dev/null +++ b/docs/html/guide/practices/jni.jd @@ -0,0 +1,719 @@ +page.title=JNI Tips +@jd:body + + + +

      JNI is the Java Native Interface. It defines a way for managed code +(written in the Java programming language) to interact with native +code (written in C/C++). It's vendor-neutral, has support for loading code from +dynamic shared libraries, and while cumbersome at times is reasonably efficient.

      + +

      You really should read through the +JNI spec for J2SE 6 +to get a sense for how JNI works and what features are available. Some +aspects of the interface aren't immediately obvious on +first reading, so you may find the next few sections handy. +There's a more detailed JNI Programmer's Guide and Specification.

      + + + +

      JavaVM and JNIEnv

      + +

      JNI defines two key data structures, "JavaVM" and "JNIEnv". Both of these are essentially +pointers to pointers to function tables. (In the C++ version, they're classes with a +pointer to a function table and a member function for each JNI function that indirects through +the table.) The JavaVM provides the "invocation interface" functions, +which allow you to create and destroy a JavaVM. In theory you can have multiple JavaVMs per process, +but Android only allows one.

      + +

      The JNIEnv provides most of the JNI functions. Your native functions all receive a JNIEnv as +the first argument.

      + +

      The JNIEnv is used for thread-local storage. For this reason, you cannot share a JNIEnv between threads. +If a piece of code has no other way to get its JNIEnv, you should share +the JavaVM, and use GetEnv to discover the thread's JNIEnv. (Assuming it has one; see AttachCurrentThread below.)

      + +

      The C declarations of JNIEnv and JavaVM are different from the C++ +declarations. The "jni.h" include file provides different typedefs +depending on whether it's included into C or C++. For this reason it's a bad idea to +include JNIEnv arguments in header files included by both languages. (Put another way: if your +header file requires #ifdef __cplusplus, you may have to do some extra work if anything in +that header refers to JNIEnv.)

      + + +

      Threads

      + +

      All threads are Linux threads, scheduled by the kernel. They're usually +started from managed code (using Thread.start), +but they can also be created elsewhere and then attached to the JavaVM. For +example, a thread started with pthread_create can be attached +with the JNI AttachCurrentThread or +AttachCurrentThreadAsDaemon functions. Until a thread is +attached, it has no JNIEnv, and cannot make JNI calls.

      + +

      Attaching a natively-created thread causes a java.lang.Thread +object to be constructed and added to the "main" ThreadGroup, +making it visible to the debugger. Calling AttachCurrentThread +on an already-attached thread is a no-op.

      + +

      Android does not suspend threads executing native code. If +garbage collection is in progress, or the debugger has issued a suspend +request, Android will pause the thread the next time it makes a JNI call.

      + +

      Threads attached through JNI must call +DetachCurrentThread before they exit. +If coding this directly is awkward, in Android 2.0 (Eclair) and higher you +can use pthread_key_create to define a destructor +function that will be called before the thread exits, and +call DetachCurrentThread from there. (Use that +key with pthread_setspecific to store the JNIEnv in +thread-local-storage; that way it'll be passed into your destructor as +the argument.)

      + + + +

      jclass, jmethodID, and jfieldID

      + +

      If you want to access an object's field from native code, you would do the following:

      + +
        +
      • Get the class object reference for the class with FindClass
      • +
      • Get the field ID for the field with GetFieldID
      • +
      • Get the contents of the field with something appropriate, such as +GetIntField
      • +
      + +

      Similarly, to call a method, you'd first get a class object reference and then a method ID. The IDs are often just +pointers to internal runtime data structures. Looking them up may require several string +comparisons, but once you have them the actual call to get the field or invoke the method +is very quick.

      + +

      If performance is important, it's useful to look the values up once and cache the results +in your native code. Because there is a limit of one JavaVM per process, it's reasonable +to store this data in a static local structure.

      + +

      The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded. Classes +are only unloaded if all classes associated with a ClassLoader can be garbage collected, +which is rare but will not be impossible in Android. Note however that +the jclass +is a class reference and must be protected with a call +to NewGlobalRef (see the next section).

      + +

      If you would like to cache the IDs when a class is loaded, and automatically re-cache them +if the class is ever unloaded and reloaded, the correct way to initialize +the IDs is to add a piece of code that looks like this to the appropriate class:

      + +
          /*
      +     * We use a class initializer to allow the native code to cache some
      +     * field offsets. This native function looks up and caches interesting
      +     * class/field/method IDs. Throws on failure.
      +     */
      +    private static native void nativeInit();
      +
      +    static {
      +        nativeInit();
      +    }
      + +

      Create a nativeClassInit method in your C/C++ code that performs the ID lookups. The code +will be executed once, when the class is initialized. If the class is ever unloaded and +then reloaded, it will be executed again.

      + + +

      Local and Global References

      + +

      Every argument passed to a native method, and almost every object returned +by a JNI function is a "local reference". This means that it's valid for the +duration of the current native method in the current thread. +Even if the object itself continues to live on after the native method +returns, the reference is not valid. +

      This applies to all sub-classes of jobject, including +jclass, jstring, and jarray. +(The runtime will warn you about most reference mis-uses when extended JNI +checks are enabled.)

      +

      The only way to get non-local references is via the functions +NewGlobalRef and NewWeakGlobalRef. + +

      If you want to hold on to a reference for a longer period, you must use +a "global" reference. The NewGlobalRef function takes the +local reference as an argument and returns a global one. +The global reference is guaranteed to be valid until you call +DeleteGlobalRef.

      + +

      This pattern is commonly used when caching a jclass returned +from FindClass, e.g.:

      +
      jclass localClass = env->FindClass("MyClass");
      +jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
      + +

      All JNI methods accept both local and global references as arguments. +It's possible for references to the same object to have different values. +For example, the return values from consecutive calls to +NewGlobalRef on the same object may be different. +To see if two references refer to the same object, +you must use the IsSameObject function. Never compare +references with == in native code.

      + +

      One consequence of this is that you +must not assume object references are constant or unique +in native code. The 32-bit value representing an object may be different +from one invocation of a method to the next, and it's possible that two +different objects could have the same 32-bit value on consecutive calls. Do +not use jobject values as keys.

      + +

      Programmers are required to "not excessively allocate" local references. In practical terms this means +that if you're creating large numbers of local references, perhaps while running through an array of +objects, you should free them manually with +DeleteLocalRef instead of letting JNI do it for you. The +implementation is only required to reserve slots for +16 local references, so if you need more than that you should either delete as you go or use +EnsureLocalCapacity/PushLocalFrame to reserve more.

      + +

      Note that jfieldIDs and jmethodIDs are opaque +types, not object references, and should not be passed to +NewGlobalRef. The raw data +pointers returned by functions like GetStringUTFChars +and GetByteArrayElements are also not objects. (They may be passed +between threads, and are valid until the matching Release call.)

      + +

      One unusual case deserves separate mention. If you attach a native +thread with AttachCurrentThread, the code you are running will +never automatically free local references until the thread detaches. Any local +references you create will have to be deleted manually. In general, any native +code that creates local references in a loop probably needs to do some manual +deletion.

      + + +

      UTF-8 and UTF-16 Strings

      + +

      The Java programming language uses UTF-16. For convenience, JNI provides methods that work with Modified UTF-8 as well. The +modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00. +The nice thing about this is that you can count on having C-style zero-terminated strings, +suitable for use with standard libc string functions. The down side is that you cannot pass +arbitrary UTF-8 data to JNI and expect it to work correctly.

      + +

      If possible, it's usually faster to operate with UTF-16 strings. Android +currently does not require a copy in GetStringChars, whereas +GetStringUTFChars requires an allocation and a conversion to +UTF-8. Note that +UTF-16 strings are not zero-terminated, and \u0000 is allowed, +so you need to hang on to the string length as well as +the jchar pointer.

      + +

      Don't forget to Release the strings you Get. The +string functions return jchar* or jbyte*, which +are C-style pointers to primitive data rather than local references. They +are guaranteed valid until Release is called, which means they are not +released when the native method returns.

      + +

      Data passed to NewStringUTF must be in Modified UTF-8 format. A +common mistake is reading character data from a file or network stream +and handing it to NewStringUTF without filtering it. +Unless you know the data is 7-bit ASCII, you need to strip out high-ASCII +characters or convert them to proper Modified UTF-8 form. If you don't, +the UTF-16 conversion will likely not be what you expect. The extended +JNI checks will scan strings and warn you about invalid data, but they +won't catch everything.

      + + +

      Primitive Arrays

      + +

      JNI provides functions for accessing the contents of array objects. +While arrays of objects must be accessed one entry at a time, arrays of +primitives can be read and written directly as if they were declared in C.

      + +

      To make the interface as efficient as possible without constraining +the VM implementation, the Get<PrimitiveType>ArrayElements +family of calls allows the runtime to either return a pointer to the actual elements, or +allocate some memory and make a copy. Either way, the raw pointer returned +is guaranteed to be valid until the corresponding Release call +is issued (which implies that, if the data wasn't copied, the array object +will be pinned down and can't be relocated as part of compacting the heap). +You must Release every array you Get. Also, if the Get +call fails, you must ensure that your code doesn't try to Release a NULL +pointer later.

      + +

      You can determine whether or not the data was copied by passing in a +non-NULL pointer for the isCopy argument. This is rarely +useful.

      + +

      The Release call takes a mode argument that can +have one of three values. The actions performed by the runtime depend upon +whether it returned a pointer to the actual data or a copy of it:

      + +
        +
      • 0 +
          +
        • Actual: the array object is un-pinned. +
        • Copy: data is copied back. The buffer with the copy is freed. +
        +
      • JNI_COMMIT +
          +
        • Actual: does nothing. +
        • Copy: data is copied back. The buffer with the copy + is not freed. +
        +
      • JNI_ABORT +
          +
        • Actual: the array object is un-pinned. Earlier + writes are not aborted. +
        • Copy: the buffer with the copy is freed; any changes to it are lost. +
        +
      + +

      One reason for checking the isCopy flag is to know if +you need to call Release with JNI_COMMIT +after making changes to an array — if you're alternating between making +changes and executing code that uses the contents of the array, you may be +able to +skip the no-op commit. Another possible reason for checking the flag is for +efficient handling of JNI_ABORT. For example, you might want +to get an array, modify it in place, pass pieces to other functions, and +then discard the changes. If you know that JNI is making a new copy for +you, there's no need to create another "editable" copy. If JNI is passing +you the original, then you do need to make your own copy.

      + +

      It is a common mistake (repeated in example code) to assume that you can skip the Release call if +*isCopy is false. This is not the case. If no copy buffer was +allocated, then the original memory must be pinned down and can't be moved by +the garbage collector.

      + +

      Also note that the JNI_COMMIT flag does not release the array, +and you will need to call Release again with a different flag +eventually.

      + + + +

      Region Calls

      + +

      There is an alternative to calls like Get<Type>ArrayElements +and GetStringChars that may be very helpful when all you want +to do is copy data in or out. Consider the following:

      + +
          jbyte* data = env->GetByteArrayElements(array, NULL);
      +    if (data != NULL) {
      +        memcpy(buffer, data, len);
      +        env->ReleaseByteArrayElements(array, data, JNI_ABORT);
      +    }
      + +

      This grabs the array, copies the first len byte +elements out of it, and then releases the array. Depending upon the +implementation, the Get call will either pin or copy the array +contents. +The code copies the data (for perhaps a second time), then calls Release; in this case +JNI_ABORT ensures there's no chance of a third copy.

      + +

      One can accomplish the same thing more simply:

      +
          env->GetByteArrayRegion(array, 0, len, buffer);
      + +

      This has several advantages:

      +
        +
      • Requires one JNI call instead of 2, reducing overhead. +
      • Doesn't require pinning or extra data copies. +
      • Reduces the risk of programmer error — no risk of forgetting + to call Release after something fails. +
      + +

      Similarly, you can use the Set<Type>ArrayRegion call +to copy data into an array, and GetStringRegion or +GetStringUTFRegion to copy characters out of a +String. + + + +

      Exceptions

      + +

      You must not call most JNI functions while an exception is pending. +Your code is expected to notice the exception (via the function's return value, +ExceptionCheck, or ExceptionOccurred) and return, +or clear the exception and handle it.

      + +

      The only JNI functions that you are allowed to call while an exception is +pending are:

      +
        +
      • DeleteGlobalRef +
      • DeleteLocalRef +
      • DeleteWeakGlobalRef +
      • ExceptionCheck +
      • ExceptionClear +
      • ExceptionDescribe +
      • ExceptionOccurred +
      • MonitorExit +
      • PopLocalFrame +
      • PushLocalFrame +
      • Release<PrimitiveType>ArrayElements +
      • ReleasePrimitiveArrayCritical +
      • ReleaseStringChars +
      • ReleaseStringCritical +
      • ReleaseStringUTFChars +
      + +

      Many JNI calls can throw an exception, but often provide a simpler way +of checking for failure. For example, if NewString returns +a non-NULL value, you don't need to check for an exception. However, if +you call a method (using a function like CallObjectMethod), +you must always check for an exception, because the return value is not +going to be valid if an exception was thrown.

      + +

      Note that exceptions thrown by interpreted code do not unwind native stack +frames, and Android does not yet support C++ exceptions. +The JNI Throw and ThrowNew instructions just +set an exception pointer in the current thread. Upon returning to managed +from native code, the exception will be noted and handled appropriately.

      + +

      Native code can "catch" an exception by calling ExceptionCheck or +ExceptionOccurred, and clear it with +ExceptionClear. As usual, +discarding exceptions without handling them can lead to problems.

      + +

      There are no built-in functions for manipulating the Throwable object +itself, so if you want to (say) get the exception string you will need to +find the Throwable class, look up the method ID for +getMessage "()Ljava/lang/String;", invoke it, and if the result +is non-NULL use GetStringUTFChars to get something you can +hand to printf(3) or equivalent.

      + + + +

      Extended Checking

      + +

      JNI does very little error checking. Errors usually result in a crash. Android also offers a mode called CheckJNI, where the JavaVM and JNIEnv function table pointers are switched to tables of functions that perform an extended series of checks before calling the standard implementation.

      + +

      The additional checks include:

      + +
        +
      • Arrays: attempting to allocate a negative-sized array.
      • +
      • Bad pointers: passing a bad jarray/jclass/jobject/jstring to a JNI call, or passing a NULL pointer to a JNI call with a non-nullable argument.
      • +
      • Class names: passing anything but the “java/lang/String” style of class name to a JNI call.
      • +
      • Critical calls: making a JNI call between a “critical” get and its corresponding release.
      • +
      • Direct ByteBuffers: passing bad arguments to NewDirectByteBuffer.
      • +
      • Exceptions: making a JNI call while there’s an exception pending.
      • +
      • JNIEnv*s: using a JNIEnv* from the wrong thread.
      • +
      • jfieldIDs: using a NULL jfieldID, or using a jfieldID to set a field to a value of the wrong type (trying to assign a StringBuilder to a String field, say), or using a jfieldID for a static field to set an instance field or vice versa, or using a jfieldID from one class with instances of another class.
      • +
      • jmethodIDs: using the wrong kind of jmethodID when making a Call*Method JNI call: incorrect return type, static/non-static mismatch, wrong type for ‘this’ (for non-static calls) or wrong class (for static calls).
      • +
      • References: using DeleteGlobalRef/DeleteLocalRef on the wrong kind of reference.
      • +
      • Release modes: passing a bad release mode to a release call (something other than 0, JNI_ABORT, or JNI_COMMIT).
      • +
      • Type safety: returning an incompatible type from your native method (returning a StringBuilder from a method declared to return a String, say).
      • +
      • UTF-8: passing an invalid Modified UTF-8 byte sequence to a JNI call.
      • +
      + +

      (Accessibility of methods and fields is still not checked: access restrictions don't apply to native code.)

      + +

      There are several ways to enable CheckJNI.

      + +

      If you’re using the emulator, CheckJNI is on by default.

      + +

      If you have a rooted device, you can use the following sequence of commands to restart the runtime with CheckJNI enabled:

      + +
      adb shell stop
      +adb shell setprop dalvik.vm.checkjni true
      +adb shell start
      + +

      In either of these cases, you’ll see something like this in your logcat output when the runtime starts:

      + +
      D AndroidRuntime: CheckJNI is ON
      + +

      If you have a regular device, you can use the following command:

      + +
      adb shell setprop debug.checkjni 1
      + +

      This won’t affect already-running apps, but any app launched from that point on will have CheckJNI enabled. (Change the property to any other value or simply rebooting will disable CheckJNI again.) In this case, you’ll see something like this in your logcat output the next time an app starts:

      + +
      D Late-enabling CheckJNI
      + + + + + +

      Native Libraries

      + +

      You can load native code from shared libraries with the standard +System.loadLibrary call. The +preferred way to get at your native code is:

      + +
        +
      • Call System.loadLibrary from a static class +initializer. (See the earlier example, where one is used to call +nativeClassInit.) The argument is the "undecorated" +library name, so to load "libfubar.so" you would pass in "fubar".
      • +
      • Provide a native function: jint JNI_OnLoad(JavaVM* vm, void* reserved)
      • +
      • In JNI_OnLoad, register all of your native methods. You +should declare +the methods "static" so the names don't take up space in the symbol table +on the device.
      • +
      + +

      The JNI_OnLoad function should look something like this if +written in C++:

      +
      jint JNI_OnLoad(JavaVM* vm, void* reserved)
      +{
      +    JNIEnv* env;
      +    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
      +        return -1;
      +    }
      +
      +    // Get jclass with env->FindClass.
      +    // Register methods with env->RegisterNatives.
      +
      +    return JNI_VERSION_1_6;
      +}
      + +

      You can also call System.load with the full path name of the +shared library. For Android apps, you may find it useful to get the full +path to the application's private data storage area from the context object.

      + +

      This is the recommended approach, but not the only approach. Explicit +registration is not required, nor is it necessary that you provide a +JNI_OnLoad function. +You can instead use "discovery" of native methods that are named in a +specific way (see the JNI spec for details), though this is less desirable because if a method signature is wrong you won't know +about it until the first time the method is actually used.

      + +

      One other note about JNI_OnLoad: any FindClass +calls you make from there will happen in the context of the class loader +that was used to load the shared library. Normally FindClass +uses the loader associated with the method at the top of the interpreted +stack, or if there isn't one (because the thread was just attached) it uses +the "system" class loader. This makes +JNI_OnLoad a convenient place to look up and cache class +object references.

      + + + +

      64-bit Considerations

      + +

      Android is currently expected to run on 32-bit platforms. In theory it +could be built for a 64-bit system, but that is not a goal at this time. +For the most part this isn't something that you will need to worry about +when interacting with native code, +but it becomes significant if you plan to store pointers to native +structures in integer fields in an object. To support architectures +that use 64-bit pointers, you need to stash your native pointers in a +long field rather than an int. + + + +

      Unsupported Features/Backwards Compatibility

      + +

      All JNI 1.6 features are supported, with the following exception:

      +
        +
      • DefineClass is not implemented. Android does not use + Java bytecodes or class files, so passing in binary class data + doesn't work.
      • +
      + +

      For backward compatibility with older Android releases, you may need to +be aware of:

      +
        +
      • Dynamic lookup of native functions +

        Until Android 2.0 (Eclair), the '$' character was not properly + converted to "_00024" during searches for method names. Working + around this requires using explicit registration or moving the + native methods out of inner classes. +

      • Detaching threads +

        Until Android 2.0 (Eclair), it was not possible to use a pthread_key_create + destructor function to avoid the "thread must be detached before + exit" check. (The runtime also uses a pthread key destructor function, + so it'd be a race to see which gets called first.) +

      • Weak global references +

        Until Android 2.2 (Froyo), weak global references were not implemented. + Older versions will vigorously reject attempts to use them. You can use + the Android platform version constants to test for support. +

        Until Android 4.0 (Ice Cream Sandwich), weak global references could only + be passed to NewLocalRef, NewGlobalRef, and + DeleteWeakGlobalRef. (The spec strongly encourages + programmers to create hard references to weak globals before doing + anything with them, so this should not be at all limiting.) +

        From Android 4.0 (Ice Cream Sandwich) on, weak global references can be + used like any other JNI references.

      • +
      • Local references +

        Until Android 4.0 (Ice Cream Sandwich), local references were + actually direct pointers. Ice Cream Sandwich added the indirection + necessary to support better garbage collectors, but this means that lots + of JNI bugs are undetectable on older releases. See + JNI Local Reference Changes in ICS for more details. +

      • Determining reference type with GetObjectRefType +

        Until Android 4.0 (Ice Cream Sandwich), as a consequence of the use of + direct pointers (see above), it was impossible to implement + GetObjectRefType correctly. Instead we used a heuristic + 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 + you called GetObjectRefType on a global jclass that happened + to be the same as the jclass passed as an implicit argument to your static + native method, you'd get JNILocalRefType rather than + JNIGlobalRefType. +

      + + + +

      FAQ: Why do I get UnsatisfiedLinkError?

      + +

      When working on native code it's not uncommon to see a failure like this:

      +
      java.lang.UnsatisfiedLinkError: Library foo not found
      + +

      In some cases it means what it says — the library wasn't found. In +other cases the library exists but couldn't be opened by dlopen(3), and +the details of the failure can be found in the exception's detail message.

      + +

      Common reasons why you might encounter "library not found" exceptions:

      +
        +
      • The library doesn't exist or isn't accessible to the app. Use + adb shell ls -l <path> to check its presence + and permissions. +
      • The library wasn't built with the NDK. This can result in + dependencies on functions or libraries that don't exist on the device. +
      + +

      Another class of UnsatisfiedLinkError failures looks like:

      +
      java.lang.UnsatisfiedLinkError: myfunc
      +        at Foo.myfunc(Native Method)
      +        at Foo.main(Foo.java:10)
      + +

      In logcat, you'll see:

      +
      W/dalvikvm(  880): No implementation found for native LFoo;.myfunc ()V
      + +

      This means that the runtime tried to find a matching method but was +unsuccessful. Some common reasons for this are:

      +
        +
      • The library isn't getting loaded. Check the logcat output for + messages about library loading. +
      • The method isn't being found due to a name or signature mismatch. This + is commonly caused by: +
          +
        • For lazy method lookup, failing to declare C++ functions + with extern "C" and appropriate + visibility (JNIEXPORT). Note that prior to Ice Cream + Sandwich, the JNIEXPORT macro was incorrect, so using a new GCC with + an old jni.h won't work. + You can use arm-eabi-nm + to see the symbols as they appear in the library; if they look + mangled (something like _Z15Java_Foo_myfuncP7_JNIEnvP7_jclass + rather than Java_Foo_myfunc), or if the symbol type is + a lowercase 't' rather than an uppercase 'T', then you need to + adjust the declaration. +
        • For explicit registration, minor errors when entering the + method signature. Make sure that what you're passing to the + registration call matches the signature in the log file. + Remember that 'B' is byte and 'Z' is boolean. + Class name components in signatures start with 'L', end with ';', + use '/' to separate package/class names, and use '$' to separate + inner-class names (Ljava/util/Map$Entry;, say). +
        +
      + +

      Using javah to automatically generate JNI headers may help +avoid some problems. + + + +

      FAQ: Why didn't FindClass find my class?

      + +

      Make sure that the class name string has the correct format. JNI class +names start with the package name and are separated with slashes, +such as java/lang/String. If you're looking up an array class, +you need to start with the appropriate number of square brackets and +must also wrap the class with 'L' and ';', so a one-dimensional array of +String would be [Ljava/lang/String;.

      + +

      If the class name looks right, you could be running into a class loader +issue. FindClass wants to start the class search in the +class loader associated with your code. It examines the call stack, +which will look something like: +

          Foo.myfunc(Native Method)
      +    Foo.main(Foo.java:10)
      +    dalvik.system.NativeStart.main(Native Method)
      + +

      The topmost method is Foo.myfunc. FindClass +finds the ClassLoader object associated with the Foo +class and uses that.

      + +

      This usually does what you want. You can get into trouble if you +create a thread yourself (perhaps by calling pthread_create +and then attaching it with AttachCurrentThread). +Now the stack trace looks like this:

      +
          dalvik.system.NativeStart.run(Native Method)
      + +

      The topmost method is NativeStart.run, which isn't part of +your application. If you call FindClass from this thread, the +JavaVM will start in the "system" class loader instead of the one associated +with your application, so attempts to find app-specific classes will fail.

      + +

      There are a few ways to work around this:

      +
        +
      • Do your FindClass lookups once, in + JNI_OnLoad, and cache the class references for later + use. Any FindClass calls made as part of executing + JNI_OnLoad will use the class loader associated with + the function that called System.loadLibrary (this is a + special rule, provided to make library initialization more convenient). + If your app code is loading the library, FindClass + will use the correct class loader. +
      • Pass an instance of the class into the functions that need + it, by declaring your native method to take a Class argument and + then passing Foo.class in. +
      • Cache a reference to the ClassLoader object somewhere + handy, and issue loadClass calls directly. This requires + some effort. +
      + + + +

      FAQ: How do I share raw data with native code?

      + +

      You may find yourself in a situation where you need to access a large +buffer of raw data from both managed and native code. Common examples +include manipulation of bitmaps or sound samples. There are two +basic approaches.

      + +

      You can store the data in a byte[]. This allows very fast +access from managed code. On the native side, however, you're +not guaranteed to be able to access the data without having to copy it. In +some implementations, GetByteArrayElements and +GetPrimitiveArrayCritical will return actual pointers to the +raw data in the managed heap, but in others it will allocate a buffer +on the native heap and copy the data over.

      + +

      The alternative is to store the data in a direct byte buffer. These +can be created with java.nio.ByteBuffer.allocateDirect, or +the JNI NewDirectByteBuffer function. Unlike regular +byte buffers, the storage is not allocated on the managed heap, and can +always be accessed directly from native code (get the address +with GetDirectBufferAddress). Depending on how direct +byte buffer access is implemented, accessing the data from managed code +can be very slow.

      + +

      The choice of which to use depends on two factors:

      +
        +
      1. Will most of the data accesses happen from code written in Java + or in C/C++? +
      2. If the data is eventually being passed to a system API, what form + must it be in? (For example, if the data is eventually passed to a + function that takes a byte[], doing processing in a direct + ByteBuffer might be unwise.) +
      + +

      If there's no clear winner, use a direct byte buffer. Support for them +is built directly into JNI, and performance should improve in future releases.

      diff --git a/docs/html/guide/practices/optimizing-for-3.0.jd b/docs/html/guide/practices/optimizing-for-3.0.jd index d6c621ea4287e7ed447ebcc581a8939be4953736..65c56744ce6a8ecbaf63de4e89c373e784b0f2d6 100644 --- a/docs/html/guide/practices/optimizing-for-3.0.jd +++ b/docs/html/guide/practices/optimizing-for-3.0.jd @@ -53,7 +53,7 @@ onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />
    5. Supporting Tablets and Handsets
    6. Compatibility Library
    7. +href="{@docRoot}tools/extras/support-library.html">Compatibility Library
    8. Google I/O App source code
    @@ -108,7 +108,7 @@ SDK with the new platform:

    SDK starter package now.)

      -
    1. Launch the Android SDK +
    2. Launch the Android SDK Manager and install the following:
      • SDK Platform Android 3.0
      • @@ -280,15 +280,15 @@ use techniques such as reflection to check for the availability of certain APIs to help you add features from Android 3.0 without requiring you to change your {@code android:minSdkVersion} or build target, we're providing a static library called the Compatibility Library +href="{@docRoot}tools/extras/support-library.html">Compatibility Library (downloadable from the Android SDK Manager).

        This library includes APIs for fragments, loaders, and some updated classes. By +href="{@docRoot}guide/components/fragments.html">fragments, loaders, and some updated classes. By simply adding this library to your Android project, you can use these APIs in your application and remain compatible with Android 1.6. For information about how to get the library and start using it in your application, see the Compatibility Library document.

        +href="{@docRoot}tools/extras/support-library.html">Compatibility Library document.

        @@ -357,7 +357,7 @@ input events. Thus, instead of using one activity to select an article and anoth read the article, the user can select an article and read it all within the same activity.

        For more information, read the Fragments document.

        +href="{@docRoot}guide/components/fragments.html">Fragments document.

        Use new animation APIs for transitions

        @@ -374,7 +374,7 @@ New transformations are made possible with a set of object properties that defin position, orientation, transparency and more.

        For more information, read the Property Animation document.

        +href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation document.

        Enable hardware acceleration

        @@ -412,15 +412,15 @@ application, such as drag and drop APIs, new Bluetooth APIs, a system-wide clipb new graphics engine called Renderscript, and more.

        To learn more about the APIs mentioned above and more, see the Android 3.0 Platform document.

        +href="{@docRoot}about/versions/android-3.0.html">Android 3.0 Platform document.

        Look at some samples

        Many of the new features and APIs that are described above and in the Android 3.0 Platform document also have accompanying +href="{@docRoot}about/versions/android-3.0.html#api">Android 3.0 Platform document also have accompanying samples that allow you to preview the effects and can help you understand how to use them. To get -the samples, download them from the SDK repository using the Android SDK Manager. After downloading the samples ("Samples for SDK API 11"), you can find them in <sdk_root>/samples/android-11/. The following list provides links to the browsable source code for some of the samples:

        @@ -474,7 +474,7 @@ android:targetSdkVersion} set to {@code "4"} or higher, then the Android sys application's layout and assets to fit the current device screen, whether the device screen is smaller or larger than the one for which you originally designed your application. As such, you should always test your application on real or virtual devices with various screen sizes +href="{@docRoot}tools/devices/index.html">virtual devices with various screen sizes and densities.

        Although we recommend that you design your application to function properly on multiple @@ -641,7 +641,7 @@ orientation. When the user rotates the screen, the system restarts the current a onCreate()}) in immediate succession. You should design your activity to account for these changes in the lifecycle, so the activity can save and restore its state. You can learn about the necessary lifecycle callback methods and how to save and restore the activity state in the Activities +href="{@docRoot}guide/components/activities.html#Lifecycle">Activities document. If your activity state is more complex and cannot retain it using the normal lifecycle callback methods, you can use alternative techniques described in Handling Runtime Changes.

        diff --git a/docs/html/guide/practices/performance.jd b/docs/html/guide/practices/performance.jd new file mode 100644 index 0000000000000000000000000000000000000000..078999becc393c3c23614685b4f1c2d836ebcfdf --- /dev/null +++ b/docs/html/guide/practices/performance.jd @@ -0,0 +1,410 @@ +page.title=Designing for Performance +@jd:body + + + +

        An Android application will run on a mobile device with limited computing +power and storage, and constrained battery life. Because of +this, it should be efficient. Battery life is one reason you might +want to optimize your app even if it already seems to run "fast enough". +Battery life is important to users, and Android's battery usage breakdown +means users will know if your app is responsible draining their battery.

        + +

        Note that although this document primarily covers micro-optimizations, +these will almost never make or break your software. Choosing the right +algorithms and data structures should always be your priority, but is +outside the scope of this document.

        + + +

        Introduction

        + +

        There are two basic rules for writing efficient code:

        +
          +
        • Don't do work that you don't need to do.
        • +
        • Don't allocate memory if you can avoid it.
        • +
        + +

        Optimize Judiciously

        + +

        This document is about Android-specific micro-optimization, so it assumes +that you've already used profiling to work out exactly what code needs to be +optimized, and that you already have a way to measure the effect (good or bad) +of any changes you make. You only have so much engineering time to invest, so +it's important to know you're spending it wisely. + +

        (See Closing Notes for more on profiling and +writing effective benchmarks.) + +

        This document also assumes that you made the best decisions about data +structures and algorithms, and that you've also considered the future +performance consequences of your API decisions. Using the right data +structures and algorithms will make more difference than any of the advice +here, and considering the performance consequences of your API decisions will +make it easier to switch to better implementations later (this is more +important for library code than for application code). + +

        (If you need that kind of advice, see Josh Bloch's Effective Java, +item 47.)

        + +

        One of the trickiest problems you'll face when micro-optimizing an Android +app is that your app is pretty much guaranteed to be running on multiple +hardware platforms. Different versions of the VM running on different +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 JIT: the "best" +code for a device with a JIT is not always the best code for a device +without.

        + +

        If you want to know how your app performs on a given device, you need to +test on that device.

        + + +

        Avoid Creating Unnecessary Objects

        + +

        Object creation is never free. A generational GC with per-thread allocation +pools for temporary objects can make allocation cheaper, but allocating memory +is always more expensive than not allocating memory.

        + +

        If you allocate objects in a user interface loop, you will force a periodic +garbage collection, creating little "hiccups" in the user experience. The +concurrent collector introduced in Gingerbread helps, but unnecessary work +should always be avoided.

        + +

        Thus, you should avoid creating object instances you don't need to. Some +examples of things that can help:

        + +
          +
        • If you have a method returning a string, and you know that its result + will always be appended to a StringBuffer anyway, change your signature + and implementation so that the function does the append directly, + instead of creating a short-lived temporary object.
        • +
        • When extracting strings from a set of input data, try + to return a substring of the original data, instead of creating a copy. + You will create a new String object, but it will share the char[] + with the data. (The trade-off being that if you're only using a small + part of the original input, you'll be keeping it all around in memory + anyway if you go this route.)
        • +
        + +

        A somewhat more radical idea is to slice up multidimensional arrays into +parallel single one-dimension arrays:

        + +
          +
        • An array of ints is a much better than an array of Integers, + but this also generalizes to the fact that two parallel arrays of ints + are also a lot more efficient than an array of (int,int) + objects. The same goes for any combination of primitive types.
        • +
        • If you need to implement a container that stores tuples of (Foo,Bar) + objects, try to remember that two parallel Foo[] and Bar[] arrays are + generally much better than a single array of custom (Foo,Bar) objects. + (The exception to this, of course, is when you're designing an API for + other code to access; in those cases, it's usually better to trade + good API design for a small hit in speed. But in your own internal + code, you should try and be as efficient as possible.)
        • +
        + +

        Generally speaking, avoid creating short-term temporary objects if you +can. Fewer objects created mean less-frequent garbage collection, which has +a direct impact on user experience.

        + + + +

        Performance Myths

        + +

        Previous versions of this document made various misleading claims. We +address some of them here.

        + +

        On devices without a JIT, it is true that invoking methods via a +variable with an exact type rather than an interface is slightly more +efficient. (So, for example, it was cheaper to invoke methods on a +HashMap map than a Map map, even though in both +cases the map was a HashMap.) It was not the case that this +was 2x slower; the actual difference was more like 6% slower. Furthermore, +the JIT makes the two effectively indistinguishable.

        + +

        On devices without a JIT, caching field accesses is about 20% faster than +repeatedly accesssing the field. With a JIT, field access costs about the same +as local access, so this isn't a worthwhile optimization unless you feel it +makes your code easier to read. (This is true of final, static, and static +final fields too.) + + +

        Prefer Static Over Virtual

        + +

        If you don't need to access an object's fields, make your method static. +Invocations will be about 15%-20% faster. +It's also good practice, because you can tell from the method +signature that calling the method can't alter the object's state.

        + + +

        Avoid Internal Getters/Setters

        + +

        In native languages like C++ it's common practice to use getters (e.g. +i = getCount()) instead of accessing the field directly (i += mCount). This is an excellent habit for C++, because the compiler can +usually inline the access, and if you need to restrict or debug field access +you can add the code at any time.

        + +

        On Android, this is a bad idea. Virtual method calls are expensive, +much more so than instance field lookups. It's reasonable to follow +common object-oriented programming practices and have getters and setters +in the public interface, but within a class you should always access +fields directly.

        + +

        Without a JIT, direct field access is about 3x faster than invoking a +trivial getter. With the JIT (where direct field access is as cheap as +accessing a local), direct field access is about 7x faster than invoking a +trivial getter. This is true in Froyo, but will improve in the future when +the JIT inlines getter methods.

        + +

        Note that if you're using ProGuard, you can have the best +of both worlds because ProGuard can inline accessors for you.

        + + +

        Use Static Final For Constants

        + +

        Consider the following declaration at the top of a class:

        + +
        static int intVal = 42;
        +static String strVal = "Hello, world!";
        + +

        The compiler generates a class initializer method, called +<clinit>, that is executed when the class is first used. +The method stores the value 42 into intVal, and extracts a +reference from the classfile string constant table for strVal. +When these values are referenced later on, they are accessed with field +lookups.

        + +

        We can improve matters with the "final" keyword:

        + +
        static final int intVal = 42;
        +static final String strVal = "Hello, world!";
        + +

        The class no longer requires a <clinit> method, +because the constants go into static field initializers in the dex file. +Code that refers to intVal will use +the integer value 42 directly, and accesses to strVal will +use a relatively inexpensive "string constant" instruction instead of a +field lookup. (Note that this optimization only applies to primitive types and +String constants, not arbitrary reference types. Still, it's good +practice to declare constants static final whenever possible.)

        + + +

        Use Enhanced For Loop Syntax

        + +

        The enhanced for loop (also sometimes known as "for-each" loop) can be used +for collections that implement the Iterable interface and for arrays. +With collections, an iterator is allocated to make interface calls +to hasNext() and next(). With an ArrayList, a hand-written counted loop is +about 3x faster (with or without JIT), but for other collections the enhanced +for loop syntax will be exactly equivalent to explicit iterator usage.

        + +

        There are several alternatives for iterating through an array:

        + +
            static class Foo {
        +        int mSplat;
        +    }
        +    Foo[] mArray = ...
        +
        +    public void zero() {
        +        int sum = 0;
        +        for (int i = 0; i < mArray.length; ++i) {
        +            sum += mArray[i].mSplat;
        +        }
        +    }
        +
        +    public void one() {
        +        int sum = 0;
        +        Foo[] localArray = mArray;
        +        int len = localArray.length;
        +
        +        for (int i = 0; i < len; ++i) {
        +            sum += localArray[i].mSplat;
        +        }
        +    }
        +
        +    public void two() {
        +        int sum = 0;
        +        for (Foo a : mArray) {
        +            sum += a.mSplat;
        +        }
        +    }
        +
        + +

        zero() is slowest, because the JIT can't yet optimize away +the cost of getting the array length once for every iteration through the +loop.

        + +

        one() is faster. It pulls everything out into local +variables, avoiding the lookups. Only the array length offers a performance +benefit.

        + +

        two() is fastest for devices without a JIT, and +indistinguishable from one() for devices with a JIT. +It uses the enhanced for loop syntax introduced in version 1.5 of the Java +programming language.

        + +

        To summarize: use the enhanced for loop by default, but consider a +hand-written counted loop for performance-critical ArrayList iteration.

        + +

        (See also Effective Java item 46.)

        + + +

        Consider Package Instead of Private Access with Private Inner Classes

        + +

        Consider the following class definition:

        + +
        public class Foo {
        +    private class Inner {
        +        void stuff() {
        +            Foo.this.doStuff(Foo.this.mValue);
        +        }
        +    }
        +
        +    private int mValue;
        +
        +    public void run() {
        +        Inner in = new Inner();
        +        mValue = 27;
        +        in.stuff();
        +    }
        +
        +    private void doStuff(int value) {
        +        System.out.println("Value is " + value);
        +    }
        +}
        + +

        The key things to note here are that we define a private inner class +(Foo$Inner) that directly accesses a private method and a private +instance field in the outer class. This is legal, and the code prints "Value is +27" as expected.

        + +

        The problem is that the VM considers direct access to Foo's +private members from Foo$Inner to be illegal because +Foo and Foo$Inner are different classes, even though +the Java language allows an inner class to access an outer class' private +members. To bridge the gap, the compiler generates a couple of synthetic +methods:

        + +
        /*package*/ static int Foo.access$100(Foo foo) {
        +    return foo.mValue;
        +}
        +/*package*/ static void Foo.access$200(Foo foo, int value) {
        +    foo.doStuff(value);
        +}
        + +

        The inner class code calls these static methods whenever it needs to +access the mValue field or invoke the doStuff method +in the outer class. What this means is that the code above really boils down to +a case where you're accessing member fields through accessor methods. +Earlier we talked about how accessors are slower than direct field +accesses, so this is an example of a certain language idiom resulting in an +"invisible" performance hit.

        + +

        If you're using code like this in a performance hotspot, you can avoid the +overhead by declaring fields and methods accessed by inner classes to have +package access, rather than private access. Unfortunately this means the fields +can be accessed directly by other classes in the same package, so you shouldn't +use this in public API.

        + + +

        Use Floating-Point Judiciously

        + +

        As a rule of thumb, floating-point is about 2x slower than integer on +Android devices. This is true on a FPU-less, JIT-less G1 and a Nexus One with +an FPU and the JIT. (Of course, absolute speed difference between those two +devices is about 10x for arithmetic operations.)

        + +

        In speed terms, there's no difference between float and +double on the more modern hardware. Space-wise, double +is 2x larger. As with desktop machines, assuming space isn't an issue, you +should prefer double to float.

        + +

        Also, even for integers, some chips have hardware multiply but lack +hardware divide. In such cases, integer division and modulus operations are +performed in software — something to think about if you're designing a +hash table or doing lots of math.

        + + +

        Know And Use The Libraries

        + +

        In addition to all the usual reasons to prefer library code over rolling +your own, bear in mind that the system is at liberty to replace calls +to library methods with hand-coded assembler, which may be better than the +best code the JIT can produce for the equivalent Java. The typical example +here is String.indexOf and friends, which Dalvik replaces with +an inlined intrinsic. Similarly, the System.arraycopy method +is about 9x faster than a hand-coded loop on a Nexus One with the JIT.

        + +

        (See also Effective Java item 47.)

        + + +

        Use Native Methods Judiciously

        + +

        Native code isn't necessarily more efficient than Java. For one thing, +there's a cost associated with the Java-native transition, and the JIT can't +optimize across these boundaries. If you're allocating native resources (memory +on the native heap, file descriptors, or whatever), it can be significantly +more difficult to arrange timely collection of these resources. You also +need to compile your code for each architecture you wish to run on (rather +than rely on it having a JIT). You may even have to compile multiple versions +for what you consider the same architecture: native code compiled for the ARM +processor in the G1 can't take full advantage of the ARM in the Nexus One, and +code compiled for the ARM in the Nexus One won't run on the ARM in the G1.

        + +

        Native code is primarily useful when you have an existing native codebase +that you want to port to Android, not for "speeding up" parts of a Java app.

        + +

        If you do need to use native code, you should read our +JNI Tips.

        + +

        (See also Effective Java item 54.)

        + + +

        Closing Notes

        + +

        One last thing: always measure. Before you start optimizing, make sure you +have a problem. 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, +which may cause it to misattribute time to code that the JIT may be able to win +back. It's especially important after making changes suggested by Traceview +data to ensure that the resulting code actually runs faster when run without +Traceview. diff --git a/docs/html/guide/practices/responsiveness.jd b/docs/html/guide/practices/responsiveness.jd new file mode 100644 index 0000000000000000000000000000000000000000..a00e3aa651143a4f7dd7234ffe85b0cd12518a2e --- /dev/null +++ b/docs/html/guide/practices/responsiveness.jd @@ -0,0 +1,140 @@ +page.title=Designing for Responsiveness +@jd:body + +

        + +
        + +
        +Screenshot of ANR dialog box +

        Figure 1. An ANR dialog displayed to the user.

        +
        + +

        It's possible to write code that wins every performance test in the world, +but still sends users in a fiery rage when they try to use the application. +These are the applications that aren't responsive enough — the +ones that feel sluggish, hang or freeze for significant periods, or take too +long to process input.

        + +

        In Android, the system guards against applications that are insufficiently +responsive for a period of time by displaying a dialog to the user, called the +Application Not Responding (ANR) dialog, shown at right in Figure 1. The user +can choose to let the application continue, but the user won't appreciate having +to act on this dialog every time he or she uses your application. It's critical +to design responsiveness into your application, so that the system never has +cause to display an ANR dialog to the user.

        + +

        Generally, the system displays an ANR if an application cannot respond to +user input. For example, if an application blocks on some I/O operation +(frequently a network access), then the main application thread won't be able to +process incoming user input events. After a time, the system concludes that the +application is frozen, and displays the ANR to give the user the option to kill +it.

        + +

        Similarly, if your application spends too much time building an elaborate in-memory +structure, or perhaps computing the next move in a game, the system will +conclude that your application has hung. It's always important to make +sure these computations are efficient using the techniques above, but even the +most efficient code still takes time to run.

        + +

        In both of these cases, the recommended approach is to create a child thread and do +most of your work there. This keeps the main thread (which drives the user +interface event loop) running and prevents the system from concluding that your code +has frozen. Since such threading usually is accomplished at the class +level, you can think of responsiveness as a class problem. (Compare +this with basic performance, which was described above as a method-level +concern.)

        + +

        This document describes how the Android system determines whether an +application is not responding and provides guidelines for ensuring that your +application stays responsive.

        + +

        What Triggers ANR?

        + +

        In Android, application responsiveness is monitored by the Activity Manager +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 (e.g. key press, screen touch) + within 5 seconds
        • +
        • A {@link android.content.BroadcastReceiver BroadcastReceiver} + hasn't finished executing within 10 seconds
        • +
        + +

        How to Avoid ANR

        + +

        Given the above definition for ANR, let's examine why this can occur in +Android applications and how best to structure your application to avoid ANR.

        + +

        Android applications normally run entirely on a single (i.e. main) thread. +This means that anything your application is doing in the main thread that +takes a long time to complete can trigger the ANR dialog because your +application is not giving itself a chance to handle the input event or Intent +broadcast.

        + +

        Therefore any method that runs in the main thread should do as little work +as possible. In particular, Activities should do as little as possible to set +up in key life-cycle methods such as onCreate() and +onResume(). Potentially long running operations such as network +or database operations, or computationally expensive calculations such as +resizing bitmaps should be done in a child thread (or in the case of databases +operations, via an asynchronous request). However, this does not mean that +your main thread should block while waiting for the child thread to +complete — nor should you call Thread.wait() or +Thread.sleep(). Instead of blocking while waiting for a child +thread to complete, your main thread should provide a {@link +android.os.Handler Handler} for child threads to post back to upon completion. +Designing your application in this way will allow your main thread to remain +responsive to input and thus avoid ANR dialogs caused by the 5 second input +event timeout. These same practices should be followed for any other threads +that display UI, as they are also subject to the same timeouts.

        + +

        You can use {@link android.os.StrictMode} to help find potentially +long running operations such as network or database operations that +you might accidentally be doing your main thread.

        + +

        The specific constraint on IntentReceiver execution time emphasizes what +they were meant to do: small, discrete amounts of work in the background such +as saving a setting or registering a Notification. So as with other methods +called in the main thread, applications should avoid potentially long-running +operations or calculations in BroadcastReceivers. But instead of doing intensive +tasks via child threads (as the life of a BroadcastReceiver is short), your +application should start a {@link android.app.Service Service} if a +potentially long running action needs to be taken in response to an Intent +broadcast. As a side note, you should also avoid starting an Activity from an +Intent Receiver, as it will spawn a new screen that will steal focus from +whatever application the user is currently has running. If your application +has something to show the user in response to an Intent broadcast, it should +do so using the {@link android.app.NotificationManager Notification +Manager}.

        + +

        Reinforcing Responsiveness

        + +

        Generally, 100 to 200ms is the threshold beyond which users will perceive +lag (or lack of "snappiness," if you will) in an application. As such, here +are some additional tips beyond what you should do to avoid ANR that will help +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 ({@link + android.widget.ProgressBar ProgressBar} and {@link + android.app.ProgressDialog ProgressDialog} are useful for this).
        • +
        • For games specifically, do calculations for moves in a child + 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 + and filling in the information asynchronously. In either case, you should + indicate somehow that progress is being made, lest the user perceive that + the application is frozen.
        • +
        diff --git a/docs/html/guide/practices/screens-distribution.jd b/docs/html/guide/practices/screens-distribution.jd index a7c4a8ee791c997cd626af9ce85712d84c2bcf25..90ac752f70085bcf383695a795ecd42ec81cafae 100644 --- a/docs/html/guide/practices/screens-distribution.jd +++ b/docs/html/guide/practices/screens-distribution.jd @@ -213,4 +213,4 @@ sizes, especially, is within reason using a single APK, as long as you follow th Supporting Multiple Screens.

        If you need more information about how to publish multiple APKs on Google Play, read Multiple APK Support.

        +href="{@docRoot}guide/google/play/publishing/multiple-apks.html">Multiple APK Support.

        diff --git a/docs/html/guide/practices/screens-support-1.5.jd b/docs/html/guide/practices/screens-support-1.5.jd index 4c6fb99f9397b5ea24bab4f8fa89e083b2ca191c..15f069535df202ef78f99e220487d1ebe00a13d6 100644 --- a/docs/html/guide/practices/screens-support-1.5.jd +++ b/docs/html/guide/practices/screens-support-1.5.jd @@ -59,7 +59,7 @@ below.

        Note: Before you begin, you should first decide whether it's even necessary to support Android 1.5. To see the relative number of devices that are still running Android 1.5, see the Platform Versions +href="http://developer.android.com/about/dashboards/index.html">Platform Versions Dashboard.

        diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd index a870b223c6ac99c932ed44e74544056601ebed99..ca29589b42048532e3de90b7066e1a1b5f4fed7c 100644 --- a/docs/html/guide/practices/screens_support.jd +++ b/docs/html/guide/practices/screens_support.jd @@ -57,7 +57,7 @@ href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResou Providing Alternative Resources
      • Icon Design Guidelines
      • -
      • Managing Virtual Devices
      • +
      • Managing Virtual Devices
    @@ -1253,7 +1253,7 @@ Manager with a selection of AVDs, for testing various screen configurations.

    to emulate some of the most common screen configurations.

    For more information about creating and using AVDs to test your application, see Managing AVDs with AVD +href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with AVD Manager.

    @@ -1366,5 +1366,5 @@ the emulator with the -scale option. For example:

    between 0.1 and 3 that represents the desired scaling factor.

    For more information about creating AVDs from the command line, see Managing AVDs from the +href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing AVDs from the Command Line

    diff --git a/docs/html/guide/practices/seamlessness.jd b/docs/html/guide/practices/seamlessness.jd new file mode 100644 index 0000000000000000000000000000000000000000..ec6b7fdff73c9326a33616925930f107fa100561 --- /dev/null +++ b/docs/html/guide/practices/seamlessness.jd @@ -0,0 +1,249 @@ +page.title=Designing for Seamlessness +@jd:body + + + +

    Even if your application is fast and responsive, certain design decisions can +still cause problems for users — because of unplanned interactions with +other applications or dialogs, inadvertent loss of data, unintended blocking, +and so on. To avoid these problems, it helps to understand the context in which +your applications run and the system interactions that can affect your +application. In short, you should strive to develop an application that +interacts seamlessly with the system and with other applications.

    + +

    A common seamlessness problem is when an application's background process +— for example, a service or broadcast receiver — pops up a dialog in +response to some event. This may seem like harmless behavior, especially when +you are building and testing your application in isolation, on the emulator. +However, when your application is run on an actual device, your application may +not have user focus at the time your background process displays the dialog. So +it could end up that your application would display it's dialog behind the +active application, or it could take focus from the current application and +display the dialog in front of whatever the user was doing (such as dialing a +phone call, for example). That behavior would not work for your application or +for the user.

    + +

    To avoid these problems, your application should use the proper system +facility for notifying the user — the +{@link android.app.Notification Notification} classes. Using +notifications, your application can signal the user that an event has +taken place, by displaying an icon in the status bar rather than taking +focus and interrupting the user.

    + +

    Another example of a seamlessness problem is when an activity inadvertently +loses state or user data because it doesn't correctly implement the onPause() +and other lifecycle methods. Or, if your application exposes data intended to be +used by other applications, you should expose it via a ContentProvider, rather +than (for example) doing so through a world-readable raw file or database.

    + +

    What those examples have in common is that they involve cooperating nicely +with the system and other applications. The Android system is designed to treat +applications as a sort of federation of loosely-coupled components, rather than +chunks of black-box code. This allows you as the developer to view the entire +system as just an even-larger federation of these components. This benefits you +by allowing you to integrate cleanly and seamlessly with other applications, and +so you should design your own code to return the favor.

    + +

    This document discusses common seamlessness problems and how to avoid them.

    + +

    Don't Drop Data

    + +

    Always keep in mind that Android is a mobile platform. It may seem obvious to +say it, but it's important to remember that another Activity (such as the +"Incoming Phone Call" app) can pop up over your own Activity at any moment. +This will fire the onSaveInstanceState() and onPause() methods, and will likely result in +your application being killed.

    + +

    If the user was editing data in your application when the other Activity +appeared, your application will likely lose that data when your application is +killed. Unless, of course, you save the work in progress first. The "Android +Way" is to do just that: Android applications that accept or edit input should +override the onSaveInstanceState() method and save their state in some appropriate +fashion. When the user revisits the application, she should be able to +retrieve her data.

    + +

    A classic example of a good use of this behavior is a mail application. If the +user was composing an email when another Activity started up, the application +should save the in-process email as a draft.

    + +

    Don't Expose Raw Data

    + +

    If you wouldn't walk down the street in your underwear, neither should your +data. While it's possible to expose certain kinds of application to the world +to read, this is usually not the best idea. Exposing raw data requires other +applications to understand your data format; if you change that format, you'll +break any other applications that aren't similarly updated.

    + +

    The "Android Way" is to create a ContentProvider to expose your data to other +applications via a clean, well-thought-out, and maintainable API. Using a +ContentProvider is much like inserting a Java language interface to split up and +componentize two tightly-coupled pieces of code. This means you'll be able to +modify the internal format of your data without changing the interface exposed +by the ContentProvider, and this without affecting other applications.

    + +

    Don't Interrupt the User

    + +

    If the user is running an application (such as the Phone application during a +call) it's a pretty safe bet he did it on purpose. That's why you should avoid +spawning activities except in direct response to user input from the current +Activity.

    + +

    That is, don't call startActivity() from BroadcastReceivers or Services running in +the background. Doing so will interrupt whatever application is currently +running, and result in an annoyed user. Perhaps even worse, your Activity may +become a "keystroke bandit" and receive some of the input the user was in the +middle of providing to the previous Activity. Depending on what your +application does, this could be bad news.

    + +

    Instead of spawning Activity UIs directly from the background, you should +instead use the NotificationManager to set Notifications. These will appear in +the status bar, and the user can then click on them at his leisure, to see +what your application has to show him.

    + +

    (Note that all this doesn't apply to cases where your own Activity is already +in the foreground: in that case, the user expects to see your next Activity in +response to input.)

    + +

    Got a Lot to Do? Do it in a Thread

    + +

    If your application needs to perform some expensive or long-running +computation, you should probably move it to a thread. This will prevent the +dreaded "Application Not Responding" dialog from being displayed to the user, +with the ultimate result being the fiery demise of your application.

    + +

    By default, all code in an Activity as well as all its Views run in the same +thread. This is the same thread that also handles UI events. For example, when +the user presses a key, a key-down event is added to the Activity's main +thread's queue. The event handler system needs to dequeue and handle that +event quickly; if it doesn't, the system concludes after a few seconds that +the application is hung and offers to kill it for the user.

    + +

    If you have long-running code, running it inline in your Activity will run it +on the event handler thread, effectively blocking the event handler. This will +delay input processing, and result in the ANR dialogs. To avoid this, move +your computations to a thread. This Design for Responsiveness document +discusses how to do that..

    + +

    Don't Overload a Single Activity Screen

    + +

    Any application worth using will probably have several different screens. +When designing the screens of your UI, be sure to make use of multiple Activity +object instances.

    + +

    Depending on your development background, you may interpret an Activity as +similar to something like a Java Applet, in that it is the entry point for +your application. However, that's not quite accurate: where an Applet subclass +is the single entry point for a Java Applet, an Activity should be thought of +as one of potentially several entry points to your application. The only +difference between your "main" Activity and any others you might have is that +the "main" one just happens to be the only one that expressed an interest in +the "android.intent.action.MAIN" action in your AndroidManifest..xml file.

    + +

    So, when designing your application, think of your application as a federation +of Activity objects. This will make your code a lot more maintainable in the long +run, and as a nice side effect also plays nicely with Android's application +history and "backstack" model.

    + +

    Extend System Themes

    + +

    When it comes to the look-and-feel of the user interface, it's important to +blend in nicely. Users are jarred by applications which contrast with the user +interface they've come to expect. When designing your UIs, you should try and +avoid rolling your own as much as possible. Instead, use a Theme. You +can override or extend those parts of the theme that you need to, but at least +you're starting from the same UI base as all the other applications. For all +the details, read Styles and Themes.

    + +

    Design Your UI to Work with Multiple Screen Resolutions

    + +

    Different Android-powered devices will support different screen resolutions. +Some will even be able to change resolutions on the fly, such as by switching +to landscape mode. It's important to make sure your layouts and drawables +are flexible enough to display properly on a variety of device screens.

    + +

    Fortunately, this is very easy to do. In brief, what you must do is +provide different versions of your artwork (if you use any) for the key +resolutions, and then design your layout to accommodate various dimensions. +(For example, avoid using hard-coded positions and instead use relative +layouts.) If you do that much, the system handles the rest, and your +application looks great on any device.

    + +

    Assume the Network is Slow

    + +

    Android devices will come with a variety of network-connectivity options. All +will have some data-access provision, though some will be faster than others. +The lowest common denominator, however, is GPRS, the non-3G data service for +GSM networks. Even 3G-capable devices will spend lots of time on non-3G +networks, so slow networks will remain a reality for quite a long time to +come.

    + +

    That's why you should always code your applications to minimize network +accesses and bandwidth. You can't assume the network is fast, so you should +always plan for it to be slow. If your users happen to be on faster networks, +then that's great — their experience will only improve. You want to avoid the +inverse case though: applications that are usable some of the time, but +frustratingly slow the rest based on where the user is at any given moment are +likely to be unpopular.

    + +

    One potential gotcha here is that it's very easy to fall into this trap if +you're using the emulator, since the emulator uses your desktop computer's +network connection. That's almost guaranteed to be much faster than a cell +network, so you'll want to change the settings on the emulator that simulate +slower network speeds. You can do this in Eclipse, in the "Emulator Settings" +tab of your launch configuration or via a command-line +option when starting the emulator.

    + +

    Don't Assume Touchscreen or Keyboard

    + +

    +Android will support a variety of handset form-factors. That's a fancy way of +saying that some Android devices will have full "QWERTY" keyboards, while +others will have 40-key, 12-key, or even other key configurations. Similarly, +some devices will have touch-screens, but many won't. +

    +When building your applications, keep that in mind. Don't make assumptions +about specific keyboard layouts -- unless, of course, you're really interested +in restricting your application so that it can only be used on those devices. +

    + +

    Do Conserve the Device Battery

    +

    +A mobile device isn't very mobile if it's constantly plugged into the +wall. Mobile devices are battery-powered, and the longer we can make that +battery last on a charge, the happier everyone is — especially the user. +Two of the biggest consumers of battery power are the processor, and the +radio; that's why it's important to write your applications to do as little +work as possible, and use the network as infrequently as possible. +

    +Minimizing the amount of processor time your application uses really comes +down to writing efficient +code. To minimize the power drain from using the radio, be sure to handle +error conditions gracefully, and only fetch what you need. For example, don't +constantly retry a network operation if one failed. If it failed once, it's +likely because the user has no reception, so it's probably going to fail again +if you try right away; all you'll do is waste battery power. +

    +Users are pretty smart: if your program is power-hungry, you can count on +them noticing. The only thing you can be sure of at that point is that your +program won't stay installed very long. +

    diff --git a/docs/html/guide/practices/security.jd b/docs/html/guide/practices/security.jd index eeaac44e394009948352af1f4ca6bf35cc026782..48ccdebcfc934c3e380eb3a7ec84c0910134c8a3 100644 --- a/docs/html/guide/practices/security.jd +++ b/docs/html/guide/practices/security.jd @@ -20,8 +20,7 @@ page.title=Designing for Security
    1. Android Security Overview
    2. -
    3. Android Security -And Permissions
    4. +
    5. Permissions

    Android was designed so that most developers will be able to build @@ -136,7 +135,7 @@ dynamic permission grants on a case-by-case basis.

    To provide additional protection for sensitive data, some applications choose to encrypt local files using a key that is not accessible to the application. (For example, a key can be placed in a KeyStore and +href="{@docRoot}reference/java/security/KeyStore.html">KeyStore and protected with a user password that is not stored on the device). While this does not protect data from a root compromise that can monitor the user inputting the password, it can provide protection for a lost device without

    See also

      -
    1. Fragments
    2. +
    3. Fragments
    4. Action Bar
    5. Supporting Multiple Screens
    @@ -85,7 +85,7 @@ activity), which has its own lifecycle and which you can add or remove while the running.

    If you haven't used fragments yet, start by reading the Fragments developer guide.

    +href="{@docRoot}guide/components/fragments.html">Fragments developer guide.

    @@ -141,16 +141,16 @@ bar below.

    Remaining backward-compatible

    If you want to use fragments in your application and remain compatible with versions of Android older than 3.0, you can do so by using the Android Support Library (downloadable from the +href="{@docRoot}tools/extras/support-library.html">Support Library (downloadable from the SDK Manager).

    The support library includes APIs for fragments, loaders, and other APIs added in newer +href="{@docRoot}guide/components/fragments.html">fragments, loaders, and other APIs added in newer versions of Android. By simply adding this library to your Android project, you can use backward-compatible versions of these APIs in your application and remain compatible with Android 1.6 (your {@code android:minSdkVersion} value can be as low as {@code "4"}). For information about how to get the -library and start using it, see the Support +library and start using it, see the Support Library document.

    The support library does not provide APIs for the action bar, but you can use 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 8e4528e8553a7ba90f9dc1951614a5c403722b7d..cb2bc373bbf153e37b435af9ca4284d475b76f10 100644 --- a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd +++ b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd @@ -19,7 +19,7 @@ parent.link=index.html for App Structure and Navigation, or the developer guide about Tasks and Back Stack.

    +href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back Stack.

    See also

      -
    1. Application Fundamentals
    2. +
    3. Application Fundamentals
    @@ -121,9 +121,9 @@ need to

    Be sure to look at the Design Tips section for guidelines, tips, and things to avoid. This document is a - complement to the Application + complement to the Application Fundamentals documentation (particularly the Tasks and Back Stack +href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back Stack document), which covers the underlying mechanics for programmers.

    @@ -189,7 +189,7 @@ document),

    An activity handles a particular type of content (data) and accepts a set of related user actions. Each activity has a - lifecycle that is + lifecycle that is independent of the other activities in its application or task — each activity is launched (started) independently, and the user or system can start, @@ -268,7 +268,7 @@ independent of the other An activity is the most prominent of four components of an application. The other components are service, content provider and broadcast receiver. For more details on activities, see the - Activities document. + Activities document.

    @@ -750,7 +750,7 @@ itself.

    For more about intents, see Intents and Intent Filters. +href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters.

    @@ -947,7 +947,7 @@ href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Fi 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 - intent filter with action + intent filter with action MAIN and category LAUNCHER.) 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 4b6768f5d8e58d5adc9631fca15441bd249d5745..28817fdd9282f193dd481a83ee9e03c93b4957cd 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd @@ -241,8 +241,8 @@ that launcher icons are legible across on any background color.

    Application Icons on Google Play

    -

    If you are publishing your application on -Google Play, you will also need to provide a 512 x 512 pixel, high-resolution application icon +

    If you are publishing your app on +Google Play, you will also need to provide a 512 x 512 pixel, high-resolution application icon in the developer console at upload time. This icon will be used in various locations on Google Play and does not replace your launcher icon.

    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 85a3cc8602429da3200dfced0083abf180c64142..f6c2247c2bbfbc221407fb6e167d1b874ed87ff2 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 @@ -58,7 +58,7 @@ suggestions on how to work with multiple sets of icons.

    Application Icons on Google Play

    -

    If you are publishing +

    If you are publishing your application on Google Play, you will also need to provide a 512x512 pixel, high-resolution application icon in the developer console at upload-time. diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd index d7894070e7006fc58c8a6da56d6fce7a15687f81..616f9aeb98e7433b9d9b2710ee30376633ab4de2 100644 --- a/docs/html/guide/practices/ui_guidelines/widget_design.jd +++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd @@ -229,7 +229,7 @@ in the Developer's Guide for information on how to achieve this with la practice to define this shape using nine patches; one for each screen density (see Supporting Multiple Screens for details). Nine-patches can be created with the draw9patch tool, or simply with a +href="{@docRoot}tools/help/draw9patch.html">draw9patch tool, or simply with a graphics editing program such as Adobe® Photoshop. This will allow the widget background shape to take up the entire available space. The nine-patch should be edge-to-edge with no transparent pixels providing extra margins, save for perhaps a few border pixels for subtle diff --git a/docs/html/guide/publishing/licensing.html b/docs/html/guide/publishing/licensing.html deleted file mode 100644 index 8e97f328da3c3365f523fee7c6fe21e40fef5417..0000000000000000000000000000000000000000 --- a/docs/html/guide/publishing/licensing.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -Redirecting... - - -

    You should have been redirected. Please click here.

    - - \ No newline at end of file diff --git a/docs/html/guide/topics/admin/index.jd b/docs/html/guide/topics/admin/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..b2a896f817c54ef72811b47ae80a2009e94f9d22 --- /dev/null +++ b/docs/html/guide/topics/admin/index.jd @@ -0,0 +1,22 @@ +page.title=Administration +page.landing=true +page.landing.intro=If you are an enterprise administrator, you can take advantage of APIs and system capabilities to manage Android devices and control access. +page.landing.image= + +@jd:body + + \ No newline at end of file diff --git a/docs/html/guide/topics/admin/keychain.jd b/docs/html/guide/topics/admin/keychain.jd new file mode 100644 index 0000000000000000000000000000000000000000..2ea24084e51b6227388265f1ca919dbc8dde3175 --- /dev/null +++ b/docs/html/guide/topics/admin/keychain.jd @@ -0,0 +1,4 @@ +page.title=Text and Input +@jd:body + +

    Add contnet here

    diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd index ba7b67c9770f03710772c0df520d8d176999a49f..a46f9a76f6ee5ed3f1886e805d4604f65df21553 100644 --- a/docs/html/guide/topics/appwidgets/index.jd +++ b/docs/html/guide/topics/appwidgets/index.jd @@ -295,7 +295,7 @@ Guidelines.

    Creating the App Widget layout is simple if you're familiar with XML Layouts. +href="{@docRoot}guide/topics/ui/declaring-layout.html">Layouts. 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.

    @@ -516,7 +516,7 @@ 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 +to an Application Not Responding (ANR) error. See the Wiktionary sample's AppWidgetProvider for an example of an App Widget running a {@link android.app.Service}.

    diff --git a/docs/html/guide/topics/wireless/bluetooth.jd b/docs/html/guide/topics/connectivity/bluetooth.jd similarity index 99% rename from docs/html/guide/topics/wireless/bluetooth.jd rename to docs/html/guide/topics/connectivity/bluetooth.jd index 0567799565e2db79739469e0c3c8f022653a7aa0..832b8506466cb97ea366ea9e5de7cda632971c89 100644 --- a/docs/html/guide/topics/wireless/bluetooth.jd +++ b/docs/html/guide/topics/connectivity/bluetooth.jd @@ -912,7 +912,7 @@ profiles:

    Bluetooth headsets to be used with mobile phones. Android provides the {@link android.bluetooth.BluetoothHeadset} class, which is a proxy for controlling the Bluetooth Headset Service via interprocess communication (IPCIPC). This includes both Bluetooth Headset and Hands-Free (v1.5) profiles. The {@link android.bluetooth.BluetoothHeadset} class includes support for AT commands. For more discussion of this topic, see Vendor-specific AT commands @@ -940,7 +940,7 @@ HDP, see Health Device Profile.
    1. Get the default adapter, as described in - Setting Up + Setting Up Bluetooth.
    2. Use {@link diff --git a/docs/html/guide/topics/connectivity/index.jd b/docs/html/guide/topics/connectivity/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..322518e6792966e7113c8d3145fd3f169daff8e3 --- /dev/null +++ b/docs/html/guide/topics/connectivity/index.jd @@ -0,0 +1,42 @@ +page.title=Connectivity +page.landing=true +page.landing.intro=Android provides rich APIs to let your app connect and interact with other devices over Bluetooth, NFC, Wi-Fi Direct, USB, and SIP, in addition to standard network connections. +page.landing.image=images/develop/connectivity.png + +@jd:body + + \ No newline at end of file diff --git a/docs/html/guide/topics/nfc/advanced-nfc.jd b/docs/html/guide/topics/connectivity/nfc/advanced-nfc.jd similarity index 98% rename from docs/html/guide/topics/nfc/advanced-nfc.jd rename to docs/html/guide/topics/connectivity/nfc/advanced-nfc.jd index b43b559678c7aa711c7ff1b2c0dd4fc0c9df9c9e..9d6cda51ab3471acc0214c43ee832c9f9f2f542e 100644 --- a/docs/html/guide/topics/nfc/advanced-nfc.jd +++ b/docs/html/guide/topics/connectivity/nfc/advanced-nfc.jd @@ -128,12 +128,12 @@ tag technologies are as follows:

      1. Filter for an {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent specifying the tag technologies that you want to handle. See Filtering for NFC +href="{@docRoot}guide/topics/connectivity/nfc/nfc.html#tech-disc">Filtering for NFC intents for more information. In general, the tag dispatch system tries to start a {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent when an NDEF message cannot be mapped to a MIME type or URI, or if the tag scanned did not contain NDEF data. For more information on how this is determined, see The Tag Dispatch System.
      2. +href="{@docRoot}guide/topics/connectivity/nfc/nfc.html#tag-dispatch">The Tag Dispatch System.
      3. When your application receives the intent, obtain the {@link android.nfc.Tag} object from the intent:
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
      4. diff --git a/docs/html/guide/topics/nfc/index.jd b/docs/html/guide/topics/connectivity/nfc/index.jd similarity index 90% rename from docs/html/guide/topics/nfc/index.jd rename to docs/html/guide/topics/connectivity/nfc/index.jd index b86d72d418d0e77e54e2ddab39ab5cfdd02fd28d..88c206f4958a2d470894de84404524527b8a1105 100644 --- a/docs/html/guide/topics/nfc/index.jd +++ b/docs/html/guide/topics/connectivity/nfc/index.jd @@ -15,13 +15,13 @@ page.title=Near Field Communication called NDEF (NFC Data Exchange Format).

        -
        NFC Basics
        +
        NFC Basics
        This document describes how Android handles discovered NFC tags and how it notifies applications of data that is relevant to the application. It also goes over how to work with the NDEF data in your applications and gives an overview of the framework APIs that support the basic NFC feature set of Android.
        -
        Advanced +
        Advanced NFC
        This document goes over the APIs that enable use of the various tag technologies that Android supports. When you are not working with NDEF data, or when you are working with NDEF diff --git a/docs/html/guide/topics/nfc/nfc.jd b/docs/html/guide/topics/connectivity/nfc/nfc.jd similarity index 98% rename from docs/html/guide/topics/nfc/nfc.jd rename to docs/html/guide/topics/connectivity/nfc/nfc.jd index 834656a9d5f57f080a6610e4adf79306386ed2b8..51c7bee04f26dc0c617323ef1ee20868ecf52560 100644 --- a/docs/html/guide/topics/nfc/nfc.jd +++ b/docs/html/guide/topics/connectivity/nfc/nfc.jd @@ -39,7 +39,7 @@ page.title=NFC Basics

        This document describes the basic NFC tasks you perform in Android. It explains how to send and receive NFC data in the form of NDEF messages and describes the Android framework APIs that support these features. For more advanced topics, including a discussion of working with non-NDEF data, -see Advanced NFC.

        +see Advanced NFC.

        There are two major uses cases when working with NDEF data and Android:

        @@ -105,7 +105,7 @@ or more records ({@link android.nfc.NdefRecord}). Each NDEF record must be well- the specification of the type of record that you want to create. Android also supports other types of tags that do not contain NDEF data, which you can work with by using the classes in the {@link android.nfc.tech} package. To learn more -about these technologies, see the Advanced +about these technologies, see the Advanced NFC topic. Working with these other types of tags involves writing your own protocol stack to communicate with the tags, so we recommend using NDEF when possible for ease of development and maximum support for Android-powered devices. @@ -454,7 +454,7 @@ within a tech-list set. Your activity is

        For more information about working with tag technologies and the {@link android.nfc.NfcAdapter#ACTION_TECH_DISCOVERED} intent, see Working with Supported Tag +href="{@docRoot}guide/topics/connectivity/nfc/advanced-nfc.html#tag-tech">Working with Supported Tag Technologies in the Advanced NFC document.

        ACTION_TAG_DISCOVERED

        To filter for {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED} use the following intent @@ -685,7 +685,7 @@ application based on the AAR.

        Note: You can override AARs and the intent dispatch system with the foreground dispatch +href="{@docRoot}guide/topics/connectivity/nfc/advanced-nfc.html#foreground-dispatch">foreground dispatch system, which allows a foreground activity to have priority when an NFC tag is discovered. With this method, the activity must be in the foreground to override AARs and the intent dispatch system.

        @@ -766,7 +766,7 @@ API level 14 (Android 4.0) and later.

        Note: If your activity enables Android Beam and is in the foreground, the standard intent dispatch system is disabled. However, if your activity also -enables foreground +enables foreground dispatching, then it can still scan tags that match the intent filters set in the foreground dispatching.

        diff --git a/docs/html/guide/topics/network/sip.jd b/docs/html/guide/topics/connectivity/sip.jd similarity index 98% rename from docs/html/guide/topics/network/sip.jd rename to docs/html/guide/topics/connectivity/sip.jd index 600da78ffcfbbbc069fbd4ac90ef044563194747..a5f0e2e49a26fc520559b446c5e6e209ab0de951 100644 --- a/docs/html/guide/topics/network/sip.jd +++ b/docs/html/guide/topics/connectivity/sip.jd @@ -140,7 +140,7 @@ manifest:

        • <uses-sdk android:minSdkVersion="9" />. This indicates that your application requires Android 2.3 or higher. For more -information, see API +information, see API Levels and the documentation for the <uses-sdk> element.
        • @@ -479,9 +479,9 @@ wireless, so you must test on an actual device. Testing on AVD won't work.
        • On your device, connect to wireless (Settings > Wireless & networks > Wi-Fi > Wi-Fi settings)
        • Set up your mobile device for testing, as described in Developing on a Device.
        • +href="{@docRoot}tools/device.html">Developing on a Device.
        • Run your application on your mobile device, as described in Developing on a Device.
        • +href="{@docRoot}tools/device.html">Developing on a Device.
        • If you are using Eclipse, you can view the application log output in Eclipse using LogCat (Window > Show View > Other > Android > diff --git a/docs/html/guide/topics/usb/accessory.jd b/docs/html/guide/topics/connectivity/usb/accessory.jd similarity index 99% rename from docs/html/guide/topics/usb/accessory.jd rename to docs/html/guide/topics/connectivity/usb/accessory.jd index 8b74bc0d6429fc63246e740eaab08ecebdf2a7a4..a2177678fc56dde241d9fecbf33b59e60c968133 100644 --- a/docs/html/guide/topics/usb/accessory.jd +++ b/docs/html/guide/topics/connectivity/usb/accessory.jd @@ -433,7 +433,7 @@ private void openAccessory() { protocol bundles the packets together for both speeds into one logical packet for simplicity.

          For more information about using threads in Android, see Processes and + "{@docRoot}guide/components/processes-and-threads.html#Threads">Processes and Threads.

          Terminating communication with an accessory

          diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/connectivity/usb/adk.jd similarity index 90% rename from docs/html/guide/topics/usb/adk.jd rename to docs/html/guide/topics/connectivity/usb/adk.jd index c8949a30bf48355427efd34a548cadc3aaf49794..034728cf9e2c4a7ac9684dce10b59670cecbe70b 100644 --- a/docs/html/guide/topics/usb/adk.jd +++ b/docs/html/guide/topics/connectivity/usb/adk.jd @@ -63,7 +63,7 @@ page.title=Android Open Accessory Development Kit
          1. Google I/O Session Video
          2. -
          3. USB Accessory Dev Guide
          4. +
          5. USB Accessory Dev Guide

          Where to buy

          @@ -121,7 +121,7 @@ page.title=Android Open Accessory Development Kit hardware and not all devices will support accessory mode. Devices that support accessory mode can be filtered using a <uses-feature> element in your corresponding application's Android manifest. For more information, see the USB Accessory Developer Guide.

          + "{@docRoot}guide/topics/connectivity/usb/accessory.html#manifest">USB Accessory Developer Guide.

          The following list of distributers are currently producing Android Open Accessory compatible development boards:

          @@ -168,7 +168,7 @@ page.title=Android Open Accessory Development Kit prototyping platform, the accessory's hardware design files, code that implements the accessory's firmware, and the Android application that interacts with the accessory. The hardware design files and firmware code are contained in the ADK package download.

          + "https://dl-ssl.google.com/android/adk/adk_release_20120606.zip">ADK package download.

          The main hardware and software components of the ADK include:

            @@ -190,18 +190,19 @@ page.title=Android Open Accessory Development Kit "http://www.circuitsathome.com/arduino_usb_host_shield_projects">Arduino USB Host Shield library provides the logic for the USB micro-controller board to act as a USB Host. This allows the board to initiate transactions with USB devices. Describing how to use this entire library - is out of the scope of this document. Where needed, this document points out important + is beyond the scope of this document. Where needed, this document points out important interactions with the library. For more information, see the source code for the Arduino USB - Host Shield library in the firmware/arduino_libs/USB_Host_Shield directory. + Host Shield library in the arduino_libs/USB_Host_Shield directory. -
          • An Arduino sketch, firmware/demokit/demokit.pde, defines the firmware that +
          • An Arduino sketch, arduino_libs/AndroidAccessory/examples/demokit/demokit.pde, + defines the firmware that runs on the ADK board and is written in C++. The sketch calls the Android accessory protocol library to interact with the Android-powered device. It also sends data from the ADK board and shield to the Android application and receives data from the Android application and outputs it to the ADK board and shield.
          • The Android accessory protocol library, which is located in the - firmware/arduino_libs/AndroidAccessory directory. This library defines how to + arduino_libs/AndroidAccessory directory. This library defines how to enumerate the bus, find a connected Android-powered device that supports accessory mode, and how to setup communication with the device.
          • @@ -228,20 +229,21 @@ page.title=Android Open Accessory Development Kit

            Getting Started with the ADK

            The following sections describe how to install the Arduino software on your computer, use the - Arduino software to install the ADK board's firmware, and install and run the accompanying + Arduino IDE to install the ADK board's firmware, and install and run the accompanying Android application for the ADK board. Before you begin, download the following items to set up your development environment:

              -
            • Arduino Software: contains libraries - and an IDE for coding and installing firmware to the ADK board.
            • +
            • Arduino 1.0 or higher: contains + libraries and an IDE for coding and installing firmware to the ADK board.
            • -
            • CapSense library: contains the - libraries to sense human capacitance. This is needed for the capacative button that is located - on the ADK shield.
            • +
            • CapSense library v.04: + contains the libraries to sense human capacitance. This library is needed for the capacitive + button that is located on the ADK shield.
            • -
            • The ADK package: contains the firmware for the ADK board and hardware design - files for the ADK board and shield.
            • +
            • ADK software + package: contains the firmware for the ADK board and hardware design files for the ADK + board and shield.

            Installing the Arduino software and necessary libraries

            @@ -250,35 +252,33 @@ page.title=Android Open Accessory Development Kit
            1. - Download and install the Arduino Software - as described on the Arduino website. + Download and install the Arduino 1.0 or + higher as described on the Arduino website.

              Note: If you are on a Mac, install the FTDI USB Serial Driver that is included in the Arduino package, even though the installation instructions say otherwise.

            2. -
            3. Download and +
            4. Download and extract the ADK package to a directory of your choice. You should have an app, - firmware, and hardware directories.
            5. + arduino_libs, and hardware directories. -
            6. Extract the CapSense download to a directory of your choice.
            7. +
            8. Download and extract + the CapSense package to a directory of your choice.
            9. Install the necessary libraries:

              On Windows:

                -
              1. Copy the firmware/arduino_libs/AndroidAccessory and - firmware/arduino_libs/USB_Host_Shield directories (the complete directories, +
              2. Copy the arduino_libs/AndroidAccessory and + arduino_libs/USB_Host_Shield directories (the complete directories, not just the files within) to the <arduino_installation_root>/libraries/ directory.
              3. -
              4. Create a CapSense directory in the - <arduino_installation_root>/libraries/ directory
              5. - -
              6. Copy CapSense.cpp and CapSense.h from the unzipped CapSense - download to the CapSense directory.
              7. +
              8. Copy the extracted CapSense/ library directory and its contents to the + <arduino_installation_root>/libraries/ directory.

              On Mac:

              @@ -288,16 +288,13 @@ page.title=Android Open Accessory Development Kit directory inside your user account's Documents directory, and within that, a libraries directory.
            10. -
            11. Copy the firmware/arduino_libs/AndroidAccessory and - firmware/arduino_libs/USB_Host_Shield directories (the +
            12. Copy the arduino_libs/AndroidAccessory and + arduino_libs/USB_Host_Shield directories (the complete directories, not just the files within) to your Documents/Arduino/libraries/ directory.
            13. -
            14. Create a CapSense directory in your - Documents/Arduino/libraries/ directory.
            15. - -
            16. Copy CapSense.cpp and CapSense.h from the unzipped CapSense - download to the CapSense directory.
            17. +
            18. Copy the extracted CapSense/ library directory and its contents to the + Documents/Arduino/libraries/ directory.

            On Linux (Ubuntu):

            @@ -308,19 +305,16 @@ page.title=Android Open Accessory Development Kit not just the files within) to the <arduino_installation_root>/libraries/ directory. -
          • Create a CapSense directory in the +
          • Copy the extracted CapSense/ library directory and its contents to the <arduino_installation_root>/libraries/ directory.
          • -
          • Copy CapSense.cpp and CapSense.h from the unzipped CapSense - download to the CapSense directory.
          • -
          • Install the avr-libc library by entering sudo apt-get install avr-libc from a shell prompt.
    -

    You should now have three new directories in the Arduino libraries directory: +

    You should now have three new directories in the Arduino libraries/ directory: AndroidAccessory, USB_Host_Shield, and CapSense.

    Installing the firmware to the ADK board

    @@ -331,7 +325,7 @@ page.title=Android Open Accessory Development Kit
  • Connect the ADK board to your computer using the micro-USB port, which allows two-way communication and provides power to the ADK board.
  • -
  • Launch Arduino.
  • +
  • Launch the Arduino IDE.
  • Click Tools > Board > Arduino Mega 2560 to specify the ADK board's type.
  • @@ -351,13 +345,13 @@ page.title=Android Open Accessory Development Kit -
  • To open the firmware code (a sketch), click File > Open and select - firmware/demokit/demokit.pde.
  • +
  • To open the Demokit sketch (firmware code), click File > Examples > + AndroidAccessory > demokit.
  • Click Sketch > Verify/Compile to ensure that the sketch has no errors.
  • -
  • Select File > Upload to I/O Board. When Arduino outputs Done +
  • Select File > Upload. When Arduino outputs Done uploading., the board is ready to communicate with your Android-powered device.
  • @@ -375,7 +369,7 @@ page.title=Android Open Accessory Development Kit 2.3.4 devices that support accessory mode. This library is also forward compatible with Android 3.1 or newer devices that support accessory mode. If you only care about Android 3.1 or newer devices, all you need is API Level 12. For more information on deciding which API level to use, - see the USB Accessory + see the USB Accessory documentation.
  • Click File > New > Project..., then select Android > @@ -414,12 +408,12 @@ page.title=Android Open Accessory Development Kit

    Monitoring the ADK Board

    The ADK firmware consists of a few files that you should be looking at if you want to build - your own accessory. The files in the firmware/arduino_libs/AndroidAccessory + your own accessory. The files in the arduino_libs/AndroidAccessory directory are the most important files and have the logic to detect and connect to Android-powered devices that support accessory mode. Feel free to add debug statements (Arduino - Serial.print() statements) to the code located in the - arduino_libraries_directory/AndroidAccessory directory and - firmware/demokit/demokit.pde sketch and re-upload the sketch to the ADK board to + Serial.println() statements) to the code located in the + <arduino_installation_root>/libraries/AndroidAccessory directory and + demokit.pde sketch and re-upload the sketch to the ADK board to discover more about how the firmware works.

    You can view the debug statements in the Arduino Serial Monitor by clicking Tools > @@ -575,11 +569,11 @@ data: none useful if you want to port the code over for your own accessories.

    The important pieces of the firmware are the - accessory/demokit/demokit/demokit.pde sketch, which is the code that receives and - sends data to the DemoKit application running on the Android-powered device. The code to detect - and set up communication with the Android-powered device is contained in the - accessory/arduino_libs/AndroidAccessory/AndroidAccessory.h and - accessory/arduino_libs/AndroidAccessory/AndroidAccessory.cpp files. This code + arduino_libs/AndroidAccessory/examples/demokit/demokit/demokit.pde sketch, which is + the code that receives and sends data to the DemoKit application running on the Android-powered + device. The code to detect and set up communication with the Android-powered device is contained + in the arduino_libs/AndroidAccessory/AndroidAccessory.h and + arduino_libs/AndroidAccessory/AndroidAccessory.cpp files. This code includes most of the logic that will help you implement your own accessory's firmware. It might be useful to have all three of these files open in a text editor as you read through these next sections.

    @@ -909,8 +903,7 @@ int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit) { int AndroidAccessory::write(void *buff, int len) { usb.outTransfer(1, out, len, (char *)buff); return len; } - -

    See the firmware/demokit/demokit.pde file for information about how the ADK board +

    See the demokit.pde sketch for information about how the ADK board reads and writes data.

    diff --git a/docs/html/guide/topics/usb/host.jd b/docs/html/guide/topics/connectivity/usb/host.jd similarity index 99% rename from docs/html/guide/topics/usb/host.jd rename to docs/html/guide/topics/connectivity/usb/host.jd index b561754451595036d34927f963de7134c2f54818..355dd2dd91993d43889f6cb456e1fb017544bf0a 100644 --- a/docs/html/guide/topics/usb/host.jd +++ b/docs/html/guide/topics/connectivity/usb/host.jd @@ -380,7 +380,7 @@ mUsbManager.requestPermission(device, mPermissionIntent); android.hardware.usb.UsbDeviceConnection#controlTransfer controlTransfer()} method. You should carry out this step in another thread to prevent blocking the main UI thread. For more information about using threads in Android, see Processes and + "{@docRoot}guide/components/processes-and-threads.html#Threads">Processes and Threads.
  • diff --git a/docs/html/guide/topics/usb/index.jd b/docs/html/guide/topics/connectivity/usb/index.jd similarity index 89% rename from docs/html/guide/topics/usb/index.jd rename to docs/html/guide/topics/connectivity/usb/index.jd index ef53bdf7c5db7068bd459d7750f997900e04ef06..7086ab199d6ebca3f15309b20ef3ff17ae90e02e 100644 --- a/docs/html/guide/topics/usb/index.jd +++ b/docs/html/guide/topics/connectivity/usb/index.jd @@ -6,9 +6,9 @@ page.title=USB Host and Accessory

    Topics

      -
    1. USB Accessory
    2. +
    3. USB Accessory
    4. -
    5. USB Host
    6. +
    7. USB Host
    @@ -42,8 +42,8 @@ page.title=USB Host and Accessory dependant on the device's hardware, regardless of platform level. You can filter for devices that support USB host and accessory through a <uses-feature> element. See - the USB accessory and host documentation for more details.

    + the USB accessory and host documentation for more details.

    Debugging considerations

    diff --git a/docs/html/guide/topics/wireless/wifip2p.jd b/docs/html/guide/topics/connectivity/wifip2p.jd similarity index 100% rename from docs/html/guide/topics/wireless/wifip2p.jd rename to docs/html/guide/topics/connectivity/wifip2p.jd diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd index d91e422a2388440506e9ec56b13741899ee6d688..602b6e84b225c86eae36c656eeec52f3bfd4f5c9 100644 --- a/docs/html/guide/topics/data/backup.jd +++ b/docs/html/guide/topics/data/backup.jd @@ -47,7 +47,7 @@ data onto the new device

    See also

      -
    1. {@code bmgr} tool
    2. +
    3. {@code bmgr} tool
    @@ -316,7 +316,7 @@ backup for all applications that have requested a backup since the last backup w

    Tip: While developing your application, you can initiate an immediate backup operation from the Backup Manager with the {@code bmgr} tool.

    +href="{@docRoot}tools/help/bmgr.html">{@code bmgr} tool.

    When the Backup Manager calls your {@link android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) @@ -460,7 +460,7 @@ android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore( href="#RequestingRestore">Requesting restore for more information).

    Note: While developing your application, you can also request a -restore operation with the {@code bmgr} +restore operation with the {@code bmgr} tool.

    When the Backup Manager calls your {@link @@ -863,7 +863,7 @@ onBackup()}.

    Note: While developing your application, you can request a backup and initiate an immediate backup operation with the {@code bmgr} +href="{@docRoot}tools/help/bmgr.html">{@code bmgr} tool.

    @@ -878,7 +878,7 @@ android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescripto 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} +restore operation with the {@code bmgr} tool.

    @@ -886,7 +886,7 @@ tool.

    Once you've implemented your backup agent, you can test the backup and restore functionality with the following procedure, using {@code bmgr}.

    +href="{@docRoot}tools/help/bmgr.html">{@code bmgr}.

    1. Install your application on a suitable Android system image diff --git a/docs/html/guide/topics/data/data-storage.jd b/docs/html/guide/topics/data/data-storage.jd index d31afa554c5e88e1a7955128f12f80e6ee8812e6..e9d2d25eefb72ef649525ae6f554cfbc301a5f2d 100644 --- a/docs/html/guide/topics/data/data-storage.jd +++ b/docs/html/guide/topics/data/data-storage.jd @@ -1,4 +1,4 @@ -page.title=Data Storage +page.title=Storage Options @jd:body @@ -16,22 +16,9 @@ page.title=Data Storage

      In this document

      1. Using Shared Preferences
      2. -
      3. Using the Internal Storage -
          -
        1. Saving cache files
        2. -
        3. Other useful methods
        4. -
      4. -
      5. Using the External Storage -
          -
        1. Checking media availability
        2. -
        3. Accessing files on external storage
        4. -
        5. Saving files that should be shared
        6. -
        7. Saving cache files
        8. -
      6. -
      7. Using Databases -
          -
        1. Database debugging
        2. -
      8. +
      9. Using the Internal Storage
      10. +
      11. Using the External Storage
      12. +
      13. Using Databases
      14. Using a Network Connection
      @@ -449,7 +436,7 @@ applications.

      The Android SDK includes a {@code sqlite3} database tool that allows you to browse table contents, run SQL commands, and perform other useful functions on SQLite -databases. See Examining sqlite3 +databases. See Examining sqlite3 databases from a remote shell to learn how to run this tool.

      diff --git a/docs/html/guide/topics/data/index.html b/docs/html/guide/topics/data/index.html deleted file mode 100644 index a94f8c0b2fe8f59b7a094c6fa04b187d33af5cdf..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/data/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -Redirecting... - - -click here if you are not redirected. - - \ No newline at end of file diff --git a/docs/html/guide/topics/data/index.jd b/docs/html/guide/topics/data/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..1e082b3fef95fd6bc53c75db6fde12e294d86782 --- /dev/null +++ b/docs/html/guide/topics/data/index.jd @@ -0,0 +1,23 @@ +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.image= + +@jd:body + + \ No newline at end of file diff --git a/docs/html/guide/topics/data/install-location.jd b/docs/html/guide/topics/data/install-location.jd new file mode 100644 index 0000000000000000000000000000000000000000..19c4b3900ef124684a48a646b853d6ea759a9b70 --- /dev/null +++ b/docs/html/guide/topics/data/install-location.jd @@ -0,0 +1,206 @@ +page.title=App Install Location +@jd:body + + +
      +
      + +

      Quickview

      +
        +
      • You can allow your application to install on the device's external storage.
      • +
      • Some types of applications should not allow installation on the external +storage.
      • +
      • Installing on the external storage is ideal for large applications that are not tightly +integrated with the system (most commonly, games).
      • +
      + +

      In this document

      +
        +
      1. Backward Compatibility
      2. +
      3. Applications That Should NOT Install on External Storage
      4. +
      5. Applications That Should Install on External Storage
      6. +
      + +

      See also

      +
        +
      1. +<manifest>
      2. +
      + +
      +
      + +

      Beginning with API Level 8, you can allow your application to be installed on the +external storage (for example, the device's SD card). This is an optional feature you can declare +for your application with the {@code +android:installLocation} manifest attribute. If you do +not declare this attribute, your application will be installed on the internal storage +only and it cannot be moved to the external storage.

      + +

      To allow the system to install your application on the external storage, modify your +manifest file to include the {@code +android:installLocation} attribute in the <manifest> element, +with a value of either "{@code preferExternal}" or "{@code auto}". For example:

      + +
      +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      +    android:installLocation="preferExternal"
      +    ... >
      +
      + +

      If you declare "{@code preferExternal}", you request that your application be installed on the +external storage, but the system does not guarantee that your application will be installed on +the external storage. If the external storage is full, the system will install it on the internal +storage. The user can also move your application between the two locations.

      + +

      If you declare "{@code auto}", you indicate that your application may be installed on the +external storage, but you don't have a preference of install location. The system will +decide where to install your application based on several factors. The user can also move your +application between the two locations.

      + +

      When your application is installed on the external storage:

      +
        +
      • There is no effect on the application performance so long +as the external storage is mounted on the device.
      • +
      • The {@code .apk} file is saved on the external storage, but all private user data, +databases, optimized {@code .dex} files, and extracted native code are saved on the +internal device memory.
      • +
      • The unique container in which your application is stored is encrypted with a randomly +generated key that can be decrypted only by the device that originally installed it. Thus, an +application installed on an SD card works for only one device.
      • +
      • The user can move your application to the internal storage through the system settings.
      • +
      + +

      Warning: When the user enables USB mass storage to share files +with a computer or unmounts the SD card via the system settings, the external storage is unmounted +from the device and all applications running on the external storage are immediately killed.

      + + + +

      Backward Compatibility

      + +

      The ability for your application to install on the external storage is a feature available only +on devices running API Level 8 (Android 2.2) or greater. Existing applications that were built prior +to API Level 8 will always install on the internal storage and cannot be moved to the external +storage (even on devices with API Level 8). However, if your application is designed to support an +API Level lower than 8, you can choose to support this feature for devices with API Level 8 +or greater and still be compatible with devices using an API Level lower than 8.

      + +

      To allow installation on external storage and remain compatible with versions lower than API +Level 8:

      +
        +
      1. Include the {@code android:installLocation} attribute with a value of "{@code auto}" or +"{@code preferExternal}" in the <manifest> +element.
      2. +
      3. Leave your {@code android:minSdkVersion} attribute as is (something less +than "8") and be certain that your application code uses only APIs compatible with that +level.
      4. +
      5. In order to compile your application, change your build target to API Level 8. This is +necessary because older Android libraries don't understand the {@code android:installLocation} +attribute and will not compile your application when it's present.
      6. +
      + +

      When your application is installed on a device with an API Level lower than 8, the {@code +android:installLocation} attribute is ignored and the application is installed on the internal +storage.

      + +

      Caution: Although XML markup such as this will be ignored by +older platforms, you must be careful not to use programming APIs introduced in API Level 8 +while your {@code minSdkVersion} is less than "8", unless you perform the work necessary to +provide backward compatibility in your code. For information about building +backward compatibility in your application code, see the Backward Compatibility +article.

      + + + +

      Applications That Should NOT Install on External Storage

      + +

      When the user enables USB mass storage to share files with their computer (or otherwise +unmounts or removes the external storage), any application +installed on the external storage and currently running is killed. The system effectively becomes +unaware of the application until mass storage is disabled and the external storage is +remounted on the device. Besides killing the application and making it unavailable to the user, +this can break some types of applications in a more serious way. In order for your application to +consistently behave as expected, you should not allow your application to be +installed on the external storage if it uses any of the following features, due to the cited +consequences when the external storage is unmounted:

      + +
      +
      Services
      +
      Your running {@link android.app.Service} will be killed and will not be restarted when +external storage is remounted. You can, however, register for the {@link +android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE} broadcast Intent, which will notify +your application when applications installed on external storage have become available to the +system again. At which time, you can restart your Service.
      +
      Alarm Services
      +
      Your alarms registered with {@link android.app.AlarmManager} will be cancelled. You must +manually re-register any alarms when external storage is remounted.
      +
      Input Method Engines
      +
      Your IME will be +replaced by the default IME. When external storage is remounted, the user can open system settings +to enable your IME again.
      +
      Live Wallpapers
      +
      Your running Live Wallpaper +will be replaced by the default Live Wallpaper. When external storage is remounted, the user can +select your Live Wallpaper again.
      +
      Live Folders
      +
      Your Live Folder will be +removed from the home screen. When external storage is remounted, the user can add your Live Folder +to the home screen again.
      +
      App Widgets
      +
      Your App Widget will be removed +from the home screen. When external storage is remounted, your App Widget will not be +available for the user to select until the system resets the home application (usually not until a +system reboot).
      +
      Account Managers
      +
      Your accounts created with {@link android.accounts.AccountManager} will disappear until +external storage is remounted.
      +
      Sync Adapters
      +
      Your {@link android.content.AbstractThreadedSyncAdapter} and all its sync functionality will +not work until external storage is remounted.
      +
      Device Administrators
      +
      Your {@link android.app.admin.DeviceAdminReceiver} and all its admin capabilities will +be disabled, which can have unforeseeable consequences for the device functionality, which may +persist after external storage is remounted.
      +
      Broadcast Receivers listening for "boot completed"
      +
      The system delivers the {@link android.content.Intent#ACTION_BOOT_COMPLETED} broadcast +before the external storage is mounted to the device. If your application is installed on the +external storage, it can never receive this broadcast.
      +
      Copy Protection
      +
      Your application cannot be installed to a device's SD card if it uses Google Play's + Copy Protection feature. However, if you use Google Play's + Application Licensing instead, your + application can be installed to internal or external storage, including SD cards.
      +
      + +

      If your application uses any of the features listed above, you should not allow +your application to install on external storage. By default, the system will not allow your +application to install on the external storage, so you don't need to worry about your existing +applications. However, if you're certain that your application should never be installed on the +external storage, then you should make this clear by declaring {@code +android:installLocation} with a value of "{@code internalOnly}". Though this does not +change the default behavior, it explicitly states that your application should only be installed +on the internal storage and serves as a reminder to you and other developers that this decision has +been made.

      + + +

      Applications That Should Install on External Storage

      + +

      In simple terms, anything that does not use the features listed in the previous section +are safe when installed on external storage. Large games are more commonly the types of +applications that should allow installation on external storage, because games don't typically +provide additional services when inactive. When external storage becomes unavailable and a game +process is killed, there should be no visible effect when the storage becomes available again and +the user restarts the game (assuming that the game properly saved its state during the normal +Activity lifecycle).

      + +

      If your application requires several megabytes for the APK file, you should +carefully consider whether to enable the application to install on the external storage so that +users can preserve space on their internal storage.

      + diff --git a/docs/html/guide/topics/drawing/index.html b/docs/html/guide/topics/drawing/index.html deleted file mode 100644 index 43c14994df239d6d479f92bf8b391fe3ab98ecbf..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/drawing/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -Redirecting... - - -click here if you are not redirected. - - \ No newline at end of file diff --git a/docs/html/guide/topics/drawing/opengl.jd b/docs/html/guide/topics/drawing/opengl.jd deleted file mode 100644 index e22a251f696272fca5c262a33e7e0fdc68add02e..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/drawing/opengl.jd +++ /dev/null @@ -1,53 +0,0 @@ -page.title=OpenGL -@jd:body - -

      Android includes support for 3D hardware acceleration. This functionality is -accessed via the OpenGL API — specifically, the OpenGL ES API.

      - -

      OpenGL ES is a flavor of the OpenGL specification intended for embedded -devices. Versions of OpenGL ES are loosely peered to versions of the primary -OpenGL standard. Android currently supports OpenGL ES 1.0, which corresponds -to OpenGL 1.3. So, if the application you have in mind is possible with OpenGL -1.3 on a desktop system, it should be possible on Android.

      - -

      The specific API provided by Android is similar to the J2ME JSR239 OpenGL -ES API. However, it may not be identical, so watch out for deviations.

      - -

      Using the API

      - -

      Here's how to use the API at an extremely high level:

      - -
        -
      1. Write a custom View subclass.
      2. -
      3. Obtain a handle to an OpenGLContext, which provides access to the OpenGL functionality.
      4. -
      5. In your View's onDraw() method, get a handle to a GL object, and use its methods to perform GL operations.
      6. -
      - -

      For an example of this usage model (based on the classic GL ColorCube), -see -com.android.samples.graphics.GLView1.java -in the ApiDemos sample code project. A slightly more sophisticated version showing how to use -it with threads can be found in -com.android.samples.graphics.GLSurfaceViewActivity.java. -

      - -

      Writing a summary of how to actually write 3D applications using OpenGL is -beyond the scope of this text and is left as an exercise for the reader.

      - -

      Links to Additional Information

      - -

      Information about OpenGL ES can be -found at http://www.khronos.org/opengles/.

      - -

      Information specifically -about OpenGL ES 1.0 (including a detailed specification) can be found -at http://www.khronos.org/opengles/1_X/.

      - -

      The documentation for the Android {@link javax.microedition.khronos.opengles.GL -OpenGL ES implementations} are also available.

      - -

      Finally, note that though Android does include some basic support for -OpenGL ES 1.1, the support is not complete, and should not be relied -upon at this time.

      diff --git a/docs/html/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd index 5cf1a59b22328d09595d12e876cbd58fbbd6e0c2..d842cb9e611d5dca633d77d7926702c1fe54da9c 100644 --- a/docs/html/guide/topics/graphics/2d-graphics.jd +++ b/docs/html/guide/topics/graphics/2d-graphics.jd @@ -476,7 +476,7 @@ allowed. do.

      -

      The Draw 9-patch tool offers +

      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. diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd deleted file mode 100644 index 561369d2fe862debd450029de6249a70162710b3..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/graphics/animation.jd +++ /dev/null @@ -1,64 +0,0 @@ -page.title=Animation -@jd:body - -

      - -

      The Android framework provides two animation systems: property animation - (introduced in Android 3.0) and view animation. Both animation systems are viable options, - but the property animation system, in general, is the preferred method to use, because it - is more flexible and offers more features. In addition to these two systems, you can utilize Drawable -animation, which allows you to load drawable resources and display them one frame after -another.

      - -

      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 -exposes a few aspects of a {@link android.view.View} object to animate, such as the scaling and -rotation of a View but not the background color, for instance.

      - -

      Another disadvantage of the view animation system is that it only modified where the - View was drawn, and not the actual View itself. For instance, if you animated a button to move - across the screen, the button draws correctly, but the actual location where you can click the - button does not change, so you have to implement your own logic to handle this.

      - -

      With the property animation system, these constraints are completely removed, and you can animate - any property of any object (Views and non-Views) and the object itself is actually modified. - The property animation system is also more robust in the way it carries out animation. At - a high level, you assign animators to the properties that you want to animate, such as color, - position, or size and can define aspects of the animation such as interpolation and - synchronization of multiple animators.

      - -

      The view animation system, however, takes less time to setup and requires less code to write. - If view animation accomplishes everything that you need to do, or if your existing code already - works the way you want, there is no need to use the property animation system. It also might - make sense to use both animation systems for different situations if the use case arises.

      - -
      -
      Property -Animation
      -
      Introduced in Android 3.0 (API level 11), the property animation system lets you -animate properties of any object, including ones that are not rendered to the screen. The system is -extensible and lets you animate properties of custom types as well.
      - -
      View -Animation
      -
      View Animation is the older system and can only be used for Views. It is relatively easy to -setup and offers enough capabilities to meet many application's needs.
      -
      - -
      Drawable -Animation
      -
      Drawable animation involves displaying {@link android.graphics.drawable.Drawable} resources one -after another, like a roll of film. This method of animation is useful if you want to animate -things that are easier to represent with Drawable resources, such as a progression of bitmaps.
      diff --git a/docs/html/guide/topics/graphics/index.jd b/docs/html/guide/topics/graphics/index.jd index ab623c26910004a6e13a5b012a43d30e9e4ccaa5..17f630994952f6ccb3443e6cf9d1b50db32b4e55 100644 --- a/docs/html/guide/topics/graphics/index.jd +++ b/docs/html/guide/topics/graphics/index.jd @@ -1,51 +1,49 @@ -page.title=Graphics -@jd:body - - - -

      When writing an application, it's important to consider exactly what your graphical demands will be. -Varying graphical tasks are best accomplished with varying techniques. For example, graphics and animations -for a rather static application should be implemented much differently than graphics and animations -for an interactive game. Here, we'll discuss a few of the options you have for drawing graphics -on Android and which tasks they're best suited for. -

      +page.title=Animation and Graphics +page.landing=true +page.landing.intro=Make your apps look and perform their best using Android's powerful graphics features such as OpenGL, hardware acceleration, and built-in UI animations. +page.landing.image= -
      -
      Canvas and -Drawables
      -
      Android provides a set of {@link android.view.View} widgets that provide general functionality -for a wide array of user interfaces. You can also extend these widgets to modify the way they -look or behave. In addition, you can do your own custom 2D rendering using the various drawing -methods contained in the {@link android.graphics.Canvas} class or create {@link -android.graphics.drawable.Drawable} objects for things such as textured buttons or frame-by-frame -animations.
      +@jd:body -
      Hardware -Acceleration
      -
      Beginning in Android 3.0, you can hardware accelerate the majority of -the drawing done by the Canvas APIs to further increase their performance.
      +
      -
      OpenGL
      -
      Android supports OpenGL ES 1.0 and 2.0, with Android framework APIs as well as natively -with the Native Development Kit (NDK). Using the framework APIs is desireable when you want to add a -few graphical enhancements to your application that are not supported with the Canvas APIs, or if -you desire platform independence and don't demand high performance. There is a performance hit in -using the framework APIs compared to the NDK, so for many graphic intensive applications such as -games, using the NDK is beneficial (It is important to note though that you can still get adequate -performance using the framework APIs. For example, the Google Body app is developed entirely -using the framework APIs). OpenGL with the NDK is also useful if you have a lot of native -code that you want to port over to Android. For more information about using the NDK, read the -docs in the docs/ directory of the NDK -download.
      -
      + + + \ No newline at end of file diff --git a/docs/html/guide/topics/graphics/opengl.jd b/docs/html/guide/topics/graphics/opengl.jd index a786d4282d6fbac62186cca74462822c8764f2a8..a9fedb708228438597aa765625f1e5dc810a9abb 100644 --- a/docs/html/guide/topics/graphics/opengl.jd +++ b/docs/html/guide/topics/graphics/opengl.jd @@ -20,6 +20,7 @@ parent.link=index.html
    2. Projection and camera in ES 2.0
    +
  • Shape Faces and Winding
  • OpenGL Versions and Device Compatibility
    1. Texture compression support
    2. @@ -33,11 +34,6 @@ parent.link=index.html
    3. {@link android.opengl.GLSurfaceView}
    4. {@link android.opengl.GLSurfaceView.Renderer}
    -

    Related tutorials

    -
      -
    1. OpenGL ES 1.0
    2. -
    3. OpenGL ES 2.0
    4. -

    Related samples

    1. GLSurfaceViewActivity
    2. @@ -48,8 +44,8 @@ href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics

    See also

      -
    1. Introducing -GLSurfaceView
    2. +
    3. + Displaying Graphics with OpenGL ES
    4. OpenGL ES
    5. OpenGL ES 1.x Specification
    6. OpenGL ES 2.x specification
    7. @@ -73,7 +69,7 @@ OpenGL ES 2.0 API specification.

      Android supports OpenGL both through its framework API and the Native Development Kit (NDK). This topic focuses on the Android framework interfaces. For more information about the -NDK, see the Android NDK. +NDK, see the Android NDK.

      There are two foundational classes in the Android framework that let you create and manipulate graphics with the OpenGL ES API: {@link android.opengl.GLSurfaceView} and {@link @@ -389,6 +385,43 @@ objects to be rendered by OpenGL. href="{@docRoot}resources/tutorials/opengl/opengl-es20.html#projection-and-views">OpenGL ES 2.0 tutorial.

      +

      Shape Faces and Winding

      + +

      In OpenGL, the face of a shape is a surface defined by three or more points in three-dimensional +space. A set of three or more three-dimensional points (called vertices in OpenGL) have a front face +and a back face. How do you know which face is front and which is the back? Good question. The +answer has to do with winding, or, the direction in which you define the points of a shape.

      + + +

      + Figure 1. Illustration of a coordinate list which translates into a +counterclockwise drawing order.

      + +

      In this example, the points of the triangle are defined in an order such that they are drawn in a +counterclockwise direction. The order in which these coordinates are drawn defines the winding +direction for the shape. By default, in OpenGL, the face which is drawn counterclockwise is the +front face. The triangle shown in Figure 1 is defined so that you are looking at the front face of +the shape (as interpreted by OpenGL) and the other side is the back face.

      + +

      Why is it important to know which face of a shape is the front face? The answer has to do with a +commonly used feature of OpenGL, called face culling. Face culling is an option for the OpenGL +environment which allows the rendering pipeline to ignore (not calculate or draw) the back face of a +shape, saving time, memory and processing cycles:

      + +
      +// enable face culling feature
      +gl.glEnable(GL10.GL_CULL_FACE);
      +// specify which faces to not draw
      +gl.glCullFace(GL10.GL_BACK);
      +
      + +

      If you try to use the face culling feature without knowing which sides of your shapes are the +front and back, your OpenGL graphics are going to look a bit thin, or possibly not show up at all. +So, always define the coordinates of your OpenGL shapes in a counterclockwise drawing order.

      + +

      Note: It is possible to set an OpenGL environment to treat the +clockwise face as the front face, but doing so requires more code and is likely to confuse +experienced OpenGL developers when you ask them for help. So don’t do that.

      OpenGL Versions and Device Compatibility

      @@ -410,7 +443,8 @@ texture compression, see the CompressedTextureActivity code sample.

      -

      To check if the ETC1 format is supported on a device, call the {@link +

      The ETC format is supported by most Android devices, but it not guarranteed to be available. To +check if the ETC1 format is supported on a device, call the {@link android.opengl.ETC1Util#isETC1Supported() ETC1Util.isETC1Supported()} method.

      Note: The ETC1 texture compression format does not support textures with an diff --git a/docs/html/guide/topics/graphics/overview.jd b/docs/html/guide/topics/graphics/overview.jd new file mode 100644 index 0000000000000000000000000000000000000000..a53cd3f15936c4086bf636f582ffb5ae33184165 --- /dev/null +++ b/docs/html/guide/topics/graphics/overview.jd @@ -0,0 +1,73 @@ +page.title=Animation and Graphics Overview +@jd:body + +

      Android provides a variety of powerful APIs for applying animation to UI elements and drawing custom + 2D and 3D graphics. The sections below provide an overview of the APIs and system capabilities available + and help you decide with approach is best for your needs.

      + +

      Animation

      + +

      The Android framework provides two animation systems: property animation + (introduced in Android 3.0) and view animation. Both animation systems are viable options, + but the property animation system, in general, is the preferred method to use, because it + is more flexible and offers more features. In addition to these two systems, you can utilize Drawable + animation, which allows you to load drawable resources and display them one frame after + another.

      + +
      +
      Property +Animation
      +
      Introduced in Android 3.0 (API level 11), the property animation system lets you +animate properties of any object, including ones that are not rendered to the screen. The system is +extensible and lets you animate properties of custom types as well.
      + +
      View +Animation
      +
      View Animation is the older system and can only be used for Views. It is relatively easy to +setup and offers enough capabilities to meet many application's needs.
      +
      + +
      Drawable +Animation
      +
      Drawable animation involves displaying {@link android.graphics.drawable.Drawable} resources one +after another, like a roll of film. This method of animation is useful if you want to animate +things that are easier to represent with Drawable resources, such as a progression of bitmaps.
      + +

      2D and 3D Graphics

      + +

      When writing an application, it's important to consider exactly what your graphical demands will be. +Varying graphical tasks are best accomplished with varying techniques. For example, graphics and animations +for a rather static application should be implemented much differently than graphics and animations +for an interactive game. Here, we'll discuss a few of the options you have for drawing graphics +on Android and which tasks they're best suited for. +

      + +
      +
      Canvas and +Drawables
      +
      Android provides a set of {@link android.view.View} widgets that provide general functionality +for a wide array of user interfaces. You can also extend these widgets to modify the way they +look or behave. In addition, you can do your own custom 2D rendering using the various drawing +methods contained in the {@link android.graphics.Canvas} class or create {@link +android.graphics.drawable.Drawable} objects for things such as textured buttons or frame-by-frame +animations.
      + +
      Hardware +Acceleration
      +
      Beginning in Android 3.0, you can hardware accelerate the majority of +the drawing done by the Canvas APIs to further increase their performance.
      + +
      OpenGL
      +
      Android supports OpenGL ES 1.0 and 2.0, with Android framework APIs as well as natively +with the Native Development Kit (NDK). Using the framework APIs is desireable when you want to add a +few graphical enhancements to your application that are not supported with the Canvas APIs, or if +you desire platform independence and don't demand high performance. There is a performance hit in +using the framework APIs compared to the NDK, so for many graphic intensive applications such as +games, using the NDK is beneficial (It is important to note though that you can still get adequate +performance using the framework APIs. For example, the Google Body app is developed entirely +using the framework APIs). OpenGL with the NDK is also useful if you have a lot of native +code that you want to port over to Android. For more information about using the NDK, read the +docs in the docs/ directory of the NDK +download.
      +
      + diff --git a/docs/html/guide/topics/graphics/prop-animation.jd b/docs/html/guide/topics/graphics/prop-animation.jd index be24788ea760a1e442955cbc511e2e961a3e2fe7..b733624a8727360bde0b6473225a834c2c893e8d 100644 --- a/docs/html/guide/topics/graphics/prop-animation.jd +++ b/docs/html/guide/topics/graphics/prop-animation.jd @@ -166,6 +166,31 @@ parent.link=animation.html "{@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 + exposes a few aspects of a {@link android.view.View} object to animate, such as the scaling and + rotation of a View but not the background color, for instance.

      + +

      Another disadvantage of the view animation system is that it only modified where the + View was drawn, and not the actual View itself. For instance, if you animated a button to move + across the screen, the button draws correctly, but the actual location where you can click the + button does not change, so you have to implement your own logic to handle this.

      + +

      With the property animation system, these constraints are completely removed, and you can animate + any property of any object (Views and non-Views) and the object itself is actually modified. + The property animation system is also more robust in the way it carries out animation. At + a high level, you assign animators to the properties that you want to animate, such as color, + position, or size and can define aspects of the animation such as interpolation and + synchronization of multiple animators.

      + +

      The view animation system, however, takes less time to setup and requires less code to write. + If view animation accomplishes everything that you need to do, or if your existing code already + works the way you want, there is no need to use the property animation system. It also might + make sense to use both animation systems for different situations if the use case arises.

      API Overview

      diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/graphics/renderscript/compute.jd similarity index 100% rename from docs/html/guide/topics/renderscript/compute.jd rename to docs/html/guide/topics/graphics/renderscript/compute.jd diff --git a/docs/html/guide/topics/renderscript/graphics.jd b/docs/html/guide/topics/graphics/renderscript/graphics.jd similarity index 99% rename from docs/html/guide/topics/renderscript/graphics.jd rename to docs/html/guide/topics/graphics/renderscript/graphics.jd index 462a9904faaae748db684d22592c65b867351456..58676ea99fe35bd128d0178925e15cd6b5f72d1e 100644 --- a/docs/html/guide/topics/renderscript/graphics.jd +++ b/docs/html/guide/topics/graphics/renderscript/graphics.jd @@ -46,7 +46,8 @@ parent.link=index.html
    8. FountainFbo
    9. -
    10. Hello World
    11. +
    12. Hello +World
    13. Misc Samples
    14. diff --git a/docs/html/guide/topics/renderscript/index.jd b/docs/html/guide/topics/graphics/renderscript/index.jd similarity index 100% rename from docs/html/guide/topics/renderscript/index.jd rename to docs/html/guide/topics/graphics/renderscript/index.jd diff --git a/docs/html/guide/topics/renderscript/reference.jd b/docs/html/guide/topics/graphics/renderscript/reference.jd similarity index 100% rename from docs/html/guide/topics/renderscript/reference.jd rename to docs/html/guide/topics/graphics/renderscript/reference.jd diff --git a/docs/html/guide/topics/intents/index.html b/docs/html/guide/topics/intents/index.html deleted file mode 100644 index b831246ad7b631fb19b2198745eff31a5ccb6841..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/intents/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -Redirecting... - - -click here if you are not redirected. - - \ No newline at end of file diff --git a/docs/html/guide/topics/location/index.jd b/docs/html/guide/topics/location/index.jd index 8a2e9cdb2bae0321e9ab90e1f7652d9a6dd78672..54c034d9cd13f56d327250d91094cb2b0299f92d 100644 --- a/docs/html/guide/topics/location/index.jd +++ b/docs/html/guide/topics/location/index.jd @@ -13,8 +13,7 @@ device's location and bearing and register for updates

      Topics

        -
      1. Obtaining User -Location
      2. +
      3. Location Strategies

      See Also

      @@ -58,8 +57,7 @@ comes within a given proximity (specified by radius in meters) of a given lat/lo

      For more information, read the guide to Obtaining User -Location.

      +href="{@docRoot}guide/topics/location/strategies.html">Location Strategies.

      Google Maps External Library

      @@ -98,8 +96,8 @@ Google APIs add-on, visit

      href="http://code.google.com/android/add-ons/google-apis">http://code.google.com/android/add-ons/google-apis

      For your convenience, the Google APIs add-on is also available as a downloadable component from -the Android SDK Manager (see Adding SDK -Components).

      +the Android SDK Manager (see Exploring the +SDK).

      Note: In order to display Google Maps data in a MapView, you must register with the Google Maps service and obtain a Maps API diff --git a/docs/html/guide/topics/location/obtaining-user-location.jd b/docs/html/guide/topics/location/strategies.jd similarity index 99% rename from docs/html/guide/topics/location/obtaining-user-location.jd rename to docs/html/guide/topics/location/strategies.jd index 3b450f0d403acd32b1cee8528ec5ac92efed0a28..f7909536f2f83b0fc1670bf83db1359302ac70e2 100644 --- a/docs/html/guide/topics/location/obtaining-user-location.jd +++ b/docs/html/guide/topics/location/strategies.jd @@ -1,4 +1,4 @@ -page.title=Obtaining User Location +page.title=Location Strategies parent.title=Location and Maps parent.link=index.html @jd:body @@ -422,7 +422,7 @@ lat/long coordinates, with a GPX file for route playback, or a KML file for mult

      For more information on using DDMS to spoof location data, see -Using DDMS. +Using DDMS.

      Using the "geo" command in the emulator console

      @@ -451,4 +451,4 @@ lat/long coordinates, with a GPX file for route playback, or a KML file for mult

    For information about how to connect to the emulator console, see -Using the Emulator Console.

    +Using the Emulator Console.

    diff --git a/docs/html/guide/topics/manifest/action-element.jd b/docs/html/guide/topics/manifest/action-element.jd index 8ad94cdc1d50d54fd41e7cc069760f400d7c0c16..037d0dc75d3dc7c09e7ecd62cf90f7aa94c7ce3b 100644 --- a/docs/html/guide/topics/manifest/action-element.jd +++ b/docs/html/guide/topics/manifest/action-element.jd @@ -16,7 +16,7 @@ parent.link=manifest-intro.html An <intent-filter> element must contain one or more {@code <action>} elements. If it doesn't contain any, no Intent objects will get through the filter. See -Intents and +Intents and Intent Filters for details on intent filters and the role of action specifications within a filter. diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd index 9dc124be4f3e101a3240336e96c25cfaf507b525..88f226c7e61b5693855441c14715f341161a7e69 100644 --- a/docs/html/guide/topics/manifest/activity-element.jd +++ b/docs/html/guide/topics/manifest/activity-element.jd @@ -508,7 +508,7 @@ other activities and tasks using the Back button.

    For more information on launch modes and their interaction with Intent flags, see the -Tasks and Back Stack +Tasks and Back Stack document.

    diff --git a/docs/html/guide/topics/manifest/category-element.jd b/docs/html/guide/topics/manifest/category-element.jd index f392c0a30f52180389d10cb13fd3b2c759f1eb0b..41a2cfdedb71f6027f3b9fa096c82222c4f31add 100644 --- a/docs/html/guide/topics/manifest/category-element.jd +++ b/docs/html/guide/topics/manifest/category-element.jd @@ -12,7 +12,7 @@ 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.
    diff --git a/docs/html/guide/topics/manifest/compatible-screens-element.jd b/docs/html/guide/topics/manifest/compatible-screens-element.jd index a27c31624de2d6c497e0cc454e8b38bc68de63c4..bb004fbef46cd3a831fa758b63ccf91298df1fe0 100644 --- a/docs/html/guide/topics/manifest/compatible-screens-element.jd +++ b/docs/html/guide/topics/manifest/compatible-screens-element.jd @@ -54,7 +54,7 @@ href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code <supports-screens>} element to declare whether the system should resize your application for different screen sizes.

    -

    Also see the Filters on Google Play +

    Also see the Filters on Google Play document for more information about how Google Play filters applications using this and other manifest elements.

    @@ -138,5 +138,5 @@ entry looks like if your application is compatible with only small and normal sc
    see also:
    Supporting Multiple Screens
    -
    Filters on Google Play
    +
    Filters on Google Play
    diff --git a/docs/html/guide/topics/manifest/data-element.jd b/docs/html/guide/topics/manifest/data-element.jd index 9b0d0df6ae06a39455ed8cfa3a936b6f0e28e89f..8fd91deae6a21ab3092c2d0d51518d03228f8e46 100644 --- a/docs/html/guide/topics/manifest/data-element.jd +++ b/docs/html/guide/topics/manifest/data-element.jd @@ -62,7 +62,7 @@ options. None of its attributes have default values.

    Information on how intent filters work, including the rules for how Intent objects are matched against filters, can be found in another document, -Intents and +Intents and Intent Filters. See also the Intent Filters section in the introduction. diff --git a/docs/html/guide/topics/manifest/intent-filter-element.jd b/docs/html/guide/topics/manifest/intent-filter-element.jd index d2934005f47be46b4cfd096763d2215af24710a9..f90541cafd17320087bc627a298de2e333400606 100644 --- a/docs/html/guide/topics/manifest/intent-filter-element.jd +++ b/docs/html/guide/topics/manifest/intent-filter-element.jd @@ -41,7 +41,7 @@ Most of the contents of the filter are described by its

    For a more detailed discussion of filters, see the separate -Intents +Intents and Intent Filters document, as well as the Intents Filters section in the introduction. diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd index 98968d739f12b7f03321a968f14cbaee2cad22ee..a3d4a955e396b80342d4423e22c34f7435194425 100644 --- a/docs/html/guide/topics/manifest/manifest-element.jd +++ b/docs/html/guide/topics/manifest/manifest-element.jd @@ -152,7 +152,7 @@ either internal or external storage through the system settings.

    Caution: If your application uses Google Play's Copy Protection feature, it cannot be installed to a device's SD card. However, if you use Google - Play's Application Licensing instead, + Play's Application Licensing instead, your application can be installed to internal or external storage, including SD cards.

    Note: By default, your application will be installed on the diff --git a/docs/html/guide/topics/manifest/manifest-intro.jd b/docs/html/guide/topics/manifest/manifest-intro.jd index 0f20305565870dda4654a4db4fb74998b3b348ae..a130f7d9761efb1e0ab25fd89b188ea051c1474a 100644 --- a/docs/html/guide/topics/manifest/manifest-intro.jd +++ b/docs/html/guide/topics/manifest/manifest-intro.jd @@ -345,7 +345,7 @@ filters.

    For information on how Intent objects are tested against intent filters, see a separate document, -Intents +Intents and Intent Filters.

    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 ebdd0b10917aad4f3611545d18c80980ee0c2e96..6dfc59e0b800f23efe708c96c3305c8f48808f0f 100644 --- a/docs/html/guide/topics/manifest/supports-gl-texture-element.jd +++ b/docs/html/guide/topics/manifest/supports-gl-texture-element.jd @@ -141,7 +141,7 @@ and others.
    see also:
    diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd index 5f0a501c367037394eb4a0b2d9fe95a648052d1b..f60529513cfc346957a284d115fa7c4da040ba9a 100644 --- a/docs/html/guide/topics/manifest/uses-feature-element.jd +++ b/docs/html/guide/topics/manifest/uses-feature-element.jd @@ -207,7 +207,7 @@ can check at run-time whether a higher level of OpenGL ES is available.)

  • {@link android.content.pm.FeatureInfo}
  • {@link android.content.pm.ConfigurationInfo}
  • <uses-permission>
  • -
  • Filters on Google Play
  • +
  • Filters on Google Play
  • @@ -501,7 +501,7 @@ If you are using SDK Tools r8 or higher, you can find aapt in the

    Note: You must use the version of aapt that is provided for the latest Platform-Tools component available. If you do not have the latest Platform-Tools component, download it using the Android SDK Manager. +href="{@docRoot}sdk/exploring.html">Android SDK Manager.

  • Run aapt using this syntax:
  • diff --git a/docs/html/guide/topics/manifest/uses-library-element.jd b/docs/html/guide/topics/manifest/uses-library-element.jd index 2f8eb508c27005b3868c704a747982a780150dc6..3ad8ddb5589a3435b11d1465c627b58bbbbce381 100644 --- a/docs/html/guide/topics/manifest/uses-library-element.jd +++ b/docs/html/guide/topics/manifest/uses-library-element.jd @@ -46,7 +46,7 @@ parent.link=manifest-intro.html
    Google Play filters applications based on the libraries installed on the user's device. For more information about filtering, see the topic - Filters on Google Play. + Filters on Google Play.

    diff --git a/docs/html/guide/topics/manifest/uses-sdk-element.jd b/docs/html/guide/topics/manifest/uses-sdk-element.jd index 8fa39d156914ca0e7758df9961f799352fcd5489..29dcb56b8b74acbefed50842210edb6c6a19e417 100644 --- a/docs/html/guide/topics/manifest/uses-sdk-element.jd +++ b/docs/html/guide/topics/manifest/uses-sdk-element.jd @@ -3,6 +3,29 @@ parent.title=The AndroidManifest.xml File parent.link=manifest-intro.html @jd:body + +

    +
    syntax:
    @@ -25,9 +48,8 @@ The API Level is always a single integer. You cannot derive the API Level from
     its associated Android version number (for example, it is not the same as the
     major version or the sum of the major and minor versions).

    -

    For more information, read about -Android API Levels and -Versioning Your Applications. +

    Also read the document about +Versioning Your Applications.

    @@ -156,3 +178,403 @@ download.
    API Level 1
    + + + + + + + + + + +

    What is API Level?

    + +

    API Level is an integer value that uniquely identifies the framework API +revision offered by a version of the Android platform.

    + +

    The Android platform provides a framework API that applications can use to +interact with the underlying Android system. The framework API consists of:

    + +
      +
    • A core set of packages and classes
    • +
    • A set of XML elements and attributes for declaring a manifest file
    • +
    • A set of XML elements and attributes for declaring and accessing resources
    • +
    • A set of Intents
    • +
    • A set of permissions that applications can request, as well as permission +enforcements included in the system
    • +
    + +

    Each successive version of the Android platform can include updates to the +Android application framework API that it delivers.

    + +

    Updates to the framework API are designed so that the new API remains +compatible with earlier versions of the API. That is, most changes in the API +are additive and introduce new or replacement functionality. As parts of the API +are upgraded, the older replaced parts are deprecated but are not removed, so +that existing applications can still use them. In a very small number of cases, +parts of the API may be modified or removed, although typically such changes are +only needed to ensure API robustness and application or system security. All +other API parts from earlier revisions are carried forward without +modification.

    + +

    The framework API that an Android platform delivers is specified using an +integer identifier called "API Level". Each Android platform version supports +exactly one API Level, although support is implicit for all earlier API Levels +(down to API Level 1). The initial release of the Android platform provided +API Level 1 and subsequent releases have incremented the API Level.

    + +

    The following table specifies the API Level supported by each version of the +Android platform.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Platform VersionAPI LevelVERSION_CODENotes
    Android 4.0.315{@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1}Platform +Highlights
    Android 4.0, 4.0.1, 4.0.214{@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}
    Android 3.213{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2}
    Android 3.1.x12{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR1}Platform Highlights
    Android 3.0.x11{@link android.os.Build.VERSION_CODES#HONEYCOMB}Platform Highlights
    Android 2.3.4
    Android 2.3.3
    10{@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1}Platform +Highlights
    Android 2.3.2
    Android 2.3.1
    Android +2.3
    9{@link android.os.Build.VERSION_CODES#GINGERBREAD}
    Android 2.2.x8{@link android.os.Build.VERSION_CODES#FROYO}Platform Highlights
    Android 2.1.x7{@link android.os.Build.VERSION_CODES#ECLAIR_MR1}Platform +Highlights
    Android 2.0.16{@link android.os.Build.VERSION_CODES#ECLAIR_0_1}
    Android 2.05{@link android.os.Build.VERSION_CODES#ECLAIR}
    Android 1.64{@link android.os.Build.VERSION_CODES#DONUT}Platform Highlights
    Android 1.53{@link android.os.Build.VERSION_CODES#CUPCAKE}Platform Highlights
    Android 1.12{@link android.os.Build.VERSION_CODES#BASE_1_1}
    Android 1.01{@link android.os.Build.VERSION_CODES#BASE}
    + + +

    Uses of API Level in Android

    + +

    The API Level identifier serves a key role in ensuring the best possible +experience for users and application developers: + +

      +
    • It lets the Android platform describe the maximum framework API revision +that it supports
    • +
    • It lets applications describe the framework API revision that they +require
    • +
    • It lets the system negotiate the installation of applications on the user's +device, such that version-incompatible applications are not installed.
    • +
    + +

    Each Android platform version stores its API Level identifier internally, in +the Android system itself.

    + +

    Applications can use a manifest element provided by the framework API — +<uses-sdk> — to describe the minimum and maximum API +Levels under which they are able to run, as well as the preferred API Level that +they are designed to support. The element offers three key attributes:

    + +
      +
    • android:minSdkVersion — Specifies the minimum API Level +on which the application is able to run. The default value is "1".
    • +
    • android:targetSdkVersion — Specifies the API Level +on which the application is designed to run. In some cases, this allows the +application to use manifest elements or behaviors defined in the target +API Level, rather than being restricted to using only those defined +for the minimum API Level.
    • +
    • android:maxSdkVersion — Specifies the maximum API Level +on which the application is able to run. Important: Please read the <uses-sdk> +documentation before using this attribute.
    • +
    + +

    For example, to specify the minimum system API Level that an application +requires in order to run, the application would include in its manifest a +<uses-sdk> element with a android:minSdkVersion +attribute. The value of android:minSdkVersion would be the integer +corresponding to the API Level of the earliest version of the Android platform +under which the application can run.

    + +

    When the user attempts to install an application, or when revalidating an +appplication after a system update, the Android system first checks the +<uses-sdk> attributes in the application's manifest and +compares the values against its own internal API Level. The system allows the +installation to begin only if these conditions are met:

    + +
      +
    • If a android:minSdkVersion attribute is declared, its value +must be less than or equal to the system's API Level integer. If not declared, +the system assumes that the application requires API Level 1.
    • +
    • If a android:maxSdkVersion attribute is declared, its value +must be equal to or greater than the system's API Level integer. +If not declared, the system assumes that the application +has no maximum API Level. Please read the <uses-sdk> +documentation for more information about how the system handles this attribute.
    • +
    + +

    When declared in an application's manifest, a <uses-sdk> +element might look like this:

    + +
    <manifest>
    +  <uses-sdk android:minSdkVersion="5" />
    +  ...
    +</manifest>
    + +

    The principal reason that an application would declare an API Level in +android:minSdkVersion is to tell the Android system that it is +using APIs that were introduced in the API Level specified. If the +application were to be somehow installed on a platform with a lower API Level, +then it would crash at run-time when it tried to access APIs that don't exist. +The system prevents such an outcome by not allowing the application to be +installed if the lowest API Level it requires is higher than that of the +platform version on the target device.

    + +

    For example, the {@link android.appwidget} package was introduced with API +Level 3. If an application uses that API, it must declare a +android:minSdkVersion attribute with a value of "3". The +application will then be installable on platforms such as Android 1.5 (API Level +3) and Android 1.6 (API Level 4), but not on the Android 1.1 (API Level 2) and +Android 1.0 platforms (API Level 1).

    + +

    For more information about how to specify an application's API Level +requirements, see the <uses-sdk> + section of the manifest file documentation.

    + + +

    Development Considerations

    + +

    The sections below provide information related to API level that you should +consider when developing your application.

    + +

    Application forward compatibility

    + +

    Android applications are generally forward-compatible with new versions of +the Android platform.

    + +

    Because almost all changes to the framework API are additive, an Android +application developed using any given version of the API (as specified by its +API Level) is forward-compatible with later versions of the Android platform and +higher API levels. The application should be able to run on all later versions +of the Android platform, except in isolated cases where the application uses a +part of the API that is later removed for some reason.

    + +

    Forward compatibility is important because many Android-powered devices +receive over-the-air (OTA) system updates. The user may install your +application and use it successfully, then later receive an OTA update to a new +version of the Android platform. Once the update is installed, your application +will run in a new run-time version of the environment, but one that has the API +and system capabilities that your application depends on.

    + +

    In some cases, changes below the API, such those in the underlying +system itself, may affect your application when it is run in the new +environment. For that reason it's important for you, as the application +developer, to understand how the application will look and behave in each system +environment. To help you test your application on various versions of the Android +platform, the Android SDK includes multiple platforms that you can download. +Each platform includes a compatible system image that you can run in an AVD, to +test your application.

    + +

    Application backward compatibility

    + +

    Android applications are not necessarily backward compatible with versions of +the Android platform older than the version against which they were compiled. +

    + +

    Each new version of the Android platform can include new framework APIs, such +as those that give applications access to new platform capabilities or replace +existing API parts. The new APIs are accessible to applications when running on +the new platform and, as mentioned above, also when running on later versions of +the platform, as specified by API Level. Conversely, because earlier versions of +the platform do not include the new APIs, applications that use the new APIs are +unable to run on those platforms.

    + +

    Although it's unlikely that an Android-powered device would be downgraded to +a previous version of the platform, it's important to realize that there are +likely to be many devices in the field that run earlier versions of the +platform. Even among devices that receive OTA updates, some might lag and +might not receive an update for a significant amount of time.

    + +

    Selecting a platform version and API Level

    + +

    When you are developing your application, you will need to choose +the platform version against which you will compile the application. In +general, you should compile your application against the lowest possible +version of the platform that your application can support. + +

    You can determine the lowest possible platform version by compiling the +application against successively lower build targets. After you determine the +lowest version, you should create an AVD using the corresponding platform +version (and API Level) and fully test your application. Make sure to declare a +android:minSdkVersion attribute in the application's manifest and +set its value to the API Level of the platform version.

    + +

    Declaring a minimum API Level

    + +

    If you build an application that uses APIs or system features introduced in +the latest platform version, you should set the +android:minSdkVersion attribute to the API Level of the latest +platform version. This ensures that users will only be able to install your +application if their devices are running a compatible version of the Android +platform. In turn, this ensures that your application can function properly on +their devices.

    + +

    If your application uses APIs introduced in the latest platform version but +does not declare a android:minSdkVersion attribute, then +it will run properly on devices running the latest version of the platform, but +not on devices running earlier versions of the platform. In the latter +case, the application will crash at runtime when it tries to use APIs that don't +exist on the earlier versions.

    + +

    Testing against higher API Levels

    + +

    After compiling your application, you should make sure to test it on the +platform specified in the application's android:minSdkVersion +attribute. To do so, create an AVD that uses the platform version required by +your application. Additionally, to ensure forward-compatibility, you should run +and test the application on all platforms that use a higher API Level than that +used by your application.

    + +

    The Android SDK includes multiple platform versions that you can use, +including the latest version, and provides an updater tool that you can use to +download other platform versions as necessary.

    + +

    To access the updater, use the android command-line tool, +located in the <sdk>/tools directory. You can launch the SDK updater by +executing android sdk. You can +also simply double-click the android.bat (Windows) or android (OS X/Linux) file. +In ADT, you can also access the updater by selecting +Window > Android SDK +Manager.

    + +

    To run your application against different platform versions in the emulator, +create an AVD for each platform version that you want to test. For more +information about AVDs, see Creating and Managing Virtual Devices. If +you are using a physical device for testing, ensure that you know the API Level +of the Android platform it runs. See the table at the top of this document for +a list of platform versions and their API Levels.

    + +

    Using a Provisional API Level

    + +

    In some cases, an "Early Look" Android SDK platform may be available. To let +you begin developing on the platform although the APIs may not be final, the +platform's API Level integer will not be specified. You must instead use the +platform's provisional API Level in your application manifest, in order +to build applications against the platform. A provisional API Level is not an +integer, but a string matching the codename of the unreleased platform version. +The provisional API Level will be specified in the release notes for the Early +Look SDK release notes and is case-sensitive.

    + +

    The use of a provisional API Level is designed to protect developers and +device users from inadvertently publishing or installing applications based on +the Early Look framework API, which may not run properly on actual devices +running the final system image.

    + +

    The provisional API Level will only be valid while using the Early Look SDK +and can only be used to run applications in the emulator. An application using +the provisional API Level can never be installed on an Android device. At the +final release of the platform, you must replace any instances of the provisional +API Level in your application manifest with the final platform's actual API +Level integer.

    + + +

    Filtering the Reference Documentation by API Level

    + +

    Reference documentation pages on the Android Developers site offer a "Filter +by API Level" control in the top-right area of each page. You can use the +control to show documentation only for parts of the API that are actually +accessible to your application, based on the API Level that it specifies in +the android:minSdkVersion attribute of its manifest file.

    + +

    To use filtering, select the checkbox to enable filtering, just below the +page search box. Then set the "Filter by API Level" control to the same API +Level as specified by your application. Notice that APIs introduced in a later +API Level are then grayed out and their content is masked, since they would not +be accessible to your application.

    + +

    Filtering by API Level in the documentation does not provide a view +of what is new or introduced in each API Level — it simply provides a way +to view the entire API associated with a given API Level, while excluding API +elements introduced in later API Levels.

    + +

    If you decide that you don't want to filter the API documentation, just +disable the feature using the checkbox. By default, API Level filtering is +disabled, so that you can view the full framework API, regardless of API Level. +

    + +

    Also note that the reference documentation for individual API elements +specifies the API Level at which each element was introduced. The API Level +for packages and classes is specified as "Since <api level>" at the +top-right corner of the content area on each documentation page. The API Level +for class members is specified in their detailed description headers, +at the right margin.

    + + + + + + + + + diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd index 7d72491ef109a88dd85fa25f0c0d34ff15addf76..a63270a77eade742293704b23beb1b846b58d6ff 100644 --- a/docs/html/guide/topics/media/camera.jd +++ b/docs/html/guide/topics/media/camera.jd @@ -162,8 +162,7 @@ information, you must request location permission: <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    For more information about getting user location, see -Obtaining User -Location.

    +Location Strategies.

    diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd index 0e0412a10d526950c05e247400219fdc15c8844a..a750c9a8809ff57b5a92aa7fe2d89bc1512a7ac6 100644 --- a/docs/html/guide/topics/media/index.jd +++ b/docs/html/guide/topics/media/index.jd @@ -1,63 +1,56 @@ -page.title=Multimedia and Camera +page.title=Media and Camera +page.landing=true +page.landing.intro=Add video, audio, and photo capabilities to your app with Android's robust APIs for playing and recording media. +page.landing.image= + @jd:body -
    -
    - -

    Topics

    -
      -
    1. Media Playback
    2. -
    3. JetPlayer
    4. -
    5. Camera
    6. -
    7. Audio Capture
    8. -
    - -

    Key classes

    -
      -
    1. {@link android.media.MediaPlayer}
    2. -
    3. {@link android.media.JetPlayer}
    4. -
    5. {@link android.hardware.Camera}
    6. -
    7. {@link android.media.MediaRecorder}
    8. -
    9. {@link android.media.AudioManager}
    10. -
    11. {@link android.media.SoundPool}
    12. -
    - -

    See also

    -
      -
    1. -
    2. Android Supported Media Formats
    3. -
    4. JetCreator User -Manual
    5. -
    - -
    -
    - -

    The Android multimedia framework includes support for capturing and playing audio, video and -images in a variety of common media types, so that you can easily integrate them into your -applications. You can play audio or video from media files stored in your application's resources, -from standalone files in the file system, or from a data stream arriving over a -network connection, all using the {@link android.media.MediaPlayer} or {@link -android.media.JetPlayer} APIs. You can also record audio, video and take pictures using the {@link -android.media.MediaRecorder} and {@link android.hardware.Camera} APIs if supported by the device -hardware.

    - -

    The following topics show you how to use the Android framework to implement multimedia capture -and playback.

    - -
    -
    Media Playback -
    -
    How to play audio and video in your application.
    - -
    JetPlayer
    -
    How to play interactive audio and video in your application using content created with -JetCreator.
    - -
    Camera
    -
    How to use a device camera to take pictures or video in your application.
    - -
    Audio -Capture
    -
    How to record sound in your application.
    -
    \ No newline at end of file + \ No newline at end of file diff --git a/docs/html/guide/topics/media/mediaplayer.jd b/docs/html/guide/topics/media/mediaplayer.jd index 002d113ea31a31852fe3aeef4b1d299415809b7e..45a58a7b5c4a333acdeb267968b81a8af74e59c2 100644 --- a/docs/html/guide/topics/media/mediaplayer.jd +++ b/docs/html/guide/topics/media/mediaplayer.jd @@ -457,7 +457,7 @@ stopForeground(true);

    For more information, see the documentation about Services and +href="{@docRoot}guide/components/services.html#Foreground">Services and Status Bar Notifications.

    diff --git a/docs/html/guide/topics/providers/calendar-provider.jd b/docs/html/guide/topics/providers/calendar-provider.jd index d30dda423ec5c95b720b71fe1572a00f1d3d61f6..f53b0625841d4b4c1532c9ca612763d6660c2aa2 100644 --- a/docs/html/guide/topics/providers/calendar-provider.jd +++ b/docs/html/guide/topics/providers/calendar-provider.jd @@ -250,27 +250,30 @@ and store its events on the device.

    Querying a calendar

    -

    Here is an example that shows how to get all the calendars for a particular +

    Here is an example that shows how to get the calendars that are owned by a particular user. For simplicity's sake, in this example the query operation is shown in the user interface thread ("main thread"). In practice, this should be done in an asynchronous thread instead of on the main thread. For more discussion, see -Loaders. If you are not just reading data but modifying it, see {@link android.content.AsyncQueryHandler}. +Loaders. If you are not just +reading data but modifying it, see {@link android.content.AsyncQueryHandler}.

    -  // Projection array. Creating indices for this array instead of doing
    -  // dynamic lookups improves performance.
    -  public static final String[] EVENT_PROJECTION = new String[] {
    +// Projection array. Creating indices for this array instead of doing
    +// dynamic lookups improves performance.
    +public static final String[] EVENT_PROJECTION = new String[] {
         Calendars._ID,                           // 0
         Calendars.ACCOUNT_NAME,                  // 1
    -    Calendars.CALENDAR_DISPLAY_NAME          // 2
    -  };
    +    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;
    +// 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;

    In the next part of the example, you construct your query. The selection specifies the criteria for the query. In this example the query is looking for -all calendars that have the ACCOUNT_NAME -"sampleuser@google.com" and the ACCOUNT_TYPE -"com.google". The query returns a {@link android.database.Cursor} +calendars that have the ACCOUNT_NAME +"sampleuser@google.com", the ACCOUNT_TYPE +"com.google", and the OWNER_ACCOUNT +"sampleuser@google.com". If you want to see all calendars that a user +has viewed, not just calendars the user owns, omit the OWNER_ACCOUNT. +The query returns a {@link android.database.Cursor} object that you can use to traverse the result set returned by the database -query. For more discussion of using queries in content providers, see Content Providers.

    +query. For more discussion of using queries in content providers, +see Content Providers.

    // Run query
    @@ -303,8 +310,10 @@ Cursor cur = null;
     ContentResolver cr = getContentResolver();
     Uri uri = Calendars.CONTENT_URI;   
     String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
    -                        + Calendars.ACCOUNT_TYPE + " = ?))";
    -String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google"}; 
    +                        + 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. 
     cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
    @@ -316,12 +325,14 @@ for each field.

    while (cur.moveToNext()) { long calID = 0; String displayName = null; - String accountName = 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... @@ -1179,5 +1190,3 @@ However, a sync adapter is restricted to the ACCOUNT_NAME and

    For a sample implementation of a sync adapter (not specifically related to Calendar), see SampleSyncAdapter. - - diff --git a/docs/html/guide/topics/providers/contacts-provider.jd b/docs/html/guide/topics/providers/contacts-provider.jd new file mode 100644 index 0000000000000000000000000000000000000000..e3b998a7677fd6cb851447cf03424ef04781dd52 --- /dev/null +++ b/docs/html/guide/topics/providers/contacts-provider.jd @@ -0,0 +1,2361 @@ +page.title=Contacts Provider +@jd:body +

    +
    +

    Quickview

    +
      +
    • Android's repository of information about people.
    • +
    • + Syncs with the web. +
    • +
    • + Integrates social stream data. +
    • +
    +

    In this document

    +
      +
    1. + Contacts Provider Organization +
    2. +
    3. + Raw contacts +
    4. +
    5. + Data +
    6. +
    7. + Contacts +
    8. +
    9. + Data From Sync Adapters +
    10. +
    11. + Required Permissions +
    12. +
    13. + The User Profile +
    14. +
    15. + Contacts Provider Metadata +
    16. +
    17. + Contacts Provider Access +
    18. +
    19. +
    20. + Contacts Provider Sync Adapters +
    21. +
    22. + Social Stream Data +
    23. +
    24. + Additional Contacts Provider Features +
    25. +
    +

    Key classes

    +
      +
    1. {@link android.provider.ContactsContract.Contacts}
    2. +
    3. {@link android.provider.ContactsContract.RawContacts}
    4. +
    5. {@link android.provider.ContactsContract.Data}
    6. +
    7. {@link android.provider.ContactsContract.StreamItems}
    8. +
    +

    Related Samples

    +
      +
    1. + + Contact Manager + +
    2. +
    3. + + Sample Sync Adapter +
    4. +
    +

    See Also

    +
      +
    1. + + Content Provider Basics + +
    2. +
    +
    +
    +

    + The Contacts Provider is a powerful and flexible Android component that manages the + device's central repository of data about people. The Contacts Provider is the source of data + you see in the device's contacts application, and you can also access its data in your own + application and transfer data between the device and online services. The provider accommodates + a wide range of data sources and tries to manage as much data as possible for each person, with + the result that its organization is complex. Because of this, the provider's API includes an + extensive set of contract classes and interfaces that facilitate both data retrieval and + modification. +

    +

    + This guide describes the following: +

    +
      +
    • + The basic provider structure. +
    • +
    • + How to retrieve data from the provider. +
    • +
    • + How to modify data in the provider. +
    • +
    • + How to write a sync adapter for synchronizing data from your server to the + Contacts Provider. +
    • +
    +

    + This guide assumes that you know the basics of Android content providers. To learn more + about Android content providers, read the + + Content Provider Basics guide. The + Sample Sync Adapter + sample app is an example of using a sync adapter to transfer data between the Contacts + Provider and a sample application hosted by Google Web Services. +

    +

    Contacts Provider Organization

    +

    + The Contacts Provider is an Android content provider component. It maintains three types of + data about a person, each of which corresponds to a table offered by the provider, as + illustrated in figure 1: +

    + +

    + Figure 1. Contacts Provider table structure. +

    +

    + The three tables are commonly referred to by the names of their contract classes. The classes + define constants for content URIs, column names, and column values used by the tables: +

    +
    +
    + {@link android.provider.ContactsContract.Contacts} table +
    +
    + Rows representing different people, based on aggregations of raw contact rows. +
    +
    + {@link android.provider.ContactsContract.RawContacts} table +
    +
    + Rows containing a summary of a person's data, specific to a user account and type. +
    +
    + {@link android.provider.ContactsContract.Data} table +
    +
    + Rows containing the details for raw contact, such as email addresses or phone numbers. +
    +
    +

    + The other tables represented by contract classes in {@link android.provider.ContactsContract} + are auxiliary tables that the Contacts Provider uses to manage its operations or support + specific functions in the device's contacts or telephony applications. +

    +

    Raw contacts

    +

    + A raw contact represents a person's data coming from a single account type and account + name. Because the Contacts Provider allows more than one online service as the source of + data for a person, the Contacts Provider allows multiple raw contacts for the same person. + Multiple raw contacts also allow a user to combine a person's data from more than one account + from the same account type. +

    +

    + Most of the data for a raw contact isn't stored in the + {@link android.provider.ContactsContract.RawContacts} table. Instead, it's stored in one or more + rows in the {@link android.provider.ContactsContract.Data} table. Each data row has a column + {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID Data.RAW_CONTACT_ID} that + contains the {@link android.provider.BaseColumns#_ID RawContacts._ID} value of its + parent {@link android.provider.ContactsContract.RawContacts} row. +

    +

    Important raw contact columns

    +

    + The important columns in the {@link android.provider.ContactsContract.RawContacts} table are + listed in table 1. Please read the notes that follow after the table: +

    +

    + Table 1. Important raw contact columns. +

    + + + + + + + + + + + + + + + + + + + + +
    Column nameUseNotes
    + {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_NAME} + + The account name for the account type that's the source of this raw contact. + For example, the account name of a Google account is one of the device owner's Gmail + addresses. See the next entry for + {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE} for more + information. + + The format of this name is specific to its account type. It is not + necessarily an email address. +
    + {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE} + + The account type that's the source of this raw contact. For example, the account + type of a Google account is com.google. Always qualify your account type + with a domain identifier for a domain you own or control. This will ensure that your + account type is unique. + + An account type that offers contacts data usually has an associated sync adapter that + synchronizes with the Contacts Provider. +
    + {@link android.provider.ContactsContract.RawContactsColumns#DELETED} + + The "deleted" flag for a raw contact. + + This flag allows the Contacts Provider to maintain the row internally until sync + adapters are able to delete the row from their servers and then finally delete the row + from the repository. +
    +

    Notes

    +

    + The following are important notes about the + {@link android.provider.ContactsContract.RawContacts} table: +

    +
      +
    • + A raw contact's name is not stored in its row in + {@link android.provider.ContactsContract.RawContacts}. Instead, it's stored in + the {@link android.provider.ContactsContract.Data} table, in a + {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} row. A raw contact + has only one row of this type in the {@link android.provider.ContactsContract.Data} table. +
    • +
    • + Caution: To use your own account data in a raw contact row, it must + first be registered with the {@link android.accounts.AccountManager}. To do this, prompt + users to add the account type and their account name to the list of accounts. If you don't + do this, the Contacts Provider will automatically delete your raw contact row. +

      + For example, if you want your app to maintain contacts data for your web-based service + with the domain {@code com.example.dataservice}, and the user's account for your service + is {@code becky.sharp@dataservice.example.com}, the user must first add the account + "type" ({@code com.example.dataservice}) and account "name" + ({@code becky.smart@dataservice.example.com}) before your app can add raw contact rows. + You can explain this requirement to the user in documentation, or you can prompt the + user to add the type and name, or both. Account types and account names + are described in more detail in the next section. +

    • +
    +

    Sources of raw contacts data

    +

    + To understand how raw contacts work, consider the user "Emily Dickinson" who has the following + three user accounts defined on her device: +

    +
      +
    • emily.dickinson@gmail.com
    • +
    • emilyd@gmail.com
    • +
    • Twitter account "belle_of_amherst"
    • +
    +

    + This user has enabled Sync Contacts for all three of these accounts in the + Accounts settings. +

    +

    + Suppose Emily Dickinson opens a browser window, logs into Gmail as + emily.dickinson@gmail.com, opens + Contacts, and adds "Thomas Higginson". Later on, she logs into Gmail as + emilyd@gmail.com and sends an email to "Thomas Higginson", which automatically + adds him as a contact. She also follows "colonel_tom" (Thomas Higginson's Twitter ID) on + Twitter. +

    +

    + The Contacts Provider creates three raw contacts as a result of this work: +

    +
      +
    1. + A raw contact for "Thomas Higginson" associated with emily.dickinson@gmail.com. + The user account type is Google. +
    2. +
    3. + A second raw contact for "Thomas Higginson" associated with emilyd@gmail.com. + The user account type is also Google. There is a second raw contact even + though the name is identical to a previous name, because the person was added for a + different user account. +
    4. +
    5. + A third raw contact for "Thomas Higginson" associated with "belle_of_amherst". The user + account type is Twitter. +
    6. +
    +

    Data

    +

    + As noted previously, the data for a raw contact is stored in a + {@link android.provider.ContactsContract.Data} row that is linked to the raw contact's + _ID value. This allows a single raw contact to have multiple instances of the same + type of data such as email addresses or phone numbers. For example, if + "Thomas Higginson" for {@code emilyd@gmail.com} (the raw contact row for Thomas Higginson + associated with the Google account emilyd@gmail.com) has a home email address of + thigg@gmail.com and a work email address of + thomas.higginson@gmail.com, the Contacts Provider stores the two email address + rows and links them both to the raw contact. +

    +

    + Notice that different types of data are stored in this single table. Display name, + phone number, email, postal address, photo, and website detail rows are all found in the + {@link android.provider.ContactsContract.Data} table. To help manage this, the + {@link android.provider.ContactsContract.Data} table has some columns with descriptive names, + and others with generic names. The contents of a descriptive-name column have the same meaning + regardless of the type of data in the row, while the contents of a generic-name column have + different meanings depending on the type of data. +

    +

    Descriptive column names

    +

    + Some examples of descriptive column names are: +

    +
    +
    + {@link android.provider.ContactsContract.Data#RAW_CONTACT_ID} +
    +
    + The value of the _ID column of the raw contact for this data. +
    +
    + {@link android.provider.ContactsContract.Data#MIMETYPE} +
    +
    + The type of data stored in this row, expressed as a custom MIME type. The Contacts Provider + uses the MIME types defined in the subclasses of + {@link android.provider.ContactsContract.CommonDataKinds}. These MIME types are open source, + and can be used by any application or sync adapter that works with the Contacts Provider. +
    +
    + {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} +
    +
    + If this type of data row can occur more than once for a raw contact, the + {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} column flags + the data row that contains the primary data for the type. For example, if + the user long-presses a phone number for a contact and selects Set default, + then the {@link android.provider.ContactsContract.Data} row containing that number + has its {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} column set to a + non-zero value. +
    +
    +

    Generic column names

    +

    + There are 15 generic columns named DATA1 through + DATA15 that are generally available and an additional four generic + columns SYNC1 through SYNC4 that should only be used by sync + adapters. The generic column name constants always work, regardless of the type of + data the row contains. +

    +

    + The DATA1 column is indexed. The Contacts Provider always uses this column for + the data that the provider expects will be the most frequent target of a query. For example, + in an email row, this column contains the actual email address. +

    +

    + By convention, the column DATA15 is reserved for storing Binary Large Object + (BLOB) data such as photo thumbnails. +

    +

    Type-specific column names

    +

    + To facilitate working with the columns for a particular type of row, the Contacts Provider + also provides type-specific column name constants, defined in subclasses of + {@link android.provider.ContactsContract.CommonDataKinds}. The constants simply give a + different constant name to the same column name, which helps you access data in a row of a + particular type. +

    +

    + For example, the {@link android.provider.ContactsContract.CommonDataKinds.Email} class defines + type-specific column name constants for a {@link android.provider.ContactsContract.Data} row + that has the MIME type + {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE + Email.CONTENT_ITEM_TYPE}. The class contains the constant + {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS} for the email address + column. The actual value of + {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS} is "data1", which is + the same as the column's generic name. +

    +

    + Caution: Don't add your own custom data to the + {@link android.provider.ContactsContract.Data} table using a row that has one of the + provider's pre-defined MIME types. If you do, you may lose the data or cause the provider to + malfunction. For example, you should not add a row with the MIME type + {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE + Email.CONTENT_ITEM_TYPE} that contains a user name instead of an email address in the + column DATA1. If you use your own custom MIME type for the row, then you are free + to define your own type-specific column names and use the columns however you wish. +

    +

    + Figure 2 shows how descriptive columns and data columns appear in a + {@link android.provider.ContactsContract.Data} row, and how type-specific column names "overlay" + the generic column names +

    +How type-specific column names map to generic column names +

    + Figure 2. Type-specific column names and generic column names. +

    +

    Type-specific column name classes

    +

    + Table 2 lists the most commonly-used type-specific column name classes: +

    +

    + Table 2. Type-specific column name classes

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Mapping classType of dataNotes
    {@link android.provider.ContactsContract.CommonDataKinds.StructuredName}The name data for the raw contact associated with this data row.A raw contact has only one of these rows.
    {@link android.provider.ContactsContract.CommonDataKinds.Photo}The main photo for the raw contact associated with this data row.A raw contact has only one of these rows.
    {@link android.provider.ContactsContract.CommonDataKinds.Email}An email address for the raw contact associated with this data row.A raw contact can have multiple email addresses.
    {@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal}A postal address for the raw contact associated with this data row.A raw contact can have multiple postal addresses.
    {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership}An identifier that links the raw contact to one of the groups in the Contacts Provider. + Groups are an optional feature of an account type and account name. They're described in + more detail in the section Contact groups. +
    +

    Contacts

    +

    + The Contacts Provider combines the raw contact rows across all account types and account names + to form a contact. This facilitates displaying and modifying all the data a + user has collected for a person. The Contacts Provider manages the creation of new contact + rows, and the aggregation of raw contacts with an existing contact row. Neither applications nor + sync adapters are allowed to add contacts, and some columns in a contact row are read-only. +

    +

    + Note: If you try to add a contact to the Contacts Provider with an + {@link android.content.ContentResolver#insert(Uri,ContentValues) insert()}, you'll get + an {@link java.lang.UnsupportedOperationException} exception. If you try to update a column + that's listed as "read-only," the update is ignored. +

    +

    + The Contacts Provider creates a new contact in response to the addition of a new raw contact + that doesn't match any existing contacts. The provider also does this if an existing raw + contact's data changes in such a way that it no longer matches the contact to which it was + previously attached. If an application or sync adapter creates a new raw contact that + does match an existing contact, the new raw contact is aggregated to the existing + contact. +

    +

    + The Contacts Provider links a contact row to its raw contact rows with the contact row's + _ID column in the {@link android.provider.ContactsContract.Contacts Contacts} + table. The CONTACT_ID column of the raw contacts table + {@link android.provider.ContactsContract.RawContacts} contains _ID values for + the contacts row associated with each raw contacts row. +

    +

    + The {@link android.provider.ContactsContract.Contacts} table also has the column + {@link android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} that is a + "permanent" link to the contact row. Because the Contacts Provider maintains contacts + automatically, it may change a contact row's {@link android.provider.BaseColumns#_ID} value + in response to an aggregation or sync. Even If this happens, the content URI + {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} combined with + contact's {@link android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} will still + point to the contact row, so you can use + {@link android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} + to maintain links to "favorite" contacts, and so forth. This column has its own format that is + unrelated to the format of the {@link android.provider.BaseColumns#_ID} column. +

    +

    + Figure 3 shows how the three main tables relate to each other. +

    +Contacts provider main tables +

    + Figure 3. Contacts, Raw Contacts, and Details table relationships. +

    +

    Data From Sync Adapters

    +

    + Users enter contacts data directly into the device, but data also flows into the Contacts + Provider from web services via sync adapters, which automate + the transfer of data between the device and services. Sync adapters run in the background + under the control of the system, and they call {@link android.content.ContentResolver} methods + to manage data. +

    +

    + In Android, the web service that a sync adapter works with is identified by an account type. + Each sync adapter works with one account type, but it can support multiple account names for + that type. Account types and account names are described briefly in the section + Sources of raw contacts data. The following definitions offer + more detail, and describe how account type and name relate to sync adapters and services. +

    +
    +
    + Account type +
    +
    + Identifies a service in which the user has stored data. Most of the time, the user has to + authenticate with the service. For example, Google Contacts is an account type, identified + by the code google.com. This value corresponds to the account type used by + {@link android.accounts.AccountManager}. +
    +
    + Account name +
    +
    + Identifies a particular account or login for an account type. Google Contacts accounts + are the same as Google accounts, which have an email address as an account name. + Other services may use a single-word username or numeric id. +
    +
    +

    + Account types don't have to be unique. A user can configure multiple Google Contacts accounts + and download their data to the Contacts Provider; this may happen if the user has one set of + personal contacts for a personal account name, and another set for work. Account names are + usually unique. Together, they identify a specific data flow between the Contacts Provider and + an external service. +

    +

    + If you want to transfer your service's data to the Contacts Provider, you need to write your + own sync adapter. This is described in more detail in the section + Contacts Provider Sync Adapters. +

    +

    + Figure 4 shows how the Contacts Provider fits into the flow of data + about people. In the box marked "sync adapters," each adapter is labeled by its account type. +

    +Flow of data about people +

    + Figure 4. The Contacts Provider flow of data. +

    +

    Required Permissions

    +

    + Applications that want to access the Contacts Provider must request the following + permissions: +

    +
    +
    Read access to one or more tables
    +
    + {@link android.Manifest.permission#READ_CONTACTS}, specified in + AndroidManifest.xml with the + + <uses-permission> element as + <uses-permission android:name="android.permission.READ_CONTACTS">. +
    +
    Write access to one or more tables
    +
    + {@link android.Manifest.permission#WRITE_CONTACTS}, specified in + AndroidManifest.xml with the + + <uses-permission> element as + <uses-permission android:name="android.permission.WRITE_CONTACTS">. +
    +
    +

    + These permissions do not extend to the user profile data. The user profile and its + required permissions are discussed in the following section, + The User Profile. +

    +

    + Remember that the user's contacts data is personal and sensitive. Users are concerned about + their privacy, so they don't want applications collecting data about them or their contacts. + If it's not obvious why you need permission to access their contacts data, they may give + your application low ratings or simply refuse to install it. +

    +

    The User Profile

    +

    + The {@link android.provider.ContactsContract.Contacts} table has a single row containing + profile data for the device's user. This data describes the device's user rather + than one of the user's contacts. The profile contacts row is linked to a raw + contacts row for each system that uses a profile. + Each profile raw contact row can have multiple data rows. Constants for accessing the user + profile are available in the {@link android.provider.ContactsContract.Profile} class. +

    +

    + Access to the user profile requires special permissions. In addition to the + {@link android.Manifest.permission#READ_CONTACTS} and + {@link android.Manifest.permission#WRITE_CONTACTS} permissions needed to read and write, access + to the user profile requires the {@link android.Manifest.permission#READ_PROFILE} and + {@link android.Manifest.permission#WRITE_PROFILE} permissions for read and write access, + respectively. +

    +

    + Remember that you should consider a user's profile to be sensitive. The permission + {@link android.Manifest.permission#READ_PROFILE} allows you to access the device user's + personally-identifying data. Make sure to tell the user why + you need user profile access permissions in the description of your application. +

    +

    + To retrieve the contact row that contains the user's profile, + call {@link android.content.ContentResolver#query(Uri,String[], String, String[], String) + ContentResolver.query()}. Set the content URI to + {@link android.provider.ContactsContract.Profile#CONTENT_URI} and don't provide any + selection criteria. You can also use this content URI as the base URI for retrieving raw + contacts or data for the profile. For example, this snippet retrieves data for the profile: +

    +
    +// Sets the columns to retrieve for the user profile
    +mProjection = new String[]
    +    {
    +        Profile._ID,
    +        Profile.DISPLAY_NAME_PRIMARY,
    +        Profile.LOOKUP_KEY,
    +        Profile.PHOTO_THUMBNAIL_URI
    +    };
    +
    +// Retrieves the profile from the Contacts Provider
    +mProfileCursor =
    +        getContentResolver().query(
    +                Profile.CONTENT_URI,
    +                mProjection ,
    +                null,
    +                null,
    +                null);
    +
    +

    + Note: If you retrieve multiple contact rows, and you want to determine if one of them + is the user profile, test the row's + {@link android.provider.ContactsContract.ContactsColumns#IS_USER_PROFILE} column. This column + is set to "1" if the contact is the user profile. +

    +

    Contacts Provider Metadata

    +

    + The Contacts Provider manages data that keeps track of the state of contacts data in the + repository. This metadata about the repository is stored in various places, including the + Raw Contacts, Data, and Contacts table rows, the + {@link android.provider.ContactsContract.Settings} table, and the + {@link android.provider.ContactsContract.SyncState} table. The following table shows the + effect of each of these pieces of metadata: +

    +

    + Table 3. Metadata in the Contacts Provider

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    TableColumnValuesMeaning
    {@link android.provider.ContactsContract.RawContacts}{@link android.provider.ContactsContract.SyncColumns#DIRTY}"0" - not changed since the last sync. + Marks raw contacts that were changed on the device and have to be synced back to the + server. The value is set automatically by the Contacts Provider when Android + applications update a row. +

    + Sync adapters that modify the raw contact or data tables should always append the + string {@link android.provider.ContactsContract#CALLER_IS_SYNCADAPTER} to the + content URI they use. This prevents the provider from marking rows as dirty. + Otherwise, sync adapter modifications appear to be local modifications and are + sent to the server, even though the server was the source of the modification. +

    +
    "1" - changed since last sync, needs to be synced back to the server.
    {@link android.provider.ContactsContract.RawContacts}{@link android.provider.ContactsContract.SyncColumns#VERSION}The version number of this row. + The Contacts Provider automatically increments this value whenever the row or + its related data changes. +
    {@link android.provider.ContactsContract.Data}{@link android.provider.ContactsContract.DataColumns#DATA_VERSION}The version number of this row. + The Contacts Provider automatically increments this value whenever the data row + is changed. +
    {@link android.provider.ContactsContract.RawContacts}{@link android.provider.ContactsContract.SyncColumns#SOURCE_ID} + A string value that uniquely identifies this raw contact to the account in + which it was created. + + When a sync adapter creates a new raw contact, this column should be set to the + server's unique ID for the raw contact. When an Android application creates a new + raw contact, the application should leave this column empty. This signals the sync + adapter that it should create a new raw contact on the server, and get a + value for the {@link android.provider.ContactsContract.SyncColumns#SOURCE_ID}. +

    + In particular, the source id must be unique for each account + type and should be stable across syncs: +

    +
      +
    • + Unique: Each raw contact for an account must have its own source id. If you + don't enforce this, you'll cause problems in the contacts application. + Notice that two raw contacts for the same account type may have + the same source id. For example, the raw contact "Thomas Higginson" for the + account {@code emily.dickinson@gmail.com} is allowed to have the same source + id as the raw contact "Thomas Higginson" for the account + {@code emilyd@gmail.com}. +
    • +
    • + Stable: Source ids are a permanent part of the online service's data for + the raw contact. For example, if the user clears Contacts Storage from the + Apps settings and re-syncs, the restored raw contacts should have the same + source ids as before. If you don't enforce this, shortcuts will stop + working. +
    • +
    +
    {@link android.provider.ContactsContract.Groups}{@link android.provider.ContactsContract.GroupsColumns#GROUP_VISIBLE}"0" - Contacts in this group should not be visible in Android application UIs. + This column is for compatibility with servers that allow a user to hide contacts in + certain groups. +
    "1" - Contacts in this group are allowed to be visible in application UIs.
    {@link android.provider.ContactsContract.Settings} + {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE} + "0" - For this account and account type, contacts that don't belong to a group are + invisible to Android application UIs. + + By default, contacts are invisible if none of their raw contacts belongs to a group + (Group membership for a raw contact is indicated by one or more + {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} rows + in the {@link android.provider.ContactsContract.Data} table). + By setting this flag in the {@link android.provider.ContactsContract.Settings} table row + for an account type and account, you can force contacts without groups to be visible. + One use of this flag is to show contacts from servers that don't use groups. +
    + "1" - For this account and account type, contacts that don't belong to a group are + visible to application UIs. +
    {@link android.provider.ContactsContract.SyncState}(all) + Use this table to store metadata for your sync adapter. + + With this table you can store sync state and other sync-related data persistently on + the device. +
    +

    Contacts Provider Access

    +

    + This section describes guidelines for accessing data from the Contacts Provider, focusing on + the following: +

    +
      +
    • + Entity queries. +
    • +
    • + Batch modification. +
    • +
    • + Retrieval and modification with intents. +
    • +
    • + Data integrity. +
    • +
    +

    + Making modifications from a sync adapter is also covered in more detail in the section + Contacts Provider Sync Adapters. +

    +

    Querying entities

    +

    + Because the Contacts Provider tables are organized in a hierarchy, it's often useful to + retrieve a row and all of the "child" rows that are linked to it. For example, to display + all the information for a person, you may want to retrieve all the + {@link android.provider.ContactsContract.RawContacts} rows for a single + {@link android.provider.ContactsContract.Contacts} row, or all the + {@link android.provider.ContactsContract.CommonDataKinds.Email} rows for a single + {@link android.provider.ContactsContract.RawContacts} row. To facilitate this, the Contacts + Provider offers entity constructs, which act like database joins between + tables. +

    +

    + An entity is like a table composed of selected columns from a parent table and its child table. + When you query an entity, you supply a projection and search criteria based on the columns + available from the entity. The result is a {@link android.database.Cursor} that contains + contains one row for each child table row that was retrieved. For example, if you query + {@link android.provider.ContactsContract.Contacts.Entity} for a contact name + and all the {@link android.provider.ContactsContract.CommonDataKinds.Email} rows for all the + raw contacts for that name, you get back a {@link android.database.Cursor} containing one row + for each {@link android.provider.ContactsContract.CommonDataKinds.Email} row. +

    +

    + Entities simplify queries. Using an entity, you can retrieve all of the contacts data for a + contact or raw contact at once, instead of having to query the parent table first to get an + ID, and then having to query the child table with that ID. Also, the Contacts Provider processes + a query against an entity in a single transaction, which ensures that the retrieved data is + internally consistent. +

    +

    + Note: An entity usually doesn't contain all the columns of the parent and + child table. If you attempt to work with a column name that isn't in the list of column name + constants for the entity, you'll get an {@link java.lang.Exception}. +

    +

    + The following snippet shows how to retrieve all the raw contact rows for a contact. The snippet + is part of a larger application that has two activities, "main" and "detail". The main activity + shows a list of contact rows; when the user select one, the activity sends its ID to the detail + activity. The detail activity uses the {@link android.provider.ContactsContract.Contacts.Entity} + to display all of the data rows from all of the raw contacts associated with the selected + contact. +

    +

    + This snippet is taken from the "detail" activity: +

    +
    +...
    +    /*
    +     * Appends the entity path to the URI. In the case of the Contacts Provider, the
    +     * expected URI is content://com.google.contacts/#/entity (# is the ID value).
    +     */
    +    mContactUri = Uri.withAppendedPath(
    +            mContactUri,
    +            ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);
    +
    +    // Initializes the loader identified by LOADER_ID.
    +    getLoaderManager().initLoader(
    +            LOADER_ID,  // The identifier of the loader to initialize
    +            null,       // Arguments for the loader (in this case, none)
    +            this);      // The context of the activity
    +
    +    // Creates a new cursor adapter to attach to the list view
    +    mCursorAdapter = new SimpleCursorAdapter(
    +            this,                        // the context of the activity
    +            R.layout.detail_list_item,   // the view item containing the detail widgets
    +            mCursor,                     // the backing cursor
    +            mFromColumns,                // the columns in the cursor that provide the data
    +            mToViews,                    // the views in the view item that display the data
    +            0);                          // flags
    +
    +    // Sets the ListView's backing adapter.
    +    mRawContactList.setAdapter(mCursorAdapter);
    +...
    +@Override
    +public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    +
    +    /*
    +     * Sets the columns to retrieve.
    +     * RAW_CONTACT_ID is included to identify the raw contact associated with the data row.
    +     * DATA1 contains the first column in the data row (usually the most important one).
    +     * MIMETYPE indicates the type of data in the data row.
    +     */
    +    String[] projection =
    +        {
    +            ContactsContract.Contacts.Entity.RAW_CONTACT_ID,
    +            ContactsContract.Contacts.Entity.DATA1,
    +            ContactsContract.Contacts.Entity.MIMETYPE
    +        };
    +
    +    /*
    +     * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw
    +     * contact collated together.
    +     */
    +    String sortOrder =
    +            ContactsContract.Contacts.Entity.RAW_CONTACT_ID +
    +            " ASC";
    +
    +    /*
    +     * Returns a new CursorLoader. The arguments are similar to
    +     * ContentResolver.query(), except for the Context argument, which supplies the location of
    +     * the ContentResolver to use.
    +     */
    +    return new CursorLoader(
    +            getApplicationContext(),  // The activity's context
    +            mContactUri,              // The entity content URI for a single contact
    +            projection,               // The columns to retrieve
    +            null,                     // Retrieve all the raw contacts and their data rows.
    +            null,                     //
    +            sortOrder);               // Sort by the raw contact ID.
    +}
    +
    +

    + When the load is finished, {@link android.app.LoaderManager} invokes a callback to + {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished(Loader, D) + onLoadFinished()}. One of the incoming arguments to this method is a + {@link android.database.Cursor} with the results of the query. In your own app, you can get the + data from this {@link android.database.Cursor} to display it or work with it further. +

    +

    Batch modification

    +

    + Whenever possible, you should insert, update, and delete data in the Contacts Provider in + "batch mode", by creating an {@link java.util.ArrayList} of + {@link android.content.ContentProviderOperation} objects and calling + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. Because + the Contacts Provider performs all of the operations in an + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} in a single + transaction, your modifications will never leave the contacts repository in an inconsistent + state. A batch modification also facilitates inserting a raw contact and its detail data at + the same time. +

    +

    + Note: To modify a single raw contact, consider sending an intent to + the device's contacts application rather than handling the modification in your app. + Doing this is described in more detail in the section + Retrieval and modification with intents. +

    +

    Yield points

    +

    + A batch modification containing a large number of operations can block other processes, + resulting in a bad overall user experience. To organize all the modifications you want to + perform in as few separate lists as possible, and at the same time prevent them from + blocking the system, you should set yield points for one or more operations. + A yield point is a {@link android.content.ContentProviderOperation} object that has its + {@link android.content.ContentProviderOperation#isYieldAllowed()} value set to + true. When the Contacts Provider encounters a yield point, it pauses its work to + let other processes run and closes the current transaction. When the provider starts again, it + continues with the next operation in the {@link java.util.ArrayList} and starts a new + transaction. +

    +

    + Yield points do result in more than one transaction per call to + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. Because of + this, you should set a yield point for the last operation for a set of related rows. + For example, you should set a yield point for the last operation in a set that adds a + raw contact rows and its associated data rows, or the last operation for a set of rows related + to a single contact. +

    +

    + Yield points are also a unit of atomic operation. All accesses between two yield points will + either succeed or fail as a single unit. If you don't set any yield points, the smallest + atomic operation is the entire batch of operations. If you do use yield points, you prevent + operations from degrading system performance, while at the same time ensuring that a subset of + operations is atomic. +

    +

    Modification back references

    +

    + When you're inserting a new raw contact row and its associated data rows as a set of + {@link android.content.ContentProviderOperation} objects, you have to link the data rows to + the raw contact row by inserting the raw contact's + {@link android.provider.BaseColumns#_ID} value as the + {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID} value. However, this + value isn't available when you're creating the {@link android.content.ContentProviderOperation} + for the data row, because you haven't yet applied the + {@link android.content.ContentProviderOperation} for the raw contact row. To work around this, + the {@link android.content.ContentProviderOperation.Builder} class has the method + {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}. + This method allows you to insert or modify a column with the + result of a previous operation. +

    +

    + The {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} + method has two arguments: +

    +
    +
    + key +
    +
    + The key of a key-value pair. The value of this argument should be the name of a column + in the table that you're modifying. +
    +
    + previousResult +
    +
    + The 0-based index of a value in the array of + {@link android.content.ContentProviderResult} objects from + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. As + the batch operations are applied, the result of each operation is stored in an + intermediate array of results. The previousResult value is the index + of one of these results, which is retrieved and stored with the key + value. This allows you to insert a new raw contact record and get back its + {@link android.provider.BaseColumns#_ID} value, then make a "back reference" to the + value when you add a {@link android.provider.ContactsContract.Data} row. +

    + The entire result array is created when you first call + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}, + with a size equal to the size of the {@link java.util.ArrayList} of + {@link android.content.ContentProviderOperation} objects you provide. However, all + the elements in the result array are set to null, and if you try + to do a back reference to a result for an operation that hasn't yet been applied, +{@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} + throws an {@link java.lang.Exception}. + +

    +
    +
    +

    + The following snippets show how to insert a new raw contact and data in batch. They + includes code that establishes a yield point and uses a back reference. The snippets are an + expanded version of the createContacEntry() method, which is part of the + ContactAdder class in the + + Contact Manager sample application. +

    +

    + The first snippet retrieves contact data from the UI. At this point, the user has already + selected the account for which the new raw contact should be added. +

    +
    +// Creates a contact entry from the current UI values, using the currently-selected account.
    +protected void createContactEntry() {
    +    /*
    +     * Gets values from the UI
    +     */
    +    String name = mContactNameEditText.getText().toString();
    +    String phone = mContactPhoneEditText.getText().toString();
    +    String email = mContactEmailEditText.getText().toString();
    +
    +    int phoneType = mContactPhoneTypes.get(
    +            mContactPhoneTypeSpinner.getSelectedItemPosition());
    +
    +    int emailType = mContactEmailTypes.get(
    +            mContactEmailTypeSpinner.getSelectedItemPosition());
    +
    +

    + The next snippet creates an operation to insert the raw contact row into the + {@link android.provider.ContactsContract.RawContacts} table: +

    +
    +    /*
    +     * Prepares the batch operation for inserting a new raw contact and its data. Even if
    +     * the Contacts Provider does not have any data for this person, you can't add a Contact,
    +     * only a raw contact. The Contacts Provider will then add a Contact automatically.
    +     */
    +
    +     // Creates a new array of ContentProviderOperation objects.
    +    ArrayList<ContentProviderOperation> ops =
    +            new ArrayList<ContentProviderOperation>();
    +
    +    /*
    +     * Creates a new raw contact with its account type (server type) and account name
    +     * (user's account). Remember that the display name is not stored in this row, but in a
    +     * StructuredName data row. No other data is required.
    +     */
    +    ContentProviderOperation.Builder op =
    +            ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
    +            .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType())
    +            .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());
    +
    +    // Builds the operation and adds it to the array of operations
    +    ops.add(op.build());
    +
    +

    + Next, the code creates data rows for the display name, phone, and email rows. +

    +

    + Each operation builder object uses + {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} + to get the + {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}. The reference points + back to the {@link android.content.ContentProviderResult} object from the first operation, + which adds the raw contact row and returns its new {@link android.provider.BaseColumns#_ID} + value. As a result, each data row is automatically linked by its + {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID} + to the new {@link android.provider.ContactsContract.RawContacts} row to which it belongs. +

    +

    + The {@link android.content.ContentProviderOperation.Builder} object that adds the email row is + flagged with {@link android.content.ContentProviderOperation.Builder#withYieldAllowed(boolean) + withYieldAllowed()}, which sets a yield point: +

    +
    +    // Creates the display name for the new raw contact, as a StructuredName data row.
    +    op =
    +            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
    +            /*
    +             * withValueBackReference sets the value of the first argument to the value of
    +             * the ContentProviderResult indexed by the second argument. In this particular
    +             * call, the raw contact ID column of the StructuredName data row is set to the
    +             * value of the result returned by the first operation, which is the one that
    +             * actually adds the raw contact row.
    +             */
    +            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
    +
    +            // Sets the data row's MIME type to StructuredName
    +            .withValue(ContactsContract.Data.MIMETYPE,
    +                    ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
    +
    +            // Sets the data row's display name to the name in the UI.
    +            .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
    +
    +    // Builds the operation and adds it to the array of operations
    +    ops.add(op.build());
    +
    +    // Inserts the specified phone number and type as a Phone data row
    +    op =
    +            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
    +            /*
    +             * Sets the value of the raw contact id column to the new raw contact ID returned
    +             * by the first operation in the batch.
    +             */
    +            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
    +
    +            // Sets the data row's MIME type to Phone
    +            .withValue(ContactsContract.Data.MIMETYPE,
    +                    ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
    +
    +            // Sets the phone number and type
    +            .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
    +            .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType);
    +
    +    // Builds the operation and adds it to the array of operations
    +    ops.add(op.build());
    +
    +    // Inserts the specified email and type as a Phone data row
    +    op =
    +            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
    +            /*
    +             * Sets the value of the raw contact id column to the new raw contact ID returned
    +             * by the first operation in the batch.
    +             */
    +            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
    +
    +            // Sets the data row's MIME type to Email
    +            .withValue(ContactsContract.Data.MIMETYPE,
    +                    ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
    +
    +            // Sets the email address and type
    +            .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email)
    +            .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType);
    +
    +    /*
    +     * Demonstrates a yield point. At the end of this insert, the batch operation's thread
    +     * will yield priority to other threads. Use after every set of operations that affect a
    +     * single contact, to avoid degrading performance.
    +     */
    +    op.withYieldAllowed(true);
    +
    +    // Builds the operation and adds it to the array of operations
    +    ops.add(op.build());
    +
    +

    + The last snippet shows the call to + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} that + inserts the new raw contact and data rows. +

    +
    +    // Ask the Contacts Provider to create a new contact
    +    Log.d(TAG,"Selected account: " + mSelectedAccount.getName() + " (" +
    +            mSelectedAccount.getType() + ")");
    +    Log.d(TAG,"Creating contact: " + name);
    +
    +    /*
    +     * Applies the array of ContentProviderOperation objects in batch. The results are
    +     * discarded.
    +     */
    +    try {
    +
    +            getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
    +    } catch (Exception e) {
    +
    +            // Display a warning
    +            Context ctx = getApplicationContext();
    +
    +            CharSequence txt = getString(R.string.contactCreationFailure);
    +            int duration = Toast.LENGTH_SHORT;
    +            Toast toast = Toast.makeText(ctx, txt, duration);
    +            toast.show();
    +
    +            // Log exception
    +            Log.e(TAG, "Exception encountered while inserting contact: " + e);
    +    }
    +}
    +
    +

    + Batch operations also allow you to implement optimistic concurrency control, + a method of applying modification transactions without having to lock the underlying repository. + To use this method, you apply the transaction and then check for other modifications that + may have been made at the same time. If you find an inconsistent modification has occurred, you + roll back your transaction and retry it. +

    +

    + Optimistic concurrency control is useful for a mobile device, where there's only one user at + a time, and simultaneous accesses to a data repository are rare. Because locking isn't used, + no time is wasted on setting locks or waiting for other transactions to release their locks. +

    +

    + To use optimistic concurrency control while updating a single + {@link android.provider.ContactsContract.RawContacts} row, follow these steps: +

    +
      +
    1. + Retrieve the raw contact's {@link android.provider.ContactsContract.SyncColumns#VERSION} + column along with the other data you retrieve. +
    2. +
    3. + Create a {@link android.content.ContentProviderOperation.Builder} object suitable for + enforcing a constraint, using the method + {@link android.content.ContentProviderOperation#newAssertQuery(Uri)}. For the content URI, + use {@link android.provider.ContactsContract.RawContacts#CONTENT_URI + RawContacts.CONTENT_URI} + with the raw contact's {@link android.provider.BaseColumns#_ID} appended to it. +
    4. +
    5. + For the {@link android.content.ContentProviderOperation.Builder} object, call + {@link android.content.ContentProviderOperation.Builder#withValue(String, Object) + withValue()} to compare the {@link android.provider.ContactsContract.SyncColumns#VERSION} + column to the version number you just retrieved. +
    6. +
    7. + For the same {@link android.content.ContentProviderOperation.Builder}, call + {@link android.content.ContentProviderOperation.Builder#withExpectedCount(int) + withExpectedCount()} to ensure that only one row is tested by this assertion. +
    8. +
    9. + Call {@link android.content.ContentProviderOperation.Builder#build()} to create the + {@link android.content.ContentProviderOperation} object, then add this object as the + first object in the {@link java.util.ArrayList} that you pass to + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. +
    10. +
    11. + Apply the batch transaction. +
    12. +
    +

    + If the raw contact row is updated by another operation between the time you read the row and + the time you attempt to modify it, the "assert" {@link android.content.ContentProviderOperation} + will fail, and the entire batch of operations will be backed out. You can then choose to retry + the batch or take some other action. +

    +

    + The following snippet demonstrates how to create an "assert" + {@link android.content.ContentProviderOperation} after querying for a single raw contact using + a {@link android.content.CursorLoader}: +

    +
    +/*
    + * The application uses CursorLoader to query the raw contacts table. The system calls this method
    + * when the load is finished.
    + */
    +public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    +
    +    // Gets the raw contact's _ID and VERSION values
    +    mRawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));
    +    mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION));
    +}
    +
    +...
    +
    +// Sets up a Uri for the assert operation
    +Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactID);
    +
    +// Creates a builder for the assert operation
    +ContentProviderOperation.Builder assertOp = ContentProviderOperation.netAssertQuery(rawContactUri);
    +
    +// Adds the assertions to the assert operation: checks the version and count of rows tested
    +assertOp.withValue(SyncColumns.VERSION, mVersion);
    +assertOp.withExpectedCount(1);
    +
    +// Creates an ArrayList to hold the ContentProviderOperation objects
    +ArrayList ops = new ArrayList<ContentProviderOperationg>;
    +
    +ops.add(assertOp.build());
    +
    +// You would add the rest of your batch operations to "ops" here
    +
    +...
    +
    +// Applies the batch. If the assert fails, an Exception is thrown
    +try
    +    {
    +        ContentProviderResult[] results =
    +                getContentResolver().applyBatch(AUTHORITY, ops);
    +
    +    } catch (OperationApplicationException e) {
    +
    +        // Actions you want to take if the assert operation fails go here
    +    }
    +
    +

    Retrieval and modification with intents

    +

    + Sending an intent to the device's contacts application allows you to access the Contacts + Provider indirectly. The intent starts the device's contacts application UI, in which users can + do contacts-related work. With this type of access, users can: +

      +
    • Pick a contact from a list and have it returned to your app for further work.
    • +
    • Edit an existing contact's data.
    • +
    • Insert a new raw contact for any of their accounts.
    • +
    • Delete a contact or contacts data.
    • +
    +

    + If the user is inserting or updating data, you can collect the data first and send it as + part of the intent. +

    +

    + When you use intents to access the Contacts Provider via the device's contacts application, you + don't have to write your own UI or code for accessing the provider. You also don't have to + request permission to read or write to the provider. The device's contacts application can + delegate read permission for a contact to you, and because you're making modifications to the + provider through another application, you don't have to have write permissions. +

    +

    + The general process of sending an intent to access a provider is described in detail in the + + Content Provider Basics guide in the section "Data access via intents." The action, + MIME type, and data values you use for the available tasks are summarized in Table 4, while the + extras values you can use with + {@link android.content.Intent#putExtra(String, String) putExtra()} are listed in the + reference documentation for {@link android.provider.ContactsContract.Intents.Insert}: +

    +

    + Table 4. Contacts Provider Intents. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    TaskActionDataMIME typeNotes
    Pick a contact from a list{@link android.content.Intent#ACTION_PICK} + One of: +
      +
    • +{@link android.provider.ContactsContract.Contacts#CONTENT_URI Contacts.CONTENT_URI}, + which displays a list of contacts. +
    • +
    • +{@link android.provider.ContactsContract.CommonDataKinds.Phone#CONTENT_URI Phone.CONTENT_URI}, + which displays a list of phone numbers for a raw contact. +
    • +
    • +{@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal#CONTENT_URI +StructuredPostal.CONTENT_URI}, + which displays a list of postal addresses for a raw contact. +
    • +
    • +{@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_URI Email.CONTENT_URI}, + which displays a list of email addresses for a raw contact. +
    • +
    +
    + Not used + + Displays a list of raw contacts or a list of data from a raw contact, depending on the + content URI type you supply. +

    + Call + {@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()}, + which returns the content URI of the selected row. The form of the URI is the + table's content URI with the row's LOOKUP_ID appended to it. + The device's contacts app delegates read and write permissions to this content URI + for the life of your activity. See the + + Content Provider Basics guide for more details. +

    +
    Insert a new raw contact{@link android.provider.ContactsContract.Intents.Insert#ACTION Insert.ACTION}N/A + {@link android.provider.ContactsContract.RawContacts#CONTENT_TYPE + RawContacts.CONTENT_TYPE}, MIME type for a set of raw contacts. + + Displays the device's contacts application's Add Contact screen. The + extras values you add to the intent are displayed. If sent with + {@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()}, + the content URI of the newly-added raw contact is passed back to your activity's + {@link android.app.Activity#onActivityResult(int, int, Intent) onActivityResult()} + callback method in the {@link android.content.Intent} argument, in the + "data" field. To get the value, call {@link android.content.Intent#getData()}. +
    Edit a contact{@link android.content.Intent#ACTION_EDIT} + {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} for + the contact. The editor activity will allow the user to edit any of the data associated + with this contact. + + {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE + Contacts.CONTENT_ITEM_TYPE}, a single contact. + Displays the Edit Contact screen in the contacts application. The extras values you add + to the intent are displayed. When the user clicks Done to save the + edits, your activity returns to the foreground. +
    Display a picker that can also add data.{@link android.content.Intent#ACTION_INSERT_OR_EDIT} + N/A + + {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE} + + This intent always displays the contacts app's picker screen. The user can either + pick a contact to edit, or add a new contact. Either the edit or the add screen + appears, depending on the user's choice, and the extras data you pass in the intent + is displayed. If your app displays contact data such as an email or phone number, use + this intent to allow the user to add the data to an existing contact. + contact, +

    + Note: There's no need to send a name value in this intent's extras, + because the user always picks an existing name or adds a new one. Moreover, + if you send a name, and the user chooses to do an edit, the contacts app will + display the name you send, overwriting the previous value. If the user doesn't + notice this and saves the edit, the old value is lost. +

    +
    +

    + The device's contacts app doesn't allow you to delete a raw contact or any of its data with an + intent. Instead, to delete a raw contact, use + {@link android.content.ContentResolver#delete(Uri, String, String[]) ContentResolver.delete()} + or {@link android.content.ContentProviderOperation#newDelete(Uri) + ContentProviderOperation.newDelete()}. +

    +

    + The following snippet shows how to construct and send an intent that inserts a new raw + contact and data: +

    +
    +// Gets values from the UI
    +String name = mContactNameEditText.getText().toString();
    +String phone = mContactPhoneEditText.getText().toString();
    +String email = mContactEmailEditText.getText().toString();
    +
    +String company = mCompanyName.getText().toString();
    +String jobtitle = mJobTitle.getText().toString();
    +
    +// Creates a new intent for sending to the device's contacts application
    +Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION);
    +
    +// Sets the MIME type to the one expected by the insertion activity
    +insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
    +
    +// Sets the new contact name
    +insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name);
    +
    +// Sets the new company and job title
    +insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company);
    +insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle);
    +
    +/*
    + * Demonstrates adding data rows as an array list associated with the DATA key
    + */
    +
    +// Defines an array list to contain the ContentValues objects for each row
    +ArrayList<ContentValues> contactData = new ArrayList<ContentValues>();
    +
    +
    +/*
    + * Defines the raw contact row
    + */
    +
    +// Sets up the row as a ContentValues object
    +ContentValues rawContactRow = new ContentValues();
    +
    +// Adds the account type and name to the row
    +rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType());
    +rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());
    +
    +// Adds the row to the array
    +contactData.add(rawContactRow);
    +
    +/*
    + * Sets up the phone number data row
    + */
    +
    +// Sets up the row as a ContentValues object
    +ContentValues phoneRow = new ContentValues();
    +
    +// Specifies the MIME type for this data row (all data rows must be marked by their type)
    +phoneRow.put(
    +        ContactsContract.Data.MIMETYPE,
    +        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
    +);
    +
    +// Adds the phone number and its type to the row
    +phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);
    +
    +// Adds the row to the array
    +contactData.add(phoneRow);
    +
    +/*
    + * Sets up the email data row
    + */
    +
    +// Sets up the row as a ContentValues object
    +ContentValues emailRow = new ContentValues();
    +
    +// Specifies the MIME type for this data row (all data rows must be marked by their type)
    +emailRow.put(
    +        ContactsContract.Data.MIMETYPE,
    +        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE
    +);
    +
    +// Adds the email address and its type to the row
    +emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email);
    +
    +// Adds the row to the array
    +contactData.add(emailRow);
    +
    +/*
    + * Adds the array to the intent's extras. It must be a parcelable object in order to
    + * travel between processes. The device's contacts app expects its key to be
    + * Intents.Insert.DATA
    + */
    +insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData);
    +
    +// Send out the intent to start the device's contacts app in its add contact activity.
    +startActivity(insertIntent);
    +
    +

    Data integrity

    +

    + Because the contacts repository contains important and sensitive data that users expect to be + correct and up-to-date, the Contacts Provider has well-defined rules for data integrity. It's + your responsibility to conform to these rules when you modify contacts data. The important + rules are listed here: +

    +
    +
    + Always add a {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} row + for every {@link android.provider.ContactsContract.RawContacts} row you add. +
    +
    + A {@link android.provider.ContactsContract.RawContacts} row without a + {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} row in the + {@link android.provider.ContactsContract.Data} table may cause problems during + aggregation. +
    +
    + Always link new {@link android.provider.ContactsContract.Data} rows to their parent + {@link android.provider.ContactsContract.RawContacts} row. +
    +
    + A {@link android.provider.ContactsContract.Data} row that isn't linked to a + {@link android.provider.ContactsContract.RawContacts} won't be visible in the device's + contacts application, and it might cause problems with sync adapters. +
    +
    + Change data only for those raw contacts that you own. +
    +
    + Remember that the Contacts Provider is usually managing data from several different + account types/online services. You need to ensure that your application only modifies + or deletes data for rows that belong to you, and that it only inserts data with an + account type and name that you control. +
    +
    + Always use the constants defined in {@link android.provider.ContactsContract} and its + subclasses for authorities, content URIs, URI paths, column names, MIME types, and + {@link android.provider.ContactsContract.CommonDataKinds.CommonColumns#TYPE} values. +
    +
    + Using these constants helps you to avoid errors. You'll also be notified with compiler + warnings if any of the constants is deprecated. +
    +
    +

    Custom data rows

    +

    + By creating and using your own custom MIME types, you can insert, edit, delete, and retrieve + your own data rows in the {@link android.provider.ContactsContract.Data} table. Your rows + are limited to using the column defined in + {@link android.provider.ContactsContract.DataColumns}, although you can map your own + type-specific column names to the default column names. In the device's contacts application, + the data for your rows is displayed but can't be edited or deleted, and users can't add + additional data. To allow users to modify your custom data rows, you must provide an editor + activity in your own application. +

    +

    + To display your custom data, provide a contacts.xml file containing a + <ContactsAccountType> element and one or more of its + <ContactsDataKind> child elements. This is described in more detail in the + section <ContactsDataKind> element. +

    +

    + To learn more about custom MIME types, read the + + Creating a Content Provider guide. +

    +

    Contacts Provider Sync Adapters

    +

    + The Contacts Provider is specifically designed for handling synchronization + of contacts data between a device and an online service. This allows users to download + existing data to a new device and upload existing data to a new account. + Synchronization also ensures that users have the latest data at hand, regardless + of the source of additions and changes. Another advantage of synchronization is that it makes + contacts data available even when the device is not connected to the network. +

    +

    + Although you can implement synchronization in a variety of ways, the Android system provides + a plug-in synchronization framework that automates the following tasks: +

      + +
    • + Checking network availability. +
    • +
    • + Scheduling and executing synchronization, based on user preferences. +
    • +
    • + Restarting synchronizations that have stopped. +
    • +
    +

    + To use this framework, you supply a sync adapter plug-in. Each sync adapter is unique to a + service and content provider, but can handle multiple account names for the same service. The + framework also allows multiple sync adapters for the same service and provider. +

    +

    Sync adapter classes and files

    +

    + You implement a sync adapter as a subclass of + {@link android.content.AbstractThreadedSyncAdapter} and install it as part of an Android + application. The system learns about the sync adapter from elements in your application + manifest, and from a special XML file pointed to by the manifest. The XML file defines the + account type for the online service and the authority for the content provider, which together + uniquely identify the adapter. The sync adapter does not become active until the user adds an + account for the sync adapter's account type and enables synchronization for the content + provider the sync adapter syncs with. At that point, the system starts managing the adapter, + calling it as necessary to synchronize between the content provider and the server. +

    +

    + Note: Using an account type as part of the sync adapter's identification allows + the system to detect and group together sync adapters that access different services from the + same organization. For example, sync adapters for Google online services all have the same + account type com.google. When users add a Google account to their devices, all + of the installed sync adapters for Google services are listed together; each sync adapter + listed syncs with a different content provider on the device. +

    +

    + Because most services require users to verify their identity before accessing + data, the Android system offers an authentication framework that is similar to, and often + used in conjunction with, the sync adapter framework. The authentication framework uses + plug-in authenticators that are subclasses of + {@link android.accounts.AbstractAccountAuthenticator}. An authenticator verifies + the user's identity in the following steps: +

      +
    1. + Collects the user's name, password or similar information (the user's + credentials). +
    2. +
    3. + Sends the credentials to the service +
    4. +
    5. + Examines the service's reply. +
    6. +
    +

    + If the service accepts the credentials, the authenticator can + store the credentials for later use. Because of the plug-in authenticator framework, the + {@link android.accounts.AccountManager} can provide access to any authtokens an authenticator + supports and chooses to expose, such as OAuth2 authtokens. +

    +

    + Although authentication is not required, most contacts services use it. + However, you're not required to use the Android authentication framework to do authentication. +

    +

    Sync adapter implementation

    +

    + To implement a sync adapter for the Contacts Provider, you start by creating an + Android application that contains the following: +

    +
    +
    + A {@link android.app.Service} component that responds to requests from the system to + bind to the sync adapter. +
    +
    + When the system wants to run a synchronization, it calls the service's + {@link android.app.Service#onBind(Intent) onBind()} method to get an + {@link android.os.IBinder} for the sync adapter. This allows the system to do + cross-process calls to the adapter's methods. +

    + In the + Sample Sync Adapter sample app, the class name of this service is + com.example.android.samplesync.syncadapter.SyncService. +

    +
    +
    + The actual sync adapter, implemented as a concrete subclass of + {@link android.content.AbstractThreadedSyncAdapter}. +
    +
    + This class does the work of downloading data from the server, uploading data from the + device, and resolving conflicts. The main work of the adapter is + done in the method {@link android.content.AbstractThreadedSyncAdapter#onPerformSync( + Account, Bundle, String, ContentProviderClient, SyncResult) + onPerformSync()}. This class must be instantiated as a singleton. +

    + In the + Sample Sync Adapter sample app, the sync adapter is defined in the class + com.example.android.samplesync.syncadapter.SyncAdapter. +

    +
    +
    + A subclass of {@link android.app.Application}. +
    +
    + This class acts as a factory for the sync adapter singleton. Use the + {@link android.app.Application#onCreate()} method to instantiate the sync adapter, and + provide a static "getter" method to return the singleton to the + {@link android.app.Service#onBind(Intent) onBind()} method of the sync adapter's + service. +
    +
    + Optional: A {@link android.app.Service} component that responds to + requests from the system for user authentication. +
    +
    + {@link android.accounts.AccountManager} starts this service to begin the authentication + process. The service's {@link android.app.Service#onCreate()} method instantiates an + authenticator object. When the system wants to authenticate a user account for the + application's sync adapter, it calls the service's + {@link android.app.Service#onBind(Intent) onBind()} method to get an + {@link android.os.IBinder} for the authenticator. This allows the system to do + cross-process calls to the authenticator's methods.. +

    + In the + Sample Sync Adapter sample app, the class name of this service is + com.example.android.samplesync.authenticator.AuthenticationService. +

    +
    +
    + Optional: A concrete subclass of + {@link android.accounts.AbstractAccountAuthenticator} that handles requests for + authentication. +
    +
    + This class provides methods that the {@link android.accounts.AccountManager} invokes + to authenticate the user's credentials with the server. The details of the + authentication process vary widely, based on the server technology in use. You should + refer to the documentation for your server software to learn more about authentication. +

    + In the + Sample Sync Adapter sample app, the authenticator is defined in the class + com.example.android.samplesync.authenticator.Authenticator. +

    +
    +
    + XML files that define the sync adapter and authenticator to the system. +
    +
    + The sync adapter and authenticator service components described previously are + defined in +<service> + elements in the application manifest. These elements + contain +<meta-data> +child elements that provide specific data to the + system: +
      +
    • + The +<meta-data> + element for the sync adapter service points to the + XML file res/xml/syncadapter.xml. In turn, this file specifies + a URI for the web service that will be synchronized with the Contacts Provider, + and an account type for the web service. +
    • +
    • + Optional: The +<meta-data> + element for the authenticator points to the XML file + res/xml/authenticator.xml. In turn, this file specifies the + account type that this authenticator supports, as well as UI resources that + appear during the authentication process. The account type specified in this + element must be the same as the account type specified for the sync + adapter. +
    • +
    +
    +
    +

    Social Stream Data

    +

    + The {@link android.provider.ContactsContract.StreamItems} and + {@link android.provider.ContactsContract.StreamItemPhotos} tables + manage incoming data from social networks. You can write a sync adapter that adds stream data + from your own network to these tables, or you can read stream data from these tables and + display it in your own application, or both. With these features, your social networking + services and applications can be integrated into Android's social networking experience. +

    +

    Social stream text

    +

    + Stream items are always associated with a raw contact. The + {@link android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID} links to the + _ID value for the raw contact. The account type and account name of the raw + contact are also stored in the stream item row. +

    +

    + Store the data from your stream in the following columns: +

    +
    +
    + {@link android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE} +
    +
    + Required. The user's account type for the raw contact associated with this + stream item. Remember to set this value when you insert a stream item. +
    +
    + {@link android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME} +
    +
    + Required. The user's account name for the raw contact associated with this + stream item. Remember to set this value when you insert a stream item. +
    +
    + Identifier columns +
    +
    + Required. You must insert the following identifier columns when you + insert a stream item: +
      +
    • + {@link android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID}: The + {@link android.provider.BaseColumns#_ID} value of the contact that this stream + item is associated with. +
    • +
    • + {@link android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY}: The + {@link android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} value of the + contact this stream item is associated with. +
    • +
    • + {@link android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}: The + {@link android.provider.BaseColumns#_ID} value of the raw contact that this stream + item is associated with. +
    • +
    +
    +
    + {@link android.provider.ContactsContract.StreamItemsColumns#COMMENTS} +
    +
    + Optional. Stores summary information that you can display at the beginning of a stream item. +
    +
    + {@link android.provider.ContactsContract.StreamItemsColumns#TEXT} +
    +
    + The text of the stream item, either the content that was posted by the source of the item, + or a description of some action that generated the stream item. This column can contain + any formatting and embedded resource images that can be rendered by + {@link android.text.Html#fromHtml(String) fromHtml()}. The provider may truncate or + ellipsize long content, but it will try to avoid breaking tags. +
    +
    + {@link android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP} +
    +
    + A text string containing the time the stream item was inserted or updated, in the form + of milliseconds since epoch. Applications that insert or update stream items are + responsible for maintaining this column; it is not automatically maintained by the + Contacts Provider. +
    +
    +

    + To display identifying information for your stream items, use the + {@link android.provider.ContactsContract.StreamItemsColumns#RES_ICON}, + {@link android.provider.ContactsContract.StreamItemsColumns#RES_LABEL}, and + {@link android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE} to link to resources + in your application. +

    +

    + The {@link android.provider.ContactsContract.StreamItems} table also contains the columns + {@link android.provider.ContactsContract.StreamItemsColumns#SYNC1} through + {@link android.provider.ContactsContract.StreamItemsColumns#SYNC4} for the exclusive use of + sync adapters. +

    +

    Social stream photos

    +

    + The {@link android.provider.ContactsContract.StreamItemPhotos} table stores photos associated + with a stream item. The table's + {@link android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID} column + links to values in the {@link android.provider.BaseColumns#_ID} column of + {@link android.provider.ContactsContract.StreamItems} table. Photo references are stored in the + table in these columns: +

    +
    +
    + {@link android.provider.ContactsContract.StreamItemPhotos#PHOTO} column (a BLOB). +
    +
    + A binary representation of the photo, resized by the provider for storage and display. + This column is available for backwards compatibility with previous versions of the Contacts + Provider that used it for storing photos. However, in the current version + you should not use this column to store photos. Instead, use + either {@link android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} or + {@link android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} (both of + which are described in the following points) to store photos in a file. This column now + contains a thumbnail of the photo, which is available for reading. +
    +
    + {@link android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} +
    +
    + A numeric identifier of a photo for a raw contact. Append this value to the constant + {@link android.provider.ContactsContract.DisplayPhoto#CONTENT_URI DisplayPhoto.CONTENT_URI} + to get a content URI pointing to a single photo file, and then call + {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) + openAssetFileDescriptor()} to get a handle to the photo file. +
    +
    + {@link android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} +
    +
    + A content URI pointing directly to the photo file for the photo represented by this row. + Call {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) + openAssetFileDescriptor()} with this URI to get a handle to the photo file. +
    +
    +

    Using the social stream tables

    +

    + These tables work the same as the other main tables in the Contacts Provider, except that: +

    +
      +
    • + These tables require additional access permissions. To read from them, your application + must have the permission {@link android.Manifest.permission#READ_SOCIAL_STREAM}. To + modify them, your application must have the permission + {@link android.Manifest.permission#WRITE_SOCIAL_STREAM}. +
    • +
    • + For the {@link android.provider.ContactsContract.StreamItems} table, the number of rows + stored for each raw contact is limited. Once this limit is reached, + the Contacts Provider makes space for new stream item rows by automatically deleting + the rows having the oldest + {@link android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP}. To get the + limit, issue a query to the content URI + {@link android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI}. You can leave + all the arguments other than the content URI set to null. The query + returns a Cursor containing a single row, with the single column + {@link android.provider.ContactsContract.StreamItems#MAX_ITEMS}. +
    • +
    + +

    + The class {@link android.provider.ContactsContract.StreamItems.StreamItemPhotos} defines a + sub-table of {@link android.provider.ContactsContract.StreamItemPhotos} containing the photo + rows for a single stream item. +

    +

    Social stream interactions

    +

    + The social stream data managed by the Contacts Provider, in conjunction with the + device's contacts application, offers a powerful way to connect your social networking system + with existing contacts. The following features are available: +

    +
      +
    • + By syncing your social networking service to the Contacts Provider with a sync + adapter, you can retrieve recent activity for a user's contacts and store it in + the {@link android.provider.ContactsContract.StreamItems} and + {@link android.provider.ContactsContract.StreamItemPhotos} tables for later use. +
    • +
    • + Besides regular synchronization, you can trigger your sync adapter to retrieve + additional data when the user selects a contact to view. This allows your sync adapter + to retrieve high-resolution photos and the most recent stream items for the contact. +
    • +
    • + By registering a notification with the device's contacts application and the Contacts + Provider, you can receive an intent when a contact is viewed, and at that point + update the contact's status from your service. This approach may be faster and use less + bandwidth than doing a full sync with a sync adapter. +
    • +
    • + Users can add a contact to your social networking service while looking at the contact + in the device's contacts application. You enable this with the "invite contact" feature, + which you enable with a combination of an activity that adds an existing contact to your + network, and an XML file that provides the device's contacts application and the + Contacts Provider with the details of your application. +
    • +
    +

    + Regular synchronization of stream items with the Contacts Provider is the same as + other synchronizations. To learn more about synchronization, see the section + Contacts Provider Sync Adapters. Registering notifications and + inviting contacts are covered in the next two sections. +

    +

    Registering to handle social networking views

    +

    + To register your sync adapter to receive notifications when the user views a contact that's + managed by your sync adapter: +

    +
      +
    1. + Create a file named contacts.xml in your project's res/xml/ + directory. If you already have this file, you can skip this step. +
    2. +
    3. + In this file, add the element +<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. + If this element already exists, you can skip this step. +
    4. +
    5. + To register a service that is notified when the user opens a contact's detail page in + the device's contacts application, add the attribute + viewContactNotifyService="serviceclass" to the element, where + serviceclass is the fully-qualified classname of the service + that should receive the intent from the device's contacts application. For the notifier + service, use a class that extends {@link android.app.IntentService}, to allow the service to + receive intents. The data in the incoming intent contains the content URI of the raw + contact the user clicked. From the notifier service, you can bind to and then call your + sync adapter to update the data for the raw contact. +
    6. +
    +

    + To register an activity to be called when the user clicks on a stream item or photo or both: +

    +
      +
    1. + Create a file named contacts.xml in your project's res/xml/ + directory. If you already have this file, you can skip this step. +
    2. +
    3. + In this file, add the element +<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. + If this element already exists, you can skip this step. +
    4. +
    5. + To register one of your activities to handle the user clicking on a stream item in the + device's contacts application, add the attribute + viewStreamItemActivity="activityclass" to the element, where + activityclass is the fully-qualified classname of the activity + that should receive the intent from the device's contacts application. +
    6. +
    7. + To register one of your activities to handle the user clicking on a stream photo in the + device's contacts application, add the attribute + viewStreamItemPhotoActivity="activityclass" to the element, where + activityclass is the fully-qualified classname of the activity + that should receive the intent from the device's contacts application. +
    8. +
    +

    + The <ContactsAccountType> element is described in more detail in the + section <ContactsAccountType> element. +

    +

    + The incoming intent contains the content URI of the item or photo that the user clicked. + To have separate activities for text items and for photos, use both attributes in the same file. +

    +

    Interacting with your social networking service

    +

    + Users don't have to leave the device's contacts application to invite a contact to your social + networking site. Instead, you can have the device's contacts app send an intent for inviting the + contact to one of your activities. To set this up: +

    +
      +
    1. + Create a file named contacts.xml in your project's res/xml/ + directory. If you already have this file, you can skip this step. +
    2. +
    3. + In this file, add the element +<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. + If this element already exists, you can skip this step. +
    4. +
    5. + Add the following attributes: +
        +
      • inviteContactActivity="activityclass"
      • +
      • + inviteContactActionLabel="@string/invite_action_label" +
      • +
      + The activityclass value is the fully-qualified classname of the + activity that should receive the intent. The invite_action_label + value is a text string that's displayed in the Add Connection menu in the + device's contacts application. +
    6. +
    +

    + Note: ContactsSource is a deprecated tag name for + ContactsAccountType. +

    +

    contacts.xml reference

    +

    + The file contacts.xml contains XML elements that control the interaction of your + sync adapter and application with the contacts application and the Contacts Provider. These + elements are described in the following sections. +

    +

    <ContactsAccountType> element

    +

    + The <ContactsAccountType> element controls the interaction of your + application with the contacts application. It has the following syntax: +

    +
    +<ContactsAccountType
    +        xmlns:android="http://schemas.android.com/apk/res/android"
    +        inviteContactActivity="activity_name"
    +        inviteContactActionLabel="invite_command_text"
    +        viewContactNotifyService="view_notify_service"
    +        viewGroupActivity="group_view_activity"
    +        viewGroupActionLabel="group_action_text"
    +        viewStreamItemActivity="viewstream_activity_name"
    +        viewStreamItemPhotoActivity="viewphotostream_activity_name">
    +
    +

    + contained in: +

    +

    + res/xml/contacts.xml +

    +

    + can contain: +

    +

    + <ContactsDataKind> +

    +

    + Description: +

    +

    + Declares Android components and UI labels that allow users to invite one of their contacts to + a social network, notify users when one of their social networking streams is updated, and + so forth. +

    +

    + Notice that the attribute prefix android: is not necessary for the attributes + of <ContactsAccountType>. +

    +

    + Attributes: +

    +
    +
    {@code inviteContactActivity}
    +
    + The fully-qualified class name of the activity in your application that you want to + activate when the user selects Add connection from the device's + contacts application. +
    +
    {@code inviteContactActionLabel}
    +
    + A text string that is displayed for the activity specified in + {@code inviteContactActivity}, in the Add connection menu. + For example, you can use the string "Follow in my network". You can use a string resource + identifier for this label. +
    +
    {@code viewContactNotifyService}
    +
    + The fully-qualified class name of a service in your application that should receive + notifications when the user views a contact. This notification is sent by the device's + contacts application; it allows your application to postpone data-intensive operations + until they're needed. For example, your application can respond to this notification + by reading in and displaying the contact's high-resolution photo and most recent + social stream items. This feature is described in more detail in the section + Social stream interactions. You can see an + example of the notification service in the NotifierService.java file in the + SampleSyncAdapter + sample app. +
    +
    {@code viewGroupActivity}
    +
    + The fully-qualified class name of an activity in your application that can display + group information. When the user clicks the group label in the device's contacts + application, the UI for this activity is displayed. +
    +
    {@code viewGroupActionLabel}
    +
    + The label that the contacts application displays for a UI control that allows + the user to look at groups in your application. +

    + For example, if you install the Google+ application on your device and you sync + Google+ with the contacts application, you'll see Google+ circles listed as groups + in your contacts application's Groups tab. If you click on a + Google+ circle, you'll see people in that circle listed as a "group". At the top of + the display, you'll see a Google+ icon; if you click it, control switches to the + Google+ app. The contacts application does this with the + {@code viewGroupActivity}, using the Google+ icon as the value of + {@code viewGroupActionLabel}. +

    +

    + A string resource identifier is allowed for this attribute. +

    +
    +
    {@code viewStreamItemActivity}
    +
    + The fully-qualified class name of an activity in your application that the device's + contacts application launches when the user clicks a stream item for a raw contact. +
    +
    {@code viewStreamItemPhotoActivity}
    +
    + The fully-qualified class name of an activity in your application that the device's + contacts application launches when the user clicks a photo in the stream item + for a raw contact. +
    +
    +

    <ContactsDataKind> element

    +

    + The <ContactsDataKind> element controls the display of your application's + custom data rows in the contacts application's UI. It has the following syntax: +

    +
    +<ContactsDataKind
    +        android:mimeType="MIMEtype"
    +        android:icon="icon_resources"
    +        android:summaryColumn="column_name"
    +        android:detailColumn="column_name">
    +
    +

    + contained in: +

    +<ContactsAccountType> +

    + Description: +

    +

    + Use this element to have the contacts application display the contents of a custom data row as + part of the details of a raw contact. Each <ContactsDataKind> child element + of <ContactsAccountType> represents a type of custom data row that your sync + adapter adds to the {@link android.provider.ContactsContract.Data} table. Add one + <ContactsDataKind> element for each custom MIME type you use. You don't have + to add the element if you have a custom data row for which you don't want to display data. +

    +

    + Attributes: +

    +
    +
    {@code android:mimeType}
    +
    + The custom MIME type you've defined for one of your custom data row types in the + {@link android.provider.ContactsContract.Data} table. For example, the value + vnd.android.cursor.item/vnd.example.locationstatus could be a custom + MIME type for a data row that records a contact's last known location. +
    +
    {@code android:icon}
    +
    + An Android + drawable resource + that the contacts application displays next to your data. Use this to indicate to the + user that the data comes from your service. +
    +
    {@code android:summaryColumn}
    +
    + The column name for the first of two values retrieved from the data row. The + value is displayed as the first line of the entry for this data row. The first line is + intended to be used as a summary of the data, but that is optional. See also + android:detailColumn. +
    +
    {@code android:detailColumn}
    +
    + The column name for the second of two values retrieved from the data row. The value is + displayed as the second line of the entry for this data row. See also + {@code android:summaryColumn}. +
    +
    +

    Additional Contacts Provider Features

    +

    + Besides the main features described in previous sections, the Contacts Provider offers + these useful features for working with contacts data: +

    +
      +
    • Contact groups
    • +
    • Photo features
    • +
    +

    Contact groups

    +

    + The Contacts Provider can optionally label collections of related contacts with + group data. If the server associated with a user account + wants to maintain groups, the sync adapter for the account's account type should transfer + groups data between the Contacts Provider and the server. When users add a new contact to the + server and then put this contact in a new group, the sync adapter must add the new group + to the {@link android.provider.ContactsContract.Groups} table. The group or groups a raw + contact belongs to are stored in the {@link android.provider.ContactsContract.Data} table, using + the {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} MIME type. +

    +

    + If you're designing a sync adapter that will add raw contact data from + server to the Contacts Provider, and you aren't using groups, then you need to tell the + Provider to make your data visible. In the code that is executed when a user adds an account + to the device, update the {@link android.provider.ContactsContract.Settings} + row that the Contacts Provider adds for the account. In this row, set the value of the + {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE + Settings.UNGROUPED_VISIBLE} column to 1. When you do this, the Contacts Provider will always + make your contacts data visible, even if you don't use groups. +

    +

    Contact photos

    +

    + The {@link android.provider.ContactsContract.Data} table stores photos as rows with MIME type + {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE + Photo.CONTENT_ITEM_TYPE}. The row's + {@link android.provider.ContactsContract.RawContactsColumns#CONTACT_ID} column is linked to the + {@link android.provider.BaseColumns#_ID} column of the raw contact to which it belongs. + The class {@link android.provider.ContactsContract.Contacts.Photo} defines a sub-table of + {@link android.provider.ContactsContract.Contacts} containing photo information for a contact's + primary photo, which is the primary photo of the contact's primary raw contact. Similarly, + the class {@link android.provider.ContactsContract.RawContacts.DisplayPhoto} defines a sub-table + of {@link android.provider.ContactsContract.RawContacts} containing photo information for a + raw contact's primary photo. +

    +

    + The reference documentation for {@link android.provider.ContactsContract.Contacts.Photo} and + {@link android.provider.ContactsContract.RawContacts.DisplayPhoto} contain examples of + retrieving photo information. There is no convenience class for retrieving the primary + thumbnail for a raw contact, but you can send a query to the + {@link android.provider.ContactsContract.Data} table, selecting on the raw contact's + {@link android.provider.BaseColumns#_ID}, the + {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE + Photo.CONTENT_ITEM_TYPE}, and the {@link android.provider.ContactsContract.Data#IS_PRIMARY} + column to find the raw contact's primary photo row. +

    +

    + Social stream data for a person may also include photos. These are stored in the + {@link android.provider.ContactsContract.StreamItemPhotos} table, which is described in more + detail in the section Social stream photos. +

    diff --git a/docs/html/guide/topics/providers/content-provider-basics.jd b/docs/html/guide/topics/providers/content-provider-basics.jd index de89568c4fc61735141da7d5d61ad9a5364a5758..b1d6827eb1c27ea912cf8f5e03696f60ba003e1d 100644 --- a/docs/html/guide/topics/providers/content-provider-basics.jd +++ b/docs/html/guide/topics/providers/content-provider-basics.jd @@ -371,7 +371,7 @@ Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4); 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 + in more detail in the Loaders guide. Also, the lines of code are snippets only; they don't show a complete application.

    @@ -941,7 +941,7 @@ mRowsDeleted = getContentResolver().delete(
  • Asynchronous queries: You should do queries in a separate thread. One way to do this is to use a {@link android.content.CursorLoader} object. The examples in the - Loaders guide demonstrate + Loaders guide demonstrate how to do this.
  • diff --git a/docs/html/guide/topics/providers/content-provider-creating.jd b/docs/html/guide/topics/providers/content-provider-creating.jd index 4ebdb502138ce5ad1d9e52ec1059e069bf56d6f7..bad5390fa5f518fe586aa1c2b6bda9b7d24604a4 100644 --- a/docs/html/guide/topics/providers/content-provider-creating.jd +++ b/docs/html/guide/topics/providers/content-provider-creating.jd @@ -551,7 +551,7 @@ public class ExampleProvider extends ContentProvider { All of these methods except {@link android.content.ContentProvider#onCreate() onCreate()} can be called by multiple threads at once, so they must be thread-safe. To learn more about multiple threads, see the topic - + Processes and Threads.
  • @@ -1211,5 +1211,5 @@ vnd.android.cursor.item/vnd.com.example.provider.table1

    Handling an incoming intent that wishes to modify your provider's data is no different from handling other intents. You can learn more about using intents by reading the topic - Intents and Intent Filters. + Intents and Intent Filters.

    diff --git a/docs/html/guide/topics/providers/content-providers.jd b/docs/html/guide/topics/providers/content-providers.jd index 1707f038b3ce0c4423c5fc18fd21a37382d9f262..751fc95bbc859599841e790e6cff93935217f9b0 100644 --- a/docs/html/guide/topics/providers/content-providers.jd +++ b/docs/html/guide/topics/providers/content-providers.jd @@ -18,6 +18,9 @@ page.title=Content Providers
  • Calendar Provider
  • +
  • + Contacts Provider +
  • @@ -38,6 +41,10 @@ page.title=Content Providers href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html"> "Cursor (Phones)" +
  • + + Sample Sync Adapter +
  • @@ -93,4 +100,11 @@ page.title=Content Providers
    How to access the Calendar Provider that is part of the Android platform.
    +
    + + Contacts Provider +
    +
    + How to access the Contacts Provider that is part of the Android platform. +
    diff --git a/docs/html/guide/topics/resources/animation-resource.jd b/docs/html/guide/topics/resources/animation-resource.jd index 6473155f33fdb07ed2dc9c612fa39868a623b0d0..3af52aae38c6356ba0a548ea34a603d49235df57 100644 --- a/docs/html/guide/topics/resources/animation-resource.jd +++ b/docs/html/guide/topics/resources/animation-resource.jd @@ -18,7 +18,7 @@ parent.link=available-resources.html

    See also

    1. View Animation
    2. -
    3. Property Animation
    4. +
    5. Property Animation
    @@ -334,7 +334,7 @@ set.start();
    see also:
    diff --git a/docs/html/guide/topics/resources/index.jd b/docs/html/guide/topics/resources/index.jd index 3f0f1eeb961164fdbe862f0a1d596c88de863fbb..386abf50a38a08a11d41b7eb56ea4c1489cd9a1a 100644 --- a/docs/html/guide/topics/resources/index.jd +++ b/docs/html/guide/topics/resources/index.jd @@ -1,103 +1,55 @@ -page.title=Application Resources -@jd:body - - - - -

    You should always externalize resources such as images and strings from your application -code, so that you can maintain them independently. Externalizing your -resources also allows you to provide alternative resources that support specific device -configurations such as different languages or screen sizes, which becomes increasingly -important as more Android-powered devices become available with different configurations. In order -to provide compatibility with different configurations, you must organize resources in your -project's {@code res/} directory, using various sub-directories that group resources by type and -configuration.

    - -
    - -

    -Figure 1. Two different devices, each using the default layout -(the app provides no alternative layouts).

    -
    - -
    - -

    -Figure 2. Two different devices, each using a different layout provided -for different screen sizes.

    -
    +page.title=App Resources +page.landing=true +page.landing.intro=It takes more than just code to build a great app. Resources are the additional files and static content that your code uses, such as bitmaps, layout definitions, user interface strings, animation instructions, and more. +page.landing.image=images/develop/resources.png -

    For any type of resource, you can specify default and multiple -alternative resources for your application:

    -
      -
    • Default resources are those that should be used regardless of -the device configuration or when there are no alternative resources that match the current -configuration.
    • -
    • Alternative resources are those that you've designed for use with a specific -configuration. To specify that a group of resources are for a specific configuration, -append an appropriate configuration qualifier to the directory name.
    • -
    - -

    For example, while your default UI -layout is saved in the {@code res/layout/} directory, you might specify a different layout to -be used when the screen is in landscape orientation, by saving it in the {@code res/layout-land/} -directory. Android automatically applies the appropriate resources by matching the -device's current configuration to your resource directory names.

    - -

    Figure 1 illustrates how the system applies the same layout for -two different devices when there are no alternative resources available. Figure 2 shows -the same application when it adds an alternative layout resource for larger screens.

    - -

    The following documents provide a complete guide to how you can organize your application resources, -specify alternative resources, access them in your application, and more:

    - -
    -
    Providing Resources
    -
    What kinds of resources you can provide in your app, where to save them, and how to create -alternative resources for specific device configurations.
    -
    Accessing Resources
    -
    How to use the resources you've provided, either by referencing them from your application -code or from other XML resources.
    -
    Handling Runtime Changes
    -
    How to manage configuration changes that occur while your Activity is running.
    -
    Localization
    -
    A bottom-up guide to localizing your application using alternative resources. While this is -just one specific use of alternative resources, it is very important in order to reach more -users.
    -
    Resource Types
    -
    A reference of various resource types you can provide, describing their XML elements, -attributes, and syntax. For example, this reference shows you how to create a resource for -application menus, drawables, animations, and more.
    -
    - - +
    + + + + +
    diff --git a/docs/html/guide/topics/resources/layout-resource.jd b/docs/html/guide/topics/resources/layout-resource.jd index 286e3d1280a3e68e24e125e820d720a797331971..5643075c6a3abb87c036206c6ad138d1292f3528 100644 --- a/docs/html/guide/topics/resources/layout-resource.jd +++ b/docs/html/guide/topics/resources/layout-resource.jd @@ -7,7 +7,7 @@ parent.link=available-resources.html

    See also

      -
    1. XML Layouts
    2. +
    3. Layouts
    @@ -128,7 +128,7 @@ or {@code "wrap_content"}). See the valid values bel

    More attributes are supported by the {@link android.view.View} base class, and many more are supported by each implementation of {@link android.view.View}. Read XML Layouts for more information. For +href="{@docRoot}guide/topics/ui/declaring-layout.html">Layouts for more information. For a reference of all available attributes, see the corresponding reference documentation (for example, the TextView XML attributes).

    @@ -275,7 +275,7 @@ public void onCreate(Bundle savedInstanceState) {
    see also:
    diff --git a/docs/html/guide/topics/resources/localization.jd b/docs/html/guide/topics/resources/localization.jd index c2b668da99ddc0a1d5fe4f32a7094200bea0e35c..41961a346d6e72a2ee200ad019dae0cd112da06c 100755 --- a/docs/html/guide/topics/resources/localization.jd +++ b/docs/html/guide/topics/resources/localization.jd @@ -38,7 +38,6 @@ defaults.
  • Testing on an Emulator
  • Testing for Default Resources
  • -
  • Publishing
  • Localization Checklists
    1. Planning and Design Checklist
    2. @@ -52,7 +51,7 @@ defaults.
    3. Hello, L10N Tutorial
    4. Providing Resources
    5. -
    6. XML Layouts
    7. +
    8. Layouts
    9. Activity Lifecycle
    @@ -430,7 +429,7 @@ Menu > Settings > Locale & text > Select locale).

    Testing on an Emulator

    For details about using the emulator, see See Android Emulator.

    +href="{@docRoot}tools/help/emulator.html">Android Emulator.

    Creating and using a custom locale

    A "custom" locale is a language/region combination that the Android @@ -505,26 +504,6 @@ the new locale.

    res/layout-port/main.xml, then set the emulator or device to portrait orientation and see if the application will run. -

    Publishing Localized Applications

    - -

    The Google Play is - the main application distribution system for Android devices. To publish a - localized application, you need to sign your application, version it, and go -through all the other steps described in Preparing to Publish.

    - -

    If you split your application in several .apk files, each targeted to a -different locale, follow these guidelines:

    - -
      -
    • Sign each .apk file with the same certificate. For more about this, see Signing -Strategies.
    • -
    • Give each .apk file a different application name. Currently it is -impossible to publish two applications on Google Play that have exactly the -same name.
    • -
    • Include a complete set of default resources in each .apk file.
    • -

    Localization Checklists

    @@ -640,8 +619,6 @@ border="0"> border="0"> Upload your .apk file or files to Google Play, selecting the appropriate languages as - you upload. (For more details, see Publishing Your -Applications.) + you upload. \ No newline at end of file diff --git a/docs/html/guide/topics/resources/menu-resource.jd b/docs/html/guide/topics/resources/menu-resource.jd index fb7612e41767b607f5f275c6e605bc31d16812ca..b2d6eb3445c9b19e3c86f609bd326c01e68c93c2 100644 --- a/docs/html/guide/topics/resources/menu-resource.jd +++ b/docs/html/guide/topics/resources/menu-resource.jd @@ -111,7 +111,7 @@ only parameter, which indicates the item clicked. This method takes precedence o callback to {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()}. See the example at the bottom.

    Warning: If you obfuscate your code using ProGuard (or a similar tool), +href="{@docRoot}tools/help/proguard.html">ProGuard (or a similar tool), be sure to exclude the method you specify in this attribute from renaming, because it can break the functionality.

    Introduced in API Level 11.

    @@ -133,7 +133,8 @@ Avoid using this unless it's critical that the item always appear in the action bar. Setting multiple items to always appear as action items can result in them overlapping with other UI in the action bar. collapseActionViewThe action view associated -with this action item (as declared by android:actionViewLayout) is +with this action item (as declared by android:actionLayout or +android:actionViewClass) is collapsible.
    Introduced in API Level 14.

    See the Action Bar developer @@ -141,7 +142,7 @@ guide for more information.

    Introduced in API Level 11.

    -
    android:actionViewLayout
    +
    android:actionLayout
    Layout resource. A layout to use as the action view.

    See the Action Bar developer guide for more information.

    @@ -154,7 +155,7 @@ to use as the action view. For example,

    See the Action Bar developer guide for more information.

    Warning: If you obfuscate your code using ProGuard (or a similar tool), +href="{@docRoot}tools/help/proguard.html">ProGuard (or a similar tool), be sure to exclude the class you specify in this attribute from renaming, because it can break the functionality.

    Introduced in API Level 11.

    @@ -166,7 +167,7 @@ android.view.ActionProvider} to use in place of the action item. For example,

    See the Action Bar developer guide for more information.

    Warning: If you obfuscate your code using ProGuard (or a similar tool), +href="{@docRoot}tools/help/proguard.html">ProGuard (or a similar tool), be sure to exclude the class you specify in this attribute from renaming, because it can break the functionality.

    Introduced in API Level 14.

    diff --git a/docs/html/guide/topics/resources/overview.jd b/docs/html/guide/topics/resources/overview.jd new file mode 100644 index 0000000000000000000000000000000000000000..c3bd0bfb05817d6e78e51ffcfa6c679898fe18e0 --- /dev/null +++ b/docs/html/guide/topics/resources/overview.jd @@ -0,0 +1,103 @@ +page.title=Resources Overview +@jd:body + + + + +

    You should always externalize resources such as images and strings from your application +code, so that you can maintain them independently. Externalizing your +resources also allows you to provide alternative resources that support specific device +configurations such as different languages or screen sizes, which becomes increasingly +important as more Android-powered devices become available with different configurations. In order +to provide compatibility with different configurations, you must organize resources in your +project's {@code res/} directory, using various sub-directories that group resources by type and +configuration.

    + +
    + +

    +Figure 1. Two different devices, each using the default layout +(the app provides no alternative layouts).

    +
    + +
    + +

    +Figure 2. Two different devices, each using a different layout provided +for different screen sizes.

    +
    + +

    For any type of resource, you can specify default and multiple +alternative resources for your application:

    +
      +
    • Default resources are those that should be used regardless of +the device configuration or when there are no alternative resources that match the current +configuration.
    • +
    • Alternative resources are those that you've designed for use with a specific +configuration. To specify that a group of resources are for a specific configuration, +append an appropriate configuration qualifier to the directory name.
    • +
    + +

    For example, while your default UI +layout is saved in the {@code res/layout/} directory, you might specify a different layout to +be used when the screen is in landscape orientation, by saving it in the {@code res/layout-land/} +directory. Android automatically applies the appropriate resources by matching the +device's current configuration to your resource directory names.

    + +

    Figure 1 illustrates how the system applies the same layout for +two different devices when there are no alternative resources available. Figure 2 shows +the same application when it adds an alternative layout resource for larger screens.

    + +

    The following documents provide a complete guide to how you can organize your application resources, +specify alternative resources, access them in your application, and more:

    + +
    +
    Providing Resources
    +
    What kinds of resources you can provide in your app, where to save them, and how to create +alternative resources for specific device configurations.
    +
    Accessing Resources
    +
    How to use the resources you've provided, either by referencing them from your application +code or from other XML resources.
    +
    Handling Runtime Changes
    +
    How to manage configuration changes that occur while your Activity is running.
    +
    Localization
    +
    A bottom-up guide to localizing your application using alternative resources. While this is +just one specific use of alternative resources, it is very important in order to reach more +users.
    +
    Resource Types
    +
    A reference of various resource types you can provide, describing their XML elements, +attributes, and syntax. For example, this reference shows you how to create a resource for +application menus, drawables, animations, and more.
    +
    + + diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd index 82b5e29472f80247970275071fd6c95214a71156..b0d5d6fc21ee0cc6ab94771fac7d6cd04f7b2131 100644 --- a/docs/html/guide/topics/resources/providing-resources.jd +++ b/docs/html/guide/topics/resources/providing-resources.jd @@ -44,7 +44,7 @@ Screens

    You should always externalize application resources such as images and strings from your code, so that you can maintain them independently. You should also provide alternative resources for specific device configurations, by grouping them in specially-named resource directories. At -runtime, Android uses uses the appropriate resource based on the current configuration. For +runtime, Android uses the appropriate resource based on the current configuration. For example, you might want to provide a different UI layout depending on the screen size or different strings depending on the language setting.

    @@ -89,7 +89,7 @@ supported inside project {@code res/} directory.

    animator/ - XML files that define property + XML files that define property animations. @@ -744,7 +744,7 @@ orientation" described above.

    The API level supported by the device. For example, v1 for API level 1 (devices with Android 1.0 or higher) and v4 for API level 4 (devices with Android 1.6 or higher). See the Android API levels document for more information +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">Android API levels document for more information about these values.

    Caution: Android 1.5 and 1.6 only match resources with this qualifier when it exactly matches the platform version. See the section below about -

  • Ensure that your SDK Tools version +
  • Ensure that your SDK Tools version is r6 or greater.

    You need SDK Tools, Revision 6 (or greater), because it includes a new packaging tool that diff --git a/docs/html/guide/topics/resources/runtime-changes.jd b/docs/html/guide/topics/resources/runtime-changes.jd index 871b06320cde6cdeae70c9c14ff93aa97ab37ce1..f5475b40abc4aeb1f2fafc249200409c6ac454d3 100644 --- a/docs/html/guide/topics/resources/runtime-changes.jd +++ b/docs/html/guide/topics/resources/runtime-changes.jd @@ -32,7 +32,7 @@ alternative resources that match the new device configuration.

    To properly handle a restart, it is important that your activity restores its previous state through the normal Activity +href="{@docRoot}guide/components/activities.html#Lifecycle">Activity lifecycle, in which Android calls {@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} before it destroys your activity so that you can save data about the application state. You can then restore the state @@ -45,7 +45,7 @@ tasks in your application. Your application should be able to restart at any tim user data or state in order to handle events such as configuration changes or when the user receives an incoming phone call and then returns to your application much later after your application process may have been destroyed. To learn how you can restore your activity state, read about the Activity lifecycle.

    +href="{@docRoot}guide/components/activities.html#Lifecycle">Activity lifecycle.

    However, you might encounter a situation in which restarting your application and restoring significant amounts of data can be costly and create a poor user experience. In such a diff --git a/docs/html/guide/topics/search/index.jd b/docs/html/guide/topics/search/index.jd index 218511b2a8e445a434e83bf0988693619e6dd5d1..2ee624b6b7a70994648f62e3c6c52836142530f4 100644 --- a/docs/html/guide/topics/search/index.jd +++ b/docs/html/guide/topics/search/index.jd @@ -1,4 +1,4 @@ -page.title=Search +page.title=Search Overview @jd:body

    diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd index 8b8e75bb8a738e2b0ae5e7ae9c5e725bfae5e0a6..49451acf4d29c39e0d35f0aa976a2271cc4666b3 100644 --- a/docs/html/guide/topics/search/search-dialog.jd +++ b/docs/html/guide/topics/search/search-dialog.jd @@ -561,7 +561,7 @@ case, the search dialog naturally disappears).

    events are triggered once the user executes a search (the current activity receives {@link android.app.Activity#onPause()} and so forth, as described in the Activities +href="{@docRoot}guide/components/activities.html#Lifecycle">Activities document). If, however, the current activity is the searchable activity, then one of two things happens:

    diff --git a/docs/html/guide/topics/security/index.jd b/docs/html/guide/topics/security/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..775fc036547be93a6b3b120398c60654b340086e --- /dev/null +++ b/docs/html/guide/topics/security/index.jd @@ -0,0 +1,65 @@ +page.title=Security and Permissions +page.landing=true +page.landing.intro=Android's security architecture gives the user full control over what resources are accessible to each app, protecting the system itself and all apps in it. Learn how to use system permissions to request access to the resources your app needs and design your app for optimal security. +page.landing.image= + +@jd:body + +
    + +
    +

    Blog Articles

    + +
    + +
    + +
    + +
    +

    Accessibility: Are You Serving All Your Users?

    +

    In the upcoming weeks, some of the older Client Login authentication keys will expire. + If you generated the token you’re currently using to authenticate with the C2DM servers before October 2011, it will stop working.

    + +

    Android C2DM — Client Login key expiration

    +

    Accessibility is about making sure that Android users who have limited vision or other physical impairments can use your application just as well

    + +

    A Faster Emulator with Better Hardware Support

    +

    The Android emulator is a key tool for Android developers in building and testing their apps. + As the power and diversity of Android devices has grown quickly, it’s been hard for the emulator keep pace.

    + + More » +
    +
    +
    + +
    +

    Training

    + +
    + +
    + +
    + +
    +

    Managing the Activity Lifecycle

    +

    This class explains important lifecycle callback methods that each Activity + instance receives and how you can use them so your activity does what the user expects and does not consume system + resources when your activity doesn't need them.

    + +

    Supporting Different Devices

    +

    This class teaches you how to use basic platform features that leverage alternative + resources and other features so your app can provide an optimized user experience on a variety of Android-compatible devices, + using a single application package (APK).

    + +

    Sharing Content

    +

    This class covers some common ways you can send and receive content between + applications using Intent APIs and the ActionProvider object.

    + + More » +
    +
    +
    + +
    \ No newline at end of file diff --git a/docs/html/guide/topics/security/permissions.jd b/docs/html/guide/topics/security/permissions.jd new file mode 100644 index 0000000000000000000000000000000000000000..3013e387008d34999afc6e7808042756290ae60e --- /dev/null +++ b/docs/html/guide/topics/security/permissions.jd @@ -0,0 +1,407 @@ +page.title=Permissions +@jd:body + + +

    This document describes how application developers can use the +security features provided by Android. A more general Android Security +Overview is provided in the Android Open Source Project.

    + +

    Android is a privilege-separated operating system, in which each +application runs with a distinct system identity (Linux user ID and group +ID). Parts of the system are also separated into distinct identities. +Linux thereby isolates applications from each other and from the system.

    + +

    Additional finer-grained security features are provided through a +"permission" mechanism that enforces restrictions on the specific operations +that a particular process can perform, and per-URI permissions for granting +ad-hoc access to specific pieces of data.

    + + +

    Security Architecture

    + +

    A central design point of the Android security architecture is that no +application, by default, has permission to perform any operations that would +adversely impact other applications, the operating system, or the user. This +includes reading or writing the user's private data (such as contacts or +e-mails), reading or writing another application's files, performing +network access, keeping the device awake, etc.

    + +

    Because Android sandboxes applications from each other, applications +must explicitly share resources and data. They do this by declaring the +permissions they need for additional capabilities not provided by +the basic sandbox. Applications statically declare the permissions they +require, and the Android system prompts the user for consent at the time the +application is installed. Android has no mechanism for granting permissions +dynamically (at run-time) because it complicates the user experience to the +detriment of security.

    + +

    The application sandbox does not depend on the technology used to build +an application. In particular the Dalvik VM is not a security boundary, and +any app can run native code (see the Android +NDK). All types of applications — Java, native, and hybrid — +are sandboxed in the same way and have the same degree of security from each +other.

    + + +

    Application Signing

    + +

    All Android applications (.apk files) must be signed with a certificate +whose private key is held by their developer. This certificate identifies +the author of the application. The certificate does not need to be +signed by a certificate authority: it is perfectly allowable, and typical, +for Android applications to use self-signed certificates. The purpose of +certificates in Android is to distinguish application authors. This allows +the system to grant or deny applications access to signature-level +permissions and to grant or deny an application's request to be given +the same Linux identity as another application.

    + + +

    User IDs and File Access

    + +

    At install time, Android gives each package a distinct Linux user ID. The +identity remains constant for the duration of the package's life on that +device. On a different device, the same package may have a different UID; +what matters is that each package has a distinct UID on a given device.

    + +

    Because security enforcement happens at the +process level, the code of any two packages can not normally +run in the same process, since they need to run as different Linux users. +You can use the {@link android.R.attr#sharedUserId} attribute in the +AndroidManifest.xml's +{@link android.R.styleable#AndroidManifest manifest} tag of each package to +have them assigned the same user ID. By doing this, for purposes of security +the two packages are then treated as being the same application, with the same +user ID and file permissions. Note that in order to retain security, only two applications +signed with the same signature (and requesting the same sharedUserId) will +be given the same user ID.

    + +

    Any data stored by an application will be assigned that application's user +ID, and not normally accessible to other packages. When creating a new file +with {@link android.content.Context#getSharedPreferences}, +{@link android.content.Context#openFileOutput}, or +{@link android.content.Context#openOrCreateDatabase}, +you can use the +{@link android.content.Context#MODE_WORLD_READABLE} and/or +{@link android.content.Context#MODE_WORLD_WRITEABLE} flags to allow any other +package to read/write the file. When setting these flags, the file is still +owned by your application, but its global read and/or write permissions have +been set appropriately so any other application can see it.

    + + + +

    Using Permissions

    + +

    A basic Android application has no permissions associated with it, +meaning it can not do anything that would adversely impact the user experience +or any data on the device. To make use of protected features of the device, +you must include in your AndroidManifest.xml one or more +{@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} +tags declaring the permissions that your application needs.

    + +

    For example, an application that needs to monitor incoming SMS messages would +specify:

    + +
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    +    package="com.android.app.myapp" >
    +    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    +    ...
    +</manifest>
    + +

    At application install time, permissions requested by the application are +granted to it by the package installer, based on checks against the +signatures of the applications declaring those permissions and/or interaction +with the user. No checks with the user +are done while an application is running: it either was granted a particular +permission when installed, and can use that feature as desired, or the +permission was not granted and any attempt to use the feature will fail +without prompting the user.

    + +

    Often times a permission failure will result in a {@link +java.lang.SecurityException} being thrown back to the application. However, +this is not guaranteed to occur everywhere. For example, the {@link +android.content.Context#sendBroadcast} method checks permissions as data is +being delivered to each receiver, after the method call has returned, so you +will not receive an exception if there are permission failures. In almost all +cases, however, a permission failure will be printed to the system log.

    + +

    The permissions provided by the Android system can be found at {@link +android.Manifest.permission}. Any application may also define and enforce its +own permissions, so this is not a comprehensive list of all possible +permissions.

    + +

    A particular permission may be enforced at a number of places during your +program's operation:

    + +
      +
    • At the time of a call into the system, to prevent an application from +executing certain functions.
    • +
    • When starting an activity, to prevent applications from launching +activities of other applications.
    • +
    • Both sending and receiving broadcasts, to control who can receive +your broadcast or who can send a broadcast to you.
    • +
    • When accessing and operating on a content provider.
    • +
    • Binding to or starting a service.
    • +
    + + + +

    Declaring and Enforcing Permissions

    + +

    To enforce your own permissions, you must first declare them in your +AndroidManifest.xml using one or more +{@link android.R.styleable#AndroidManifestPermission <permission>} +tags.

    + +

    For example, an application that wants to control who can start one +of its activities could declare a permission for this operation as follows:

    + +
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    +    package="com.me.app.myapp" >
    +    <permission android:name="com.me.app.myapp.permission.DEADLY_ACTIVITY"
    +        android:label="@string/permlab_deadlyActivity"
    +        android:description="@string/permdesc_deadlyActivity"
    +        android:permissionGroup="android.permission-group.COST_MONEY"
    +        android:protectionLevel="dangerous" />
    +    ...
    +</manifest>
    + +

    The {@link android.R.styleable#AndroidManifestPermission_protectionLevel +<protectionLevel>} attribute is required, telling the system how the +user is to be informed of applications requiring the permission, or who is +allowed to hold that permission, as described in the linked documentation.

    + +

    The {@link android.R.styleable#AndroidManifestPermission_permissionGroup +<permissionGroup>} attribute is optional, and only used to help the system display +permissions to the user. You will usually want to set this to either a standard +system group (listed in {@link android.Manifest.permission_group +android.Manifest.permission_group}) or in more rare cases to one defined by +yourself. It is preferred to use an existing group, as this simplifies the +permission UI shown to the user.

    + +

    Note that both a label and description should be supplied for the +permission. These are string resources that can be displayed to the user when +they are viewing a list of permissions +({@link android.R.styleable#AndroidManifestPermission_label android:label}) +or details on a single permission ( +{@link android.R.styleable#AndroidManifestPermission_description android:description}). +The label should be short, a few words +describing the key piece of functionality the permission is protecting. The +description should be a couple sentences describing what the permission allows +a holder to do. Our convention for the description is two sentences, the first +describing the permission, the second warning the user of what bad things +can happen if an application is granted the permission.

    + +

    Here is an example of a label and description for the CALL_PHONE +permission:

    + +
    +    <string name="permlab_callPhone">directly call phone numbers</string>
    +    <string name="permdesc_callPhone">Allows the application to call
    +        phone numbers without your intervention. Malicious applications may
    +        cause unexpected calls on your phone bill. Note that this does not
    +        allow the application to call emergency numbers.</string>
    +
    + +

    You can look at the permissions currently defined in the system with the +Settings app and the shell command adb shell pm list permissions. +To use the Settings app, go to Settings > Applications. Pick an app and +scroll down to see the permissions that the app uses. For developers, the adb '-s' +option displays the permissions in a form similar to how the user will see them:

    + +
    +$ adb shell pm list permissions -s
    +All Permissions:
    +
    +Network communication: view Wi-Fi state, create Bluetooth connections, full
    +Internet access, view network state
    +
    +Your location: access extra location provider commands, fine (GPS) location,
    +mock location sources for testing, coarse (network-based) location
    +
    +Services that cost you money: send SMS messages, directly call phone numbers
    +
    +...
    + + +

    Enforcing Permissions in AndroidManifest.xml

    + +

    High-level permissions restricting access to entire components of the +system or application can be applied through your +AndroidManifest.xml. All that this requires is including an {@link +android.R.attr#permission android:permission} attribute on the desired +component, naming the permission that will be used to control access to +it.

    + +

    {@link android.app.Activity} permissions +(applied to the +{@link android.R.styleable#AndroidManifestActivity <activity>} tag) +restrict who can start the associated +activity. The permission is checked during +{@link android.content.Context#startActivity Context.startActivity()} and +{@link android.app.Activity#startActivityForResult Activity.startActivityForResult()}; +if the caller does not have +the required permission then {@link java.lang.SecurityException} is thrown +from the call.

    + +

    {@link android.app.Service} permissions +(applied to the +{@link android.R.styleable#AndroidManifestService <service>} tag) +restrict who can start or bind to the +associated service. The permission is checked during +{@link android.content.Context#startService Context.startService()}, +{@link android.content.Context#stopService Context.stopService()} and +{@link android.content.Context#bindService Context.bindService()}; +if the caller does not have +the required permission then {@link java.lang.SecurityException} is thrown +from the call.

    + +

    {@link android.content.BroadcastReceiver} permissions +(applied to the +{@link android.R.styleable#AndroidManifestReceiver <receiver>} tag) +restrict who can send broadcasts to the associated receiver. +The permission is checked after +{@link android.content.Context#sendBroadcast Context.sendBroadcast()} returns, +as the system tries +to deliver the submitted broadcast to the given receiver. As a result, a +permission failure will not result in an exception being thrown back to the +caller; it will just not deliver the intent. In the same way, a permission +can be supplied to +{@link android.content.Context#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler) +Context.registerReceiver()} +to control who can broadcast to a programmatically registered receiver. +Going the other way, a permission can be supplied when calling +{@link android.content.Context#sendBroadcast(Intent, String) Context.sendBroadcast()} +to restrict which BroadcastReceiver objects are allowed to receive the broadcast (see +below).

    + +

    {@link android.content.ContentProvider} permissions +(applied to the +{@link android.R.styleable#AndroidManifestProvider <provider>} tag) +restrict who can access the data in +a {@link android.content.ContentProvider}. (Content providers have an important +additional security facility available to them called +URI permissions which is described later.) +Unlike the other components, +there are two separate permission attributes you can set: +{@link android.R.attr#readPermission android:readPermission} restricts who +can read from the provider, and +{@link android.R.attr#writePermission android:writePermission} restricts +who can write to it. Note that if a provider is protected with both a read +and write permission, holding only the write permission does not mean +you can read from a provider. The permissions are checked when you first +retrieve a provider (if you don't have either permission, a SecurityException +will be thrown), and as you perform operations on the provider. Using +{@link android.content.ContentResolver#query ContentResolver.query()} requires +holding the read permission; using +{@link android.content.ContentResolver#insert ContentResolver.insert()}, +{@link android.content.ContentResolver#update ContentResolver.update()}, +{@link android.content.ContentResolver#delete ContentResolver.delete()} +requires the write permission. +In all of these cases, not holding the required permission results in a +{@link java.lang.SecurityException} being thrown from the call.

    + + + +

    Enforcing Permissions when Sending Broadcasts

    + +

    In addition to the permission enforcing who can send Intents to a +registered {@link android.content.BroadcastReceiver} (as described above), you +can also specify a required permission when sending a broadcast. By calling {@link +android.content.Context#sendBroadcast(android.content.Intent,String) +Context.sendBroadcast()} with a +permission string, you require that a receiver's application must hold that +permission in order to receive your broadcast.

    + +

    Note that both a receiver and a broadcaster can require a permission. When +this happens, both permission checks must pass for the Intent to be delivered +to the associated target.

    + + + +

    Other Permission Enforcement

    + +

    Arbitrarily fine-grained permissions can be enforced at any call into a +service. This is accomplished with the {@link +android.content.Context#checkCallingPermission Context.checkCallingPermission()} +method. Call with a desired +permission string and it will return an integer indicating whether that +permission has been granted to the current calling process. Note that this can +only be used when you are executing a call coming in from another process, +usually through an IDL interface published from a service or in some other way +given to another process.

    + +

    There are a number of other useful ways to check permissions. If you have +the pid of another process, you can use the Context method {@link +android.content.Context#checkPermission(String, int, int) Context.checkPermission(String, int, int)} +to check a permission against that pid. If you have the package name of another +application, you can use the direct PackageManager method {@link +android.content.pm.PackageManager#checkPermission(String, String) +PackageManager.checkPermission(String, String)} +to find out whether that particular package has been granted a specific permission.

    + + + +

    URI Permissions

    + +

    The standard permission system described so far is often not sufficient +when used with content providers. A content provider may want to +protect itself with read and write permissions, while its direct clients +also need to hand specific URIs to other applications for them to operate on. +A typical example is attachments in a mail application. Access to the mail +should be protected by permissions, since this is sensitive user data. However, +if a URI to an image attachment is given to an image viewer, that image viewer +will not have permission to open the attachment since it has no reason to hold +a permission to access all e-mail.

    + +

    The solution to this problem is per-URI permissions: when starting an +activity or returning a result to an activity, the caller can set +{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION +Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or +{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION +Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. This grants the receiving activity +permission access the specific data URI in the Intent, regardless of whether +it has any permission to access data in the content provider corresponding +to the Intent.

    + +

    This mechanism allows a common capability-style model where user interaction +(opening an attachment, selecting a contact from a list, etc) drives ad-hoc +granting of fine-grained permission. This can be a key facility for reducing +the permissions needed by applications to only those directly related to their +behavior.

    + +

    The granting of fine-grained URI permissions does, however, require some +cooperation with the content provider holding those URIs. It is strongly +recommended that content providers implement this facility, and declare that +they support it through the +{@link android.R.styleable#AndroidManifestProvider_grantUriPermissions +android:grantUriPermissions} attribute or +{@link android.R.styleable#AndroidManifestGrantUriPermission +<grant-uri-permissions>} tag.

    + +

    More information can be found in the +{@link android.content.Context#grantUriPermission Context.grantUriPermission()}, +{@link android.content.Context#revokeUriPermission Context.revokeUriPermission()}, and +{@link android.content.Context#checkUriPermission Context.checkUriPermission()} +methods.

    + diff --git a/docs/html/guide/topics/security/security.jd b/docs/html/guide/topics/security/security.jd index 1fd9ba011ce110e17cb749ff21eccb7136ee9e1b..eeaac44e394009948352af1f4ca6bf35cc026782 100644 --- a/docs/html/guide/topics/security/security.jd +++ b/docs/html/guide/topics/security/security.jd @@ -1,407 +1,770 @@ -page.title=Security and Permissions +page.title=Designing for Security @jd:body -

    This document describes how application developers can use the -security features provided by Android. A more general Android Security -Overview is provided in the Android Open Source Project.

    - -

    Android is a privilege-separated operating system, in which each -application runs with a distinct system identity (Linux user ID and group -ID). Parts of the system are also separated into distinct identities. -Linux thereby isolates applications from each other and from the system.

    - -

    Additional finer-grained security features are provided through a -"permission" mechanism that enforces restrictions on the specific operations -that a particular process can perform, and per-URI permissions for granting -ad-hoc access to specific pieces of data.

    - - -

    Security Architecture

    - -

    A central design point of the Android security architecture is that no -application, by default, has permission to perform any operations that would -adversely impact other applications, the operating system, or the user. This -includes reading or writing the user's private data (such as contacts or -e-mails), reading or writing another application's files, performing -network access, keeping the device awake, etc.

    - -

    Because Android sandboxes applications from each other, applications -must explicitly share resources and data. They do this by declaring the -permissions they need for additional capabilities not provided by -the basic sandbox. Applications statically declare the permissions they -require, and the Android system prompts the user for consent at the time the -application is installed. Android has no mechanism for granting permissions -dynamically (at run-time) because it complicates the user experience to the -detriment of security.

    - -

    The application sandbox does not depend on the technology used to build -an application. In particular the Dalvik VM is not a security boundary, and -any app can run native code (see the Android -NDK). All types of applications — Java, native, and hybrid — -are sandboxed in the same way and have the same degree of security from each -other.

    - - -

    Application Signing

    - -

    All Android applications (.apk files) must be signed with a certificate -whose private key is held by their developer. This certificate identifies -the author of the application. The certificate does not need to be -signed by a certificate authority: it is perfectly allowable, and typical, -for Android applications to use self-signed certificates. The purpose of -certificates in Android is to distinguish application authors. This allows -the system to grant or deny applications access to signature-level -permissions and to grant or deny an application's request to be given -the same Linux identity as another application.

    - - -

    User IDs and File Access

    - -

    At install time, Android gives each package a distinct Linux user ID. The -identity remains constant for the duration of the package's life on that -device. On a different device, the same package may have a different UID; -what matters is that each package has a distinct UID on a given device.

    - -

    Because security enforcement happens at the -process level, the code of any two packages can not normally -run in the same process, since they need to run as different Linux users. -You can use the {@link android.R.attr#sharedUserId} attribute in the -AndroidManifest.xml's -{@link android.R.styleable#AndroidManifest manifest} tag of each package to -have them assigned the same user ID. By doing this, for purposes of security -the two packages are then treated as being the same application, with the same -user ID and file permissions. Note that in order to retain security, only two applications -signed with the same signature (and requesting the same sharedUserId) will -be given the same user ID.

    - -

    Any data stored by an application will be assigned that application's user -ID, and not normally accessible to other packages. When creating a new file -with {@link android.content.Context#getSharedPreferences}, -{@link android.content.Context#openFileOutput}, or -{@link android.content.Context#openOrCreateDatabase}, -you can use the -{@link android.content.Context#MODE_WORLD_READABLE} and/or -{@link android.content.Context#MODE_WORLD_WRITEABLE} flags to allow any other -package to read/write the file. When setting these flags, the file is still -owned by your application, but its global read and/or write permissions have -been set appropriately so any other application can see it.

    - - - -

    Using Permissions

    - -

    A basic Android application has no permissions associated with it, -meaning it can not do anything that would adversely impact the user experience -or any data on the device. To make use of protected features of the device, -you must include in your AndroidManifest.xml one or more -{@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} -tags declaring the permissions that your application needs.

    - -

    For example, an application that needs to monitor incoming SMS messages would -specify:

    - -
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    -    package="com.android.app.myapp" >
    -    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    -    ...
    -</manifest>
    - -

    At application install time, permissions requested by the application are -granted to it by the package installer, based on checks against the -signatures of the applications declaring those permissions and/or interaction -with the user. No checks with the user -are done while an application is running: it either was granted a particular -permission when installed, and can use that feature as desired, or the -permission was not granted and any attempt to use the feature will fail -without prompting the user.

    - -

    Often times a permission failure will result in a {@link -java.lang.SecurityException} being thrown back to the application. However, -this is not guaranteed to occur everywhere. For example, the {@link -android.content.Context#sendBroadcast} method checks permissions as data is -being delivered to each receiver, after the method call has returned, so you -will not receive an exception if there are permission failures. In almost all -cases, however, a permission failure will be printed to the system log.

    - -

    The permissions provided by the Android system can be found at {@link -android.Manifest.permission}. Any application may also define and enforce its -own permissions, so this is not a comprehensive list of all possible +

    See also

    +
      +
    1. Android +Security Overview
    2. +
    3. Android Security +And Permissions
    4. +
    +
    +

    Android was designed so that most developers will be able to build +applications using the default settings and not be confronted with difficult +decisions about security. Android also has a number of security features built +into the operating system that significantly reduce the frequency and impact of +application security issues.

    + +

    Some of the security features that help developers build secure applications +include: +

      +
    • The Android Application Sandbox that isolates data and code execution on a +per-application basis.
    • +
    • Android application framework with robust implementations of common +security functionality such as cryptography, permissions, and secure IPC.
    • +
    • Technologies like ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD +calloc, and Linux mmap_min_addr to mitigate risks associated with common memory +management errors
    • +
    • An encrypted filesystem that can be enabled to protect data on lost or +stolen devices.
    • +

    + +

    Nevertheless, it is important for developers to be familiar with Android +security best practices to make sure they take advantage of these capabilities +and to reduce the likelihood of inadvertently introducing security issues that +can affect their applications.

    + +

    This document is organized around common APIs and development techniques +that can have security implications for your application and its users. As +these best practices are constantly evolving, we recommend you check back +occasionally throughout your application development process.

    + + +

    Using Dalvik Code

    +

    Writing secure code that runs in virtual machines is a well-studied topic +and many of the issues are not specific to Android. Rather than attempting to +rehash these topics, we’d recommend that you familiarize yourself with the +existing literature. Two of the more popular resources are: +

    + +

    This document is focused on the areas which are Android specific and/or +different from other environments. For developers experienced with VM +programming in other environments, there are two broad issues that may be +different about writing apps for Android: +

      +
    • Some virtual machines, such as the JVM or .net runtime, act as a security +boundary, isolating code from the underlying operating system capabilities. On +Android, the Dalvik VM is not a security boundary -- the application sandbox is +implemented at the OS level, so Dalvik can interoperate with native code in the +same application without any security constraints.
    • +
    • Given the limited storage on mobile devices, it’s common for developers +to want to build modular applications and use dynamic class loading. When +doing this consider both the source where you retrieve your application logic +and where you store it locally. Do not use dynamic class loading from sources +that are not verified, such as unsecured network sources or external storage, +since that code can be modified to include malicious behavior.
    • +

    + + +

    Using Native Code

    + +

    In general, we encourage developers to use the Android SDK for most +application development, rather than using native code. Applications built +with native code are more complex, less portable, and more like to include +common memory corruption errors such as buffer overflows.

    + +

    Android is built using the Linux kernel and being familiar with Linux +development security best practices is especially useful if you are going to +use native code. This document is too short to discuss all of those best +practices, but one of the most popular resources is “Secure Programming for +Linux and Unix HOWTO”, available at +http://www.dwheeler.com/secure-programs.

    + +

    An important difference between Android and most Linux environments is the +Application Sandbox. On Android, all applications run in the Application +Sandbox, including those written with native code. At the most basic level, a +good way to think about it for developers familiar with Linux is to know that +every application is given a unique UID with very limited permissions. This is +discussed in more detail in the Android Security +Overview and you should be familiar with application permissions even if +you are using native code.

    + + +

    Storing Data

    + +

    Using internal files

    + +

    By default, files created on internal +storage are only accessible to the application that created the file. This +protection is implemented by Android and is sufficient for most +applications.

    + +

    Use of +world writable or world +readable files for IPC is discouraged because it does not provide +the ability to limit data access to particular applications, nor does it +provide any control on data format. As an alternative, you might consider using +a ContentProvider which provides read and write permissions, and can make +dynamic permission grants on a case-by-case basis.

    + +

    To provide additional protection for sensitive data, some applications +choose to encrypt local files using a key that is not accessible to the +application. (For example, a key can be placed in a KeyStore and +protected with a user password that is not stored on the device). While this +does not protect data from a root compromise that can monitor the user +inputting the password, it can provide protection for a lost device without file system +encryption.

    + +

    Using external storage

    + +

    Files created on external +storage, such as SD Cards, are globally readable and writable. Since +external storage can be removed by the user and also modified by any +application, applications should not store sensitive information using +external storage.

    + +

    As with data from any untrusted source, applications should perform input +validation when handling data from external storage (see Input Validation +section). We strongly recommend that applications not store executables or +class files on external storage prior to dynamic loading. If an application +does retrieve executable files from external storage they should be signed and +cryptographically verified prior to dynamic loading.

    + +

    Using content providers

    + +

    ContentProviders provide a structured storage mechanism that can be limited +to your own application, or exported to allow access by other applications. By +default, a + +ContentProvider is +exported + for use by other applications. If you do not intend to provide other +applications with access to your + +ContentProvider, mark them as +android:exported=false in the application manifest.

    + +

    When creating a +ContentProvider + that will be exported for use by other applications, you can specify +a single +permission + for reading and writing, or distinct permissions for reading and writing +within the manifest. We recommend that you limit your permissions to those +required to accomplish the task at hand. Keep in mind that it’s usually +easier to add permissions later to expose new functionality than it is to take +them away and break existing users.

    + +

    If you are using a + +ContentProvider for sharing data between applications built by the +same developer, it is preferable to use +signature +level permissions. Signature permissions do not require user confirmation, +so they provide a better user experience and more controlled access to the + + +ContentProvider.

    + +

    ContentProviders can also provide more granular access by declaring the +grantUriPermissions element and using the FLAG_GRANT_READ_URI_PERMISSION +and FLAG_GRANT_WRITE_URI_PERMISSION +flags in the Intent object +that activates the component. The scope of these permissions can be further +limited by the +grant-uri-permission element.

    + +

    When accessing a + +ContentProvider, use parameterized query methods such as +query(), update(), and delete() to avoid +potential SQL +Injection from untrusted data. Note that using parameterized methods is not +sufficient if the selection is built by concatenating user data +prior to submitting it to the method.

    + +

    Do not have a false sense of security about the write permission. Consider +that the write permission allows SQL statements which make it possible for some +data to be confirmed using creative WHERE clauses and parsing the +results. For example, an attacker might probe for presence of a specific phone +number in a call-log by modifying a row only if that phone number already +exists. If the content provider data has predictable structure, the write +permission may be equivalent to providing both reading and writing.

    + + +

    Using Interprocess Communication (IPC)

    + +

    Some Android applications attempt to implement IPC using traditional Linux +techniques such as network sockets and shared files. We strongly encourage the +use of Android system functionality for IPC such as Intents, Binders, Services, +and Receivers. The Android IPC mechanisms allow you to verify the identity of +the application connecting to your IPC and set security policy for each IPC +mechanism.

    + +

    Many of the security elements are shared across IPC mechanisms. +Broadcast Receivers, +Activities, and +Services are all declared in the application manifest. If your IPC mechanism is +not intended for use by other applications, set the {@code android:exported} +property to false. This is useful for applications that consist of multiple processes +within the same UID, or if you decide late in development that you do not +actually want to expose functionality as IPC but you don’t want to rewrite +the code.

    + +

    If your IPC is intended to be accessible to other applications, you can +apply a security policy by using the +Permission tag. If IPC is between applications built by the same developer, +it is preferable to use signature +level permissions. Signature permissions do not require user confirmation, +so they provide a better user experience and more controlled access to the IPC +mechanism.

    + +

    One area that can introduce confusion is the use of intent filters. Note +that Intent filters should not be considered a security feature -- components +can be invoked directly and may not have data that would conform to the intent +filter. You should perform input validation within your intent receiver to +confirm that it is properly formatted for the invoked receiver, service, or +activity.

    + +

    Using intents

    + +

    Intents are the preferred mechanism for asynchronous IPC in Android. +Depending on your application requirements, you might use sendBroadcast(), +sendOrderedBroadcast(), +or direct an intent to a specific application component.

    + +

    Note that ordered broadcasts can be “consumed” by a recipient, so they +may not be delivered to all applications. If you are sending an Intent where +delivery to a specific receiver is required, the intent must be delivered +directly to the receiver.

    + +

    Senders of an intent can verify that the recipient has a permission +specifying a non-Null Permission upon sending. Only applications with that +Permission will receive the intent. If data within a broadcast intent may be +sensitive, you should consider applying a permission to make sure that +malicious applications cannot register to receive those messages without +appropriate permissions. In those circumstances, you may also consider +invoking the receiver directly, rather than raising a broadcast.

    + +

    Using binder and AIDL interfaces

    + +

    Binders are the +preferred mechanism for RPC-style IPC in Android. They provide a well-defined +interface that enables mutual authentication of the endpoints, if required.

    + +

    We strongly encourage designing interfaces in a manner that does not require +interface specific permission checks. Binders are not declared within the +application manifest, and therefore you cannot apply declarative permissions +directly to a Binder. Binders generally inherit permissions declared in the +application manifest for the Service or Activity within which they are +implemented. If you are creating an interface that requires authentication +and/or access controls on a specific binder interface, those controls must be +explicitly added as code in the interface.

    + +

    If providing an interface that does require access controls, use checkCallingPermission() +to verify whether the +caller of the Binder has a required permission. This is especially important +before accessing a Service on behalf of the caller, as the identify of your +application is passed to other interfaces. If invoking an interface provided +by a Service, the bindService() + invocation may fail if you do not have permission to access the given Service. + If calling an interface provided locally by your own application, it may be +useful to use the +clearCallingIdentity() to satisfy internal security checks.

    + +

    Using broadcast receivers

    + +

    Broadcast receivers are used to handle asynchronous requests initiated via +an intent.

    + +

    By default, receivers are exported and can be invoked by any other +application. If your +BroadcastReceivers is intended for use by other applications, you +may want to apply security permissions to receivers using the +<receiver> element within the application manifest. This will +prevent applications without appropriate permissions from sending an intent to +the +BroadcastReceivers.

    + +

    Using Services

    + +

    Services are often used to supply functionality for other applications to +use. Each service class must have a corresponding declaration in its +package's AndroidManifest.xml.

    + +

    By default, Services are exported and can be invoked by any other +application. Services can be protected using the {@code android:permission} +attribute +within the manifest’s +<service> tag. By doing so, other applications will need to declare +a corresponding <uses-permission> + element in their own manifest to be +able to start, stop, or bind to the service.

    + +

    A Service can protect individual IPC calls into it with permissions, by +calling checkCallingPermission() +before executing +the implementation of that call. We generally recommend using the +declarative permissions in the manifest, since those are less prone to +oversight.

    + +

    Using Activities

    + +

    Activities are most often used for providing the core user-facing +functionality of an application. By default, Activities are exported and +invokable by other applications only if they have an intent filter or binder +declared. In general, we recommend that you specifically declare a Receiver or +Service to handle IPC, since this modular approach reduces the risk of exposing +functionality that is not intended for use by other applications.

    + +

    If you do expose an Activity for purposes of IPC, the android:permission +attribute in the +<activity> declaration in the application manifest can be used to +restrict access to only those applications which have the stated permissions.

    -

    A particular permission may be enforced at a number of places during your -program's operation:

    + +

    Using Permissions

    +

    Requesting Permissions

    + +

    We recommend minimizing the number of permissions requested by an +application. Not having access to sensitive permissions reduces the risk of +inadvertently misusing those permissions, can improve user adoption, and makes +applications less attractive targets for attackers.

    + +

    If it is possible to design your application in a way that does not require +a permission, that is preferable. For example, rather than requesting access +to device information to create an identifier, create a GUID for your application. +(This specific example is also discussed in Handling User Data) Or, rather than +using external storage, store data in your application directory.

    + +

    If a permission is not required, do not request it. This sounds simple, but +there has been quite a bit of research into the frequency of over-requesting +permissions. If you’re interested in the subject you might start with this +research paper published by U.C. Berkeley: +http://www.eecs.berkeley.edu/Pubs/TechRpts/2011/EECS-2011-48.pdf

    + +

    In addition to requesting permissions, your application can use permissions +to protect IPC that is security sensitive and will be exposed to other +applications -- such as a +ContentProvider. In general, we recommend using access controls +other than user confirmed permissions where possible since permissions can +be confusing for users. For example, consider using the signature +protection level on permissions for IPC communication between applications +provided by a single developer.

    + +

    Do not cause permission re-delegation. This occurs when an app exposes data +over IPC that is only available because it has a specific permission, but does +not require that permission of any clients of it’s IPC interface. More +details on the potential impacts, and frequency of this type of problem is +provided in this research paper published at USENIX: http://www.cs.be +rkeley.edu/~afelt/felt_usenixsec2011.pdf

    + +

    Creating Permissions

    + +

    Generally, you should strive to create as few permissions as possible while +satisfying your security requirements. Creating a new permission is relatively +uncommon for most applications, since system-defined +permissions cover many situations. Where appropriate, +perform access checks using existing permissions.

    + +

    If you must create a new permission, consider whether you can accomplish +your task with a Signature permission. Signature permissions are transparent +to the user and only allow access by applications signed by the same developer +as application performing the permission check. If you create a Dangerous +permission, then the user needs to decide whether to install the application. +This can be confusing for other developers, as well as for users.

    + +

    If you create a Dangerous permission, there are a number of complexities +that you need to consider.

      -
    • At the time of a call into the system, to prevent an application from -executing certain functions.
    • -
    • When starting an activity, to prevent applications from launching -activities of other applications.
    • -
    • Both sending and receiving broadcasts, to control who can receive -your broadcast or who can send a broadcast to you.
    • -
    • When accessing and operating on a content provider.
    • -
    • Binding to or starting a service.
    • -
    - - - -

    Declaring and Enforcing Permissions

    - -

    To enforce your own permissions, you must first declare them in your -AndroidManifest.xml using one or more -{@link android.R.styleable#AndroidManifestPermission <permission>} -tags.

    - -

    For example, an application that wants to control who can start one -of its activities could declare a permission for this operation as follows:

    - -
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    -    package="com.me.app.myapp" >
    -    <permission android:name="com.me.app.myapp.permission.DEADLY_ACTIVITY"
    -        android:label="@string/permlab_deadlyActivity"
    -        android:description="@string/permdesc_deadlyActivity"
    -        android:permissionGroup="android.permission-group.COST_MONEY"
    -        android:protectionLevel="dangerous" />
    -    ...
    -</manifest>
    - -

    The {@link android.R.styleable#AndroidManifestPermission_protectionLevel -<protectionLevel>} attribute is required, telling the system how the -user is to be informed of applications requiring the permission, or who is -allowed to hold that permission, as described in the linked documentation.

    - -

    The {@link android.R.styleable#AndroidManifestPermission_permissionGroup -<permissionGroup>} attribute is optional, and only used to help the system display -permissions to the user. You will usually want to set this to either a standard -system group (listed in {@link android.Manifest.permission_group -android.Manifest.permission_group}) or in more rare cases to one defined by -yourself. It is preferred to use an existing group, as this simplifies the -permission UI shown to the user.

    - -

    Note that both a label and description should be supplied for the -permission. These are string resources that can be displayed to the user when -they are viewing a list of permissions -({@link android.R.styleable#AndroidManifestPermission_label android:label}) -or details on a single permission ( -{@link android.R.styleable#AndroidManifestPermission_description android:description}). -The label should be short, a few words -describing the key piece of functionality the permission is protecting. The -description should be a couple sentences describing what the permission allows -a holder to do. Our convention for the description is two sentences, the first -describing the permission, the second warning the user of what bad things -can happen if an application is granted the permission.

    - -

    Here is an example of a label and description for the CALL_PHONE -permission:

    - -
    -    <string name="permlab_callPhone">directly call phone numbers</string>
    -    <string name="permdesc_callPhone">Allows the application to call
    -        phone numbers without your intervention. Malicious applications may
    -        cause unexpected calls on your phone bill. Note that this does not
    -        allow the application to call emergency numbers.</string>
    -
    - -

    You can look at the permissions currently defined in the system with the -Settings app and the shell command adb shell pm list permissions. -To use the Settings app, go to Settings > Applications. Pick an app and -scroll down to see the permissions that the app uses. For developers, the adb '-s' -option displays the permissions in a form similar to how the user will see them:

    - -
    -$ adb shell pm list permissions -s
    -All Permissions:
    -
    -Network communication: view Wi-Fi state, create Bluetooth connections, full
    -Internet access, view network state
    -
    -Your location: access extra location provider commands, fine (GPS) location,
    -mock location sources for testing, coarse (network-based) location
    -
    -Services that cost you money: send SMS messages, directly call phone numbers
    -
    -...
    - - -

    Enforcing Permissions in AndroidManifest.xml

    - -

    High-level permissions restricting access to entire components of the -system or application can be applied through your -AndroidManifest.xml. All that this requires is including an {@link -android.R.attr#permission android:permission} attribute on the desired -component, naming the permission that will be used to control access to -it.

    - -

    {@link android.app.Activity} permissions -(applied to the -{@link android.R.styleable#AndroidManifestActivity <activity>} tag) -restrict who can start the associated -activity. The permission is checked during -{@link android.content.Context#startActivity Context.startActivity()} and -{@link android.app.Activity#startActivityForResult Activity.startActivityForResult()}; -if the caller does not have -the required permission then {@link java.lang.SecurityException} is thrown -from the call.

    - -

    {@link android.app.Service} permissions -(applied to the -{@link android.R.styleable#AndroidManifestService <service>} tag) -restrict who can start or bind to the -associated service. The permission is checked during -{@link android.content.Context#startService Context.startService()}, -{@link android.content.Context#stopService Context.stopService()} and -{@link android.content.Context#bindService Context.bindService()}; -if the caller does not have -the required permission then {@link java.lang.SecurityException} is thrown -from the call.

    - -

    {@link android.content.BroadcastReceiver} permissions -(applied to the -{@link android.R.styleable#AndroidManifestReceiver <receiver>} tag) -restrict who can send broadcasts to the associated receiver. -The permission is checked after -{@link android.content.Context#sendBroadcast Context.sendBroadcast()} returns, -as the system tries -to deliver the submitted broadcast to the given receiver. As a result, a -permission failure will not result in an exception being thrown back to the -caller; it will just not deliver the intent. In the same way, a permission -can be supplied to -{@link android.content.Context#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler) -Context.registerReceiver()} -to control who can broadcast to a programmatically registered receiver. -Going the other way, a permission can be supplied when calling -{@link android.content.Context#sendBroadcast(Intent, String) Context.sendBroadcast()} -to restrict which BroadcastReceiver objects are allowed to receive the broadcast (see -below).

    - -

    {@link android.content.ContentProvider} permissions -(applied to the -{@link android.R.styleable#AndroidManifestProvider <provider>} tag) -restrict who can access the data in -a {@link android.content.ContentProvider}. (Content providers have an important -additional security facility available to them called -URI permissions which is described later.) -Unlike the other components, -there are two separate permission attributes you can set: -{@link android.R.attr#readPermission android:readPermission} restricts who -can read from the provider, and -{@link android.R.attr#writePermission android:writePermission} restricts -who can write to it. Note that if a provider is protected with both a read -and write permission, holding only the write permission does not mean -you can read from a provider. The permissions are checked when you first -retrieve a provider (if you don't have either permission, a SecurityException -will be thrown), and as you perform operations on the provider. Using -{@link android.content.ContentResolver#query ContentResolver.query()} requires -holding the read permission; using -{@link android.content.ContentResolver#insert ContentResolver.insert()}, -{@link android.content.ContentResolver#update ContentResolver.update()}, -{@link android.content.ContentResolver#delete ContentResolver.delete()} -requires the write permission. -In all of these cases, not holding the required permission results in a -{@link java.lang.SecurityException} being thrown from the call.

    - - - -

    Enforcing Permissions when Sending Broadcasts

    - -

    In addition to the permission enforcing who can send Intents to a -registered {@link android.content.BroadcastReceiver} (as described above), you -can also specify a required permission when sending a broadcast. By calling {@link -android.content.Context#sendBroadcast(android.content.Intent,String) -Context.sendBroadcast()} with a -permission string, you require that a receiver's application must hold that -permission in order to receive your broadcast.

    - -

    Note that both a receiver and a broadcaster can require a permission. When -this happens, both permission checks must pass for the Intent to be delivered -to the associated target.

    - - - -

    Other Permission Enforcement

    - -

    Arbitrarily fine-grained permissions can be enforced at any call into a -service. This is accomplished with the {@link -android.content.Context#checkCallingPermission Context.checkCallingPermission()} -method. Call with a desired -permission string and it will return an integer indicating whether that -permission has been granted to the current calling process. Note that this can -only be used when you are executing a call coming in from another process, -usually through an IDL interface published from a service or in some other way -given to another process.

    - -

    There are a number of other useful ways to check permissions. If you have -the pid of another process, you can use the Context method {@link -android.content.Context#checkPermission(String, int, int) Context.checkPermission(String, int, int)} -to check a permission against that pid. If you have the package name of another -application, you can use the direct PackageManager method {@link -android.content.pm.PackageManager#checkPermission(String, String) -PackageManager.checkPermission(String, String)} -to find out whether that particular package has been granted a specific permission.

    - - - -

    URI Permissions

    - -

    The standard permission system described so far is often not sufficient -when used with content providers. A content provider may want to -protect itself with read and write permissions, while its direct clients -also need to hand specific URIs to other applications for them to operate on. -A typical example is attachments in a mail application. Access to the mail -should be protected by permissions, since this is sensitive user data. However, -if a URI to an image attachment is given to an image viewer, that image viewer -will not have permission to open the attachment since it has no reason to hold -a permission to access all e-mail.

    - -

    The solution to this problem is per-URI permissions: when starting an -activity or returning a result to an activity, the caller can set -{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION -Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or -{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION -Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. This grants the receiving activity -permission access the specific data URI in the Intent, regardless of whether -it has any permission to access data in the content provider corresponding -to the Intent.

    - -

    This mechanism allows a common capability-style model where user interaction -(opening an attachment, selecting a contact from a list, etc) drives ad-hoc -granting of fine-grained permission. This can be a key facility for reducing -the permissions needed by applications to only those directly related to their -behavior.

    - -

    The granting of fine-grained URI permissions does, however, require some -cooperation with the content provider holding those URIs. It is strongly -recommended that content providers implement this facility, and declare that -they support it through the -{@link android.R.styleable#AndroidManifestProvider_grantUriPermissions -android:grantUriPermissions} attribute or -{@link android.R.styleable#AndroidManifestGrantUriPermission -<grant-uri-permissions>} tag.

    - -

    More information can be found in the -{@link android.content.Context#grantUriPermission Context.grantUriPermission()}, -{@link android.content.Context#revokeUriPermission Context.revokeUriPermission()}, and -{@link android.content.Context#checkUriPermission Context.checkUriPermission()} -methods.

    - +
  • The permission must have a string that concisely expresses to a user the +security decision they will be required to make.
  • +
  • The permission string must be localized to many different languages.
  • +
  • Uses may choose not to install an application because a permission is +confusing or perceived as risky.
  • +
  • Applications may request the permission when the creator of the permission +has not been installed.
  • +

    + +

    Each of these poses a significant non-technical challenge for an application +developer, which is why we discourage the use of Dangerous permission.

    + + +

    Using Networking

    + +

    Using IP Networking

    + +

    Networking on Android is not significantly different from Linux +environments. The key consideration is making sure that appropriate protocols +are used for sensitive data, such as HTTPS for +web traffic. We prefer use of HTTPS over HTTP anywhere that HTTPS is +supported on the server, since mobile devices frequently connect on networks +that are not secured, such as public WiFi hotspots.

    + +

    Authenticated, encrypted socket-level communication can be easily +implemented using the SSLSocket +class. Given the frequency with which Android devices connect to unsecured +wireless networks using WiFi, the use of secure networking is strongly +encouraged for all applications.

    + +

    We have seen some applications use localhost network ports for +handling sensitive IPC. We discourage this approach since these interfaces are +accessible by other applications on the device. Instead, use an Android IPC +mechanism where authentication is possible such as a Service and Binder. (Even +worse than using loopback is to bind to INADDR_ANY since then your application +may receive requests from anywhere. We’ve seen that, too.)

    + +

    Also, one common issue that warrants repeating is to make sure that you do +not trust data downloaded from HTTP or other insecure protocols. This includes +validation of input in WebView and +any responses to intents issued against HTTP.

    + +

    Using Telephony Networking

    + +

    SMS is the telephony protocol most frequently used by Android developers. +Developers should keep in mind that this protocol was primarily designed for +user-to-user communication and is not well-suited for some application +purposes. Due to the limitations of SMS, we strongly recommend the use of C2DM and IP networking for +sending data messages to devices.

    + +

    Many developers do not realize that SMS is not encrypted or strongly +authenticated on the network or on the device. In particular, any SMS receiver +should expect that a malicious user may have sent the SMS to your application +-- do not rely on unauthenticated SMS data to perform sensitive commands. +Also, you should be aware that SMS may be subject to spoofing and/or +interception on the network. On the Android-powered device itself, SMS +messages are transmitted as Broadcast intents, so they may be read or captured +by other applications that have the READ_SMS permission.

    + + +

    Dynamically Loading Code

    + +

    We strongly discourage loading code from outside of the application APK. +Doing so significantly increases the likelihood of application compromise due +to code injection or code tampering. It also adds complexity around version +management and application testing. Finally, it can make it impossible to +verify the behavior of an application, so it may be prohibited in some +environments.

    + +

    If your application does dynamically load code, the most important thing to +keep in mind about dynamically loaded code is that it runs with the same +security permissions as the application APK. The user made a decision to +install your application based on your identity, and they are expecting that +you provide any code run within the application, including code that is +dynamically loaded.

    + +

    The major security risk associated with dynamically loading code is that the +code needs to come from a verifiable source. If the modules are included +directly within your APK, then they cannot be modified by other applications. +This is true whether the code is a native library or a class being loaded using + +DexClassLoader. We have seen many instances of applications +attempting to load code from insecure locations, such as downloaded from the +network over unencrypted protocols or from world writable locations such as +external storage. These locations could allow someone on the network to modify +the content in transit, or another application on a users device to modify the +content, respectively.

    + + +

    Using WebView

    + +

    Since WebView consumes web content that can include HTML and JavaScript, +improper use can introduce common web security issues such as cross-site-scripting (JavaScript injection). Android includes a number of mechanisms to reduce +the scope of these potential issues by limiting the capability of WebView to +the minimum functionality required by your application.

    + +

    If your application does not directly use JavaScript within a WebView, do +not call + +setJavaScriptEnabled(). We have seen this method invoked +in sample code that might be repurposed in production application -- so +remove it if necessary. By default, WebView does +not execute JavaScript so cross-site-scripting is not possible.

    + +

    Use addJavaScriptInterface() with +particular care because it allows JavaScript to invoke operations that are +normally reserved for Android applications. Only expose addJavaScriptInterface() to +sources from which all input is trustworthy. If untrusted input is allowed, +untrusted JavaScript may be able to invoke Android methods. In general, we +recommend only exposing addJavaScriptInterface() to +JavaScript that is contained within your application APK.

    + +

    Do not trust information downloaded over HTTP, use HTTPS instead. Even if +you are connecting only to a single website that you trust or control, HTTP is +subject to MiTM attacks +and interception of data. Sensitive capabilities using addJavaScriptInterface() should +not ever be exposed to unverified script downloaded over HTTP. Note that even +with the use of HTTPS, +addJavaScriptInterface() +increases the attack surface of your application to include the server +infrastructure and all CAs trusted by the Android-powered device.

    + +

    If your application accesses sensitive data with a WebView, you +may want to use the +clearCache() method to delete any files stored locally. Server side +headers like no-cache can also be used to indicate that an application should +not cache particular content.

    + + +

    Performing Input Validation

    + +

    Insufficient input validation is one of the most common security problems +affecting applications, regardless of what platform they run on. Android does +have platform-level countermeasures that reduce the exposure of applications to +input validation issues, you should use those features where possible. Also +note that selection of type-safe languages tends to reduce the likelihood of +input validation issues. We strongly recommend building your applications with +the Android SDK.

    + +

    If you are using native code, then any data read from files, received over +the network, or received from an IPC has the potential to introduce a security +issue. The most common problems are buffer overflows, use after +free, and off-by-one errors. +Android provides a number of technologies like ASLR and DEP that reduce the +exploitability of these errors, but they do not solve the underlying problem. +These can be prevented by careful handling of pointers and managing of +buffers.

    + +

    Dynamic, string based languages such as JavaScript and SQL are also subject +to input validation problems due to escape characters and script injection.

    + +

    If you are using data within queries that are submitted to SQL Database or a +Content Provider, SQL Injection may be an issue. The best defense is to use +parameterized queries, as is discussed in the ContentProviders section. +Limiting permissions to read-only or write-only can also reduce the potential +for harm related to SQL Injection.

    + +

    If you are using WebView, then +you must consider the possibility of XSS. If your application does not +directly use JavaScript within a WebView, do +not call setJavaScriptEnabled() and XSS is no longer possible. If you must +enable JavaScript then the WebView section provides other security best +practices.

    + +

    If you cannot use the security features above, we strongly recommend the use +of well-structured data formats and verifying that the data conforms to the +expected format. While blacklisting of characters or character-replacement can +be an effective strategy, these techniques are error-prone in practice and +should be avoided when possible.

    + + +

    Handling User Data

    + +

    In general, the best approach is to minimize use of APIs that access +sensitive or personal user data. If you have access to data and can avoid +storing or transmitting the information, do not store or transmit the data. +Finally, consider if there is a way that your application logic can be +implemented using a hash or non-reversible form of the data. For example, your +application might use the hash of an an email address as a primary key, to +avoid transmitting or storing the email address. This reduces the chances of +inadvertently exposing data, and it also reduces the chance of attackers +attempting to exploit your application.

    + +

    If your application accesses personal information such as passwords or +usernames, keep in mind that some jurisdictions may require you to provide a +privacy policy explaining your use and storage of that data. So following the +security best practice of minimizing access to user data may also simplify +compliance.

    + +

    You should also consider whether your application might be inadvertently +exposing personal information to other parties such as third-party components +for advertising or third-party services used by your application. If you don't +know why a component or service requires a personal information, don’t +provide it. In general, reducing the access to personal information by your +application will reduce the potential for problems in this area.

    + +

    If access to sensitive data is required, evaluate whether that information +must be transmitted to a server, or whether the operation can be performed on +the client. Consider running any code using sensitive data on the client to +avoid transmitting user data.

    + +

    Also, make sure that you do not inadvertently expose user data to other +application on the device through overly permissive IPC, world writable files, +or network sockets. This is a special case of permission redelegation, +discussed in the Requesting Permissions section.

    + +

    If a GUID is required, create a large, unique number and store it. Do not +use phone identifiers such as the phone number or IMEI which may be associated +with personal information. This topic is discussed in more detail in the Android Developer Blog.

    + +

    Application developers should be careful writing to on-device logs. +In Android, logs are a shared resource, and are available +to an application with the + +READ_LOGS permission. Even though the phone log data +is temporary and erased on reboot, inappropriate logging of user information +could inadvertently leak user data to other applications.

    + + +

    Handling Credentials

    + +

    In general, we recommend minimizing the frequency of asking for user +credentials -- to make phishing attacks more conspicuous, and less likely to be +successful. Instead use an authorization token and refresh it.

    + +

    Where possible, username and password should not be stored on the device. +Instead, perform initial authentication using the username and password +supplied by the user, and then use a short-lived, service-specific +authorization token.

    + +

    Services that will be accessible to multiple applications should be accessed +using + +AccountManager. If possible, use the +AccountManager class to invoke a cloud-based service and do not store +passwords on the device.

    + +

    After using +AccountManager to retrieve an Account, check the CREATOR + before passing in any credentials, so that you do not inadvertently pass +credentials to the wrong application.

    + +

    If credentials are to be used only by applications that you create, then you +can verify the application which accesses the +AccountManager using checkSignature(). +Alternatively, if only one application will use the credential, you might use a +KeyStore for +storage.

    + + +

    Using Cryptography

    + +

    In addition to providing data isolation, supporting full-filesystem +encryption, and providing secure communications channels Android provides a +wide array of algorithms for protecting data using cryptography.

    + +

    In general, try to use the highest level of pre-existing framework +implementation that can support your use case. If you need to securely +retrieve a file from a known location, a simple HTTPS URI may be adequate and +require no knowledge of cryptography on your part. If you need a secure +tunnel, consider using + +HttpsURLConnection or SSLSocket, +rather than writing your own protocol.

    + +

    If you do find yourself needing to implement your own protocol, we strongly +recommend that you not implement your own cryptographic algorithms. Use +existing cryptographic algorithms such as those in the implementation of AES or +RSA provided in the Cipher class.

    + +

    Use a secure random number generator ( + +SecureRandom) to initialize any cryptographic keys ( +KeyGenerator). Use of a key that is not generated with a secure random +number generator significantly weakens the strength of the algorithm, and may +allow offline attacks.

    + +

    If you need to store a key for repeated use, use a mechanism like KeyStore that +provides a mechanism for long term storage and retrieval of cryptographic +keys.

    + +

    Conclusion

    + +

    Android provides developers with the ability to design applications with a +broad range of security requirements. These best practices will help you make +sure that your application takes advantage of the security benefits provided by +the platform.

    + +

    You can receive more information on these topics and discuss security best +practices with other developers in the Android Security +Discuss Google Group

    diff --git a/docs/html/guide/topics/sensors/index.jd b/docs/html/guide/topics/sensors/index.jd index 43903dcf735ae28884f66dfaf30892f95ca73228..a0458994d36dc88b7eaf890809e575be46aa2c16 100644 --- a/docs/html/guide/topics/sensors/index.jd +++ b/docs/html/guide/topics/sensors/index.jd @@ -1,88 +1,40 @@ -page.title=Sensors -@jd:body - -
    -
    -

    Topics

    -
      -
    1. Sensors Overview
    2. -
    3. Motion Sensors
    4. -
    5. Position - Sensors
    6. -
    7. Environment - Sensors
    8. -
    -

    Key classes and interfaces

    -
      -
    1. {@link android.hardware.Sensor}
    2. -
    3. {@link android.hardware.SensorEvent}
    4. -
    5. {@link android.hardware.SensorManager}
    6. -
    7. {@link android.hardware.SensorEventListener}
    8. -
    -

    Related samples

    -
      -
    1. Accelerometer - Play
    2. -
    3. -API Demos (OS - RotationVectorDemo)
    4. -
    5. API Demos -(OS - Sensors)
    6. -
    -
    -
    +page.title=Location and Sensors +page.landing=true +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= -

    Most Android-powered devices have built-in sensors that measure motion, orientation, -and various environmental conditions. These sensors are capable of providing raw data with high -precision and accuracy, and are useful if you want to monitor three-dimensional device movement or -positioning, or you want to monitor changes in the ambient environment near a device. For example, a -game might track readings from a device's gravity sensor to infer complex user gestures -and motions, such as tilt, shake, rotation, or swing. Likewise, a weather application might use a -device's temperature sensor and humidity sensor to calculate and report the dewpoint, or a travel -application might use the geomagnetic field sensor and accelerometer to report a compass -bearing.

    +@jd:body -

    The Android platform supports three broad categories of sensors:

    +
    -
      -
    • Motion sensors -

      These sensors measure acceleration forces and rotational forces along three axes. This - category includes accelerometers, gravity sensors, gyroscopes, and rotational vector - sensors.

      -
    • -
    • Environmental sensors -

      These sensors measure various environmental parameters, such as ambient air temperature - and pressure, illumination, and humidity. This category includes barometers, photometers, and - thermometers.

      -
    • -
    • Position sensors -

      These sensors measure the physical position of a device. This category includes - orientation sensors and magnetometers.

      -
    • -
    + -

    To access these sensors, you can use the Android sensor framework. The sensor framework provides -several classes and interfaces that help you perform a wide variety of sensor-related tasks. To -learn more about the framework and the sensors that are supported on the Android system, read the -following documents:

    + -
    -
    Sensors - Overview
    -
    Learn how to list the sensors that are on a device, set up sensor event listeners, and - acquire sensor data. Also learn best practices for accessing and using sensors.
    -
    Motion - Sensors
    -
    Learn how to use the sensors that provide acceleration data, such as the accelerometer, - gravity sensor, and linear acceleration sensor. Also learn how to use the sensors that - provide rotational data, such as gyroscopes and rotational vector sensors.
    -
    Position - Sensors
    -
    Learn how to use the sensors that provide orientation and compass data, such as the - orientation sensor and the geomagnetic field sensor.
    -
    Environment - Sensors
    -
    Learn how to use the sensors that provide environmental data, such as the light, - humidity, pressure, temperature, and proximity sensors.
    -
    +
    \ No newline at end of file diff --git a/docs/html/guide/topics/sensors/sensors_overview.jd b/docs/html/guide/topics/sensors/sensors_overview.jd index 543872ce57fbe86bb2e864bb32690d8108c4c209..e38a8430a878bfd4895d9a78dc31e53cf4d5ffb8 100644 --- a/docs/html/guide/topics/sensors/sensors_overview.jd +++ b/docs/html/guide/topics/sensors/sensors_overview.jd @@ -50,13 +50,39 @@ href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/Senso -

    Most Android-powered devices have sensors that let you monitor changes in device -position and motion. Many devices also have sensors that let you determine ambient environmental -conditions, such as temperature, pressure, humidity, and lighting. You can access these -sensors and acquire raw sensor data by using the Android sensor framework.

    +

    Most Android-powered devices have built-in sensors that measure motion, orientation, +and various environmental conditions. These sensors are capable of providing raw data with high +precision and accuracy, and are useful if you want to monitor three-dimensional device movement or +positioning, or you want to monitor changes in the ambient environment near a device. For example, a +game might track readings from a device's gravity sensor to infer complex user gestures +and motions, such as tilt, shake, rotation, or swing. Likewise, a weather application might use a +device's temperature sensor and humidity sensor to calculate and report the dewpoint, or a travel +application might use the geomagnetic field sensor and accelerometer to report a compass +bearing.

    + +

    The Android platform supports three broad categories of sensors:

    -

    The sensor framework provides several classes and interfaces that help you perform a wide variety -of sensor-related tasks. For example, you can use the sensor framework to do the following:

    +
      +
    • Motion sensors +

      These sensors measure acceleration forces and rotational forces along three axes. This + category includes accelerometers, gravity sensors, gyroscopes, and rotational vector + sensors.

      +
    • +
    • Environmental sensors +

      These sensors measure various environmental parameters, such as ambient air temperature + and pressure, illumination, and humidity. This category includes barometers, photometers, and + thermometers.

      +
    • +
    • Position sensors +

      These sensors measure the physical position of a device. This category includes + orientation sensors and magnetometers.

      +
    • +
    + + +

    You can access sensors available on the device and acquire raw sensor data by using the Android +sensor framework. The sensor framework provides several classes and interfaces that help you perform a wide +variety of sensor-related tasks. For example, you can use the sensor framework to do the following:

    • Determine which sensors are available on a device.
    • diff --git a/docs/html/guide/topics/testing/index.jd b/docs/html/guide/topics/testing/index.jd deleted file mode 100644 index cf87187aa0122627d55ce89ef3426109bb2a2eb9..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/testing/index.jd +++ /dev/null @@ -1,86 +0,0 @@ -page.title=Testing -@jd:body -

      - The Android development environment includes an integrated testing framework that helps you - test all aspects of your application. -

      -

      Fundamentals

      -

      - To start learning how to use the framework to create tests for your applications, please - read the topic - Testing Fundamentals. -

      -

      Concepts

      -
        -
      • - - Activity Testing focuses on testing activities. It describes how instrumentation allows - you to control activities outside the normal application lifecycle. It also lists - activity-specific features you should test, and it provides tips for testing Android - user interfaces. -
      • -
      • - - Content Provider Testing focuses on testing content providers. It describes the - mock system objects you can use, provides tips for designing providers so that they - can be tested, and lists provider-specific features you should test. -
      • -
      • - - Service Testing focuses on testing services. It also lists service-specific features - you should test. -
      • -
      • - What to Test - is an overview of the types of testing you should do. It focuses on testing - system-wide aspects of Android that can affect every component in your application. -
      • -
      -

      Procedures

      - -

      Tutorials

      -
        -
      • - The - Hello, Testing tutorial introduces basic testing concepts and procedures. -
      • -
      • - For a more advanced tutorial, try - Activity Testing, - which guides you through a more complex testing scenario. -
      • -
      -

      Tools

      -
        -
      • - The - UI/Application Exerciser Monkey, - usually called Monkey, is a command-line tool that sends pseudo-random - streams of keystrokes, touches, and gestures to a device. -
      • -
      • - The monkeyrunner tool - is an API and execution environment. You use monkeyrunner with Python programs - to test applications and devices. -
      • -
      - diff --git a/docs/html/guide/topics/clipboard/copy-paste.jd b/docs/html/guide/topics/text/copy-paste.jd similarity index 100% rename from docs/html/guide/topics/clipboard/copy-paste.jd rename to docs/html/guide/topics/text/copy-paste.jd diff --git a/docs/html/resources/articles/creating-input-method.jd b/docs/html/guide/topics/text/creating-input-method.jd similarity index 98% rename from docs/html/resources/articles/creating-input-method.jd rename to docs/html/guide/topics/text/creating-input-method.jd index 84c2704f5568eb8b225806290b7416bc12413442..e49610f6f34ea5996144b8d2999e18ea8155cf24 100644 --- a/docs/html/resources/articles/creating-input-method.jd +++ b/docs/html/guide/topics/text/creating-input-method.jd @@ -8,7 +8,7 @@ parent.link=../browser.html?tag=article

      See also

      1. - Onscreen Input Methods + Onscreen Input Methods
      2. Soft Keyboard sample @@ -40,7 +40,7 @@ parent.link=../browser.html?tag=article

    If you haven't worked with IMEs before, you should read the introductory article - Onscreen Input Methods first. + Onscreen Input Methods first. Also, the Soft Keyboard sample app included in the SDK contains sample code that you can modify to start building your own IME.

    diff --git a/docs/html/guide/topics/text/index.jd b/docs/html/guide/topics/text/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..3865f25aee71481fb072c7653f820ac79aff4ccd --- /dev/null +++ b/docs/html/guide/topics/text/index.jd @@ -0,0 +1,40 @@ +page.title=Text and Input +page.landing=true +page.landing.intro=Use text services to add conventient features such as copy/paste and spell checking to your app. You can also develop your own text services to offer custom IMEs, dictionaries, and spelling checkers that you can distribute to users as applications. +page.landing.image= + +@jd:body + + \ No newline at end of file diff --git a/docs/html/resources/articles/spell-checker-framework.jd b/docs/html/guide/topics/text/spell-checker-framework.jd similarity index 81% rename from docs/html/resources/articles/spell-checker-framework.jd rename to docs/html/guide/topics/text/spell-checker-framework.jd index 8d57b4eb09cdb8fada3fd32f918ba904375fafc6..05b68907bdf5c574ca57d4d145cd3753f7c0497b 100644 --- a/docs/html/resources/articles/spell-checker-framework.jd +++ b/docs/html/guide/topics/text/spell-checker-framework.jd @@ -1,4 +1,4 @@ -page.title=Using the Spell Checker Framework +page.title=Spelling Checker Framework parent.title=Articles parent.link=../browser.html?tag=article @jd:body @@ -31,37 +31,37 @@ parent.link=../browser.html?tag=article

    - The Android platform offers a spell checker framework that lets you implement + 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 - generates a spell checker session object. Based on text you provide, - the session object returns spelling suggestions generated by the spell checker. + generates a spelling checker session object. Based on text you provide, + the session object returns spelling suggestions generated by the spelling checker.

    Spell Checker Lifecycle

    - The following diagram shows the lifecycle of the spell checker service: + The following diagram shows the lifecycle of the spelling checker service:

    - Figure 1. The spell checker service lifecycle. + Figure 1. The spelling checker service lifecycle.

    - To initiate spell checking, your app starts its implementation of the spell checker + To initiate spell checking, your app starts its implementation of the spelling checker service. Clients in your app, such as activities or individual UI elements, request a - spell checker session from the service, then use the session to get suggestions for text. - As a client terminates its operation, it closes its spell checker session. If necessary, your - app can shut down the spell checker service at any time. + spelling checker session from the service, then use the session to get suggestions for text. + As a client terminates its operation, it closes its spelling checker session. If necessary, your + app can shut down the spelling checker service at any time.

    Implementing a Spell Checker Service

    - To use the spell checker framework in your app, add a spell checker service component including + To use the spelling checker framework in your app, add a spelling checker service component including the session object definition. You can also add to your app an optional activity that controls settings. You must also add an XML metadata file that describes - the spell checker service, and add the appropriate elements to your manifest file. + the spelling checker service, and add the appropriate elements to your manifest file.

    Spell checker classes

    @@ -73,7 +73,7 @@ parent.link=../browser.html?tag=article

    The {@link android.service.textservice.SpellCheckerService} implements both the - {@link android.app.Service} class and the spell checker framework interface. Within your + {@link android.app.Service} class and the spelling checker framework interface. Within your subclass, you must implement the following method:
    {@link android.service.textservice.SpellCheckerService#createSession()}
    @@ -93,8 +93,8 @@ parent.link=../browser.html?tag=article An implementation of {@link android.service.textservice.SpellCheckerService.Session}
    - An object that the spell checker service provides to clients, to let them pass text to - the spell checker and receive suggestions. Within this class, you must implement the + An object that the spelling checker service provides to clients, to let them pass text to + the spelling checker and receive suggestions. Within this class, you must implement the following methods:
    @@ -132,7 +132,7 @@ onGetSuggestionsMultiple()}, which handles batches of suggestion requests, or bo

    Note: You must implement all aspects of spell checking as asynchronous and - thread-safe. A spell checker may be called simultaneously by different threads running on + thread-safe. A spelling checker may be called simultaneously by different threads running on different cores. The {@link android.service.textservice.SpellCheckerService} and {@link android.service.textservice.SpellCheckerService.Session} take care of this automatically. @@ -140,7 +140,7 @@ onGetSuggestionsMultiple()}, which handles batches of suggestion requests, or bo

    Spell checker manifest and metadata

    In addition to code, you need to provide the appropriate manifest file and a metadata file for - the spell checker. + the spelling checker.

    The manifest file defines the application, the service, and the activity for controlling @@ -198,9 +198,9 @@ onGetSuggestionsMultiple()}, which handles batches of suggestion requests, or bo </spell-checker>

    - The metadata specifies the activity that the spell checker uses for controlling settings. It - also defines subtypes for the spell checker; in this case, the subtypes define locales that - the spell checker can handle. + The metadata specifies the activity that the spelling checker uses for controlling settings. It + also defines subtypes for the spelling checker; in this case, the subtypes define locales that + the spelling checker can handle.

    @@ -208,7 +208,7 @@ onGetSuggestionsMultiple()}, which handles batches of suggestion requests, or bo

    Accessing the Spell Checker Service from a Client

    Applications that use {@link android.widget.TextView} views automatically benefit from spell - checking, because {@link android.widget.TextView} automatically uses a spell checker. The + checking, because {@link android.widget.TextView} automatically uses a spelling checker. The following screenshots show this:

    Figure 2.
    Spell checking in TextView.

    - However, you may want to interact directly with a spell checker service in other cases as well. - The following diagram shows the flow of control for interacting with a spell checker service: + However, you may want to interact directly with a spelling checker service in other cases as well. + The following diagram shows the flow of control for interacting with a spelling checker service:

    - Figure 3. Interacting with a spell checker service. + Figure 3. Interacting with a spelling checker service.

    The - Spell Checker Client sample app shows how to interact with a spell checker service. The + Spell Checker Client sample app shows how to interact with a spelling checker service. The LatinIME input method editor in the Android Open Source Project also contains an example of spell checking.

    \ No newline at end of file diff --git a/docs/html/guide/topics/ui/accessibility/apps.jd b/docs/html/guide/topics/ui/accessibility/apps.jd index dc916385b5de49079f98d14038b33b972194dfc8..d23512b3e1154d9022f7281c217d49b2448a8ed1 100644 --- a/docs/html/guide/topics/ui/accessibility/apps.jd +++ b/docs/html/guide/topics/ui/accessibility/apps.jd @@ -328,7 +328,7 @@ following approaches:

  • If your application targets Android 4.0 (API level 14) and higher, override and implement the accessibility methods listed above directly in your custom view class.
  • If your custom view is intended to be compatible with Android 1.6 (API Level 4) and above, add -the Android Support Library, revision 5 or +the Android Support Library, revision 5 or higher, to your project. Then, within your custom view class, call the {@link android.support.v4.view.ViewCompat#setAccessibilityDelegate ViewCompat.setAccessibilityDelegate()} method to implement the accessibility methods @@ -467,7 +467,7 @@ appropriate feedback to users.

    The example code below shows how override these three methods by using {@link android.support.v4.view.ViewCompat#setAccessibilityDelegate ViewCompat.setAccessibilityDelegate()}. Note that this sample code requires that the Android -Support Library for API Level 4 (revision 5 +Support Library for API Level 4 (revision 5 or higher) is added to your project.

    @@ -511,7 +511,7 @@ ViewCompat.setAccessibilityDelegate(new AccessibilityDelegateCompat() {
     
     

    On applications targeting Android 4.0 (API Level 14) and higher, these methods can be implemented directly in your custom view class. For another example of this approach, see the Android -Support Library (revision 5 or higher) sample +Support Library (revision 5 or higher) sample {@code AccessibilityDelegateSupportActivity} in ({@code <sdk>/extras/android/support/v4/samples/Support4Demos/}).

    @@ -567,7 +567,7 @@ option is not available.

    As part of your accessibility testing, you can test navigation of your application using focus, even if your test devices does not have a directional controller. The Android Emulator provides a +href="{@docRoot}tools/help/emulator.html">Android Emulator provides a simulated directional controller that you can easily use to test navigation. You can also use a software-based directional controller, such as the one provided by the diff --git a/docs/html/guide/topics/ui/accessibility/index.jd b/docs/html/guide/topics/ui/accessibility/index.jd index 414d5f3ec6e73922f19fbf86b0dfb2d9bccf09d2..6fd71e2c9ad7dd22ac8ba8d87410921c2bb22764 100644 --- a/docs/html/guide/topics/ui/accessibility/index.jd +++ b/docs/html/guide/topics/ui/accessibility/index.jd @@ -47,9 +47,9 @@ Accessible

    Development practices and API features to ensure your application is accessible to users with disabilities.
    -
    Building Accessibility +
    Building Accessibility Services
    How to use API features to build services that make other applications more accessible for users.
    -
  • \ No newline at end of file + diff --git a/docs/html/guide/topics/ui/accessibility/services.jd b/docs/html/guide/topics/ui/accessibility/services.jd index 0dad4ec5c851a206192780e98b67f0557c08f332..0c1d065121286a46e806301e007324d62d092b58 100644 --- a/docs/html/guide/topics/ui/accessibility/services.jd +++ b/docs/html/guide/topics/ui/accessibility/services.jd @@ -50,7 +50,7 @@ accessibility service.

    Support Library was also updated with the release of Android 4.0 to provide support for these enhanced accessibility features back to Android 1.6. Developers aiming for widely compatible accessibility services are encouraged to use the -Support Library and develop for the more +Support Library and develop for the more advanced accessibility features introduced in Android 4.0.

    @@ -279,7 +279,7 @@ android.accessibilityservice.AccessibilityService} and can be used as a base for accessibility services that are compatible with Android 1.6 (API Level 4) and higher.
  • TaskBackService - This service is based on the enhanced accessibility APIs introduced in Android 4.0 (API Level -14). However, you can use the Android Support +14). However, you can use the Android Support Libary to substitute classes introduced in later API levels (e.g., {@link android.view.accessibility.AccessibilityRecord}, {@link android.view.accessibility.AccessibilityNodeInfo} diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd index bf7369adb21f4ae216db1c08a60b3ba5230d6da8..4842000fe238996955e765dd6abcb0d1afe1f72c 100644 --- a/docs/html/guide/topics/ui/actionbar.jd +++ b/docs/html/guide/topics/ui/actionbar.jd @@ -6,13 +6,6 @@ parent.link=index.html
    -

    Quickview

    -
      -
    • A title bar that includes the application icon and activity title
    • -
    • Provides access to menu items and navigation modes such as tabs
    • -
    • Requires API level 11 or greater
    • -
    -

    In this document

    1. Adding the Action Bar @@ -102,7 +95,7 @@ navigation label, such as the currently selected tab.

    2. Provide consistent navigation and view refinement across different applications.

      The action bar provides built-in tab navigation for switching between fragments. It also offers a drop-down +href="{@docRoot}guide/components/fragments.html">fragments. It also offers a drop-down list you can use as an alternative navigation mode or to refine the current view (such as to sort a list by different criteria).

    3. @@ -120,7 +113,7 @@ include a Menu button).

      - +

      Figure 1. Action bar from the Honeycomb Gallery app (on a landscape handset), showing the logo on the left, navigation tabs, and an action item on the @@ -510,7 +503,7 @@ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

      For more information about these flags and other back stack behaviors, read the Tasks and Back Stack +href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back Stack developer guide.

      Note: If you're using the icon to navigate to the home @@ -955,7 +948,7 @@ when the screen is too narrow, as shown in figures 9 and 10.

      To switch between fragments using the tabs, you must perform a fragment transaction each time a tab is selected. If you're not familiar with how to change fragments using {@link android.app.FragmentTransaction}, first read the Fragments developer guide.

      +href="{@docRoot}guide/components/fragments.html">Fragments developer guide.

      To get started, your layout must include a {@link android.view.ViewGroup} in which you place each {@link android.app.Fragment} associated with a tab. Be sure the {@link android.view.ViewGroup} has a @@ -1092,7 +1085,7 @@ href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/Frag

      If your activity stops, you should retain the currently selected tab with the saved instance +href="{@docRoot}guide/components/activities.html#SavingActivityState">saved instance state so you can open the appropriate tab when the user returns. When it's time to save the state, you can query the currently selected tab with {@link android.app.ActionBar#getSelectedNavigationIndex()}. This returns the index position of the selected @@ -1101,7 +1094,7 @@ tab.

      Caution: It's important that you save the state of each fragment as necessary, so that when users switch fragments with the tabs and then return to a previous fragment, it looks the way it did when they left. For information about saving the state of your -fragment, see the Fragments +fragment, see the Fragments developer guide.

      diff --git a/docs/html/guide/topics/ui/binding.jd b/docs/html/guide/topics/ui/binding.jd index 26364ee8e4c9427a0fe771b182492b542a58ed1c..e8b49d553ebcea494db9ccc93d0ff8306838d7fc 100644 --- a/docs/html/guide/topics/ui/binding.jd +++ b/docs/html/guide/topics/ui/binding.jd @@ -1,4 +1,4 @@ -page.title=Binding to Data with AdapterView +page.title=AdapterView parent.title=User Interface parent.link=index.html @jd:body @@ -20,32 +20,7 @@ parent.link=index.html
    -

    The {@link android.widget.AdapterView} is a ViewGroup subclass whose child Views are determined by an {@link android.widget.Adapter Adapter} that -binds to data of some type. AdapterView is useful whenever you need to display stored data (as opposed to resource strings or drawables) in your layout.

    -

    {@link android.widget.Gallery Gallery}, {@link android.widget.ListView ListView}, and {@link android.widget.Spinner Spinner} are examples of AdapterView subclasses that you can use to bind to a specific type of data and display it in a certain way.

    - - -

    AdapterView objects have two main responsibilities:

    -
      -
    • Filling the layout with data -
    • -
    • Handling user selections -
    • -
    - - -

    Filling the Layout with Data

    -

    Inserting data into the layout is typically done by binding the AdapterView class to an {@link -android.widget.Adapter}, which retrieves data from an external source (perhaps a list that -the code supplies or query results from the device's database).

    -

    The following code sample does the following:

    -
      -
    1. Creates a {@link android.widget.Spinner Spinner} with an existing View and binds it to a new ArrayAdapter -that reads an array of colors from the local resources.
    2. -
    3. Creates another Spinner object from a View and binds it to a new SimpleCursorAdapter that will read -people's names from the device contacts (see {@link android.provider.Contacts.People}).
    4. -
     // Get a Spinner and bind it to an ArrayAdapter that 
    diff --git a/docs/html/guide/topics/ui/controls.jd b/docs/html/guide/topics/ui/controls.jd
    new file mode 100644
    index 0000000000000000000000000000000000000000..83bb0c8e64faff739a22555fffbf1eec68dbe924
    --- /dev/null
    +++ b/docs/html/guide/topics/ui/controls.jd
    @@ -0,0 +1,92 @@
    +page.title=Input Controls
    +parent.title=User Interface
    +parent.link=index.html
    +@jd:body
    +
    +
    + +
    + +

    Input controls are the interactive components in your app's user interface. Android provides a +wide variety of controls you can use in your UI, such as buttons, text fields, seek bars, +checkboxes, zoom buttons, toggle buttons, and many more.

    + +

    Adding an input control to your UI is as simple as adding an XML element to your XML layout. For example, here's a +layout with a text field and button:

    + +
    +<?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:orientation="horizontal">
    +    <EditText android:id="@+id/edit_message"
    +        android:layout_weight="1"
    +        android:layout_width="0dp"
    +        android:layout_height="wrap_content"
    +        android:hint="@string/edit_message" />
    +    <Button android:id="@+id/button_send"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:text="@string/button_send"
    +        android:onClick="sendMessage" />
    +</LinearLayout>
    +
    + +

    Each input control supports a specific set of input events so you can handle events such as when +the user enters text or touches a button.

    + + +

    Common Controls

    +

    Here's a list of some common controls that you can use in your app. Follow the links to learn +more about using each one.

    + +

    Note: Android provides several more controls than are listed +here. Browse the {@link android.widget} package to discover more. If your app requires a +specific kind of input control, you can build your own custom components.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Control TypeDescriptionRelated Classes
    ButtonA push-button that can be pressed, or clicked, by the user to perform an action.{@link android.widget.Button Button}
    Text fieldAn editable text field. You can use the AutoCompleteTextView widget to create a text entry widget that provides auto-complete suggestions{@link android.widget.EditText EditText}, {@link android.widget.AutoCompleteTextView}
    CheckboxAn on/off switch that can be toggled by the user. You should use checkboxes when presenting users with a group of selectable options that are not mutually exclusive.{@link android.widget.CheckBox CheckBox}
    Radio buttonSimilar to checkboxes, except that only one option can be selected in the group.{@link android.widget.RadioGroup RadioGroup} +
    {@link android.widget.RadioButton RadioButton}
    Toggle buttonAn on/off button with a light indicator.{@link android.widget.ToggleButton ToggleButton}
    SpinnerA drop-down list that allows users to select one value from a set.{@link android.widget.Spinner Spinner}
    PickersA dialog for users to select a single value for a set by using up/down buttons or via a swipe gesture. Use a DatePickercode> widget to enter the values for the date (month, day, year) or a TimePicker widget to enter the values for a time (hour, minute, AM/PM), which will be formatted automatically for the user's locale.{@link android.widget.DatePicker}, {@link android.widget.TimePicker}
    diff --git a/docs/html/guide/topics/ui/controls/button.jd b/docs/html/guide/topics/ui/controls/button.jd new file mode 100644 index 0000000000000000000000000000000000000000..8d48e9cb5dac0bd0331cccdb8c15cf85dcddb25d --- /dev/null +++ b/docs/html/guide/topics/ui/controls/button.jd @@ -0,0 +1,245 @@ +page.title=Buttons +parent.title=Input Controls +parent.link=../controls.html +@jd:body + +
    +
    +

    In this document

    +
      +
    1. Responding to Click Events +
        +
      1. Using an OnClickListener
      2. +
      +
    2. +
    3. Styling Your Button +
        +
      1. Borderless button
      2. +
      3. Custom background
      4. +
      +
    4. +
    +

    Key classes

    +
      +
    1. {@link android.widget.Button}
    2. +
    3. {@link android.widget.ImageButton}
    4. +
    +
    +
    + + +

    A button consists of text or an icon (or both text and an icon) that communicates what action +occurs when the user touches it.

    + + + +

    Depending on whether you want a button with text, an icon, or both, you can create the +button in your layout in three ways:

    +
      +
    • With text, using the {@link android.widget.Button} class: +
      +<Button
      +    android:layout_width="wrap_content"
      +    android:layout_height="wrap_content"
      +    android:text="@string/button_text"
      +    ... />
      +
      +
    • +
    • With an icon, using the {@link android.widget.ImageButton} class: +
      +<ImageButton
      +    android:layout_width="wrap_content"
      +    android:layout_height="wrap_content"
      +    android:src="@drawable/button_icon"
      +    ... />
      +
      +
    • +
    • With text and an icon, using the {@link android.widget.Button} class with the {@code +android:drawableLeft} attribute: +
      +<Button
      +    android:layout_width="wrap_content"
      +    android:layout_height="wrap_content"
      +    android:text="@string/button_text"
      +    android:drawableLeft="@drawable/button_icon"
      +    ... />
      +
      +
    • +
    + +

    Responding to Click Events

    + +

    When the user clicks a button, the {@link android.widget.Button} object receives +an on-click event.

    + +

    To define the click event handler for a button, add the {@link +android.R.attr#onClick android:onClick} attribute to the {@code <Button>} element in your XML +layout. The value for this attribute must be the name of the method you want to call in response +to a click event. The {@link android.app.Activity} hosting the layout must then implement the +corresponding method.

    + +

    For example, here's a layout with a button using {@link +android.R.attr#onClick android:onClick}:

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<Button xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:id="@+id/button_send"
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
    +    android:text="@string/button_send"
    +    android:onClick="sendMessage" />
    +
    + +

    Within the {@link android.app.Activity} that hosts this layout, the following method handles +the click event:

    + +
    +/** Called when the user touches the button */
    +public void sendMessage(View view) {
    +    // Do something in response to button click
    +}
    +
    + +

    The method you declare in the {@link android.R.attr#onClick android:onClick} attribute must have +a signature exactly as shown above. Specifically, the method must:

    +
      +
    • Be public
    • +
    • Return void
    • +
    • Define a {@link android.view.View} as its only parameter (this will be the {@link +android.view.View} that was clicked)
    • +
    + + +

    Using an OnClickListener

    + +

    You can also declare the click event handler pragmatically rather than in an XML layout. This +might be necessary if you instantiate the {@link android.widget.Button} at runtime or you need to +declare the click behavior in a {@link android.app.Fragment} subclass.

    + +

    To declare the event handler programmatically, create an {@link +android.view.View.OnClickListener} object and assign it to the button by calling {@link +android.view.View#setOnClickListener}. For example:

    + +
    +Button button = (Button) findViewById(R.id.button_send);
    +button.setOnClickListener(new View.OnClickListener() {
    +    public void onClick(View v) {
    +        // Do something in response to button click
    +    }
    +});
    +
    + + +

    Styling Your Button

    + +

    The appearance of your button (background image and font) may vary from one device to +another, because devices by different manufacturers often have different default styles for +input controls.

    + +

    You can control exactly how your controls are styled using a theme that you apply to your +entire application. For instance, to ensure that all devices running Android 4.0 and higher use +the Holo theme in your app, declare {@code android:theme="@android:style/Theme.Holo"} in your +manifest's {@code <application>} element. Also read the blog post, Holo Everywhere +for information about using the Holo theme while supporting older devices.

    + +

    To customize individual buttons with a different background, specify the {@link +android.R.attr#background android:background} attribute with a drawable or color resource. +Alternatively, you can apply a style for the button, which works in a manner similar to +HTML styles to define multiple style properties such as the background, font, size, and others. +For more information about applying styles, see Styles and Themes.

    + + +

    Borderless button

    + +

    One design that can be useful is a "borderless" button. Borderless buttons resemble +basic buttons except that they have no borders or background but still change appearance during +different states, such as when clicked.

    + +

    To create a borderless button, apply the {@link android.R.attr#borderlessButtonStyle} +style to the button. For example:

    + +
    +<Button
    +    android:id="@+id/button_send"
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
    +    android:text="@string/button_send"
    +    android:onClick="sendMessage"
    +    style="?android:attr/borderlessButtonStyle" />
    +
    + + + +

    Custom background

    + +

    If you want to truly redefine the appearance of your button, you can specify a custom +background. Instead of supplying a simple bitmap or color, however, your background should be a +state list resource that changes appearance depending on the button's current state.

    + +

    You can define the state list in an XML file that defines three different images or colors to use +for the different button states.

    + +

    To create a state list drawable for your button background:

    + +
      +
    1. Create three bitmaps for the button background that represent the default, pressed, and +focused button states. +

      To ensure that your images fit buttons of various sizes, create the bitmaps as Nine-patch bitmaps.

      +
    2. +
    3. Place the bitmaps into the res/drawable/ directory of +your project. Be sure each bitmap is named properly to reflect the button state that they each +represent, such as {@code button_default.9.png}, {@code button_pressed.9.png}, and {@code +button_focused.9.png}.
    4. +
    5. Create a new XML file in the res/drawable/ directory (name it something like +button_custom.xml). Insert the following XML: +
      +<?xml version="1.0" encoding="utf-8"?>
      +<selector xmlns:android="http://schemas.android.com/apk/res/android">
      +    <item android:drawable="@drawable/button_pressed"
      +          android:state_pressed="true" />
      +    <item android:drawable="@drawable/button_focused"
      +          android:state_focused="true" />
      +    <item android:drawable="@drawable/button_default" />
      +</selector>
      +
      +

      This defines a single drawable resource, which will change its image based on the current +state of the button.

      +
        +
      • The first <item> defines the bitmap to use when the button is +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 +default state (it's neither pressed nor focused).
      • +
      +

      Note: The order of the <item> elements is +important. When this drawable is referenced, the <item> elements are traversed +in-order to determine which one is appropriate for the current button state. Because the default +bitmap is last, it is only applied when the conditions android:state_pressed and +android:state_focused have both evaluated as false.

      +

      This XML file now represents a single +drawable resource and when referenced by a {@link android.widget.Button} for its background, +the image displayed will change based on these three states.

      +
    6. +
    7. Then simply apply the drawable XML file as the button background: +
      +<Button
      +    android:id="@+id/button_send"
      +    android:layout_width="wrap_content"
      +    android:layout_height="wrap_content"
      +    android:text="@string/button_send"
      +    android:onClick="sendMessage"
      +    android:background="@drawable/button_custom"  />
      +
      +
    + +

    For more information about this XML syntax, including how to define a disabled, hovered, or +other button states, read about State List +Drawable.

    \ No newline at end of file diff --git a/docs/html/guide/topics/ui/controls/checkbox.jd b/docs/html/guide/topics/ui/controls/checkbox.jd new file mode 100644 index 0000000000000000000000000000000000000000..35b8f560b15c577a32bcbc81b7ea0dfb42c172b1 --- /dev/null +++ b/docs/html/guide/topics/ui/controls/checkbox.jd @@ -0,0 +1,101 @@ +page.title=Checkboxes +parent.title=Input Controls +parent.link=../controls.html +@jd:body + +
    +
    +

    In this document

    +
      +
    1. Responding to Click Events
    2. +
    + +

    Key classes

    +
      +
    1. {@link android.widget.CheckBox}
    2. +
    +
    +
    + +

    Checkboxes allow the user to select one or more options from a set. Typically, you should +present each checkbox option in a vertical list.

    + + + +

    To create each checkbox option, create a {@link android.widget.CheckBox} in your layout. Because +a set of checkbox options allows the user to select multiple items, each checkbox is managed +separately and you must register a click listener for each one.

    + +

    Responding to Click Events

    + +

    When the user selects a checkbox, the {@link android.widget.CheckBox} object receives an +on-click event.

    + +

    To define the click event handler for a checkbox, add the android:onClick attribute to the +<CheckBox> element in your XML +layout. The value for this attribute must be the name of the method you want to call in response +to a click event. The {@link android.app.Activity} hosting the layout must then implement the +corresponding method.

    + +

    For example, here are a couple {@link android.widget.CheckBox} objects in a list:

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:orientation="vertical"
    +    android:layout_width="fill_parent"
    +    android:layout_height="fill_parent">
    +    <CheckBox android:id="@+id/checkbox_meat"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:text="@string/meat"
    +        android:onClick="onCheckboxClicked"/>
    +    <CheckBox android:id="@+id/checkbox_cheese"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:text="@string/cheese"
    +        android:onClick="onCheckboxClicked"/>
    +</LinearLayout>
    +
    + +

    Within the {@link android.app.Activity} that hosts this layout, the following method handles the +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:
    +            if (checked)
    +                // Put some meat on the sandwich
    +            else
    +                // Remove the meat
    +            break;
    +        case R.id.checkbox_cheese:
    +            if (checked)
    +                // Cheese me
    +            else
    +                // I'm lactose intolerant
    +            break;
    +        // TODO: Veggie sandwich
    +    }
    +}
    +
    + +

    The method you declare in the {@link android.R.attr#onClick android:onClick} attribute +must have a signature exactly as shown above. Specifically, the method must:

    +
      +
    • Be public
    • +
    • Return void
    • +
    • Define a {@link android.view.View} as its only parameter (this will be the {@link +android.view.View} that was clicked)
    • +
    + +

    Tip: If you need to change the radio button state +yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), +use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link +android.widget.CompoundButton#toggle()} method.

    \ No newline at end of file diff --git a/docs/html/guide/topics/ui/controls/pickers.jd b/docs/html/guide/topics/ui/controls/pickers.jd new file mode 100644 index 0000000000000000000000000000000000000000..cf90f1d6d4820b14c48664a18c52800cecaf8188 --- /dev/null +++ b/docs/html/guide/topics/ui/controls/pickers.jd @@ -0,0 +1,259 @@ +page.title= Pickers +parent.title=Form Controls +parent.link=controls-form.html +@jd:body + +
    +
    +

    In this document

    +
      +
    1. Creating a Time Picker +
        +
      1. Extending DialogFragment for a time picker
      2. +
      3. Showing the time picker
      4. +
      +
    2. +
    3. Creating a Date Picker +
        +
      1. Extending DialogFragment for a date picker
      2. +
      3. Showing the date picker
      4. +
      +
    4. +
    +

    Key classes

    +
      +
    1. {@link android.app.DatePickerDialog}
    2. +
    3. {@link android.app.TimePickerDialog}
    4. +
    5. {@link android.support.v4.app.DialogFragment}
    6. +
    +

    See also

    +
      +
    1. Fragments
    2. +
    +
    +
    + +

    Android provides controls for the user to pick a time or pick a date as ready-to-use dialogs. +Each picker provides controls for selecting each part of the time (hour, minute, AM/PM) or date +(month, day, year). Using these pickers helps ensure that your users can pick a time or date that +is valid, formatted correctly, and adjusted to the user's locale.

    + + + +

    We recommend that you use {@link android.support.v4.app.DialogFragment} to host each time or date +picker. The {@link android.support.v4.app.DialogFragment} manages the dialog lifecycle for you and +allows you to display the pickers in different layout configurations, +such as in a basic dialog on handsets or as an embedded part of the layout on large screens.

    + +

    Although {@link android.app.DialogFragment} was first added to the platform in Android 3.0 (API +level 11), if your app supports versions of Android older than 3.0—even as low as Android +1.6—you can use the {@link android.support.v4.app.DialogFragment} class that's available in +the support library for backward +compatibility.

    + +

    Note: The code samples below show how to create dialogs for a time +picker and date picker using the support +library APIs for {@link android.support.v4.app.DialogFragment}. If your app's {@code minSdkVersion} is 11 or +higher, you can instead use the platform version of {@link android.app.DialogFragment}.

    + + + +

    Creating a Time Picker

    + +

    To display a {@link android.app.TimePickerDialog} using {@link +android.support.v4.app.DialogFragment}, you need to define a fragment class that extends {@link +android.support.v4.app.DialogFragment} and return a {@link android.app.TimePickerDialog} from the +fragment's {@link android.support.v4.app.DialogFragment#onCreateDialog onCreateDialog()} method.

    + +

    Note: If your app supports versions of Android older than 3.0, +be sure you've set up your Android project with the support library as described in Setting Up a Project to Use a +Library.

    + +

    Extending DialogFragment for a time picker

    + +

    To define a {@link +android.support.v4.app.DialogFragment} for a {@link android.app.TimePickerDialog}, you +must:

    +
      +
    • Define the {@link android.support.v4.app.DialogFragment#onCreateDialog onCreateDialog()} +method to return an instance of {@link android.app.TimePickerDialog}
    • +
    • Implement the +{@link android.app.TimePickerDialog.OnTimeSetListener} interface to receive a callback when the user +sets the time.
    • +
    + +

    Here's an example:

    + +
    +public static class TimePickerFragment extends DialogFragment
    +                            implements TimePickerDialog.OnTimeSetListener {
    +
    +    @Override
    +    public Dialog onCreateDialog(Bundle savedInstanceState) {
    +        // Use the current time as the default values for the picker
    +        final Calendar c = Calendar.getInstance();
    +        int hour = c.get(Calendar.HOUR_OF_DAY);
    +        int minute = c.get(Calendar.MINUTE);
    +
    +        // Create a new instance of TimePickerDialog and return it
    +        return new TimePickerDialog(getActivity(), this, hour, minute,
    +                DateFormat.is24HourFormat(getActivity()));
    +    }
    +
    +    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
    +        // Do something with the time chosen by the user
    +    }
    +}
    +
    + +

    See the {@link android.app.TimePickerDialog} class for information about the constructor +arguments.

    + +

    Now all you need is an event that adds an instance of this fragment to your activity.

    + + +

    Showing the time picker

    + +

    Once you've defined a {@link android.support.v4.app.DialogFragment} like the one shown above, +you can display the time picker by creating an instance of the {@link +android.support.v4.app.DialogFragment} and calling {@link +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" 
    +    android:layout_height="wrap_content"
    +    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();
    +    newFragment.show(getSupportFragmentManager(), "timePicker");
    +}
    +
    + +

    This method calls {@link +android.support.v4.app.DialogFragment#show show()} on a new instance of the {@link +android.support.v4.app.DialogFragment} defined above. The {@link +android.support.v4.app.DialogFragment#show show()} method requires an instance of {@link +android.support.v4.app.FragmentManager} and a unique tag name for the fragment.

    + +

    Caution: If your app supports versions of Android lower than +3.0, be sure that you call {@link +android.support.v4.app.FragmentActivity#getSupportFragmentManager()} to acquire an instance of +{@link android.support.v4.app.FragmentManager}. Also make sure that your activity that displays the +time picker extends {@link android.support.v4.app.FragmentActivity} instead of the standard {@link +android.app.Activity} class.

    + + + + + + + + + +

    Creating a Date Picker

    + +

    Creating a {@link android.app.DatePickerDialog} is just like creating a {@link +android.app.TimePickerDialog}. The only difference is the dialog you create for the fragment.

    + +

    To display a {@link android.app.DatePickerDialog} using {@link +android.support.v4.app.DialogFragment}, you need to define a fragment class that extends {@link +android.support.v4.app.DialogFragment} and return a {@link android.app.DatePickerDialog} from the +fragment's {@link android.support.v4.app.DialogFragment#onCreateDialog onCreateDialog()} method.

    + +

    Note: If your app supports versions of Android older than 3.0, +be sure you've set up your Android project with the support library as described in Setting Up a Project to Use a +Library.

    + +

    Extending DialogFragment for a date picker

    + +

    To define a {@link +android.support.v4.app.DialogFragment} for a {@link android.app.DatePickerDialog}, you +must:

    +
      +
    • Define the {@link android.support.v4.app.DialogFragment#onCreateDialog onCreateDialog()} +method to return an instance of {@link android.app.DatePickerDialog}
    • +
    • Implement the +{@link android.app.DatePickerDialog.OnDateSetListener} interface to receive a callback when the user +sets the date.
    • +
    + +

    Here's an example:

    + +
    +public static class DatePickerFragment extends DialogFragment
    +                            implements DatePickerDialog.OnDateSetListener {
    +
    +    @Override
    +    public Dialog onCreateDialog(Bundle savedInstanceState) {
    +        // Use the current date as the default date in the picker
    +        final Calendar c = Calendar.getInstance();
    +        int year = c.get(Calendar.YEAR);
    +        int month = c.get(Calendar.MONTH);
    +        int day = c.get(Calendar.DAY_OF_MONTH);
    +
    +        // Create a new instance of DatePickerDialog and return it
    +        return new DatePickerDialog(getActivity(), this, year, month, day);
    +    }
    +
    +    public void onDateSet(DatePicker view, int year, int month, int day) {
    +        // Do something with the date chosen by the user
    +    }
    +}
    +
    + +

    See the {@link android.app.DatePickerDialog} class for information about the constructor +arguments.

    + +

    Now all you need is an event that adds an instance of this fragment to your activity.

    + + +

    Showing the date picker

    + +

    Once you've defined a {@link android.support.v4.app.DialogFragment} like the one shown above, +you can display the date picker by creating an instance of the {@link +android.support.v4.app.DialogFragment} and calling {@link +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" 
    +    android:layout_height="wrap_content"
    +    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();
    +    newFragment.show(getSupportFragmentManager(), "datePicker");
    +}
    +
    + +

    This method calls {@link +android.support.v4.app.DialogFragment#show show()} on a new instance of the {@link +android.support.v4.app.DialogFragment} defined above. The {@link +android.support.v4.app.DialogFragment#show show()} method requires an instance of {@link +android.support.v4.app.FragmentManager} and a unique tag name for the fragment.

    + +

    Caution: If your app supports versions of Android lower than +3.0, be sure that you call {@link +android.support.v4.app.FragmentActivity#getSupportFragmentManager()} to acquire an instance of +{@link android.support.v4.app.FragmentManager}. Also make sure that your activity that displays the +time picker extends {@link android.support.v4.app.FragmentActivity} instead of the standard {@link +android.app.Activity} class.

    diff --git a/docs/html/guide/topics/ui/controls/radiobutton.jd b/docs/html/guide/topics/ui/controls/radiobutton.jd new file mode 100644 index 0000000000000000000000000000000000000000..f6f6d49f72946365c7f9383c2b82968f9b1cfb1b --- /dev/null +++ b/docs/html/guide/topics/ui/controls/radiobutton.jd @@ -0,0 +1,103 @@ +page.title=Radio Buttons +parent.title=Input Controls +parent.link=../controls.html +@jd:body + +
    +
    +

    In this document

    +
      +
    1. Responding to Click Events
    2. +
    + +

    Key classes

    +
      +
    1. {@link android.widget.RadioButton}
    2. +
    3. {@link android.widget.RadioGroup}
    4. +
    +
    +
    + +

    Radio buttons allow the user to select one option from a set. You should use radio buttons for +optional sets that are mutually exclusive if you think that the user needs to see all available +options side-by-side. If it's not necessary to show all options side-by-side, use a spinner instead.

    + + + +

    To create each radio button option, create a {@link android.widget.RadioButton} in your layout. +However, because radio buttons are mutually exclusive, you must group them together inside a +{@link android.widget.RadioGroup}. By grouping them together, the system ensures that only one +radio button can be selected at a time.

    + +

    Responding to Click Events

    + +

    When the user selects one of the radio buttons, the corresponding {@link +android.widget.RadioButton} object receives an on-click event.

    + +

    To define the click event handler for a button, add the android:onClick attribute to the +<RadioButton> element in your XML +layout. The value for this attribute must be the name of the method you want to call in response +to a click event. The {@link android.app.Activity} hosting the layout must then implement the +corresponding method.

    + +

    For example, here are a couple {@link android.widget.RadioButton} objects:

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:layout_width="fill_parent"
    +    android:layout_height="wrap_content"
    +    android:orientation="vertical">
    +    <RadioButton android:id="@+id/radio_pirates"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:text="@string/pirates"
    +        android:onClick="onRadioButtonClicked"/>
    +    <RadioButton android:id="@+id/radio_ninjas"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:text="@string/ninjas"
    +        android:onClick="onRadioButtonClicked"/>
    +</RadioGroup>
    +
    + +

    Note: The {@link android.widget.RadioGroup} is a subclass of +{@link android.widget.LinearLayout} that has a vertical orientation by default.

    + +

    Within the {@link android.app.Activity} that hosts this layout, the following method handles the +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:
    +            if (checked)
    +                // Pirates are the best
    +            break;
    +        case R.id.radio_ninjas:
    +            if (checked)
    +                // Ninjas rule
    +            break;
    +    }
    +}
    +
    + +

    The method you declare in the {@link android.R.attr#onClick android:onClick} attribute +must have a signature exactly as shown above. Specifically, the method must:

    +
      +
    • Be public
    • +
    • Return void
    • +
    • Define a {@link android.view.View} as its only parameter (this will be the {@link +android.view.View} that was clicked)
    • +
    + +

    Tip: If you need to change the radio button state +yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), +use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link +android.widget.CompoundButton#toggle()} method.

    diff --git a/docs/html/guide/topics/ui/controls/spinner.jd b/docs/html/guide/topics/ui/controls/spinner.jd new file mode 100644 index 0000000000000000000000000000000000000000..deba3e609469863ae04956bcfcba58046b165804 --- /dev/null +++ b/docs/html/guide/topics/ui/controls/spinner.jd @@ -0,0 +1,147 @@ +page.title= Spinners +parent.title=Input Controls +parent.link=../controls.html +@jd:body + +
    +
    + +

    In this document

    +
      +
    1. Populate the Spinner with User Choices
    2. +
    3. Responding to User Selections
    4. +
    +

    Key classes

    +
      +
    1. {@link android.widget.Spinner}
    2. +
    3. {@link android.widget.SpinnerAdapter}
    4. +
    5. {@link android.widget.AdapterView.OnItemSelectedListener}
    6. +
    + +
    +
    + +

    Spinners provide a quick way to select one value from a set. In the default state, a spinner +shows its currently selected value. Touching the spinner displays a dropdown menu with all other +available values, from which the user can select a new one.

    + + + +

    You can add a spinner to your layout with the {@link android.widget.Spinner} object. You +should usually do so in your XML layout with a {@code <Spinner>} element. For example:

    + +
    +<Spinner
    +    android:id="@+id/planets_spinner"
    +    android:layout_width="fill_parent"
    +    android:layout_height="wrap_content" />
    +
    + +

    To populate the spinner with a list of choices, you then need to specify a {@link +android.widget.SpinnerAdapter} in your {@link android.app.Activity} or {@link android.app.Fragment} +source code.

    + +

    Populate the Spinner with User Choices

    + +

    The choices you provide for the spinner can come from any source, but must be provided through +an {@link android.widget.SpinnerAdapter}, such as an {@link android.widget.ArrayAdapter} if the +choices are available in an array or a {@link android.widget.CursorAdapter} if the choices are +available from a database query.

    + +

    For instance, if the available choices for your spinner are pre-determined, you can provide +them with a string array defined in a string +resource file:

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<resources>
    +    <string-array name="planets_array">
    +        <item>Mercury</item>
    +        <item>Venus</item>
    +        <item>Earth</item>
    +        <item>Mars</item>
    +        <item>Jupiter</item>
    +        <item>Saturn</item>
    +        <item>Uranus</item>
    +        <item>Neptune</item>
    +    </string-array>
    +</resources>
    +
    + +

    With an array such as this one, you can use the following code in your {@link +android.app.Activity} or {@link android.app.Fragment} to supply the spinner with the array using +an instance of {@link android.widget.ArrayAdapter}: + +

    +Spinner spinner = (Spinner) findViewById(R.id.spinner);
    +// Create an ArrayAdapter using the string array and a default spinner layout
    +ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
    +        R.array.planets_array, android.R.layout.simple_spinner_item);
    +// Specify the layout to use when the list of choices appears
    +adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    +// Apply the adapter to the spinner
    +spinner.setAdapter(adapter);
    +
    + +

    The {@link +android.widget.ArrayAdapter#createFromResource(Context,int,int) createFromResource()} method allows +you to create an {@link android.widget.ArrayAdapter} from the string array. The third argument for +this method is a layout resource that defines how the selected choice appears in the +spinner control. The {@link android.R.layout#simple_spinner_item} layout is provided by the +platform and is the default layout you should use unless you'd like to define your own layout +for the spinner's appearance.

    + +

    You should then call {@link android.widget.ArrayAdapter#setDropDownViewResource(int)} to specify +the layout the adapter should use to display the list of spinner choices ({@link +android.R.layout#simple_spinner_dropdown_item} is another standard layout defined by the +platform).

    + +

    Call {@link android.widget.AdapterView#setAdapter setAdapter()} to apply the adapter to your +{@link android.widget.Spinner}.

    + + +

    Responding to User Selections

    + +

    When the user selects an item from the drop-down, the {@link android.widget.Spinner} object +receives an on-item-selected event.

    + +

    To define the selection event handler for a spinner, implement the {@link +android.widget.AdapterView.OnItemSelectedListener} interface and the corresponding {@link +android.widget.AdapterView.OnItemSelectedListener#onItemSelected onItemSelected()} callback method. +For example, here's an implementation of the interface in an {@link android.app.Activity}:

    + +
    +public class SpinnerActivity extends Activity implements OnItemSelectedListener {
    +    ...
    +    
    +    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)
    +    }
    +
    +    public void onNothingSelected(AdapterView<?> parent) {
    +        // Another interface callback
    +    }
    +}
    +
    + +

    The {@link android.widget.AdapterView.OnItemSelectedListener} requires the {@link +android.widget.AdapterView.OnItemSelectedListener#onItemSelected(AdapterView,View,int,long) +onItemSelected()} and {@link +android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(AdapterView) +onNothingSelected()} callback methods.

    + +

    Then you need to specify the interface implementation by calling {@link +android.widget.AdapterView#setOnItemSelectedListener setOnItemSelectedListener()}:

    + +
    +Spinner spinner = (Spinner) findViewById(R.id.spinner);
    +spinner.setOnItemSelectedListener(this);
    +
    + +

    If you implement the {@link +android.widget.AdapterView.OnItemSelectedListener} interface with your {@link +android.app.Activity} or {@link android.app.Fragment} (such as in the example above), you can pass +this as the interface instance.

    \ No newline at end of file diff --git a/docs/html/guide/topics/ui/controls/text.jd b/docs/html/guide/topics/ui/controls/text.jd new file mode 100644 index 0000000000000000000000000000000000000000..2d9d2158f1addac7075ad4e9d5c04cec706f9036 --- /dev/null +++ b/docs/html/guide/topics/ui/controls/text.jd @@ -0,0 +1,306 @@ +page.title=Text Fields +parent.title=Input Controls +parent.link=../controls.html +@jd:body + +
    +
    + +

    In this document

    +
      +
    1. Specifying the Keyboard Type +
        +
      1. Controlling other behaviors
      2. +
      +
    2. +
    3. Specifying Keyboard Actions +
        +
      1. Responding to action button events
      2. +
      3. Setting a custom action button label
      4. +
      +
    4. +
    5. Adding Other Keyboard Flags
    6. +
    7. Providing Auto-complete Suggestions
    8. +
    +

    Key classes

    +
      +
    1. {@link android.widget.EditText}
    2. +
    3. {@link android.widget.AutoCompleteTextView}
    4. +
    + +
    +
    + +

    A text field allows the user to type text into your app. It can be either single line or +multi-line. Touching a text field places the cursor and automatically displays the keyboard. In +addition to typing, text fields allow for a variety of other activities, such as text selection +(cut, copy, paste) and data look-up via auto-completion.

    + +

    You can add a text field to you layout with the {@link android.widget.EditText} object. You +should usually do so in your XML layout with a {@code <EditText>} element.

    + + + + + +

    Specifying the Keyboard Type

    + +
    + +

    Figure 1. The default {@code text} input type.

    +
    + +
    + +

    Figure 2. The {@code textEmailAddress} input type.

    +
    + +
    + +

    Figure 3. The {@code phone} input type.

    +
    + +

    Text fields can have different input types, such as number, date, password, or email address. The +type determines what kind of characters are allowed inside the field, and may prompt the virtual +keyboard to optimize its layout for frequently used characters.

    + +

    You can specify the type of keyboard you want for your {@link android.widget.EditText} object +with the {@code +android:inputType} attribute. For example, if you want the user to input an email address, you +should use the {@code textEmailAddress} input type:

    + +
    +<EditText
    +    android:id="@+id/email_address"
    +    android:layout_width="fill_parent"
    +    android:layout_height="wrap_content"
    +    android:hint="@string/email_hint"
    +    android:inputType="textEmailAddress" />
    +
    + + +

    There are several different input types available for different situations. You can find +them all listed with the documentation for {@code +android:inputType}.

    + +

    Tip: To allow users to input long strings of text with line +breaks, use the {@code "textMultiLine"} input type. By default, an {@link android.widget.EditText} +object is restricted to one line of text and scrolls horizontally when the text exceeds the +available width.

    + + +

    Controlling other behaviors

    + +

    The {@code +android:inputType} also allows you to specify certain keyboard behaviors, such as whether to +capitalize all new words or use features like auto-complete and spelling suggestions.

    + +

    The {@code +android:inputType} attribute allows bitwise combinations so you can specify both a keyboard +layout and one or more behaviors at once. For example, here's how you can collect a postal +address, capitalize each word, and disable text suggestions:

    + +
    +<EditText
    +    android:id="@+id/postal_address"
    +    android:layout_width="fill_parent"
    +    android:layout_height="wrap_content"
    +    android:hint="@string/postal_address_hint"
    +    android:inputType="textPostalAddress|
    +                       textCapWords|
    +                       textNoSuggestions" />
    +
    + +

    All behaviors are also listed with the {@code +android:inputType} documentation.

    + + +

    Specifying Keyboard Actions

    + +
    + +

    Figure 4. If you declare {@code +android:imeOptions="actionSend"}, the keyboard includes the Send action.

    +
    + +

    In addition to changing the keyboard's input type, Android allows you to specify an action to be +made when users have completed their input. The action specifies the button that appears in place of +the carriage return key and the action to be made, such as "Search" or "Send."

    + +

    You can specify the action by setting the {@code +android:imeOptions} attribute. For example, here's how you can specify the Send action:

    + +
    +<EditText
    +    android:id="@+id/search"
    +    android:layout_width="fill_parent"
    +    android:layout_height="wrap_content"
    +    android:hint="@string/search_hint"
    +    android:inputType="text"
    +    android:imeOptions="actionSend" />
    +
    + +

    If you do not explicitly specify an input action then the system attempts to determine if there +are any subsequent {@code +android:focusable} fields. If any focusable fields are found following this one, the system +applies the (@code actionNext} action to the current {@link android.widget.EditText} so the user can +select Next to move to the next field. If there's no subsequent focusable field, the system applies +the {@code "actionDone"} action. You can override this by setting the {@code +android:imeOptions} attribute to any other value such as {@code "actionSend"} or {@code +"actionSearch"} or suppress the default behavior by using the {@code "actionNone"} action.

    + + +

    Responding to action button events

    + +

    If you have specified a keyboard action for the input method using {@code +android:imeOptions} attribute (such as {@code "actionSend"}), you can listen for the specific +action event using an {@link android.widget.TextView.OnEditorActionListener}. The {@link +android.widget.TextView.OnEditorActionListener} interface provides a callback method called {@link +android.widget.TextView.OnEditorActionListener#onEditorAction onEditorAction()} that indicates the +action type invoked with an action ID such as {@link +android.view.inputmethod.EditorInfo#IME_ACTION_SEND} or {@link +android.view.inputmethod.EditorInfo#IME_ACTION_SEARCH}.

    + +

    For example, here's how you can listen for when the user clicks the Send button on the +keyboard:

    + +
    +EditText editText = (EditText) findViewById(R.id.search);
    +editText.setOnEditorActionListener(new OnEditorActionListener() {
    +    @Override
    +    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    +        boolean handled = false;
    +        if (actionId == EditorInfo.IME_ACTION_SEND) {
    +            // Send the user message
    +            handled = true;
    +        }
    +        return handled;
    +    }
    +});
    +
    + + +

    Setting a custom action button label

    + +

    If the keyboard is too large to reasonably share space with the underlying application (such as +when a handset device is in landscape orientation) then fullscreen ("extract mode") is triggered. In +this mode, a labeled action button is displayed next to the input. You can customize the text of +this button by setting the {@code +android:imeActionLabel} attribute:

    + +
    +<EditText
    +    android:id="@+id/launch_codes"
    +    android:layout_width="fill_parent"
    +    android:layout_height="wrap_content"
    +    android:hint="@string/enter_launch_codes"
    +    android:inputType="number"
    +    android:imeActionLabel="@string/launch" />
    +
    + + +

    Figure 5. A custom action label with {@code +android:imeActionLabel}.

    + + + +

    Adding Other Keyboard Flags

    + +

    In addition to the actions you can specify with the {@code +android:imeOptions} attribute, you can add additional flags to specify other keyboard +behaviors. All available flags are listed along with the actions in the {@code +android:imeOptions} documentation.

    + +

    For example, figure 5 shows how the system enables a fullscreen text field when a handset device +is in landscape orientation (or the screen space is otherwise constrained for space). You can +disable the fullscreen input mode with {@code flagNoExtractUi} in the {@code +android:imeOptions} attribute, as shown in figure 6.

    + + +

    Figure 6. The fullscreen text field ("extract mode") is +disabled with {@code android:imeOptions="flagNoExtractUi"}.

    + + + + +

    Providing Auto-complete Suggestions

    + +

    If you want to provide suggestions to users as they type, you can use a subclass of {@link +android.widget.EditText} called {@link android.widget.AutoCompleteTextView}. To implement +auto-complete, you must specify an (@link android.widget.Adapter) that provides the text +suggestions. There are several kinds of adapters available, depending on where the data is coming +from, such as from a database or an array.

    + + +

    Figure 7. Example of {@link +android.widget.AutoCompleteTextView} with text suggestions.

    + +

    The following procedure describes how to set up an {@link android.widget.AutoCompleteTextView} +that provides suggestions from an array, using {@link android.widget.ArrayAdapter}: + +

      +
    1. Add the {@link android.widget.AutoCompleteTextView} to your layout. Here's a +layout with only the text field: +
      +<?xml version="1.0" encoding="utf-8"?>
      +<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" />
      +
      +
    2. + +
    3. Define the array that contains all text suggestions. For example, here's an array of country +names that's defined in an XML resource file ({@code res/values/strings.xml}): +
      +<?xml version="1.0" encoding="utf-8"?>
      +<resources>
      +    <string-array name="countries_array">
      +        <item>Afghanistan</item>
      +        <item>Albania</item>
      +        <item>Algeria</item>
      +        <item>American Samoa</item>
      +        <item>Andorra</item>
      +        <item>Angola</item>
      +        <item>Anguilla</item>
      +        <item>Antarctica</item>
      +        ...
      +    </string-array>
      +</resources>
      +
      +
    4. + +
    5. In your {@link android.app.Activity} or {@link android.app.Fragment}, use the following +code to specify the adapter that supplies the suggestions: +
      +// Get a reference to the AutoCompleteTextView in the layout
      +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 = 
      +        new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, countries);
      +textView.setAdapter(adapter);
      +
      + +

      Here, a new {@link +android.widget.ArrayAdapter} is initialized to bind each item in the COUNTRIES +string array to a {@link android.widget.TextView} that exists in the {@code simple_list_item_1} +layout (this is a layout provided by Android that provides a standard appearance for text in a +list).

      +

      Then assign the adapter to the {@link android.widget.AutoCompleteTextView} by +calling {@link android.widget.AutoCompleteTextView#setAdapter setAdapter()}.

      +
    6. +
    + diff --git a/docs/html/guide/topics/ui/controls/togglebutton.jd b/docs/html/guide/topics/ui/controls/togglebutton.jd new file mode 100644 index 0000000000000000000000000000000000000000..dd7634be3e60a50b693a710cc6e36c131fb16a13 --- /dev/null +++ b/docs/html/guide/topics/ui/controls/togglebutton.jd @@ -0,0 +1,124 @@ +page.title=Toggle Buttons +parent.title=Input Controls +parent.link=../controls.html +@jd:body + +
    +
    +

    In this document

    +
      +
    1. Responding to Click Events +
        +
      1. Using an OnCheckedChangeListener
      2. +
      +
    2. +
    +

    Key classes

    +
      +
    1. {@link android.widget.ToggleButton}
    2. +
    3. {@link android.widget.Switch}
    4. +
    +
    +
    + +

    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.

    + +
    + +

    Toggle buttons

    +
    + +
    + +

    Switches (in Android 4.0+)

    +
    + +

    The {@link android.widget.ToggleButton} and {@link android.widget.Switch} +controls are subclasses of {@link android.widget.CompoundButton} and function in the same manner, so +you can implement their behavior the same way.

    + +

    Responding to Click Events

    + +

    When the user selects a {@link android.widget.ToggleButton} and {@link android.widget.Switch}, +the object receives an on-click event.

    + +

    To define the click event handler, add the android:onClick attribute to the +<ToggleButton> or <Switch> element in your XML +layout. The value for this attribute must be the name of the method you want to call in response +to a click event. The {@link android.app.Activity} hosting the layout must then implement the +corresponding method.

    + +

    For example, here's a {@link android.widget.ToggleButton} with the android:onClick attribute:

    + +
    +<ToggleButton 
    +    android:id="@+id/togglebutton"
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
    +    android:textOn="Vibrate on"
    +    android:textOff="Vibrate off"
    +    android:onClick="onToggleClicked"/>
    +
    + +

    Within the {@link android.app.Activity} that hosts this layout, the following method handles the +click event:

    + +
    +public void onToggleClicked(View view) {
    +    // Is the toggle on?
    +    boolean on = ((ToggleButton) view).isChecked();
    +    
    +    if (on) {
    +        // Enable vibrate
    +    } else {
    +        // Disable vibrate
    +    }
    +}
    +
    + +

    The method you declare in the {@link android.R.attr#onClick android:onClick} attribute +must have a signature exactly as shown above. Specifically, the method must:

    +
      +
    • Be public
    • +
    • Return void
    • +
    • Define a {@link android.view.View} as its only parameter (this will be the {@link +android.view.View} that was clicked)
    • +
    + +

    Tip: If you need to change the state +yourself, +use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link +android.widget.CompoundButton#toggle()} method to change the state.

    + + + +

    Using an OnCheckedChangeListener

    + +

    You can also declare a click event handler pragmatically rather than in an XML layout. This +might be necessary if you instantiate the {@link android.widget.ToggleButton} or {@link +android.widget.Switch} at runtime or you need to +declare the click behavior in a {@link android.app.Fragment} subclass.

    + +

    To declare the event handler programmatically, create an {@link +android.widget.CompoundButton.OnCheckedChangeListener} object and assign it to the button by calling +{@link +android.widget.CompoundButton#setOnCheckedChangeListener}. For example:

    + +
    +ToggleButton toggle = (ToggleButton) findViewById(R.id.togglebutton);
    +toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    +    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    +        if (isChecked) {
    +            // The toggle is enabled
    +        } else {
    +            // The toggle is disabled
    +        }
    +    }
    +});
    +
    diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd index 8af4a1cd143e8aa4409029d8c48bd12b65fb4308..3c9faa8b2cee261e85c9f5bab6bd58479896be99 100644 --- a/docs/html/guide/topics/ui/declaring-layout.jd +++ b/docs/html/guide/topics/ui/declaring-layout.jd @@ -1,4 +1,4 @@ -page.title=XML Layouts +page.title=Layouts parent.title=User Interface parent.link=index.html @jd:body @@ -6,18 +6,25 @@ parent.link=index.html

    In this document

    -
      -
    1. Write the XML
    2. -
    3. Load the XML Resource
    4. -
    5. Attributes -
        -
      1. ID
      2. -
      3. Layout Parameters
      4. -
      -
    6. -
    7. Position
    8. -
    9. Size, Padding and Margins
    10. -
    +
      +
    1. Write the XML
    2. +
    3. Load the XML Resource
    4. +
    5. Attributes +
        +
      1. ID
      2. +
      3. Layout Parameters
      4. +
      +
    6. +
    7. Layout Position
    8. +
    9. Size, Padding and Margins
    10. +
    11. Common Layouts
    12. +
    13. Building Layouts with an Adapter +
        +
      1. Filling an adapter view with data
      2. +
      3. Handling click events
      4. +
      +
    14. +

    Key classes

      @@ -43,15 +50,15 @@ application can create View and ViewGroup objects (and manipulate their properti @@ -125,7 +132,7 @@ public void onCreate(Bundle savedInstanceState) {

      The onCreate() callback method in your Activity is called by the Android framework when your Activity is launched (see the discussion about lifecycles, in the -Activities +Activities document).

      @@ -300,5 +307,213 @@ Available Resources document.

      + + + + + + + + + +

      Common Layouts

      + +

      Each subclass of the {@link android.view.ViewGroup} class provides a unique way to display +the views you nest within it. Below are some of the more common layout types that are built +into the Android platform.

      + +

      Note: Although you can nest one or more layouts within another +layout to acheive your UI design, you should strive to keep your layout hierarchy as shallow as +possible. Your layout draws faster if it has fewer nested layouts (a wide view hierarchy is +better than a deep view hierarchy).

      + + + + +
      +

      Linear Layout

      + +

      A layout that organizes its children into a single horizontal or vertical row. It + creates a scrollbar if the length of the window exceeds the length of the screen.

      +
      + +
      +

      Relative Layout

      + +

      Enables you to specify the location of child objects relative to each other (child A to +the left of child B) or to the parent (aligned to the top of the parent).

      +
      + + + +
      +

      Web View

      + +

      Displays web pages.

      +
      + + + + +

      Building Layouts with an Adapter

      + +

      When the content for your layout is dynamic or not pre-determined, you can use a layout that +subclasses {@link android.widget.AdapterView} to populate the layout with views at runtime. A +subclass of the {@link android.widget.AdapterView} class uses an {@link android.widget.Adapter} to +bind data to its layout. The {@link android.widget.Adapter} behaves as a middle-man between the data +source and the {@link android.widget.AdapterView} layout—the {@link android.widget.Adapter} +retreives the data (from a source such as an array or a database query) and converts each entry +into a view that can be added into the {@link android.widget.AdapterView} layout.

      + +

      Common layouts backed by an adapter include:

      + +
      +

      List View

      + +

      Displays a scrolling single column list.

      +
      + +
      +

      Grid View

      + +

      Displays a scrolling grid of columns and rows.

      +
      + + + +

      Filling an adapter view with data

      + +

      You can populate an {@link android.widget.AdapterView} such as {@link android.widget.ListView} or +{@link android.widget.GridView} by binding the {@link android.widget.AdapterView} instance to an +{@link android.widget.Adapter}, which retrieves data from an external source and creates a {@link +android.view.View} that represents each data entry.

      + +

      Android provides several subclasses of {@link android.widget.Adapter} that are useful for +retrieving different kinds of data and building views for an {@link android.widget.AdapterView}. The +two most common adapters are:

      + +
      +
      {@link android.widget.ArrayAdapter}
      +
      Use this adapter when your data source is an array. By default, {@link +android.widget.ArrayAdapter} creates a view for each array item by calling {@link +java.lang.Object#toString()} on each item and placing the contents in a {@link +android.widget.TextView}. +

      For example, if you have an array of strings you want to display in a {@link +android.widget.ListView}, initialize a new {@link android.widget.ArrayAdapter} using a +constructor to specify the layout for each string and the string array:

      +
      +ArrayAdapter adapter = new ArrayAdapter<String>(this, 
      +        android.R.layout.simple_list_item_1, myStringArray);
      +
      +

      The arguments for this constructor are:

      +
        +
      • Your app {@link android.content.Context}
      • +
      • The layout that contains a {@link android.widget.TextView} for each string in the array
      • +
      • The string array
      • +
      +

      Then simply call +{@link android.widget.ListView#setAdapter setAdapter()} on your {@link android.widget.ListView}:

      +
      +ListView listView = (ListView) findViewById(R.id.listview);
      +listView.setAdapter(adapter);
      +
      + +

      To customize the appearance of each item you can override the {@link +java.lang.Object#toString()} method for the objects in your array. Or, to create a view for each +item that's something other than a {@link android.widget.TextView} (for example, if you want an +{@link android.widget.ImageView} for each array item), extend the {@link +android.widget.ArrayAdapter} class and override {@link android.widget.ArrayAdapter#getView +getView()} to return the type of view you want for each item.

      + +
      + +
      {@link android.widget.SimpleCursorAdapter}
      +
      Use this adapter when your data comes from a {@link android.database.Cursor}. When +using {@link android.widget.SimpleCursorAdapter}, you must specify a layout to use for each +row in the {@link android.database.Cursor} and which columns in the {@link android.database.Cursor} +should be inserted into which views of the layout. For example, if you want to create a list of +people's names and phone numbers, you can perform a query that returns a {@link +android.database.Cursor} containing a row for each person and columns for the names and +numbers. You then create a string array specifying which columns from the {@link +android.database.Cursor} you want in the layout for each result and an integer array specifying the +corresponding views that each column should be placed:

      +
      +String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, 
      +                        ContactsContract.CommonDataKinds.Phone.NUMBER};
      +int[] toViews = {R.id.display_name, R.id.phone_number};
      +
      +

      When you instantiate the {@link android.widget.SimpleCursorAdapter}, pass the layout to use for +each result, the {@link android.database.Cursor} containing the results, and these two arrays:

      +
      +SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, 
      +        R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
      +ListView listView = getListView();
      +listView.setAdapter(adapter);
      +
      +

      The {@link android.widget.SimpleCursorAdapter} then creates a view for each row in the +{@link android.database.Cursor} using the provided layout by inserting each {@code +fromColumns} item into the corresponding {@code toViews} view.

      .
      +
      + + +

      If, during the course of your application's life, you change the underlying data that is read by +your adapter, you should call {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. This will +notify the attached view that the data has been changed and it should refresh itself.

      + + + +

      Handling click events

      + +

      You can respond to click events on each item in an {@link android.widget.AdapterView} by +implementing the {@link android.widget.AdapterView.OnItemClickListener} interface. For example:

      + +
      +// Create a message handling object as an anonymous class.
      +private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
      +    public void onItemClick(AdapterView parent, View v, int position, long id) {
      +        // Do something in response to the click
      +    }
      +};
      +
      +listView.setOnItemClickListener(mMessageClickedHandler); 
      +
      + diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd index 82cbfd161b6b4aebc50e66744064e8b20b73afaf..9c2805817288c702ef442275de3e6009b4293810 100644 --- a/docs/html/guide/topics/ui/dialogs.jd +++ b/docs/html/guide/topics/ui/dialogs.jd @@ -313,7 +313,7 @@ Activity, the selection is lost.

      Note: To save the selection when the user leaves or pauses the Activity, you must properly save and restore the setting throughout -the activity lifecycle. +the activity lifecycle. To permanently save the selections, even when the Activity process is completely shutdown, you need to save the settings with one of the Data diff --git a/docs/html/resources/tutorials/views/images/android_focused.png b/docs/html/guide/topics/ui/images/android_focused.png similarity index 100% rename from docs/html/resources/tutorials/views/images/android_focused.png rename to docs/html/guide/topics/ui/images/android_focused.png diff --git a/docs/html/resources/tutorials/views/images/android_normal.png b/docs/html/guide/topics/ui/images/android_normal.png similarity index 100% rename from docs/html/resources/tutorials/views/images/android_normal.png rename to docs/html/guide/topics/ui/images/android_normal.png diff --git a/docs/html/resources/tutorials/views/images/android_pressed.png b/docs/html/guide/topics/ui/images/android_pressed.png similarity index 100% rename from docs/html/resources/tutorials/views/images/android_pressed.png rename to docs/html/guide/topics/ui/images/android_pressed.png diff --git a/docs/html/guide/tutorials/views/images/hello-gallery.png b/docs/html/guide/topics/ui/images/hello-gallery.png similarity index 100% rename from docs/html/guide/tutorials/views/images/hello-gallery.png rename to docs/html/guide/topics/ui/images/hello-gallery.png diff --git a/docs/html/guide/tutorials/views/images/hello-gridview.png b/docs/html/guide/topics/ui/images/hello-gridview.png similarity index 100% rename from docs/html/guide/tutorials/views/images/hello-gridview.png rename to docs/html/guide/topics/ui/images/hello-gridview.png diff --git a/docs/html/guide/tutorials/views/images/hello-linearlayout.png b/docs/html/guide/topics/ui/images/hello-linearlayout.png similarity index 100% rename from docs/html/guide/tutorials/views/images/hello-linearlayout.png rename to docs/html/guide/topics/ui/images/hello-linearlayout.png diff --git a/docs/html/resources/tutorials/views/images/hello-listview.png b/docs/html/guide/topics/ui/images/hello-listview.png similarity index 100% rename from docs/html/resources/tutorials/views/images/hello-listview.png rename to docs/html/guide/topics/ui/images/hello-listview.png diff --git a/docs/html/resources/tutorials/views/images/hello-mapview.png b/docs/html/guide/topics/ui/images/hello-mapview.png similarity index 100% rename from docs/html/resources/tutorials/views/images/hello-mapview.png rename to docs/html/guide/topics/ui/images/hello-mapview.png diff --git a/docs/html/guide/tutorials/views/images/hello-relativelayout.png b/docs/html/guide/topics/ui/images/hello-relativelayout.png similarity index 100% rename from docs/html/guide/tutorials/views/images/hello-relativelayout.png rename to docs/html/guide/topics/ui/images/hello-relativelayout.png diff --git a/docs/html/guide/tutorials/views/images/hello-tablelayout.png b/docs/html/guide/topics/ui/images/hello-tablelayout.png similarity index 100% rename from docs/html/guide/tutorials/views/images/hello-tablelayout.png rename to docs/html/guide/topics/ui/images/hello-tablelayout.png diff --git a/docs/html/resources/tutorials/views/images/hello-tabwidget.png b/docs/html/guide/topics/ui/images/hello-tabwidget.png similarity index 100% rename from docs/html/resources/tutorials/views/images/hello-tabwidget.png rename to docs/html/guide/topics/ui/images/hello-tabwidget.png diff --git a/docs/html/resources/tutorials/views/images/hello-webview.png b/docs/html/guide/topics/ui/images/hello-webview.png similarity index 100% rename from docs/html/resources/tutorials/views/images/hello-webview.png rename to docs/html/guide/topics/ui/images/hello-webview.png diff --git a/docs/html/resources/tutorials/views/images/ic_tab_artists_grey.png b/docs/html/guide/topics/ui/images/ic_tab_artists_grey.png similarity index 100% rename from docs/html/resources/tutorials/views/images/ic_tab_artists_grey.png rename to docs/html/guide/topics/ui/images/ic_tab_artists_grey.png diff --git a/docs/html/resources/tutorials/views/images/ic_tab_artists_white.png b/docs/html/guide/topics/ui/images/ic_tab_artists_white.png similarity index 100% rename from docs/html/resources/tutorials/views/images/ic_tab_artists_white.png rename to docs/html/guide/topics/ui/images/ic_tab_artists_white.png diff --git a/docs/html/guide/topics/ui/index.jd b/docs/html/guide/topics/ui/index.jd index be07249a4e1ecf5ebc69f194a00628861e007896..f342b0652f5ba0eddb489860c664846df07d17eb 100644 --- a/docs/html/guide/topics/ui/index.jd +++ b/docs/html/guide/topics/ui/index.jd @@ -1,236 +1,61 @@ page.title=User Interface -@jd:body - -

      -
      - -

      In this document

      -
        -
      1. View Hierarchy
      2. -
      3. Layout
      4. -
      5. Widgets
      6. -
      7. Input Events
      8. -
      9. Menus
      10. -
      11. Advanced Topics -
          -
        1. Adapters
        2. -
        3. Styles and Themes
        4. -
        -
      12. -
      - -

      Key classes

      -
        -
      1. {@link android.view.View}
      2. -
      3. {@link android.view.ViewGroup}
      4. -
      5. {@link android.widget Widget classes}
      6. -
      -
      -
      - -

      In an Android application, the user interface is built using {@link android.view.View} and -{@link android.view.ViewGroup} objects. There are many types of views and view groups, each of which -is a descendant of the {@link android.view.View} class.

      - -

      View objects are the basic units of user interface expression on the Android platform. -The View class serves as the base for subclasses called "widgets," which offer fully implemented -UI objects, like text fields and buttons. The ViewGroup class serves as the base for subclasses called "layouts," -which offer different kinds of layout architecture, like linear, tabular and relative.

      - -

      A View object is a data structure whose properties store the layout parameters and content for a specific -rectangular area of the screen. A View object handles its own measurement, layout, drawing, focus change, -scrolling, and key/gesture interactions for the rectangular area of the screen in which it resides. As an -object in the user interface, a View is also a point of interaction for the user and the receiver -of the interaction events.

      - - -

      View Hierarchy

      - -

      On the Android platform, you define an Activity's UI using a hierarchy of View and ViewGroup nodes, -as shown in the diagram below. This hierarchy tree can be as simple or complex as you need it to be, and you -can build it up using Android's set of predefined widgets and layouts, or with custom Views that you -create yourself.

      +page.landing=true +page.landing.intro=Your app's user interface is everything that the user can see and interact with. Android provides a variety of pre-build UI components such as structured layout objects and UI controls that allow you to build the graphical user interface for your app. Android also provides other UI modules for special interfaces such as dialogs, notifications, and menus. +page.landing.image=images/ui/ui_index.png +page.landing.next=overview.html - - -

      -In order to attach the view hierarchy tree to the screen for rendering, your Activity must call the -{@link android.app.Activity#setContentView(int) setContentView()} -method and pass a reference to the root node object. The Android system -receives this reference and uses it to invalidate, measure, and draw the tree. The root node of the hierarchy requests -that its child nodes draw themselves — in turn, each view group node is responsible for calling -upon each of its own child views to draw themselves. -The children may request a size and location within the parent, but the parent object has the final -decision on where how big each child can be. Android parses -the elements of your layout in-order (from the top of the hierarchy tree), instantiating the Views and -adding them to their parent(s). Because these are drawn in-order, if there are elements that -overlap positions, the last one to be drawn will lie on top of others previously drawn to that space.

      - -

      For a more detailed discussion on how view hierarchies are measured -and drawn, read How Android Draws Views.

      - - -

      Layout

      - -

      The most common way to define your layout and express the view hierarchy is with an XML layout file. -XML offers a human-readable structure for the layout, much like HTML. Each element in XML is -either a View or ViewGroup object (or descendant thereof). View objects are leaves in the tree, -ViewGroup objects are branches in the tree (see the View Hierarchy figure above).

      -

      The name of an XML element -is respective to the Java class that it represents. So a <TextView> element creates -a {@link android.widget.TextView} in your UI, and a <LinearLayout> element creates -a {@link android.widget.LinearLayout} view group. When you load a layout resource, -the Android system initializes these run-time objects, corresponding to the elements in your layout.

      - -

      For example, a simple vertical layout with a text view and a button looks like this:

      -
      -<?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:orientation="vertical" >
      -    <TextView android:id="@+id/text"
      -              android:layout_width="wrap_content"
      -              android:layout_height="wrap_content"
      -              android:text="Hello, I am a TextView" />
      -    <Button android:id="@+id/button"
      -            android:layout_width="wrap_content"
      -            android:layout_height="wrap_content"
      -            android:text="Hello, I am a Button" />
      -</LinearLayout>
      -
      - -

      Notice that the LinearLayout element contains both the TextView and the Button. You can nest -another LinearLayout (or other type of view group) inside here, to lengthen the view hierarchy and create a more -complex layout.

      +@jd:body -

      For more on building a UI layout, read XML Layouts. +

      + + + + - -

      There are a variety of ways in which you can layout your views. Using more and different kinds of view groups, -you can structure child views and view groups in an infinite number of ways. -Some pre-defined view groups offered by Android (called layouts) include LinearLayout, RelativeLayout, -TableLayout, GridLayout and others. Each offers a unique set of layout parameters that are used to define the -positions of child views and layout structure.

      -

      To learn about some of the different kinds of view groups used for a layout, -read Common Layout Objects.

      - - -

      Widgets

      - -

      A widget is a View object that serves as an interface for interaction with the user. -Android provides a set of fully implemented -widgets, like buttons, checkboxes, and text-entry fields, so you can quickly build your UI. -Some widgets provided by Android are more complex, like a date picker, a clock, and zoom controls. -But you're not limited to the kinds of widgets provided by the Android platform. If you'd -like to do something more customized and create your own actionable elements, you can, by defining your own -View object or by extending and combining existing widgets.

      -

      Read more in the Custom Components developer guide.

      - -

      For a list of the widgets provided by Android, see the {@link android.widget} package.

      - - -

      Input Events

      - -

      Once you've added some Views/widgets to the UI, you probably want to know about the -user's interaction with them, so you can perform actions. To be informed of user input events, you -need to do one of two things:

      -
        -
      • Define an event listener and register it with the View. More often than not, -this is how you'll listen for events. The View class contains a collection of nested interfaces named -On<something>Listener, each with a callback method called On<something>(). -For example, {@link android.view.View.OnClickListener} (for handling "clicks" on a View), -{@link android.view.View.OnTouchListener} (for handling touch screen events in a View), and -{@link android.view.View.OnKeyListener} if you want to handle hardware key presses within a View. So if you want your View -to be notified when it is "clicked" (such as when a button is selected), implement OnClickListener and define -its onClick() callback method (where you perform the action upon click), and register it -to the View with {@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}. -
      • -
      • Override an existing callback method for the View. This is -what you should do when you've implemented your own View class and want to listen for specific events -that occur within it. Example events you can handle include when the -screen is touched ({@link android.view.View#onTouchEvent(MotionEvent) onTouchEvent()}), when -the trackball is moved ({@link android.view.View#onTrackballEvent(MotionEvent) onTrackballEvent()}), -or when a hardware key on the device is pressed ({@link android.view.View#onKeyDown(int, KeyEvent) -onKeyDown()}). This allows you to define the default behavior for each event inside your custom View and determine -whether the event should be passed on to some other child View. Again, these are callbacks to the View class, -so your only chance to define them is when you -build a custom component. -
      • -
      - -

      Continue reading about handling user interaction with Views in the Input Events document.

      - - - - -

      Application menus are another important part of an application's UI. Menus offers a reliable interface that reveals -application functions and settings. The most common application menu is revealed by pressing -the Menu button on the device. However, you can also add Context Menus, which may be -revealed when the user presses -and holds down on an item.

      - -

      Menus are also structured using a View hierarchy, but you don't define this structure yourself. Instead, -you define the {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} or -{@link android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) onCreateContextMenu()} -callback methods for your Activity and declare the items that you want to include in your menu. -At the appropriate time, Android will automatically create the necessary View hierarchy for the menu and -draw each of your menu items in it.

      - -

      Menus also handle their own events, so there's no need to register event listeners on the items in your menu. -When an item in your menu is selected, the {@link android.app.Activity#onOptionsItemSelected(MenuItem) -onOptionsItemSelected()} or -{@link android.app.Activity#onContextItemSelected(MenuItem) onContextItemSelected()} -method will be called by the framework.

      - -

      And just like your application layout, you have the option to declare the items for you menu in an XML file.

      - -

      Read Menus to learn more.

      - - -

      Advanced Topics

      - -

      Once you've grappled the fundamentals of creating a user interface, you can explore -some advanced features for creating a more complex application interface.

      - -

      Adapters

      - -

      Sometimes you'll want to populate a view group with some information that can't be hard-coded, instead, -you want to bind your view to an external source of data. To do this, you use an AdapterView as -your view group and each child View is initialized and populated with data from the Adapter.

      -

      The AdapterView object is an implementation of ViewGroup that determines its child views -based on a given Adapter object. The Adapter acts like a courier between your data source (perhaps an -array of external strings) and the AdapterView, which displays it. There are several implementations -of the Adapter class, for specific tasks, such as the CursorAdapter for reading database data from a Cursor, -or an ArrayAdapter for reading from an arbitrary array.

      -

      To learn more about using an Adapter to populate your views, read -Binding to Data with AdapterView.

      - - -

      Styles and Themes

      - -

      Perhaps you're not satisfied with the look of the standard widgets. To revise them, you can create some -of your own styles and themes.

      - -
        -
      • A style is a set of one or more formatting attributes that you can apply as a unit to individual elements -in your layout. For example, you could define a style that specifies a certain text size and color, then -apply it to only specific View elements.
      • -
      • A theme is a set of one or more formatting attributes that you can apply as a unit to all activities in -an application, or just a single activity. For example, you could define a theme that sets specific colors for -the window frame and the panel background, and sets text sizes and colors for menus. This theme can then be -applied to specific activities or the entire application.
      • -
      - -

      Styles and themes are resources. Android provides some default style and theme resources that you can use, -or you can declare your own custom style and theme resources.

      -

      Learn more about using styles and themes in the -Styles and Themes document.

      diff --git a/docs/html/guide/topics/ui/layout-objects.jd b/docs/html/guide/topics/ui/layout-objects.jd index e251fe980b0ae4efbde1e1eda29eab750f69a30e..1d15ad60c0799c3e66d2e673fe7833a0176cb854 100644 --- a/docs/html/guide/topics/ui/layout-objects.jd +++ b/docs/html/guide/topics/ui/layout-objects.jd @@ -1,291 +1,6 @@ -page.title=Common Layout Objects +page.title=Layouts parent.title=User Interface parent.link=index.html @jd:body - - -

      This section describes some of the more common types of layout objects -to use in your applications. Like all layouts, they are subclasses of {@link android.view.ViewGroup ViewGroup}.

      - -

      Also see the Hello Views tutorials for -some guidance on using more Android View layouts.

      - -

      FrameLayout

      -

      {@link android.widget.FrameLayout FrameLayout} is the simplest type of layout -object. It's basically a blank space on your screen that you can -later fill with a single object — for example, a picture that you'll swap in and out. -All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot -specify a different location for a child view. Subsequent child views will simply be drawn over previous ones, -partially or totally obscuring them (unless the newer object is transparent). -

      - - -

      LinearLayout

      -

      {@link android.widget.LinearLayout LinearLayout} aligns all children in a -single direction — vertically or horizontally, depending on how you -define the orientation attribute. All children are -stacked one after the other, so a vertical list will only have one child per -row, no matter how wide they are, and a horizontal list will only be one row -high (the height of the tallest child, plus padding). A {@link -android.widget.LinearLayout LinearLayout} respects margins between children -and the gravity (right, center, or left alignment) of each child.

      - -

      {@link android.widget.LinearLayout LinearLayout} also supports assigning a -weight to individual children. This attribute assigns an "importance" value to a view, -and allows it to expand to fill any remaining space in the parent view. -Child views can specify an integer 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. For example, if there are three text boxes and two of -them declare a weight of 1, while the other is given no weight (0), the third text box without weight -will not grow and will only occupy the area required by its content. -The other two will expand equally to fill the space remaining after all three boxes are measured. -If the third box is then given a weight of 2 (instead of 0), then it is now declared -"more important" than both the others, so it gets half the total remaining space, while the first two -share the rest equally.

      - - - -

      The following two forms represent a {@link android.widget.LinearLayout LinearLayout} with a set of elements: a -button, some labels and text boxes. The text boxes have their width set to fill_parent; other -elements are set to wrap_content. The gravity, by default, is left. -The difference between the two versions of the form is that the form -on the left has weight values unset (0 by default), while the form on the right has -the comments text box weight set to 1. If the Name textbox had also been set -to 1, the Name and Comments text boxes would be the same height.

      - - - -

      Within a horizontal {@link android.widget.LinearLayout LinearLayout}, items are aligned by the position of -their text base line (the first line of the first list element — topmost or -leftmost — is considered the reference line). This is so that people scanning -elements in a form shouldn't have to jump up and down to read element text in -neighboring elements. This can be turned off by setting -android:baselineAligned="false" in the layout XML.

      - -

      To view other sample code, see the -Hello LinearLayout tutorial.

      - - -

      TableLayout

      -

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

      - - - - - - -
      -
      -<?xml version="1.0" encoding="utf-8"?>
      -<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:layout_width="fill_parent"
      -    android:layout_height="fill_parent"
      -    android:stretchColumns="1">
      -    <TableRow>
      -        <TextView
      -            android:text="@string/table_layout_4_open"
      -            android:padding="3dip" />
      -        <TextView
      -            android:text="@string/table_layout_4_open_shortcut"
      -            android:gravity="right"
      -            android:padding="3dip" />
      -    </TableRow>
      -
      -    <TableRow>
      -        <TextView
      -            android:text="@string/table_layout_4_save"
      -            android:padding="3dip" />
      -        <TextView
      -            android:text="@string/table_layout_4_save_shortcut"
      -            android:gravity="right"
      -            android:padding="3dip" />
      -    </TableRow>
      -</TableLayout>
      -
      - -

      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} -documentation for more details.

      - -

      To view sample code, see the Hello -TableLayout tutorial.

      - - -

      RelativeLayout

      -

      {@link android.widget.RelativeLayout} lets child views specify their - position relative to the parent view or to each other (specified by ID). So you can - align two elements by right border, or make one below another, centered in - the screen, centered left, and so on. Elements are rendered in the order given, so if the first element - is centered in the screen, other elements aligning themselves to that element - will be aligned relative to screen center. Also, because of this ordering, if using XML to specify this layout, - the element that you will reference (in order to position other view objects) must be listed in the XML -file before you refer to it from the other views via its reference ID.

      -

      The example below shows an XML file and the resulting screen in the UI. -Note that the attributes that refer to relative elements (e.g., layout_toLeft) -refer to the ID using the syntax of a relative resource -(@id/id).

      - - - - - - -
      -
      -<?xml version="1.0" encoding="utf-8"?>
      -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -                android:layout_width="fill_parent" 
      -                android:layout_height="wrap_content"
      -                android:background="@drawable/blue"
      -                android:padding="10px" >
      -
      -    <TextView android:id="@+id/label" 
      -              android:layout_width="fill_parent" 
      -              android:layout_height="wrap_content" 
      -              android:text="Type here:" />
      -
      -    <EditText android:id="@+id/entry" 
      -              android:layout_width="fill_parent" 
      -              android:layout_height="wrap_content" 
      -              android:background="@android:drawable/editbox_background"
      -              android:layout_below="@id/label" />
      -  
      -    <Button android:id="@+id/ok" 
      -            android:layout_width="wrap_content" 
      -            android:layout_height="wrap_content" 
      -            android:layout_below="@id/entry"
      -            android:layout_alignParentRight="true"
      -            android:layout_marginLeft="10px"
      -            android:text="OK" />
      -
      -    <Button android:layout_width="wrap_content" 
      -            android:layout_height="wrap_content"
      -            android:layout_toLeftOf="@id/ok"
      -            android:layout_alignTop="@id/ok"
      -            android:text="Cancel" />
      -</RelativeLayout>
      -
      - - -

      Some of these properties are supported directly by - the element, and some are supported by its LayoutParams member (subclass RelativeLayout - for all the elements in this screen, because all elements are children of a RelativeLayout - parent object). The defined RelativeLayout parameters are: width, height, - below, alignTop, toLeft, padding[Bottom|Left|Right|Top], - and margin[Bottom|Left|Right|Top]. Note that some of these parameters specifically support - relative layout positions — their values must be the ID of the element to which you'd like this view laid relative. - For example, assigning the parameter toLeft="my_button" to a TextView would place the TextView to - the left of the View with the ID my_button (which must be written in the XML before the TextView).

      - -

      To view this sample code, see the Hello -RelativeLayout tutorial.

      - - -

      Summary of Important View Groups

      -

      These objects all hold child UI elements. Some provide their own form of a visible UI, while others - are invisible structures that only manage the layout of their child views.

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      ClassDescription
      {@link android.widget.FrameLayout FrameLayout}Layout that acts as a view frame to display - a single object.
      {@link android.widget.Gallery Gallery} A horizontal scrolling display of images, from a bound list.
      {@link android.widget.GridView GridView} Displays a scrolling grid of m columns and n rows.
      {@link android.widget.LinearLayout LinearLayout} A layout that organizes its children into a single horizontal or vertical - row. It creates a scrollbar if the length of the window exceeds the length - of the screen.
      {@link android.widget.ListView ListView} Displays a scrolling single column list.
      {@link android.widget.RelativeLayout RelativeLayout} Enables you to specify the location of child objects relative to each - other (child A to the left of child B) or to the parent (aligned to the - top of the parent).
      {@link android.widget.ScrollView ScrollView} A vertically scrolling column of elements.
      {@link android.widget.Spinner Spinner} Displays a single item at a time from a bound list, inside a one-row - textbox. Rather like a one-row listbox that can scroll either horizontally - or vertically.
      {@link android.view.SurfaceView SurfaceView} Provides direct access to a dedicated drawing surface. It can hold child - views layered on top of the surface, but is intended for applications - that need to draw pixels, rather than using widgets.
      {@link android.widget.TabHost TabHost} Provides a tab selection list that monitors clicks and enables the application - to change the screen whenever a tab is clicked.
      {@link android.widget.TableLayout TableLayout} A tabular layout with an arbitrary number of rows and columns, each cell - holding the widget of your choice. The rows resize to fit the largest - column. The cell borders are not - visible.
      {@link android.widget.ViewFlipper ViewFlipper} A list that displays one item at a time, inside a one-row textbox. It - can be set to swap items at timed intervals, like a slide show.
      {@link android.widget.ViewSwitcher ViewSwitcher} Same as ViewFlipper.
      +

      You should have been redirected to Layouts.

      \ No newline at end of file diff --git a/docs/html/resources/tutorials/views/hello-tablelayout.jd b/docs/html/guide/topics/ui/layout/grid.jd similarity index 58% rename from docs/html/resources/tutorials/views/hello-tablelayout.jd rename to docs/html/guide/topics/ui/layout/grid.jd index c8c59828599c96760a4c5da50d0e02583ccd841a..52f453bb6a3398dcfc44b995e1a1365689cec2e0 100644 --- a/docs/html/resources/tutorials/views/hello-tablelayout.jd +++ b/docs/html/guide/topics/ui/layout/grid.jd @@ -1,12 +1,81 @@ -page.title=Table Layout -parent.title=Hello, Views -parent.link=index.html +page.title=Table +parent.title=Layouts +parent.link=layout-objects.html @jd:body - +
      +
      +

      In this document

      +
        +
      1. Example
      2. +
      +

      Key classes

      +
        +
      1. {@link android.widget.TableLayout}
      2. +
      3. {@link android.widget.TableRow}
      4. +
      5. {@link android.widget.TextView}
      6. +
      +
      +

      {@link android.widget.TableLayout} is a {@link android.view.ViewGroup} that 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).

      + + + + + + +
      +
      +<?xml version="1.0" encoding="utf-8"?>
      +<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
      +    android:layout_width="fill_parent"
      +    android:layout_height="fill_parent"
      +    android:stretchColumns="1">
      +    <TableRow>
      +        <TextView
      +            android:text="@string/table_layout_4_open"
      +            android:padding="3dip" />
      +        <TextView
      +            android:text="@string/table_layout_4_open_shortcut"
      +            android:gravity="right"
      +            android:padding="3dip" />
      +    </TableRow>
      +
      +    <TableRow>
      +        <TextView
      +            android:text="@string/table_layout_4_save"
      +            android:padding="3dip" />
      +        <TextView
      +            android:text="@string/table_layout_4_save_shortcut"
      +            android:gravity="right"
      +            android:padding="3dip" />
      +    </TableRow>
      +</TableLayout>
      +
      + +

      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} +documentation for more details.

      + + +

      Example

      1. Start a new project named HelloTableLayout.
      2. Open the res/layout/main.xml file and insert the following: @@ -114,11 +183,5 @@ file.

        You should see the following:

        -

        References

        -
          -
        • {@link android.widget.TableLayout}
        • -
        • {@link android.widget.TableRow}
        • -
        • {@link android.widget.TextView}
        • -
        diff --git a/docs/html/resources/tutorials/views/hello-gridview.jd b/docs/html/guide/topics/ui/layout/gridview.jd similarity index 95% rename from docs/html/resources/tutorials/views/hello-gridview.jd rename to docs/html/guide/topics/ui/layout/gridview.jd index 03bfc5449187ad9f0ea1520943527e8fa076c69b..284a25a5271bbc562829e0650d6802a664d7b38e 100644 --- a/docs/html/resources/tutorials/views/hello-gridview.jd +++ b/docs/html/guide/topics/ui/layout/gridview.jd @@ -1,13 +1,31 @@ -page.title=Grid View -parent.title=Hello, Views -parent.link=index.html +page.title=Grid +parent.title=Layouts +parent.link=layout-objects.html @jd:body - +
        +
        +

        In this document

        +
          +
        1. Example
        2. +
        +

        Key classes

        +
          +
        1. {@link android.widget.GridView}
        2. +
        3. {@link android.widget.ImageView}
        4. +
        5. {@link android.widget.BaseAdapter}
        6. +
        7. {@link android.widget.AdapterView.OnItemClickListener}
        8. +
        +
        +

        {@link android.widget.GridView} is a {@link android.view.ViewGroup} that displays items in a two-dimensional, scrollable grid. The grid items are automatically inserted to the layout using a {@link android.widget.ListAdapter}.

        + + + +

        Example

        In this tutorial, you'll create a grid of image thumbnails. When an item is selected, a toast message will display the position of the image.

        @@ -164,19 +182,10 @@ array, which is set as the image resource for the {@link android.widget.ImageVie
      3. Run the application.
      -

      Your grid layout should look something like this:

      -

      Try experimenting with the behaviors of the {@link android.widget.GridView} and {@link android.widget.ImageView} elements by adjusting their properties. For example, instead of using {@link android.view.View#setLayoutParams(ViewGroup.LayoutParams)}, try using {@link android.widget.ImageView#setAdjustViewBounds(boolean)}.

      -

      References

      -
        -
      • {@link android.widget.GridView}
      • -
      • {@link android.widget.ImageView}
      • -
      • {@link android.widget.BaseAdapter}
      • -
      • {@link android.widget.AdapterView.OnItemClickListener}
      • -
      diff --git a/docs/html/guide/topics/ui/layout/linear.jd b/docs/html/guide/topics/ui/layout/linear.jd new file mode 100644 index 0000000000000000000000000000000000000000..8e3370642e3155811f808652ca18cddd1892878b --- /dev/null +++ b/docs/html/guide/topics/ui/layout/linear.jd @@ -0,0 +1,116 @@ +page.title=Linear Layout +parent.title=Layouts +parent.link=layout-objects.html +@jd:body + +
      +
      +

      In this document

      +
        +
      1. Layout Weight
      2. +
      3. Example
      4. +
      + +

      Key classes

      +
        +
      1. {@link android.widget.LinearLayout}
      2. +
      3. {@link android.widget.LinearLayout.LayoutParams}
      4. +
      +
      +
      + +

      {@link android.widget.LinearLayout} is a view group that aligns all children in a single +direction, vertically or horizontally. You can specify the layout direction with the +{@code +android:orientation} attribute.

      + + + +

      All children of a {@link android.widget.LinearLayout} are +stacked one after the other, so a vertical list will only have one child per +row, no matter how wide they are, and a horizontal list will only be one row +high (the height of the tallest child, plus padding). A {@link +android.widget.LinearLayout LinearLayout} respects margins between children +and the gravity (right, center, or left alignment) of each child.

      + + +

      Layout Weight

      + + + + +

      {@link android.widget.LinearLayout} also supports assigning a +weight to individual children with the {@code android:layout_weight} attribute. +This attribute assigns an "importance" value to a view in +terms of how much space is should occupy on the screen. A larger weight value allows it to expand +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.

      + +

      For example, if there are three text fields and two of them declare a weight of 1, while the +other is given no weight, the third text field without weight will not grow and will only occupy the +area required by its content. The other two will expand equally to fill the space remaining after +all three fields are measured. If the third field is then given a weight of 2 (instead of 0), then +it is now declared more important than both the others, so it gets half the total remaining space, +while the first two +share the rest equally.

      + + +

      Example

      + +
      + +
      + +
      +<?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:paddingLeft="16dp"
      +    android:paddingRight="16dp"
      +    android:orientation="vertical" >
      +    <EditText
      +        android:layout_width="fill_parent"
      +        android:layout_height="wrap_content"
      +        android:hint="@string/to" />
      +    <EditText
      +        android:layout_width="fill_parent"
      +        android:layout_height="wrap_content"
      +        android:hint="@string/subject" />
      +    <EditText
      +        android:layout_width="fill_parent"
      +        android:layout_height="0dp"
      +        android:layout_weight="1"
      +        android:gravity="top"
      +        android:hint="@string/message" />
      +    <Button
      +        android:layout_width="100dp"
      +        android:layout_height="wrap_content"
      +        android:layout_gravity="right"
      +        android:text="@string/send" />
      +</LinearLayout>
      +
      + +

      For details about the attributes available to each child view of a {@link +android.widget.LinearLayout}, see {@link android.widget.LinearLayout.LayoutParams}.

      + + diff --git a/docs/html/guide/topics/ui/layout/listview.jd b/docs/html/guide/topics/ui/layout/listview.jd new file mode 100644 index 0000000000000000000000000000000000000000..26a75979988d5a08e3e76e5c364f3cae3eac1f0c --- /dev/null +++ b/docs/html/guide/topics/ui/layout/listview.jd @@ -0,0 +1,151 @@ +page.title=List View +parent.title=Layouts +parent.link=declaring-layout.html +@jd:body +
      +
      +

      In this document

      +
        +
      1. Using a Loader
      2. +
      3. Example
      4. +
      +

      Key classes

      +
        +
      1. {@link android.widget.ListView}
      2. +
      3. {@link android.widget.Adapter}
      4. +
      5. {@link android.support.v4.content.CursorLoader}
      6. +
      +

      See also

      +
        +
      1. Loaders
      2. +
      +
      +
      + +

      {@link android.widget.ListView} is a view group that displays a list of +scrollable items. The list items are automatically inserted to the list using an {@link +android.widget.Adapter} that pulls content from a source such as an array or database query and +converts each item result into a view that's placed into the list.

      + + + +

      Using a Loader

      + +

      Using a {@link +android.support.v4.content.CursorLoader} is the standard way to query a {@link +android.database.Cursor} as an asynchronous task in order to avoid blocking your app's main thread +with the query. When the {@link android.support.v4.content.CursorLoader} receives the {@link +android.database.Cursor} result, the {@link android.support.v4.app.LoaderManager.LoaderCallbacks +LoaderCallbacks} receives a callback to {@link +android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, which is +where you update your {@link +android.widget.Adapter} with the new {@link android.database.Cursor} and the list view then +displays the results.

      + +

      Although the {@link android.support.v4.content.CursorLoader} APIs were first introduced in +Android 3.0 (API level 11), they are also available in the Support Library so that your app may use them +while supporting devices running Android 1.6 or higher.

      + +

      For more information about using a {@link +android.support.v4.content.Loader} to asynchronously load data, see the Loaders guide.

      + + +

      Example

      + +

      The following example uses {@link android.app.ListActivity}, which is an activity that includes +a {@link android.widget.ListView} as its only layout element by default. It performs a query to +the Contacts +Provider for a list of names and phone numbers.

      + +

      The activity implements the {@link android.support.v4.app.LoaderManager.LoaderCallbacks +LoaderCallbacks} interface in order to use a {@link android.support.v4.content.CursorLoader} that +dynamically loads the data for the list view.

      + +
      +public class ListViewLoader extends ListActivity
      +        implements LoaderManager.LoaderCallbacks<Cursor> {
      +
      +    // This is the Adapter being used to display the list's data
      +    SimpleCursorAdapter mAdapter;
      +
      +    // These are the Contacts rows that we will retrieve
      +    static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,
      +            ContactsContract.Data.DISPLAY_NAME};
      +
      +    // This is the select criteria
      +    static final String SELECTION = "((" + 
      +            ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" +
      +            ContactsContract.Data.DISPLAY_NAME + " != '' ))";
      +
      +    @Override
      +    protected void onCreate(Bundle savedInstanceState) {
      +        super.onCreate(savedInstanceState);
      +
      +        // Create a progress bar to display while the list loads
      +        ProgressBar progressBar = new ProgressBar(this);
      +        progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
      +                LayoutParams.WRAP_CONTENT, Gravity.CENTER));
      +        progressBar.setIndeterminate(true);
      +        getListView().setEmptyView(progressBar);
      +
      +        // Must add the progress bar to the root of the layout
      +        ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
      +        root.addView(progressBar);
      +
      +        // For the cursor adapter, specify which columns go into which views
      +        String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
      +        int[] toViews = {android.R.id.text1}; // The TextView in simple_list_item_1
      +
      +        // 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, 
      +                android.R.layout.simple_list_item_1, null,
      +                fromColumns, toViews, 0);
      +        setListAdapter(mAdapter);
      +
      +        // Prepare the loader.  Either re-connect with an existing one,
      +        // or start a new one.
      +        getLoaderManager().initLoader(0, null, this);
      +    }
      +
      +    // Called when a new Loader needs to be created
      +    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
      +        // Now create and return a CursorLoader that will take care of
      +        // creating a Cursor for the data being displayed.
      +        return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
      +                PROJECTION, SELECTION, null, null);
      +    }
      +
      +    // Called when a previously created loader has finished loading
      +    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
      +        // Swap the new cursor in.  (The framework will take care of closing the
      +        // old cursor once we return.)
      +        mAdapter.swapCursor(data);
      +    }
      +
      +    // Called when a previously created loader is reset, making the data unavailable
      +    public void onLoaderReset(Loader<Cursor> loader) {
      +        // This is called when the last Cursor provided to onLoadFinished()
      +        // above is about to be closed.  We need to make sure we are no
      +        // longer using it.
      +        mAdapter.swapCursor(null);
      +    }
      +
      +    @Override 
      +    public void onListItemClick(ListView l, View v, int position, long id) {
      +        // Do something when a list item is clicked
      +    }
      +}
      +
      + +

      Note: Because this sample performs a query on the Contacts +Provider, if you want to +try this code, your app must request the {@link android.Manifest.permission#READ_CONTACTS} +permission in the manifest file:
      +<uses-permission android:name="android.permission.READ_CONTACTS" />

      + diff --git a/docs/html/guide/topics/ui/layout/relative.jd b/docs/html/guide/topics/ui/layout/relative.jd new file mode 100644 index 0000000000000000000000000000000000000000..ee6cf02bd6424c6dc52853b47ddebe17c6ca776c --- /dev/null +++ b/docs/html/guide/topics/ui/layout/relative.jd @@ -0,0 +1,118 @@ +page.title=Relative Layout +parent.title=Layouts +parent.link=layout-objects.html +@jd:body + +
      +
      +

      In this document

      +
        +
      1. Positioning Views
      2. +
      3. Example
      4. +
      +

      Key classes

      +
        +
      1. {@link android.widget.RelativeLayout}
      2. +
      3. {@link android.widget.RelativeLayout.LayoutParams}
      4. +
      +
      +
      + +

      {@link android.widget.RelativeLayout} is a view group that displays child views in relative +positions. The position of each view can be specified as relative to sibling elements (such as to +the left-of or below another view) or in positions relative to the parent {@link +android.widget.RelativeLayout} area (such as aligned to the bottom, left of center).

      + + + +

      A {@link android.widget.RelativeLayout} is a very powerful utility for designing a user interface +because it can eliminate nested view groups and keep your layout hierarchy flat, which improves +performance. If you find yourself using several nested {@link android.widget.LinearLayout} groups, +you may be able to replace them with a single {@link android.widget.RelativeLayout}.

      + + +

      Positioning Views

      + +

      {@link android.widget.RelativeLayout} lets child views specify their position relative to the +parent view or to each other (specified by ID). So you can align two elements by right border, or +make one below another, centered in the screen, centered left, and so on. By default, all child +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:

      +
      +
      {@code android:layout_alignParentTop}
      +
      If {@code "true"}, makes the top edge of this view match the top edge of the parent.
      +
      {@code android:layout_centerVertical}
      +
      If {@code "true"}, centers this child vertically within its parent.
      +
      {@code android:layout_below}
      +
      Positions the top edge of this view below the view specified with a resource ID.
      +
      {@code android:layout_toRightOf}
      +
      Positions the left edge of this view to the right of the view specified with a resource ID.
      +
      + +

      These are just a few examples. All layout attributes are documented at {@link +android.widget.RelativeLayout.LayoutParams}.

      + +

      The value for each layout property is either a boolean to +enable a layout position relative to the parent {@link android.widget.RelativeLayout} or an ID that +references another view in the layout against which the view should be positioned.

      + +

      In your XML layout, dependencies against other views in the layout can be declared in any order. +For example, you can declare that "view1" be positioned below "view2" even if "view2" is the last +view declared in the hierarchy. The example below demonstrates such a scenario.

      + + +

      Example

      + +

      Each of the attributes that control the relative position of each view are emphasized.

      +
      + +
      + +
      +<?xml version="1.0" encoding="utf-8"?>
      +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      +    android:layout_width="fill_parent"
      +    android:layout_height="fill_parent"
      +    android:paddingLeft="16dp"
      +    android:paddingRight="16dp" >
      +    <EditText
      +        android:id="@+id/name"
      +        android:layout_width="fill_parent"
      +        android:layout_height="wrap_content"
      +        android:hint="@string/reminder" />
      +    <Spinner
      +        android:id="@+id/dates"
      +        android:layout_width="0dp"
      +        android:layout_height="wrap_content"
      +        android:layout_below="@id/name"
      +        android:layout_alignParentLeft="true"
      +        android:layout_toLeftOf="@+id/times" />
      +    <Spinner
      +        android:id="@id/times"
      +        android:layout_width="96dp"
      +        android:layout_height="wrap_content"
      +        android:layout_below="@id/name"
      +        android:layout_alignParentRight="true" />
      +    <Button
      +        android:layout_width="96dp"
      +        android:layout_height="wrap_content"
      +        android:layout_below="@id/times"
      +        android:layout_alignParentRight="true"
      +        android:text="@string/done" />
      +</RelativeLayout>
      +
      + +

      For details about all the layout attributes available to each child view of a {@link +android.widget.RelativeLayout}, see {@link android.widget.RelativeLayout.LayoutParams}.

      \ No newline at end of file diff --git a/docs/html/resources/tutorials/views/hello-tabwidget.jd b/docs/html/guide/topics/ui/layout/tabs.jd similarity index 96% rename from docs/html/resources/tutorials/views/hello-tabwidget.jd rename to docs/html/guide/topics/ui/layout/tabs.jd index 9bafd84e26c15da24da599bab699f06f00ae67db..62663de8a84ddd0530536502a0f6848b65d09878 100644 --- a/docs/html/resources/tutorials/views/hello-tabwidget.jd +++ b/docs/html/guide/topics/ui/layout/tabs.jd @@ -1,20 +1,36 @@ -page.title=Tab Layout -parent.title=Hello, Views -parent.link=index.html +page.title=Tabbed +parent.title=Layouts +parent.link=layout-objects.html @jd:body - +
      +
      +

      In this document

      +
        +
      1. Example
      2. +
      +

      Key classes

      +
        +
      1. {@link android.widget.TabWidget}
      2. +
      3. {@link android.widget.TabHost}
      4. +
      5. {@link android.widget.TabHost.TabSpec}
      6. +
      7. {@link android.widget.FrameLayout}
      8. +
      +
      +

      To create a tabbed UI, you need to use a {@link android.widget.TabHost} and a {@link android.widget.TabWidget}. The {@link android.widget.TabHost} must be the root node for the layout, which contains both the {@link android.widget.TabWidget} for displaying the tabs and a {@link android.widget.FrameLayout} for displaying the tab content.

      + +

      You can implement your tab content in one of two ways: use the tabs to swap {@link android.view.View}s within the same {@link android.app.Activity}, or use the tabs to change between entirely separate activities. Which method you want for your application will depend on your demands, but if each tab provides a distinct user activity, then it probably makes sense to use a separate {@link android.app.Activity} for each tab, so that you can better manage the application in discrete groups, rather than one massive application and layout.

      - +

      Example

      In this tutorial, you'll create a tabbed UI that uses a separate {@link android.app.Activity} for each tab.

      @@ -200,11 +216,4 @@ calling {@link android.widget.TabHost#addTab(TabHost.TabSpec)}.

      Your application should look like this (though your icons may be different):

      -

      References

      -
        -
      • {@link android.widget.TabWidget}
      • -
      • {@link android.widget.TabHost}
      • -
      • {@link android.widget.TabHost.TabSpec}
      • -
      • {@link android.widget.FrameLayout}
      • -
      diff --git a/docs/html/guide/topics/ui/menus.jd b/docs/html/guide/topics/ui/menus.jd index d51a378cb4a340853691b91b4bef180a36d535ee..01d373ef2e86aa43fef230308955118f4a84e12a 100644 --- a/docs/html/guide/topics/ui/menus.jd +++ b/docs/html/guide/topics/ui/menus.jd @@ -1040,7 +1040,7 @@ category. For example:

    Read more about writing intent filters in the -Intents and Intent Filters document.

    +Intents and Intent Filters document.

    For a sample application using this technique, see the Note diff --git a/docs/html/guide/topics/ui/notifiers/index.jd b/docs/html/guide/topics/ui/notifiers/index.jd index c61d4f010f3523202c6f236978849147977d7f71..caf0df70edd115dac6ff8fa98864ea3db7d0a14b 100644 --- a/docs/html/guide/topics/ui/notifiers/index.jd +++ b/docs/html/guide/topics/ui/notifiers/index.jd @@ -21,7 +21,7 @@ the application should show a hovering progress wheel or bar.

  • @@ -44,16 +44,16 @@ out, and does not accept interaction events. Because a toast can be created from when you're fairly certain the user is paying attention to the screen. A toast can not accept user interaction events; if you'd like the user to respond and take action, consider using a -Status Bar Notification instead.

    +Status Notification instead.

    For more information, refer to Toast Notifications.

    -

    Status Bar Notification

    +

    Status Notification

    -

    A status bar notification adds an icon to the system's status bar +

    A status notification adds an icon to the system's status bar (with an optional ticker-text message) and an expanded message in the "Notifications" window. When the user selects the expanded message, Android fires an {@link android.content.Intent} that is defined by the notification (usually to launch an @@ -68,7 +68,7 @@ while your Activity is still in focus, consider using a Dialog Notification instead.

    For more information, refer to -Status Bar Notifications.

    +Status Notifications.

    Dialog Notification

    diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd index d104b4bccd14249f9a06eee4b350da29174587fe..52092f9409cf0d82a4ff26b212e6dab8992d5bdd 100644 --- a/docs/html/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html/guide/topics/ui/notifiers/notifications.jd @@ -1,4 +1,4 @@ -page.title=Status Bar Notifications +page.title=Status Notifications parent.title=Notifications parent.link=index.html @jd:body @@ -7,7 +7,7 @@ parent.link=index.html

    Quickview

      -
    • A status bar notification allows your application to notify the user of an event +
    • A status notification allows your application to notify the user of an event without interupting their current activity
    • You can attach an intent to your notification that the system will initiate when the user clicks it
    • @@ -43,7 +43,7 @@ Design: Notifications
    -

    A status bar notification adds an icon to the system's status bar +

    A status notification adds an icon to the system's status bar (with an optional ticker-text message) and a notification message in the notifications window. When the user selects the notification, Android fires an {@link android.content.Intent} that is defined by the {@link android.app.Notification} (usually to @@ -51,11 +51,11 @@ launch an {@link android.app.Activity}). You can also configure the notification to alert the user with a sound, a vibration, and flashing lights on the device.

    -

    A status bar notification should be used for any case in +

    A status notification should be used for any case in which a background service needs to alert the user about an event that requires a response. A background service should never launch an activity on its own in order to receive user interaction. -The service should instead create a status bar notification that will launch the activity +The service should instead create a status notification that will launch the activity when selected by the user.

    Figure 1 shows the status bar with a notification icon on the left side.

    @@ -78,9 +78,9 @@ href="{@docRoot}design/patterns/notifications.html">Notifications guide.

    The Basics

    -

    An {@link android.app.Activity} or {@link android.app.Service} can initiate a status bar +

    An {@link android.app.Activity} or {@link android.app.Service} can initiate a status notification. Because an activity can perform actions only while it is -running in the foreground and its window has focus, you will usually create status bar notifications +running in the foreground and its window has focus, you will usually create status notifications from a service. This way, the notification can be created from the background, while the user is using another application or @@ -88,9 +88,9 @@ while the device is asleep. To create a notification, you must use two classes: {@link android.app.Notification} and {@link android.app.NotificationManager}.

    Use an instance of the {@link android.app.Notification} class to define the properties of your -status bar notification, such as the status bar icon, the notification message, and extra settings +status notification, such as the status icon, the notification message, and extra settings such as a sound to play. The {@link android.app.NotificationManager} is an Android system service -that executes and manages all status bar notifications. You do not instantiate the +that executes and manages all status notifications. You do not instantiate the {@link android.app.NotificationManager} directly. In order to give it your {@link android.app.Notification}, you must retrieve a reference to the {@link android.app.NotificationManager} with @@ -98,7 +98,7 @@ to give it your {@link android.app.Notification}, you must retrieve a reference then, when you want to notify the user, pass it your {@link android.app.Notification} with {@link android.app.NotificationManager#notify(int,Notification) notify()}.

    -

    To create a status bar notification:

    +

    To create a status notification:

    1. Get a reference to the {@link android.app.NotificationManager}:
      @@ -277,7 +277,7 @@ String ns = Context.NOTIFICATION_SERVICE;
       NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
       
      -

      When you want to deliver your status bar notification, pass the {@link android.app.Notification} +

      When you want to deliver your status notification, pass the {@link android.app.Notification} to the {@link android.app.NotificationManager} with {@link android.app.NotificationManager#notify(int,Notification)}. The first parameter is the unique ID for the notification and the second is the {@link @@ -287,7 +287,7 @@ application. The ID is necessary if you need to update the notification or (if your application manages different kinds of notifications) select the appropriate action when the user returns to your application via the intent defined in the notification.

      -

      To clear the status bar notification when the user selects it from the notifications +

      To clear the status notification when the user selects it from the notifications window, add the "FLAG_AUTO_CANCEL" flag to your {@link android.app.Notification}. You can also clear it manually with {@link android.app.NotificationManager#cancel(int)}, passing it the notification ID, or clear all your notifications with {@link @@ -300,14 +300,14 @@ android.app.NotificationManager#cancelAll()}.

      message that is displayed in the status bar and notifications window, and any other alert settings, such as sounds and blinking lights.

      -

      A status bar notification requires all of the following:

      +

      A status notification requires all of the following:

      • An icon for the status bar
      • A title and message, unless you define a custom notification layout
      • A {@link android.app.PendingIntent}, to be fired when the notification is selected
      -

      Optional settings for the status bar notification include:

      +

      Optional settings for the status notification include:

      • A ticker-text message for the status bar
      • An alert sound
      • @@ -339,7 +339,7 @@ notification.setLatestEventInfo(context, contentTitle, contentText, contentInten

        Updating the notification

        -

        You can update the information in your status bar notification as events +

        You can update the information in your status notification as events continue to occur in your application. For example, when a new SMS text message arrives before previous messages have been read, the Messaging application updates the existing notification to display the total number of new messages received. @@ -484,7 +484,7 @@ following:

        your notification is on-going.
    {@link android.app.Notification#number} field
    This value indicates the current number of events represented by the notification. - The appropriate number is overlaid on top of the status bar icon. + The appropriate number is overlaid on top of the status icon. If you intend to use this field, then you must start with "1" when the Notification is first created. (If you change the value from zero to anything greater during an update, the number is not shown.)
    diff --git a/docs/html/guide/topics/ui/overview.jd b/docs/html/guide/topics/ui/overview.jd new file mode 100644 index 0000000000000000000000000000000000000000..41f7cc7b3f018939ba60071755ec1efddc23ce61 --- /dev/null +++ b/docs/html/guide/topics/ui/overview.jd @@ -0,0 +1,74 @@ +page.title=UI Overview +@jd:body + + +

    All user interface elements in an Android app are built using {@link android.view.View} and +{@link android.view.ViewGroup} objects. A {@link android.view.View} is an object that draws +something on the screen that the user can interact with. A {@link android.view.ViewGroup} is an +object that holds other {@link android.view.View} (and {@link android.view.ViewGroup}) objects in +order to define the layout of the interface.

    + +

    Android provides a collection of both {@link android.view.View} and {@link +android.view.ViewGroup} subclasses that offer you common input controls (such as buttons and text +fields) and various layout models (such as a linear or relative layout).

    + + +

    User Interface Layout

    + +

    The user interface for each component of your app is defined using a hierarchy of {@link +android.view.View} and {@link android.view.ViewGroup} objects, as shown in figure 1. Each view group +is an invisible container that organizes child views, while the child views may be input +controls or other widgets that +draw some part of the UI. This hierarchy tree can be as simple or complex as you need +it to be (but simplicity is best for performance).

    + + +

    Figure 1. Illustration of a view hierarchy, which defines a +UI layout.

    + +

    To declare your layout, you can instantiate {@link android.view.View} objects in code and start +building a tree, but the easiest and most effective way to define your layout is with an XML file. +XML offers a human-readable structure for the layout, similar to HTML.

    + +

    The name of an XML element for a view is respective to the Android class it represents. So a +<TextView> element creates a {@link android.widget.TextView} widget in your UI, +and a <LinearLayout> element creates a {@link android.widget.LinearLayout} view +group.

    + +

    For example, a simple vertical layout with a text view and a button looks like this:

    +
    +<?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:orientation="vertical" >
    +    <TextView android:id="@+id/text"
    +              android:layout_width="wrap_content"
    +              android:layout_height="wrap_content"
    +              android:text="I am a TextView" />
    +    <Button android:id="@+id/button"
    +            android:layout_width="wrap_content"
    +            android:layout_height="wrap_content"
    +            android:text="I am a Button" />
    +</LinearLayout>
    +
    + +

    When you load a layout resource in your app, Android initializes each node of the layout into a +runtime object you can use to define additional behaviors, query the object state, or modify the +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 +android.view.ViewGroup} objects. Android provides several app components that offer +a standard UI layout for which you simply need to define the content. These UI components each +have a unique set of APIs that are described in their respective documents, such as Action Bar, Dialogs, and Status Notifications.

    + + diff --git a/docs/html/guide/topics/ui/sharables/sample_images.zip b/docs/html/guide/topics/ui/sharables/sample_images.zip new file mode 100644 index 0000000000000000000000000000000000000000..007a68aca79ec370246b50f2cbebb3aa0fb3ee0d Binary files /dev/null and b/docs/html/guide/topics/ui/sharables/sample_images.zip differ diff --git a/docs/html/guide/topics/views/custom-views.jd b/docs/html/guide/topics/views/custom-views.jd deleted file mode 100644 index 8589b1a01a1a16bff3639d62e9e6ec4a1be8e6b5..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/views/custom-views.jd +++ /dev/null @@ -1,544 +0,0 @@ -page.title=Building Custom Views -parent.title=Views and Layout -parent.link=index.html -@jd:body - -

    Android offers a sophisticated and powerful componentized model for building your UI, based on the fundamental building block 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. The widgets and layouts are fully implemented and handle all of their own measuring and drawing, so you can use them right away. You can make new types of UI elements simply by nesting and grouping the widgets and layouts. Using widgets and layouts is the recommended approach to building a UI for your applications.

    - -

    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.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.AbsoluteLayout AbsoluteLayout}, and others. For more examples, see Common Layout Objects.

    - -

    If none of the prebuilt widgets or layouts meets your needs, you can also create your own View subclass, such as a layout group or compound control. 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 examples of what you could do with them:

    - -
      -
    • - You could create a completely custom-rendered View type, for example a "volume - control" knob rendered using 2D graphics, and which resembles an - analog electronic control. -
    • -
    • - You could combine a group of View components into a new single component, perhaps - to make something like a ComboBox (a combination of popup list and free - entry text field), a dual-pane selector control (a left and right pane - with a list in each where you can re-assign which item is in which - list), and so on. -
    • -
    • - You could override the way that an EditText component is rendered on the screen - (the Notepad sample uses this to good effect, - to create a lined-notepad page). -
    • -
    • - You could capture other events like key presses and handle them in some custom - way (such as for a game). -
    • -
    -

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

    - -

    This document covers the following:

    -
      -
    1. The Basic Approach
    2. -
    3. Fully Customized Views
    4. -
    5. Customized View Example
    6. -
    7. Compound Controls
    8. -
    9. Modifying an Existing Component Type
    10. -
    - - -

    The Basic Approach -

    -

    -These steps provide 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 - with your own class. -
    2. -
    3. - 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 - {@link android.view.View#onKeyDown onKeyDown()}. -
        -
      • - This is similar to the on... events in {@link android.app.Activity - Activity} or {@link android.app.ListActivity ListActivity} - that you override for life cycle and other functionality hooks. -
      • -
      -
    4. - Use your new extension class: once completed, your new extension class - can be used in place of the view upon which it was based, but now with the new - functionality. -
    5. -
    -

    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 - isn't necessary (perhaps you want to create a new public View for - wider use in your application). -

    - - -

    Fully Customized Components

    -

    -Fully customized components can be used to create graphical components that -appear however you wish. Perhaps a graphical VU -meter that looks like an old analog gauge, or a sing-a-long text view where -a bouncing ball moves along the words so you can sing along with a karaoke -machine. Either way, you want something that the built-in components just -won't do, no matter how you combine them.

    -

    Fortunately, you can easily create components that look and behave in any -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:

    -
      -
    1. - The most generic view you can extend is, unsurprisingly, {@link - android.view.View View}, so you will usually start by extending this to - create your new super component. -
    2. -
    3. - You can supply a constructor which can - take attributes and parameters from the XML, and you can also consume - your own such attributes and parameters (perhaps the color and range of - the VU meter, or the width and damping of the needle, etc.) -
    4. -
    5. - You will probably want to create your own event listeners, - property accessors and modifiers, and possibly more sophisticated - behavior in your component class as well. -
    6. -
    7. - You will almost certainly want to override onMeasure() and - are also likely to need to override onDraw() if you want - the component to show something. While both have default behavior, - the default onDraw() will do nothing, and the default - onMeasure() will always set a size of 100x100 — which is - probably not what you want. -
    8. -
    9. - Other on... methods may also be overridden as required. -
    10. -
    -

    onDraw() and onMeasure()

    -

    onDraw() delivers you a {@link android.graphics.Canvas Canvas} -upon which you can implement anything you want: 2D graphics, other standard or -custom components, styled text, or anything else you can think of.

    -

    Note: -Except for 3D graphics. If you want to -use 3D graphics, you must extend {@link android.view.SurfaceView SurfaceView} -instead of View, and draw from a separate thread. See the -GLSurfaceViewActivity sample -for details.

    -

    onMeasure() is a little more involved. onMeasure() -is a critical piece of the rendering contract between your component and its -container. onMeasure() should be overridden to efficiently and -accurately report the measurements of its contained parts. This is made -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 -result will be an exception at measurement time.

    -

    At a high level, implementing onMeasure() looks something - like this:

    - -
      -
    1. - The overridden onMeasure() method is called with width and - height measure specifications (widthMeasureSpec and - heightMeasureSpec parameters, both are integer codes - representing dimensions) which should be treated as requirements for - the restrictions on the width and height measurements you should produce. A - full reference to the kind of restrictions these specifications can require - can be found in the reference documentation under {@link - android.view.View#onMeasure View.onMeasure(int, int)} (this reference - documentation does a pretty good job of explaining the whole measurement - operation as well). -
    2. -
    3. - Your component's onMeasure() method should calculate a - 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, - or asking the onMeasure() to try again, perhaps with - different measurement specifications). -
    4. -
    5. - Once the width and height are calculated, the setMeasuredDimension(int - width, int height) method must be called with the calculated - measurements. Failure to do this will result in an exception being - thrown. -
    6. -
    - -

    -Here's a summary of some of the other standard methods that the framework calls on views: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Category Methods Description
    CreationConstructorsThere is a form of the constructor that are called when the view - is created from code and a form that is called when the view is - inflated from a layout file. The second form should parse and apply - any attributes defined in the layout file. -
    {@link android.view.View#onFinishInflate()}Called after a view and all of its children has been inflated - from XML.
    Layout{@link android.view.View#onMeasure}Called to determine the size requirements for this view and all - of its children. -
    {@link android.view.View#onLayout}Called when this view should assign a size and position to all - of its children. -
    {@link android.view.View#onSizeChanged}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}Called when a new key event occurs. -
    {@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 -API Demos provides an example -of a customized View. The custom View is defined in the -LabelView -class.

    -

    The LabelView sample demonstrates a number of different aspects of custom components:

    -
      -
    • Extending the View class for a completely custom component.
    • -
    • Parameterized constructor that takes the view inflation parameters - (parameters defined in the XML). Some of these are passed through to the - View superclass, but more importantly, there are some custom attributes defined - and used for LabelView.
    • -
    • Standard public methods of the type you would expect to see for a label - component, for example setText(), setTextSize(), - setTextColor() and so on.
    • -
    • An overridden onMeasure method to determine and set the - rendering size of the component. (Note that in LabelView, the real work is done - by a private measureWidth() method.)
    • -
    • An overridden onDraw() method to draw the label onto the - provided canvas.
    • -
    -

    You can see some sample usages of the LabelView custom View in -custom_view_1.xml -from the samples. In particular, you can see a mix of both android: -namespace parameters and custom app: namespace parameters. These -app: parameters are the custom ones that the LabelView recognizes -and works with, and are defined in a styleable inner class inside of the -samples R resources definition class.

    - - -

    Compound Controls -

    -

    If you don't want to create a completely customized component, but instead -are looking to put together a reusable component that consists of a group of -existing controls, then creating a Compound Component (or Compound Control) might -fit the bill. In a nutshell, this brings together a number of more atomic -controls (or views) into a logical group of items that can be treated as a -single thing. For example, a Combo Box can be thought of as a -combination of a single line EditText field and an adjacent button with an attached - PopupList. If you press the button and select -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 -example.

    -

    To create a compound component:

    -
      -
    1. - The usual starting point is a Layout of some kind, so create a class - that extends a Layout. Perhaps in the case of a Combo box we might use - a LinearLayout with horizontal orientation. Remember that other layouts - can be nested inside, so the compound component can be arbitrarily - complex and structured. Note that just like with an Activity, you can - use either the declarative (XML-based) approach to creating the - contained components, or you can nest them programmatically from your - code. -
    2. -
    3. - In the constructor for the new class, take whatever parameters the - superclass expects, and pass them through to the superclass constructor - first. Then you can set up the other views to use within your new - component; this is where you would create the EditText field and the - PopupList. Note that you also might introduce your own attributes and - parameters into the XML that can be pulled out and used by your - constructor. -
    4. -
    5. - You can also create listeners for events that your contained views might - generate, for example, a listener method for the List Item Click Listener - to update the contents of the EditText if a list selection is made. -
    6. -
    7. - You might also create your own properties with accessors and modifiers, - for example, allow the EditText value to be set initially in the - component and query for its contents when needed. -
    8. -
    9. - 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, - you can still override them if you need to. -
    10. -
    11. - You might override other on... methods, like - onKeyDown(), to perhaps choose certain default values from - the popup list of a combo box when a certain key is pressed. -
    12. -
    -

    - To summarize, the use of a Layout as the basis for a Custom Control has a -number of advantages, including:

    - -
      -
    • - You can specify the layout using the declarative XML files just like - with an activity screen, or you can create views programmatically and - nest them into the layout from your code. -
    • -
    • - The onDraw() and onMeasure() methods (plus - most of the other on... methods) will likely have suitable behavior so - you don't have to override them. -
    • -
    • - In the end, you can very quickly construct arbitrarily complex compound - views and re-use them as if they were a single component. -
    • -
    -

    Examples of Compound Controls

    -

    In the API Demos project - that comes with the SDK, there are two List - examples — Example 4 and Example 6 under Views/Lists demonstrate a - SpeechView which extends LinearLayout to make a component for displaying - Speech quotes. The corresponding classes in the sample code are - List4.java and List6.java.

    - - -

    Modifying an Existing View Type -

    -

    There is an even easier option for creating a custom View which is -useful in certain circumstances. If there is a component that is already very -similar to what you want, you can simply extend that component and just -override the behavior that you want to change. You can do all of the things -you would do with a fully customized component, but by starting with a more -specialized class in the View hierarchy, you can also get a lot of behavior for -free that probably does exactly what you want.

    -

    For example, the SDK includes a NotePad application in the -samples. This demonstrates many aspects of using the Android platform, among -them is extending an EditText View to make a lined notepad. This is not a -perfect example, and the APIs for doing this might change from this early -preview, but it does demonstrate the principles.

    -

    If you haven't done so already, import the -NotePad sample into Eclipse (or -just look at the source using the link provided). In particular look at the definition of -MyEditText in the NoteEditor.java -file.

    -

    Some points to note here

    -
      -
    1. - The Definition -

      The class is defined with the following line:

      - public static class MyEditText extends EditText

      - -
        -
      • - It is defined as an inner class within the NoteEditor - activity, but it is public so that it could be accessed as - NoteEditor.MyEditText from outside of the NoteEditor - class if desired. -
      • -
      • - It is static, meaning it does not generate the so-called - "synthetic methods" that allow it to access data from the parent - class, which in turn means that it really behaves as a separate - class rather than something strongly related to NoteEditor. - This is a cleaner way to create inner classes if they do not need - access to state from the outer class, keeps the generated class - small, and allows it to be used easily from other classes. -
      • -
      • - It extends EditText, which is the View we have chosen to - customize in this case. When we are finished, the new class will be - able to substitute for a normal EditText view.
        -
        -
      • -
      -
    2. -
    3. - Class Initialization -

      As always, the super is called first. Furthermore, - this is not a default constructor, but a parameterized one. The - EditText is created with these parameters when it is inflated from an - XML layout file, thus, our constructor needs to both take them and pass them - to the superclass constructor as well.

      -
    4. -
    5. - Overridden Methods -

      In this example, there is only one method to be overridden: - onDraw() — but there could easily be others needed when you - create your own custom components.

      -

      For the NotePad sample, overriding the onDraw() method allows - us to paint the blue lines on the EditText view canvas (the - canvas is passed into the overridden onDraw() method). The - super.onDraw() method is called before the method ends. The - superclass method should be invoked, but in this case, we do it at the - end after we have painted the lines we want to include.

      -
    6. - Use the Custom Component -

      We now have our custom component, but how can we use it? In the - NotePad example, the custom component is used directly from the - declarative layout, so take a look at note_editor.xml in the - res/layout folder.

      -
      -<view xmlns:android="http://schemas.android.com/apk/res/android" 
      -  class="com.android.notepad.NoteEditor$MyEditText" 
      -  id="@+id/note"
      -  android:layout_width="fill_parent"
      -  android:layout_height="fill_parent"
      -  android:background="@android:drawable/empty"
      -  android:padding="10dip"
      -  android:scrollbars="vertical"
      -  android:fadingEdge="vertical" /> 
      - -
        -
      • - The custom component is created as a generic view in the XML, and - the class is specified using the full package. Note also that the - inner class we defined is referenced using the - NoteEditor$MyEditText notation which is a standard way to - refer to inner classes in the Java programming language. -
      • -
      • - The other attributes and parameters in the definition are the ones - passed into the custom component constructor, and then passed - through to the EditText constructor, so they are the same - parameters that you would use for an EditText view. Note that it is - possible to add your own parameters as well, and we will touch on - this again below. -
      • -
      -
    7. -
    -

    And that's all there is to it. Admittedly this is a simple case, but -that's the point — creating custom components is only as complicated as you -need it to be.

    -

    A more sophisticated component may override even more on... methods and -introduce some of its own helper methods, substantially customizing its properties and -behavior. The only limit is your imagination and what you need the component to -do.

    - diff --git a/docs/html/guide/topics/views/intro.jd b/docs/html/guide/topics/views/intro.jd deleted file mode 100644 index f49f5478bce3fbf17606512d54974ea07357be6b..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/views/intro.jd +++ /dev/null @@ -1,49 +0,0 @@ -page.title=Introduction to Views -parent.title=Views and Layout -parent.link=index.html -@jd:body - -

    The basic functional unit of an Android application is the activity — an object of the class {@link android.app.Activity android.app.Activity}. An activity can do many things, but by itself it does not have a presence on the screen. To give your activity a screen presence and design its UI, you work with views and viewgroups -- basic units of user interface expression on the Android platform.

    - -

    Views

    -

    A view is an object of base class {@link android.view.View android.view.View}. It's a data structure whose properties store the layout and content for a specific rectangular area of the screen. A View object handles measuring and layout, drawing, focus change, scrolling, and key/gestures for the screen area it represents.

    -

    The View class serves as a base class for widgets — a set of fully implemented subclasses that draw interactive screen elements. Widgets handle their own measuring and drawing, so you can use them to build your UI more quickly. The list of widgets available includes Text, EditText, InputMethod, MovementMethod, Button, RadioButton, Checkbox, and ScrollView.

    - -

    Viewgroups

    - -

    A viewgroup is an object of class {@link android.view.ViewGroup android.view.Viewgroup}. As its name indicates, a viewgroup is a special type of view object whose function is to contain and manage a subordinate set of views and other viewgroups, Viewgroups let you add structure to your UI and build up complex screen elements that can be addressed as a single entity.

    - -

    The Viewgroup class serves as a base class for layouts — a set of fully implemented subclasses that provide common types of screen layout. The layouts give you a way to build a structure for a set of views.

    - -

    A Tree-Structured UI

    - -

    On the Android platform, you define an Activity's UI using a tree of view and viewgroup nodes, as shown in the diagram below. The tree can be as simple or complex as you need to make it, and you can build it up using Android's set of predefined widgets and layouts or custom view types that you create yourself.

    - -An example of a tree of views and viewgroups - -

    To attach the tree to the screen for rendering, your Activity calls its setContentView() method and passes a reference to the root node object. Once the Android system has the reference to the root node object, it can work directly with the node to invalidate, measure, and draw the tree. When your Activity becomes active and receives focus, the system notifies your activity and requests the root node to measure and draw the tree. The root node then requests that its child nodes draw themselves — in turn, each viewgroup node in the tree is responsible for drawing its direct children.

    - -

    As mentioned previously, each view group has the responsibility of - measuring its available space, laying out its children, and calling Draw() on - each child to let it render itself. The children may request a size and location - in the parent, but the parent object has the final decision on where how big - each child can be.

    - -

    LayoutParams: How a Child Specifies Its Position and Size

    - -

    Every viewgroup class uses a nested class that extends {@link -android.view.ViewGroup.LayoutParams ViewGroup.LayoutParams}. This subclass - contains property types that define a child's size and position, in properties - appropriate for that view group class.

    - -An example of layoutparams - -

    Note that every LayoutParams subclass has its own syntax for setting -values. Each child element must define LayoutParams that are appropriate for its parent, although it may define different LayoutParams for its children.

    - -

    All viewgroups include width and height. Many also include margins and -borders. You can specify width and height exactly, though you probably won't want -to do this often. More often you will tell your view to size itself either to -the dimensions of its content, or to become as big as its containing object -will allow.

    - diff --git a/docs/html/guide/topics/views/ui-xml.jd b/docs/html/guide/topics/views/ui-xml.jd deleted file mode 100644 index bcfa56286ab5232c4e607f92f044ab76d25a5545..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/views/ui-xml.jd +++ /dev/null @@ -1,138 +0,0 @@ -page.title=Declaring a UI in XML -parent.title=Views and Layout -parent.link=index.html -@jd:body - -

    You can create your application's user interface in two ways: -

      -
    • You can declare UI elements statically, in XML. Android provides a straightforward XML vocabulary that corresponds to the View classes and subclasses, such as those for widgets and layouts.
    • -
    • You can instantiate screen elements dynamically, at runtime, through code in your application. Your application can refer to or create View or other class objects and manipulate their properties programmatically.
    • -
    - -

    One advantage of declaring your UI in XML is that it enables you to better separate the presentation of your application from the code that controls it's behavior. Your UI description is external to your application code, which means that you can modify or adapt it without having to modify your source code and recompile. For example, you can create XML layouts for different screen orientations and for a variety of device screen sizes or languages. Additionally, declaring in XML makes it easier to see the elements and structure of your UI, so it's easier to debug problems.

    - -

    The Android framework gives you the flexibility to use either or both of these ways of declaring and managing your application's UI. For example, you could declare your application's default layouts in XML, including the screen elements that will appear in them and their properties. You could then add code in your application that would modify the state of the screen objects, including those declared in XML, at run time.

    - -

    You build your application's UI in approximately the same way, whether you are declaring it in XML or programmatically. In both cases, your UI will be a tree structure that may include multiple View or Viewgroup subclasses.

    - -

    In general, the XML vocabulary for declaring UI elements closely follows the structure and naming of the framework's UI-related classes and methods, where element names correspond to class names and attribute names correspond to methods. In fact, the correspondence is often so direct that you can guess what XML attribute corresponds to a class method, or guess what class corresponds to a given xml element.

    - -

    However, note that the XML vocabulary for defining UI is not entirely identical to the framework's classes and methods. In some cases, there are slight naming differences. For -example, the EditText element has a text attribute that corresponds to -EditText.setText.

    - - - -

    Using Android's XML vocabulary, you can quickly design UI layouts and the screen elements they contain, in the same way you create HTML files — as a series of nested tags.

    - -

    Each layout file must contain exactly one root element, and the root element must be a View or ViewGroup object. Once you've defined the root element, you can add additional layout objects or controls as child elements of the root element, if needed. In the example below, the tree of XML elements evaluates to the outermost LinearLayout object. - -

    After you've declared your layout in XML, you must save the file, with the .xml extension, in the proper location, so that it will be compiled correctly. The proper location for storing layout files is in your application's res/layout/ directory.

    - -

    When you compile your application, each XML layout file is compiled into an -android.view.View resource. You can then load the layout resource from your application code, by calling setContentView(R.layout.layout_file_name) in your {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()} -implementation.

    - -

    When you load a layout resource, the Android system initializes run-time objects corresponding to the elements in your layout. It parses the elements of your layout in-order (depth-first), instantiating the Views and adding them to their parent(s).

    - -

    Attributes named layout_something apply to that -object's LayoutParams member. Layout -Resources also describes how to learn the syntax for specifying -LayoutParams properties.

    - -

    Also note that Android draws elements in the order in which they -appear in the XML. Therefore, if elements overlap, the last one in the XML -file will probably be drawn on top of any previously listed elements in that -same space.

    - -

    The following values are supported for dimensions (described in {@link -android.util.TypedValue TypedValue}):

    - -
      -
    • px (pixels)
    • -
    • dip (device independent pixels)
    • -
    • sp (scaled pixels — best for text size)
    • -
    • pt (points)
    • -
    • in (inches)
    • -
    • mm (millimeters)
    • -
    - -

    Example: android:layout_width="25px"

    - -

    For more information about these dimensions, see Dimension Values.

    - -

    The example below shows an XML file and the resulting screen in the UI. Note that the text on the -top of the screen was set by calling {@link -android.app.Activity#setTitle(java.lang.CharSequence) Activity.setTitle}. Note -that the attributes that refer to relative elements (i.e., layout_toLeft) -refer to the ID using the syntax of a relative resource -(@id/id_number).

    - - - - - - -
    -
    <?xml version="1.0" encoding="utf-8"?>
    -<!-- Demonstrates using a relative layout to create a form -->
    -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android
    -                android:layout_width="fill_parent" 
    -                android:layout_height="wrap_content"
    -                android:background="@drawable/blue"
    -                android:padding="10px">
    -
    -    <TextView id="@+id/label" 
    -              android:layout_width="fill_parent" 
    -              android:layout_height="wrap_content" 
    -              android:text="Type here:"/>
    -
    -    <EditText id="@+id/entry" 
    -              android:layout_width="fill_parent" 
    -              android:layout_height="wrap_content" 
    -              android:background="@android:drawable/editbox_background"
    -              android:layout_below="@id/label"/>
    -  
    -    <Button id="@+id/ok" 
    -            android:layout_width="wrap_content" 
    -            android:layout_height="wrap_content" 
    -            android:layout_below="@id/entry"
    -            android:layout_alignParentRight="true"
    -            android:layout_marginLeft="10px"
    -            android:text="OK" />
    -
    -    <Button android:layout_width="wrap_content" 
    -            android:layout_height="wrap_content"
    -            android:layout_toLeftOf="@id/ok"
    -            android:layout_alignTop="@id/ok"
    -            android:text="Cancel" />
    -</RelativeLayout>
    Screen shot showing how this layout XML file is rendered.
    - -

    Loading the XML Resource

    - -

    Loading the compiled layout resource is very easy, and done with a single -call in the activity's onCreate() method, as shown here:

    - -
    -protected void onCreate(Bundle savedValues)
    -{
    -   // Be sure to call the super class.
    -   super.onCreate(savedValues);
    -
    -   // Load the compiled layout resource into the window's
    -   // default ViewGroup.
    -   // The source file is res/layout/hello_activity.xml
    -    setContentView(R.layout.hello_activity);
    -  
    -   // Retrieve any important stored values.
    -   restoreValues(savedValues);
    -} 
    diff --git a/docs/html/guide/topics/wireless/index.jd b/docs/html/guide/topics/wireless/index.jd deleted file mode 100644 index 23d2f0fc4f78874d651a3114a5b63a8fcaa05950..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/wireless/index.jd +++ /dev/null @@ -1,23 +0,0 @@ -page.title=Wireless Controls -@jd:body - -Go away. - - - - diff --git a/docs/html/guide/topics/wireless/wifi.jd b/docs/html/guide/topics/wireless/wifi.jd deleted file mode 100644 index 761e463f0dea766e306ae54d460bfb7959acb067..0000000000000000000000000000000000000000 --- a/docs/html/guide/topics/wireless/wifi.jd +++ /dev/null @@ -1,18 +0,0 @@ -page.title=Wi-Fi -parent.title=Wireless Controls -parent.link=index.html -@jd:body - -
    -
    - -

    In this document

    -
      - -
    - -
    -
    - - -Go away. \ No newline at end of file diff --git a/docs/html/guide/tutorials/hello-world.html b/docs/html/guide/tutorials/hello-world.html deleted file mode 100644 index 55187bd7a1a8eec337a47ced6ac25db60857fdbb..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/hello-world.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting... - - -

    You should have been redirected. Please click here.

    - - \ No newline at end of file diff --git a/docs/html/guide/tutorials/images/hello_world_0.png b/docs/html/guide/tutorials/images/hello_world_0.png deleted file mode 100644 index 330a07c7476024a08846ce92fd3486687f9c91cb..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/images/hello_world_0.png and /dev/null differ diff --git a/docs/html/guide/tutorials/images/hello_world_1.png b/docs/html/guide/tutorials/images/hello_world_1.png deleted file mode 100644 index 1e5f7b0cdfe3a84432e940d897b4fbd000d24026..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/images/hello_world_1.png and /dev/null differ diff --git a/docs/html/guide/tutorials/images/hello_world_2.png b/docs/html/guide/tutorials/images/hello_world_2.png deleted file mode 100644 index 3e9c58b2a45d89af545e500facaa8126b094c338..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/images/hello_world_2.png and /dev/null differ diff --git a/docs/html/guide/tutorials/images/hello_world_3.png b/docs/html/guide/tutorials/images/hello_world_3.png deleted file mode 100644 index 22901a97ffde646e3ab08c7e80ec7041b3bbbaec..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/images/hello_world_3.png and /dev/null differ diff --git a/docs/html/guide/tutorials/images/hello_world_4.png b/docs/html/guide/tutorials/images/hello_world_4.png deleted file mode 100644 index 5c41e80ad9417acc2748a19a6205c7500fb335ba..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/images/hello_world_4.png and /dev/null differ diff --git a/docs/html/guide/tutorials/images/hello_world_5.png b/docs/html/guide/tutorials/images/hello_world_5.png deleted file mode 100644 index 96b830a963a0daf6105f5281f378d89c3d09233a..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/images/hello_world_5.png and /dev/null differ diff --git a/docs/html/guide/tutorials/images/hello_world_8.png b/docs/html/guide/tutorials/images/hello_world_8.png deleted file mode 100644 index 07db36019fed132d27966770740e4734f4576704..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/images/hello_world_8.png and /dev/null differ diff --git a/docs/html/guide/tutorials/images/hello_world_9.png b/docs/html/guide/tutorials/images/hello_world_9.png deleted file mode 100644 index a66526ad6ca22265fb1dcdeca14d941f5bb51a6d..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/images/hello_world_9.png and /dev/null differ diff --git a/docs/html/guide/tutorials/index.html b/docs/html/guide/tutorials/index.html deleted file mode 100644 index e412dec94b3ba6278571dc05793f634c7dea6862..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting... - - -

    You should have been redirected. Please click here.

    - - \ No newline at end of file diff --git a/docs/html/guide/tutorials/localization/index.html b/docs/html/guide/tutorials/localization/index.html deleted file mode 100644 index 2ea666182f07125710b69f23f7057d97ff4fe6c4..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/localization/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting... - - -

    You should have been redirected. Please click here.

    - - \ No newline at end of file diff --git a/docs/html/guide/tutorials/notepad/codelab/NotepadCodeLab.zip b/docs/html/guide/tutorials/notepad/codelab/NotepadCodeLab.zip deleted file mode 100644 index 24fefc1a31fba645c4f066b31a00ddcdda7c505d..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/notepad/codelab/NotepadCodeLab.zip and /dev/null differ diff --git a/docs/html/guide/tutorials/notepad/index.html b/docs/html/guide/tutorials/notepad/index.html deleted file mode 100644 index 01e4d098a48bb4d1ca3a39b192eff8d8da1e7a87..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/notepad/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting... - - -

    You should have been redirected. Please click here.

    - - \ No newline at end of file diff --git a/docs/html/guide/tutorials/notepad/notepad-ex1.jd b/docs/html/guide/tutorials/notepad/notepad-ex1.jd deleted file mode 100644 index cf7765e1693a8035ad8b1b2f89fee7dd673f8ad3..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/notepad/notepad-ex1.jd +++ /dev/null @@ -1,582 +0,0 @@ -page.title=Notepad Exercise 1 -parent.title=Notepad Tutorial -parent.link=index.html -@jd:body - - -

    In this exercise, you will construct a simple notes list that lets the -user add new notes but not edit them. The exercise demonstrates:

    -
      -
    • The basics of ListActivities and creating and handling menu -options.
    • -
    • How to use a SQLite database to store the notes.
    • -
    • How to bind data from a database cursor into a ListView using a -SimpleCursorAdapter.
    • -
    • The basics of screen layouts, including how to lay out a list view, how -you can add items to the activity menu, and how the activity handles those menu -selections.
    • -
    - - - - - -

    Step 1

    - -

    Open up the Notepadv1 project in Eclipse.

    - -

    Notepadv1 is a project that is provided as a starting point. It - takes care of some of the boilerplate work that you have already seen if you - followed the Hello, - World tutorial.

    - -
      -
    1. - Start a new Android Project by clicking File > - New > Android Project.
    2. -
    3. - In the New Android Project dialog, select Create project from existing source.
    4. -
    5. - Click Browse and navigate to where you copied the NotepadCodeLab - (downloaded during setup) - and select Notepadv1.
    6. -
    7. - The Project Name and other properties should be automatically filled for you. - You must select the Build Target—we recommend selecting a target with the - lowest platform version available. Also add an integer to the Min SDK Version field - that matches the API Level of the selected Build Target.
    8. -
    9. - Click Finish. The Notepadv1 project should open and be - visible in your Eclipse package explorer.
    10. -
    - -

    If you see an error about AndroidManifest.xml, or some - problems related to an Android zip file, right click on the project and - select Android Tools > Fix Project Properties. - (The project is looking in the wrong location for the library file, - this will fix it for you.)

    - -

    Step 2

    - - - -

    Take a look at the NotesDbAdapter class — this class is provided to - encapsulate data access to a SQLite database that will hold our notes data - and allow us to update it.

    -

    At the top of the class are some constant definitions that will be used in the application - to look up data from the proper field names in the database. There is also a database creation - string defined, which is used to create a new database schema if one doesn't exist already.

    -

    Our database will have the name data, and have a single table called - notes, which in turn has three fields: _id, title and - body. The _id is named with an underscore convention used in a number of - places inside the Android SDK and helps keep a track of state. The _id - usually has to be specified when querying or updating the database (in the column projections - and so on). The other two fields are simple text fields that will store data. -

    -

    The constructor for NotesDbAdapter takes a Context, which allows it to communicate with aspects - of the Android operating system. This is quite common for classes that need to touch the - Android system in some way. The Activity class implements the Context class, so usually you will just pass - this from your Activity, when needing a Context.

    -

    The open() method calls up an instance of DatabaseHelper, which is our local - implementation of the SQLiteOpenHelper class. It calls getWritableDatabase(), - which handles creating/opening a database for us.

    -

    close() just closes the database, releasing resources related to the - connection.

    -

    createNote() takes strings for the title and body of a new note, - then creates that note in the database. Assuming the new note is created successfully, the - method also returns the row _id value for the newly created note.

    -

    deleteNote() takes a rowId for a particular note, and deletes that note from - the database.

    - -

    fetchAllNotes() issues a query to return a {@link android.database.Cursor} over all notes in the - database. The query() call is worth examination and understanding. The first field is the - name of the database table to query (in this case DATABASE_TABLE is "notes"). - The next is the list of columns we want returned, in this case we want the _id, - title and body columns so these are specified in the String array. - The remaining fields are, in order: selection, - selectionArgs, groupBy, having and orderBy. - Having these all null means we want all data, need no grouping, and will take the default - order. See {@link android.database.sqlite.SQLiteDatabase SQLiteDatabase} for more details.

    -

    Note: A Cursor is returned rather than a collection of rows. This allows - Android to use resources efficiently -- instead of putting lots of data straight into memory - the cursor will retrieve and release data as it is needed, which is much more efficient for - tables with lots of rows.

    - -

    fetchNote() is similar to fetchAllNotes() but just gets one note - with the rowId we specify. It uses a slightly different version of the - {@link android.database.sqlite.SQLiteDatabase} query() method. - The first parameter (set true) indicates that we are interested - in one distinct result. The selection parameter (the fourth parameter) has been specified to search - only for the row "where _id =" the rowId we passed in. So we are returned a Cursor on - the one row.

    -

    And finally, updateNote() takes a rowId, title and body, and uses a - {@link android.content.ContentValues ContentValues} instance to update the note of the given - rowId.

    - -

    Step 3

    - - - -

    Open the notepad_list.xml file in res/layout -and - take a look at it. (You may have to - hit the xml tab, at the bottom, in order to view the XML markup.)

    - -

    This is a mostly-empty layout definition file. Here are some - things you should know about a layout file:

    - - -
      -
    • - All Android layout files must start with the XML header line: - <?xml version="1.0" encoding="utf-8"?>.
    • -
    • - The next definition will often (but not always) be a layout - definition of some kind, in this case a LinearLayout.
    • -
    • - The XML namespace of Android should always be defined in - the top level component or layout in the XML so that android: tags can - be used through the rest of the file: -

      xmlns:android="http://schemas.android.com/apk/res/android"

      -
    • -
    - -

    Step 4

    -

    We need to create the layout to hold our list. Add code inside - of the LinearLayout element so the whole file looks like this:

    -
    -<?xml version="1.0" encoding="utf-8"?>
    -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -    android:layout_width="wrap_content"
    -    android:layout_height="wrap_content">
    -
    -  <ListView android:id="@android:id/list"
    -        android:layout_width="wrap_content"
    -        android:layout_height="wrap_content"/>
    -  <TextView android:id="@android:id/empty"
    -        android:layout_width="wrap_content"
    -        android:layout_height="wrap_content"
    -        android:text="@string/no_notes"/>
    -
    -</LinearLayout>
    -
    -
      -
    • - The @ symbol in the id strings of the ListView and - TextView tags means - that the XML parser should parse and expand the rest of - the id string and use an ID resource.
    • -
    • - The ListView and TextView can be - thought as two alternative views, only one of which will be displayed at once. - ListView will be used when there are notes to be shown, while the TextView - (which has a default value of "No Notes Yet!" defined as a string - resource in res/values/strings.xml) will be displayed if there - aren't any notes to display.
    • -
    • The list and empty IDs are - provided for us by the Android platform, so, we must - prefix the id with android: (e.g., @android:id/list).
    • -
    • The View with the empty id is used - automatically when the {@link android.widget.ListAdapter} has no data for the ListView. The - ListAdapter knows to look for this name by default. Alternatively, you could change the - default empty view by using {@link android.widget.AdapterView#setEmptyView(View)} - on the ListView. -

      - More broadly, the android.R class is a set of predefined - resources provided for you by the platform, while your project's - R class is the set of resources your project has defined. - Resources found in the android.R resource class can be - used in the XML files by using the android: name space prefix - (as we see here).

      -
    • -
    - -

    Step 5

    - - - -

    To make the list of notes in the ListView, we also need to define a View for each row:

    -
      -
    1. - Create a new file under res/layout called - notes_row.xml.
    2. -
    3. - Add the following contents (note: again the XML header is used, and the - first node defines the Android XML namespace)
      -
      -<?xml version="1.0" encoding="utf-8"?>
      -<TextView android:id="@+id/text1"
      -    xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:layout_width="wrap_content"
      -    android:layout_height="wrap_content"/>
      -

      - This is the View that will be used for each notes title row — it has only - one text field in it.

      -

      In this case we create a new id called text1. The - + after the @ in the id string indicates that the id should - be automatically created as a resource if it does not already exist, so we are defining - text1 on the fly and then using it.

      -
    4. -
    5. Save the file.
    6. -
    -

    Open the R.java class in the - project and look at it, you should see new definitions for - notes_row and text1 (our new definitions) - meaning we can now gain access to these from the our code.

    - -

    Step 6

    -

    Next, open the Notepadv1 class in the source. In the following steps, we are going to - alter this class to become a list adapter and display our notes, and also - allow us to add new notes.

    - -

    Notepadv1 will inherit from a subclass - of Activity called a ListActivity, - which has extra functionality to accommodate the kinds of - things you might want to do with a list, for - example: displaying an arbitrary number of list items in rows on the screen, - moving through the list items, and allowing them to be selected.

    - -

    Take a look through the existing code in Notepadv1 class. - There is a currently an unused private field called mNoteNumber that - we will use to create numbered note titles.

    -

    There are also three override methods defined: - onCreate, onCreateOptionsMenu and - onOptionsItemSelected; we need to fill these - out:

    -
      -
    • onCreate() is called when the activity is - started — it is a little like the "main" method for an Activity. We use - this to set up resources and state for the activity when it is - running.
    • -
    • onCreateOptionsMenu() is used to populate the - menu for the Activity. This is shown when the user hits the menu button, -and - has a list of options they can select (like "Create - Note").
    • -
    • onOptionsItemSelected() is the other half of the - menu equation, it is used to handle events generated from the menu (e.g., - when the user selects the "Create Note" item). -
    • -
    - -

    Step 7

    -

    Change the inheritance of Notepadv1 from -Activity - to ListActivity:

    -
    public class Notepadv1 extends ListActivity
    -

    Note: you will have to import ListActivity into the -Notepadv1 - class using Eclipse, ctrl-shift-O on Windows or Linux, or - cmd-shift-O on the Mac (organize imports) will do this for you - after you've written the above change.

    - -

    Step 8

    -

    Fill out the body of the onCreate() method.

    -

    Here we will set the title for the Activity (shown at the top of the - screen), use the notepad_list layout we created in XML, - set up the NotesDbAdapter instance that will - access notes data, and populate the list with the available note - titles:

    -
      -
    1. - In the onCreate method, call super.onCreate() with the - savedInstanceState parameter that's passed in.
    2. -
    3. - Call setContentView() and pass R.layout.notepad_list.
    4. -
    5. - At the top of the class, create a new private class field called mDbHelper of class - NotesDbAdapter. -
    6. -
    7. - Back in the onCreate method, construct a new -NotesDbAdapter - instance and assign it to the mDbHelper field (pass - this into the constructor for DBHelper) -
    8. -
    9. - Call the open() method on mDbHelper to open (or create) the - database. -
    10. -
    11. - Finally, call a new method fillData(), which will get the data and - populate the ListView using the helper — we haven't defined this method yet.
    12. -
    -

    - onCreate() should now look like this:

    -
    -    @Override
    -    public void onCreate(Bundle savedInstanceState) {
    -        super.onCreate(savedInstanceState);
    -        setContentView(R.layout.notepad_list);
    -        mDbHelper = new NotesDbAdapter(this);
    -        mDbHelper.open();
    -        fillData();
    -    }
    -

    And be sure you have the mDbHelper field definition (right - under the mNoteNumber definition):

    -
        private NotesDbAdapter mDbHelper;
    - -

    Step 9

    - - - -

    Fill out the body of the onCreateOptionsMenu() method.

    - -

    We will now create the "Add Item" button that can be accessed by pressing the menu -button on the device. We'll specify that it occupy the first position in the menu.

    - -
      -
    1. - In strings.xml resource (under res/values), add - a new string named "menu_insert" with its value set to Add Item: -
      <string name="menu_insert">Add Item</string>
      -

      Then save the file and return to Notepadv1.

      -
    2. -
    3. Create a menu position constant at the top of the class: -
      public static final int INSERT_ID = Menu.FIRST;
      -
    4. -
    5. In the onCreateOptionsMenu() method, change the - super call so we capture the boolean return as result. We'll return this value at the end.
    6. -
    7. Then add the menu item with menu.add().
    8. -
    -

    The whole method should now look like this: -

    -    @Override
    -    public boolean onCreateOptionsMenu(Menu menu) {
    -        boolean result = super.onCreateOptionsMenu(menu);
    -        menu.add(0, INSERT_ID, 0, R.string.menu_insert);
    -        return result;
    -    }
    -

    The arguments passed to add() indicate: a group identifier for this menu (none, - in this case), a unique ID (defined above), the order of the item (zero indicates no preference), - and the resource of the string to use for the item.

    - -

    Step 10

    -

    Fill out the body of the onOptionsItemSelected() method:

    -

    This is going - to handle our new "Add Note" menu item. When this is selected, the - onOptionsItemSelected() method will be called with the - item.getId() set to INSERT_ID (the constant we - used to identify the menu item). We can detect this, and take the - appropriate actions:

    -
      -
    1. - The super.onOptionsItemSelected(item) method call goes at the - end of this method — we want to catch our events first!
    2. -
    3. - Write a switch statement on item.getItemId(). -

      In the case of INSERT_ID, call a new method, createNote(), - and return true, because we have handled this event and do not want to - propagate it through the system.

      -
    4. -
    5. Return the result of the superclass' onOptionsItemSelected() - method at the end.
    6. -
    -

    - The whole onOptionsItemSelect() method should now look like - this:

    -
    -    @Override
    -    public boolean onOptionsItemSelected(MenuItem item) {
    -        switch (item.getItemId()) {
    -        case INSERT_ID:
    -            createNote();
    -            return true;
    -        }
    -       
    -        return super.onOptionsItemSelected(item);
    -    }
    - -

    Step 11

    -

    Add a new createNote() method:

    -

    In this first version of - our application, createNote() is not going to be very useful. -We will simply - create a new note with a title assigned to it based on a counter ("Note 1", - "Note 2"...) and with an empty body. At present we have no way of editing - the contents of a note, so for now we will have to be content making one - with some default values:

    -
      -
    1. Construct the name using "Note" and the counter we defined in the class: - String noteName = "Note " + mNoteNumber++
    2. -
    3. - Call mDbHelper.createNote() using noteName as the - title and "" for the body -
    4. -
    5. - Call fillData() to populate the list of notes (inefficient but - simple) — we'll create this method next.
    6. -
    -

    - The whole createNote() method should look like this:

    -
    -    private void createNote() {
    -        String noteName = "Note " + mNoteNumber++;
    -        mDbHelper.createNote(noteName, "");
    -        fillData();
    -    }
    - - -

    Step 12

    - - -

    Define the fillData() method:

    -

    This - method uses SimpleCursorAdapter, which takes a database Cursor - and binds it to fields provided in the layout. These fields define the row elements of our list - (in this case we use the text1 field in our - notes_row.xml layout), so this allows us to easily populate the list with - entries from our database.

    -

    To do this we have to provide a mapping from the title field in the returned Cursor, to - our text1 TextView, which is done by defining two arrays: the first a string array - with the list of columns to map from (just "title" in this case, from the constant - NotesDbAdapter.KEY_TITLE) and, the second, an int array - containing references to the views that we'll bind the data into - (the R.id.text1 TextView).

    -

    This is a bigger chunk of code, so let's first take a look at it:

    - -
    -    private void fillData() {
    -        // Get all of the notes from the database and create the item list
    -        Cursor c = mDbHelper.fetchAllNotes();
    -        startManagingCursor(c);
    -
    -        String[] from = new String[] { NotesDbAdapter.KEY_TITLE };
    -        int[] to = new int[] { R.id.text1 };
    -        
    -        // Now create an array adapter and set it to display using our row
    -        SimpleCursorAdapter notes =
    -            new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
    -        setListAdapter(notes);
    -    }
    - -

    Here's what we've done:

    -
      -
    1. - After obtaining the Cursor from mDbHelper.fetchAllNotes(), we - use an Activity method called - startManagingCursor() that allows Android to take care of the - Cursor lifecycle instead of us needing to worry about it. (We will cover the implications - of the lifecycle in exercise 3, but for now just know that this allows Android to do some - of our resource management work for us.)
    2. -
    3. - Then we create a string array in which we declare the column(s) we want - (just the title, in this case), and an int array that defines the View(s) - to which we'd like to bind the columns (these should be in order, respective to - the string array, but here we only have one for each).
    4. -
    5. - Next is the SimpleCursorAdapter instantiation. - Like many classes in Android, the SimpleCursorAdapter needs a Context in order to do its - work, so we pass in this for the context (since subclasses of Activity - implement Context). We pass the notes_row View we created as the receptacle - for the data, the Cursor we just created, and then our arrays.
    6. -
    -

    - In the future, remember that the mapping between the from columns and to resources - is done using the respective ordering of the two arrays. If we had more columns we wanted - to bind, and more Views to bind them in to, we would specify them in order, for example we - might use { NotesDbAdapter.KEY_TITLE, NotesDbAdapter.KEY_BODY } and - { R.id.text1, R.id.text2 } to bind two fields into the row (and we would also need - to define text2 in the notes_row.xml, for the body text). This is how you can bind multiple fields - into a single row (and get a custom row layout as well).

    -

    - If you get compiler errors about classes not being found, ctrl-shift-O or - (cmd-shift-O on the mac) to organize imports. -

    - -

    Step 13

    -

    Run it! -

      -
    1. - Right click on the Notepadv1 project.
    2. -
    3. - From the popup menu, select Run As > - Android Application.
    4. -
    5. - If you see a dialog come up, select Android Launcher as the way of running - the application (you can also use the link near the top of the dialog to - set this as your default for the workspace; this is recommended as it will - stop the plugin from asking you this every time).
    6. -
    7. Add new notes by hitting the menu button and selecting Add - Item from the menu.
    8. -
    - -

    Solution and Next Steps

    -

    You can see the solution to this class in Notepadv1Solution -from -the zip file to compare with your own.

    - -

    Once you are ready, move on to Tutorial -Exercise 2 to add the ability to create, edit and delete notes.

    - diff --git a/docs/html/guide/tutorials/notepad/notepad-ex2.jd b/docs/html/guide/tutorials/notepad/notepad-ex2.jd deleted file mode 100644 index fed40abb267ee97f0a0474a51cfc5e9c7bb34b63..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/notepad/notepad-ex2.jd +++ /dev/null @@ -1,642 +0,0 @@ -Rpage.title=Notepad Exercise 2 -parent.title=Notepad Tutorial -parent.link=index.html -@jd:body - - -

    In this exercise, you will add a second Activity to your notepad application, to let the user -create and edit notes. You will also allow the user to delete existing notes through a context menu. -The new Activity assumes responsibility for creating new notes by -collecting user input and packing it into a return Bundle provided by the intent. This exercise -demonstrates:

    -
      -
    • Constructing a new Activity and adding it to the Android manifest
    • -
    • Invoking another Activity asynchronously using startActivityForResult()
    • -
    • Passing data between Activity in Bundle objects
    • -
    • How to use a more advanced screen layout
    • -
    • How to create a context menu
    • -
    - - - -

    Step 1

    - -

    Create a new Android project using the sources from Notepadv2 under the -NotepadCodeLab folder, just like you did for the first exercise. If you see an error about -AndroidManifest.xml, or some problems related to an -android.zip file, right click on the project and select Android -Tools > Fix Project Properties.

    - -

    Open the Notepadv2 project and take a look around:

    -
      -
    • - Open and look at the strings.xml file under - res/values — there are several new strings which we will use - for our new functionality -
    • -
    • - Also, open and take a look at the top of the Notepadv2 class, - you will notice several new constants have been defined along with a new mNotesCursor - field used to hold the cursor we are using. -
    • -
    • - Note also that the fillData() method has a few more comments and now uses - the new field to store the notes Cursor. The onCreate() method is - unchanged from the first exercise. Also notice that the member field used to store the - notes Cursor is now called mNotesCursor. The m denotes a member - field and is part of the Android coding style standards. -
    • -
    • - There are also a couple of new overridden methods - (onCreateContextMenu(), onContextItemSelected(), - onListItemClick() and onActivityResult()) - which we will be filling in below. -
    • -
    - - -

    Step 2

    - - -

    First, let's create the context menu that will allow users to delete individual notes. -Open the Notepadv2 class.

    - -
      -
    1. In order for each list item in the ListView to register for the context menu, we call - registerForContextMenu() and pass it our ListView. So, at the very end of - the onCreate() method add this line: -
      registerForContextMenu(getListView());
      -

      Because our Activity extends the ListActivity class, getListView() will return us - the local ListView object for the Activity. Now, each list item in this ListView will activate the - context menu. -

    2. - Now fill in the onCreateContextMenu() method. This callback is similar to the other - menu callback used for the options menu. Here, we add just one line, which will add a menu item - to delete a note. Call menu.add() like so: -
      -public void onCreateContextMenu(Menu menu, View v,
      -        ContextMenu.ContextMenuInfo menuInfo) {
      -    super.onCreateContextMenu(menu, v, menuInfo);
      -    menu.add(0, DELETE_ID, 0, R.string.menu_delete);
      -}
      -

      The onCreateContextMenu() callback passes some other information in addition to the Menu object, - such as the View that has been triggered for the menu and - an extra object that may contain additional information about the object selected. However, we don't care about - these here, because we only have one kind of object in the Activity that uses context menus. In the next - step, we'll handle the menu item selection.

      -
    3. -
    - -

    Step 3

    -

    Now that the we've registered our ListView for a context menu and defined our context menu item, we need - to handle the callback when it is selected. For this, we need to identify the list ID of the - selected item, then delete it. So fill in the - onContextItemSelected() method like this:

    -
    -public boolean onContextItemSelected(MenuItem item) {
    -    switch(item.getItemId()) {
    -    case DELETE_ID:
    -        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    -        mDbHelper.deleteNote(info.id);
    -        fillData();
    -        return true;
    -    }
    -    return super.onContextItemSelected(item);
    -}
    -

    Here, we retrieve the {@link android.widget.AdapterView.AdapterContextMenuInfo AdapterContextMenuInfo} -with {@link android.view.MenuItem#getMenuInfo()}. The id field of this object tells us -the position of the item in the ListView. We then pass this to the deleteNote() -method of our NotesDbAdapter and the note is deleted. That's it for the context menu — notes -can now be deleted.

    - -

    Step 4

    - - -

    Fill in the body of the createNote() method: -

    Create a new Intent to create a note - (ACTIVITY_CREATE) using the NoteEdit class. - Then fire the Intent using the startActivityForResult() method - call:

    -
    -Intent i = new Intent(this, NoteEdit.class);
    -startActivityForResult(i, ACTIVITY_CREATE);
    -

    This form of the Intent call targets a specific class in our Activity, in this case - NoteEdit. Since the Intent class will need to communicate with the Android - operating system to route requests, we also have to provide a Context (this).

    -

    The startActivityForResult() method fires the Intent in a way that causes a method - in our Activity to be called when the new Activity is completed. The method in our Activity - that receives the callback is called - onActivityResult() and we will implement it in a later step. The other way - to call an Activity is using startActivity() but this is a "fire-and-forget" way - of calling it — in this manner, our Activity is not informed when the Activity is completed, and there is - no way to return result information from the called Activity with startActivity(). -

    Don't worry about the fact that NoteEdit doesn't exist yet, - we will fix that soon.

    - - - -

    Step 5

    - -

    Fill in the body of the onListItemClick() override.

    -

    onListItemClick() is a callback method that we'll override. It is called when - the user selects an item from the list. It is passed four parameters: the - ListView object it was invoked from, the View - inside the ListView that was clicked on, the - position in the list that was clicked, and the - mRowId of the item that was clicked. In this instance we can - ignore the first two parameters (we only have one ListView it - could be), and we ignore the mRowId as well. All we are - interested in is the position that the user selected. We use - this to get the data from the correct row, and bundle it up to send to - the NoteEdit Activity.

    -

    In our implementation of the callback, the method creates an - Intent to edit the note using - the NoteEdit class. It then adds data into the extras Bundle of - the Intent, which will be passed to the called Activity. We use it - to pass in the title and body text, and the mRowId for the note we are - editing. Finally, it will fire the Intent using the - startActivityForResult() method call. Here's the code that - belongs in onListItemClick():

    -
    -super.onListItemClick(l, v, position, id);
    -Cursor c = mNotesCursor;
    -c.moveToPosition(position);
    -Intent i = new Intent(this, NoteEdit.class);
    -i.putExtra(NotesDbAdapter.KEY_ROWID, id);
    -i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
    -        c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
    -i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
    -        c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
    -startActivityForResult(i, ACTIVITY_EDIT);
    -
      -
    • - putExtra() is the method to add items into the extras Bundle - to pass in to intent invocations. Here, we are - using the Bundle to pass in the title, body and mRowId of the note we want to edit. -
    • -
    • - The details of the note are pulled out from our query Cursor, which we move to the - proper position for the element that was selected in the list, with - the moveToPosition() method.
    • -
    • With the extras added to the Intent, we invoke the Intent on the - NoteEdit class by passing startActivityForResult() - the Intent and the request code. (The request code will be - returned to onActivityResult as the requestCode parameter.)
    • -
    -

    Note: We assign the mNotesCursor field to a local variable at the - start of the method. This is done as an optimization of the Android code. Accessing a local - variable is much more efficient than accessing a field in the Dalvik VM, so by doing this - we make only one access to the field, and five accesses to the local variable, making the - routine much more efficient. It is recommended that you use this optimization when possible.

    - - -

    Step 6

    - -

    The above createNote() and onListItemClick() - methods use an asynchronous Intent invocation. We need a handler for the callback, so here we fill - in the body of the onActivityResult().

    -

    onActivityResult() is the overridden method - which will be called when an Activity returns with a result. (Remember, an Activity - will only return a result if launched with startActivityForResult.) The parameters provided - to the callback are:

    -
      -
    • requestCode — the original request code - specified in the Intent invocation (either ACTIVITY_CREATE or - ACTIVITY_EDIT for us). -
    • -
    • resultCode — the result (or error code) of the call, this - should be zero if everything was OK, but may have a non-zero code indicating - that something failed. There are standard result codes available, and you - can also create your own constants to indicate specific problems. -
    • -
    • intent — this is an Intent created by the Activity returning - results. It can be used to return data in the Intent "extras." -
    • -
    -

    The combination of startActivityForResult() and - onActivityResult() can be thought of as an asynchronous RPC - (remote procedure call) and forms the recommended way for an Activity to invoke - another and share services.

    -

    Here's the code that belongs in your onActivityResult():

    -
    -super.onActivityResult(requestCode, resultCode, intent);
    -Bundle extras = intent.getExtras();
    -
    -switch(requestCode) {
    -case ACTIVITY_CREATE:
    -    String title = extras.getString(NotesDbAdapter.KEY_TITLE);
    -    String body = extras.getString(NotesDbAdapter.KEY_BODY);
    -    mDbHelper.createNote(title, body);
    -    fillData();
    -    break;
    -case ACTIVITY_EDIT:
    -    Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
    -    if (mRowId != null) {
    -        String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
    -        String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
    -        mDbHelper.updateNote(mRowId, editTitle, editBody);
    -    }
    -    fillData();
    -    break;
    -}
    - -
      -
    • - We are handling both the ACTIVITY_CREATE and - ACTIVITY_EDIT activity results in this method. -
    • -
    • - In the case of a create, we pull the title and body from the extras (retrieved from the - returned Intent) and use them to create a new note. -
    • -
    • - In the case of an edit, we pull the mRowId as well, and use that to update - the note in the database. -
    • -
    • - fillData() at the end ensures everything is up to date . -
    • -
    - - -

    Step 7

    - - - -

    Open the file note_edit.xml that has been provided and take a - look at it. This is the UI code for the Note Editor.

    -

    This is the most - sophisticated UI we have dealt with yet. The file is given to you to avoid - problems that may sneak in when typing the code. (The XML is very strict - about case sensitivity and structure, mistakes in these are the usual cause - of problems with layout.)

    -

    There is a new parameter used - here that we haven't seen before: android:layout_weight (in - this case set to use the value 1 in each case).

    -

    layout_weight is used in LinearLayouts - to assign "importance" to Views within the layout. All Views have a default - layout_weight of zero, meaning they take up only as much room - on the screen as they need to be displayed. Assigning a value higher than - zero will split up the rest of the available space in the parent View, according - to the value of each View's layout_weight and its ratio to the - overall layout_weight specified in the current layout for this - and other View elements.

    -

    To give an example: let's say we have a text label - and two text edit elements in a horizontal row. The label has no - layout_weight specified, so it takes up the minimum space - required to render. If the layout_weight of each of the two - text edit elements is set to 1, the remaining width in the parent layout will - be split equally between them (because we claim they are equally important). - If the first one has a layout_weight of 1 - and the second has a layout_weight of 2, then one third of the - remaining space will be given to the first, and two thirds to the - second (because we claim the second one is more important).

    -

    This layout also demonstrates how to nest multiple layouts - inside each other to achieve a more complex and pleasant layout. In this - example, a horizontal linear layout is nested inside the vertical one to - allow the title label and text field to be alongside each other, - horizontally.

    - - -

    Step 8

    - -

    Create a NoteEdit class that extends - android.app.Activity.

    -

    This is the first time we will have - created an Activity without the Android Eclipse plugin doing it for us. When - you do so, the onCreate() method is not automatically - overridden for you. It is hard to imagine an Activity that doesn't override - the onCreate() method, so this should be the first thing you do.

    -
      -
    1. Right click on the com.android.demo.notepad2 package - in the Package Explorer, and select New > Class from the popup - menu.
    2. -
    3. Fill in NoteEdit for the Name: field in the - dialog.
    4. -
    5. In the Superclass: field, enter - android.app.Activity (you can also just type Activity and hit - Ctrl-Space on Windows and Linux or Cmd-Space on the Mac, to invoke code - assist and find the right package and class).
    6. -
    7. Click Finish.
    8. -
    9. In the resulting NoteEdit class, right click in the editor - window and select Source > Override/Implement Methods...
    10. -
    11. Scroll down through the checklist in the dialog until you see - onCreate(Bundle) — and check the box next to it.
    12. -
    13. Click OK.

      The method should now appear in your class.

    14. -
    - -

    Step 9

    - -

    Fill in the body of the onCreate() method for NoteEdit.

    - -

    This will set the title of our new Activity to say "Edit Note" (one - of the strings defined in strings.xml). It will also set the - content view to use our note_edit.xml layout file. We can then - grab handles to the title and body text edit views, and the confirm button, - so that our class can use them to set and get the note title and body, - and attach an event to the confirm button for when it is pressed by the - user.

    -

    We can then unbundle the values that were passed in to the Activity - with the extras Bundle attached to the calling Intent. We'll use them to pre-populate - the title and body text edit views so that the user can edit them. - Then we will grab and store the mRowId so we can keep - track of what note the user is editing.

    - -
      -
    1. - Inside onCreate(), set up the layout:
      -
      setContentView(R.layout.note_edit);
      -
    2. -
    3. - Find the edit and button components we need: -

      These are found by the - IDs associated to them in the R class, and need to be cast to the right - type of View (EditText for the two text views, - and Button for the confirm button):

      -
      -mTitleText = (EditText) findViewById(R.id.title);
      -mBodyText = (EditText) findViewById(R.id.body);
      -Button confirmButton = (Button) findViewById(R.id.confirm);
      -

      Note that mTitleText and mBodyText are member - fields (you need to declare them at the top of the class definition).

      -
    4. -
    5. At the top of the class, declare a Long mRowId private field to store - the current mRowId being edited (if any). -
    6. -
    7. Continuing inside onCreate(), - add code to initialize the title, body and - mRowId from the extras Bundle in - the Intent (if it is present):
      -
      -mRowId = null;
      -Bundle extras = getIntent().getExtras();
      -if (extras != null) {
      -    String title = extras.getString(NotesDbAdapter.KEY_TITLE);
      -    String body = extras.getString(NotesDbAdapter.KEY_BODY);
      -    mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
      -
      -    if (title != null) {
      -        mTitleText.setText(title);
      -    }
      -    if (body != null) {
      -        mBodyText.setText(body);
      -    }
      -}
      -
        -
      • - We are pulling the title and - body out of the - extras Bundle that was set from the - Intent invocation. -
      • - We also null-protect the text field setting (i.e., we don't want to set - the text fields to null accidentally).
      • -
      -
    8. -
    9. - Create an onClickListener() for the button: -

      Listeners can be one of the more confusing aspects of UI - implementation, but - what we are trying to achieve in this case is simple. We want an - onClick() method to be called when the user presses the - confirm button, and use that to do some work and return the values - of the edited note to the Intent caller. We do this using something called - an anonymous inner class. This is a bit confusing to look at unless you - have seen them before, but all you really need to take away from this is - that you can refer to this code in the future to see how to create a - listener and attach it to a button. (Listeners are a common idiom - in Java development, particularly for user interfaces.) Here's the empty listener:
      -

      -confirmButton.setOnClickListener(new View.OnClickListener() {
      -
      -    public void onClick(View view) {
      -
      -    }
      -
      -});
      -
    10. -
    -

    Step 10

    - -

    Fill in the body of the onClick() method of the OnClickListener created in the last step.

    - -

    This is the code that will be run when the user clicks on the - confirm button. We want this to grab the title and body text from the edit - text fields, and put them into the return Bundle so that they can be passed - back to the Activity that invoked this NoteEdit Activity. If the - operation is an edit rather than a create, we also want to put the - mRowId into the Bundle so that the - Notepadv2 class can save the changes back to the correct - note.

    -
      -
    1. - Create a Bundle and put the title and body text into it using the - constants defined in Notepadv2 as keys:
      -
      -Bundle bundle = new Bundle();
      -
      -bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
      -bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
      -if (mRowId != null) {
      -    bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
      -}
      -
    2. -
    3. - Set the result information (the Bundle) in a new Intent and finish the Activity: -
      -Intent mIntent = new Intent();
      -mIntent.putExtras(bundle);
      -setResult(RESULT_OK, mIntent);
      -finish();
      -
        -
      • The Intent is simply our data carrier that carries our Bundle - (with the title, body and mRowId).
      • -
      • The setResult() method is used to set the result - code and return Intent to be passed back to the - Intent caller. In this case everything worked, so we return RESULT_OK for the - result code.
      • -
      • The finish() call is used to signal that the Activity - is done (like a return call). Anything set in the Result will then be - returned to the caller, along with execution control.
      • -
      -
    4. -
    -

    The full onCreate() method (plus supporting class fields) should - now look like this:

    -
    -private EditText mTitleText;
    -private EditText mBodyText;
    -private Long mRowId;
    -
    -@Override
    -protected void onCreate(Bundle savedInstanceState) {
    -    super.onCreate(savedInstanceState);
    -    setContentView(R.layout.note_edit);
    -
    -    mTitleText = (EditText) findViewById(R.id.title);
    -    mBodyText = (EditText) findViewById(R.id.body);
    -
    -    Button confirmButton = (Button) findViewById(R.id.confirm);
    -
    -    mRowId = null;
    -    Bundle extras = getIntent().getExtras();
    -    if (extras != null) {
    -        String title = extras.getString(NotesDbAdapter.KEY_TITLE);
    -        String body = extras.getString(NotesDbAdapter.KEY_BODY);
    -        mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
    -
    -        if (title != null) {
    -            mTitleText.setText(title);
    -        }
    -        if (body != null) {
    -            mBodyText.setText(body);
    -        }
    -    }
    -
    -    confirmButton.setOnClickListener(new View.OnClickListener() {
    -
    -        public void onClick(View view) {
    -            Bundle bundle = new Bundle();
    -
    -            bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
    -            bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
    -            if (mRowId != null) {
    -                bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
    -            }
    -
    -            Intent mIntent = new Intent();
    -            mIntent.putExtras(bundle);
    -            setResult(RESULT_OK, mIntent);
    -            finish();
    -        }
    -    });
    -}
    - - - -

    Step 11

    - - - -

    Finally, the new Activity has to be defined in the manifest file:

    -

    Before the new Activity can be seen by Android, it needs its own - Activity entry in the AndroidManifest.xml file. This is to let - the system know that it is there and can be called. We could also specify - which IntentFilters the activity implements here, but we are going to skip - this for now and just let Android know that the Activity is - defined.

    -

    There is a Manifest editor included in the Eclipse plugin that makes it much easier - to edit the AndroidManifest file, and we will use this. If you prefer to edit the file directly - or are not using the Eclipse plugin, see the box at the end for information on how to do this - without using the new Manifest editor.

    -

      -
    1. Double click on the AndroidManifest.xml file in the package explorer to open it. -
    2. -
    3. Click the Application tab at the bottom of the Manifest editor.
    4. -
    5. Click Add... in the Application Nodes section. -

      If you see a dialog with radiobuttons at the top, select the top radio button: - "Create a new element at the top level, in Application".

    6. -
    7. Make sure "(A) Activity" is selected in the selection pane of the dialog, and click OK.
    8. -
    9. Click on the new "Activity" node, in the Application Nodes section, then - type .NoteEdit into the Name* - field to the right. Press Return/Enter.
    10. -
    -

    The Android Manifest editor helps you add more complex entries into the AndroidManifest.xml - file, have a look around at some of the other options available (but be careful not to select - them otherwise they will be added to your Manifest). This editor should help you understand - and alter the AndroidManifest.xml file as you move on to more advanced Android applications.

    - -

    If you prefer to edit this file directly, simply open the - AndroidManifest.xml file and look at the source (use the - AndroidManifest.xml tab in the eclipse editor to see the source code directly). - Then edit the file as follows:
    - <activity android:name=".NoteEdit" />

    - This should be placed just below the line that reads:
    - </activity> for the .Notepadv2 activity.

    - -

    Step 12

    - -

    Now Run it!

    -

    You should now be able to add real notes from -the menu, as well as delete an existing one. Notice that in order to delete, you must -first use the directional controls on the device to highlight the note. -Furthermore, selecting a note title from the list should bring up the note -editor to let you edit it. Press confirm when finished to save the changes -back to the database. - -

    Solution and Next Steps

    - -

    You can see the solution to this exercise in Notepadv2Solution -from the zip file to compare with your own.

    -

    Now try editing a note, and then hitting the back button on the emulator -instead of the confirm button (the back button is below the menu button). You -will see an error come up. Clearly our application still has some problems. -Worse still, if you did make some changes and hit the back button, when you go -back into the notepad to look at the note you changed, you will find that all -your changes have been lost. In the next exercise we will fix these -problems.

    - -

    -Once you are ready, move on to Tutorial -Exercise 3 where you will fix the problems with the back button and lost -edits by introducing a proper life cycle into the NoteEdit Activity.

    - - diff --git a/docs/html/guide/tutorials/notepad/notepad-ex3.jd b/docs/html/guide/tutorials/notepad/notepad-ex3.jd deleted file mode 100644 index 557738e4c105b9c6c1ef2c5d02358f1980f6a297..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/notepad/notepad-ex3.jd +++ /dev/null @@ -1,366 +0,0 @@ -page.title=Notepad Exercise 3 -parent.title=Notepad Tutorial -parent.link=index.html -@jd:body - - -

    In this exercise, you will use life-cycle event callbacks to store and -retrieve application state data. This exercise demonstrates:

    -
      -
    • Life-cycle events and how your application can use them
    • -
    • Techniques for maintaining application state
    • -
    - - - -

    Step 1

    - -

    Import Notepadv3 into Eclipse. If you see an error about -AndroidManifest.xml, or some problems related to an Android zip -file, right click on the project and select Android Tools > -Fix Project Properties from the popup menu. The starting point for this exercise is -exactly where we left off at the end of the Notepadv2.

    -

    The current application has some problems — hitting the back button when editing -causes a crash, and anything else that happens during editing will cause the -edits to be lost.

    -

    To fix this, we will move most of the functionality for creating and editing -the note into the NoteEdit class, and introduce a full life cycle for editing -notes.

    - -
      -
    1. Remove the code in NoteEdit that parses the title and body - from the extras Bundle. -

      Instead, we are going to use the DBHelper class - to access the notes from the database directly. All we need passed into the - NoteEdit Activity is a mRowId (but only if we are editing, if creating we pass - nothing). Remove these lines:

      -
      -String title = extras.getString(NotesDbAdapter.KEY_TITLE);
      -String body = extras.getString(NotesDbAdapter.KEY_BODY);
      -
    2. -
    3. We will also get rid of the properties that were being passed in - the extras Bundle, which we were using to set the title - and body text edit values in the UI. So delete: -
      -if (title != null) {
      -    mTitleText.setText(title);
      -}
      -if (body != null) {
      -    mBodyText.setText(body);
      -}
      -
    4. -
    - -

    Step 2

    - -

    Create a class field for a NotesDbAdapter at the top of the NoteEdit class:

    -
        private NotesDbAdapter mDbHelper;
    -

    Also add an instance of NotesDbAdapter in the - onCreate() method (right below the super.onCreate() call):

    -
    -    mDbHelper = new NotesDbAdapter(this);
    -    mDbHelper.open();
    - -

    Step 3

    - -

    In NoteEdit, we need to check the savedInstanceState for the -mRowId, in case the note - editing contains a saved state in the Bundle, which we should recover (this would happen - if our Activity lost focus and then restarted).

    -
      -
    1. - Replace the code that currently initializes the mRowId:
      -
      -        mRowId = null;
      -
      -        Bundle extras = getIntent().getExtras();
      -        if (extras != null) {
      -            mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
      -        }
      -        
      - with this: -
      -        mRowId = (savedInstanceState == null) ? null :
      -            (Long) savedInstanceState.getSerializable(NotesDbAdapter.KEY_ROWID);
      -        if (mRowId == null) {
      -            Bundle extras = getIntent().getExtras();
      -            mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID)
      -                                    : null;
      -        }
      -        
      -
    2. -
    3. - Note the null check for savedInstanceState, and we still need to load up - mRowId from the extras Bundle if it is not - provided by the savedInstanceState. This is a ternary operator shorthand - to safely either use the value or null if it is not present. -
    4. -
    5. - Note the use of Bundle.getSerializable() instead of - Bundle.getLong(). The latter encoding returns a long primitive and - so can not be used to represent the case when mRowId is null. -
    6. -
    - -

    Step 4

    - -

    Next, we need to populate the fields based on the mRowId if we - have it:

    -
    populateFields();
    -

    This goes before the confirmButton.setOnClickListener() line. - We'll define this method in a moment.

    - -

    Step 5

    - -

    Get rid of the Bundle creation and Bundle value settings from the - onClick() handler method. The Activity no longer needs to - return any extra information to the caller. And because we no longer have - an Intent to return, we'll use the shorter version - of setResult():

    -
    -public void onClick(View view) {
    -    setResult(RESULT_OK);
    -    finish();
    -}
    -

    We will take care of storing the updates or new notes in the database - ourselves, using the life-cycle methods.

    - -

    The whole onCreate() method should now look like this:

    -
    -super.onCreate(savedInstanceState);
    -
    -mDbHelper = new NotesDbAdapter(this);
    -mDbHelper.open();
    -
    -setContentView(R.layout.note_edit);
    -
    -mTitleText = (EditText) findViewById(R.id.title);
    -mBodyText = (EditText) findViewById(R.id.body);
    -
    -Button confirmButton = (Button) findViewById(R.id.confirm);
    -
    -mRowId = (savedInstanceState == null) ? null :
    -    (Long) savedInstanceState.getSerializable(NotesDbAdapter.KEY_ROWID);
    -if (mRowId == null) {
    -    Bundle extras = getIntent().getExtras();
    -    mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID)
    -                            : null;
    -}
    -
    -populateFields();
    -
    -confirmButton.setOnClickListener(new View.OnClickListener() {
    -
    -    public void onClick(View view) {
    -        setResult(RESULT_OK);
    -        finish();
    -    }
    -
    -});
    - -

    Step 6

    - -

    Define the populateFields() method.

    -
    -private void populateFields() {
    -    if (mRowId != null) {
    -        Cursor note = mDbHelper.fetchNote(mRowId);
    -        startManagingCursor(note);
    -        mTitleText.setText(note.getString(
    -	            note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
    -        mBodyText.setText(note.getString(
    -                note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
    -    }
    -}
    -

    This method uses the NotesDbAdapter.fetchNote() method to find the right note to -edit, then it calls startManagingCursor() from the Activity class, which -is an Android convenience method provided to take care of the Cursor life-cycle. This will release -and re-create resources as dictated by the Activity life-cycle, so we don't need to worry about -doing that ourselves. After that, we just look up the title and body values from the Cursor -and populate the View elements with them.

    - - -

    Step 7

    - - - -

    Still in the NoteEdit class, we now override the methods - onSaveInstanceState(), onPause() and - onResume(). These are our life-cycle methods - (along with onCreate() which we already have).

    - -

    onSaveInstanceState() is called by Android if the - Activity is being stopped and may be killed before it is - resumed! This means it should store any state necessary to - re-initialize to the same condition when the Activity is restarted. It is - the counterpart to the onCreate() method, and in fact the - savedInstanceState Bundle passed in to onCreate() is the same - Bundle that you construct as outState in the - onSaveInstanceState() method.

    - -

    onPause() and onResume() are also - complimentary methods. onPause() is always called when the - Activity ends, even if we instigated that (with a finish() call for example). - We will use this to save the current note back to the database. Good - practice is to release any resources that can be released during an - onPause() as well, to take up less resources when in the - passive state. onResume() will call our populateFields() method - to read the note out of the database again and populate the fields.

    - -

    So, add some space after the populateFields() method - and add the following life-cycle methods:

    -
      -
    1. - onSaveInstanceState(): -
      -    @Override
      -    protected void onSaveInstanceState(Bundle outState) {
      -        super.onSaveInstanceState(outState);
      -        saveState();
      -        outState.putSerializable(NotesDbAdapter.KEY_ROWID, mRowId);
      -    }
      -

      We'll define saveState() next.

      -
    2. -
    3. - onPause(): -
      -    @Override
      -    protected void onPause() {
      -        super.onPause();
      -        saveState();
      -    }
      -
    4. -
    5. - onResume(): -
      -    @Override
      -    protected void onResume() {
      -        super.onResume();
      -        populateFields();
      -    }
      -
    6. -
    -

    Note that saveState() must be called in both onSaveInstanceState() -and onPause() to ensure that the data is saved. This is because there is no -guarantee that onSaveInstanceState() will be called and because when it is -called, it is called before onPause().

    - - -

    Step 8

    - -

    Define the saveState() method to put the data out to the -database.

    -
    -     private void saveState() {
    -        String title = mTitleText.getText().toString();
    -        String body = mBodyText.getText().toString();
    -
    -        if (mRowId == null) {
    -            long id = mDbHelper.createNote(title, body);
    -            if (id > 0) {
    -                mRowId = id;
    -            }
    -        } else {
    -            mDbHelper.updateNote(mRowId, title, body);
    -        }
    -    }
    -

    Note that we capture the return value from createNote() and if a valid row ID is - returned, we store it in the mRowId field so that we can update the note in future - rather than create a new one (which otherwise might happen if the life-cycle events are - triggered).

    - - -

    Step 9

    - -

    Now pull out the previous handling code from the - onActivityResult() method in the Notepadv3 - class.

    -

    All of the note retrieval and updating now happens within the - NoteEdit life cycle, so all the onActivityResult() - method needs to do is update its view of the data, no other work is - necessary. The resulting method should look like this:

    -
    -@Override
    -protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    -    super.onActivityResult(requestCode, resultCode, intent);
    -    fillData();
    -}
    - -

    Because the other class now does the work, all this has to do is refresh - the data.

    - -

    Step 10

    - -

    Also remove the lines which set the title and body from the - onListItemClick() method (again they are no longer needed, - only the mRowId is):

    -
    -    Cursor c = mNotesCursor;
    -    c.moveToPosition(position);
    -
    -and also remove: -
    -
    -    i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
    -                    c.getColumnIndex(NotesDbAdapter.KEY_TITLE)));
    -    i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
    -                    c.getColumnIndex(NotesDbAdapter.KEY_BODY)));
    -
    -so that all that should be left in that method is: -
    -
    -    super.onListItemClick(l, v, position, id);
    -    Intent i = new Intent(this, NoteEdit.class);
    -    i.putExtra(NotesDbAdapter.KEY_ROWID, id);
    -    startActivityForResult(i, ACTIVITY_EDIT);
    - -

    You can also now remove the mNotesCursor field from the class, and set it back to using - a local variable in the fillData() method: -

    -    Cursor notesCursor = mDbHelper.fetchAllNotes();

    -

    Note that the m in mNotesCursor denotes a member field, so when we - make notesCursor a local variable, we drop the m. Remember to rename the - other occurrences of mNotesCursor in your fillData() method. - -

    -Run it! (use Run As -> Android Application on the project right -click menu again)

    - -

    Solution and Next Steps

    - -

    You can see the solution to this exercise in Notepadv3Solution -from -the zip file to compare with your own.

    -

    -When you are ready, move on to the Tutorial -Extra Credit exercise, where you can use the Eclipse debugger to -examine the life-cycle events as they happen.

    diff --git a/docs/html/guide/tutorials/notepad/notepad-extra-credit.jd b/docs/html/guide/tutorials/notepad/notepad-extra-credit.jd deleted file mode 100644 index 34f7063dfa01d1b6267142afaaf4b5abe532c279..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/notepad/notepad-extra-credit.jd +++ /dev/null @@ -1,70 +0,0 @@ -page.title=Notepad Extra Credit -parent.title=Notepad Tutorial -parent.link=index.html -@jd:body - - -

    In this exercise, you will use the debugger to look at the work you did -in Exercise 3. This exercise demonstrates:

    -
      -
    • How to set breakpoints to observe execution
    • -
    • How to run your application in debug mode
    • -
    - -
    - - [Exercise 1] - [Exercise 2] - [Exercise 3] - - [Extra Credit] - -
    - -

    Step 1

    - -

    Using the working Notepadv3, put breakpoints in the code at the - beginning of the onCreate(), onPause(), - onSaveInstanceState() and onResume() methods in the - NoteEdit class (if you are not familiar with Eclipse, just - right click in the narrow grey border on the left of the edit window at the - line you want a breakpoint, and select Toggle Breakpoint, you -should see a blue dot appear).

    - -

    Step 2

    - -

    Now start the notepad demo in debug mode:

    - -
      -
    1. - Right click on the Notepadv3 project and from the Debug menu - select Debug As -> Android Application.
    2. -
    3. - The Android emulator should say "waiting for debugger to connect" - briefly and then run the application.
    4. -
    5. - If it gets stuck on the waiting... screen, quit the emulator and Eclipse, - from the command line do an adb kill-server, and then restart -Eclipse and try again.
    - -

    Step 3

    - -

    When you edit or create a new note you should see the breakpoints getting - hit and the execution stopping.

    - -

    Step 4

    - -

    Hit the Resume button to let execution continue (yellow rectangle with a -green triangle to its right in the Eclipse toolbars near the top).

    - -

    Step 5

    - -

    Experiment a bit with the confirm and back buttons, and try pressing Home and - making other mode changes. Watch what life-cycle events are generated and -when.

    - -

    The Android Eclipse plugin not only offers excellent debugging support for -your application development, but also superb profiling support. You can also -try using Traceview to profile your application. If your application is running too slow, this can help you -find the bottlenecks and fix them.

    - diff --git a/docs/html/guide/tutorials/notepad/notepad-index.jd b/docs/html/guide/tutorials/notepad/notepad-index.jd deleted file mode 100644 index 151c50dcda674aac98c42ab54caea2fd54396254..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/notepad/notepad-index.jd +++ /dev/null @@ -1,143 +0,0 @@ -page.title=Notepad Tutorial -@jd:body - - -

    The tutorial in this section gives you a "hands-on" introduction -to the Android framework and the tools you use to build applications on it. -Starting from a preconfigured project file, it guides you through the process of -developing a simple notepad application and provides concrete examples of how to -set up the project, develop the application logic and user interface, and then -compile and run the application.

    - -

    The tutorial presents the notepad application development as a set of -exercises (see below), each consisting of several steps. You can follow along -with the steps in each exercise and gradually build up and refine your -application. The exercises explain each step in detail and provide all the -sample code you need to complete the application.

    - -

    When you are finished with the tutorial, you will have created a functioning -Android application and learned in depth about many of the most important -concepts in Android development. If you want to add more complex features to -your application, you can examine the code in an alternative implementation -of a notepad application, in the -Sample Code documentation.

    - - - -

    Who Should Use this Tutorial

    - -

    This tutorial is designed for experienced developers, especially those with -knowledge of the Java programming language. If you haven't written Java -applications before, you can still use the tutorial, but you might need to work -at a slower pace.

    - -

    The tutorial assumes that you have some familiarity with the basic Android -application concepts and terminology. If you aren't yet familiar with those, you -should read Overview of an Android -Application before continuing.

    - -

    Also note that this tutorial uses -the Eclipse development environment, with the Android plugin installed. If you -are not using Eclipse, you can follow the exercises and build the application, -but you will need to determine how to accomplish the Eclipse-specific -steps in your environment.

    - - -

    Preparing for the Exercises

    - -

    This tutorial builds on the information provided in the Installing the SDK and Hello Android -documents, which explain in detail how to set up your development environment -for building Android applications. Before you start this tutorial, you should -read both these documents, have the SDK installed, and your work environment set up.

    - -

    To prepare for this lesson:

    - -
      -
    1. Download the project - exercises archive (.zip)
    2. -
    3. Unpack the archive file to a suitable location on your machine
    4. -
    5. Open the NotepadCodeLab folder
    6. -
    - -

    Inside the NotepadCodeLab folder, you should see six project -files: Notepadv1, - Notepadv2, Notepadv3, - Notepadv1Solution, Notepadv2Solution - and Notepadv3Solution. The Notepadv# projects are -the starting points for each of the exercises, while the -Notepadv#Solution projects are the exercise - solutions. If you are having trouble with a particular exercise, you - can compare your current work against the exercise solution.

    - - -

    Exercises

    - -

    The table below lists the tutorial exercises and describes the development -areas that each covers. Each exercise assumes that you have completed any -previous exercises.

    - - - - - - - - - - - - - - - - - - -
    Exercise -1Start here. Construct a simple notes list that lets the user add new notes but not -edit them. Demonstrates the basics of ListActivity and creating -and handling - menu options. Uses a SQLite database to store the notes.
    Exercise 2Add a second Activity to the -application. Demonstrates constructing a -new Activity, adding it to the Android manifest, passing data between the -activities, and using more advanced screen layout. Also shows how to -invoke another Activity to return a result, using -startActivityForResult().
    Exercise 3Add handling of life-cycle events to -the application, to let it -maintain application state across the life cycle.
    Extra -CreditDemonstrates how to use the Eclipse -debugger and how you can use it to -view life-cycle events as they are generated. This section is optional but -highly recommended.
    - - - -

    Other Resources and Further Learning

    -
      -
    • For a lighter but broader introduction to concepts not covered in the -tutorial, -take a look at Common Android Tasks.
    • -
    • The Android SDK includes a variety of fully functioning sample applications -that make excellent opportunities for further learning. You can find the sample -applications in the samples/ directory of your downloaded SDK.
    • -
    • This tutorial draws from the full Notepad application included in the -samples/ directory of the SDK, though it does not match it exactly. -When you are done with the tutorial, -it is highly recommended that you take a closer look at this version of the Notepad -application, -as it demonstrates a variety of interesting additions for your application, -such as:
    • -
        -
      • Setting up a custom striped list for the list of notes.
      • -
      • Creating a custom text edit view that overrides the draw() -method to - make it look like a lined notepad.
      • -
      • Implementing a full ContentProvider for notes.
      • -
      • Reverting and discarding edits instead of just automatically saving -them.
      • -
      -
    diff --git a/docs/html/guide/tutorials/views/hello-autocomplete.jd b/docs/html/guide/tutorials/views/hello-autocomplete.jd deleted file mode 100644 index 07235a14ab48b95b06b599772397f1afbadcc257..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-autocomplete.jd +++ /dev/null @@ -1,116 +0,0 @@ -page.title=Hello, AutoCompleteTextView -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    {@link android.widget.AutoCompleteTextView} is an implementation of the EditText widget that will provide -auto-complete suggestions as the user types. The suggestions are extracted from a collection of strings.

    - - -
      -
    1. Start a new project/Activity called HelloAutoComplete.
    2. -
    3. Open the layout file. - Make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      -    android:orientation="horizontal"
      -    android:layout_width="fill_parent" 
      -    android:layout_height="wrap_content">
      -
      -    <TextView
      -        android:layout_width="wrap_content"
      -        android:layout_height="wrap_content"
      -        android:text="Country" />
      -
      -    <AutoCompleteTextView android:id="@+id/edit"
      -        android:layout_width="fill_parent"
      -        android:layout_height="wrap_content"/>
      -
      -</LinearLayout>
      -
      -
    4. - -
    5. Open HelloAutoComplete.java and insert the following as the onCreate method: -
      -@Override
      -protected void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -
      -    AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit);
      -    ArrayAdapter adapter = new ArrayAdapter(this,
      -            android.R.layout.simple_dropdown_item_1line, COUNTRIES);
      -    textView.setAdapter(adapter);
      -}
      -
      -

      Here, we create an AutoCompleteTextView from our layout. We then - create an {@link android.widget.ArrayAdapter} that binds a simple_dropdown_item_1line - layout item to each entry in the COUNTRIES array (which we'll add next). - The last part sets the ArrayAdapter to associate with our AutoCompleteTextView.

      -
    6. - -
    7. After the onCreate() method, add the String array: -
      -static final String[] COUNTRIES = new String[] {
      -  "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
      -  "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
      -  "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
      -  "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
      -  "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
      -  "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",
      -  "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
      -  "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
      -  "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
      -  "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
      -  "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
      -  "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
      -  "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
      -  "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
      -  "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
      -  "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
      -  "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
      -  "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
      -  "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
      -  "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
      -  "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
      -  "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
      -  "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
      -  "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
      -  "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
      -  "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
      -  "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
      -  "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
      -  "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
      -  "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
      -  "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
      -  "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
      -  "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
      -  "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
      -  "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
      -  "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
      -  "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
      -  "Ukraine", "United Arab Emirates", "United Kingdom",
      -  "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
      -  "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
      -  "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
      -};
      -
      -

      This is the list of suggestions that will be offered as the user types into the - AutoCompleteTextView.

      -
    8. - -
    9. Now run it.
    10. -
    -

    As you type, you should see something like this:

    - - - -

    References

    -
      -
    • {@link android.R.layout}
    • -
    • {@link android.widget.ArrayAdapter}
    • -
    • {@link android.widget.AutoCompleteTextView}
    • -
    - - diff --git a/docs/html/guide/tutorials/views/hello-datepicker.jd b/docs/html/guide/tutorials/views/hello-datepicker.jd deleted file mode 100644 index fcd43f3f890f36550080fad78b2d1d74241780e8..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-datepicker.jd +++ /dev/null @@ -1,151 +0,0 @@ -page.title=Hello, DatePicker -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.DatePicker} is a widget that allows the user to select a month, day and year.

    - - -
      -
    1. Start a new project/Activity called HelloDatePicker.
    2. -
    3. Open the layout file and make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:layout_width="wrap_content"
      -    android:layout_height="wrap_content"
      -    android:orientation="vertical">
      -
      -    <TextView android:id="@+id/dateDisplay"
      -            android:layout_width="wrap_content"
      -            android:layout_height="wrap_content"
      -            android:text=""/>
      -
      -    <Button android:id="@+id/pickDate"
      -            android:layout_width="wrap_content"
      -            android:layout_height="wrap_content"
      -            android:text="Change the date"/>
      -
      -</LinearLayout>
      -
      -

      For the layout, we're using a vertical LinearLayout, with a {@link android.widget.TextView} that - will display the date and a {@link android.widget.Button} that will initiate the DatePicker dialog. - With this layout, the TextView will sit above the Button. - The text value in the TextView is set empty, as it will be filled - with the current date when our Activity runs.

      -
    4. - -
    5. Open HelloDatePicker.java. Insert the following to the HelloDatePicker class: -
      -    private TextView mDateDisplay;
      -    private Button mPickDate;
      -
      -    private int mYear;
      -    private int mMonth;
      -    private int mDay;
      -
      -    static final int DATE_DIALOG_ID = 0;
      -
      -    @Override
      -    protected void onCreate(Bundle savedInstanceState) {
      -        super.onCreate(savedInstanceState);
      -        setContentView(R.layout.main);
      -
      -        // capture our View elements
      -        mDateDisplay = (TextView) findViewById(R.id.dateDisplay);
      -        mPickDate = (Button) findViewById(R.id.pickDate);
      -
      -        // add a click listener to the button
      -        mPickDate.setOnClickListener(new View.OnClickListener() {
      -            public void onClick(View v) {
      -                showDialog(DATE_DIALOG_ID);
      -            }
      -        });
      -
      -        // get the current date
      -        final Calendar c = Calendar.getInstance();
      -        mYear = c.get(Calendar.YEAR);
      -        mMonth = c.get(Calendar.MONTH);
      -        mDay = c.get(Calendar.DAY_OF_MONTH);
      -
      -        // display the current date
      -        updateDisplay();
      -    }
      -
      -

      Tip: Press Ctrl(or Cmd) + Shift + O to import all needed packages.

      -

      We start by instantiating variables for our Views and date fields. - The DATE_DIALOG_ID is a static integer that uniquely identifies the Dialog. In the - onCreate() method, we get prepared by setting the layout and capturing the View elements. - Then we create an on-click listener for the Button, so that when it is clicked it will - show our DatePicker dialog. The showDialog() method will pop-up the date picker dialog - by calling the onCreateDialog() callback method - (which we'll define in the next section). We then create an - instance of {@link java.util.Calendar} and get the current year, month and day. Finally, we call - updateDisplay()—our own method (defined later) that will fill the TextView.

      -
    6. - -
    7. After the onCreate() method, add the onCreateDialog() callback method -(which is called by showDialog()) -
      -@Override
      -protected Dialog onCreateDialog(int id) {
      -    switch (id) {
      -    case DATE_DIALOG_ID:
      -        return new DatePickerDialog(this,
      -                    mDateSetListener,
      -                    mYear, mMonth, mDay);
      -    }
      -    return null;
      -}
      -
      -

      This method is passed the identifier we gave showDialog() and initializes - the DatePicker to the date we retrieved from our Calendar instance.

      -
    8. - -
    9. Following that, add the updateDisplay() method: -
      -    // updates the date we display in the TextView
      -    private void updateDisplay() {
      -        mDateDisplay.setText(
      -            new StringBuilder()
      -                    // Month is 0 based so add 1
      -                    .append(mMonth + 1).append("-")
      -                    .append(mDay).append("-")
      -                    .append(mYear).append(" "));
      -    }
      -
      -

      This uses the member date values to write the date to our TextView.

      -
    10. -
    11. Finally, add a listener that will be called when the user sets a new date: -
      -    // the callback received when the user "sets" the date in the dialog
      -    private DatePickerDialog.OnDateSetListener mDateSetListener =
      -            new DatePickerDialog.OnDateSetListener() {
      -
      -                public void onDateSet(DatePicker view, int year, 
      -                                      int monthOfYear, int dayOfMonth) {
      -                    mYear = year;
      -                    mMonth = monthOfYear;
      -                    mDay = dayOfMonth;
      -                    updateDisplay();
      -                }
      -            };
      -
      -

      This OnDateSetListener method listens for when the user is done setting the date - (clicks the "Set" button). At that time, this fires and we update our member fields with - the new date defined by the user and update our TextView by calling updateDisplay().

      -
    12. - -
    13. Now run it.
    14. -
    -

    When you press the "Change the date" button, you should see the following:

    - - -

    References

    -
      -
    • {@link android.widget.DatePicker}
    • -
    • {@link android.widget.Button}
    • -
    • {@link android.widget.TextView}
    • -
    • {@link java.util.Calendar}
    • -
    - diff --git a/docs/html/guide/tutorials/views/hello-formstuff.jd b/docs/html/guide/tutorials/views/hello-formstuff.jd deleted file mode 100644 index b554001b8bf418d930d6be7152f7077c2b9aa04f..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-formstuff.jd +++ /dev/null @@ -1,262 +0,0 @@ -page.title=Hello, Form Stuff -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    This page introduces a variety of widgets, like image buttons, -text fields, checkboxes and radio buttons.

    - - -
      -
    1. Start a new project/Activity called HelloFormStuff.
    2. -
    3. Your layout file should have a basic LinearLayout: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:orientation="vertical"
      -    android:layout_width="fill_parent"
      -    android:layout_height="fill_parent" >
      -    	
      -</LinearLayout>
      -
      -

      For each widget you want to add, just put the respective View inside here.

      -
    4. -
    -

    Tip: As you add new Android code, press Ctrl(or Cmd) + Shift + O -to import all needed packages.

    - - -

    ImageButton

    -

    A button with a custom image on it. -We'll make it display a message when pressed.

    -
      -
    1. - Drag the Android image on the right (or your own image) into the - res/drawable/ directory of your project. - We'll use this for the button.
    2. -
    3. Open the layout file and, inside the LinearLayout, add the {@link android.widget.ImageButton} element: -
      -<ImageButton
      -    android:id="@+id/android_button"
      -    android:layout_width="100dip"
      -    android:layout_height="wrap_content"
      -    android:src="@drawable/android" />	
      -
      -

      The source of the button - is from the res/drawable/ directory, where we've placed the android.png.

      -

      Tip: You can also reference some of the many built-in - images from the Android {@link android.R.drawable} resources, - like ic_media_play, for a "play" button image. To do so, change the source - attribute to android:src="@android:drawable/ic_media_play".

      -
    4. -
    5. To make the button to actually do something, add the following -code at the end of the onCreate() method: -
      -final ImageButton button = (ImageButton) findViewById(R.id.android_button);
      -button.setOnClickListener(new OnClickListener() {
      -    public void onClick(View v) {
      -        // Perform action on clicks
      -        Toast.makeText(HelloFormStuff.this, "Beep Bop", Toast.LENGTH_SHORT).show();
      -    }
      -});
      -
      -

      This captures our ImageButton from the layout, then adds an on-click listener to it. -The {@link android.view.View.OnClickListener} must define the onClick() method, which -defines the action to be made when the button is clicked. Here, we show a -{@link android.widget.Toast} message when clicked.

      -
    6. -
    7. Run it.
    8. -
    - - -

    EditText

    -

    A text field for user input. We'll make it display the text entered so far when the "Enter" key is pressed.

    - -
      -
    1. Open the layout file and, inside the LinearLayout, add the {@link android.widget.EditText} element: -
      -<EditText
      -    android:id="@+id/edittext"
      -    android:layout_width="fill_parent"
      -    android:layout_height="wrap_content"/>
      -
      -
    2. -
    3. To do something with the text that the user enters, add the following code -to the end of the onCreate() method: -
      -final EditText edittext = (EditText) findViewById(R.id.edittext);
      -edittext.setOnKeyListener(new OnKeyListener() {
      -    public boolean onKey(View v, int keyCode, KeyEvent event) {
      -        if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
      -          // Perform action on key press
      -          Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show();
      -          return true;
      -        }
      -        return false;
      -    }
      -});
      -
      -

      This captures our EditText element from the layout, then adds an on-key listener to it. -The {@link android.view.View.OnKeyListener} must define the onKey() method, which -defines the action to be made when a key is pressed. In this case, we want to listen for the -Enter key (when pressed down), then pop up a {@link android.widget.Toast} message with the -text from the EditText field. Be sure to return true after the event is handled, -so that the event doesn't bubble-up and get handled by the View (which would result in a -carriage return in the text field).

      -
    4. Run it.
    5. -
    - - -

    CheckBox

    -

    A checkbox for selecting items. We'll make it display the the current state when pressed.

    - -
      -
    1. Open the layout file and, inside the LinearLayout, add the {@link android.widget.CheckBox} element: -
      -<CheckBox android:id="@+id/checkbox"
      -    android:layout_width="wrap_content"
      -    android:layout_height="wrap_content"
      -    android:text="check it out" />
      -
      -
    2. -
    3. To do something when the state is changed, add the following code -to the end of the onCreate() method: -
      -final CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox);
      -checkbox.setOnClickListener(new OnClickListener() {
      -    public void onClick(View v) {
      -        // Perform action on clicks
      -        if (checkbox.isChecked()) {
      -            Toast.makeText(HelloFormStuff.this, "Selected", Toast.LENGTH_SHORT).show();
      -        } else {
      -            Toast.makeText(HelloFormStuff.this, "Not selected", Toast.LENGTH_SHORT).show();
      -        }
      -    }
      -});
      -
      -

      This captures our CheckBox element from the layout, then adds an on-click listener to it. -The {@link android.view.View.OnClickListener} must define the onClick() method, which -defines the action to be made when the checkbox is clicked. Here, we query the current state of the -checkbox, then pop up a {@link android.widget.Toast} message that displays the current state. -Notice that the CheckBox handles its own state change between checked and un-checked, so we just -ask which it currently is.

      -
    4. Run it.
    5. -
    -

    Tip: If you find that you need to change the state -in another way (such as when loading a saved {@link android.preference.CheckBoxPreference}), -use setChecked(true) or toggle().

    - - -

    RadioButton

    -

    Two mutually-exclusive radio buttons—enabling one disables the other. -When each is pressed, we'll pop up a message.

    - -
      -
    1. Open the layout file and, inside the LinearLayout, add two {@link android.widget.RadioButton}s, -inside a {@link android.widget.RadioGroup}: -
      -<RadioGroup
      -  android:layout_width="fill_parent"
      -  android:layout_height="wrap_content"
      -  android:orientation="vertical">
      -  
      -  <RadioButton android:id="@+id/radio_red"
      -      android:layout_width="wrap_content"
      -      android:layout_height="wrap_content"
      -      android:text="Red" />
      -  
      -  <RadioButton android:id="@+id/radio_blue"
      -      android:layout_width="wrap_content"
      -      android:layout_height="wrap_content"
      -      android:text="Blue" />
      -  
      -</RadioGroup>
      -
      -
    2. -
    3. To do something when each is selected, we'll need an OnClickListener. Unlike the other -listeners we've created, instead of creating this one as an anonymous inner class, -we'll create it as a new object. This way, we can re-use the OnClickListener for -both RadioButtons. So, add the following code in the HelloFormStuff Activity -(outside the onCreate() method): -
      -OnClickListener radio_listener = new OnClickListener() {
      -    public void onClick(View v) {
      -        // Perform action on clicks
      -        RadioButton rb = (RadioButton) v;
      -        Toast.makeText(HelloFormStuff.this, rb.getText(), Toast.LENGTH_SHORT).show();
      -    }
      -};
      -
      -

      Our onClick() method will be handed the View clicked, so the first thing to do -is cast it into a RadioButton. Then we pop up a -{@link android.widget.Toast} message that displays the selection.

      -
    4. Now, at the bottom of the onCreate() method, add the following: -
      -  final RadioButton radio_red = (RadioButton) findViewById(R.id.radio_red);
      -  final RadioButton radio_blue = (RadioButton) findViewById(R.id.radio_blue);
      -  radio_red.setOnClickListener(radio_listener);
      -  radio_blue.setOnClickListener(radio_listener);
      -
      -

      This captures each of the RadioButtons from our layout and adds the newly-created -OnClickListener to each.

      -
    5. Run it.
    6. -
    -

    Tip: If you find that you need to change the state of a -RadioButton in another way (such as when loading a saved {@link android.preference.CheckBoxPreference}), -use setChecked(true) or toggle().

    - - -

    ToggleButton

    -

    A button used specifically for toggling something on and off.

    - -
      -
    1. Open the layout file and, inside the LinearLayout, add the {@link android.widget.ToggleButton} element: -
      -<ToggleButton android:id="@+id/togglebutton"
      -    android:layout_width="wrap_content"
      -    android:layout_height="wrap_content" />
      -
      -
    2. -
    3. To do something when the state is changed, add the following code -to the end of the onCreate() method: -
      -final ToggleButton togglebutton = (ToggleButton) findViewById(R.id.togglebutton);
      -togglebutton.setOnClickListener(new OnClickListener() {
      -    public void onClick(View v) {
      -        // Perform action on clicks
      -        if (togglebutton.isChecked()) {
      -            Toast.makeText(HelloFormStuff.this, "ON", Toast.LENGTH_SHORT).show();
      -        } else {
      -            Toast.makeText(HelloFormStuff.this, "OFF", Toast.LENGTH_SHORT).show();
      -        }
      -    }
      -});
      -
      -

      This captures our ToggleButton element from the layout, then adds an on-click listener to it. -The {@link android.view.View.OnClickListener} must define the onClick() method, which -defines the action to be made when the button is clicked. Here, we query the current state of the -ToggleButton, then pop up a {@link android.widget.Toast} message that displays the current state. -Notice that the ToggleButton handles its own state change between checked and un-checked, so we just -ask which it is.

      -
    4. Run it.
    5. -
    - -

    Tip: By default, the text on the button is "ON" and "OFF", but -you can change each of these with setTextOn(CharSequence) and -setTextOff(CharSequence). And, if you find that you need to change the state -in another way (such as when loading a saved {@link android.preference.CheckBoxPreference}), -use setChecked(true) or toggle().

    - - -

    If you've added all the form items above, your application should look something like this:

    - - -

    References

    -
      -
    • {@link android.widget.ImageButton}
    • -
    • {@link android.widget.EditText}
    • -
    • {@link android.widget.CheckBox}
    • -
    • {@link android.widget.RadioButton}
    • -
    • {@link android.widget.ToggleButton}
    • -
    - diff --git a/docs/html/guide/tutorials/views/hello-gallery.jd b/docs/html/guide/tutorials/views/hello-gallery.jd deleted file mode 100644 index 084f912ca646599d72fb8c9549f3cd2ba9d59a97..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-gallery.jd +++ /dev/null @@ -1,135 +0,0 @@ -page.title=Hello, Gallery -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.Gallery} is a View commonly used to display items in a horizontally scrolling list -that locks the current selection at the center. When one is selected, we'll show a message.

    - - -
      -
    1. Start a new project/Activity called HelloGallery.
    2. -
    3. Add some images to your res/drawable/ directory.
    4. -
    5. Open the layout file and make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<Gallery xmlns:android="http://schemas.android.com/apk/res/android" 
      -    android:id="@+id/gallery"
      -    android:layout_width="fill_parent"
      -    android:layout_height="wrap_content"
      -/>
      -
      -
    6. - - -
    7. Open the HelloGallery.java file. Insert the following for the onCreate() method: -
      -@Override
      -public void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -
      -    Gallery g = (Gallery) findViewById(R.id.gallery);
      -    g.setAdapter(new ImageAdapter(this));
      -
      -    g.setOnItemClickListener(new OnItemClickListener() {
      -        public void onItemClick(AdapterView parent, View v, int position, long id) {
      -            Toast.makeText(HelloGallery.this, "" + position, Toast.LENGTH_SHORT).show();
      -        }
      -    });
      -}
      -
      -

      We start as usual: set the layout and capture the View we want (our Gallery). -We then set an Adapter, called ImageAdapter for the Gallery—this is a new class that -we'll create next. Then we create an item click listener for the Gallery. This is like a normal -on-click listener (which you might be familiar with for buttons), but it listens to each item -that we've added to the Gallery. The onItemClick() callback method -receives the AdapterView where the click occurred, the specific View that received the click, the -position of the View clicked (zero-based), and the row id of the item clicked (if applicable). All -that we care about is the position, so that we can pop up a {@link android.widget.Toast} message that -tells us the index position of the item clicked. We do this with Toast.makeText().show(). -

      -
    8. - -
    9. After the onCreate() method, add the ImageAdapter class: -
      -public class ImageAdapter extends BaseAdapter {
      -    int mGalleryItemBackground;
      -    private Context mContext;
      -
      -    private Integer[] mImageIds = {
      -            R.drawable.sample_1,
      -            R.drawable.sample_2,
      -            R.drawable.sample_3,
      -            R.drawable.sample_4,
      -            R.drawable.sample_5,
      -            R.drawable.sample_6,
      -            R.drawable.sample_7
      -    };
      -
      -    public ImageAdapter(Context c) {
      -        mContext = c;
      -        TypedArray a = obtainStyledAttributes(android.R.styleable.Theme);
      -        mGalleryItemBackground = a.getResourceId(
      -                android.R.styleable.Theme_galleryItemBackground, 0);
      -        a.recycle();
      -    }
      -
      -    public int getCount() {
      -        return mImageIds.length;
      -    }
      -
      -    public Object getItem(int position) {
      -        return position;
      -    }
      -
      -    public long getItemId(int position) {
      -        return position;
      -    }
      -
      -    public View getView(int position, View convertView, ViewGroup parent) {
      -        ImageView i = new ImageView(mContext);
      -
      -        i.setImageResource(mImageIds[position]);
      -        i.setLayoutParams(new Gallery.LayoutParams(150, 100));
      -        i.setScaleType(ImageView.ScaleType.FIT_XY);
      -        i.setBackgroundResource(mGalleryItemBackground);
      -
      -        return i;
      -    }
      -}
      -
      -

      First, there are a few member variables, including an array of IDs that reference -the images we placed in our drawable resources directory.

      -

      Next is the constructor, where we define the member Context. The rest of the constructor -sets up a reference for our Gallery them, which adds the nice framing for each Gallery item. -Once we have our mGalleryItemBackground, it's important to recycle the -StyledAttribute for later re-use.

      -

      The next three methods are required for basic member queries. -But then we have the getView() method, which is called -for each item read by our ImageAdapter, when the Gallery is being built. Here, we -use our member Context to create a new {@link android.widget.ImageView}. We then define -the image resource with the current position of the Gallery items (corresponding to our -array of drawables), set the dimensions for the ImageView, -set the image scaling to fit the ImageView dimensions, then finally set the -background theme for the ImageView.

      - -

      See {@link android.widget.ImageView.ScaleType} -for other image scaling options, in case you want to avoid stretching images that don't -exactly match the ImageView dimensions.

      - -
    10. Now run it.
    11. -
    -

    You should see something like this:

    - - - -

    References

    -
      -
    • {@link android.widget.BaseAdapter}
    • -
    • {@link android.widget.Gallery}
    • -
    • {@link android.widget.ImageView}
    • -
    • {@link android.widget.Toast}
    • -
    - - diff --git a/docs/html/guide/tutorials/views/hello-gridview.jd b/docs/html/guide/tutorials/views/hello-gridview.jd deleted file mode 100644 index 186c4e7513a6077f55613d7843d7b866b2ae233c..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-gridview.jd +++ /dev/null @@ -1,129 +0,0 @@ -page.title=Hello, GridView -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.GridView} displays items in a two-dimensional, scrolling grid. The items -are acquired from a {@link android.widget.ListAdapter}.

    - - -
      -
    1. Start a new project/Activity called HelloGridView.
    2. -
    3. Find some photos you'd like to use, or copy some from the SDK samples res/drawable/ - folder of your project.
    4. -
    5. Open the layout and make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
      -    android:id="@+id/gridview"
      -    android:layout_width="fill_parent" 
      -    android:layout_height="fill_parent"
      -    android:numColumns="auto_fit"
      -    android:verticalSpacing="10dp"
      -    android:horizontalSpacing="10dp"
      -    android:columnWidth="90dp"
      -    android:stretchMode="columnWidth"
      -    android:gravity="center"
      -/>
      -
      -
    6. -
    7. Open the HelloGridView Java file. Insert the following for the onCreate() method: -
      -public void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -
      -    GridView gridview = (GridView) findViewById(R.id.gridview);
      -    gridview.setAdapter(new ImageAdapter(this));
      -}
      -
      -

      Here, we get a handle on our GridView, from the layout, and give it an Adapter. - We're actually going to create our own Adapter called ImageAdapter.

      -
    8. -
    9. Create a new class (nested or otherwise), called ImageAdapter, which extends {@link android.widget.BaseAdapter}: -
      -public class ImageAdapter extends BaseAdapter {
      -    private Context mContext;
      -
      -    public ImageAdapter(Context c) {
      -        mContext = c;
      -    }
      -
      -    public int getCount() {
      -        return mThumbIds.length;
      -    }
      -
      -    public Object getItem(int position) {
      -        return null;
      -    }
      -
      -    public long getItemId(int position) {
      -        return 0;
      -    }
      -
      -    // create a new ImageView for each item referenced by the Adapter
      -    public View getView(int position, View convertView, ViewGroup parent) {
      -        ImageView imageView;
      -        if (convertView == null) {  // if it's not recycled, initialize some attributes
      -            imageView = new ImageView(mContext);
      -            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
      -            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
      -            imageView.setPadding(8, 8, 8, 8);
      -        } else {
      -            imageView = (ImageView) convertView;
      -        }
      -
      -        imageView.setImageResource(mThumbIds[position]);
      -        return imageView;
      -    }
      -
      -    // references to our images
      -    private Integer[] mThumbIds = {
      -            R.drawable.sample_2, R.drawable.sample_3,
      -            R.drawable.sample_4, R.drawable.sample_5,
      -            R.drawable.sample_6, R.drawable.sample_7,
      -            R.drawable.sample_0, R.drawable.sample_1,
      -            R.drawable.sample_2, R.drawable.sample_3,
      -            R.drawable.sample_4, R.drawable.sample_5,
      -            R.drawable.sample_6, R.drawable.sample_7,
      -            R.drawable.sample_0, R.drawable.sample_1,
      -            R.drawable.sample_2, R.drawable.sample_3,
      -            R.drawable.sample_4, R.drawable.sample_5,
      -            R.drawable.sample_6, R.drawable.sample_7
      -    };
      -}
      -
      -

      First we take care of some required methods inherited from BaseAdapter. - The constructor and getCount() are self-explanatory. Normally, getItem() - should return the actual object at the specified position in our Adapter, but for this Hello World, - we're not going to bother. Likewise, getItemId() should return the row id of - the item, but right now we don't care.

      -

      However, getView() is the method we care about. This one creates a new View for each image that we - put in our ImageAdapter. So we're going to create an ImageView each time. When this is called, we're - going to receive a View, which is likely a recycled View object (at least after the first call), so we - check for this—if it's null, we initialize the ImageView and setup all the properties we want. - The LayoutParams() initialization sets the height and width of the View—this ensures - that no matter the drawable size, each image is resized and cropped to fit in the ImageView (if necessary). - With setScaleType(), we say that images should be cropped toward the center (if necessary). - And finally, we set the padding within the ImageView. (Note that, if the images have various aspect-ratios, - as they do in this demo, then less padding will cause for more cropping of the image, if it does not match - the dimensions given to the ImageView.) At the end of getView() we set the image resource and - return the ImageView.

      -

      All that's left is our array or drawable resources at the bottom.

      -
    10. -
    11. Run it.
    12. -
    -

    Your grid layout should look something like this:

    - - -

    Try experimenting with the behaviors of the GridView and ImageView by adjusting their properties. For example, - instead of setting the ImageView LayoutParams, you can try using - {@link android.widget.ImageView#setAdjustViewBounds(boolean)}.

    - -

    References

    -
      -
    • {@link android.widget.GridView}
    • -
    • {@link android.widget.ImageView}
    • -
    • {@link android.widget.BaseAdapter}
    • -
    - diff --git a/docs/html/guide/tutorials/views/hello-linearlayout.jd b/docs/html/guide/tutorials/views/hello-linearlayout.jd deleted file mode 100644 index 0e8947c10e3aee8c8364412a8920c5084e3e718f..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-linearlayout.jd +++ /dev/null @@ -1,130 +0,0 @@ -page.title=Hello, LinearLayout -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.LinearLayout} is a GroupView that will lay child View elements -vertically or horizontally.

    - - -
      -
    1. Start a new project/Activity called HelloLinearLayout.
    2. -
    3. Open the layout file. - Make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:orientation="vertical"
      -    android:layout_width="fill_parent"
      -    android:layout_height="fill_parent">
      -
      -    <LinearLayout
      -	android:orientation="horizontal"
      -	android:layout_width="fill_parent"
      -	android:layout_height="fill_parent"
      -	android:layout_weight="1">
      -	
      -	<TextView
      -	    android:text="red"
      -	    android:gravity="center_horizontal"
      -	    android:background="#aa0000"
      -	    android:layout_width="wrap_content"
      -	    android:layout_height="fill_parent"
      -	    android:layout_weight="1"/>
      -	
      -	<TextView
      -	    android:text="green"
      -	    android:gravity="center_horizontal"
      -	    android:background="#00aa00"
      -	    android:layout_width="wrap_content"
      -	    android:layout_height="fill_parent"
      -	    android:layout_weight="1"/>
      -	
      -	<TextView
      -	    android:text="blue"
      -	    android:gravity="center_horizontal"
      -	    android:background="#0000aa"
      -	    android:layout_width="wrap_content"
      -	    android:layout_height="fill_parent"
      -	    android:layout_weight="1"/>
      -	
      -	<TextView
      -	    android:text="yellow"
      -	    android:gravity="center_horizontal"
      -	    android:background="#aaaa00"
      -	    android:layout_width="wrap_content"
      -	    android:layout_height="fill_parent"
      -	    android:layout_weight="1"/>
      -		
      -    </LinearLayout>
      -	
      -    <LinearLayout
      -	android:orientation="vertical"
      -	android:layout_width="fill_parent"
      -	android:layout_height="fill_parent"
      -	android:layout_weight="1">
      -	
      -	<TextView
      -	    android:text="row one"
      -	    android:textSize="15pt"
      -	    android:layout_width="fill_parent"
      -	    android:layout_height="wrap_content"
      -	    android:layout_weight="1"/>
      -	
      -	<TextView
      -	    android:text="row two"
      -	    android:textSize="15pt"
      -	    android:layout_width="fill_parent"
      -	    android:layout_height="wrap_content"
      -	    android:layout_weight="1"/>
      -	
      -	<TextView
      -	    android:text="row three"
      -	    android:textSize="15pt"
      -	    android:layout_width="fill_parent"
      -	    android:layout_height="wrap_content"
      -	    android:layout_weight="1"/>
      -	
      -	<TextView
      -	    android:text="row four"
      -	    android:textSize="15pt"
      -	    android:layout_width="fill_parent"
      -	    android:layout_height="wrap_content"
      -	    android:layout_weight="1"/>
      -        
      -    </LinearLayout>
      -        
      -</LinearLayout>
      -
      -

      Carefully inspect the XML. You'll notice how this layout works a lot like - an HTML layout. There is one parent LinearLayout that is defined to lay - its child elements vertically. The first child is another LinearLayout that uses a horizontal layout - and the second uses a vertical layout. Each LinearLayout contains several {@link android.widget.TextView} - elements.

      -
    4. -
    5. Now open the HelloLinearLayout Activity and be sure it loads this layout in the onCreate() method:

      -
      -public void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -}
      -
      -

      R.layout.main refers to the main.xml layout file.

      -
    6. -
    7. Run it.
    8. -
    -

    You should see the following:

    - - -

    Notice how the various XML attributes define the View's behavior. -Pay attention to the effect of the layout_weight. Try - experimenting with different values to see how the screen real estate is - distributed based on the weight of each element.

    - -

    References

    -
      -
    • {@link android.widget.LinearLayout}
    • -
    • {@link android.widget.TextView}
    • -
    - - diff --git a/docs/html/guide/tutorials/views/hello-listview.jd b/docs/html/guide/tutorials/views/hello-listview.jd deleted file mode 100644 index d90005bb4e5f6d73df9ca78d65259ee2cb701af1..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-listview.jd +++ /dev/null @@ -1,90 +0,0 @@ -page.title=Hello, ListView -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.ListView} is a View that shows items in a vertically scrolling list. The items are - acquired from a {@link android.widget.ListAdapter}.

    - - -
      -
    1. Start a new project/ListActivity called HelloListView.
    2. -
    3. Open the HelloListView Java file. Make the class extend ListActivity (instead of Activity). -
      public class HelloListView extends ListActivity {
      -
    4. -
    5. Insert the following for the onCreate() method: -
      -@Override
      -public void onCreate(Bundle savedInstanceState) {
      -  super.onCreate(savedInstanceState);
      -  
      -  setListAdapter(new ArrayAdapter<String>(this,
      -          android.R.layout.simple_list_item_1, COUNTRIES));
      -  getListView().setTextFilterEnabled(true);
      -}
      -
      -

      Notice that we don't need to load a layout (at least, not in this case, because we're using - the whole screen for our list). Instead, we just call setListAdapter() (which automatically - adds a ListView to the ListActivity), and provide it with an ArrayAdapter that binds a - simple_list_item_1 layout item to each entry in the COUNTRIES - array (added next). The next line of code adds a text filter to the ListView, so that when the user - begins typing, the list will filter the entire view to display only the items that match the entry.

      -
    6. -
    7. Following the onCreate() method, add the String array: -
      -  static final String[] COUNTRIES = new String[] {
      -    "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
      -    "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
      -    "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
      -    "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
      -    "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
      -    "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",
      -    "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
      -    "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
      -    "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
      -    "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
      -    "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
      -    "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
      -    "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
      -    "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
      -    "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
      -    "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
      -    "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
      -    "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
      -    "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
      -    "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
      -    "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
      -    "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
      -    "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
      -    "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
      -    "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
      -    "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
      -    "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
      -    "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
      -    "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
      -    "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
      -    "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
      -    "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
      -    "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
      -    "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
      -    "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
      -    "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
      -    "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
      -    "Ukraine", "United Arab Emirates", "United Kingdom",
      -    "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
      -    "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
      -    "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
      -  };
      -
      -
    8. -
    9. Run it.
    10. -
    -

    You can scroll the list, or type to filter it. You should see something like this:

    - - -

    References

    -
      -
    • {@link android.widget.ListView}
    • -
    • {@link android.widget.ListAdapter}
    • -
    - diff --git a/docs/html/guide/tutorials/views/hello-mapview.jd b/docs/html/guide/tutorials/views/hello-mapview.jd deleted file mode 100644 index 5217b6b20e9f56c1c8a7d117d1474a794ff11bd4..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-mapview.jd +++ /dev/null @@ -1,245 +0,0 @@ -page.title=Hello, MapView -parent.title=Hello, Views -parent.link=index.html -@jd:body - -
    -

    This tutorial requires that you have the Google Maps external library -installed in your SDK environment. By default the Android SDK includes the -Google APIs add-on, which in turn includes the Maps external library. If you -don't have the Google APIs SDK add-on, you can download it from this -location:

    - -

    http://code.google.com/android/add-ons/google-apis

    - -

    The Google APIs add-on requires Android 1.5 SDK or later release. After -installing the add-on in your SDK, set your project properties to use a Google -APIs build target. See the instructions for setting a build -target in Developing in -Eclipse with ADT or Developing in Other IDEs, -as appropriate for your environment.

    - -

    You will also need to use the android tool to set up an AVD that uses the -Google APIs deployment target. See Android Virtual Devices for -more information. Once you have set up your environment, you will be able to -build and run the project described in this tutorial

    - -
    - -

    A MapView allows you to create your own map-viewing Activity. -First, we'll create a simple Activity that can view and navigate a map. Then we will add some overlay items.

    - -
      -
    1. Start a new project/Activity called HelloMapView. - -
    2. Because we're using the Google Maps library, - which is not a part of the standard Android library, we need to - declare it in the Android Manifest. Open the AndroidManifest.xml - file and add the following as a child of the <application> element: - -
      <uses-library android:name="com.google.android.maps" />
      -
    3. -
    4. We also need access to the internet in order to retrieve the Google Maps tiles, - so the application must request the {@link android.Manifest.permission#INTERNET INTERNET} permissions. - In the manifest file, add the following as a child of the <manifest> element: -
      <uses-permission android:name="android.permission.INTERNET" />
      -
    5. -
    6. Now open the main layout file for your project. Define a layout with a com.google.android.maps.MapView - inside a android.widget.RelativeLayout: - -
      -<?xml version="1.0" encoding="utf-8"?>
      -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:id="@+id/mainlayout"
      -    android:orientation="vertical"
      -    android:layout_width="fill_parent"
      -    android:layout_height="fill_parent" >
      -
      -    <com.google.android.maps.MapView
      -        android:id="@+id/mapview"
      -        android:layout_width="fill_parent"
      -        android:layout_height="fill_parent"
      -        android:clickable="true"
      -        android:apiKey="Your Maps API Key"
      -    />
      -
      -</RelativeLayout>
      -
      -

      The clickable attribute defines whether you want to allow user-interaction with the map. - In this case, we set it "true" so that the user can navigate.

      - -

      The apiKey attribute holds the Google Maps API Key that proves your application and signer - certificate has been registered with the Google Maps service. Because MapView uses Google Maps data, this key is required - in order to receive the map data, even while you are developing. Registration is free and it only takes a couple - minutes to register your certificate and receive a Maps API Key. For instructions on getting a key, read - Obtaining a Maps API Key. - (For the purpose of this tutorial, you should register with the fingerprint of the SDK debug certificate.) - Once you've acquired the Maps API Key, insert it for the apiKey value.

    7. - -
    8. Now open the HelloMapView.java file. For this Activity, we're going to extend the special sub-class of - Activity called MapActivity, so change the class declaration to extend - MapActivity, instead of Activity:

      - -
      public class HelloMapView extends MapActivity {
      - -
    9. The isRouteDisplayed() method is required, so add it inside the class: -
      -@Override
      -protected boolean isRouteDisplayed() {
      -    return false;
      -}
      -
      -

      You can actually run this now, but all it does is allow you to pan around the map.

      - -
    10. Now go back to the HelloMapView class. We'll now retrieve the ZoomControls object from - the MapView and add it to our new layout element. First, at the top of the HelloMapView, - instantiate handles for the MapView and LinearLayout, plus a ZoomControl object: -
      -LinearLayout linearLayout;
      -MapView mapView;
      -
      - -
    11. Then initialize each of these in onCreate(). We'll capture the LinearLayout and - MapView through their layout resources. Then get the ZoomControls from the MapView:: -
      -mapView = (MapView) findViewById(R.id.mapview);
      -mapView.setBuiltInZoomControls(true);
      -
      - -

      By using the built-in zoom control provided by MapView, we don't have to do any of the work - required to actually perform the zoom operations. The controls will appear whenever the user - touches the map, then disappear after a few moments of inactivity.

    12. - -
    13. Run it.
    14. -
    - -
    - -

    So, we now have full interaction controls. All well and good, but what we really want our map -for is custom markers and layovers. Let's add some Overlay -objects to our map. To do this, we're going to -implement the ItemizedOverlay -class, which can manage a whole set of Overlay items for us.

    - -
      -
    1. Create a new Java class named HelloItemizedOverlay that implements ItemizedOverlay. - -

      When using Eclipse, right-click the package name in the Eclipse Package Explorer, and select New > Class. Fill-in - the Name field as HelloItemizedOverlay. For the Superclass, enter - com.google.android.maps.ItemizedOverlay. Click the checkbox for Constructors from - superclass. Click Finish.

    2. - -
    3. First thing, we need an OverlayItem ArrayList, in which we'll put each of the OverlayItem - objects we want on our map. Add this at the top of the HelloItemizedOverlay class: - -
      private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
    4. - -
    5. All the constructor does is define the default marker to be used on each of the OverlayItems. - In order for the Drawable to actually get drawn, it must have its bounds defined. And we want the - center-point at the bottom of the image to be the point at which it's attached to the map - coordinates. We handle all this with the boundCenterBottom() method. Wrap this around our - defaultMarker, so the super constructor call looks like this: - -
      super(boundCenterBottom(defaultMarker));
    6. - -
    7. In order to add new OverlayItems to our ArrayList, we need a new public method. We'll handle - this with the following method: - -
      -public void addOverlay(OverlayItem overlay) {
      -    mOverlays.add(overlay);
      -    populate();
      -}
      - -

      Each time we add a new OverlayItem, we must call populate(), which will read each of out - OverlayItems and prepare them to be drawn.

    8. - -
    9. In order for the populate() method to read each OverlayItem, it will make a request to - createItem(int). We must define this method to properly read from our ArrayList. Replace the - existing contents of the createItem method with a get() call to our ArrayList: - -
      -@Override
      -protected OverlayItem createItem(int i) {
      -  return mOverlays.get(i);
      -}
      -
    10. - -
    11. We're also required to override the size() method. Replace the existing contents of the - method with a size request to our ArrayList: - -
      return mOverlays.size();
    12. -
    - - -

    That's it for the HelloItemizedOverlay class. We're now ready to use it.

    - -
    -

    Go back to the HelloMapView -class. We'll start by creating one OverlayItem, adding to an instance of our HelloItemizedOverlay, -and then adding this to the MapView.

    - - -

    First, we need the image that we'll use for our map overlay. Here, we'll use the Android on the -right as our marker. Drag this image (or your own) to the res/drawable/ directory of your project workspace.

    - -

    Now we're ready to work in the HelloMapView:

    - -
      -
    1. First we need some more types. Add the following at the top of the HelloMapView class: - -
      -List<Overlay> mapOverlays;
      -Drawable drawable;
      -HelloItemizedOverlay itemizedOverlay;
    2. - -
    3. Now pick up where we left off in the onCreate() method. Instantiate the - new fields: - -
      -mapOverlays = mapView.getOverlays();
      -drawable = this.getResources().getDrawable(R.drawable.androidmarker);
      -itemizedoverlay = new HelloItemizedOverlay(drawable);
      - -

      All overlay elements on a map are held by the MapView, so when we want to add some, we must - first retrieve the List with getOverlays() methods. We instantiate the Drawable, which will - be used as our map marker, by using our Context resources to get the Drawable we placed in - the res/drawable/ directory (androidmarker.png). Our HelloItemizedOverlay takes the Drawable in order to set the - default marker.

    4. - -
    5. Now let's make our first OverlayItem by creating a GeoPoint - that defines our map coordinates, then pass it to a new OverlayItem: - -
      -GeoPoint point = new GeoPoint(19240000,-99120000);
      -OverlayItem overlayitem = new OverlayItem(point, "", "");
      - -

      GeoPoint coordinates are based in microdegrees (degrees * 1e6). The OverlayItem takes this - GeoPoint and two strings. Here, we won't concern ourselves with the strings, which can display - text when we click our marker, because we haven't yet written the click handler for the OverlayItem.

    6. - -
    7. All that's left is for us to add this OverlayItem to our collection in the HelloItemizedOverlay, - and add this to the List of Overlay objects retrieved from the MapView: - -
      -itemizedoverlay.addOverlay(overlayitem);
      -mapOverlays.add(itemizedoverlay);
    8. - -
    9. Run it!
    10. -
    - -

    We've sent our droid to Mexico City. Hola, Mundo!

    -

    You should see the following:

    - - -

    Because we created our ItemizedOverlay class with an ArrayList, we can continue adding new -OverlayItems. Try adding another one. Before the addOverlay() method is called, add these lines:

    -
    -GeoPoint point2 = new GeoPoint(35410000, 139460000);
    -OverlayItem overlayitem2 = new OverlayItem(point2, "", "");
    -
    -

    Run it again... We've sent a new droid to Tokyo. Sekai, konichiwa!

    - diff --git a/docs/html/guide/tutorials/views/hello-relativelayout.jd b/docs/html/guide/tutorials/views/hello-relativelayout.jd deleted file mode 100644 index 1b915379739ce6fd99cee9294dbbf96e3d252249..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-relativelayout.jd +++ /dev/null @@ -1,75 +0,0 @@ -page.title=Hello, RelativeLayout -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.RelativeLayout} is a ViewGroup that allows you to layout child elements -in positions relative to the parent or siblings elements.

    - -
      -
    1. Start a new project/Activity called HelloRelativeLayout.
    2. -
    3. Open the layout file. Make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:layout_width="fill_parent"
      -    android:layout_height="fill_parent">
      -
      -    <TextView
      -        android:id="@+id/label"
      -        android:layout_width="fill_parent"
      -        android:layout_height="wrap_content"
      -        android:text="Type here:"/>
      -
      -    <EditText
      -        android:id="@+id/entry"
      -        android:layout_width="fill_parent"
      -        android:layout_height="wrap_content"
      -        android:background="@android:drawable/editbox_background"
      -        android:layout_below="@id/label"/>
      -
      -    <Button
      -        android:id="@+id/ok"
      -        android:layout_width="wrap_content"
      -        android:layout_height="wrap_content"
      -        android:layout_below="@id/entry"
      -        android:layout_alignParentRight="true"
      -        android:layout_marginLeft="10dip"
      -        android:text="OK" />
      -
      -    <Button
      -        android:layout_width="wrap_content"
      -        android:layout_height="wrap_content"
      -        android:layout_toLeftOf="@id/ok"
      -        android:layout_alignTop="@id/ok"
      -        android:text="Cancel" />
      -
      -</RelativeLayout>
      -
      -

      Pay attention to each of the additional layout_* attributes (besides the -usual width and height, which are required for all elements). When using relative layout, -we use attributes like layout_below and layout_toLeftOf to describe -how we'd like to position each View. Naturally, these are different relative positions, and the -value of the attribute is the id of the element we want the position relative to.

      -
    4. -
    5. Make sure your Activity loads this layout in the onCreate() method:

      -
      -public void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -}
      -
      -

      R.layout.main refers to the main.xml layout file.

      -
    6. -
    7. Run it.
    8. -
    -

    You should see the following:

    - - -

    Resources

    -
      -
    • {@link android.widget.RelativeLayout}
    • -
    • {@link android.widget.TextView}
    • -
    • {@link android.widget.EditText}
    • -
    • {@link android.widget.Button}
    • -
    diff --git a/docs/html/guide/tutorials/views/hello-spinner.jd b/docs/html/guide/tutorials/views/hello-spinner.jd deleted file mode 100644 index 3a04214a1f3d52983f8ceedc8b65b87142acd13b..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-spinner.jd +++ /dev/null @@ -1,106 +0,0 @@ -page.title=Hello, Spinner -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.Spinner} is a widget that allows the user to select an item from a group. -It is similar to a dropdown list and will allow scrolling when the -list exceeds the available vertical space on the screen.

    - - -
      -
    1. Start a new project/Activity called HelloSpinner.
    2. -
    3. Open the layout file. - Make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:orientation="vertical"
      -    android:padding="10dip"
      -    android:layout_width="fill_parent"
      -    android:layout_height="wrap_content">
      -
      -    <TextView
      -        android:layout_width="fill_parent"
      -        android:layout_height="wrap_content"
      -        android:layout_marginTop="10dip"
      -        android:text="Please select a planet:"
      -    />
      -
      -    <Spinner 
      -        android:id="@+id/spinner"
      -        android:layout_width="fill_parent"
      -        android:layout_height="wrap_content"
      -        android:drawSelectorOnTop="true"
      -        android:prompt="@string/planet_prompt"
      -    />
      -
      -</LinearLayout>
      -
      -

      Notice that the Spinner's android:prompt is a string resource. In - this case, Android does not allow it to be a string, it must be a reference to a resource. - So...

      -
    4. - -
    5. Open the strings.xml file in res/values/ and add the following <string> -element inside the <resources> element: -
      -<string name="planet_prompt">Choose a planet</string>
      -
      -
    6. - -
    7. Create a new XML file in res/values/ called arrays.xml. Insert the following: -
      -<resources>
      -
      -    <string-array name="planets">
      -        <item>Mercury</item>
      -        <item>Venus</item>
      -        <item>Earth</item>
      -        <item>Mars</item>
      -        <item>Jupiter</item>
      -        <item>Saturn</item>
      -        <item>Uranus</item>
      -        <item>Neptune</item>
      -    </string-array>
      -    
      -</resources>
      -
      -

      This is the list of items (planets) that the user can select from in the Spinner widget.

      -
    8. - -
    9. Now open the HelloSpinner.java file. Insert the following code into the HelloSpinner class: -
      -@Override
      -public void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -
      -    Spinner s = (Spinner) findViewById(R.id.spinner);
      -    ArrayAdapter adapter = ArrayAdapter.createFromResource(
      -            this, R.array.planets, android.R.layout.simple_spinner_item);
      -    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
      -    s.setAdapter(adapter);
      -}
      -
      -

      That's it. We start by creating a Spinner from our layout. We then create an {@link android.widget.ArrayAdapter} - that binds each element of our string array to a layout view—we pass createFromResource our Context, - the array of selectable items and the type of layout we'd like each one bound to. We then call - setDropDownViewResource() to define the type of layout in which to present the - entire collection. Finally, we set this Adapter to associate with our Spinner, - so the string items have a place to go.

      -
    10. - -
    11. Now run it.
    12. -
    -

    It should look like this:

    - - - -

    Resources

    -
      -
    • {@link android.R.layout}
    • -
    • {@link android.widget.ArrayAdapter}
    • -
    • {@link android.widget.Spinner}
    • -
    - diff --git a/docs/html/guide/tutorials/views/hello-tablelayout.jd b/docs/html/guide/tutorials/views/hello-tablelayout.jd deleted file mode 100644 index 83d6f5d46be5d811115997e40176627b9291aebd..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-tablelayout.jd +++ /dev/null @@ -1,118 +0,0 @@ -page.title=Hello, TableLayout -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.TableLayout} is a ViewGroup that -will lay child View elements into rows and columns.

    - - -
      -
    1. Start a new project/Activity called HelloTableLayout.
    2. -
    3. Open the layout file. - Make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:layout_width="fill_parent"
      -    android:layout_height="fill_parent"
      -    android:stretchColumns="1">
      -
      -    <TableRow>
      -        <TextView
      -            android:layout_column="1"
      -            android:text="Open..."
      -            android:padding="3dip" />
      -        <TextView
      -            android:text="Ctrl-O"
      -            android:gravity="right"
      -            android:padding="3dip" />
      -    </TableRow>
      -
      -    <TableRow>
      -        <TextView
      -            android:layout_column="1"
      -            android:text="Save..."
      -            android:padding="3dip" />
      -        <TextView
      -            android:text="Ctrl-S"
      -            android:gravity="right"
      -            android:padding="3dip" />
      -    </TableRow>
      -
      -    <TableRow>
      -        <TextView
      -            android:layout_column="1"
      -            android:text="Save As..."
      -            android:padding="3dip" />
      -        <TextView
      -            android:text="Ctrl-Shift-S"
      -            android:gravity="right"
      -            android:padding="3dip" />
      -    </TableRow>
      -
      -    <View
      -        android:layout_height="2dip"
      -        android:background="#FF909090" />
      -
      -    <TableRow>
      -        <TextView
      -            android:text="X"
      -            android:padding="3dip" />
      -        <TextView
      -            android:text="Import..."
      -            android:padding="3dip" />
      -    </TableRow>
      -
      -    <TableRow>
      -        <TextView
      -            android:text="X"
      -            android:padding="3dip" />
      -        <TextView
      -            android:text="Export..."
      -            android:padding="3dip" />
      -        <TextView
      -            android:text="Ctrl-E"
      -            android:gravity="right"
      -            android:padding="3dip" />
      -    </TableRow>
      -
      -    <View
      -        android:layout_height="2dip"
      -        android:background="#FF909090" />
      -
      -    <TableRow>
      -        <TextView
      -            android:layout_column="1"
      -            android:text="Quit"
      -            android:padding="3dip" />
      -    </TableRow>
      -</TableLayout>
      -
      -

      Notice how this resembles the structure of an HTML table. TableLayout is like the -table element; TableRow is like a tr element; but for our cells like -the html td element, we can use any kind of View. Here, we use TextView for the cells.

      - -
    4. -
    5. Make sure your Activity loads this layout in the onCreate() method: -
      -public void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -}
      -
      -

      R.layout.main refers to the main.xml layout file.

      -
    6. -
    7. Run it.
    8. -
    -

    You should see the following:

    - - -

    References

    -
      -
    • {@link android.widget.TableLayout}
    • -
    • {@link android.widget.TableRow}
    • -
    • {@link android.widget.TextView}
    • -
    - - diff --git a/docs/html/guide/tutorials/views/hello-tabwidget.jd b/docs/html/guide/tutorials/views/hello-tabwidget.jd deleted file mode 100644 index 98dddf539049cbf2e7f21e289be798739dd7bd35..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-tabwidget.jd +++ /dev/null @@ -1,124 +0,0 @@ -page.title=Hello, TabWidget -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.TabWidget} offers the ability to easily draw an interface that uses -tabs to navigate between different views.

    - -
      -
    1. Start a new project/Activity called HelloTabWidget.
    2. -
    3. Open the layout file and make it like so:
    4. -
      -<?xml version="1.0" encoding="utf-8"?>
      -<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:id="@android:id/tabhost"
      -    android:layout_width="fill_parent"
      -    android:layout_height="fill_parent">
      -    <LinearLayout
      -        android:orientation="vertical"
      -        android:layout_width="fill_parent"
      -        android:layout_height="fill_parent">
      -        <TabWidget
      -            android:id="@android:id/tabs"
      -            android:layout_width="fill_parent"
      -            android:layout_height="wrap_content" />
      -        <FrameLayout
      -            android:id="@android:id/tabcontent"
      -            android:layout_width="fill_parent"
      -            android:layout_height="fill_parent">
      -            <TextView 
      -                android:id="@+id/textview1"
      -                android:layout_width="fill_parent"
      -                android:layout_height="fill_parent" 
      -                android:text="this is a tab" />
      -            <TextView 
      -                android:id="@+id/textview2"
      -                android:layout_width="fill_parent"
      -                android:layout_height="fill_parent" 
      -                android:text="this is another tab" />
      -            <TextView 
      -                android:id="@+id/textview3"
      -                android:layout_width="fill_parent"
      -                android:layout_height="fill_parent" 
      -                android:text="this is a third tab" />
      -    	</FrameLayout>
      -    </LinearLayout>
      -</TabHost>
      -
      -

      Here, we've created a {@link android.widget.TabHost} that contains the entire layout of the Activity. - A TabHost requires two descendant elements: a {@link android.widget.TabWidget} and a {@link android.widget.FrameLayout}. - In order to properly layout these elements, we've put them inside a vertical {@link android.widget.LinearLayout}. - The FrameLayout is where we keep the content that will change with each tab. Each child in the FrameLayout will - be associated with a different tab. - In this case, each tab simply shows a different {@link android.widget.TextView} with some text.

      -

      Notice that the TabWidget and the FrameLayout elements have specific android namespace IDs. These are necessary - so that the TabHost can automatically retrieve references to them, populate the TabWidget with the tabs that we'll define - in our code, and swap the views in the FrameLayout. We've also defined our own IDs for each TextView, which we'll use to - associate each tab with the view that it should reveal.

      -

      Of course, you can - make these child views as large as complex as you'd like — instead of the TextView elements, - you could start with other layout views and build a unique layout hierarchy for each tab.

      - -
    5. Now we'll add our code. Open HelloTabWidget.java and make it a TabActivity. -

      By default, Eclipse creates a class that extends Activity. Change it to - extend TabActivity:

      -
      -public class HelloTabWidget extends TabActivity {
      -
      -
    6. -
    7. Now fill in the the onCreate method like this: -
      -public void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -
      -    mTabHost = getTabHost();
      -    
      -    mTabHost.addTab(mTabHost.newTabSpec("tab_test1").setIndicator("TAB 1").setContent(R.id.textview1));
      -    mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator("TAB 2").setContent(R.id.textview2));
      -    mTabHost.addTab(mTabHost.newTabSpec("tab_test3").setIndicator("TAB 3").setContent(R.id.textview3));
      -    
      -    mTabHost.setCurrentTab(0);
      -}
      -
      -

      As usual, we start by setting our layout.

      -

      We then call the TabActivity method getTabHost(), - which returns us a reference to the TabHost we created in our layout. Upon our TabHost, we call addTab() - for each of the tabs that we want to add to the TabWidget. Each time we call this, we pass a - {@link android.widget.TabHost.TabSpec} that we build on the fly, and with it, chain together two necessary methods: - setIndicator() to set the text for the tab button, and setContent() to define - which View we want to associate with the tab and reveal when pressed. Our indicator is just a text string and - our content is an ID reference to the TextView elements we inserted in the FrameLayout.

      -

      At the end, we call setCurrentTab() to define which tab should be opened by default. The tabs - are saved like a zero-based array, so to open the first tab, we pass zero (0).

      -
    8. -
    9. To clean-up the presentation a bit more, let's remove the window title that appears at the top of the layout. - Android includes a theme that removes that title for us. To add it, open the Android Manifest file and add - the NoTitleBar theme to the <application> tag. It should end up like this: -
      -<application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar">
      -
      -
    10. -
    11. That's it. Run your application.
    12. - -
    - - -

    Your application should look like this:

    - - -

    You can include icons in your tabs by passing a -{@link android.graphics.drawable.Drawable} when you call setIndicator(). Here's an example -that uses a Drawable created from an image in the project resources:

    -
    setIndicator("TAB 1", getResources().getDrawable(R.drawable.tab_icon))
    -
    - -

    References

    -
      -
    • {@link android.widget.TabWidget}
    • -
    • {@link android.widget.TabHost}
    • -
    • {@link android.widget.TabHost.TabSpec}
    • -
    • {@link android.widget.FrameLayout}
    • -
    - diff --git a/docs/html/guide/tutorials/views/hello-timepicker.jd b/docs/html/guide/tutorials/views/hello-timepicker.jd deleted file mode 100644 index 1a6c8f9eeb2900ebe11efeb34b3187fb3958d341..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-timepicker.jd +++ /dev/null @@ -1,159 +0,0 @@ -page.title=Hello, TimePicker -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.widget.TimePicker} is a widget that allows the -user to select the time by hour, minute and AM or PM.

    - - -
      -
    1. Start a new project/Activity called HelloTimePicker.
    2. -
    3. Open the layout file and make it like so: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:layout_width="wrap_content"
      -    android:layout_height="wrap_content"
      -    android:orientation="vertical">
      -
      -    <TextView android:id="@+id/timeDisplay"
      -        android:layout_width="wrap_content"
      -        android:layout_height="wrap_content"
      -        android:text=""/>
      -
      -    <Button android:id="@+id/pickTime"
      -        android:layout_width="wrap_content"
      -        android:layout_height="wrap_content"
      -        android:text="Change the time"/>
      -
      -</LinearLayout>
      -
      -

      For the layout, we're using a vertical LinearLayout, with a {@link android.widget.TextView} that - will display the time and a {@link android.widget.Button} that will initiate the - {@link android.widget.TimePicker} dialog. - With this layout, the TextView will sit above the Button. - The text value in the TextView is set empty, as it will be filled by our Activity - with the current time.

      -
    4. - -
    5. Open HelloTimePicker.java. Insert the following to the HelloTimePicker class: -
      -private TextView mTimeDisplay;
      -private Button mPickTime;
      -
      -private int mHour;
      -private int mMinute;
      -
      -static final int TIME_DIALOG_ID = 0;
      -
      -@Override
      -protected void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -    
      -    // capture our View elements
      -    mTimeDisplay = (TextView) findViewById(R.id.timeDisplay);
      -    mPickTime = (Button) findViewById(R.id.pickTime);
      -
      -    // add a click listener to the button
      -    mPickTime.setOnClickListener(new View.OnClickListener() {
      -        public void onClick(View v) {
      -            showDialog(TIME_DIALOG_ID);
      -        }
      -    });
      -
      -    // get the current time
      -    final Calendar c = Calendar.getInstance();
      -    mHour = c.get(Calendar.HOUR_OF_DAY);
      -    mMinute = c.get(Calendar.MINUTE);
      -
      -    // display the current date
      -    updateDisplay();
      -}
      -
      -

      Tip: Press Ctrl(or Cmd) + Shift + O to import all needed packages.

      -

      We start by instantiating variables for our View elements and time fields. - The TIME_DIALOG_ID is a static integer that uniquely identifies the dialog. In the - onCreate() method, we get prepared by setting the layout and capturing the View elements. - We then set an on-click listener for the Button, so that when it is clicked, it will - show our TimePicker dialog. The showDialog() method will perform a callback - to our Activity. (We'll define this callback in the next section.) We then create an - instance of {@link java.util.Calendar} and get the current hour and minute. Finally, we call - updateDisplay()—our own method that will fill the TextView with the time.

      -
    6. - -
    7. After the onCreate() method, add the onCreateDialog() callback method: -
      -@Override
      -protected Dialog onCreateDialog(int id) {
      -    switch (id) {
      -    case TIME_DIALOG_ID:
      -        return new TimePickerDialog(this,
      -                mTimeSetListener, mHour, mMinute, false);
      -    }
      -    return null;
      -}
      -
      -

      This is passed the identifier we gave showDialog() and initializes - the TimePicker to the time we retrieved from our Calendar instance. It will be called by - showDialog().

      -
    8. - -
    9. Now add our updateDisplay() method: -
      -// updates the time we display in the TextView
      -private void updateDisplay() {
      -    mTimeDisplay.setText(
      -        new StringBuilder()
      -                .append(pad(mHour)).append(":")
      -                .append(pad(mMinute)));
      -}
      -
      -

      This simply takes our member fields for the time and inserts them in - the mTimeDisplay TextView. Note that we call a new method, pad(), - on the hour and minute. (We'll create this method in the last step.)

      -
    10. - -
    11. Next, add a listener to be called when the time is reset: -
      -// the callback received when the user "sets" the time in the dialog
      -private TimePickerDialog.OnTimeSetListener mTimeSetListener =
      -    new TimePickerDialog.OnTimeSetListener() {
      -        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
      -            mHour = hourOfDay;
      -            mMinute = minute;
      -            updateDisplay();
      -        }
      -    };
      -
      -

      Now when the user is done setting the time (clicks the "Set" button), we update our member fields with - the new time and update our TextView.

      -
    12. -
    13. Finally, add the pad() method that we called from the updateDisplay(): -
      -private static String pad(int c) {
      -    if (c >= 10)
      -        return String.valueOf(c);
      -    else
      -        return "0" + String.valueOf(c);
      -}
      -
      -

      This method returns the appropriate String representation of the hour or minute. - It will prefix a zero to the number if it's a single digit. -

      -
    14. - -
    15. Now run it.
    16. -
    -

    When you press the "Change the time" button, you should see the following:

    - - -

    References

    -
      -
    1. {@link android.widget.TimePicker}
    2. -
    3. {@link android.widget.Button}
    4. -
    5. {@link android.widget.TextView}
    6. -
    7. {@link java.util.Calendar}
    8. -
    - diff --git a/docs/html/guide/tutorials/views/hello-webview.jd b/docs/html/guide/tutorials/views/hello-webview.jd deleted file mode 100644 index a927b0497dde8d95d4ee4346ac5dd50025b18f33..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/hello-webview.jd +++ /dev/null @@ -1,118 +0,0 @@ -page.title=Hello, WebView -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

    A {@link android.webkit.WebView} allows you to create your own web browser Activity. In this tutorial, -we'll create a simple Activity that can view web pages.

    - -
      -
    1. Create a new project/Activity called HelloWebView.
    2. -
    3. Open the layout file. Insert a WebView so it looks like so: -
      -<?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:orientation="vertical">
      -
      -    <WebView 
      -        android:id="@+id/webview"
      -        android:layout_width="fill_parent"
      -        android:layout_height="fill_parent"
      -    />
      -
      -</LinearLayout>
      -
    4. - -
    5. Now open the HelloWebView.java file. - At the top of the class, instantiate a WebView object: -
      WebView webview;
      -

      Then add the following at the end of the onCreate() method:

      -
      -webview = (WebView) findViewById(R.id.webview);
      -webview.getSettings().setJavaScriptEnabled(true);
      -webview.loadUrl("http://www.google.com");
      -
      - -

      This captures the WebView we created in our layout, then requests a - {@link android.webkit.WebSettings} object and enables JavaScript. - Then we load a URL.

    6. - -
    7. Because we're accessing the internet, we need to add the appropriate - permissions to the Android manifest file. So open the AndroidManifest.xml file - and, add the following as a child of the <manifest> element: - -
      <uses-permission android:name="android.permission.INTERNET" />
    8. - -
    9. Now run it.
    10. -
    -

    You now have the world's simplest web page viewer. - It's not quite a browser yet. It only loads the page we've requested.

    - -
    - -

    We can load a page, but as soon as we click a link, the default Android web browser -handles the Intent, instead of our own WebView handling the action. So now we'll -override the {@link android.webkit.WebViewClient} to enable us to handle our own URL loading.

    - -
      -
    1. In the HelloAndroid Activity, add this nested private class: -
      -private class HelloWebViewClient extends WebViewClient {
      -    @Override
      -    public boolean shouldOverrideUrlLoading(WebView view, String url) {
      -        view.loadUrl(url);
      -        return true;
      -    }
      -}
    2. - -
    3. Now, in the onCreate() method, set an instance of the HelloWebViewClient - as our WebViewClient: -
      webview.setWebViewClient(new HelloWebViewClient());
      - -

      This line should immediately follow the initialization of our WebView object.

      -

      What we've done is create a WebViewClient that will load any URL selected in our -WebView in the same WebView. You can see this in the shouldOverrideUrlLoading() -method, above—it is passed the current WebView and the URL, so all we do -is load the URL in the given view. Returning true says that we've handled the URL -ourselves and the event should not bubble-up.

      -

      If you try it again, new pages will now load in the HelloWebView Activity. However, you'll notice that -we can't navigate back. We need to handle the back button -on the device, so that it will return to the previous page, rather than exit the application.

      -
    4. - -
    5. To handle the back button key press, add the following method inside the HelloWebView -Activity: -
       
      -@Override
      -public boolean onKeyDown(int keyCode, KeyEvent event) {
      -    if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {
      -        webview.goBack();
      -        return true;
      -    }
      -    return super.onKeyDown(keyCode, event);
      -}
      -

      The condition uses a {@link android.view.KeyEvent} to check - whether the key pressed is the BACK button and whether the - WebView is actually capable of navigating back (if it has a history). If both are - not true, then we send the event up the chain (and the Activity will close). - But if both are true, then we call goBack(), - which will navigate back one step in the history. We then return true to indicate - that we've handled the event.

      -
    6. -
    -

    When you open the application, it should look like this:

    - - -

    Resource

    -
      -
    • {@link android.webkit.WebView}
    • -
    • {@link android.webkit.WebViewClient}
    • -
    • {@link android.view.KeyEvent}
    • -
    - - - - - diff --git a/docs/html/guide/tutorials/views/images/android.png b/docs/html/guide/tutorials/views/images/android.png deleted file mode 100755 index 39a1ac729394b5f97674af47e2c04f37baf6be90..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/android.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/androidmarker.png b/docs/html/guide/tutorials/views/images/androidmarker.png deleted file mode 100755 index 8c43d4668218c55294e23d28b7f5872bc1dc2257..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/androidmarker.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-autocomplete.png b/docs/html/guide/tutorials/views/images/hello-autocomplete.png deleted file mode 100755 index e1fd80dfbf8b95560436fb3c63698a8cc8f54e5e..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-autocomplete.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-datepicker.png b/docs/html/guide/tutorials/views/images/hello-datepicker.png deleted file mode 100755 index 2075066bfdc17e38f02d8705509dd337d2e59ef7..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-datepicker.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-formstuff.png b/docs/html/guide/tutorials/views/images/hello-formstuff.png deleted file mode 100755 index 3b4bf54d10dd1f88ae4a0ed73155d8586720a52f..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-formstuff.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-listview.png b/docs/html/guide/tutorials/views/images/hello-listview.png deleted file mode 100755 index a1cf7aa6e90b4664b24ea614a452112880addbc2..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-listview.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-mapview.png b/docs/html/guide/tutorials/views/images/hello-mapview.png deleted file mode 100755 index 0956760a39c345791fc0d52fc42a963a4edf4d0f..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-mapview.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-spinner.png b/docs/html/guide/tutorials/views/images/hello-spinner.png deleted file mode 100755 index 42e2a915cb47f1e21f2f69640c7a88aeaba2865a..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-spinner.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-tabwidget.png b/docs/html/guide/tutorials/views/images/hello-tabwidget.png deleted file mode 100644 index 6a52356c8f9972b6d66eec8f8415aeda6792e7d6..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-tabwidget.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-timepicker.png b/docs/html/guide/tutorials/views/images/hello-timepicker.png deleted file mode 100755 index bd5a1eeadaae59fd84601092564bee83f86feeb8..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-timepicker.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/images/hello-webview.png b/docs/html/guide/tutorials/views/images/hello-webview.png deleted file mode 100755 index 283ce7d0f4d60591db9ae2d8c5646b034c16fcf0..0000000000000000000000000000000000000000 Binary files a/docs/html/guide/tutorials/views/images/hello-webview.png and /dev/null differ diff --git a/docs/html/guide/tutorials/views/index.html b/docs/html/guide/tutorials/views/index.html deleted file mode 100644 index 41d67965e59b74ad37c3bd8eed7fc84c22a1a5e8..0000000000000000000000000000000000000000 --- a/docs/html/guide/tutorials/views/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -Redirecting... - - -

    You should have been redirected. Please click here.

    - - \ No newline at end of file diff --git a/docs/html/guide/webapps/debugging.jd b/docs/html/guide/webapps/debugging.jd index c0dce48813c051cc62bd8e7bda018367274eb4f6..1eef1ae1c83980908a433ae9fd72d51e4deacb36 100644 --- a/docs/html/guide/webapps/debugging.jd +++ b/docs/html/guide/webapps/debugging.jd @@ -18,7 +18,7 @@ messages

    See also

      -
    1. Debugging
    2. +
    3. Debugging
    @@ -43,10 +43,10 @@ the device throws an error, as well as log messages written from your applicatio those written using JavaScript {@code console} APIs.

    To run logcat and view messages, execute {@code adb logcat} from your Android SDK {@code tools/} directory, or, from DDMS, select -Device > Run logcat. When using the ADT +Device > Run logcat. When using the ADT plugin for Eclipse, you can also view logcat messages by opening the Logcat view, available from Window > Show View > Other > Android > Logcat.

    -

    See Debugging +

    See Debugging for more information about .

    diff --git a/docs/html/guide/webapps/index.jd b/docs/html/guide/webapps/index.jd index 069290ae935269252879faab450fdb29da01fbb7..df7ddbe7b10230bab27b02e1b032f49447e40b53 100644 --- a/docs/html/guide/webapps/index.jd +++ b/docs/html/guide/webapps/index.jd @@ -1,71 +1,16 @@ -page.title=Web Apps Overview -@jd:body - -
    - -

    Figure 1. You can make your web content available to -users in two ways: in a traditional web browser and in an Android application, by -including a WebView in the layout.

    -
    - -

    There are essentially two ways to deliver an application on Android: as a -client-side application (developed using the Android SDK and installed on user devices as an {@code -.apk}) or as a web application (developed using web standards and accessed through a web -browser—there's nothing to install on user devices).

    +page.title=Web Apps +page.landing=true +page.landing.intro=Android has always been about connectivity and providing a great web browsing experience, so building your app with web technologies can be a great opportunity. Not only can you build an app on the web and still optimize your designs for Android's various screen sizes and densities, but you can also embed web-based content into your Android app using WebView. +page.landing.image= -

    The approach you choose for your application could depend on several factors, but Android makes -the decision to develop a web application easier by providing:

    -
      -
    • Support for viewport properties that allow you to properly size your web application -based on the screen size
    • -
    • CSS and JavaScript features that allow you to provide different styles and images -based on the screen's pixel density (screen resolution)
    • -
    - -

    Thus, your decision to develop a web application for Android can exclude consideration for -screen support, because it's already easy to make your web pages look good on all types of screens -powered by Android.

    - -

    Another great feature of Android is that you don't have to build your application purely on -the client or purely on the web. You can mix the two together by developing a client-side Android -application that embeds some web pages (using a {@link android.webkit.WebView} in your Android -application layout). Figure 1 visualizes how you can provide access to your web pages from either -a web browser or your Android application. However, you shouldn't develop an Android -application simply as a means to launch your web site. Rather, the web pages you embed in your -Android application should be designed especially for that environment. You can even define an -interface between your Android application and your web pages that allows JavaScript in the web -pages to call upon APIs in your Android application—providing Android APIs to your web-based -application.

    +@jd:body -

    Since Android 1.0, {@link android.webkit.WebView} has been available for Android -applications to embed web content in their layout and bind JavaScript to Android APIs. After -Android added support for more screen densities (adding support for high and low-density -screens), Android 2.0 added features to the WebKit framework to allow web pages to specify -viewport properties and query the screen density in order to modify styles -and image assets, as mentioned above. Because these features are a part of Android's WebKit -framework, both the Android Browser (the default web browser provided with the platform) and -{@link android.webkit.WebView} support the same viewport and screen density features.

    +
    -

    To develop a web application for Android-powered devices, you should read the -following documents:

    +
    +
    -
    -
    Targeting Screens from Web -Apps
    -
    How to properly size your web app on Android-powered devices and support -multiple screen densities. The information in this document is important if you're building a web -application that you at least expect to be available on Android-powered devices (which you should -assume for anything you publish on the web), but especially if you're targeting mobile devices -or using {@link android.webkit.WebView}.
    -
    Building Web Apps in -WebView
    -
    How to embed web pages into your Android application using {@link android.webkit.WebView} and -bind JavaScript to Android APIs.
    -
    Debugging Web Apps
    -
    How to debug web apps using JavaScript Console APIs.
    -
    Best Practices for Web -Apps
    -
    A list of practices you should follow, in order to provide an effective web application on -Android-powered devices.
    -
    +
    +
    +
    \ No newline at end of file diff --git a/docs/html/guide/webapps/overview.jd b/docs/html/guide/webapps/overview.jd new file mode 100644 index 0000000000000000000000000000000000000000..069290ae935269252879faab450fdb29da01fbb7 --- /dev/null +++ b/docs/html/guide/webapps/overview.jd @@ -0,0 +1,71 @@ +page.title=Web Apps Overview +@jd:body + +
    + +

    Figure 1. You can make your web content available to +users in two ways: in a traditional web browser and in an Android application, by +including a WebView in the layout.

    +
    + +

    There are essentially two ways to deliver an application on Android: as a +client-side application (developed using the Android SDK and installed on user devices as an {@code +.apk}) or as a web application (developed using web standards and accessed through a web +browser—there's nothing to install on user devices).

    + +

    The approach you choose for your application could depend on several factors, but Android makes +the decision to develop a web application easier by providing:

    +
      +
    • Support for viewport properties that allow you to properly size your web application +based on the screen size
    • +
    • CSS and JavaScript features that allow you to provide different styles and images +based on the screen's pixel density (screen resolution)
    • +
    + +

    Thus, your decision to develop a web application for Android can exclude consideration for +screen support, because it's already easy to make your web pages look good on all types of screens +powered by Android.

    + +

    Another great feature of Android is that you don't have to build your application purely on +the client or purely on the web. You can mix the two together by developing a client-side Android +application that embeds some web pages (using a {@link android.webkit.WebView} in your Android +application layout). Figure 1 visualizes how you can provide access to your web pages from either +a web browser or your Android application. However, you shouldn't develop an Android +application simply as a means to launch your web site. Rather, the web pages you embed in your +Android application should be designed especially for that environment. You can even define an +interface between your Android application and your web pages that allows JavaScript in the web +pages to call upon APIs in your Android application—providing Android APIs to your web-based +application.

    + +

    Since Android 1.0, {@link android.webkit.WebView} has been available for Android +applications to embed web content in their layout and bind JavaScript to Android APIs. After +Android added support for more screen densities (adding support for high and low-density +screens), Android 2.0 added features to the WebKit framework to allow web pages to specify +viewport properties and query the screen density in order to modify styles +and image assets, as mentioned above. Because these features are a part of Android's WebKit +framework, both the Android Browser (the default web browser provided with the platform) and +{@link android.webkit.WebView} support the same viewport and screen density features.

    + +

    To develop a web application for Android-powered devices, you should read the +following documents:

    + +
    +
    Targeting Screens from Web +Apps
    +
    How to properly size your web app on Android-powered devices and support +multiple screen densities. The information in this document is important if you're building a web +application that you at least expect to be available on Android-powered devices (which you should +assume for anything you publish on the web), but especially if you're targeting mobile devices +or using {@link android.webkit.WebView}.
    +
    Building Web Apps in +WebView
    +
    How to embed web pages into your Android application using {@link android.webkit.WebView} and +bind JavaScript to Android APIs.
    +
    Debugging Web Apps
    +
    How to debug web apps using JavaScript Console APIs.
    +
    Best Practices for Web +Apps
    +
    A list of practices you should follow, in order to provide an effective web application on +Android-powered devices.
    +
    + diff --git a/docs/html/images/about/growth-chart.png b/docs/html/images/about/growth-chart.png new file mode 100644 index 0000000000000000000000000000000000000000..fee4e0942545bb57314fbb2649f97c95b2e4f4fd Binary files /dev/null and b/docs/html/images/about/growth-chart.png differ diff --git a/docs/html/images/activity_fragment_lifecycle.png b/docs/html/images/activity_fragment_lifecycle.png index bab957960df15235844b735cbbbbb34b4d131535..c44777493cfae2c58d709b9b94060e89da3bd285 100644 Binary files a/docs/html/images/activity_fragment_lifecycle.png and b/docs/html/images/activity_fragment_lifecycle.png differ diff --git a/docs/html/images/activity_lifecycle.png b/docs/html/images/activity_lifecycle.png index 357349c44254c23d0f864e8cf9b59a705d282595..879f51f6e8fafe75d267984680ef63f85b118dc5 100644 Binary files a/docs/html/images/activity_lifecycle.png and b/docs/html/images/activity_lifecycle.png differ diff --git a/docs/html/images/android-logo.png b/docs/html/images/android-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d72fed1b2b31f33117fb0bb7280911bcc09fbc22 Binary files /dev/null and b/docs/html/images/android-logo.png differ diff --git a/docs/html/images/billing_subscription_flow.png b/docs/html/images/billing_subscription_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..a293228bd7b96e1ae5dd0e6187276dd8ac06293e Binary files /dev/null and b/docs/html/images/billing_subscription_flow.png differ diff --git a/docs/html/images/brand/android_app_on_play_logo_large.png b/docs/html/images/brand/android_app_on_play_logo_large.png new file mode 100644 index 0000000000000000000000000000000000000000..a46bf3538c4ef76ba874a97e1a62777fa2c848bd Binary files /dev/null and b/docs/html/images/brand/android_app_on_play_logo_large.png differ diff --git a/docs/html/images/brand/android_app_on_play_logo_small.png b/docs/html/images/brand/android_app_on_play_logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..2d8ef525df084fe8907447b17871de789b061d9f Binary files /dev/null and b/docs/html/images/brand/android_app_on_play_logo_small.png differ diff --git a/docs/html/images/brand/droid.gif b/docs/html/images/brand/droid.gif new file mode 100644 index 0000000000000000000000000000000000000000..7c7b941218c9b7910ea7956339f76279940c50a3 Binary files /dev/null and b/docs/html/images/brand/droid.gif differ diff --git a/docs/html/images/brand/get_it_on_play_logo_large.png b/docs/html/images/brand/get_it_on_play_logo_large.png new file mode 100644 index 0000000000000000000000000000000000000000..8b48767fc561703c3cacb88c299b68786a33986c Binary files /dev/null and b/docs/html/images/brand/get_it_on_play_logo_large.png differ diff --git a/docs/html/images/brand/get_it_on_play_logo_small.png b/docs/html/images/brand/get_it_on_play_logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..1fcbec86b92565fbb6b36221764c04de3562672a Binary files /dev/null and b/docs/html/images/brand/get_it_on_play_logo_small.png differ diff --git a/docs/html/images/brand/google_play_logo_450.png b/docs/html/images/brand/google_play_logo_450.png new file mode 100644 index 0000000000000000000000000000000000000000..59a1fcfdad1d6cc5313974f6c5d4190a0440ee91 Binary files /dev/null and b/docs/html/images/brand/google_play_logo_450.png differ diff --git a/docs/html/images/brand/learnmore.gif b/docs/html/images/brand/learnmore.gif new file mode 100644 index 0000000000000000000000000000000000000000..70a8e6bc45796ace5b4348c32942b1c553e08d6d Binary files /dev/null and b/docs/html/images/brand/learnmore.gif differ diff --git a/docs/html/images/brand/logo_android.gif b/docs/html/images/brand/logo_android.gif new file mode 100644 index 0000000000000000000000000000000000000000..169c764c097690f8b9583042f47bdfda3a657a28 Binary files /dev/null and b/docs/html/images/brand/logo_android.gif differ diff --git a/docs/html/images/brand/mediaplayer.gif b/docs/html/images/brand/mediaplayer.gif new file mode 100644 index 0000000000000000000000000000000000000000..860d110866fa562afea05fbc80cc5156d53be989 Binary files /dev/null and b/docs/html/images/brand/mediaplayer.gif differ diff --git a/docs/html/images/brand/norad.gif b/docs/html/images/brand/norad.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8707bdd871a696db0f939529ca96f7772f3ab6e Binary files /dev/null and b/docs/html/images/brand/norad.gif differ diff --git a/docs/html/images/dac-design-icon.png b/docs/html/images/dac-design-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..245f080113475e6dfa36e2d1a7e4a07351ee80a4 Binary files /dev/null and b/docs/html/images/dac-design-icon.png differ diff --git a/docs/html/images/debugging-tall.png b/docs/html/images/debugging-tall.png new file mode 100644 index 0000000000000000000000000000000000000000..d29c4d151148b2aa06ff51e1eebf56290ae0baf8 Binary files /dev/null and b/docs/html/images/debugging-tall.png differ diff --git a/docs/html/images/develop-placeholder.png b/docs/html/images/develop-placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..35a8767892acce7cbae5ea05f0d6c1d45c38f9f5 Binary files /dev/null and b/docs/html/images/develop-placeholder.png differ diff --git a/docs/html/images/develop/app_components.png b/docs/html/images/develop/app_components.png new file mode 100644 index 0000000000000000000000000000000000000000..0e3460d8046cc1cdde9752c50c6fb96910a1ad72 Binary files /dev/null and b/docs/html/images/develop/app_components.png differ diff --git a/docs/html/images/develop/auth-code.png b/docs/html/images/develop/auth-code.png new file mode 100644 index 0000000000000000000000000000000000000000..6dfabf9cc35f5e78cda8a59e57ddb80a1377102d Binary files /dev/null and b/docs/html/images/develop/auth-code.png differ diff --git a/docs/html/images/develop/connectivity.png b/docs/html/images/develop/connectivity.png new file mode 100644 index 0000000000000000000000000000000000000000..2c9dadb2d9e098f600190630e739e476b6a0cc7f Binary files /dev/null and b/docs/html/images/develop/connectivity.png differ diff --git a/docs/html/images/develop/marquee-play.png b/docs/html/images/develop/marquee-play.png new file mode 100644 index 0000000000000000000000000000000000000000..de8802d349e2845d3b1bb85c7115c347a72c0fe9 Binary files /dev/null and b/docs/html/images/develop/marquee-play.png differ diff --git a/docs/html/images/develop/resources.png b/docs/html/images/develop/resources.png new file mode 100644 index 0000000000000000000000000000000000000000..f6cbf5d2bddea7077b0ea7cd7122dd7d03c60f35 Binary files /dev/null and b/docs/html/images/develop/resources.png differ diff --git a/docs/html/images/distribute/feature-market.png b/docs/html/images/distribute/feature-market.png new file mode 100644 index 0000000000000000000000000000000000000000..e9d3abf1e6a8f02662da900b1e227b6a1c38685e Binary files /dev/null and b/docs/html/images/distribute/feature-market.png differ diff --git a/docs/html/images/distribute/feature-monetize.png b/docs/html/images/distribute/feature-monetize.png new file mode 100644 index 0000000000000000000000000000000000000000..4b1b5095cbf40edf406969f6b8a48e49339a0abe Binary files /dev/null and b/docs/html/images/distribute/feature-monetize.png differ diff --git a/docs/html/images/distribute/feature-register.png b/docs/html/images/distribute/feature-register.png new file mode 100644 index 0000000000000000000000000000000000000000..ad387bf2da2d028b9b079f69fea46d0526b99670 Binary files /dev/null and b/docs/html/images/distribute/feature-register.png differ diff --git a/docs/html/images/distribute/marquee-play.png b/docs/html/images/distribute/marquee-play.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa4823c6af75b6838ff447a7aa06227167565b4 Binary files /dev/null and b/docs/html/images/distribute/marquee-play.png differ diff --git a/docs/html/images/editorschoice_ann.png b/docs/html/images/editorschoice_ann.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f2c06834c898b9863638854f22cda56b8d3fa6 Binary files /dev/null and b/docs/html/images/editorschoice_ann.png differ diff --git a/docs/html/images/fragment_lifecycle.png b/docs/html/images/fragment_lifecycle.png index d207db42514fc7c5b76b82430d1e8f2c93791f81..fcaa63b646b0bfd4336e1b505cf3e51648be088a 100644 Binary files a/docs/html/images/fragment_lifecycle.png and b/docs/html/images/fragment_lifecycle.png differ diff --git a/docs/html/images/fundamentals/diagram_backstack.png b/docs/html/images/fundamentals/diagram_backstack.png index bdb6893047418f248b46fce545959ce14e762e9a..5ddadcbe4f4779876189254531415dd04c7b741e 100644 Binary files a/docs/html/images/fundamentals/diagram_backstack.png and b/docs/html/images/fundamentals/diagram_backstack.png differ diff --git a/docs/html/images/fundamentals/diagram_backstack_singletask_multiactivity.png b/docs/html/images/fundamentals/diagram_backstack_singletask_multiactivity.png index aab324ddd5fd11531a1ca360946cc849e32b58a0..b9e5ed48f69705f0184c732b7cef3868448e8cc5 100644 Binary files a/docs/html/images/fundamentals/diagram_backstack_singletask_multiactivity.png and b/docs/html/images/fundamentals/diagram_backstack_singletask_multiactivity.png differ diff --git a/docs/html/images/fundamentals/diagram_multiple_instances.png b/docs/html/images/fundamentals/diagram_multiple_instances.png index 64b476ff436e8e2c549e3c5603368b8f44c8edb2..606f540955c576c853640adffe984a433fc20769 100644 Binary files a/docs/html/images/fundamentals/diagram_multiple_instances.png and b/docs/html/images/fundamentals/diagram_multiple_instances.png differ diff --git a/docs/html/images/fundamentals/diagram_multitasking.png b/docs/html/images/fundamentals/diagram_multitasking.png index e21959992bd6970d8e884efea1c80b552bf15424..ffe5c65151d8b60201263be34b6a6083f958de10 100644 Binary files a/docs/html/images/fundamentals/diagram_multitasking.png and b/docs/html/images/fundamentals/diagram_multitasking.png differ diff --git a/docs/html/images/fundamentals/fragments.png b/docs/html/images/fundamentals/fragments.png index bf986b1abb30c9e4c38ef73bc345b14e93e4d4ab..cb7204b46227b84ea550c7eff2b3fd53103ee3f2 100644 Binary files a/docs/html/images/fundamentals/fragments.png and b/docs/html/images/fundamentals/fragments.png differ diff --git a/docs/html/images/fundamentals/restore_instance.png b/docs/html/images/fundamentals/restore_instance.png index 57a95eca6f994a068db192fd226948cef9ad5827..698b83a8149c0846fb158e57f10bb40fd46c1498 100644 Binary files a/docs/html/images/fundamentals/restore_instance.png and b/docs/html/images/fundamentals/restore_instance.png differ diff --git a/docs/html/images/fundamentals/service_binding_tree_lifecycle.png b/docs/html/images/fundamentals/service_binding_tree_lifecycle.png index 526521625b5ad8cd637984058408dd72223f2bbc..8b826f677babdb028b2c971e47c4a3863e7f6fa0 100644 Binary files a/docs/html/images/fundamentals/service_binding_tree_lifecycle.png and b/docs/html/images/fundamentals/service_binding_tree_lifecycle.png differ diff --git a/docs/html/images/gp-apps-home.png b/docs/html/images/gp-apps-home.png new file mode 100644 index 0000000000000000000000000000000000000000..851f7227fb7943fb1fef403526725cfc74bdcec6 Binary files /dev/null and b/docs/html/images/gp-apps-home.png differ diff --git a/docs/html/images/gp-buyer-currency.png b/docs/html/images/gp-buyer-currency.png new file mode 100644 index 0000000000000000000000000000000000000000..51b810857194e4122c8ffa8b4909de2ec0d23279 Binary files /dev/null and b/docs/html/images/gp-buyer-currency.png differ diff --git a/docs/html/images/gp-collectibles.png b/docs/html/images/gp-collectibles.png new file mode 100644 index 0000000000000000000000000000000000000000..a63cd505114b55aaee5f29666b73f409388e3fa9 Binary files /dev/null and b/docs/html/images/gp-collectibles.png differ diff --git a/docs/html/images/gp-dc-countries.png b/docs/html/images/gp-dc-countries.png new file mode 100644 index 0000000000000000000000000000000000000000..00d0d5e3ff7499b100c231113a108ff5b931f765 Binary files /dev/null and b/docs/html/images/gp-dc-countries.png differ diff --git a/docs/html/images/gp-dc-details.png b/docs/html/images/gp-dc-details.png new file mode 100644 index 0000000000000000000000000000000000000000..567567e65503e3a84b4855d53dca8de9d6438c37 Binary files /dev/null and b/docs/html/images/gp-dc-details.png differ diff --git a/docs/html/images/gp-dc-home.png b/docs/html/images/gp-dc-home.png new file mode 100644 index 0000000000000000000000000000000000000000..381d0db017c45caafa332881d2fa5c1e7394cec8 Binary files /dev/null and b/docs/html/images/gp-dc-home.png differ diff --git a/docs/html/images/gp-dc-profile.png b/docs/html/images/gp-dc-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..e52636970d35e8e54c22adf7b77137cc5966e717 Binary files /dev/null and b/docs/html/images/gp-dc-profile.png differ diff --git a/docs/html/images/gp-dc-reviews.png b/docs/html/images/gp-dc-reviews.png new file mode 100644 index 0000000000000000000000000000000000000000..cab175a7d8d5f51b1b740e72c8b5ccc1ccd7e47d Binary files /dev/null and b/docs/html/images/gp-dc-reviews.png differ diff --git a/docs/html/images/gp-dc-stats-mini.png b/docs/html/images/gp-dc-stats-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..d29a270bfd81401a93155314cb1bb81adfa39502 Binary files /dev/null and b/docs/html/images/gp-dc-stats-mini.png differ diff --git a/docs/html/images/gp-dc-stats.png b/docs/html/images/gp-dc-stats.png new file mode 100644 index 0000000000000000000000000000000000000000..06f88e56d0bf1e732e797e1f23caf3045408beac Binary files /dev/null and b/docs/html/images/gp-dc-stats.png differ diff --git a/docs/html/images/gp-details-pages-magicpiano.png b/docs/html/images/gp-details-pages-magicpiano.png new file mode 100644 index 0000000000000000000000000000000000000000..4bb196273d8cf08368954516ac8c39beb5f45a92 Binary files /dev/null and b/docs/html/images/gp-details-pages-magicpiano.png differ diff --git a/docs/html/images/gp-details-ww-purchase.png b/docs/html/images/gp-details-ww-purchase.png new file mode 100644 index 0000000000000000000000000000000000000000..46df4434f8edb3e14f8e8df83145ca3a9b1a4569 Binary files /dev/null and b/docs/html/images/gp-details-ww-purchase.png differ diff --git a/docs/html/images/gp-details-ww.png b/docs/html/images/gp-details-ww.png new file mode 100644 index 0000000000000000000000000000000000000000..ccc522c79e71f2f42f1b3ab334c00feefd08d3ee Binary files /dev/null and b/docs/html/images/gp-details-ww.png differ diff --git a/docs/html/images/gp-devconsole-home.png b/docs/html/images/gp-devconsole-home.png new file mode 100644 index 0000000000000000000000000000000000000000..1d758fd97a8868afd66590cad603fe13da87472a Binary files /dev/null and b/docs/html/images/gp-devconsole-home.png differ diff --git a/docs/html/images/gp-device.png b/docs/html/images/gp-device.png new file mode 100644 index 0000000000000000000000000000000000000000..86e46e5da746c459fa6c9494d23919c18cef7b65 Binary files /dev/null and b/docs/html/images/gp-device.png differ diff --git a/docs/html/images/gp-games-home.png b/docs/html/images/gp-games-home.png new file mode 100644 index 0000000000000000000000000000000000000000..81b7f7a2897b26e09d72573c40b460deee8dd880 Binary files /dev/null and b/docs/html/images/gp-games-home.png differ diff --git a/docs/html/images/gp-growth-downloads.png b/docs/html/images/gp-growth-downloads.png new file mode 100644 index 0000000000000000000000000000000000000000..4a4b194a0476e98650da15fce5652fbb2395622e Binary files /dev/null and b/docs/html/images/gp-growth-downloads.png differ diff --git a/docs/html/images/gp-rating-web.png b/docs/html/images/gp-rating-web.png new file mode 100644 index 0000000000000000000000000000000000000000..0885826995dc278c2c18d9dd1145cf88522fb429 Binary files /dev/null and b/docs/html/images/gp-rating-web.png differ diff --git a/docs/html/images/gp-sendto.png b/docs/html/images/gp-sendto.png new file mode 100644 index 0000000000000000000000000000000000000000..7409c140c05a959f1067469293adfdd57fcce6bc Binary files /dev/null and b/docs/html/images/gp-sendto.png differ diff --git a/docs/html/images/gp-subs.png b/docs/html/images/gp-subs.png new file mode 100644 index 0000000000000000000000000000000000000000..9b3a7df3f1a1bfdbd0a80ffe9e415673605814c9 Binary files /dev/null and b/docs/html/images/gp-subs.png differ diff --git a/docs/html/images/gp-supported-dev-requirements.png b/docs/html/images/gp-supported-dev-requirements.png new file mode 100644 index 0000000000000000000000000000000000000000..d84f34efe089f1aee60d5439f1f5813e56c8d623 Binary files /dev/null and b/docs/html/images/gp-supported-dev-requirements.png differ diff --git a/docs/html/images/gp-tab.png b/docs/html/images/gp-tab.png new file mode 100644 index 0000000000000000000000000000000000000000..4673d21d76225d019f160c4f345c0192d464328b Binary files /dev/null and b/docs/html/images/gp-tab.png differ diff --git a/docs/html/images/gp-top-new-paid.png b/docs/html/images/gp-top-new-paid.png new file mode 100644 index 0000000000000000000000000000000000000000..d98d6cad4e67c0c2be8efa3e8cb4d30b288c37f2 Binary files /dev/null and b/docs/html/images/gp-top-new-paid.png differ diff --git a/docs/html/images/gpp-cat-feature280-photo.png b/docs/html/images/gpp-cat-feature280-photo.png new file mode 100644 index 0000000000000000000000000000000000000000..ae2749b88cafb913666ffef6a84cd475b9398fc4 Binary files /dev/null and b/docs/html/images/gpp-cat-feature280-photo.png differ diff --git a/docs/html/images/gpp-cat-feature280-puzzle.png b/docs/html/images/gpp-cat-feature280-puzzle.png new file mode 100644 index 0000000000000000000000000000000000000000..db203c6f1e54711121f5f1daab84aee31c657eaf Binary files /dev/null and b/docs/html/images/gpp-cat-feature280-puzzle.png differ diff --git a/docs/html/images/gpp-cat-feature280-sports.png b/docs/html/images/gpp-cat-feature280-sports.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd70aaf7a9655db715d35b150ec2bc50ee3be8e Binary files /dev/null and b/docs/html/images/gpp-cat-feature280-sports.png differ diff --git a/docs/html/images/home-marquee.jpg b/docs/html/images/home-marquee.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94d83d738da03f63f9f0272721e378dd7c75bfb7 Binary files /dev/null and b/docs/html/images/home-marquee.jpg differ diff --git a/docs/html/images/home/design.png b/docs/html/images/home/design.png new file mode 100644 index 0000000000000000000000000000000000000000..bbaa767b9aa84425220d59741021162e2abbfb27 Binary files /dev/null and b/docs/html/images/home/design.png differ diff --git a/docs/html/images/home/developers_live.png b/docs/html/images/home/developers_live.png new file mode 100644 index 0000000000000000000000000000000000000000..13dbb5c580e95cbd6d301ece46085e5b23f0b00f Binary files /dev/null and b/docs/html/images/home/developers_live.png differ diff --git a/docs/html/images/home/google-io.png b/docs/html/images/home/google-io.png new file mode 100644 index 0000000000000000000000000000000000000000..d21a24da46bd1645ce5abf237a66c3eeaef6e688 Binary files /dev/null and b/docs/html/images/home/google-io.png differ diff --git a/docs/html/images/home/google-play.png b/docs/html/images/home/google-play.png new file mode 100644 index 0000000000000000000000000000000000000000..20321542fe407e39c084e9528e0b87e3eea58652 Binary files /dev/null and b/docs/html/images/home/google-play.png differ diff --git a/docs/html/images/home/ics-android.png b/docs/html/images/home/ics-android.png new file mode 100644 index 0000000000000000000000000000000000000000..f4c3b5bee165848e1878506a3806e0dee53b36a1 Binary files /dev/null and b/docs/html/images/home/ics-android.png differ diff --git a/docs/html/images/layoutparams.png b/docs/html/images/layoutparams.png index d99625e2efa95294f3163d5031033505881ab5d3..ac31e44a65f0a41ad25dbb09f43940abe546a0a2 100644 Binary files a/docs/html/images/layoutparams.png and b/docs/html/images/layoutparams.png differ diff --git a/docs/html/images/market/version-codes.png b/docs/html/images/market/version-codes.png index c0c985864fa9b00ba64a604e1cfdeecfe48df270..aa4fd4193ef3dc469f922498019a0d5c5daaff4f 100644 Binary files a/docs/html/images/market/version-codes.png and b/docs/html/images/market/version-codes.png differ diff --git a/docs/html/images/opengl/ccw-square.png b/docs/html/images/opengl/ccw-square.png new file mode 100644 index 0000000000000000000000000000000000000000..010def9537bd191fab3bc36e4b98068cce7e222f Binary files /dev/null and b/docs/html/images/opengl/ccw-square.png differ diff --git a/docs/html/images/opengl/ccw-winding.png b/docs/html/images/opengl/ccw-winding.png new file mode 100644 index 0000000000000000000000000000000000000000..a7ece315a1460c4962af7a0deca622febb8f8604 Binary files /dev/null and b/docs/html/images/opengl/ccw-winding.png differ diff --git a/docs/html/images/opengl/coordinates.png b/docs/html/images/opengl/coordinates.png index 7180cd5cecf3db079685aad9846a16881f7c2537..7a02cdd5b82c9e814e2961680aec108d1fa76d0d 100644 Binary files a/docs/html/images/opengl/coordinates.png and b/docs/html/images/opengl/coordinates.png differ diff --git a/docs/html/images/opengl/helloopengl-es10-1.png b/docs/html/images/opengl/helloopengl-es10-1.png deleted file mode 100644 index 9aa2376ed720f4b0b07c211ff0f658109b6d6869..0000000000000000000000000000000000000000 Binary files a/docs/html/images/opengl/helloopengl-es10-1.png and /dev/null differ diff --git a/docs/html/images/opengl/helloopengl-es10-2.png b/docs/html/images/opengl/helloopengl-es10-2.png deleted file mode 100644 index cdfd9c70539a434740e7de360deb0ccf5e412411..0000000000000000000000000000000000000000 Binary files a/docs/html/images/opengl/helloopengl-es10-2.png and /dev/null differ diff --git a/docs/html/images/opengl/helloopengl-es20-1.png b/docs/html/images/opengl/helloopengl-es20-1.png deleted file mode 100644 index 1f76c22cb23b32087d647aba7e01aaf131b8508c..0000000000000000000000000000000000000000 Binary files a/docs/html/images/opengl/helloopengl-es20-1.png and /dev/null differ diff --git a/docs/html/images/opengl/helloopengl-es20-2.png b/docs/html/images/opengl/helloopengl-es20-2.png deleted file mode 100644 index 0fbbe60010e3b021a73ce8fc39043ac6cfa599dd..0000000000000000000000000000000000000000 Binary files a/docs/html/images/opengl/helloopengl-es20-2.png and /dev/null differ diff --git a/docs/html/images/opengl/ogl-triangle-projected.png b/docs/html/images/opengl/ogl-triangle-projected.png new file mode 100644 index 0000000000000000000000000000000000000000..d10bbdc0d27f9462b48c53537fade70bbd711ce6 Binary files /dev/null and b/docs/html/images/opengl/ogl-triangle-projected.png differ diff --git a/docs/html/images/opengl/ogl-triangle-touch.png b/docs/html/images/opengl/ogl-triangle-touch.png new file mode 100644 index 0000000000000000000000000000000000000000..35177a4670b0ba47b63bcff017cfae8b9c847ff3 Binary files /dev/null and b/docs/html/images/opengl/ogl-triangle-touch.png differ diff --git a/docs/html/images/opengl/ogl-triangle.png b/docs/html/images/opengl/ogl-triangle.png new file mode 100644 index 0000000000000000000000000000000000000000..3d4a385f198a67ca2e6c54b3ce607eeb1db1a1d9 Binary files /dev/null and b/docs/html/images/opengl/ogl-triangle.png differ diff --git a/docs/html/images/play_tableft.png b/docs/html/images/play_tableft.png new file mode 100644 index 0000000000000000000000000000000000000000..14740cb4347d632710a6352f8812deb17fffacdd Binary files /dev/null and b/docs/html/images/play_tableft.png differ diff --git a/docs/html/images/providers/ContactsDataFlow.png b/docs/html/images/providers/ContactsDataFlow.png new file mode 100644 index 0000000000000000000000000000000000000000..403afc77441e8335cba7517cb95f36f5e1a019ff Binary files /dev/null and b/docs/html/images/providers/ContactsDataFlow.png differ diff --git a/docs/html/images/providers/contacts_structure.png b/docs/html/images/providers/contacts_structure.png new file mode 100644 index 0000000000000000000000000000000000000000..3cdc5de5a15f335f6d82e83b0f3e47e7036cfecb Binary files /dev/null and b/docs/html/images/providers/contacts_structure.png differ diff --git a/docs/html/images/providers/contacts_tables.png b/docs/html/images/providers/contacts_tables.png new file mode 100644 index 0000000000000000000000000000000000000000..c44994830a9c68939e5623f3f8aa54f0e52efbeb Binary files /dev/null and b/docs/html/images/providers/contacts_tables.png differ diff --git a/docs/html/images/providers/data_columns.png b/docs/html/images/providers/data_columns.png new file mode 100644 index 0000000000000000000000000000000000000000..6e9d90e669c73ec2c5adfe2026a9359631398b68 Binary files /dev/null and b/docs/html/images/providers/data_columns.png differ diff --git a/docs/html/images/publishing/publishing_unknown_sources.png b/docs/html/images/publishing/publishing_unknown_sources.png deleted file mode 100755 index ad310a1810dcd2aa6435ec881e173a411fa168f3..0000000000000000000000000000000000000000 Binary files a/docs/html/images/publishing/publishing_unknown_sources.png and /dev/null differ diff --git a/docs/html/images/publishing/publishing_unknown_sources_sm.png b/docs/html/images/publishing/publishing_unknown_sources_sm.png new file mode 100644 index 0000000000000000000000000000000000000000..34cba2a7f8584b8ad3ce0f2fc5ade1414d32b131 Binary files /dev/null and b/docs/html/images/publishing/publishing_unknown_sources_sm.png differ diff --git a/docs/html/images/publishing/publishing_via_email.png b/docs/html/images/publishing/publishing_via_email.png index 54c64bd6e8099b429080fa121ffba31044616c90..d367747230b46ab0aefe830852b7e9b62f499940 100755 Binary files a/docs/html/images/publishing/publishing_via_email.png and b/docs/html/images/publishing/publishing_via_email.png differ diff --git a/docs/html/images/resources/res-selection-flowchart.png b/docs/html/images/resources/res-selection-flowchart.png index 5de7688a2532094b7003e4db415c8087c8594641..149f4dcadda2b7513c8cd915d7412ec7429fea10 100644 Binary files a/docs/html/images/resources/res-selection-flowchart.png and b/docs/html/images/resources/res-selection-flowchart.png differ diff --git a/docs/html/images/resources/resource_devices_diagram1.png b/docs/html/images/resources/resource_devices_diagram1.png index 0b3c856ff8592c7d52d570892b0a3fb58082bdd3..e2f515fdb57086e932fa90e7ee640df0eaae7a33 100644 Binary files a/docs/html/images/resources/resource_devices_diagram1.png and b/docs/html/images/resources/resource_devices_diagram1.png differ diff --git a/docs/html/images/resources/resource_devices_diagram2.png b/docs/html/images/resources/resource_devices_diagram2.png index d32a7811f64c3d72c17df1afd247e7cf306b5673..f0a3886bf30fba38fabda853e3bc5ae1412400ad 100644 Binary files a/docs/html/images/resources/resource_devices_diagram2.png and b/docs/html/images/resources/resource_devices_diagram2.png differ diff --git a/docs/html/images/robot-sdk.png b/docs/html/images/robot-sdk.png new file mode 100644 index 0000000000000000000000000000000000000000..962d4d512436f1d129dae7852be49aa32643b5a7 Binary files /dev/null and b/docs/html/images/robot-sdk.png differ diff --git a/docs/html/images/robot-tiny.png b/docs/html/images/robot-tiny.png new file mode 100644 index 0000000000000000000000000000000000000000..f925062b3fb6cb5189398b19b4f7b90d87fe4244 Binary files /dev/null and b/docs/html/images/robot-tiny.png differ diff --git a/docs/html/images/screens_support/screens-densities.png b/docs/html/images/screens_support/screens-densities.png index edbd1e32572a866df1717d485820c0905040402a..3220ecf5f687ab5ea54520f4dd3f1138f31f54f5 100644 Binary files a/docs/html/images/screens_support/screens-densities.png and b/docs/html/images/screens_support/screens-densities.png differ diff --git a/docs/html/images/screens_support/screens-ranges.png b/docs/html/images/screens_support/screens-ranges.png index d8a0ffae549f65a47fcea92c1512535a04a2b2ca..c6a06771a554f7de23f1287cab1f75564dfcb92d 100644 Binary files a/docs/html/images/screens_support/screens-ranges.png and b/docs/html/images/screens_support/screens-ranges.png differ diff --git a/docs/html/images/sdk-cube.png b/docs/html/images/sdk-cube.png new file mode 100644 index 0000000000000000000000000000000000000000..58b43aec28c91212587ba3e75672c8dbc1e7ab4d Binary files /dev/null and b/docs/html/images/sdk-cube.png differ diff --git a/docs/html/images/service_lifecycle.png b/docs/html/images/service_lifecycle.png index 7ab96d7c733a7b021f3d28ef9f52833d46c4983d..413bf5627f42e64010b31f7c4851ce2867c77bbe 100644 Binary files a/docs/html/images/service_lifecycle.png and b/docs/html/images/service_lifecycle.png differ diff --git a/docs/html/images/tools-home.png b/docs/html/images/tools-home.png new file mode 100644 index 0000000000000000000000000000000000000000..291a36138a4efa9e881e5f4e868521a46473bf44 Binary files /dev/null and b/docs/html/images/tools-home.png differ diff --git a/docs/html/images/topdev_ann.png b/docs/html/images/topdev_ann.png new file mode 100644 index 0000000000000000000000000000000000000000..9564387e8d8b6b7c02b162a3bf26649548bd9c92 Binary files /dev/null and b/docs/html/images/topdev_ann.png differ diff --git a/docs/html/images/training/basics/basic-lifecycle-create.png b/docs/html/images/training/basics/basic-lifecycle-create.png index 01d7328da8a4e3f40ba09df34ff620f6e13a4636..d6c66fc0fcc6dc94df18cffd6cd6ab8ef44b1b48 100644 Binary files a/docs/html/images/training/basics/basic-lifecycle-create.png and b/docs/html/images/training/basics/basic-lifecycle-create.png differ diff --git a/docs/html/images/training/basics/basic-lifecycle-paused.png b/docs/html/images/training/basics/basic-lifecycle-paused.png index fcb8bd245fa95f40f2df421fa075b4df2e8db547..1b81c07b3ffb3d558863512a096eb8446b9d7638 100644 Binary files a/docs/html/images/training/basics/basic-lifecycle-paused.png and b/docs/html/images/training/basics/basic-lifecycle-paused.png differ diff --git a/docs/html/images/training/basics/basic-lifecycle-savestate.png b/docs/html/images/training/basics/basic-lifecycle-savestate.png index d74f1baa303344bce52c804debe4c9078cad7b8a..9ea9484fc620680fbcc89bae3d1e77c0b18af458 100644 Binary files a/docs/html/images/training/basics/basic-lifecycle-savestate.png and b/docs/html/images/training/basics/basic-lifecycle-savestate.png differ diff --git a/docs/html/images/training/basics/basic-lifecycle-stopped.png b/docs/html/images/training/basics/basic-lifecycle-stopped.png index 26c22ee0cc33afe9c4b681b6b9e0355c2d754628..6f45fccb7f4221fbffa98a8f0c83de03d827a855 100644 Binary files a/docs/html/images/training/basics/basic-lifecycle-stopped.png and b/docs/html/images/training/basics/basic-lifecycle-stopped.png differ diff --git a/docs/html/images/training/basics/basic-lifecycle.png b/docs/html/images/training/basics/basic-lifecycle.png index 61eb422de9ba39a53e46bd86a701f4eb69347128..f991787f68b8c8c58dbe4d4bb03e353c3553d1bc 100644 Binary files a/docs/html/images/training/basics/basic-lifecycle.png and b/docs/html/images/training/basics/basic-lifecycle.png differ diff --git a/docs/html/images/training/basics/network-settings1.png b/docs/html/images/training/basics/network-settings1.png new file mode 100644 index 0000000000000000000000000000000000000000..9eaf207d29eec4076b7d913c98845028db2b939d Binary files /dev/null and b/docs/html/images/training/basics/network-settings1.png differ diff --git a/docs/html/images/training/basics/network-settings2.png b/docs/html/images/training/basics/network-settings2.png new file mode 100644 index 0000000000000000000000000000000000000000..5f4dc63aa96da8cf1d9db3775c348bd4a9a2a385 Binary files /dev/null and b/docs/html/images/training/basics/network-settings2.png differ diff --git a/docs/html/images/ui/button-types.png b/docs/html/images/ui/button-types.png new file mode 100644 index 0000000000000000000000000000000000000000..dcb083f0a687b4070056d83c74b57e6a9579ab49 Binary files /dev/null and b/docs/html/images/ui/button-types.png differ diff --git a/docs/html/images/ui/buttons-holo.png b/docs/html/images/ui/buttons-holo.png new file mode 100644 index 0000000000000000000000000000000000000000..16e2fd274b11b6a23a130d24fb4b6bbd4b648f27 Binary files /dev/null and b/docs/html/images/ui/buttons-holo.png differ diff --git a/docs/html/images/ui/checkboxes.png b/docs/html/images/ui/checkboxes.png new file mode 100644 index 0000000000000000000000000000000000000000..8878fb137cf6cee1aef2246ad24940905d7ccef8 Binary files /dev/null and b/docs/html/images/ui/checkboxes.png differ diff --git a/docs/html/images/ui/edittext-actionlabel.png b/docs/html/images/ui/edittext-actionlabel.png new file mode 100644 index 0000000000000000000000000000000000000000..a0e9fe9fcb35d03f45e4257feebc0315f342ce5d Binary files /dev/null and b/docs/html/images/ui/edittext-actionlabel.png differ diff --git a/docs/html/images/ui/edittext-actionsend.png b/docs/html/images/ui/edittext-actionsend.png new file mode 100644 index 0000000000000000000000000000000000000000..63ccbd1b9b19ffda0ed933190ca45e90f47163ee Binary files /dev/null and b/docs/html/images/ui/edittext-actionsend.png differ diff --git a/docs/html/images/ui/edittext-autocomplete.png b/docs/html/images/ui/edittext-autocomplete.png new file mode 100644 index 0000000000000000000000000000000000000000..c29091ac75c9fde2a9903d0e5f6c96e735136c22 Binary files /dev/null and b/docs/html/images/ui/edittext-autocomplete.png differ diff --git a/docs/html/images/ui/edittext-email.png b/docs/html/images/ui/edittext-email.png new file mode 100644 index 0000000000000000000000000000000000000000..26f6136b2ee65908050d37acdfbc0cd3f347e66f Binary files /dev/null and b/docs/html/images/ui/edittext-email.png differ diff --git a/docs/html/images/ui/edittext-noextract.png b/docs/html/images/ui/edittext-noextract.png new file mode 100644 index 0000000000000000000000000000000000000000..b459283c4d600576189ddc264a7ed3525409cf7d Binary files /dev/null and b/docs/html/images/ui/edittext-noextract.png differ diff --git a/docs/html/images/ui/edittext-phone.png b/docs/html/images/ui/edittext-phone.png new file mode 100644 index 0000000000000000000000000000000000000000..45177d3af7f40c0697663545d2ebbc5e108ef2a5 Binary files /dev/null and b/docs/html/images/ui/edittext-phone.png differ diff --git a/docs/html/images/ui/edittext-text-next.png b/docs/html/images/ui/edittext-text-next.png new file mode 100644 index 0000000000000000000000000000000000000000..ef5ff1deea8f1ca078770664020e0e1e5c8febd9 Binary files /dev/null and b/docs/html/images/ui/edittext-text-next.png differ diff --git a/docs/html/images/ui/edittext-text.png b/docs/html/images/ui/edittext-text.png new file mode 100644 index 0000000000000000000000000000000000000000..599dcec187b7375de2b8512b7ff04528ed027a2b Binary files /dev/null and b/docs/html/images/ui/edittext-text.png differ diff --git a/docs/html/images/ui/edittext.png b/docs/html/images/ui/edittext.png new file mode 100644 index 0000000000000000000000000000000000000000..d4bcaaa643cf64b706aaca46ce63e332c96c09f7 Binary files /dev/null and b/docs/html/images/ui/edittext.png differ diff --git a/docs/html/images/ui/gridlayout-small.png b/docs/html/images/ui/gridlayout-small.png new file mode 100644 index 0000000000000000000000000000000000000000..935b481c20cf1aed42919c77b7f4c41f01c753df Binary files /dev/null and b/docs/html/images/ui/gridlayout-small.png differ diff --git a/docs/html/images/ui/gridlayout.png b/docs/html/images/ui/gridlayout.png new file mode 100644 index 0000000000000000000000000000000000000000..12ae414dfafa39123c321bf08760bb4df0cd732a Binary files /dev/null and b/docs/html/images/ui/gridlayout.png differ diff --git a/docs/html/images/ui/gridview-small.png b/docs/html/images/ui/gridview-small.png new file mode 100644 index 0000000000000000000000000000000000000000..104a4d4ec95f2414c306b4f1c4bf472bca3c80f4 Binary files /dev/null and b/docs/html/images/ui/gridview-small.png differ diff --git a/docs/html/images/ui/gridview.png b/docs/html/images/ui/gridview.png new file mode 100644 index 0000000000000000000000000000000000000000..a780df3134693b3fb3df9384c3adf420d6b43471 Binary files /dev/null and b/docs/html/images/ui/gridview.png differ diff --git a/docs/html/images/ui/linearlayout-small.png b/docs/html/images/ui/linearlayout-small.png new file mode 100644 index 0000000000000000000000000000000000000000..5d929e25d641d7df59aced34301096742afc88c6 Binary files /dev/null and b/docs/html/images/ui/linearlayout-small.png differ diff --git a/docs/html/images/ui/linearlayout.png b/docs/html/images/ui/linearlayout.png new file mode 100644 index 0000000000000000000000000000000000000000..392cc11bd749c03106443ea813fd9a3cb2a8d0f8 Binary files /dev/null and b/docs/html/images/ui/linearlayout.png differ diff --git a/docs/html/images/ui/listview-small.png b/docs/html/images/ui/listview-small.png new file mode 100644 index 0000000000000000000000000000000000000000..97eba89c100bebbf14167e13e0117f4c83eb73f1 Binary files /dev/null and b/docs/html/images/ui/listview-small.png differ diff --git a/docs/html/images/ui/listview.png b/docs/html/images/ui/listview.png new file mode 100644 index 0000000000000000000000000000000000000000..456ed0c851ca7be794f1cdb7f425826b09880c31 Binary files /dev/null and b/docs/html/images/ui/listview.png differ diff --git a/docs/html/images/ui/pickers.png b/docs/html/images/ui/pickers.png new file mode 100644 index 0000000000000000000000000000000000000000..e446fab48a4266653f364497233f7cde4a501e47 Binary files /dev/null and b/docs/html/images/ui/pickers.png differ diff --git a/docs/html/images/ui/radiobuttons.png b/docs/html/images/ui/radiobuttons.png new file mode 100644 index 0000000000000000000000000000000000000000..8f6b22a7ab0f8c4383d84cd291816977d349400a Binary files /dev/null and b/docs/html/images/ui/radiobuttons.png differ diff --git a/docs/html/images/ui/relativelayout-small.png b/docs/html/images/ui/relativelayout-small.png new file mode 100644 index 0000000000000000000000000000000000000000..c531e9a76cddb02ac926dfc0ba6123df08361972 Binary files /dev/null and b/docs/html/images/ui/relativelayout-small.png differ diff --git a/docs/html/images/ui/relativelayout.png b/docs/html/images/ui/relativelayout.png new file mode 100644 index 0000000000000000000000000000000000000000..72c06ae15796121fa2cd0ae8aa76092e3c7b158c Binary files /dev/null and b/docs/html/images/ui/relativelayout.png differ diff --git a/docs/html/images/ui/sample-linearlayout.png b/docs/html/images/ui/sample-linearlayout.png new file mode 100644 index 0000000000000000000000000000000000000000..c4beb93a6d0735c9edd3a88695dd37dc70b53c13 Binary files /dev/null and b/docs/html/images/ui/sample-linearlayout.png differ diff --git a/docs/html/images/ui/sample-relativelayout.png b/docs/html/images/ui/sample-relativelayout.png new file mode 100644 index 0000000000000000000000000000000000000000..d9ea30e0b02ce8e09552c59ed9bfeab94496a88f Binary files /dev/null and b/docs/html/images/ui/sample-relativelayout.png differ diff --git a/docs/html/images/ui/spinner.png b/docs/html/images/ui/spinner.png new file mode 100644 index 0000000000000000000000000000000000000000..79ee4e44362629fe0f12ba2b373fca577df65076 Binary files /dev/null and b/docs/html/images/ui/spinner.png differ diff --git a/docs/html/images/ui/switch.png b/docs/html/images/ui/switch.png new file mode 100644 index 0000000000000000000000000000000000000000..e8d801484dd926e1b3051f0893f3ea69f10ac4aa Binary files /dev/null and b/docs/html/images/ui/switch.png differ diff --git a/docs/html/images/ui/tabs-small.png b/docs/html/images/ui/tabs-small.png new file mode 100644 index 0000000000000000000000000000000000000000..622f1e70b6c51c2290919c1b5f7ce74c2afa7de1 Binary files /dev/null and b/docs/html/images/ui/tabs-small.png differ diff --git a/docs/html/images/ui/tabs.png b/docs/html/images/ui/tabs.png new file mode 100644 index 0000000000000000000000000000000000000000..da9d4b661dc10c649c8628f3ec2aed615dc0cba5 Binary files /dev/null and b/docs/html/images/ui/tabs.png differ diff --git a/docs/html/images/ui/togglebutton.png b/docs/html/images/ui/togglebutton.png new file mode 100644 index 0000000000000000000000000000000000000000..a69b3fe38a30adffcf803e845a0b64f6311a8789 Binary files /dev/null and b/docs/html/images/ui/togglebutton.png differ diff --git a/docs/html/images/ui/ui-controls.png b/docs/html/images/ui/ui-controls.png new file mode 100644 index 0000000000000000000000000000000000000000..13534d3861bd9b2020a4637a5c3e3029a617e2df Binary files /dev/null and b/docs/html/images/ui/ui-controls.png differ diff --git a/docs/html/images/ui/ui_index.png b/docs/html/images/ui/ui_index.png new file mode 100644 index 0000000000000000000000000000000000000000..3cc82c2707257cb93cf3ee179bb0d502f92f5e94 Binary files /dev/null and b/docs/html/images/ui/ui_index.png differ diff --git a/docs/html/images/ui/webview-small.png b/docs/html/images/ui/webview-small.png new file mode 100644 index 0000000000000000000000000000000000000000..4c3243246376d2be72da4af7f98f2a08fb97b299 Binary files /dev/null and b/docs/html/images/ui/webview-small.png differ diff --git a/docs/html/images/ui/webview.png b/docs/html/images/ui/webview.png new file mode 100644 index 0000000000000000000000000000000000000000..12cef588cecda0b37a7b72f8a383484b34659f3e Binary files /dev/null and b/docs/html/images/ui/webview.png differ diff --git a/docs/html/images/viewgroup.png b/docs/html/images/viewgroup.png index 2c86ddbd187463817286646694ae93b516f4d58a..fa077991037ab1f2fcceb48b01c3daa9ed97a43d 100644 Binary files a/docs/html/images/viewgroup.png and b/docs/html/images/viewgroup.png differ diff --git a/docs/html/images/webapps/webapps.png b/docs/html/images/webapps/webapps.png index 6ad6205303456500aba7d8d5f8208045252840d6..ff499cfcd4dc5bf8e92f46383d4a382ed82a4857 100644 Binary files a/docs/html/images/webapps/webapps.png and b/docs/html/images/webapps/webapps.png differ diff --git a/docs/html/index.jd b/docs/html/index.jd index d3203bbb04cbea30beb273a0c706fb5bb5562bde..58bfd040815c1a421f60c3712c20a5553f30e6e0 100644 --- a/docs/html/index.jd +++ b/docs/html/index.jd @@ -1,218 +1,70 @@ -home=true +fullpage=true +no_footer_links=true +carousel=true page.metaDescription=The official site for Android developers. Provides the Android SDK and documentation for app developers and designers. @jd:body -
    -
    -
    -
    -
    -

    Developer Announcements

    -
    -
    - - -
    -

    Introducing Google Play: An integrated digital content destination where -users buy and enjoy all of their favorite content in one place. It's the new destination for -Android apps!

    -

    Read more »

    -
    -
    -
    -
    +
    + +
    + Prev + Next +
    +
      + +
    - -
     
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    Download

    -

    The Android SDK has the tools, sample code, and docs you need to create great apps.

    -

    Learn more »

    -
     
    -

    Design

    -

    Learn about principles, building blocks, and patterns for creating world-class Android user interfaces.

    -

    Learn more »

    -
     
    -

    Publish

    -

    Google Play is an open service that lets you distribute your apps to devices.

    -

    Learn more »

    -
     
    -

    Target Devices

    -

    The Device Dashboard -provides information about deployed Android devices to -help you target suitable device configurations as you build and update your -apps.

    -

    Learn more »

    -
    -
    -
    - - - - - - + + +
    + - - diff --git a/docs/html/intl/es/training/monitoring-device-state/battery-monitoring.jd b/docs/html/intl/es/training/monitoring-device-state/battery-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..08a42dd1f7f459aa84eb80330681c9e01ef2b52f --- /dev/null +++ b/docs/html/intl/es/training/monitoring-device-state/battery-monitoring.jd @@ -0,0 +1,120 @@ +page.title=Cómo controlar el nivel de batería y el estado de carga +parent.title=Cómo optimizar la duración de la batería +parent.link=index.html + +trainingnavtop=true +next.title=Cómo determinar y controlar el tipo de conector y el estado de la conexión +next.link=docking-monitoring.html + +@jd:body + + + +

    Al modificar la frecuencia de las actualizaciones en segundo plano para reducir el efecto de las mismas en la duración de la batería, te recomendamos que comiences por comprobar el estado de carga y el nivel actual de la batería.

    + +

    El impacto derivado de actualizar aplicaciones en la duración de la batería varía en función del nivel de batería y del estado de carga del dispositivo, mientras que es insignificante cuando este está conectado a la corriente. Por ello, en la mayoría de los casos, puedes maximizar la frecuencia de actualización cuando el dispositivo esté conectado a un cargador. Por el contrario, si el dispositivo está en proceso de descarga, disminuir la frecuencia de actualización te permitirá aumentar la duración de la batería.

    + +

    Del mismo modo, puedes comprobar el nivel de carga de la batería y reducir la frecuencia de las actualizaciones o incluso detenerlas cuando la batería esté a punto de agotarse.

    + + +

    Cómo determinar el estado de carga actual

    + +

    En primer lugar, te recomendamos que determines el estado de carga actual. {@link android.os.BatteryManager} envía los detalles de carga y de la batería en un {@link android.content.Intent} persistente que incluye el estado de carga.

    + +

    Se trata de un intento persistente, por lo que no es necesario registrar un {@link android.content.BroadcastReceiver}. Para ello, solo tienes que ejecutar {@code registerReceiver} transmitiendo {@code null} como el receptor (como se muestra en el siguiente fragmento). A continuación, se devuelve el intento de estado actual de la batería. Puedes transmitir un objeto {@link android.content.BroadcastReceiver} real, pero hablaremos sobre las actualizaciones en otra sección, por lo que no es necesario ahora.

    + +
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    +Intent batteryStatus = context.registerReceiver(null, ifilter);
    + +

    Puedes extraer el estado de carga actual y, si el dispositivo está cargando, puedes saber también si se está usando un cargador de corriente alterna o USB:

    + +

    // Are we charging / charged?
    +int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
    +boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
    +                     status == BatteryManager.BATTERY_STATUS_FULL;
    +
    +// How are we charging?
    +int chargePlug = battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    +boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
    +boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
    + +

    Normalmente, debes maximizar la frecuencia de las actualizaciones en segundo plano si el dispositivo está conectado a un cargador de corriente alterna, disminuir esa frecuencia si se utiliza un cargador USB y reducirla aún más si la batería se está descargando.

    + + +

    Cómo supervisar los cambios en el estado de carga

    + +

    Modificar el estado de carga es tan fácil como conectar el dispositivo a un enchufe o USB. Por ello, es importante que supervises el estado de carga por si se producen cambios y modifiques la frecuencia de actualización según corresponda.

    + +

    {@link android.os.BatteryManager} emite una acción siempre que el dispositivo se conecta o desconecta de la corriente. Es importante recibir estos eventos aunque la aplicación no esté en ejecución (especialmente porque estos eventos pueden afectar a la frecuencia con la que inicias tu aplicación para actualizarla en segundo plano), por lo que debes registrar un {@link android.content.BroadcastReceiver} en tu archivo de manifiesto para detectar ambos eventos definiendo {@link android.content.Intent#ACTION_POWER_CONNECTED} y {@link android.content.Intent#ACTION_POWER_DISCONNECTED} en un filtro de intentos.

    + +
    <receiver android:name=".PowerConnectionReceiver">
    +  <intent-filter>
    +    <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
    +    <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
    +  </intent-filter>
    +</receiver>
    + +

    En la implementación de {@link android.content.BroadcastReceiver} asociada, puedes extraer el método y el estado de carga actual como se describe en el paso anterior.

    + +
    public class PowerConnectionReceiver extends BroadcastReceiver {
    +    @Override
    +    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;
    +    }
    +}
    + + +

    Cómo determinar el nivel de batería actual

    + +

    En algunos casos, también es útil determinar el nivel de batería actual. Puedes disminuir la frecuencia de las actualizaciones en segundo plano si el nivel de carga de la batería es inferior a un valor determinado.

    + +

    Puedes consultar la carga actual de la batería extrayendo el nivel actual de la batería y subir a partir del intento de estado de batería, como se muestra a continuación:

    + +
    int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    +int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
    +
    +float batteryPct = level / (float)scale;
    + + +

    Cómo supervisar cambios importantes en el nivel de batería

    + +

    No puedes controlar el estado de la batería de forma continua fácilmente, pero tampoco es necesario.

    + +

    En términos generales, el impacto sobre la batería derivado de controlar continuamente el nivel de batería es mayor que el comportamiento habitual de la aplicación. Por ello, te recomendamos que supervises únicamente los cambios en el nivel de batería más significativos, especialmente cuando el dispositivo tenga poca batería o acabe de cargarse.

    + +

    El fragmento de manifiesto que aparece a continuación se ha extraído del elemento de filtro de intento de un receptor de emisión. El receptor detecta {@link android.content.Intent#ACTION_BATTERY_LOW} y {@link android.content.Intent#ACTION_BATTERY_OKAY} y se activa cuando el nivel de batería del dispositivo es bajo o cuando se sale de un estado bajo de batería.

    + +
    <receiver android:name=".BatteryLevelReceiver">
    +<intent-filter>
    +  <action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
    +  <action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
    +  </intent-filter>
    +</receiver>
    + +

    Cuando la batería esté a punto de agotarse, te recomendamos que inhabilites las actualizaciones en segundo plano. Si el teléfono se apaga antes de poder utilizar las aplicaciones, no importa que tengan los datos actualizados.

    + +

    En muchos casos, el hecho de cargar un dispositivo coincide con la acción de utilizar un conector. En la próxima sección, hablaremos sobre cómo determinar el estado de conexión actual y cómo supervisar los cambios que se produzcan al conectar el dispositivo.

    + diff --git a/docs/html/intl/es/training/monitoring-device-state/connectivity-monitoring.jd b/docs/html/intl/es/training/monitoring-device-state/connectivity-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..2a5ff120e23d0497e66299374514fdabad759aeb --- /dev/null +++ b/docs/html/intl/es/training/monitoring-device-state/connectivity-monitoring.jd @@ -0,0 +1,70 @@ +page.title=Cómo determinar y controlar el estado de la conectividad +parent.title=Cómo optimizar la duración de la batería +parent.link=index.html + +trainingnavtop=true + +previous.title=Cómo determinar y controlar el tipo de conector y el estado de la conexión +previous.link=docking-monitoring.html +next.title=Cómo manipular los receptores de emisión bajo demanda +next.link=manifest-receivers.html + +@jd:body + + + +

    Algunos de los usos más comunes para las alarmas con repetición y los servicios en segundo plano es programar actualizaciones regulares de los datos de aplicaciones a partir de recursos de Internet, almacenar datos en la memoria caché o ejecutar descargas a largo plazo. Sin embargo, si no estás conectado a Internet o la conexión es demasiado débil para completar la descarga, ¿para qué activar el dispositivo y programar la actualización?

    + +

    Puedes utilizar {@link android.net.ConnectivityManager} para comprobar si estás conectado a Internet y, en ese caso, el tipo de conexión que estás utilizando.

    + + +

    Cómo determinar si tienes conexión a Internet

    + +

    No es necesario programar una actualización basada en un recurso de Internet si no estás conectado. En el fragmento que aparece a continuación, se muestra cómo utilizar {@link android.net.ConnectivityManager} para consultar la red activa y determinar si hay conexión a Internet.

    + +
    ConnectivityManager cm =
    +        (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    + 
    +NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    +boolean isConnected = activeNetwork.isConnectedOrConnecting();
    + + +

    Cómo determinar el tipo de conexión a Internet

    + +

    También puedes determinar el tipo de conexión a Internet que hay disponible.

    + +

    El dispositivo se puede conectar a Internet a través de conexiones Ethernet, Wi-Fi, WiMAX y de datos móviles. Al consultar el tipo de red activa, como se muestra a continuación, puedes modificar la frecuencia de actualización en función del ancho de banda disponible.

    + +
    boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
    + +

    El coste de las conexiones de datos móviles suele ser superior al de las conexiones Wi-Fi, por lo que en la mayoría de los casos, la frecuencia de actualización de tu aplicación debería ser menor si utilizas conexiones móviles. Del mismo modo, las descargas grandes deberían cancelarse hasta que estés conectado a una red Wi-Fi.

    + +

    Cuando hayas inhabilitado las actualizaciones, es importante que detectes si se hay cambios en la conectividad para poder reanudarlas cuando se haya establecido una conexión a Internet.

    + + +

    Cómo supervisar los cambios en la conectividad

    + +

    {@link android.net.ConnectivityManager} emite la acción {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} ({@code "android.net.conn.CONNECTIVITY_CHANGE"}) cuando se han modificado los detalles de la conectividad. Puedes registrar un receptor de emisión en el archivo de manifiesto para detectar estos cambios y reanudar (o cancelar) las actualizaciones en segundo plano según corresponda.

    + +
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    + +

    Los cambios en la conectividad de un dispositivo pueden ser muy frecuentes (esta emisión se activa siempre que cambias de una conexión de datos móviles a una conexión Wi-Fi). Como resultado, te recomendamos que supervises esta emisión únicamente cuando hayas cancelado anteriormente las actualizaciones o las descargas para reanudarlas. Normalmente, basta con comprobar la conexión a Internet antes de iniciar una actualización y, si no hay ninguna, cancelar el resto de actualizaciones hasta que se restablezca la conexión.

    + +

    Esta técnica requiere que alternes receptores de emisión que hayas declarado en el archivo de manifiesto, que se describe en la próxima sección.

    diff --git a/docs/html/intl/es/training/monitoring-device-state/docking-monitoring.jd b/docs/html/intl/es/training/monitoring-device-state/docking-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..d6122811e4221b1ba1931f7ff49292bcd2e2d6a6 --- /dev/null +++ b/docs/html/intl/es/training/monitoring-device-state/docking-monitoring.jd @@ -0,0 +1,74 @@ +page.title=Cómo determinar y controlar el tipo de conector y el estado de la conexión +parent.title=Cómo optimizar la duración de la batería +parent.link=index.html + +trainingnavtop=true +previous.title=Cómo controlar el nivel de batería y el estado de carga +previous.link=battery-monitoring.html +next.title=Cómo determinar y controlar el estado de la conectividad +next.link=connectivity-monitoring.html + +@jd:body + + + +

    Los dispositivos Android se pueden conectar a distintos tipos de conectores. Por ejemplo, se puede utilizar conectores para coche o domésticos y tanto digitales como analógicos. Normalmente, el estado del conector está vinculado al estado de carga, ya que muchos conectores cargan el dispositivo mientras está conectado.

    + +

    El modo en el que el estado del conector del teléfono afecta a la frecuencia de actualización depende de tu aplicación. Puedes aumentar la frecuencia de actualización de una aplicación sobre noticias cuando el dispositivo esté conectado a un conector de escritorio o inhabilitar las actualizaciones completamente si está conectado a un conector de coche. Por el contrario, puedes maximizar las actualizaciones si el dispositivo está conectado a un conector de coche y tu servicio en segundo plano se actualiza con el estado del tráfico.

    + +

    El estado del conector se emite también como un {@link android.content.Intent} persistente, lo que te permite consultar si el dispositivo está conectado o no y, si lo está, determinar el tipo de conector.

    + + +

    Cómo determinar el estado de conexión actual

    + +

    La información sobre el estado del conector se incluye como información adicional en una emisión persistente de la acción {@link android.content.Intent#ACTION_DOCK_EVENT}. Por ello, no es necesario registrar un {@link android.content.BroadcastReceiver}. Solo tienes que ejecutar {@link android.content.Context#registerReceiver registerReceiver()} transmitiendo {@code null} como el receptor de emisión, como se muestra en el fragmento de código que aparece a continuación.

    + +
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
    +Intent dockStatus = context.registerReceiver(null, ifilter);
    + +

    Puedes extraer el estado actual de la conexión de la información adicional de {@code EXTRA_DOCK_STATE}:

    + +

    int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
    +boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
    + + +

    Cómo determinar el tipo de conector actual

    + +

    Si un dispositivo está insertado en un conector, se puede conectar a cualquiera de estos cuatro tipos de conectores: +

    • coche,
    • +
    • escritorio,
    • +
    • escritorio de gama baja (analógico),
    • +
    • escritorio de gama alta (digital).

    + +

    Ten en cuenta que las últimas dos opciones se introdujeron en Android únicamente en el nivel 11 del API. Por ello, te recomendamos que compruebes las tres opciones solo cuando te interese más el tipo de conector que si se trata de un conector digital o analógico:

    + +
    boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
    +boolean isDesk = dockState == EXTRA_DOCK_STATE_DESK || 
    +                 dockState == EXTRA_DOCK_STATE_LE_DESK ||
    +                 dockState == EXTRA_DOCK_STATE_HE_DESK;
    + + +

    Cómo supervisar los cambios en el tipo de conector o en el estado del mismo

    + +

    Cuando el dispositivo está conectado a un conector o desconectado del mismo, se emite la acción {@link android.content.Intent#ACTION_DOCK_EVENT}. Para controlar los cambios que se produzcan en el estado del conector del dispositivo, solo tienes que registrar un receptor de emisión en el archivo de manifiesto de la aplicación, como se muestra en el fragmento que aparece a continuación:

    + +
    <action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
    + +

    Puedes extraer el estado y el tipo de conector en la implementación del receptor con las mismas técnicas que se han descrito en el paso anterior.

    diff --git a/docs/html/intl/es/training/monitoring-device-state/index.jd b/docs/html/intl/es/training/monitoring-device-state/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..bf6b1c1e7091c20c09d72f699c5353cbefcfd875 --- /dev/null +++ b/docs/html/intl/es/training/monitoring-device-state/index.jd @@ -0,0 +1,49 @@ +page.title=Cómo optimizar la duración de la batería + +trainingnavtop=true +startpage=true +next.title=Cómo controlar el nivel de batería y el estado de carga +next.link=battery-monitoring.html + +@jd:body + +
    +
    + +

    Dependencias y requisitos previos

    + + +

    También puedes consultar:

    + + +
    +
    + +

    Uno de los objetivos de tu aplicación debe ser limitar su impacto en la duración de la batería del dispositivo en el que esté instalada. Después de leer estas secciones, podrás desarrollar aplicaciones que optimizarán el uso de la batería en función del estado del dispositivo en el que estén instaladas.

    + +

    Al tomar medidas como inhabilitar las actualizaciones de servicios en segundo plano o disminuir la frecuencia de dichas actualizaciones cuando el nivel de batería sea bajo, puedes garantizar que se minimice el impacto de tu aplicación en la duración de la batería sin afectar a la experiencia del usuario.

    + +

    Secciones

    + + + +
    +
    Cómo controlar el nivel de batería y el estado de carga
    +
    Obtén más información sobre cómo determinar y controlar el nivel de batería actual y los cambios en el estado de carga para modificar la frecuencia de actualizaciones en segundo plano de tu aplicación.
    + +
    Cómo determinar y controlar el tipo de conector y el estado de la conexión
    +
    La frecuencia de actualización óptima puede variar en función de cómo se utilice el dispositivo en el que está instalada la aplicación. Obtén más información sobre cómo determinar y controlar cuándo el dispositivo está conectado a algún sistema de acoplamiento u otra conexión.
    + +
    Cómo determinar y controlar el estado de la conectividad
    +
    Si no tienes conexión a Internet, no puedes actualizar tu aplicación a partir de una fuente online. Obtén más información sobre cómo comprobar el estado de la conectividad para modificar la frecuencia de actualización en segundo plano de tu aplicación. También puedes obtener más información sobre cómo comprobar la conectividad móvil o Wi-Fi antes de iniciar operaciones que requieran un nivel elevado de ancho de banda.
    + +
    Cómo manipular los receptores de emisión bajo demanda
    +
    Los receptores de emisión que declaras en el archivo de manifiesto se pueden alternar durante la ejecución para inhabilitar los que no son necesarios debido al estado actual del dispositivo. Obtén más información sobre cómo alternar y superponer receptores de cambio de estado para mejorar el rendimiento y cómo posponer acciones hasta que el dispositivo se encuentre en un estado concreto.
    +
    \ No newline at end of file diff --git a/docs/html/intl/es/training/monitoring-device-state/manifest-receivers.jd b/docs/html/intl/es/training/monitoring-device-state/manifest-receivers.jd new file mode 100644 index 0000000000000000000000000000000000000000..a90468e37336584bd6fa32aad092dd8e6b23070e --- /dev/null +++ b/docs/html/intl/es/training/monitoring-device-state/manifest-receivers.jd @@ -0,0 +1,50 @@ +page.title=Cómo manipular los receptores de emisión bajo demanda +parent.title=Cómo optimizar la duración de la batería +parent.link=index.html + +trainingnavtop=true + +previous.title=Cómo determinar y controlar el estado de la conectividad +previous.link=connectivity-monitoring.html + +@jd:body + +
    +
    + +

    En esta sección puedes aprender:

    +
      +
    1. Cómo alternar y superponer receptores de cambio de estado para mejorar el rendimiento
    2. +
    + + +

    También puedes consultar:

    + + +
    +
    + +

    La forma más sencilla de controlar los cambios en el estado del dispositivo es crear un {@link android.content.BroadcastReceiver} para cada estado que vayas a controlar y registrar cada uno de ellos en el archivo de manifiesto de tu aplicación. A continuación, en cada uno de esos receptores solo tienes que volver a programar las alarmas recurrentes en función del estado actual del dispositivo.

    + +

    Un efecto secundario de este método es que tu aplicación activará el dispositivo siempre que uno de los receptores se active (probablemente, con más frecuencia de la necesaria).

    + +

    Te recomendamos que inhabilites o habilites los receptores de emisión en el momento de la ejecución. De este modo, puedes utilizar los receptores que hayas declarado en el archivo de manifiesto como alarmas pasivas que se activan mediante los eventos del sistema solo cuando es necesario.

    + + +

    Cómo alternar y superponer receptores de cambio de estado para mejorar el rendimiento

    + +

    Se puede utilizar el {@link android.content.pm.PackageManager} para alternar el estado habilitado en cualquier componente definido en el archivo de manifiesto, incluidos los receptores de emisión que quieras habilitar o inhabilitar, como se muestra en el fragmento que aparece a continuación:

    + +
    ComponentName receiver = new ComponentName(context, myReceiver.class);
    +
    +PackageManager pm = context.getPackageManager();
    +
    +pm.setComponentEnabledSetting(receiver,
    +        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
    +        PackageManager.DONT_KILL_APP)
    + +

    Al utilizar esta técnica, si determinas que la conectividad se ha perdido, puedes inhabilitar todos los receptores excepto el receptor de cambio de conectividad. Por el contrario, cuando estés conectado, puedes dejar de detectar cambios de conectividad y solo comprobar si tienes conexión antes de realizar una actualización y de volver a programar una alarma de actualización recurrente.

    + +

    Puedes utilizar la misma técnica para posponer una descarga que requiera un nivel de ancho de banda superior para completarse. Solo tienes que habilitar un receptor de emisión que detecte los cambios de conectividad y que inicie la descarga solo cuando estés conectado a una red Wi-Fi.

    diff --git a/docs/html/intl/es/training/multiscreen/adaptui.jd b/docs/html/intl/es/training/multiscreen/adaptui.jd new file mode 100644 index 0000000000000000000000000000000000000000..61f0735bc409da52e91ef118ec72e49b25364bbd --- /dev/null +++ b/docs/html/intl/es/training/multiscreen/adaptui.jd @@ -0,0 +1,212 @@ +page.title=Cómo implementar interfaces de usuario adaptables +parent.title=Cómo diseñar aplicaciones para varias pantallas +parent.link=index.html + +trainingnavtop=true +previous.title=Cómo admitir varias densidades de pantalla +previous.link=screendensities.html + +@jd:body + + + + + +

    En función del diseño actual de tu aplicación, la interfaz puede variar. Por ejemplo, si tu aplicación está en modo de panel dual, haz clic en un elemento del panel izquierdo para que aparezca en el panel de la derecha. Asimismo, si está en modo de panel único, el contenido debería aparecer por sí mismo (en otra actividad).

    + + +

    Cómo determinar el diseño actual

    + +

    Dado que la implementación de cada diseño variará en cierta medida, probablemente una de las primeras cosas que tendrás que hacer será determinar el diseño que el usuario puede ver en ese momento. Por ejemplo, puedes determinar si el usuario utiliza el modo de "panel único" o de "panel dual". Para ello, puedes consultar si una vista determinada existe y es visible:

    + +
    +public class NewsReaderActivity extends FragmentActivity {
    +    boolean mIsDualPane;
    +
    +    @Override
    +    public void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        setContentView(R.layout.main_layout);
    +
    +        View articleView = findViewById(R.id.article);
    +        mIsDualPane = articleView != null && 
    +                        articleView.getVisibility() == View.VISIBLE;
    +    }
    +}
    +
    + +

    Ten en cuenta que este código consulta la disponibilidad del panel del "artículo", lo que es mucho más flexible que incluir una consulta para un diseño determinado.

    + +

    Otro ejemplo de cómo puedes adaptar la existencia de diferentes componentes es comprobar su disponibilidad antes de realizar una operación relacionada con los mismos. Por ejemplo, en la aplicación de ejemplo News Reader, hay un botón que abre un menú, pero ese botón solo aparece en las versiones anteriores a Android 3.0 (porque {@link android.app.ActionBar} en el nivel 11 del API y en niveles superiores). Por tanto, para añadir el detector de eventos para este botón, puedes hacer lo siguiente:

    + +
    +Button catButton = (Button) findViewById(R.id.categorybutton);
    +OnClickListener listener = /* create your listener here */;
    +if (catButton != null) {
    +    catButton.setOnClickListener(listener);
    +}
    +
    + + +

    Cómo reaccionar en función del diseño actual

    + +

    El resultado de algunas acciones puede variar en función del diseño actual. Por ejemplo, en el ejemplo de News Reader, al hacer clic en un encabezado de la lista se abrirá el artículo del panel situado a la derecha si la interfaz de usuario está en modo de panel dual, pero se iniciará una actividad independiente si esta está en modo de panel único:

    + +
    +@Override
    +public void onHeadlineSelected(int index) {
    +    mArtIndex = index;
    +    if (mIsDualPane) {
    +        /* display article on the right pane */
    +        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    +    } else {
    +        /* start a separate activity */
    +        Intent intent = new Intent(this, ArticleActivity.class);
    +        intent.putExtra("catIndex", mCatIndex);
    +        intent.putExtra("artIndex", index);
    +        startActivity(intent);
    +    }
    +}
    +
    + +

    De igual modo, si la aplicación está en modo de panel dual, debe configurar la barra de acción con pestañas para la navegación, mientras que si la aplicación está en modo de panel único, debe configurar la navegación con un widget giratorio. Por tanto, el código debe comprobar también cuál es el caso adecuado:

    + +
    +final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" };
    +
    +public void onCreate(Bundle savedInstanceState) {
    +    ....
    +    if (mIsDualPane) {
    +        /* use tabs for navigation */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
    +        int i;
    +        for (i = 0; i < CATEGORIES.length; i++) {
    +            actionBar.addTab(actionBar.newTab().setText(
    +                CATEGORIES[i]).setTabListener(handler));
    +        }
    +        actionBar.setSelectedNavigationItem(selTab);
    +    }
    +    else {
    +        /* use list navigation (spinner) */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
    +        SpinnerAdapter adap = new ArrayAdapter(this, 
    +                R.layout.headline_item, CATEGORIES);
    +        actionBar.setListNavigationCallbacks(adap, handler);
    +    }
    +}
    +
    + + +

    Cómo volver a utilizar fragmentos en otras actividades

    + +

    Un patrón recurrente a la hora de diseñar para distintas pantallas es utilizar una parte de la interfaz que se implementa como un panel en algunas configuraciones de pantalla y como actividad independiente en otras. Por ejemplo, en el ejemplo de News Reader, el texto del artículo de noticias se presenta en el panel de la derecha en las pantallas grandes, pero es una actividad independiente en las pantallas más pequeñas.

    + +

    En otros casos similares, puedes evitar la duplicación de código reutilizando la misma {@link android.app.Fragment} en distintas actividades. Por ejemplo, ArticleFragment se utiliza en el diseño de panel dual:

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    A continuación, se vuelve a utilizar (sin diseño) en el diseño de actividad para pantallas más pequeñas (ArticleActivity):

    + +
    +ArticleFragment frag = new ArticleFragment();
    +getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
    +
    + +

    Evidentemente, esto tiene el mismo efecto que declarar el fragmento en un diseño XML. Sin embargo, en este caso, un diseño XML sería un trabajo innecesario porque el fragmento del artículo es el único componente de esta actividad.

    + +

    Un punto muy importante que debes tener en cuenta al diseñar tus fragmentos es no crear un acoplamiento fuerte para una actividad determinada. Para ello, normalmente puedes definir una interfaz que resuma todas las formas en las que tiene que interactuar el fragmento con su actividad principal y, a continuación, la actividad principal implementa esa interfaz:

    + +

    Por ejemplo, ese es precisamente el objetivo del HeadlinesFragment de la aplicación News Reader:

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    OnHeadlineSelectedListener mHeadlineSelectedListener = null;
    +
    +    /* Must be implemented by host activity */
    +    public interface OnHeadlineSelectedListener {
    +        public void onHeadlineSelected(int index);
    +    }
    +    ...
    +
    +    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
    +        mHeadlineSelectedListener = listener;
    +    }
    +}
    +
    + +

    A continuación, cuando el usuario selecciona un encabezado, el fragmento notifica el detector especificado por la actividad principal (en lugar de notificar una actividad predefinida específica):

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    @Override
    +    public void onItemClick(AdapterView<?> parent, 
    +                            View view, int position, long id) {
    +        if (null != mHeadlineSelectedListener) {
    +            mHeadlineSelectedListener.onHeadlineSelected(position);
    +        }
    +    }
    +    ...
    +}
    +
    + +

    Si quieres obtener más información sobre esta técnica, puedes consultar la guía sobre Cómo admitir tablets y dispositivos móviles.

    + + +

    Cómo gestionar los cambios en la configuración de la pantalla

    + +

    Si utilizas actividades independientes para implementar partes individuales de tu interfaz, debes tener en cuenta que es posible que tengas que reaccionar ante determinados cambios en la configuración (como un cambio de rotación) para mantener la homogeneidad de tu interfaz.

    + +

    Por ejemplo, en un tablet de 7" que utilice Android 3.0 o una versión superior, el ejemplo de News Reader utiliza una actividad independiente para mostrar el artículo de noticias en el modo vertical, pero utiliza el diseño de panel dual en el modo horizontal.

    + +

    Esto significa que cuando el usuario utiliza el modo vertical y está consultando un artículo, tienes que detectar que la orientación ha cambiado al modo horizontal y reaccionar de forma adecuada finalizando la actividad. A continuación, debes volver a la actividad principal para que el contenido pueda mostrarse en el diseño de panel dual:

    + +
    +public class ArticleActivity extends FragmentActivity {
    +    int mCatIndex, mArtIndex;
    +
    +    @Override
    +    protected void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
    +        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
    +
    +        // If should be in two-pane mode, finish to return to main activity
    +        if (getResources().getBoolean(R.bool.has_two_panes)) {
    +            finish();
    +            return;
    +        }
    +        ...
    +}
    +
    + + diff --git a/docs/html/intl/es/training/multiscreen/index.jd b/docs/html/intl/es/training/multiscreen/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..0a1461b12cdc051b2f2181a56aeb96e613343bfc --- /dev/null +++ b/docs/html/intl/es/training/multiscreen/index.jd @@ -0,0 +1,63 @@ +page.title=Cómo diseñar aplicaciones para varias pantallas +trainingnavtop=true +startpage=true +next.title=Cómo admitir varios tamaños de pantalla +next.link=screensizes.html + +@jd:body + +
    +
    + +

    Dependencias y requisitos previos

    + + + +

    También puedes consultar:

    + + + +

    ¡Pruébalo!

    + + + +
    +
    + +

    Android se utiliza en cientos de dispositivos con diferentes tamaños de pantalla, desde pequeños teléfonos hasta enormes televisores. Por ello, es importante que diseñes tu aplicación para que sea compatible con todos los tamaños de pantalla y esté disponible para el mayor número de usuarios posible.

    + +

    Sin embargo, no es suficiente con que tu aplicación sea compatible con diferentes dispositivos. Cada tamaño de pantalla ofrece diferentes posibilidades y retos para la interacción del usuario. Por ello, para satisfacer completamente a tus usuarios e impresionarlos, tu aplicación debe ir más allá de simplemente admitir varias pantallas: debe optimizar la experiencia de usuario para cada configuración de pantalla.

    + +

    En esta sección se explica cómo implementar una interfaz de usuario que esté optimizada para diferentes configuraciones de pantalla.

    + +

    El código que aparece en cada sección se ha extraído de una aplicación de ejemplo para explicar las prácticas recomendadas a la hora de optimizar tu aplicación para varias pantallas. Puedes descargar el ejemplo (situado a la derecha) y utilizarlo como fuente de código reutilizable para tu propia aplicación.

    + +

    Nota: en esta sección y en el ejemplo correspondiente, se utiliza la biblioteca de compatibilidad para poder usar las API de {@link android.app.Fragment} en versiones anteriores a Android 3.0. Debes descargar y la biblioteca y añadirla a tu aplicación para poder utilizar todas las API que se indican en esta sección.

    + + +

    Secciones

    + +
    +
    Cómo admitir varios tamaños de pantalla
    +
    En esta sección se explica cómo crear diseños que se adapten a diferentes tamaños de pantalla (mediante dimensiones flexibles para vistas, {@link android.widget.RelativeLayout}, calificadores de orientación y tamaño de pantalla, filtros de alias y mapas de bits de la clase NinePatch).
    + +
    Cómo admitir varias densidades de pantalla
    +
    En esta sección se explica cómo admitir pantallas con diferentes densidades de píxeles (mediante píxeles independientes de la densidad y mapas de bits adecuados a cada densidad).
    + +
    Cómo implementar interfaces de usuario adaptables
    +
    En esta sección se explica cómo implementar tu interfaz de usuario para que se adapte a varias combinaciones de densidad o de tamaño de pantalla (detección de tiempo de ejecución del diseño activo, cómo reaccionar en función del diseño actual y cómo administrar los cambios en la configuración de la pantalla).
    +
    diff --git a/docs/html/intl/es/training/multiscreen/screendensities.jd b/docs/html/intl/es/training/multiscreen/screendensities.jd new file mode 100644 index 0000000000000000000000000000000000000000..0edb89fd470725be73c981a4dbaa700d2377caea --- /dev/null +++ b/docs/html/intl/es/training/multiscreen/screendensities.jd @@ -0,0 +1,100 @@ +page.title=Cómo admitir varias densidades de pantalla +parent.title=Cómo diseñar aplicaciones para varias pantallas +parent.link=index.html + +trainingnavtop=true +previous.title=Cómo admitir varios tamaños de pantalla +previous.link=screensizes.html +next.title=Cómo implementar interfaces de usuario adaptables +next.link=adaptui.html + +@jd:body + + + +
    +
    + +

    En esta sección puedes aprender:

    +
      +
    1. Cómo utilizar píxeles independientes de la densidad
    2. +
    3. Cómo proporcionar mapas de bits alternativos
    4. +
    + +

    También puedes consultar:

    + + + +

    ¡Pruébalo!

    + + + + +
    +
    + +

    En esta sección se explica cómo proporcionar diferentes recursos y utilizar unidades de medida de resolución independiente para admitir diferentes densidades de pantalla.

    + +

    Cómo utilizar píxeles independientes de la densidad

    + +

    Un error común que debes evitar al crear tus diseños es utilizar píxeles absolutos para definir distancias o tamaños. Definir dimensiones de diseño mediante píxeles es problemático porque cada pantalla tiene densidades de píxeles diferentes, por lo que es posible que el mismo número de píxeles corresponda a varios tamaños físicos en distintos dispositivos. Por tanto, al especificar dimensiones, debes utilizar siempre unidades dp o sp. dp es un píxel independiente de la densidad que corresponde al tamaño físico de un píxel a 160 dpi. sp es la misma unidad de base, pero aumentada en función del tamaño de letra preferido por el usuario (se trata de un píxel independiente de la escala). Por tanto, debes utilizar esta unidad de medida para definir el tamaño de letra (pero no para tamaños de diseños).

    + +

    Por ejemplo, al especificar un espacio entre dos vistas, debes utilizar dp en lugar de px:

    + +
    +<Button android:layout_width="wrap_content" 
    +    android:layout_height="wrap_content" 
    +    android:text="@string/clickme"
    +    android:layout_marginTop="20dp" />
    +
    + +

    Al especificar el tamaño de letra, debes usar siempre sp:

    + +
    +<TextView android:layout_width="match_parent" 
    +    android:layout_height="wrap_content" 
    +    android:textSize="20sp" />
    +
    + + +

    Cómo proporcionar mapas de bits alternativos

    + +

    Dado que Android se ejecuta en dispositivos con diferentes densidades de pantalla, siempre debes proporcionar tus recursos de mapas de bits adaptados a los conjuntos de densidades generalizados: baja, media, alta y muy alta. De este modo, podrás conseguir un rendimiento y una calidad gráfica óptimos en todas las densidades de pantalla.

    + +

    Para generar estas imágenes, debes empezar con tu recurso genérico en formato vectorial y generar las imágenes para cada densidad con la siguiente escala de tamaños:

    + +

      +
    • xhdpi: 2,0 +
    • hdpi: 1,5 +
    • mdpi: 1.0 (base) +
    • ldpi: 0,75 +

    + +

    Esto significa que si generas una imagen de 200 x 200 para dispositivos xhdpi, debes generar el mismo recurso en 150 x 150 para hdpi, en 100 x 100 para mdpi y, por último, una imagen de 75 x 75 para dispositivos ldpi.

    + +

    A continuación, sitúa los archivos de imagen generados en el subdirectorio adecuado en res/ y el sistema seleccionará el archivo correspondiente automáticamente en función de la densidad de la pantalla del dispositivo en el que se esté ejecutando la aplicación:

    + +
    +MyProject/
    +  res/
    +    drawable-xhdpi/
    +        awesomeimage.png
    +    drawable-hdpi/
    +        awesomeimage.png
    +    drawable-mdpi/
    +        awesomeimage.png
    +    drawable-ldpi/
    +        awesomeimage.png
    +
    + +

    Por tanto, cada vez que hagas referencia a @drawable/awesomeimage, el sistema seleccionará el mapa de bits adecuado en función de los puntos por pulgada de la pantalla.

    + +

    Para consultar más sugerencias y directrices sobre cómo crear recursos de iconos para tu aplicación, consulta la sección Directrices para diseñar iconos.

    + diff --git a/docs/html/intl/es/training/multiscreen/screensizes.jd b/docs/html/intl/es/training/multiscreen/screensizes.jd new file mode 100644 index 0000000000000000000000000000000000000000..9a971d1c000c7300884a0c233157aed89898a305 --- /dev/null +++ b/docs/html/intl/es/training/multiscreen/screensizes.jd @@ -0,0 +1,279 @@ +page.title=Cómo admitir varios tamaños de pantalla +parent.title=Cómo diseñar aplicaciones para varias pantallas +parent.link=index.html + +trainingnavtop=true +next.title=Cómo admitir varias densidades de pantalla +next.link=screendensities.html + +@jd:body + + + + + +

    En esta sección se explica cómo admitir varios tamaños de pantalla. Para ello, sigue estos pasos:

    +
      +
    • Asegúrate de que el diseño se haya ajustado correctamente al tamaño de la pantalla.
    • +
    • Configura la pantalla con el diseño de interfaz adecuado.
    • +
    • Asegúrate de aplicar el diseño adecuado a la pantalla correspondiente.
    • +
    • Utiliza el mapa de bits con la escala adecuada.
    • +
    + + +

    Cómo utilizar los valores "wrap_content" y "match_parent"

    + +

    Para garantizar que el diseño es flexible y que se adapta a varios tamaños de pantalla, debes utilizar los valores "wrap_content" y "match_parent" para la altura y el ancho de algunos componentes de la vista. Si utilizas "wrap_content", el ancho o la altura de la vista se establece en el tamaño mínimo necesario para adaptar el contenido a esta vista, mientras que "match_parent" (también conocido como "fill_parent" antes del nivel 8 del API) provoca que el componente se amplíe hasta coincidir con el tamaño de la vista principal.

    + +

    Al utilizar los valores de tamaño "wrap_content" y "match_parent" en lugar de los tamaños predefinidos, las vistas pueden utilizar únicamente el espacio requerido para esa vista o ampliarse hasta rellenar el espacio disponible respectivamente. Por ejemplo:

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    Observa cómo se utilizan en el ejemplo los valores "wrap_content" y "match_parent" para los tamaños de los componentes en lugar de dimensiones específicas. Esto permite que el diseño se adapte correctamente a diferentes tamaños y orientaciones de la pantalla.

    + +

    Por ejemplo, esta es la apariencia del diseño en modo horizontal y vertical. Ten en cuenta que los tamaños de los componentes se adaptan automáticamente a la altura y al ancho:

    + + +

    Figura 1. La aplicación de ejemplo News Reader en modo vertical (izquierda) y horizontal (derecha)

    + + +

    Cómo utilizar RelativeLayout

    + +

    Puedes crear diseños de un cierto nivel de complejidad con instancias anidadas de {@link android.widget.LinearLayout} y combinaciones de los valores de tamaño "wrap_content" y "match_parent". Sin embargo, {@link android.widget.LinearLayout} no te permite controlar con precisión las relaciones espaciales de las vistas secundarias; las vistas de {@link android.widget.LinearLayout} simplemente se alinean en paralelo. Si quieres orientar las vistas secundarias de una forma que no sea una línea recta, a menudo la mejor solución es utilizar {@link android.widget.RelativeLayout}que te permite especificar el diseño según las relaciones espaciales entre los componentes. Por ejemplo, puedes alinear una vista secundaria en el lateral izquierdo y otra vista en el lateral derecho de la pantalla.

    + +

    Por ejemplo:

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:layout_width="match_parent"
    +    android:layout_height="match_parent">
    +    <TextView
    +        android:id="@+id/label"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:text="Type here:"/>
    +    <EditText
    +        android:id="@+id/entry"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/label"/>
    +    <Button
    +        android:id="@+id/ok"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/entry"
    +        android:layout_alignParentRight="true"
    +        android:layout_marginLeft="10dp"
    +        android:text="OK" />
    +    <Button
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_toLeftOf="@id/ok"
    +        android:layout_alignTop="@id/ok"
    +        android:text="Cancel" />
    +</RelativeLayout>
    +
    + +

    La figura 2 indica cómo se muestra este diseño en una pantalla QVGA.

    + + +

    Figura 2. Captura de pantalla de una pantalla QVGA (pantalla pequeña)

    + +

    La figura 3 indica cómo se muestra este diseño en una pantalla más grande.

    + + +

    Figura 3. Captura de pantalla de una pantalla WSVGA (pantalla grande)

    + +

    Ten en cuenta que aunque el tamaño de los componentes es diferente, las relaciones espaciales se mantienen según se ha especificado con {@link android.widget.RelativeLayout.LayoutParams}.

    + + +

    Cómo utilizar calificadores de tamaño

    + +

    Hay mucha diferencia entre un diseño flexible y un diseño relativo como el que se ha utilizado en las secciones anteriores. Aunque ambos diseños se adaptan a diferentes pantalla estirando el espacio dentro de los componentes y alrededor de los mismos, puede que no ofrezcan la mejor experiencia de usuario para cada tamaño de pantalla. Por tanto, tu aplicación no solo debe implementar los diseños flexibles, sino que también debe ofrecer varios diseños alternativos para diferentes configuraciones de pantalla. Para ello, se utilizan calificadores de configuración, que permiten que el tiempo de ejecución seleccione el recurso adecuado en función de la configuración actual del dispositivo (por ejemplo, un diseño diferente para diferentes tamaños de pantalla).

    + +

    Por ejemplo, muchas aplicaciones implementan el patrón de "panel dual" para pantallas grandes (la aplicación mostraría una lista de elementos en un panel y el contenido en otro panel). Aunque los tablets y las televisiones son lo suficientemente grandes como para que los dos paneles aparezcan simultáneamente en la pantalla, las pantallas de los teléfonos tienen que mostrarlos por separado. Para implementar estos diseños, puedes utilizar los siguientes archivos:

    + +
      +
    • res/layout/main.xml, diseño de panel único (predeterminado): + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-large/main.xml, diseño de panel dual: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    Observa el calificador large en el nombre de directorio del segundo diseño. Este diseño se seleccionará en dispositivos con pantallas clasificadas como grandes (por ejemplo, tablets de 7" y superiores). El otro diseño (sin calificadores) se seleccionará en el caso de dispositivos más pequeños.

    + + +

    Cómo utilizar el calificador de ancho mínimo

    + +

    Una de las dificultades a las que se enfrentaron los desarrolladores con los dispositivos Android anteriores a la versión 3.2 fue el contenedor de tamaño de pantalla "grande". Algunos ejemplos de este tipo de dispositivo son el tablet Dell Streak, el tablet Galaxy Tab original y los tablets de 7" en general. Sin embargo, es posible que muchas aplicaciones quieran mostrar varios diseños para diferentes dispositivos de esta categoría (por ejemplo, para dispositivos de 5" y de 7"), aunque todos estos dispositivos se consideren de pantalla grande. Por esta razón, Android introdujo el calificador de "ancho mínimo" (entre otros) en Android 3.2.

    + +

    Este calificador te permite mostrar contenido en pantallas que tengan un ancho mínimo determinado en píxeles independientes de la densidad. Por ejemplo, el tablet típico de 7" tiene un ancho mínimo de 600 dp, por lo que si quieres que la interfaz de usuario sea de panel dual en esta pantalla (y una única lista en pantallas más pequeñas), puedes utilizar los mismos dos diseños de la sección anterior para los diseños de panel único y de panel dual, solo que en lugar de utilizar el calificador de tamaño large, debes utilizar sw600dp para indicar que el diseño de panel dual se utiliza con las pantallas cuyo ancho mínimo sea de 600 dp:

    + +
      +
    • res/layout/main.xml, diseño de panel único (predeterminado): + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-sw600dp/main.xml, diseño de panel dual: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    Esto significa que los dispositivos cuyo ancho mínimo sea igual o superior a 600 dp utilizarán el diseño layout-sw600dp/main.xml (panel dual), mientras que las pantallas más pequeñas utilizarán el diseño layout/main.xml (panel único).

    + +

    No obstante, esto no funcionará en los dispositivos anteriores a Android 3.2 porque no reconocen sw600dp como calificador de tamaño, por lo que también tendrás que seguir utilizando el calificador large. Por tanto, debes tener un archivo con el nombre res/layout-large/main.xml idéntico a res/layout-sw600dp/main.xml. En la siguiente sección, obtendrás información sobre una técnica que te permite evitar que se dupliquen los archivos de diseños.

    + + +

    Cómo utilizar alias de diseño

    + +

    El calificador de ancho mínimo solo está disponible en Android 3.2 o superior. Por tanto, tendrás que seguir utilizando los contenedores de tamaño abstractos (pequeño, normal, grande y extragrande) para que sean compatibles con versiones anteriores. Por ejemplo, si quieres que tu interfaz de usuario sea de panel único en teléfonos pero multipanel en tablets de 7", televisiones y otros dispositivos grandes, tendrás que utilizar los siguientes archivos:

    + +

      +
    • res/layout/main.xml: diseño de panel único,
    • +
    • res/layout-large: diseño multipanel,
    • +
    • res/layout-sw600dp: diseño multipanel.
    • +

    + +

    Los dos últimos archivos son idénticos porque uno de ellos se utilizará con dispositivos Android 3.2 y el otro con tablets y televisiones que utilicen versiones anteriores de Android.

    + +

    Para evitar la duplicación del mismo archivo para tablets y televisiones (así como todos los problemas que esto conlleva), puedes utilizar archivos alias. Por ejemplo, puedes establecer los siguientes diseños:

    + +
      +
    • res/layout/main.xml: diseño de panel único,
    • +
    • res/layout/main_twopanes.xml: diseño de panel dual.
    • +
    + +

    Añade estos dos archivos:

    + +

      +
    • res/values-large/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      +
    • + +
    • res/values-sw600dp/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      + +
    • +

    + +

    Estos dos últimos archivos tienen el mismo contenido, pero en realidad no definen el diseño. Solo configuran {@code main} para que sea un alias de {@code main_twopanes}. Como los archivos tienen selectores large y sw600dp, se aplican a tablets y a televisiones independientemente de la versión de Android (las televisiones y los tablets anteriores a la versión 3.2 utilizarán +{@code large}y las televisiones y los tablets posteriores a la versión 3.2 utilizarán sw600dp).

    + + +

    Cómo utilizar calificadores de orientación

    + +

    Aunque algunos diseños se pueden utilizar tanto en modo horizontal como vertical, la mayoría de ellos pueden beneficiarse de los ajustes. A continuación, se indica cómo se comporta el diseño según cada tamaño y orientación de la pantalla en la aplicación de ejemplo News Reader:

    + +

      +
    • pantalla pequeña, vertical: panel único con logotipo,
    • +
    • pantalla pequeña, horizontal: panel único con logotipo,
    • +
    • tablet de 7", vertical: panel único con barra de acciones,
    • +
    • tablet de 7", horizontal: panel dual ancho con barra de acciones,
    • +
    • tablet de 10", vertical: panel dual estrecho con barra de acciones,
    • +
    • tablet de 10", horizontal: panel dual ancho con barra de acciones,
    • +
    • televisión, horizontal: panel dual ancho con barra de acciones.
    • +

    + +

    Cada uno de estos diseños se establecen en un archivo XML en el directorio res/layout/. Para definir posteriormente las diferentes configuraciones de pantalla, la aplicación utiliza alias de diseño para asignarlos a cada configuración:

    + +

    res/layout/onepane.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} + +

    res/layout/onepane_with_bar.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    res/layout/twopanes.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    res/layout/twopanes_narrow.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all} + +

    Una vez que se hayan definido todos los diseños posibles, solo se debe asignar el diseño adecuado a cada configuración a través de calificadores de configuración. Ahora ya puedes utilizar la técnica de los alias de diseño:

    + +

    res/values/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all} + +

    res/values-sw600dp-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml +all} + +

    res/values-sw600dp-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml +all} + +

    res/values-large-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all} + +

    res/values-large-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all} + + + +

    Cómo utilizar mapas de bits de la clase NinePatch

    + +

    Admitir diferentes tamaños de pantalla normalmente implica que las fuentes de imagen también deben poder adaptarse a varios tamaños. Por ejemplo, un fondo de botón debe adaptarse a cualquier forma de botón a la que se aplique.

    + +

    Si utilizas imágenes sencillas en componentes que pueden cambiar de tamaño, observarás rápidamente que los resultados no es que sean precisamente impresionantes, ya que las imágenes se estirarán o estrecharán. La solución es utilizar mapas de bits de la clase NinePatch, que son archivos PNG con un formato especial que indican las áreas que se pueden y no se pueden estirar.

    + +

    Por tanto, al diseñar mapas de bits que se vayan a utilizar en componentes con tamaño variable, utiliza siempre mapas de bits de la clase NinePatch. Para convertir un mapa de bits en uno de la clase NinePatch, puedes empezar con una imagen normal (consulta la figura 4, que se ha ampliado cuatro veces para obtener una mayor claridad).

    + + +

    Figura 4. button.png

    + +

    A continuación, puedes pasar a la utilidad draw9patch del SDK (que se localiza en el directorio tools/) en la que puedes marcar las áreas que se deben estirar dibujando píxeles a lo largo de los bordes superior e izquierdo. También puedes marcar el área que debe incluir el contenido dibujando píxeles a lo largo de los bordes inferior y derecho, como se muestra en la figura 5.

    + + +

    Figura 5. button.9.png

    + +

    Observa los píxeles de color negro situados junto a los bordes. Los que aparecen en los bordes superior e izquierdo indican los lugares en los que se puede estirar la imagen, mientras que los que aparecen en los bordes inferior y derecho indican dónde se debe situar el contenido.

    + +

    Además, observa la extensión .9.png. Debes utilizar esta extensión, ya que, de este modo, el marco detecta que se trata de una imagen de la clase NinePatch, en lugar de una imagen PNG normal.

    + +

    Cuando aplicas este fondo a un componente (definiendo android:background="@drawable/button"), el marco estira la imagen de forma adecuada para adaptarla al botón, como se muestra en varios tamaños de la figura 6.

    + + +

    Figura 6. Botón que utiliza la clase NinePatch button.9.png en varios tamaños

    + diff --git a/docs/html/intl/ja/guide/developing/eclipse-adt.jd b/docs/html/intl/ja/guide/developing/eclipse-adt.jd index 397c0068ab7581fb89c686d6745445b43bacfc75..2cd69496145e62a2b29ba1103e91b9543db4dd9f 100644 --- a/docs/html/intl/ja/guide/developing/eclipse-adt.jd +++ b/docs/html/intl/ja/guide/developing/eclipse-adt.jd @@ -29,8 +29,8 @@ page.title=Eclipse 内で ADT を使用
  • プロジェクトを、ユーザーに配布可能な署名済みの APK 形式でエクスポートすることもできます。
  • -

    ADT を組み込んだ Eclipse 総合開発環境で Android アプリケーションの開発を始めるには、最初に Eclipse 総合開発環境をダウンロードしてから、ADT プラグインをダウンロードしてインストールする必要があります。そのためには、Eclipse 用 ADT プラグインのインストールに記載されている手順どおりに操作します。

    -

    バージョン 0.9 より前の ADT を使用してアプリケーションを既に開発中の場合は、必ず最新バージョンにアップグレードしてから続行してください。Eclipse ADT プラグインをアップデートするためのガイドをご覧ください。

    +

    ADT を組み込んだ Eclipse 総合開発環境で Android アプリケーションの開発を始めるには、最初に Eclipse 総合開発環境をダウンロードしてから、ADT プラグインをダウンロードしてインストールする必要があります。そのためには、Eclipse 用 ADT プラグインのインストールに記載されている手順どおりに操作します。

    +

    バージョン 0.9 より前の ADT を使用してアプリケーションを既に開発中の場合は、必ず最新バージョンにアップグレードしてから続行してください。Eclipse ADT プラグインをアップデートするためのガイドをご覧ください。

    注: このガイドでは、ADT プラグインの最新バージョンを使用していることを前提としています。説明の大半は、以前のバージョンにも当てはまりますが、以前のバージョンを使用している場合は、このドキュメントのオンライン版ではなく、SDK パッケージに付属された資料内の同ドキュメントをご覧ください。

    @@ -84,9 +84,9 @@ page.title=Eclipse 内で ADT を使用

    アプリケーションの実行

    -

    注意してください。アプリケーションを Android エミュレータで実行する前に、Android 仮想デバイス(AVD)を作成する必要があります。AVD では、エミュレータで使用する Android プラットフォームを指定します。詳しくは Android 仮想デバイス のドキュメントをご覧ください。ただし、すぐにアプリケーションを実行したい場合は、次の簡単な手順に従って AVD を作成してください。

    +

    注意してください。アプリケーションを Android エミュレータで実行する前に、Android 仮想デバイス(AVD)を作成する必要があります。AVD では、エミュレータで使用する Android プラットフォームを指定します。詳しくは Android 仮想デバイス のドキュメントをご覧ください。ただし、すぐにアプリケーションを実行したい場合は、次の簡単な手順に従って AVD を作成してください。

    -

    携帯端末の実機でのみアプリケーションを実行する場合は、AVD は必要ありません。この場合のアプリケーションの実行について詳しくは、Developing On a Device をご覧ください。

    +

    携帯端末の実機でのみアプリケーションを実行する場合は、AVD は必要ありません。この場合のアプリケーションの実行について詳しくは、Developing On a Device をご覧ください。

    AVD の作成

    @@ -119,7 +119,7 @@ id:2

    これで AVD が作成できました。次のセクションでは、エミュレータでアプリケーションを起動する際に、AVD がどのように使用されるかについて説明します。

    -

    AVD の作成と管理について詳しくは、Android 仮想デバイス のドキュメントをご覧ください。

    +

    AVD の作成と管理について詳しくは、Android 仮想デバイス のドキュメントをご覧ください。

    アプリケーションの実行

    @@ -193,7 +193,7 @@ id:2

    Android アプリケーションの開発を始めると、Android アプリケーションをシステムがエミュレータや実機にインストールする前に、どの Android アプリケーションにもデジタル署名が必要であることがわかります。署名には、デバッグ キーを使用する方法(エミュレータや開発用端末ですぐにテストする場合)と、非公開キーを使用する方法(アプリケーションを配布する場合)の 2 つがあります。

    ADT プラグインでは、アプリケーションをエミュレータや開発用端末にインストールする前に、.apk ファイルがデバッグ キーを使用して署名されるので、開発を早めることができます。つまり、独自の非公開キーを生成する必要がなく、Eclipse からアプリケーションをすぐに実行できます。Keytool に ADT がアクセスできれば、デベロッパーが特に操作する必要はありません。ただし、アプリケーションを公開する場合は、SDK ツールが生成するデバッグ キーではなく、独自の非公開キーを使用してアプリケーションに署名する必要があります

    -

    アプリケーションへの署名をご覧ください。Android でのアプリケーションへの署名と、Android アプリケーション デベロッパーにとっての署名の意味について説明しています。このドキュメントには、ADT のエクスポート ウィザードを使用してアプリケーションをエクスポートし、署名するためのガイドも含まれています。

    +

    アプリケーションへの署名をご覧ください。Android でのアプリケーションへの署名と、Android アプリケーション デベロッパーにとっての署名の意味について説明しています。このドキュメントには、ADT のエクスポート ウィザードを使用してアプリケーションをエクスポートし、署名するためのガイドも含まれています。

    Eclipse のヒント

    @@ -224,7 +224,7 @@ id:2

    DDMS の手動による実行

    -

    ADT プラグインを使用するデバッグをおすすめしますが、手動で DDMS を実行し、ポート 8700 でデバッグするように Eclipse を設定することができます(注: 最初に必ず DDMS を起動してください)。

    +

    ADT プラグインを使用するデバッグをおすすめしますが、手動で DDMS を実行し、ポート 8700 でデバッグするように Eclipse を設定することができます(注: 最初に必ず DDMS を起動してください)。

    + +
    +
    電池残量と充電状態の監視
    +
    アプリの更新頻度を変更するために現在の電池残量や充電状態の変化を特定および監視する方法を学習します。
    + +
    ホルダーの装着状態とタイプの特定と監視
    +
    最適な更新頻度は、ホスト端末がどのように使用されているかによって異なります。ホルダーの装着状態とタイプに応じてアプリの動作を変更するために、これらを特定および監視する方法を学習します。
    + +
    接続状態の特定と監視
    +
    インターネットに接続していないときは、オンライン ソースからアプリを更新することはできません。接続状態を調べ、それに応じてバックグラウンド更新の頻度を変更する方法を学習します。また、大量の帯域幅を消費する処理を開始する前に接続が Wi-Fi かモバイル データかを調べる方法も学習します。
    + +
    オンデマンドでのブロードキャスト レシーバ操作
    +
    マニフェスト内で宣言したブロードキャスト レシーバのオンとオフを実行時に切り替えます。端末の状態に応じて、不要なレシーバを無効にすることができます。効率を上げるために、状態変化レシーバのオンとオフを切り替える方法や、端末が特定の状態になるまでアクションを延期する方法を学習します。
    +
    \ No newline at end of file diff --git a/docs/html/intl/ja/training/monitoring-device-state/manifest-receivers.jd b/docs/html/intl/ja/training/monitoring-device-state/manifest-receivers.jd new file mode 100644 index 0000000000000000000000000000000000000000..7635d9f87c025b2e62751715eb12d8b44997bda5 --- /dev/null +++ b/docs/html/intl/ja/training/monitoring-device-state/manifest-receivers.jd @@ -0,0 +1,50 @@ +page.title=オンデマンドでのブロードキャスト レシーバ操作 +parent.title=電池消費量の最適化 +parent.link=index.html + +trainingnavtop=true + +previous.title=接続状態の特定と監視 +previous.link=connectivity-monitoring.html + +@jd:body + + + +

    端末の状態変化を監視する最も単純な方法は、監視対象とする状態ごとに {@link android.content.BroadcastReceiver} を作成し、それぞれをアプリのマニフェスト内で登録するというものです。これらの各レシーバ内で、端末の現在の状態に基づいて反復アラームのスケジュールを再設定します。

    + +

    この方法のデメリットは、これらのレシーバのいずれかがトリガされるたびに端末がスリープから復帰することですが、このことは必要以上に頻繁に発生する可能性があります。

    + +

    これよりも良い方法は、実行時にブロードキャスト レシーバをオンまたはオフにするというものです。このようにすれば、マニフェスト内で宣言したレシーバを受動的アラームとして使用できます。つまり、このアラームは、必要なときにだけシステム イベントによって呼び出されます。

    + + +

    効率を上げるために状態変化レシーバのオンとオフを切り替える

    + +

    {@link android.content.pm.PackageManager} を使用すると、マニフェスト内で定義されているコンポーネントの有効化状態を切り替えることができます。このコンポーネントにはブロードキャスト レシーバも該当するので、次に示すようにオンとオフを切り替えることができます。

    + +
    ComponentName receiver = new ComponentName(context, myReceiver.class);
    +
    +PackageManager pm = context.getPackageManager();
    +
    +pm.setComponentEnabledSetting(receiver,
    +        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
    +        PackageManager.DONT_KILL_APP)
    + +

    この手法を使用すれば、接続が失われたことが判明した場合に、接続状態変化レシーバ以外のレシーバをすべて無効にすることができます。逆に、接続が確立された後は、接続状態変化の受信を停止します。オンラインかどうかを調べるのは、更新を実行する直前や、反復更新アラームのスケジュール再設定の直前だけで十分です。

    + +

    同じ手法を使用して、大量の帯域幅を必要とするダウンロードを延期することもできます。それには、接続状態の変化をリッスンするブロードキャスト レシーバを有効にしておき、端末が Wi-Fi に接続されたらダウンロードを開始します。

    diff --git a/docs/html/intl/ja/training/multiscreen/adaptui.jd b/docs/html/intl/ja/training/multiscreen/adaptui.jd new file mode 100644 index 0000000000000000000000000000000000000000..8b1e6acdee0552d9be9d119ca5507fb6ed32eb24 --- /dev/null +++ b/docs/html/intl/ja/training/multiscreen/adaptui.jd @@ -0,0 +1,212 @@ +page.title=順応性のある UI フローの実装 +parent.title=複数画面のデザイン +parent.link=index.html + +trainingnavtop=true +previous.title=さまざまな画面密度のサポート +previous.link=screendensities.html + +@jd:body + + + + + +

    アプリが現在表示しているレイアウトによって、UI フローが異なる可能性があります。たとえば、アプリがデュアルペイン モードであれば、左ペインのアイテムをクリックすると、単に右ペインにコンテンツが表示されるだけですが、シングルペイン モードであれば、コンテンツは(別のアクティビティ内の)コンテンツ専用のペインに表示される必要があります。

    + + +

    現在のレイアウトを判別する

    + +

    レイアウトによって実装が多少異なるので、まず、ユーザーが現在どのようなレイアウトを表示しているかを判別する必要があります。たとえば、ユーザーが表示しているレイアウトが「シングルペイン」モードなのか、「デュアルペイン」モードなのかを確認する必要があります。それは、以下のようなコードで、ある特定のビューが存在し、かつ可視になっているかを照会することで可能です:

    + +
    +public class NewsReaderActivity extends FragmentActivity {
    +    boolean mIsDualPane;
    +
    +    @Override
    +    public void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        setContentView(R.layout.main_layout);
    +
    +        View articleView = findViewById(R.id.article);
    +        mIsDualPane = articleView != null && 
    +                        articleView.getVisibility() == View.VISIBLE;
    +    }
    +}
    +
    + +

    このコードにおいて「article」ペインが使用可能かどうかを照会している点に注目してください。特定のレイアウトの照会をハードコーディングするよりもはるかに柔軟性があります。

    + +

    その他にも、さまざまなコンポーネントでも対応できる方法として、コンポーネントを操作する前に使用可能かどうかを確認する方法もあります。たとえば、News Reader サンプル アプリでは、メニューを開くボタンがありますが、このボタンは Android 3.0 よりも古いバージョンで動作しているときにしか表示されません(この機能は、API レベル 11 以上の {@link android.app.ActionBar} で提供されるため)。そこで、以下のようなコードを追加して、このボタンのイベント リスナーを追加します:

    + +
    +Button catButton = (Button) findViewById(R.id.categorybutton);
    +OnClickListener listener = /* create your listener here */;
    +if (catButton != null) {
    +    catButton.setOnClickListener(listener);
    +}
    +
    + + +

    現在のレイアウトに合わせて応答する

    + +

    現在のレイアウトによって、一部のアクションの結果が異なる可能性があります。たとえば、News Reader サンプルでは、見出しリストで見出しをクリックしたとき、デュアルペイン モードの UI の場合は右ペインに記事が表示されますが、シングルペインの UI の場合は別のアクティビティが起動します:

    + +
    +@Override
    +public void onHeadlineSelected(int index) {
    +    mArtIndex = index;
    +    if (mIsDualPane) {
    +        /* display article on the right pane */
    +        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    +    } else {
    +        /* start a separate activity */
    +        Intent intent = new Intent(this, ArticleActivity.class);
    +        intent.putExtra("catIndex", mCatIndex);
    +        intent.putExtra("artIndex", index);
    +        startActivity(intent);
    +    }
    +}
    +
    + +

    同様に、アプリがデュアルペイン モードの場合は、ナビ用タブでアクション バーを設定し、一方、シングルペイン モードの場合は、スピナー ウィジェットでナビを設定することになります。したがって、コードでは以下のようにどちらのケースが適切かを調べることも必要です:

    + +
    +final String CATEGORIES[] = { "トップ ニュース 政治", "政治", "経済", "Technology" };
    +
    +public void onCreate(Bundle savedInstanceState) {
    +    ....
    +    if (mIsDualPane) {
    +        /* use tabs for navigation */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
    +        int i;
    +        for (i = 0; i < CATEGORIES.length; i++) {
    +            actionBar.addTab(actionBar.newTab().setText(
    +                CATEGORIES[i]).setTabListener(handler));
    +        }
    +        actionBar.setSelectedNavigationItem(selTab);
    +    }
    +    else {
    +        /* use list navigation (spinner) */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
    +        SpinnerAdapter adap = new ArrayAdapter(this, 
    +                R.layout.headline_item, CATEGORIES);
    +        actionBar.setListNavigationCallbacks(adap, handler);
    +    }
    +}
    +
    + + +

    他のアクティビティのフラグメントを再利用する

    + +

    複数の画面に対応するように設計する場合、あるパターンが繰り返されますが、そうしたパターンは、ある画面設定ではペインとして、別の画面設定では別のアクティビティとして実装されるインターフェースの一部に存在します。たとえば、News Reader サンプルでは、ラージ画面の場合はニュース記事のテキストが右ペインに表示されますが、それよりも小さい画面の場合は別のアクティビティになります。

    + +

    このような場合、通常、複数のアクティビティで同じ {@link android.app.Fragment} サブクラスを再利用することでコードの重複を回避できます。たとえば、ArticleFragment は以下のようにデュアルペイン レイアウトで使用されます:

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    また、より小さな画面向けのアクティビティ レイアウト内では(レイアウトを使用せずに)再利用されます(ArticleActivity):

    + +
    +ArticleFragment frag = new ArticleFragment();
    +getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
    +
    + +

    当然、これは XML レイアウトでフラグメントを宣言するのと同じ効果がありますが、この場合は、XML レイアウトは必要ありません。このアクティビティのコンポーネントは記事フラグメントしかないからです。

    + +

    フラグメントを設計する際に注意すべき非常に重要なポイントの 1 つとして、特定のアクティビティに対して強い結合を作成しないことがあります。通常、これは、フラグメントが自分のホスト アクティビティとやり取りするのに必要なあらゆる手段を抽象化したインターフェースを定義し、さらに、そのインターフェースをホスト アクティビティに実装することで可能になります:

    + +

    たとえば、News Reader アプリの HeadlinesFragment は、まさにそのようになっています:

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    OnHeadlineSelectedListener mHeadlineSelectedListener = null;
    +
    +    /* Must be implemented by host activity */
    +    public interface OnHeadlineSelectedListener {
    +        public void onHeadlineSelected(int index);
    +    }
    +    ...
    +
    +    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
    +        mHeadlineSelectedListener = listener;
    +    }
    +}
    +
    + +

    これにより、ユーザーが見出しを選択すると、フラグメントは以下のように(特定のハードコーディングされたアクティビティに通知するのではなく)ホスト アクティビティが指定したリスナーに通知します:

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    @Override
    +    public void onItemClick(AdapterView<?> parent, 
    +                            View view, int position, long id) {
    +        if (null != mHeadlineSelectedListener) {
    +            mHeadlineSelectedListener.onHeadlineSelected(position);
    +        }
    +    }
    +    ...
    +}
    +
    + +

    このテクニックについては、タブレットと携帯端末のサポートで詳しく説明されています。

    + + +

    画面設定の変更を処理する

    + +

    インターフェースの各パーツを実装するのに個別のアクティビティを使用している場合、インターフェースの一貫性を維持するために、(向きの変更などの)特定の設定変更に対応できるように注意する必要があります。

    + +

    たとえば、Android 3.0 以上が動作する一般的な 7 インチ タブレットでは、News Reader サンプルがニュース記事を表示する場合、縦表示では個別のアクティビティを使用しますが、横表示では 2 ペイン レイアウトを使用します。

    + +

    つまり、縦表示のときに記事閲覧用アクティビティが画面上にある場合、画面の向きが横方向に変わったことを検出したら、コンテンツを 2 ペイン レイアウトで表示するために、そのアクティビティを終了してメインのアクティビティに戻り、適切に応答しなければなりません:

    + +
    +public class ArticleActivity extends FragmentActivity {
    +    int mCatIndex, mArtIndex;
    +
    +    @Override
    +    protected void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
    +        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
    +
    +        // If should be in two-pane mode, finish to return to main activity
    +        if (getResources().getBoolean(R.bool.has_two_panes)) {
    +            finish();
    +            return;
    +        }
    +        ...
    +}
    +
    + + diff --git a/docs/html/intl/ja/training/multiscreen/index.jd b/docs/html/intl/ja/training/multiscreen/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..ff84f8a718e656ca4f26e0fea50f6f7e2f694ef7 --- /dev/null +++ b/docs/html/intl/ja/training/multiscreen/index.jd @@ -0,0 +1,64 @@ +page.title=複数画面のデザイン + +trainingnavtop=true +startpage=true +next.title=さまざまな画面サイズのサポート +next.link=screensizes.html + +@jd:body + +
    +
    + +

    必要な知識と前提条件

    + + + +

    関連ドキュメント

    + + + +

    試してみる

    + + + +
    +
    + +

    Android は、小さな携帯電話から大きなテレビまで、画面サイズも種類もさまざまなデバイスに搭載できます。そのため、できる限り多くのユーザーが使用できるように、すべての画面サイズに対応できるようアプリを設計することが重要になります。

    + +

    しかし、さまざまな種類のデバイスに対応できるだけでは十分ではありません。画面サイズによって、ユーザーが操作できることが決まってくるため、本当にユーザーを満足させてよい印象を持ってもらうためには、アプリが単に複数の画面をサポートするだけでは不十分です: 画面設定ごとにユーザー エクスペリエンスを最適化する必要があります。

    + +

    このクラスは、いくつかの画面設定に合わせて最適化されたユーザー インターフェースを実装する方法を提供します。

    + +

    各レッスンで紹介されているコードは、複数の画面に合わせて最適化する際、ベスト プラクティスとなるサンプル アプリから抜粋したものです。このサンプルを(右側から)ダウンロードして、再利用可能なコードのソースとしてご自分のアプリに使用することができます。

    + +

    注: このクラスと関連サンプルでは、サポート ライブラリを使用します。理由は、Android 3.0 未満のバージョンで {@link android.app.Fragment} API を使用するためです。このクラスのすべての API を使用するには、ライブラリをダウンロードして、アプリに追加する必要があります。

    + + +

    レッスン

    + +
    +
    さまざまな画面サイズのサポート
    +
    このレッスンでは、さまざまな画面サイズに適したレイアウトを(柔軟なビュー サイズ、 {@link android.widget.RelativeLayout}、画面サイズと画面の向きの修飾子、エイリアス フィルタ、ナインパッチ ビットマップを使用して)設計する方法について学習します。
    + +
    さまざまな画面密度のサポート
    +
    このレッスンでは、(密度非依存ピクセルを使用し、各密度に適したビットマップを提供して)ピクセル密度が異なる画面をサポートする方法について学習します。
    + +
    順応性のある UI フローの実装
    +
    このレッスンでは、いくつかの画面サイズ/密度の組み合わせに適した方法(実行時にアクティブなレイアウトを検出する方法、現在のレイアウトに合わせて応答する方法、画面設定の変更を処理する方法)で UI を実装する方法について学習します。
    +
    diff --git a/docs/html/intl/ja/training/multiscreen/screendensities.jd b/docs/html/intl/ja/training/multiscreen/screendensities.jd new file mode 100644 index 0000000000000000000000000000000000000000..3482d5c5117e7ec5789a1c5c6577fd5c81c5a8a3 --- /dev/null +++ b/docs/html/intl/ja/training/multiscreen/screendensities.jd @@ -0,0 +1,100 @@ +page.title=さまざまな画面密度のサポート +parent.title=複数画面のデザイン +parent.link=index.html + +trainingnavtop=true +previous.title=さまざまな画面サイズのサポート +previous.link=screensizes.html +next.title=順応性のある UI フローの実装 +next.link=adaptui.html + +@jd:body + + + +
    +
    + +

    このレッスンでの学習内容

    +
      +
    1. 密度非依存ピクセルを使用する
    2. +
    3. 代替ビットマップを生成する
    4. +
    + +

    関連ドキュメント

    + + + +

    試してみる

    + + + + +
    +
    + +

    このレッスンでは、異なるリソースを生成し、かつ解像度非依存単位を使用して、異なる画面密度をサポートする方法について学習します。

    + +

    密度非依存ピクセルを使用する

    + +

    レイアウトを設計する際に回避すべきよくある落とし穴の 1 つとして、絶対ピクセルを使用して距離やサイズを定義することがあります。ピクセルを使用してレイアウトのサイズを定義すると、画面によってピクセル密度が異なるため、問題が起こります。したがって、同じピクセル数では、デバイスが異なる場合に物理サイズが異なる可能性があります。そのため、サイズを指定する場合は、常に dp 単位や sp 単位を使用します。dp とは、1 ピクセルの物理サイズが 160 dpi に相当する密度非依存ピクセルです。sp も基本単位は同じですが、ユーザーの優先テキスト サイズによってサイズが決まるので(スケール非依存ピクセル)、テキスト サイズを定義する際にはこの単位を使用する必要があります(ただし、レイアウト サイズには絶対に使用しないこと)。

    + +

    たとえば、2 つのビューの間にスペースを挿入する場合は、px ではなくて dp を使用します:

    + +
    +<Button android:layout_width="wrap_content" 
    +    android:layout_height="wrap_content" 
    +    android:text="@string/clickme"
    +    android:layout_marginTop="20dp" />
    +
    + +

    テキスト サイズを指定する場合は、常に sp を使用します:

    + +
    +<TextView android:layout_width="match_parent" 
    +    android:layout_height="wrap_content" 
    +    android:textSize="20sp" />
    +
    + + +

    代替ビットマップを生成する

    + +

    Android は、画面密度がさまざまなデバイスで動作するため、それぞれの汎用密度バケット(低密度、中密度、高密度、超高密度)に合わせてビットマップ リソースを生成する必要があります。そうすることで、すべての画面密度で画質とパフォーマンスが向上します。

    + +

    これらの画像を生成するには、ベクター形式の未加工リソースから、次のサイズ スケールを使用して密度別に画像を生成する必要があります:

    + +

      +
    • xhdpi: 2.0 +
    • hdpi: 1.5 +
    • mdpi: 1.0(基準) +
    • ldpi: 0.75 +

    + +

    つまり、200×200 画像(xhdpi デバイス用)を生成する場合、同じリソースを 150×150 画像(hdpi デバイス用)、100×100 画像(mdpi デバイス用)、75×75(ldpi デバイス用)でも生成する必要があります。

    + +

    さらに、生成した画像を res/ 下の適切なサブディレクトリに配置することで、アプリが動作するデバイスの画面密度に基づいて、自動的に適切な画像が表示されます:

    + +
    +MyProject/
    +  res/
    +    drawable-xhdpi/
    +        awesomeimage.png
    +    drawable-hdpi/
    +        awesomeimage.png
    +    drawable-mdpi/
    +        awesomeimage.png
    +    drawable-ldpi/
    +        awesomeimage.png
    +
    + +

    また、@drawable/awesomeimage を参照する場合は常に画面の dpi に基づいて、適切なビットマップが選択されます。

    + +

    アプリ用のアイコン アセットを作成するためのヒントとガイドラインについては、アイコン設計のガイドラインをご覧ください。

    + diff --git a/docs/html/intl/ja/training/multiscreen/screensizes.jd b/docs/html/intl/ja/training/multiscreen/screensizes.jd new file mode 100644 index 0000000000000000000000000000000000000000..3655a33be2b96857a8132a5a6fbe76e65222719e --- /dev/null +++ b/docs/html/intl/ja/training/multiscreen/screensizes.jd @@ -0,0 +1,279 @@ +page.title=さまざまな画面サイズのサポート +parent.title=複数画面のデザイン +parent.link=index.html + +trainingnavtop=true +next.title=さまざまな画面密度のサポート +next.link=screendensities.html + +@jd:body + + + + + +

    このレッスンでは、異なる画面サイズを以下のような方法でサポートする方法について学習します:

    +
      +
    • 画面に収まるようにレイアウト サイズを適切に変更する
    • +
    • 画面設定に基づいて適切な UI レイアウトを表示する
    • +
    • 適切な画面に適切なレイアウトを適用する
    • +
    • 適切にサイズ調整したビットマップを表示する
    • +
    + + +

    「wrap_content」と「match_parent」を使用する

    + +

    レイアウトをさまざまな画面サイズに柔軟に対応させるには、一部のビュー コンポーネントの幅と高さに "wrap_content""match_parent" を使用する必要があります。"wrap_content" を使用すると、ビューの幅や高さがそのビュー内にコンテンツが収まるのに必要な最小サイズに設定されます。一方、"match_parent"(API レベル 8 より前の名称は "fill_parent")を使用すると、コンポーネントがその親ビューのサイズに一致するまで拡大されます。

    + +

    ハードコーディングされたサイズの代わりに "wrap_content""match_parent" を使用することで、ビューはそれぞれ、そのビューに必要なスペースだけを使用したり、空きスペースを埋めるまで拡大したりします。次に例を示します:

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    このサンプルでは、特定のサイズではない "wrap_content""match_parent" をコンポーネント サイズにどのように使用しているかに注目してください。こうすることで、異なる画面のサイズと向きにレイアウトを正しく対応させることができます。

    + +

    たとえば、このレイアウトを縦表示と横表示で表示したときの見え方を以下に示します。コンポーネントのサイズが幅と高さに自動的に適合している点に注目してください:

    + + +

    図 1. News Reader サンプル アプリの縦表示(左)と横表示(右)

    + + +

    RelativeLayout を使用する

    + +

    ネストされた {@link android.widget.LinearLayout} インスタンスや、 "wrap_content""match_parent" のサイズの組み合わせを使用すると、かなり複雑なレイアウトを作成できます。しかし、 {@link android.widget.LinearLayout} では、子ビューの空間的な位置関係を正確に制御することはできません。 {@link android.widget.LinearLayout} のビューは、 単に一列に並ぶだけです。子ビューに対して直線以外のさまざまな配置を実現する必要がある場合は、 {@link android.widget.RelativeLayout}を使用することでうまくいくことがよくあります。たとえば、1 つの子ビューを画面の左側に配置し、もう 1 つの子ビューを右側に配置できます。

    + +

    次に例を示します:

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:layout_width="match_parent"
    +    android:layout_height="match_parent">
    +    <TextView
    +        android:id="@+id/label"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:text="Type here:"/>
    +    <EditText
    +        android:id="@+id/entry"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/label"/>
    +    <Button
    +        android:id="@+id/ok"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/entry"
    +        android:layout_alignParentRight="true"
    +        android:layout_marginLeft="10dp"
    +        android:text="OK" />
    +    <Button
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_toLeftOf="@id/ok"
    +        android:layout_alignTop="@id/ok"
    +        android:text="Cancel" />
    +</RelativeLayout>
    +
    + +

    図 2 は、このレイアウトの QVGA 画面での見え方を示しています。

    + + +

    図 2. QVGA 画面(スモール画面)のスクリーンショット

    + +

    図 3 は、このレイアウトのラージ画面での見え方を示しています。

    + + +

    図 3. WSVGA 画面(ラージ画面)のスクリーンショット

    + +

    コンポーネントのサイズが変更されても、 {@link android.widget.RelativeLayout.LayoutParams}で指定されたとおりに空間的な位置関係が維持されていることがわかります。

    + + +

    サイズ修飾子を使用する

    + +

    柔軟なレイアウトや相対的なレイアウトから得られる恩恵は、前のセクションで説明したことくらいです。これらのレイアウトはコンポーネントの内部や周囲のスペースを引き延ばすことでさまざまな画面に対応しますが、それぞれの画面サイズに合った最高のユーザー エクスペリエンスを実現していない可能性があります。したがって、アプリでは、柔軟なレイアウトの実装だけではなく、さまざまな画面設定に合わせた複数の代替レイアウトも必要になります。これは、設定修飾子を使用することで実現可能です。設定修飾子により、ランタイムが現在のデバイスの設定に基づいて適切なリソース(画面サイズ別のレイアウト デザインなど)を自動的に選択できます。

    + +

    たとえば、多くのアプリでは、ラージ画面用に「2 ペイン」パターンを実装しています(一方のペインに項目リスト、もう一方のペインにそのコンテンツを表示することが可能です)。タブレットやテレビは両方のペインを同時に表示できるほど十分に大きい画面ですが、携帯端末の画面では 2 つのペインを別々に表示する必要があります。そのようなレイアウトを実装するには、次のようなファイルが必要になります:

    + +
      +
    • res/layout/main.xml、シングルペイン(デフォルト)レイアウト: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-large/main.xml、2 ペイン レイアウト: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    2 番目のレイアウトのディレクトリ名の large 修飾子に注目してください。このレイアウトは、ラージ(7 インチ以上のタブレットなど)と分類された画面のデバイスで選択されます。それよりも小さいデバイスでは、その他のレイアウト(修飾子なし)が選択されます。

    + + +

    最小幅修飾子を使用する

    + +

    Android 3.2 未満のデバイスでデベロッパーが抱えていた問題の 1 つに、Dell Streak、初代 Galaxy Tab、7 インチ タブレット全般を含む、「ラージ」画面サイズの分類があります。しかし、多くのアプリでは、すべて「ラージ」画面と見なされたとしても、このカテゴリ内のデバイスのサイズに合わせて異なるレイアウト(5 インチと 7 インチのデバイス用など)を表示したい場合があります。そこで、Android 3.2 では「最小幅」修飾子などが導入されました。

    + +

    最小幅修飾子を使用すると、dp で指定した特定の最小幅の画面を対象とすることができます。たとえば、一般的な 7 インチ タブレットは最小幅が 600 dp なので、これらの画面の UI で 2 つのペイン(ただし、それよりも小さい画面ではシングル リスト)を表示したい場合は、前のセクションで説明した 2 つのレイアウトをシングルペイン レイアウト用と 2 ペイン レイアウト用としてそのまま利用できます。ただし、large サイズ修飾子の代わりに、sw600dp を使用して、最小幅が 600 dp の画面では 2 ペイン レイアウトになるよう指定します:

    + +
      +
    • res/layout/main.xml、シングルペイン(デフォルト)レイアウト: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-sw600dp/main.xml、2 ペイン レイアウト: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    つまり、最小幅が 600dp 以上のデバイスでは layout-sw600dp/main.xml(2 ペイン)レイアウトが選択され、それよりも小さい画面では layout/main.xml(シングルペイン)レイアウトが選択されるということです。

    + +

    ただし、Android 3.2 未満のデバイスではこの修飾子は機能しません。これは sw600dp をサイズ修飾子として認識できないためです。したがって、引き続き large 修飾子も使用する必要があります。そこで、res/layout-sw600dp/main.xml と同じ内容の res/layout-large/main.xml という名前のファイルも必要になります。次のセクションでは、このようにレイアウト ファイルの重複を避けるためのテクニックについて学習します。

    + + +

    レイアウト エイリアスを使用する

    + +

    最小幅修飾子は、Android 3.2 以上でしか利用できません。したがって、旧バージョンとの互換性を維持するために、あいまいなサイズ分類(small、normal、large、xlarge)も併用することが必要です。たとえば、携帯端末ではシングルペイン UI、7 インチ タブレットやテレビなどの大きなデバイスではマルチペイン UI を表示するよう UI を設計する場合、以下のようなファイルが必要になります:

    + +

      +
    • res/layout/main.xml: シングルペイン レイアウト
    • +
    • res/layout-large: マルチペイン レイアウト
    • +
    • res/layout-sw600dp: マルチペイン レイアウト
    • +

    + +

    最後の 2 つのファイルは同じものです。一方は Android 3.2 デバイス用で、もう一方は旧バージョンの Android を搭載したタブレットとテレビ用です。

    + +

    このようにタブレット/テレビ用として同じファイルを使用することで起こる重複(さらに、その結果メンテナンスが困難になる状況)を避けるために、エイリアス ファイルを使用できます。たとえば、次のようなレイアウトを定義できます:

    + +
      +
    • res/layout/main.xml、シングルペイン レイアウト
    • +
    • res/layout/main_twopanes.xml、2 ペイン レイアウト
    • +
    + +

    さらに、次の 2 つのファイルを追加します:

    + +

      +
    • res/values-large/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      +
    • + +
    • res/values-sw600dp/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      + +
    • +

    + +

    最後の 2 つのファイルの内容は同じですが、実際のレイアウトは定義していません。これらのファイルは、単に {@code main}{@code main_twopanes}へのエイリアスになるように設定しただけです。これらのファイルには largesw600dp セレクタが含まれているので、Android のバージョンに関係なく( +Android 3.2 未満のタブレット/テレビは {@code large} に一致し、Android 3.2 以上のタブレット/テレビは sw600dp に一致します)タブレット/テレビに適用されます。

    + + +

    画面の向きの修飾子を使用する

    + +

    横表示と縦表示が両方とも正しく表示されるレイアウトもありますが、ほとんどのレイアウトは調整が必要になります。以下に、News Reader サンプル アプリの各画面のサイズと向きでレイアウトがどのように表示されるかを示します:

    + +

      +
    • スモール画面、縦表示: シングル ペイン、ロゴ付き
    • +
    • スモール画面、横表示: シングル ペイン、ロゴ付き
    • +
    • 7 インチ タブレット、縦表示: シングル ペイン、アクション バー付き
    • +
    • 7 インチ タブレット、横表示: デュアル ペイン、ワイド、アクション バー付き
    • +
    • 10 インチ タブレット、縦表示: デュアル ペイン、ナロー、アクション バー付き
    • +
    • 10 インチ タブレット、横表示: デュアル ペイン、ワイド、アクション バー付き
    • +
    • テレビ、横表示: デュアル ペイン、ワイド、アクション バー付き
    • +

    + +

    これらの各レイアウトは、res/layout/ ディレクトリ内の XML ファイルに定義されています。各レイアウトをさまざまな画面設定に割り当てるには、アプリでレイアウト エイリアスを使用して、各設定に対応付けます:

    + +

    res/layout/onepane.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} + +

    res/layout/onepane_with_bar.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    res/layout/twopanes.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    res/layout/twopanes_narrow.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all} + +

    これで、考えられるすべてのレイアウトが定義されました。あとは、設定修飾子を使用して、適切なレイアウトを各設定にマッピングするだけです。そのためには、以下のようなレイアウト エイリアス テクニックを使用することができます:

    + +

    res/values/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all} + +

    res/values-sw600dp-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml +all} + +

    res/values-sw600dp-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml +all} + +

    res/values-large-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all} + +

    res/values-large-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all} + + + +

    ナインパッチ ビットマップを使用する

    + +

    異なる画面サイズをサポートするには、画像リソースも異なるサイズに対応できないといけません。たとえば、ボタンの背景は、適用されるボタンの形状が異なってもサイズが合わなければいけません。

    + +

    サイズ変更可能なコンポーネントでシンプルな画像を使用すると、ランタイムによって画像が一様に拡大縮小されるので、いくぶん期待はずれの結果になることがすぐにわかります。これは、ナインパッチ ビットマップを使用することで解決します。ナインパッチ ビットマップとは、拡大可能な領域と拡大不可能な領域が指定された特殊なフォーマットの PNG ファイルです。

    + +

    そのため、サイズが変化するコンポーネントで使用するビットマップをデザインする場合は、常にナインパッチを使用してください。ビットマップをナインパッチに変換するには、まず、通常の画像を用意します(図 4: わかりやすく 4 倍に拡大しています)。

    + + +

    図 4. button.png

    + +

    次に、 SDK の draw9patch ユーティリティ(tools/ ディレクトリにあります)からナインパッチを実行して、左境界線と上境界線上にピクセル(ドット)を描くことで拡大する領域にマークを付けます。また、右境界線と下境界線上にピクセルを描くことで、コンテンツを入れる領域をマークできます(図 5)。

    + + +

    図 5. button.9.png

    + +

    境界線上に黒いピクセルがあることに注目してください。左境界線と上境界線上のものは画像を拡大できる領域で、右境界線と下境界線上のものはコンテンツを配置する領域を示しています。

    + +

    さらに、.9.png という拡張子にも注目してください。この拡張子は必ず使用してください。そうすることで、通常の PNG 画像ではなく、ナインパッチ画像であることがフレームワークによって検出されます。

    + +

    この背景を(android:background="@drawable/button" を設定して)コンポーネントに適用すると、ボタンのサイズに合わせて適切に画像が拡大します(図 6 のさまざまなサイズを参照)。

    + + +

    図 6button.9.png ナインパッチを使用したさまざまなサイズのボタン

    + diff --git a/docs/html/intl/ko/training/monitoring-device-state/battery-monitoring.jd b/docs/html/intl/ko/training/monitoring-device-state/battery-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..2eacccf64106d67ac830dc9b34661c377e29e90e --- /dev/null +++ b/docs/html/intl/ko/training/monitoring-device-state/battery-monitoring.jd @@ -0,0 +1,120 @@ +page.title=배터리 수준 및 충전 상태 모니터링 +parent.title=배터리 수명 최적화 +parent.link=index.html + +trainingnavtop=true +next.title=도킹 상태와 유형 확인 및 모니터링 +next.link=docking-monitoring.html + +@jd:body + + + +

    백그라운드 업데이트가 배터리 수명에 미치는 영향을 줄이기 위하여 백그라운드 업데이트 빈도수를 변경하는 경우, 현재 배터리 수준과 충전 상태부터 확인하는 것이 좋습니다.

    + +

    애플리케이션 업데이트 수행이 배터리 수명에 미치는 영향은 배터리 수준 및 기기의 충전 상태에 따라 다릅니다. 기기를 AC 충전기로 충전하는 동안 업데이트 수행이 미치는 영향은 무시해도 좋습니다. 따라서 기기가 범용 충전기에 연결되어 있을 때는 대부분 새로고침 빈도를 최대화할 수 있습니다. 반대로 기기가 충전 중이 아니라면, 업데이트 빈도를 줄이는 것이 배터리 수명 연장에 도움이 됩니다.

    + +

    마찬가지로 배터리가 거의 방전된 경우, 업데이트 빈도를 줄이거나 중단할 수 있습니다.

    + + +

    현재 충전 상태 확인

    + +

    먼저 현재 충전 상태를 확인하는 것부터 시작합니다. {@link android.os.BatteryManager}는 배터리 충전 상태 등 충전 정보를 스티키 {@link android.content.Intent}를 통해 브로드캐스트합니다.

    + +

    스티키 인텐트이므로 {@link android.content.BroadcastReceiver}를 등록할 필요가 없으며 아래 코드 상의 리시버와 같이 간단히 {@code registerReceiver}을(를) 호출하여 {@code null}에 제출하면 현재 배터리 상태가 담긴 인텐트가 반환됩니다. 여기에 실제 {@link android.content.BroadcastReceiver} 개체 사용할 수 있으나, 이후 섹션에서 업데이트를 다루게 되므로 그럴 필요는 없습니다.

    + +
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    +Intent batteryStatus = context.registerReceiver(null, ifilter);
    + +

    현재 충전 상태와 어떤 충전기(USB 또는 AC 전원)로 충전하는지 추출할 수 있습니다.

    + +

    // Are we charging / charged?
    +int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
    +boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
    +                     status == BatteryManager.BATTERY_STATUS_FULL;
    +
    +// How are we charging?
    +int chargePlug = battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    +boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
    +boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
    + +

    일반적으로 기기가 AC 충전기에 연결된 경우 백그라운드 업데이트 빈도를 최대화합니다. USB를 통해 충전하는 경우 업데이트 빈도를 낮춥니다. 배터리가 방전 중이라면 빈도를 더 많이 낮추도록 합니다.

    + + +

    충전 상태 변경사항 모니터링

    + +

    충전 상태는 수시로 변하므로 충전 상태의 변경사항을 확인하고 이에 따라 업데이트 주기를 변경하는 것이 중요합니다.

    + +

    {@link android.os.BatteryManager}는 기기가 전원에 연결되어 있는지 여부와 관계없이 언제나 액션을 브로드캐스트합니다. 앱이 실행되지 않는 동안에도 이벤트를 수신하는 것이 중요합니다. 특히 백그라운드 업데이트를 실행하기 위해 앱을 시작하는 빈도수에 이벤트가 영향을 주기 때문입니다. 따라서 두 이벤트를 수신하려면 매니페스트에서 {@link android.content.BroadcastReceiver}를 등록하여 인텐트 필터 내에 {@link android.content.Intent#ACTION_POWER_CONNECTED}와 {@link android.content.Intent#ACTION_POWER_DISCONNECTED}를 정의해야 합니다.

    + +
    <receiver android:name=".PowerConnectionReceiver">
    +  <intent-filter>
    +    <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
    +    <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
    +  </intent-filter>
    +</receiver>
    + +

    다음의 {@link android.content.BroadcastReceiver} 구현에서 이전 단계에서 설명한 대로 현재 충전 상태와 방법을 알아낼 수 있습니다.

    + +
    public class PowerConnectionReceiver extends BroadcastReceiver {
    +    @Override
    +    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;
    +    }
    +}
    + + +

    현재 배터리 수준 확인

    + +

    현재 배터리 수준을 확인하는 것이 유용한 경우도 있습니다. 배터리 충전이 수준 이하인 경우 백그라운드 업데이트 빈도를 줄일 수 있습니다.

    + +

    다음은 배터리 상태 정보가 담긴 인텐트에서 현재 배터리 수준 및 충전 상태를 추출하는 방법입니다.

    + +
    int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    +int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
    +
    +float batteryPct = level / (float)scale;
    + + +

    배터리 수준 중요 변경사항 모니터링

    + +

    배터리 상태를 지속적으로 확인하는 것은 쉽지 않지만, 꼭 그럴 필요도 없습니다.

    + +

    배터리 수준을 지속적으로 모니터링하는 것은 앱의 다른 작업보다 배터리에 더 큰 영향을 미칩니다. 따라서 기기가 배터리 전원 부족 상태가 되거나 이를 벗어날 때 등 중요한 변경사항만 확인하는 것이 좋습니다.

    + +

    다음 코드는 매니페스트의 브로드캐스트 리시버 내의 인텐트 필터를 보여줍니다. 배터리가 얼마 남지 않거나{@link android.content.Intent#ACTION_BATTERY_LOW} 배터리 상태가 회복되었을 때{@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"/>
    +  </intent-filter>
    +</receiver>
    + +

    배터리 충전 상태가 매우 낮은 경우 백그라운드 업데이트를 사용하지 않는 것이 좋습니다. 전화기가 꺼져버리면 최신 데이터를 제공하는 것이 의미가 없기 때문입니다.

    + +

    기기를 충전하는 것은 곧 기기를 도크에 집어넣는 것과 같은 경우가 많습니다. 다음 강의는 현재 도크 상태를 확인하고 기기 도킹의 변경사항을 모니터링하는 방법을 보여줍니다.

    + diff --git a/docs/html/intl/ko/training/monitoring-device-state/connectivity-monitoring.jd b/docs/html/intl/ko/training/monitoring-device-state/connectivity-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..5666b98c904532b37fdde6274fad8d16eeaa2595 --- /dev/null +++ b/docs/html/intl/ko/training/monitoring-device-state/connectivity-monitoring.jd @@ -0,0 +1,70 @@ +page.title=연결 상태 확인 및 모니터링 +parent.title=배터리 수명 최적화 +parent.link=index.html + +trainingnavtop=true + +previous.title=도킹 상태와 유형 확인 및 모니터링 +previous.link=docking-monitoring.html +next.title=온디맨드로 브로드캐스트 수신기 조작 +next.link=manifest-receivers.html + +@jd:body + + + +

    반복 알람과 백그라운드 서비스는 일반적으로 인터넷 리소스 및 캐시 데이터로부터 애플리케이션의 업데이트를 예약하거나 긴 시간이 필요한 다운로드를 실행하는 데 사용됩니다. 하지만 인터넷에 연결되어 있지 않거나 연결이 매우 느려 다운로드를 완료하지 못한다면 업데이트 예약을 해도 소용이 없겠죠?

    + +

    인터넷에 연결되었는지, 어떤 연결 방식인지를 확인하기 위하여 {@link android.net.ConnectivityManager}를 사용할 수 있습니다.

    + + +

    인터넷에 연결되어 있는지 확인

    + +

    인터넷에 연결되어 있지 않는 경우 인터넷 리소스를 기반으로 한 업데이트 예약을 할 필요가 없습니다. 다음은 활성 네트워크를 쿼리하고 인터넷이 연결되어 있는지 확인하기 위한 {@link android.net.ConnectivityManager} 사용법을 보여줍니다.

    + +
    ConnectivityManager cm =
    +        (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    + 
    +NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    +boolean isConnected = activeNetwork.isConnectedOrConnecting();
    + + +

    인터넷 연결 유형 확인

    + +

    현재 사용할 수 있는 인터넷 연결 유형을 확인할 수도 있습니다.

    + +

    연결은 모바일 데이터, WiMAZ, Wi-Fi 및 이더넷 연결을 통해 제공될 수 있습니다. 아래와 같이 활성 네트워크의 유형을 쿼리하면, 사용 가능한 대역폭에 따라 업데이트 빈도를 변경할 수 있습니다.

    + +
    boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
    + +

    모바일 데이터 비용은 Wi-Fi보다 높은 경향이 있으므로, 모바일 연결인 경우 앱의 업데이트 빈도를 줄여야 합니다. 마찬가지로 Wi-Fi로 연결되기까지 큰 용량의 다운로드는 일시 중지해야 합니다.

    + +

    업데이트를 비활성화한 경우, 인터넷 연결이 재개되면 업데이트를 다시 시작하기 위해 연결 변경사항을 알고 있는 것이 중요합니다.

    + + +

    연결 변경사항 모니터링

    + +

    연결 정보가 변경될 때마다 {@link android.net.ConnectivityManager}는 {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION}({@code "android.net.conn.CONNECTIVITY_CHANGE"}) 액션을 브로드캐스트합니다. 변경사항을 수신하거나 적절히 백그라운드 업데이트를 다시 시작 또는 일시 중지하기 위해 매니페스트에서 브로드캐스트 리시버를 등록할 수 있습니다.

    + +
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    + +

    연결 정보는 수시로 변경될 수 있습니다. 모바일과 Wi-Fi 간에 이동할 때마다 브로드캐스트가 실행됩니다. 따라서 업데이트나 다운로드를 일시 중지한 경우에만 브로드캐스트를 확인하는 것이 좋습니다. 업데이트를 시작하기 전이나 이전에 업데이트를 일시 중지했던 경우에만 확인하는 것으로 충분합니다.

    + +

    이 기술은 다음 강의에서 설명하는 매니페스트에서 선언한 브로드캐스트 리시버의 전환이 필요합니다.

    diff --git a/docs/html/intl/ko/training/monitoring-device-state/docking-monitoring.jd b/docs/html/intl/ko/training/monitoring-device-state/docking-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..0cd61a067d93b96794857e72052388369e847246 --- /dev/null +++ b/docs/html/intl/ko/training/monitoring-device-state/docking-monitoring.jd @@ -0,0 +1,74 @@ +page.title=도킹 상태와 유형 확인 및 모니터링 +parent.title=배터리 수명 최적화 +parent.link=index.html + +trainingnavtop=true +previous.title= 배터리 수준 및 충전 상태 모니터링 +previous.link=battery-monitoring.html +next.title= 연결 상태 확인 및 모니터링 +next.link=connectivity-monitoring.html + +@jd:body + + + +

    Android 기기는 여러 종류의 도크로 도킹될 수 있습니다. 여기에는 카폰 또는 홈 도크와 디지털 및 아날로그 도크가 포함됩니다. 많은 도크가 도킹된 기기에 전기를 공급하므로 일반적으로 충전 상태와 도크 상태는 밀접한 관련이 있습니다.

    + +

    전화의 도크 상태가 업데이트 빈도에 어떻게 영향을 미치는지는 앱에 따라 다릅니다. 스포츠 센터 앱이라면 데스크톱 도크에서 업데이트 빈도를 높이고 카폰 도크에 연결된 경우 업데이트를 완전히 사용 중지해도 좋습니다. 반대로 교통 상황을 제공하는 앱이라면 카폰 도크에서 업데이트를 최대화해도 좋습니다.

    + +

    도크 상태는 스티키 {@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);
    +Intent dockStatus = context.registerReceiver(null, ifilter);
    + +

    {@code EXTRA_DOCK_STATE} 추가로부터 현재 도킹 상태를 추출할 수 있습니다.

    + +

    int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
    +boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
    + + +

    현재 도크 유형 확인

    + +

    4가지 유형의 도크가 있습니다. +

    • 카폰
    • +
    • 데스크
    • +
    • 저가형(아날로그) 데스크
    • +
    • 고가형(디지털) 데스크

    + +

    마지막 두 가지 옵션은 API 수준 11의 Android에만 제공되어 있으므로, 디지털 또는 아날로그에 상관하지 않고 관심 있는 세 가지 도크 유형에 대해 확인하는 것이 좋습니다.

    + +
    boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
    +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} 액션이 브로드캐스트됩니다. 기기의 도크 상태 변경사항을 모니터링하려면 아래에 표시된 대로 애플리케이션 매니페스트에서 브로드캐스트 리시버를 등록하세요.

    + +
    <action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
    + +

    이전 단계에서 설명한 기술을 사용하여 리시버 구현에서 도크 유형 및 상태를 추출할 수 있습니다.

    diff --git a/docs/html/intl/ko/training/monitoring-device-state/index.jd b/docs/html/intl/ko/training/monitoring-device-state/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..f96e2e16dc57837ae1cde90fa62ce07e8ec2bcee --- /dev/null +++ b/docs/html/intl/ko/training/monitoring-device-state/index.jd @@ -0,0 +1,49 @@ +page.title=배터리 수명 최적화 + +trainingnavtop=true +startpage=true +next.title=배터리 수준 및 충전 상태 모니터링 +next.link=battery-monitoring.html + +@jd:body + +
    +
    + +

    요구사항과 선행조건

    + + +

    참고자료

    + + +
    +
    + +

    좋은 앱은 호스트 기기의 배터리 수명에 미치는 영향이 미미해야 합니다. 강의를 통해 호스트 기기의 상태에 따라 기능과 동작을 수정하는 것을 모니터링하는 앱을 구축할 수 있게 됩니다.

    + +

    연결이 끊겼을 때 백그라운드 서비스 업데이트를 사용 중지하거나, 배터리 수준이 낮을 때 업데이트 빈도를 줄이는 조치를 취하여, 사용자 환경을 손상시키지 않고 배터리 수명에 미치는 영향을 최소화할 수 있습니다.

    + +

    강의

    + + + +
    +
    배터리 수준 및 충전 상태 모니터링
    +
    충전 상태에서 현재 배터리 수준 및 변경사항을 확인 및 모니터링하여 앱의 업데이트 빈도를 변경하는 법을 알아보세요.
    + +
    도킹 상태와 유형 확인 및 모니터링
    +
    최적의 새로고침 빈도는 호스트 기기의 사용 방법에 따라 달라질 수 있습니다. 앱의 동작에 영향을 미치는 도킹 상태와 도크 유형을 확인 및 모니터링하는 방법을 알아보세요.
    + +
    연결 상태 확인 및 모니터링
    +
    인터넷 연결 없이 온라인 소스를 통해 앱을 업데이트할 수 없습니다. 연결 상태를 확인하여 백그라운드 업데이트 빈도를 변경하는 방법을 알아보세요. 고대역폭 작업을 시작하기 전에 Wi-Fi 또는 모바일 연결을 확인하는 방법도 알 수 있습니다.
    + +
    온디맨드로 브로드캐스트 수신기 조작
    +
    매니페스트 내에 선언했던 브로드캐스트 리시버는 현재 기기 상태에서 필요 없는 것을 사용 중지하도록 런타임 때 전환될 수 있습니다. 기기가 특정 상태에 도달할 때까지 상태 변화 리시버 및 지연 액션을 전환 및 단계적으로 연결하여 효율성을 향상하는 법을 알아보세요.
    +
    \ No newline at end of file diff --git a/docs/html/intl/ko/training/monitoring-device-state/manifest-receivers.jd b/docs/html/intl/ko/training/monitoring-device-state/manifest-receivers.jd new file mode 100644 index 0000000000000000000000000000000000000000..c5c311b75f6bd3e80daa7a6ce7322f0ef963a8e7 --- /dev/null +++ b/docs/html/intl/ko/training/monitoring-device-state/manifest-receivers.jd @@ -0,0 +1,50 @@ +page.title=온디맨드로 브로드캐스트 수신기 조작 +parent.title=배터리 수명 최적화 +parent.link=index.html + +trainingnavtop=true + +previous.title=연결 상태 확인 및 모니터링 +previous.link=connectivity-monitoring.html + +@jd:body + + + +

    기기 상태 변경을 모니터링하는 가장 간단한 방법은 모니터링하는 각 상태에 대해 {@link android.content.BroadcastReceiver}를 만들어 각각을 애플리케이션 매니페스트에 등록하는 것입니다. 그러면 각 리시버 내에서 현재 기기 상태를 기반으로 반복 알람의 일정을 간단히 변경할 수 있습니다.

    + +

    이 방법의 부작용은 리시버 중 하나라도 실행되면 매번 앱이 기기의 절전 모드를 해제시킨다는 것입니다.

    + +

    더 나은 방법은 런타임 때 브로드캐스트 리시버를 사용 중지 또는 사용하도록 설정하는 것입니다. 이렇게 하면 매니페스트에 선언한 리시버를 필요할 때만 시스템 이벤트에 의해 실행되는 수동적인 알람으로 사용할 수 있습니다.

    + + +

    효율성 향상을 위한 상태 변화 수신기의 전환 및 단계적 연결

    + +

    {@link android.content.pm.PackageManager}를 사용하여 아래에서 표시된 대로 모든 사용 또는 사용 중지하기 원하는 브로드캐스트 리시버를 포함하여 매니페스트 내에 정의된 모든 요소의 사용 가능 상태를 전환할 수 있습니다.

    + +
    ComponentName receiver = new ComponentName(context, myReceiver.class);
    +
    +PackageManager pm = context.getPackageManager();
    +
    +pm.setComponentEnabledSetting(receiver,
    +        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
    +        PackageManager.DONT_KILL_APP)
    + +

    이 방법을 사용하면 연결이 없음을 확인한 경우 연결 변경 리시버를 제외한 모든 리시버를 사용 중지할 수 있습니다. 반대로 한 번 연결되면 연결 변경사항의 수신을 중지할 수 있으며, 업데이트를 수행하고 반복 업데이트 알람의 일정을 변경하기 전에 온라인 상태인지만 간단히 확인할 수 있습니다.

    + +

    높은 대역폭을 요구하는 다운로드를 중지시키는 데 동일한 기술을 사용할 수 있습니다. 연결 변경을 수신하는 브로드캐스트 리시버를 사용하도록 설정하고 반드시 Wi-Fi에 연결한 후에 다운로드를 시작하도록 합니다.

    diff --git a/docs/html/intl/ko/training/multiscreen/adaptui.jd b/docs/html/intl/ko/training/multiscreen/adaptui.jd new file mode 100644 index 0000000000000000000000000000000000000000..cb7b66c90238b040394f383e39cd0c295928be65 --- /dev/null +++ b/docs/html/intl/ko/training/multiscreen/adaptui.jd @@ -0,0 +1,212 @@ +page.title=조정형 UI 플로우 구현 +parent.title=다양한 화면 지원 +parent.link=index.html + +trainingnavtop=true +previous.title=다양한 화면 밀도 지원 +previous.link=screendensities.html + +@jd:body + + + + + +

    현재 애플리케이션이 표시하는 레이아웃에 따라 UI 플로가 달라질 수 있습니다. 예를 들어 애플리케이션이 이중 창 모드로 되어 있는 경우에는 왼쪽 창에 있는 항목을 클릭하면 오른쪽 창에 콘텐츠가 표시되고, 단일 창 모드로 되어 있는 경우에는 콘텐츠가 해당 창에 표시됩니다(다른 액티비티에서).

    + + +

    현재 레이아웃 확인

    + +

    각 레이아웃을 구현하는 방식이 약간씩 다르므로 가장 먼저 해야 할 일은 현재 사용자에게 어떤 레이아웃이 표시되는지 확인하는 것입니다. 예를 들어, 사용자가 '단일 창' 모드에 있는지 혹은 '이중 창' 모드에 있는지 파악할 수 있습니다. 이는 특정 뷰가 존재하고 그 뷰가 표시되는지 조회하면 됩니다.

    + +
    +public class NewsReaderActivity extends FragmentActivity {
    +    boolean mIsDualPane;
    +
    +    @Override
    +    public void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        setContentView(R.layout.main_layout);
    +
    +        View articleView = findViewById(R.id.article);
    +        mIsDualPane = articleView != null && 
    +                        articleView.getVisibility() == View.VISIBLE;
    +    }
    +}
    +
    + +

    이 코드는 'article' 창을 사용할 수 있는지 여부를 조회하며 이러한 방식이 특정 레이아웃에 대한 조회를 하드코딩하는 것보다 훨씬 유연한 방식입니다.

    + +

    다른 구성요소의 존재 여부에 맞게 앱을 조정하는 또 다른 방법은 구성요소에 대한 작업을 수행하기 전에 해당 구성요소를 사용할 수 있는지 확인하는 것입니다. 예를 들어 뉴스 리더 샘플 앱의 경우, 메뉴를 여는 버튼이 있긴 하지만 이 버튼은 Android 3.0 이전 버전에서 실행되는 경우에만 존재합니다(API 수준 11 이상에서 {@link android.app.ActionBar} 가 그 기능을 대신하기 때문). 따라서 이 버튼에 대한 이벤트 리스너를 추가하기 위해 다음과 같이 할 수 있습니다.

    + +
    +Button catButton = (Button) findViewById(R.id.categorybutton);
    +OnClickListener listener = /* create your listener here */;
    +if (catButton != null) {
    +    catButton.setOnClickListener(listener);
    +}
    +
    + + +

    현재 레이아웃에 대한 대응

    + +

    현재 레이아웃에 따라 일부 액션의 결과가 달라질 수 있습니다. 예를 들어 뉴스 리더 샘플의 헤드라인 목록에서 헤드라인을 클릭하면 UI가 이중 창 모드인 경우에는 기사가 오른쪽 창에서 열리지만, UI가 단일 창 모드인 경우에는 별도의 액티비티가 실행됩니다.

    + +
    +@Override
    +public void onHeadlineSelected(int index) {
    +    mArtIndex = index;
    +    if (mIsDualPane) {
    +        /* display article on the right pane */
    +        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    +    } else {
    +        /* start a separate activity */
    +        Intent intent = new Intent(this, ArticleActivity.class);
    +        intent.putExtra("catIndex", mCatIndex);
    +        intent.putExtra("artIndex", index);
    +        startActivity(intent);
    +    }
    +}
    +
    + +

    마찬가지로, 앱이 이중 창 모드인 경우에는 탐색용 탭이 포함된 작업 표시줄이 설정되지만, 앱이 단일 창 모드인 경우에는 스피너 위젯이 포함된 탐색 메뉴가 설정됩니다. 따라서 어떤 경우가 적합한지도 코드에서 확인해야 합니다.

    + +
    +final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" };
    +
    +public void onCreate(Bundle savedInstanceState) {
    +    ....
    +    if (mIsDualPane) {
    +        /* use tabs for navigation */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
    +        int i;
    +        for (i = 0; i < CATEGORIES.length; i++) {
    +            actionBar.addTab(actionBar.newTab().setText(
    +                CATEGORIES[i]).setTabListener(handler));
    +        }
    +        actionBar.setSelectedNavigationItem(selTab);
    +    }
    +    else {
    +        /* use list navigation (spinner) */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
    +        SpinnerAdapter adap = new ArrayAdapter(this, 
    +                R.layout.headline_item, CATEGORIES);
    +        actionBar.setListNavigationCallbacks(adap, handler);
    +    }
    +}
    +
    + + +

    다른 액티비티에 프래그먼트 재사용

    + +

    다양한 화면의 디자인에 반복되는 패턴에는 일부 화면 구성에서는 창으로 구현되고 다른 화면 구성에서는 별도의 액티비티로 구현되는 인터페이스가 일부 있습니다. 예를 들어 뉴스 리더 샘플에서 뉴스 기사 텍스트가 큰 화면에서는 오른쪽 창에 표시되지만 작은 화면에서는 별도의 액티비티입니다.

    + +

    이러한 경우 일반적으로 동일한 {@link android.app.Fragment} 하위 클래스를 여러 액티비티에 재사용하여 코드 중복을 피할 수 있습니다. 예를 들어 ArticleFragment는 이중 창 레이아웃에서 사용되며

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    작은 화면의 액티비티 레이아웃에 레이아웃 없이 재사용됩니다(ArticleActivity).

    + +
    +ArticleFragment frag = new ArticleFragment();
    +getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
    +
    + +

    당연히 이는 XML 레이아웃에서 프래그먼트(fragment)를 명시하는 것과 같은 효과가 있지만 이 경우에는 아티클 프래그먼트가 이 액티비티의 유일한 구성요소이기 때문에 XML 레이아웃은 불필요한 작업이 됩니다.

    + +

    프래그먼트를 디자인할 때 염두에 두어야 할 매우 중요한 점 한 가지는 특정 액티비티에 대한 강한 커플링을 만들지 말아야 한다는 점입니다. 이렇게 하려면 일반적으로 프래그먼트가 호스트 액티비티와 상호작용해야 하는 모든 방식을 추상화하는 인터페이스를 정의하면 됩니다. 그러면 호스트 액티비티가 해당 인터페이스를 구현합니다.

    + +

    예를 들어 뉴스 리더 앱의 HeadlinesFragment가 정확하게 그 일을 해 줍니다.

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    OnHeadlineSelectedListener mHeadlineSelectedListener = null;
    +
    +    /* Must be implemented by host activity */
    +    public interface OnHeadlineSelectedListener {
    +        public void onHeadlineSelected(int index);
    +    }
    +    ...
    +
    +    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
    +        mHeadlineSelectedListener = listener;
    +    }
    +}
    +
    + +

    그런 다음 사용자가 헤드라인을 선택하면 프래그먼트가 하드코딩된 특정 액티비티를 알리지 않고 호스트 액티비티가 지정한 리스너를 알립니다.

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    @Override
    +    public void onItemClick(AdapterView<?> parent, 
    +                            View view, int position, long id) {
    +        if (null != mHeadlineSelectedListener) {
    +            mHeadlineSelectedListener.onHeadlineSelected(position);
    +        }
    +    }
    +    ...
    +}
    +
    + +

    이 기술은 태블릿 및 휴대전화 지원 가이드에서 자세히 설명되어 있습니다.

    + + +

    화면 구성 변경 처리

    + +

    인터페이스 중 일부를 구현하는데 별도의 액티비티를 사용 중인 경우 인터페이스의 일관성을 유지하기 위해 특정 구성의 변경(예: 화면 전환)에 대응해야 합니다.

    + +

    예를 들어 Android 3.0 이상을 실행하는 일반적인 7인치 태블릿에서 뉴스 리더 샘플은 세로 모드에서 실행될 때에는 뉴스 기사를 표시하는 데 별도의 액티비티를 사용하지만 가로모드에서는 이중 창(two-pane) 레이아웃을 사용합니다.

    + +

    즉 사용자가 세로 모드에 있고 기사를 보기 위한 액티비티가 화면에 있는 경우, 방향이 가로로 바뀌었음을 감지하고, 액티비티를 종료한 다음 주요 액티비티로 돌아감으로써 콘텐츠가 이중 창 레이아웃에서 표시되도록 적절하게 대응해야 합니다.

    + +
    +public class ArticleActivity extends FragmentActivity {
    +    int mCatIndex, mArtIndex;
    +
    +    @Override
    +    protected void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
    +        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
    +
    +        // If should be in two-pane mode, finish to return to main activity
    +        if (getResources().getBoolean(R.bool.has_two_panes)) {
    +            finish();
    +            return;
    +        }
    +        ...
    +}
    +
    + + diff --git a/docs/html/intl/ko/training/multiscreen/index.jd b/docs/html/intl/ko/training/multiscreen/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..d9e09b08ae48d076d42fe6d49c455fa9e87018b7 --- /dev/null +++ b/docs/html/intl/ko/training/multiscreen/index.jd @@ -0,0 +1,64 @@ +page.title=다양한 화면 지원 + +trainingnavtop=true +startpage=true +next.title=다양한 화면 크기 지원 +next.link=screensizes.html + +@jd:body + +
    +
    + +

    요구사항과 선행조건

    + + + +

    참고자료

    + + + +

    다운로드

    + +
    +샘플 앱 다운로드 +

    NewsReader.zip

    +
    + +
    +
    + +

    Android는 소형 휴대전화에서부터 대형 TV에 이르기까지 다양한 화면 크기의 수많은 기기 유형을 지원합니다. 따라서 애플리케이션이 모든 화면 크기와 호환되어 최대한 많은 사용자가 사용할 수 있도록 디자인하는 것이 중요합니다.

    + +

    하지만 다양한 기기 유형과 호환되는 것만으로는 충분하지 않습니다. 각 화면 크기에 따라 사용자 상호작용에 유리한 점과 불리한 점이 다릅니다. 따라서 사용자에게 만족을 주고 깊은 인상을 심어주려면 애플리케이션이 단지 여러 화면을 지원하는 데 그치지 않고 화면 구성별로 사용자 환경을 최적화해야 합니다.

    + +

    이번 강의에서는 여러 화면 구성에 최적화된 사용자 인터페이스를 구현하는 방법을 설명합니다.

    + +

    각 강의에서 사용되는 코드는 여러 화면에 대한 최적화의 모범 사례를 보여주는 샘플 애플리케이션에서 가져온 것입니다. 샘플(오른쪽)을 다운로드하여 본인의 애플리케이션에 코드로 재사용할 수 있습니다.

    + +

    참고: 이 강의 및 강의와 관련된 샘플은 호환성 라이브러리를 사용하며 이는 Android 3.0 이하 버전에서 {@link android.app.Fragment} API를 사용하기 위해서입니다. 이 강의에서 API를 모두 사용하려면 라이브러리를 다운로드하여 애플리케이션에 추가해야 합니다.

    + + +

    강의

    + +
    +
    다양한 화면 크기 지원
    +
    이 강의에서는 여러 다양한 화면 크기에 조정되는 레이아웃을 디자인하는 방법(유연한 보기 크기, {@link android.widget.RelativeLayout}, 화면 크기 및 방향 한정자, 별칭 필터 및 나인-패치 비트맵 사용하기)을 안내합니다.
    + +
    다양한 화면 밀도 지원
    +
    이 강의에서는 다양한 픽셀 밀도를 가진 화면을 지원하는 방법(밀도 독립형 픽셀(density-independent pixel) 사용하기 및 밀도별로 적합한 비트맵 제공하기)을 설명합니다.
    + +
    조정형 UI 플로우 구현
    +
    이 강의에서는 여러 화면 크기/밀도 조합에 조정되도록 UI 플로우를 구현하는 방법(활성 레이아웃의 런타임 감지, 현재 레이아웃에 따른 대응, 화면 구성 변경 처리)을 설명합니다.
    +
    diff --git a/docs/html/intl/ko/training/multiscreen/screendensities.jd b/docs/html/intl/ko/training/multiscreen/screendensities.jd new file mode 100644 index 0000000000000000000000000000000000000000..5d6e2f3c59b78326ee4a63403543c4e1262394d5 --- /dev/null +++ b/docs/html/intl/ko/training/multiscreen/screendensities.jd @@ -0,0 +1,100 @@ +page.title=다양한 화면 밀도 지원 +parent.title=다양한 화면 지원 +parent.link=index.html + +trainingnavtop=true +previous.title=다양한 화면 크기 지원 +previous.link=screensizes.html +next.title=조정형 UI 플로우 구현 +next.link=adaptui.html + +@jd:body + + + +
    +
    + +

    강의 목표

    +
      +
    1. DIP(Density Independent Pixel) 사용
    2. +
    3. 대체 비트맵 제공
    4. +
    + +

    참고자료

    + + + +

    다운로드

    + +
    +샘플 앱 다운로드 +

    NewsReader.zip

    +
    + + +
    +
    + +

    이 강의에서는 다양한 리소스를 제공하고 해상도 독립형(resolution-independent) 측정 단위를 사용함으로써 다양한 화면 밀도를 지원하는 방법을 설명합니다.

    + +

    DIP(Density Independent Pixel) 사용

    + +

    레이아웃을 디자인할 때 범하기 쉬운 실수 중 하나는 절대 픽셀(absolute pixel)을 사용하여 거리나 크기를 정의하는 것입니다. 각 화면은 픽셀 밀도가 서로 다른데 레이아웃 크기를 픽셀로 정의하면 동일한 픽셀 수치가 다른 기기에서 다른 물리적 크기와 대응할 수 있어 문제가 됩니다. 따라서 크기를 지정할 때에는 항상 dp 또는 sp 단위를 사용하시기 바랍니다. dp는 160dpi에서 픽셀의 물리적 크기에 대응하는 밀도 독립형 픽셀(Density Independent Pixel)입니다. sp는 동일한 기본 단위이지만 사용자의 기본 텍스트 크기에 따라 확대/축소될 수 있으므로(배율 독립형 픽셀(Scale Independent Pixel)임) 텍스트 크기를 정의할 때 이 측정 단위를 사용해야 합니다(레이아웃 크기에 사용해서는 안됨).

    + +

    예를 들어 두 개의 보기 사이에 여백을 지정할 때 px가 아닌 dp를 사용합니다.

    + +
    +<Button android:layout_width="wrap_content" 
    +    android:layout_height="wrap_content" 
    +    android:text="@string/clickme"
    +    android:layout_marginTop="20dp" />
    +
    + +

    텍스트 크기를 지정할 때에는 항상 sp를 사용합니다.

    + +
    +<TextView android:layout_width="match_parent" 
    +    android:layout_height="wrap_content" 
    +    android:textSize="20sp" />
    +
    + + +

    대체 비트맵 제공

    + +

    Android는 화면 밀도가 다양한 기기에서 실행되므로 각각의 일반화된 밀도 종류(저, 중, 고 및 초고 밀도)에 맞춤화된 비트맵 리소스를 제공해야 합니다. 이렇게 하면 모든 화면 밀도에서 좋은 그래픽 품질 및 성능을 얻는데 도움이 됩니다.

    + +

    이러한 이미지를 생성하려면 벡터 형식의 원본 리소스부터 시작해야 하며 다음 크기 배율을 사용하여 각 밀도에 사용할 이미지를 생성해야 합니다.

    + +

      +
    • xhdpi: 2.0 +
    • hdpi: 1.5 +
    • mdpi: 1.0 (기선) +
    • ldpi: 0.75 +

    + +

    xhdpi 기기에 대해 200x200 이미지를 생성하는 경우 hdpi 기기에 대해 동일한 리소스를 150x150으로 생성해야 하며 mdpi 기기에 대해서는 100x100, ldpi 기기에 대해서는 75x75으로 동일한 리소스를 생성해야 합니다.

    + +

    그런 다음 생성된 이미지 파일을 res/ 아래의 적절한 하위 디렉토리에 배치하면 시스템에서 애플리케이션이 실행되는 기기의 화면 밀도에 따라 정확한 이미지 파일을 자동으로 선택합니다.

    + +
    +MyProject/
    +  res/
    +    drawable-xhdpi/
    +        awesomeimage.png
    +    drawable-hdpi/
    +        awesomeimage.png
    +    drawable-mdpi/
    +        awesomeimage.png
    +    drawable-ldpi/
    +        awesomeimage.png
    +
    + +

    그런 다음 언제든지 @drawable/awesomeimage를 참조하면 시스템이 화면의 dpi에 따라 적합한 비트맵을 선택합니다.

    + +

    애플리케이션에 사용할 아이콘 저작물 제작에 대한 자세한 도움말 및 가이드라인은 아이콘 디자인 가이드라인을 참조하세요.

    + diff --git a/docs/html/intl/ko/training/multiscreen/screensizes.jd b/docs/html/intl/ko/training/multiscreen/screensizes.jd new file mode 100644 index 0000000000000000000000000000000000000000..f2e77a6e2b04b74bb72ad0d747c4d1d8feb03be4 --- /dev/null +++ b/docs/html/intl/ko/training/multiscreen/screensizes.jd @@ -0,0 +1,279 @@ +page.title=다양한 화면 크기 지원 +parent.title=다양한 화면 지원 +parent.link=index.html + +trainingnavtop=true +next.title=다양한 화면 밀도 지원 +next.link=screendensities.html + +@jd:body + + + + + +

    이 강의에서는 다양한 화면 크기를 지원하는 방법을 설명합니다.

    +
      +
    • 화면에 맞게 레이아웃 크기 조정
    • +
    • 화면 구성에 따라 적합한 UI 레이아웃 제공
    • +
    • 올바른 화면에 올바른 레이아웃 적용
    • +
    • 정확하게 확대되는 비트맵 제공
    • +
    + + +

    'wrap_content' 및 'match_parent' 사용

    + +

    레이아웃이 다양한 화면 크기에 따라 유연하게 조정되도록 하려면 일부 뷰 구성요소의 너비와 높이에 "wrap_content""match_parent"를 사용해야 합니다. "wrap_content"를 사용하면 뷰의 너비와 높이가 해당 뷰 내에 콘텐츠가 들어가는데 필요한 최소 크기로 설정되는 반면, "match_parent"(API 수준 8 이전에는 "fill_parent"라고도 함)를 사용하면 구성요소가 확장되어 부모뷰의 크기와 일치하게 됩니다.

    + +

    하드코딩된 크기 대신 "wrap_content" 크기 값을 사용하면 뷰가 해당 뷰에 필요한 여백만을 사용하며 "match_parent" 크기 값을 사용하면 뷰가 확대되어 사용 가능한 여백을 채웁니다. 예를 들면 다음과 같습니다.

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    샘플에서 구성요소 크기에 특정 크기가 아닌 "wrap_content""match_parent"가 사용된 것을 눈여겨 보시기 바랍니다. 이렇게 하면 레이아웃이 다양한 화면 크기 및 방향에 맞게 조정됩니다.

    + +

    예를 들어 세로 및 가로 모드에서 레이아웃은 다음과 같이 표시됩니다. 구성요소의 크기가 너비와 높이에 맞게 자동으로 조정됩니다.

    + + +

    그림 1. 세로 모드(왼쪽) 및 가로 모드(오른쪽)에서의 뉴스 리더 샘플 앱

    + + +

    RelativeLayout 사용

    + +

    비교적 복잡한 레이아웃을 만들려면 {@link android.widget.LinearLayout}의 중첩 인스턴스와 "wrap_content""match_parent" 크기의 조합을 사용합니다. 하지만 {@link android.widget.LinearLayout} 을 사용하면 자식뷰의 여백 관계를 정확하게 제어할 수 없으며 {@link android.widget.LinearLayout} 단순히 나란하게 표시됩니다. 자식뷰를 일직선이 아닌 다양한 방향으로 표시해야 하는 경우 구성요소 사이의 여백 관계를 중심으로 레이아웃을 지정할 수 있는 {@link android.widget.RelativeLayout}을 사용하는 것이 더 좋은 방법일 수 있습니다. 예를 들어 화면 왼쪽에 하나의 자식뷰를, 오른쪽에 다른 자식뷰를 정렬할 수 있습니다.

    + +

    예를 들면 다음과 같습니다.

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:layout_width="match_parent"
    +    android:layout_height="match_parent">
    +    <TextView
    +        android:id="@+id/label"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:text="Type here:"/>
    +    <EditText
    +        android:id="@+id/entry"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/label"/>
    +    <Button
    +        android:id="@+id/ok"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/entry"
    +        android:layout_alignParentRight="true"
    +        android:layout_marginLeft="10dp"
    +        android:text="OK" />
    +    <Button
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_toLeftOf="@id/ok"
    +        android:layout_alignTop="@id/ok"
    +        android:text="Cancel" />
    +</RelativeLayout>
    +
    + +

    그림 2는 이 레이아웃이 QVGA 화면에 어떻게 표시되는지 보여줍니다.

    + + +

    그림 2. QVGA 화면(작은 화면)의 스크린샷

    + +

    그림 3은 이 레이아웃이 큰 화면에서 어떻게 표시되는지 보여줍니다.

    + + +

    그림 3. WSVGA 화면(큰 화면)의 스크린샷

    + +

    구성요소의 크기가 변하더라도 여백 관계가 {@link android.widget.RelativeLayout.LayoutParams}.

    + + +

    크기 한정자 사용

    + +

    이전 섹션에서 다룬 유연한 레이아웃이나 상대적 레이아웃으로는 한계가 있습니다. 이러한 레이아웃이 구성요소 내부 및 주위의 여백을 확장하여 다양한 화면에 맞게 조정되긴 하지만 화면 크기별로 최적의 사용자 환경을 제공하지는 못할 수 있습니다. 따라서 애플리케이션은 유연한 레이아웃을 구현할 뿐 아니라 다양한 화면 구성을 타겟팅할 수 있도록 다양한 대체 레이아웃을 제공해야 합니다. 그 방법은 런타임이 현재 기기의 구성에 따라 적합한 리소스(예: 화면 크기별로 다른 레이아웃 디자인)를 자동으로 선택하도록 해 주는 구성 한정자를 사용하는 것입니다.

    + +

    예를 들어 많은 애플리케이션이 큰 화면에 '이중 창(two pane)' 패턴을 구현합니다(한 쪽 창에는 아이템의 목록을 표시하고 다른 창에는 콘텐츠를 표시). 태블릿 및 TV는 두 개의 창 모두가 화면에 동시에 들어갈 정도로 크지만 휴대전화 화면은 두 창을 따로 표시해야 합니다. 따라서 이러한 레이아웃을 구현하려면 다음 파일이 있어야 합니다.

    + +
      +
    • res/layout/main.xml, 단일 창(기본값) 레이아웃: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-large/main.xml, 이중 창 레이아웃: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    두 번째 레이아웃의 디렉토리 이름에서 large 한정자를 눈여겨 보시기 바랍니다. 이 레이아웃은 대형(예: 7인치 태블릿 이상)으로 분류된 화면을 가진 기기에서 선택됩니다. 한정자가 없는 다른 레이아웃은 소형 기기에서 선택됩니다.

    + + +

    최소 너비 한정자 사용

    + +

    Android 3.2 이전 기기에서 개발자가 어려움을 느꼈던 문제 중의 하나는 Dell Streak, 최초의 Galaxy 탭 및 7인치 태블릿에 두루 사용되는 '큰' 화면 크기 빈이었습니다. 하지만 많은 애플리케이션은 화면이 '큰' 기기라 하더라도 이 카테고리(예: 5인치 및 7인치 기기)에 속하는 다양한 기기에 다양한 레이아웃을 표시하고 싶어 합니다. 이것이 Android에서 Android 3.2에 '최소 너비' 한정자를 도입한 이유입니다.

    + +

    최소 너비 한정자를 사용하면 dp 단위의 특정 최소 너비를 가진 화면을 타겟팅할 수 있습니다. 예를 들어 일반적인 7인치 태블릿에는 600dp라는 최소 너비가 있으므로 이러한 화면에서 두 개의 창에 UI를 사용(작은 화면에서는 단일 목록 사용) 하고 싶은 경우 단일 및 이중 창 레이아웃에 이전 섹션과 동일한 레이아웃을 사용하면 되지만, 이중 창 레이아웃은 최소 너비가 600dp인 화면에 사용한다는 것을 나타내기 위해서 large 크기 한정자 대신 sw600dp를 사용해야 합니다.

    + +
      +
    • res/layout/main.xml, 단일 창(기본값) 레이아웃: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-sw600dp/main.xml, 이중 창 레이아웃: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    이는 최소 너비가 600dp 이상인 기기는 layout-sw600dp/main.xml(이중 창) 레이아웃을 선택하는 반면 소형 화면은 layout/main.xml (단일 창) 레이아웃을 선택한다는 것을 의미합니다.

    + +

    하지만 Android 3.2 이전 기기는 sw600dp를 크기 한정자로 인식하지 않기 때문에 최소 너비 한정자가 제대로 작동하지 않으며 따라서 large 한정자도 계속 사용해야 합니다. 따라서 res/layout-large/main.xml라는 이름의 파일이 있어야 하며 이 파일은 res/layout-sw600dp/main.xml과 동일한 파일입니다. 다음 섹션에서는 이런 식으로 레이아웃 파일이 중복되지 않게 하는 기술을 살펴보겠습니다.

    + + +

    레이아웃 별칭 사용

    + +

    최소 너비 한정자는 Android 3.2 이상 버전에서만 사용할 수 있습니다. 따라서 이전 버전과 호환되도록 하려면 추상화 크기 빈(소형, 보통, 대형 및 초대형)을 계속 사용해야 합니다. 예를 들어 휴대전화에서는 단일 창 UI가 표시되고 7인치 태블릿, TV 및 기타 대형 기기에서는 다중 창 UI가 표시되도록 UI를 디자인하려면 다음 파일을 제공해야 합니다.

    + +

      +
    • res/layout/main.xml: 단일 창 레이아웃
    • +
    • res/layout-large: 다중 창 레이아웃
    • +
    • res/layout-sw600dp: 다중 창 레이아웃
    • +

    + +

    마지막 두 개의 파일은 하나는 Android 3.2 기기와 일치하고 다른 하나는 이전 버전의 Android가 탑재된 태블릿 및 TV를 위한 것으로 서로 동일한 파일입니다.

    + +

    이 경우 별칭 파일을 사용하면 태블릿 및 TV용으로 동일한 파일이 중복되지 않도록 하고 이를 관리해야 하는 번거로움을 없앨 수 있습니다. 예를 들어 다음 레이아웃을 지정할 수 있습니다.

    + +
      +
    • res/layout/main.xml, 단일 창 레이아웃
    • +
    • res/layout/main_twopanes.xml, 이중 창 레이아웃
    • +
    + +

    또한 다음 두 개의 파일을 추가합니다.

    + +

      +
    • res/values-large/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      +
    • + +
    • res/values-sw600dp/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      + +
    • +

    + +

    뒤에 있는 두 개의 파일은 콘텐츠는 동일하지만 실제로 레이아웃을 지정하지는 않으며 단지 {@code main}{@code main_twopanes}에 대한 별칭이 되도록 설정합니다. 이 파일에는 largesw600dp 선택기가 있으므로 Android 버전에 관계없이 태블릿 및 TV에 적용됩니다(3.2 버전 이전의 태블릿 및 TV는 +{@code large},3.2 이후 버전은 sw600dp와 일치).

    + + +

    방향 한정자 사용

    + +

    일부 레이아웃은 가로 및 세로 방향 모두에서 잘 작동하지만 대부분의 레이아웃은 조정을 통해 많은 이점을 누릴 수 있습니다. 다음은 뉴스 리더 샘플 앱에서 화면 크기와 방향별로 레이아웃이 어떻게 작동하는지 보여줍니다.

    + +

      +
    • 소형 화면, 세로: 단일 창, 로고 표시
    • +
    • 소형 화면, 가로: 단일 창, 로고 표시
    • +
    • 7인치 태블릿, 세로: 단일 창, 작업 표시줄 표시
    • +
    • 7인치 태블릿, 가로: 이중 창, 와이드, 작업 표시줄 표시
    • +
    • 10인치 태블릿, 세로: 이중 창, 내로우, 작업 표시줄 표시
    • +
    • 10인치 태블릿, 가로: 이중 창, 와이드, 작업 표시줄 표시
    • +
    • TV, 가로: 이중 창, 와이드, 작업 표시줄 표시
    • +

    + +

    따라서 이러한 각 레이아웃은 res/layout/ 디렉토리의 XML 파일에서 지정됩니다. 그러면 앱은 각 레이아웃을 다양한 화면 구성에 지정하기 위해 레이아웃 별칭을 사용해 레이아웃을 각 구성과 일치시킵니다.

    + +

    res/layout/onepane.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} + +

    res/layout/onepane_with_bar.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    res/layout/twopanes.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    res/layout/twopanes_narrow.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all} + +

    가능한 레이아웃을 모두 지정했으므로 구성 한정자를 사용하여 올바른 레이아웃을 각 구성에 매핑하기만 하면 되며 이는 레이아웃 별칭 기술을 사용하면 됩니다.

    + +

    res/values/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all} + +

    res/values-sw600dp-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml +all} + +

    res/values-sw600dp-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml +all} + +

    res/values-large-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all} + +

    res/values-large-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all} + + + +

    나인-패치 비트맵 사용

    + +

    일반적으로 다양한 화면 크기를 지원하려면 이미지 리소스도 다양한 크기에 맞게 조정될 수 있어야 합니다. 예를 들어 버튼 배경은 버튼 배경이 적용되는 모든 버튼 모양과 맞아야 합니다.

    + +

    구성요소에 크기가 바뀔 수 있는 단순한 이미지를 사용하는 경우 런타임이 이미지를 균등하게 확대하거나 축소하기 때문에 기대에 미치지 못하는 결과가 나옵니다. 이에 대한 해결 방법은 확대될 수 있는 영역과 확대될 수 없는 영역을 나타내는 특별한 형식의 PNG 파일인 나인-패치 비트맵을 사용하는 것입니다.

    + +

    따라서 다양한 크기를 가진 구성요소에 사용할 비트맵을 디자인할 때에는 항상 나인-패치를 사용하시기 바랍니다. 비트맵을 나인-패치로 변환하려면 일반적인 이미지부터 시작합니다(그림 4, 명확하게 보이도록 4배 줌으로 표시).

    + + +

    그림 4. button.png

    + +

    그 다음 이 이미지에 SDK의 draw9patch 유틸리티(tools/ 디렉토리에 있음)를 실행합니다. 이 때 왼쪽 및 상단 테두리를 따라 픽셀을 그려 확대되어야 할 영역을 표시할 수 있습니다. 또한 오른쪽 및 하단 테두리를 따라 픽셀을 그려 콘텐츠가 들어가야 할 영역을 표시할 수 있으며 그 결과는 그림 5와 같습니다.

    + + +

    그림 5. button.9.png

    + +

    테두리를 따라 있는 검은색 픽셀을 눈여겨 보시기 바랍니다. 상단 및 왼쪽 테두리의 픽셀은 이미지가 확대될 수 있는 영역을 나타내며 오른쪽 및 하단 테두리는 콘텐츠가 위치해야 하는 영역을 나타냅니다.

    + +

    또한 .9.png 확장자를 확인하시기 바랍니다. 프레임워크는 이 확장자를 통해 이미지가 일반적인 PNG 이미지가 아닌 나인-패치 이미지임을 감지할 수 있으므로 이 확장자를 사용해야 합니다.

    + +

    android:background="@drawable/button"을 설정하여 이 배경을 구성요소에 적용하면 그림 6의 다양한 크기로 표시된 것처럼 프레임워크가 버튼의 크기를 수용할 수 있도록 이미지를 올바르게 확대합니다.

    + + +

    그림 6. 다양한 크기에 button.9.png 나인-패치를 사용하는 버튼

    + diff --git a/docs/html/intl/ru/training/monitoring-device-state/battery-monitoring.jd b/docs/html/intl/ru/training/monitoring-device-state/battery-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..26daf04bd1ceacb36bb963004cd3e7830d46de0a --- /dev/null +++ b/docs/html/intl/ru/training/monitoring-device-state/battery-monitoring.jd @@ -0,0 +1,120 @@ +page.title=Monitoring the Battery Level and Charging State +parent.title=Optimizing Battery Life +parent.link=index.html + +trainingnavtop=true +next.title=Determining and Monitoring the Docking State and Type +next.link=docking-monitoring.html + +@jd:body + + + +

    Если вы хотите изменить частоту фоновых обновлений, чтобы продлить время работы устройства от батареи, сначала рекомендуется проверить текущий уровень заряда и состояние зарядки.

    + +

    Именно от этих двух факторов зависит, как обновления повлияют на время работы устройства от батареи. Когда устройство подключено к сети переменного тока, приложение можно обновлять максимально часто, поскольку процесс обновления не будет сказываться на уровне заряда батареи. Если устройство не подключено к сети, следует воздержаться от обновлений, чтобы продлить время его работы от батареи.

    + +

    Если заряд батареи практически исчерпан, можно снизить частоту обновлений (вплоть до их полного прекращения).

    + + +

    Определение текущего состояния зарядки

    + +

    Начните с определения текущего состояния зарядки. {@link android.os.BatteryManager} передает все сведения о батарее и зарядке в закрепленном намерении {@link android.content.Intent}, которое содержит также информацию о состоянии зарядки.

    + +

    Поскольку это намерение является закрепленным, регистрировать {@link android.content.BroadcastReceiver} не нужно. Чтобы получить текущее состояние батареи в виде намерения, нужно вызвать {@code registerReceiver}, передав {@code null} в качестве приемника, как показано в коде ниже. Можно также передать фактический объект {@link android.content.BroadcastReceiver}, но это необязательно, поскольку обработка обновлений будет выполняться позднее.

    + +
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    +Intent batteryStatus = context.registerReceiver(null, ifilter);
    + +

    Можно извлечь данные как о текущем состоянии, так и об источнике зарядки (USB или сеть переменного тока), если устройство заряжается:

    + +

    // Are we charging / charged?
    +int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
    +boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
    +                     status == BatteryManager.BATTERY_STATUS_FULL;
    +
    +// How are we charging?
    +int chargePlug = battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    +boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
    +boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
    + +

    Как правило, если устройство подключено к сети переменного тока, фоновые обновления можно выполнять с максимальной частотой. Если устройство заряжается через USB, частоту можно несколько сократить, а если устройство не подключено к сети – сократить еще больше.

    + + +

    Отслеживание изменений состояния зарядки

    + +

    Состояние зарядки изменяется всякий раз, когда пользователь подключает устройство к источнику питания. Поскольку это случается довольно часто, важно отслеживать изменения этого состояния и соответствующим образом корректировать частоту обновления приложения.

    + +

    {@link android.os.BatteryManager} передает действие каждый раз, когда устройство подключается к источнику питания или отключается от него. Важно получать эти события, даже если приложение не работает. Они помогут, в частности, определить, как часто будет запускаться приложение для выполнения фоновых обновлений. Чтобы отслеживать их, зарегистрируйте {@link android.content.BroadcastReceiver} в манифесте, задав {@link android.content.Intent#ACTION_POWER_CONNECTED} и {@link android.content.Intent#ACTION_POWER_DISCONNECTED} в фильтре намерений.

    + +
    <receiver android:name=".PowerConnectionReceiver">
    +  <intent-filter>
    +    <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
    +    <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
    +  </intent-filter>
    +</receiver>
    + +

    Соответствующая реализация {@link android.content.BroadcastReceiver} позволяет извлечь данные о текущем состоянии и способе зарядки, как описано в предыдущем шаге.

    + +
    public class PowerConnectionReceiver extends BroadcastReceiver {
    +    @Override
    +    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;
    +    }
    +}
    + + +

    Определение текущего уровня заряда батареи

    + +

    В некоторых случаях целесообразно определять текущий уровень заряда батареи. Если он ниже определенного значения, частоту фоновых обновлений следует уменьшить.

    + +

    Узнать, каков в настоящий момент заряд батареи, можно путем извлечения данных о текущем и максимальном уровне заряда из намерения состояния батареи, как показано в этом коде:

    + +
    int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    +int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
    +
    +float batteryPct = level / (float)scale;
    + + +

    Отслеживание существенных изменений уровня заряда батареи

    + +

    Отслеживать состояние батареи непрерывно не следует,

    + +

    поскольку при этом нагрузка на батарею будет значительно выше, чем при обычной работе приложения. Рекомендуется отслеживать только существенные изменения уровня заряда, в частности, переход устройства в состояние низкого заряда и обратно.

    + +

    Фрагмент манифеста, приведенный ниже, относится к фильтру намерений в приемнике широковещательных намерений. Приемник срабатывает, когда батарея устройства переходит в состояние низкого заряда или выходит из него. Для этого прослушиваются события {@link android.content.Intent#ACTION_BATTERY_LOW} и {@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"/>
    +  </intent-filter>
    +</receiver>
    + +

    Общепринятой практикой является отключение всех фоновых обновлений, когда заряд батареи достигает критически низкого уровня. Будет уже неважно, насколько актуальны данные в вашем приложении, если телефон самопроизвольно выключится, прежде чем пользователь успеет их просмотреть.

    + +

    Во многих случаях начало зарядки устройства совпадает с моментом его установки в док-станцию. В следующем уроке описаны способы определения текущего состояния подключения устройства к док-станции и отслеживания изменений этого состояния.

    + diff --git a/docs/html/intl/ru/training/monitoring-device-state/connectivity-monitoring.jd b/docs/html/intl/ru/training/monitoring-device-state/connectivity-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..ca1a9423692f8faa90d067dd9afa485dbdd0b997 --- /dev/null +++ b/docs/html/intl/ru/training/monitoring-device-state/connectivity-monitoring.jd @@ -0,0 +1,70 @@ +page.title=Determining and Monitoring the Connectivity Status +parent.title=Optimizing Battery Life +parent.link=index.html + +trainingnavtop=true + +previous.title=Determining and Monitoring the Docking State and Type +previous.link=docking-monitoring.html +next.title=Manipulating Broadcast Receivers On Demand +next.link=manifest-receivers.html + +@jd:body + + + +

    Чаще всего повторяющиеся оповещения и фоновые службы используются для планового обновления приложения из Интернета, кэширования или загрузки больших объемов данных. Однако если подключение к Интернету не установлено или скорость соединения слишком низкая, выполнять загрузку не имеет смысла.

    + +

    Проверить наличие подключения к Интернету и его тип можно с помощью {@link android.net.ConnectivityManager}.

    + + +

    Определение наличия подключения к Интернету

    + +

    Если подключение отсутствует, нет смысла планировать обновление из Интернета. В приведенном ниже коде показано, как использовать {@link android.net.ConnectivityManager} для отправки запросов об активной сети и определять возможности подключения.

    + +
    ConnectivityManager cm =
    +        (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    + 
    +NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    +boolean isConnected = activeNetwork.isConnectedOrConnecting();
    + + +

    Определение типа подключения к Интернету

    + +

    Также можно определить тип доступного в настоящий момент подключения к Интернету.

    + +

    Устройство может подключаться по сети мобильной связи, WiMAX, Wi-Fi и Ethernet. Получив ответ на запрос о типе активной сети, как показано ниже, можно изменить частоту обновлений на основе ее пропускной способности.

    + +
    boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
    + +

    Стоимость передачи данных по мобильной сети, как правило, значительно выше, чем по сети Wi-Fi, поэтому частота обновлений в первом случае должна быть ниже. То же касается загрузки большого количества данных: ее следует отложить, пока не будет установлено подключение к сети Wi-Fi.

    + +

    Когда обновления отключены, необходимо отслеживать изменения доступных соединений, чтобы возобновить их сразу после подключения устройства к Интернету.

    + + +

    Отслеживание изменения возможностей подключения

    + +

    {@link android.net.ConnectivityManager} передает действие {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} ({@code "android.net.conn.CONNECTIVITY_CHANGE"}) при каждом изменении сведений о подключении. Зарегистрируйте в манифесте приемник широковещательных намерений, чтобы отслеживать эти изменения и запускать (или приостанавливать) фоновые обновления соответствующим образом.

    + +
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    + +

    Доступные соединения могут меняться очень часто – эта передача инициируется при каждом переключении между сетью мобильной связи и Wi-Fi. Ее рекомендуется отслеживать, только когда необходимо запускать ранее приостановленные обновления или загрузки. Как правило, достаточно проверить наличие подключения к Интернету перед запуском обновления и, если оно отсутствует, приостановить дальнейшие обновления до восстановления соединения.

    + +

    Для использования этого метода необходимо включать и отключать приемники широковещательных намерений, объявленные в манифесте. В следующем уроке описано, как это делать.

    diff --git a/docs/html/intl/ru/training/monitoring-device-state/docking-monitoring.jd b/docs/html/intl/ru/training/monitoring-device-state/docking-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..d94f3570458cc770735272ed505b3fa63b69415f --- /dev/null +++ b/docs/html/intl/ru/training/monitoring-device-state/docking-monitoring.jd @@ -0,0 +1,74 @@ +page.title=Determining and Monitoring the Docking State and Type +parent.title=Optimizing Battery Life +parent.link=index.html + +trainingnavtop=true +previous.title= Monitoring the Battery Level and Charging State +previous.link=battery-monitoring.html +next.title= Determining and Monitoring the Connectivity Status +next.link=connectivity-monitoring.html + +@jd:body + + + +

    Устройства под управлением ОС Android можно подключать к нескольким типам док-станций: настольным, которые делятся на цифровые и аналоговые, и автомобильным. В большинстве случаев устройства заряжаются при подключении к док-станции, поэтому состояние подключения к док-станции часто связано с состоянием зарядки.

    + +

    Насколько состояние подключения к док-станции влияет на частоту обновления, зависит от конкретного приложения. Например, можно увеличить частоту обновлений приложения, показывающего спортивные новости, когда устройство подключено к настольной док-станции, и полностью отключить обновления при подключении к автомобильной. И наоборот, если используется приложение, которое в фоновом режиме загружает данные о дорожной обстановке, то при подключении устройства к автомобильной док-станции следует выполнять обновления максимально часто.

    + +

    Состояние подключения к док-станции также передается в виде закрепленного намерения {@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);
    +Intent dockStatus = context.registerReceiver(null, ifilter);
    + +

    Сведения о текущем состоянии подключения к док-станции можно извлечь из дополнительных данных {@code EXTRA_DOCK_STATE}:

    + +

    int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
    +boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
    + + +

    Определение типа док-станции

    + +

    Док-станция, к которой подключено устройство, может быть одного из четырех типов: +

    • автомобильная;
    • +
    • настольная;
    • +
    • настольная с минимальным набором функций (аналоговая);
    • +
    • настольная с широким набором функций (цифровая).

    + +

    Обратите внимание, что последние два типа поддерживаются только на уровне API 11, поэтому, даже если вас не интересует, является ли док-станция цифровой или аналоговой, а интересует только ее тип, рекомендуется выполнять проверку по всем трем типам:

    + +
    boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
    +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}. Чтобы отслеживать состояние подключения к док-станции, достаточно зарегистрировать в манифесте приложения приемник широковещательных намерений, как показано ниже.

    + +
    <action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
    + +

    Данные о типе док-станции и о состоянии подключения к ней можно извлечь внутри реализации приемника с помощью методов, описанных в предыдущем шаге.

    diff --git a/docs/html/intl/ru/training/monitoring-device-state/index.jd b/docs/html/intl/ru/training/monitoring-device-state/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..c87d9af5da4da28685faae4d7d166f4460d276cc --- /dev/null +++ b/docs/html/intl/ru/training/monitoring-device-state/index.jd @@ -0,0 +1,49 @@ +page.title=Optimizing Battery Life + +trainingnavtop=true +startpage=true +next.title=Monitoring the Battery Level and Charging State +next.link=battery-monitoring.html + +@jd:body + +
    +
    + +

    Требования

    + + +

    Дополнительные материалы

    + + +
    +
    + +

    Качественное приложение должно оказывать минимальное влияние на время работы устройства от батареи. В этом уроке вы научитесь создавать приложения, способные изменять функционал и режим работы в зависимости от состояния устройства.

    + +

    Отключение обновления данных фоновых служб при потере подключения и снижение частоты обновления при низком заряде батареи позволяет снизить расход энергии и продлить работу устройства без подзарядки.

    + +

    Уроки

    + + + +
    +
    Отслеживание уровня заряда батареи и состояния зарядки
    +
    Вы узнаете, как изменять частоту обновления приложения, определяя и отслеживая текущий уровень заряда батареи и изменение состояния зарядки.
    + +
    Отслеживание состояния подключения к док-станции и определение ее типа
    +
    Оптимальная частота обновления зависит от способа использования устройства. Вы узнаете, как определять и отслеживать состояние подключения к док-станции и ее тип, чтобы соответствующим образом корректировать работу приложения.
    + +
    Определение и отслеживание состояния подключения
    +
    Приложение невозможно обновить через Интернет, если отсутствует подключение. Вы узнаете, как проверить состояние подключения, чтобы при необходимости изменить частоту фоновых обновлений. Также вы научитесь проверять наличие мобильного подключения или подключения по сети Wi-Fi перед началом операций, требующих передачи больших объемов данных.
    + +
    Операции с приемниками широковещательных намерений по запросу
    +
    Приемники широковещательных намерений, объявленные в манифесте, можно включать и отключать во время работы приложения. Это позволяет отключать ненужные приемники в зависимости от состояния устройства. Вы узнаете, как повысить эффективность путем включения, отключения или каскадирования приемников изменения состояния и как отложить действие до момента перехода устройства в заданное состояние.
    +
    \ No newline at end of file diff --git a/docs/html/intl/ru/training/monitoring-device-state/manifest-receivers.jd b/docs/html/intl/ru/training/monitoring-device-state/manifest-receivers.jd new file mode 100644 index 0000000000000000000000000000000000000000..724ee93e282231d5960116ee5cd2d491a7b5ba70 --- /dev/null +++ b/docs/html/intl/ru/training/monitoring-device-state/manifest-receivers.jd @@ -0,0 +1,50 @@ +page.title=Manipulating Broadcast Receivers On Demand +parent.title=Optimizing Battery Life +parent.link=index.html + +trainingnavtop=true + +previous.title=Determining and Monitoring the Connectivity Status +previous.link=connectivity-monitoring.html + +@jd:body + + + +

    Самый простой способ отслеживать изменения состояния устройства – создать приемники {@link android.content.BroadcastReceiver} для каждого отслеживаемого состояния и зарегистрировать их в манифесте приложения. Затем в каждом из этих приемников можно переопределять график повторяющихся оповещений в зависимости от текущего состояния устройства.

    + +

    Этот способ имеет недостатки: приложение активирует устройство при каждом запуске любого из этих приемников, что далеко не всегда оправданно.

    + +

    Оптимальный вариант – включать и выключать приемники широковещательных намерений во время работы приложения. Это позволяет использовать приемники, объявленные в манифесте, как пассивные оповещения, которые инициируются системными событиями только в случае необходимости.

    + + +

    Включение, отключение и каскадирование приемников изменения состояния для повышения эффективности

    + +

    {@link android.content.pm.PackageManager} позволяет включать и выключать любые компоненты, определенные в манифесте, в том числе все приемники широковещательных намерений:

    + +
    ComponentName receiver = new ComponentName(context, myReceiver.class);
    +
    +PackageManager pm = context.getPackageManager();
    +
    +pm.setComponentEnabledSetting(receiver,
    +        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
    +        PackageManager.DONT_KILL_APP)
    + +

    При разрыве соединения этот метод позволяет выключить все приемники, кроме приемника изменения состояния подключения. И наоборот, когда подключение уже установлено, отслеживать изменения его состояния не требуется. Достаточно проверить наличие подключения к Интернету непосредственно перед обновлением или изменением графика оповещений о регулярном обновлении.

    + +

    Точно так же можно отложить загрузку, для выполнения которой требуется более высокая пропускная способность. Просто включите приемник широковещательных намерений, который будет отслеживать изменения возможности подключения и инициировать загрузку только после подключения к сети Wi-Fi.

    diff --git a/docs/html/intl/ru/training/multiscreen/adaptui.jd b/docs/html/intl/ru/training/multiscreen/adaptui.jd new file mode 100644 index 0000000000000000000000000000000000000000..490a64ad2de6abf81692ac542336b4b72379903f --- /dev/null +++ b/docs/html/intl/ru/training/multiscreen/adaptui.jd @@ -0,0 +1,212 @@ +page.title=Implementing Adaptative UI Flows +parent.title=Designing for Multiple Screens +parent.link=index.html + +trainingnavtop=true +previous.title=Supporting Different Screen Densities +previous.link=screendensities.html + +@jd:body + + + + + +

    Алгоритм пользовательского интерфейса зависит от макета, который в данный момент отображается. Например, если приложение работает в двухпанельном режиме, то при нажатии на элемент в левой панели содержание отобразится в правой. В однопанельном режиме содержание откроется отдельно (в другой активности).

    + + +

    Определение текущего макета

    + +

    Так как в реализации макетов существуют отличия, первое, что необходимо сделать, – определить, какой макет отображается в данный момент. Например, работает ли приложение в однопанельном или двухпанельном режиме. Для этого создадим запрос о том, существует ли данное представление и отображается ли оно в настоящий момент:

    + +
    +public class NewsReaderActivity extends FragmentActivity {
    +    boolean mIsDualPane;
    +
    +    @Override
    +    public void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        setContentView(R.layout.main_layout);
    +
    +        View articleView = findViewById(R.id.article);
    +        mIsDualPane = articleView != null && 
    +                        articleView.getVisibility() == View.VISIBLE;
    +    }
    +}
    +
    + +

    Обратите внимание: представленный выше код содержит запрос о том, доступна ли панель article, поскольку это удобнее, чем писать отдельные запросы для каждого макета.

    + +

    Кроме того, для работы с учетом существующих компонентов можно также проверять их доступность, прежде чем выполнять с ними какие-либо операции. Например, в учебном приложении News Reader есть кнопка, которая служит для доступа в меню, однако она отображается только в операционных системах Android версии ниже, чем 3.0, потому что в последующих версиях ее функцию выполняет элемент {@link android.app.ActionBar} на уровне API 11 и выше. Чтобы проверить наличие этой кнопки, добавим прослушиватель событий с помощью следующего кода:

    + +
    +Button catButton = (Button) findViewById(R.id.categorybutton);
    +OnClickListener listener = /* create your listener here */;
    +if (catButton != null) {
    +    catButton.setOnClickListener(listener);
    +}
    +
    + + +

    Дальнейшие действия в зависимости от текущего макета

    + +

    Результаты некоторых операций зависят от текущего макета. Например, если в приложении News Reader в двухпанельном режиме нажать на заголовок в списке, то статья откроется в правой панели. Если же интерфейс работает в однопанельном режиме, будет запущена отдельная активность:

    + +
    +@Override
    +public void onHeadlineSelected(int index) {
    +    mArtIndex = index;
    +    if (mIsDualPane) {
    +        /* display article on the right pane */
    +        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    +    } else {
    +        /* start a separate activity */
    +        Intent intent = new Intent(this, ArticleActivity.class);
    +        intent.putExtra("catIndex", mCatIndex);
    +        intent.putExtra("artIndex", index);
    +        startActivity(intent);
    +    }
    +}
    +
    + +

    Аналогично, в двухпанельном режиме должна отображаться панель действий с навигационными вкладками, а в однопанельном навигация должна быть реализована с помощью раскрывающегося списка. Приложение должно проверять, какой из этих вариантов следует использовать:

    + +
    +final String CATEGORIES[] = { "Лучшие статьи", "Политика", "Экономика", "Новости технологий" };
    +
    +public void onCreate(Bundle savedInstanceState) {
    +    ....
    +    if (mIsDualPane) {
    +        /* use tabs for navigation */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
    +        int i;
    +        for (i = 0; i < CATEGORIES.length; i++) {
    +            actionBar.addTab(actionBar.newTab().setText(
    +                CATEGORIES[i]).setTabListener(handler));
    +        }
    +        actionBar.setSelectedNavigationItem(selTab);
    +    }
    +    else {
    +        /* use list navigation (spinner) */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
    +        SpinnerAdapter adap = new ArrayAdapter(this, 
    +                R.layout.headline_item, CATEGORIES);
    +        actionBar.setListNavigationCallbacks(adap, handler);
    +    }
    +}
    +
    + + +

    Повторное использование фрагментов в других активностях

    + +

    Одним из примеров повторяющегося фрагмента является реализация части интерфейса как панели в одних конфигурациях и как отдельной активности в других. Например, если приложение News Reader работает на достаточно большом экране, текст новостной статьи отображается в правой панели, а если на маленьком, то он открывается в отдельной активности.

    + +

    В таких случаях следует повторно использовать подкласс {@link android.app.Fragment} в нескольких активностях. Например, в двухпанельном макете используется подкласс ArticleFragment:

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    Он же (без макета) используется при работе на маленьком экране (активность ArticleActivity):

    + +
    +ArticleFragment frag = new ArticleFragment();
    +getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
    +
    + +

    Результат будет таким же, как если бы мы объявили фрагмент в макете XML, однако в этом случае макет XML не требуется, так как фрагмент article является единственным компонентом этой активности.

    + +

    При создании фрагментов важно не привязывать их строго к конкретной активности. Для этого можно определить интерфейс с абстрактным описанием всех необходимых способов взаимодействия фрагмента с активностью, в которой он содержится. Затем этот интерфейс нужно реализовать в самой активности.

    + +

    Например, именно так работает фрагмент HeadlinesFragment в приложении News Reader:

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    OnHeadlineSelectedListener mHeadlineSelectedListener = null;
    +
    +    /* Must be implemented by host activity */
    +    public interface OnHeadlineSelectedListener {
    +        public void onHeadlineSelected(int index);
    +    }
    +    ...
    +
    +    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
    +        mHeadlineSelectedListener = listener;
    +    }
    +}
    +
    + +

    Затем, когда пользователь выбирает заголовок, фрагмент оповещает об этом не указанную в коде активность, а заданный ею прослушиватель:

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    @Override
    +    public void onItemClick(AdapterView<?> parent, 
    +                            View view, int position, long id) {
    +        if (null != mHeadlineSelectedListener) {
    +            mHeadlineSelectedListener.onHeadlineSelected(position);
    +        }
    +    }
    +    ...
    +}
    +
    + +

    Этот метод рассматривается подробнее в разделе Поддержка планшетных ПК и мобильных телефонов.

    + + +

    Обработка изменений конфигурации экрана

    + +

    При реализации отдельных частей интерфейса с помощью разных активностей нужно учитывать, что интерфейс должен уметь реагировать на определенные изменения конфигурации, такие как поворот экрана.

    + +

    Например, на типичном планшетном ПК с размером экрана 7 дюймов под управлением ОС Android 3.0 или более поздней версии при вертикальной ориентации статья в приложении News Reader открывается с помощью отдельной активности, а при горизонтальной используется двухпанельный макет.

    + +

    Это означает, что если пользователь держит планшетный ПК вертикально и на экране запущена активность для просмотра статьи, приложение должно уметь определить, что ориентация была изменена на горизонтальную. Затем оно должно соответствующим образом отреагировать на изменение, то есть завершить эту активность и вернуться к основной активности, чтобы содержание отобразилось в двухпанельном макете:

    + +
    +public class ArticleActivity extends FragmentActivity {
    +    int mCatIndex, mArtIndex;
    +
    +    @Override
    +    protected void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
    +        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
    +
    +        // If should be in two-pane mode, finish to return to main activity
    +        if (getResources().getBoolean(R.bool.has_two_panes)) {
    +            finish();
    +            return;
    +        }
    +        ...
    +}
    +
    + + diff --git a/docs/html/intl/ru/training/multiscreen/index.jd b/docs/html/intl/ru/training/multiscreen/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..023eaecff494b48019bd4fe19f8bc082fef61545 --- /dev/null +++ b/docs/html/intl/ru/training/multiscreen/index.jd @@ -0,0 +1,64 @@ +page.title=Designing for Multiple Screens + +trainingnavtop=true +startpage=true +next.title=Supporting Different Screen Sizes +next.link=screensizes.html + +@jd:body + +
    +
    + +

    Требования

    + + + +

    Дополнительные материалы

    + + + +

    Упражнение

    + + + +
    +
    + +

    На платформе Android работают устройства с самыми разными размерами экрана: от телефонов до телевизоров. Чтобы с вашим приложением могли работать как можно больше пользователей, оно должно корректно отображаться на всех этих устройствах.

    + +

    Однако совместимость с разными типами устройств – это еще не все. От размера экрана зависит, какие возможности будет иметь пользователь при работе с приложением. Чтобы пользователи действительно остались довольны вашим приложением, оно должно не просто поддерживать разные экраны, но и быть оптимизировано для каждого из них.

    + +

    Этот модуль посвящен реализации пользовательского интерфейса, оптимизированного для разных конфигураций экрана.

    + +

    Код, приведенный в каждом уроке, взят из учебного приложения, в котором демонстрируются способы оптимизации для разных экранов. Вы можете загрузить его (в правой части экрана) и использовать части кода в собственном приложении.

    + +

    Примечание. В этом модуле и в учебном приложении используется вспомогательная библиотека, позволяющая работать с API {@link android.app.Fragment} в версиях до Android 3.0. Чтобы иметь возможность использовать все необходимые API, загрузите библиотеку и добавьте ее в свое приложение.

    + + +

    Уроки

    + +
    +
    Поддержка разных размеров экрана
    +
    В этом уроке рассказывается, как создать макет, который адаптируется к разным размерам экрана, используя масштабируемые представления, объекты {@link android.widget.RelativeLayout}, квалификаторы размера и ориентации, фильтры псевдонимов и растровые изображений формата nine-patch.
    + +
    Поддержка разных разрешений экрана
    +
    В этом уроке рассказывается, как работать с экранами разного разрешения с помощью не зависящих от разрешения пикселей и как подготовить растровые изображения для каждого из них.
    + +
    Реализация адаптируемых алгоритмов работы пользовательского интерфейса
    +
    В этом уроке рассказывается, как реализовать алгоритм работы интерфейса, адаптирующийся к размеру и разрешению экрана, то есть способный определять активный макет во время выполнения приложения, выбирать дальнейшие действия на основе текущего макета и обрабатывать изменения конфигурации экрана.
    +
    diff --git a/docs/html/intl/ru/training/multiscreen/screendensities.jd b/docs/html/intl/ru/training/multiscreen/screendensities.jd new file mode 100644 index 0000000000000000000000000000000000000000..cfd47246282404ab886065d8999ec3f5c39c9475 --- /dev/null +++ b/docs/html/intl/ru/training/multiscreen/screendensities.jd @@ -0,0 +1,100 @@ +page.title=Supporting Different Densities +parent.title=Designing for Multiple Screens +parent.link=index.html + +trainingnavtop=true +previous.title=Supporting Different Screen Sizes +previous.link=screensizes.html +next.title=Implementing Adaptative UI Flows +next.link=adaptui.html + +@jd:body + + + + + +

    В этом уроке рассказывается, как создать интерфейс, поддерживающий разные разрешения экрана, за счет использования разных ресурсов и не зависящих от разрешения единиц измерения.

    + +

    Использование пикселей, не зависящих от разрешения

    + +

    Разработчики часто допускают одну и ту же ошибку при создании макетов – указывают размеры и расстояния с помощью абсолютных значений в пикселях. Задавать размеры в пикселях не рекомендуется, поскольку из-за различной плотности пикселей на экранах разных устройств фактический размер макета будет неодинаков. Всегда задавайте размеры в единицах dp или sp. dp – это не зависящий от разрешения пиксель, равный физическому пикселю на экране с плотностью 160 точек/дюйм. sp является аналогичной единицей измерения, но масштабируется на основе выбранного пользователем размера текста, поэтому ее следует применять для указания величины шрифта, но не размера макета.

    + +

    Например, если вы задаете расстояние между двумя представлениями, рекомендуется использовать dp, а не px:

    + +
    +<Button android:layout_width="wrap_content" 
    +    android:layout_height="wrap_content" 
    +    android:text="@string/clickme"
    +    android:layout_marginTop="20dp" />
    +
    + +

    Для определения размера шрифта всегда используйте sp:

    + +
    +<TextView android:layout_width="match_parent" 
    +    android:layout_height="wrap_content" 
    +    android:textSize="20sp" />
    +
    + + +

    Предоставление альтернативных растровых изображений

    + +

    Так как платформа Android предназначена для устройств с разными разрешениями экрана, необходимо позаботиться о наличии растровых изображений для каждого из четырех обобщенных типов разрешения: низкого, среднего, высокого и очень высокого. Это обеспечит оптимальное сочетание качества графики и производительности на всех устройствах.

    + +

    На основе исходного векторного рисунка создайте растровые изображения для каждого из указанных разрешений согласно следующей шкале размеров:

    + +

      +
    • xhdpi: 2,0 +
    • hdpi: 1,5 +
    • mdpi: 1,0 (стандартный размер) +
    • ldpi: 0,75 +

    + +

    Это означает, что изображение, которое на устройствах с разрешением экрана xhdpi имеет размер 200 x 200, на устройствах hdpi должно иметь размер 150 x 150, на устройствах mdpi – 100 x 100, а на устройствах ldpi – 75 x 75.

    + +

    Поместите файлы изображений в соответствующие подкаталоги в папке res/, и система автоматически выберет подходящий в зависимости от разрешения экрана устройства, на котором выполняется приложение:

    + +
    +MyProject/
    +  res/
    +    drawable-xhdpi/
    +        awesomeimage.png
    +    drawable-hdpi/
    +        awesomeimage.png
    +    drawable-mdpi/
    +        awesomeimage.png
    +    drawable-ldpi/
    +        awesomeimage.png
    +
    + +

    При каждом обращении к файлу @drawable/awesomeimage система будет выбирать изображение, отвечающее разрешению экрана.

    + +

    Дополнительную информацию и советы можно найти в разделе Рекомендации по созданию значков.

    + diff --git a/docs/html/intl/ru/training/multiscreen/screensizes.jd b/docs/html/intl/ru/training/multiscreen/screensizes.jd new file mode 100644 index 0000000000000000000000000000000000000000..9684d77486dde06138f211ba56773608ee5597df --- /dev/null +++ b/docs/html/intl/ru/training/multiscreen/screensizes.jd @@ -0,0 +1,279 @@ +page.title=Supporting Different Screen Sizes +parent.title=Designing for Multiple Screens +parent.link=index.html + +trainingnavtop=true +next.title=Supporting Different Screen Densities +next.link=screendensities.html + +@jd:body + + + + + +

    В этом уроке описаны следующие аспекты обеспечения совместимости интерфейса с разными экранами:

    +
      +
    • обеспечение способности макета адаптироваться к размеру экрана;
    • +
    • выбор макета интерфейса, отвечающего конфигурации экрана;
    • +
    • контроль правильности применяемого макета;
    • +
    • использование масштабируемых растровых изображений.
    • +
    + + +

    Использование параметров wrap_content и match_parent

    + +

    Чтобы создать масштабируемый макет, способный адаптироваться к разным экранам, используйте в качестве значений ширины и высоты отдельных компонентов представления параметры "wrap_content" и "match_parent". Если используется "wrap_content", для ширины или высоты представления устанавливается минимальное значение, позволяющее уместить содержание на экран, а параметр "match_parent" (известный как "fill_parent" в API до 8 уровня) служит для растягивания компонента по размеру родительского представления.

    + +

    Если указать параметры "wrap_content" и "match_parent" вместо строго заданных размеров, в представлениях будет использоваться минимально необходимое место или они будут растягиваться на всю доступную длину и ширину соответственно. Например:

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    Обратите внимание на то, что в коде учебного приложения размеры компонентов заданы с помощью параметров "wrap_content" и "match_parent". В результате макет правильно отображается на экранах разных размеров при разных ориентациях.

    + +

    Например, вот так он выглядит в вертикальной и горизонтальной ориентациях. Обратите внимание на то, как размеры компонентов автоматически адаптируются к длине и ширине:

    + + +

    Рисунок 1. Приложение News Reader при вертикальной (слева) и горизонтальной (справа) ориентации.

    + + +

    Использование объекта RelativeLayout

    + +

    С помощью вложенных экземпляров объекта {@link android.widget.LinearLayout} и параметров "wrap_content" и "match_parent" можно создавать достаточно сложные макеты. Однако {@link android.widget.LinearLayout} не дает возможности точно управлять взаимным расположением дочерних представлений: в {@link android.widget.LinearLayout} они просто помещаются в ряд друг за другом. Если необходимо расположить дочерние представления иным образом, используйте объект {@link android.widget.RelativeLayout}, позволяющий задать относительные позиции компонентов. Например, одно дочернее представление можно выровнять по левому краю экрана, а другое – по правому.

    + +

    Например:

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:layout_width="match_parent"
    +    android:layout_height="match_parent">
    +    <TextView
    +        android:id="@+id/label"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:text="Type here:"/>
    +    <EditText
    +        android:id="@+id/entry"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/label"/>
    +    <Button
    +        android:id="@+id/ok"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/entry"
    +        android:layout_alignParentRight="true"
    +        android:layout_marginLeft="10dp"
    +        android:text="OK" />
    +    <Button
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_toLeftOf="@id/ok"
    +        android:layout_alignTop="@id/ok"
    +        android:text="Cancel" />
    +</RelativeLayout>
    +
    + +

    На рис. 2 показано, как этот макет выглядит на экране QVGA.

    + + +

    Рисунок 2. Скриншот экрана QVGA (маленького размера).

    + +

    На рис. 3 показано, как он выглядит на экране с большей диагональю.

    + + +

    Рисунок 3. Скриншот экрана WSVGA (большего размера).

    + +

    Обратите внимание: несмотря на изменение размера компонентов их взаимное расположение остается прежним, так как оно задано объектом {@link android.widget.RelativeLayout.LayoutParams}.

    + + +

    Использование квалификаторов размера

    + +

    Масштабируемые или относительные макеты, один из которых продемонстрирован выше, имеют свои ограничения. Хотя они позволяют создать интерфейс, способный адаптироваться к разным экранам за счет растягивания пространства внутри и вокруг компонентов, пользователю может оказаться не слишком удобно работать с таким интерфейсом. Поэтому в приложении должен использоваться не один масштабируемый макет, а несколько альтернативных вариантов для разных конфигураций экрана. Их можно создать с помощью квалификаторов конфигураций, которые позволяют оперативно выбирать ресурсы, отвечающие текущим параметрам экрана (например, разные варианты макетов для экранов разных размеров).

    + +

    Многие приложения отображаются на больших экранах в двухпанельном режиме, при котором список элементов расположен в одной панели, а их содержание открывается в другой. Такой режим просмотра удобен на достаточно больших экранах планшетных ПК и телевизоров, однако на экране телефона эти панели следует отображать по отдельности. Для каждого режима просмотра нужно создать отдельный файл.

    + +
      +
    • res/layout/main.xml, однопанельный макет (по умолчанию): + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-large/main.xml, двухпанельный макет: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    Обратите внимание, что во втором случае в названии каталога использован квалификатор large. Этот макет будет выбран на устройствах, экраны которых считаются большими (например, 7 дюймов и более). Первый макет (без квалификаторов) будет выбран для устройств с маленьким экраном.

    + + +

    Использование квалификатора Smallest-width

    + +

    Одной из проблем, с которой сталкивались разработчики приложений для устройств Android версий до 3.2, было слишком общее определение "большого" экрана. Это касалось устройств Dell Streak, первой модели Galaxy Tab и планшетных ПК с экраном размером 7 дюймов. Многие приложения требовалось по-разному отображать на разных устройствах (например, с 5- и 7-дюймовыми экранами), хотя они и относились к одной категории "больших" экранов. В Android версии 3.2 и более поздних доступен квалификатор Smallest-width.

    + +

    Он позволяет определять экраны с заданной минимальной шириной в dp. Например, типичный планшетный ПК с экраном 7 дюймов имеет минимальную ширину 600 dp, и если вы хотите, чтобы приложение работало на нем в двухпанельном режиме (а на меньших экранах в однопанельном), используйте два макета из предыдущего раздела, но вместо квалификатора размера large укажите sw600dp. В таком случае на экранах, минимальная ширина которых составляет 600 dp, будет использоваться двухпанельный макет.

    + +
      +
    • res/layout/main.xml, однопанельный макет (по умолчанию): + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-sw600dp/main.xml, двухпанельный макет: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    Это означает, что на устройствах, минимальная ширина экрана которых не меньше 600 dp, будет выбран layout-sw600dp/main.xml (двухпанельный макет), а на экранах меньшего размера – layout/main.xml (однопанельный макет).

    + +

    Следует учесть, что на 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-дюймовым экраном, телевизорах и других крупных устройствах, подготовьте следующие файлы:

    + +

      +
    • res/layout/main.xml: однопанельный макет;
    • +
    • res/layout-large: многопанельный макет;
    • +
    • res/layout-sw600dp: многопанельный макет.
    • +

    + +

    Последние два файла идентичны: один из них предназначен для устройств Android 3.2 и новее, а второй для более старых планшетных ПК и телевизоров на платформе Android.

    + +

    Чтобы не создавать дубликаты файлов и упростить процесс поддержки приложения, используйте псевдонимы. Например, можно определить следующие макеты:

    + +
      +
    • res/layout/main.xml (однопанельный макет);
    • +
    • res/layout/main_twopanes.xml (двухпанельный макет).
    • +
    + +

    Затем добавьте следующие два файла:

    + +

      +
    • res/values-large/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      +
    • + +
    • res/values-sw600dp/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      + +
    • +

    + +

    Содержание последних двух файлов одинаково, но сами по себе они не определяют макет. Они служат для того, чтобы назначить файл {@code main} в качестве псевдонима {@code main_twopanes}. Так как в них используются селекторы large и sw600dp, они применяются к планшетным ПК и телевизорам на платформе Android независимо от версии (для версий до 3.2 используется +{@code large}, а для более новых – sw600dp).

    + + +

    Использование квалификаторов ориентации

    + +

    Хотя некоторые макеты одинаково хорошо смотрятся в вертикальной и горизонтальной ориентациях, в большинстве случаев интерфейс все же приходится адаптировать. Ниже показано, как изменяется макет в приложении News Reader в зависимости от размера и ориентации экрана.

    + +

      +
    • Маленький экран, вертикальная ориентация: однопанельный вид с логотипом.
    • +
    • Маленький экран, горизонтальная ориентация: однопанельный вид с логотипом.
    • +
    • Планшетный ПК с 7-дюймовым экраном, вертикальная ориентация: однопанельный вид с панелью действий.
    • +
    • Планшетный ПК с 7-дюймовым экраном, горизонтальная ориентация: двухпанельный вид с панелью действий.
    • +
    • Планшетный ПК с 10-дюймовым экраном, вертикальная ориентация: двухпанельный вид (узкий вариант) с панелью действий.
    • +
    • Планшетный ПК с 10-дюймовым экраном, горизонтальная ориентация: двухпанельный вид (широкий вариант) с панелью действий.
    • +
    • Телевизор, горизонтальная ориентация: двухпанельный вид с панелью действий.
    • +

    + +

    Каждый из этих макетов определен в XML-файле в каталоге res/layout/. Чтобы сопоставить их с определенными конфигурациями экрана, в приложении используются псевдонимы:

    + +

    res/layout/onepane.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} + +

    res/layout/onepane_with_bar.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    res/layout/twopanes.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    res/layout/twopanes_narrow.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all} + +

    После того как все возможные макеты определены, остается сопоставить каждый из них с подходящей конфигурацией, используя квалификаторы конфигураций. Воспользуемся псевдонимами макетов:

    + +

    res/values/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all} + +

    res/values-sw600dp-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml +all} + +

    res/values-sw600dp-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml +all} + +

    res/values-large-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all} + +

    res/values-large-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all} + + + +

    Использование растровых изображений nine-patch

    + +

    Чтобы интерфейс был совместим с экранами разных размеров, используемые в нем графические элементы также должны быть адаптированы соответствующим образом. Например, фон кнопки должен одинаково хорошо выглядеть независимо от ее формы.

    + +

    Если использовать для компонентов, размеры которых меняются, обычные изображения, то они будут равномерно сжиматься и растягиваться, и результат будет далек от идеального. Решением являются растровые изображения формата nine-patch – специальные PNG-файлы, содержащие информацию о том, какие области можно растягивать, а какие нет.

    + +

    Создавая растровые изображения для масштабируемых компонентов, обязательно используйте формат nine-patch. На рис. 4 показано обычное растровое изображение (увеличенное в 4 раза для наглядности), которое мы переведем в формат nine-patch.

    + + +

    Рисунок 4. button.png

    + +

    Откройте его с помощью утилиты draw9patch, входящей в комплект разработчика (в каталоге tools/). Установите метки на левом и верхнем краях, чтобы ограничить области, которые можно растягивать. Можно также провести линию вдоль правого и нижнего краев, как показано на рис. 5, чтобы отметить области, в которых содержание должно быть зафиксировано.

    + + +

    Рисунок 5. button.9.png

    + +

    Обратите внимание на черные пиксели по краям. Метки у верхней и левой границ обозначают те области, которые можно растягивать, а метки у правой и нижней границ – те, куда должно быть помещено содержание.

    + +

    Также обратите внимание на расширение .9.png. Оно должно быть задано именно в таком виде, чтобы система могла определить, что это формат nine-patch, а не обычный PNG-файл.

    + +

    При применении этого фона к компоненту (с помощью android:background="@drawable/button") изображение будет растянуто по размеру кнопки, как показано на рис. 6.

    + + +

    Рисунок 6. Кнопки разных размеров с файлом фона button.9.png в формате nine-patch.

    + diff --git a/docs/html/intl/zh-CN/training/monitoring-device-state/battery-monitoring.jd b/docs/html/intl/zh-CN/training/monitoring-device-state/battery-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..0e1ccb7391681b8a69edb98f64094953d2dd63df --- /dev/null +++ b/docs/html/intl/zh-CN/training/monitoring-device-state/battery-monitoring.jd @@ -0,0 +1,120 @@ +page.title=监控电池电量和充电状态 +parent.title=优化电池使用时间 +parent.link=index.html + +trainingnavtop=true +next.title=确定和监控基座对接状态和类型 +next.link=docking-monitoring.html + +@jd:body + + + +

    如果您要更改后台更新频率,从而减少更新对电池使用时间的影响,最好先查看当前的电池电量和充电状态。

    + +

    对应用进行更新会影响电池使用时间,具体取决于设备的电池电量和充电状态。如果用户正在通过交流电源为设备充电,更新应用的影响就可以忽略不计。因此,在大多数情况下,只要设备连接了充电器,您就可以最大程度地提高刷新频率。相反,如果设备在消耗电池电量,那么降低更新频率就可以延长电池使用时间。

    + +

    同样,您也可以查看电池电量,如果电量即将耗尽,您就可以降低更新频率,甚至停止更新。

    + + +

    确定当前的充电状态

    + +

    请先确定当前的充电状态。{@link android.os.BatteryManager} 会通过一个包含充电状态的持续 {@link android.content.Intent} 广播所有的电池详情和充电详情。

    + +

    由于这是个持续 intent,因此您无需通过将传入 {@code null} 的 {@code registerReceiver} 作为接收器直接调用(如下一代码段所示)来注册 {@link android.content.BroadcastReceiver},系统会返回当前电池状态 intent。您可以在此处传入实际的 {@link android.content.BroadcastReceiver} 对象,不过我们会在下文中介绍如何处理更新,因此您不一定要执行此操作。

    + +
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    +Intent batteryStatus = context.registerReceiver(null, ifilter);
    + +

    如果设备正在充电,则您可以提取当前的充电状态和充电方式(无论是通过 USB 还是交流充电器),如下所示:

    + +

    // Are we charging / charged?
    +int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
    +boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
    +                     status == BatteryManager.BATTERY_STATUS_FULL;
    +
    +// How are we charging?
    +int chargePlug = battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    +boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
    +boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
    + +

    通常,如果设备连接了交流充电器,您就应最大程度地提高后台更新频率;如果设备通过 USB 充电,请降低更新频率;如果电池在耗电,请进一步降低更新频率。

    + + +

    监控充电状态的变化

    + +

    充电状态的改变就像设备连接电源那样容易,因此监控充电状态的变化并相应地调整刷新频率就很重要了。

    + +

    只要设备连接或断开电源,{@link android.os.BatteryManager} 就会广播相应的操作。即使您的应用没有运行,也请务必接收这些事件,尤其是当这些事件会影响您启动应用以执行后台更新的频率时。因此,您应该通过在 intent 过滤器中定义 {@link android.content.Intent#ACTION_POWER_CONNECTED} 和 {@link android.content.Intent#ACTION_POWER_DISCONNECTED},在清单中注册 {@link android.content.BroadcastReceiver} 来侦听这两个事件。

    + +
    <receiver android:name=".PowerConnectionReceiver">
    +  <intent-filter>
    +    <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
    +    <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
    +  </intent-filter>
    +</receiver>
    + +

    在实施相关的 {@link android.content.BroadcastReceiver} 时,您可以按上一步骤所述提取当前的充电状态和充电方式。

    + +
    public class PowerConnectionReceiver extends BroadcastReceiver {
    +    @Override
    +    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;
    +    }
    +}
    + + +

    确定当前的电池电量

    + +

    在某些情况下,确定当前的电池电量会对您有所帮助。如果电池电量低于一定水平,您可以降低后台更新频率。

    + +

    您可以从电池状态 intent 中提取要了解的当前电池电量以及电池容量,具体如下所示:

    + +
    int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    +int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
    +
    +float batteryPct = level / (float)scale;
    + + +

    监控电池电量的显著变化

    + +

    您无法轻松地对电池状态进行持续监控,不过也无需这么做。

    + +

    一般来说,与应用的正常行为相比,持续监控电池电量会消耗更多电量。因此,比较合适的做法是只监控电池电量的显著变化(尤其是在设备进入或结束低电量状态的情况下)。

    + +

    以下清单代码段提取自广播接收器中的 intent 过滤器元素。通过侦听 {@link android.content.Intent#ACTION_BATTERY_LOW} 和 {@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"/>
    +  </intent-filter>
    +</receiver>
    + +

    如果电池电量极低,通常比较合适的做法是停用所有后台更新。如果您还没用上更新的数据,手机就自动关机了,那这些数据再新也没有意义。

    + +

    在很多情况下,将设备插入基座就可以为其充电。下一教程将向您介绍如何确定当前基座状态及如何监控设备对接的变化。

    + diff --git a/docs/html/intl/zh-CN/training/monitoring-device-state/connectivity-monitoring.jd b/docs/html/intl/zh-CN/training/monitoring-device-state/connectivity-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..8313e089b908f08d6470bf63159d52fac7f48a67 --- /dev/null +++ b/docs/html/intl/zh-CN/training/monitoring-device-state/connectivity-monitoring.jd @@ -0,0 +1,70 @@ +page.title=确定和监控网络连接状态 +parent.title=优化电池使用时间 +parent.link=index.html + +trainingnavtop=true + +previous.title=确定和监控基座对接状态和类型 +previous.link=docking-monitoring.html +next.title=根据需要操作广播接收器 +next.link=manifest-receivers.html + +@jd:body + + + +

    重复提醒和后台服务最常见的用途之一,就是为来自互联网资源的应用数据、缓存数据安排定期更新或执行长时间运行的下载任务。但是,如果您没有连接互联网,或因连接过慢而无法完成下载,那就根本没必要唤醒设备并安排更新了。

    + +

    您可以使用 {@link android.net.ConnectivityManager} 查看是否确实已连接互联网,如果已连接,您还可以了解当前的连接类型。

    + + +

    确定是否已连接互联网

    + +

    如果设备未连接互联网,就没有必要根据互联网资源安排更新了。以下代码段说明如何使用 {@link android.net.ConnectivityManager} 查询有效网络并确定该网络是否已连接互联网。

    + +
    ConnectivityManager cm =
    +        (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    + 
    +NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    +boolean isConnected = activeNetwork.isConnectedOrConnecting();
    + + +

    确定互联网连接的类型

    + +

    您也可以确定当前可用的互联网连接的类型。

    + +

    通过移动数据、WiMAX、Wi-Fi 和以太网连接可提供设备连接。您可以查询有效网络的类型(具体如下所示),以便根据可用带宽调整刷新频率。

    + +
    boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
    + +

    移动数据的费用往往比 Wi-Fi 高很多,因此在大多数情况下,如果您使用的是移动连接,就应降低应用更新频率。同样,在没有 Wi-Fi 连接的情况下,您就应暂停较大的下载任务。

    + +

    停用更新后,请务必侦听连接情况的变化,以便在建立互联网连接后恢复更新。

    + + +

    监控连接情况的变化

    + +

    只要连接的具体情况发生变化,{@link android.net.ConnectivityManager} 就会广播 {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} ({@code "android.net.conn.CONNECTIVITY_CHANGE"}) 操作。您可以在清单中注册广播接收器,以便侦听这些变化并相应地恢复(或暂停)后台更新。

    + +
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    + +

    设备连接情况的变化可能会非常频繁,只要您在移动数据和 Wi-Fi 之间相互切换,系统就会触发此广播。因此比较合适的做法是,仅当之前暂停了更新或下载时才监控此广播,以便恢复更新或下载。通常,您只需在开始更新前检查互联网连接情况即可,如果未连接互联网,请暂停后续更新,直到连接恢复。

    + +

    此技巧需要切换您在清单中声明的广播接收器,具体说明请见下一教程。

    diff --git a/docs/html/intl/zh-CN/training/monitoring-device-state/docking-monitoring.jd b/docs/html/intl/zh-CN/training/monitoring-device-state/docking-monitoring.jd new file mode 100644 index 0000000000000000000000000000000000000000..53b951dd584e8ff2c56b7ff81a15e4912fcfb092 --- /dev/null +++ b/docs/html/intl/zh-CN/training/monitoring-device-state/docking-monitoring.jd @@ -0,0 +1,74 @@ +page.title=确定和监控基座对接状态和类型 +parent.title=优化电池使用时间 +parent.link=index.html + +trainingnavtop=true +previous.title= 监控电池电量和充电状态 +previous.link=battery-monitoring.html +next.title= 确定和监控网络连接状态 +next.link=connectivity-monitoring.html + +@jd:body + + + +

    Android 设备支持几种不同类型的基座。这些类型包括车载或家用基座以及数字和模拟基座。许多基座可用于为插入的设备充电,因此基座状态通常与充电状态紧密相关。

    + +

    您可以根据手机的基座状态调整更新频率,具体取决于相关应用。如果设备插入的是桌面基座,您就可以提高体育中心类应用的更新频率;如果设备插入的是车载基座,您就可以完全停用此类更新。相反,如果设备插入的是车载基座且后台服务正在更新路况,您就可以最大程度地提高更新频率。

    + +

    系统是以持续 {@link android.content.Intent} 的形式广播基座状态的,这样您就可以查询设备是否插入了基座,如果已插入,您还可以查询基座类型。

    + + +

    确定当前的基座状态

    + +

    基座状态详情是以附加信息的形式包含在 {@link android.content.Intent#ACTION_DOCK_EVENT} 操作的持续广播中的。由于这属于持续广播,因此您无需注册 {@link android.content.BroadcastReceiver}。您可以将传入 {@code null} 的 {@link android.content.Context#registerReceiver registerReceiver()} 作为广播接收器直接调用,具体如下一代码段所示。

    + +
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
    +Intent dockStatus = context.registerReceiver(null, ifilter);
    + +

    您可以从 {@code EXTRA_DOCK_STATE} 附加信息中提取当前的基座对接状态:

    + +

    int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
    +boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
    + + +

    确定当前的基座类型

    + +

    用户可以将设备插入以下四种类型的基座: +

    • 车载基座
    • +
    • 桌面基座
    • +
    • 低端(模拟)桌面基座
    • +
    • 高端(数字)桌面基座

    + +

    请注意,后两种类型仅适用于 API 级别为 11 及以上的 Android,因此如果您只关注基座类型,而不在意基座究竟是数字的还是模拟的,那么比较合适的做法就是查看全部三种类型:

    + +
    boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
    +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} 操作。要监控设备基座状态的变化,您只需在应用清单中注册广播接收器即可,具体如以下代码段所示:

    + +
    <action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
    + +

    您可以使用上一步骤中所述的技术在接收器实施过程中提取基座的类型和状态。

    diff --git a/docs/html/intl/zh-CN/training/monitoring-device-state/index.jd b/docs/html/intl/zh-CN/training/monitoring-device-state/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..aa107539eeca5450c082ac96d3c658d9572f19e3 --- /dev/null +++ b/docs/html/intl/zh-CN/training/monitoring-device-state/index.jd @@ -0,0 +1,49 @@ +page.title=优化电池使用时间 + +trainingnavtop=true +startpage=true +next.title=监控电池电量和充电状态 +next.link=battery-monitoring.html + +@jd:body + +
    +
    + +

    依存关系和前提条件

    + + +

    您还应参阅

    + + +
    +
    + +

    为了打造一个优秀的应用,您应设法降低应用对电池使用时间的影响。阅读完本教程后,您就可以让自己构建的应用根据其所在设备的状态来监控和调整自身的功能和行为。

    + +

    要确保在不影响用户体验的情况下最大程度地降低应用对电池使用时间的影响,您可以采取一些措施,例如在网络连接断开时停用后台服务更新,或在电池电量较低时降低此类更新的频率。

    + +

    教程

    + + + +
    +
    监控电池电量和充电状态
    +
    了解如何通过确定和监控当前的电池电量和充电状态的变化来相应地调整应用的更新频率。
    + +
    确定和监控基座对接状态和类型
    +
    最佳刷新频率可能各有不同,具体取决于安装了相关应用的设备的使用方式。了解如何确定和监控所用基座的对接状态和类型,以便相应地调整应用的行为。
    + +
    确定和监控网络连接状态
    +
    如果没有互联网连接,您就无法通过在线来源更新应用。了解如何查看连接状态,以便相应地调整后台更新频率。您还可以了解如何在执行高带宽操作前查看 Wi-Fi 或移动连接的状态。
    + +
    根据需要操作广播接收器
    +
    您可以在运行时切换自己在清单中声明的广播接收器,以便根据当前设备状态停用不需要的接收器。了解如何在设备未处于特定状态的情况下切换和层叠状态变化接收器和延迟操作,以便提高效率。
    +
    \ No newline at end of file diff --git a/docs/html/intl/zh-CN/training/monitoring-device-state/manifest-receivers.jd b/docs/html/intl/zh-CN/training/monitoring-device-state/manifest-receivers.jd new file mode 100644 index 0000000000000000000000000000000000000000..07c014f10a31555dac087e5e0b221aeaed8592a2 --- /dev/null +++ b/docs/html/intl/zh-CN/training/monitoring-device-state/manifest-receivers.jd @@ -0,0 +1,50 @@ +page.title=根据需要操作广播接收器 +parent.title=优化电池使用时间 +parent.link=index.html + +trainingnavtop=true + +previous.title=确定和监控网络连接状态 +previous.link=connectivity-monitoring.html + +@jd:body + +
    +
    + +

    本教程将指导您

    +
      +
    1. 切换和层叠状态变化接收器以提高效率
    2. +
    + + +

    您还应参阅

    + + +
    +
    + +

    监控设备状态变化的最简单方法就是,为您监控的每种状态创建 {@link android.content.BroadcastReceiver} 并在应用清单中逐一进行注册。然后,您只需根据当前设备状态在每个接收器中重新安排重复提醒即可。

    + +

    此方法的负面影响在于,只要系统触发了这些接收器中的任何一个,相关应用就会唤醒设备,其频率可能会远远超过所需的水平。

    + +

    更好的方法是在运行时停用或启用广播接收器。这样的话,您就可以将自己在清单中声明的接收器用作被动提醒,只有在需要时才会由系统事件触发。

    + + +

    切换和层叠状态变化接收器以提高效率

    + +

    您可以使用 {@link android.content.pm.PackageManager} 切换清单中定义的任意组件的启用状态(包括您要启用或停用的任意广播接收器),具体如以下片段所示:

    + +
    ComponentName receiver = new ComponentName(context, myReceiver.class);
    +
    +PackageManager pm = context.getPackageManager();
    +
    +pm.setComponentEnabledSetting(receiver,
    +        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
    +        PackageManager.DONT_KILL_APP)
    + +

    在使用此技巧时,如果您确定连接已断开,就可以停用除连接变化接收器外的所有接收器。相反,成功连接后,您就可以停止侦听连接变化,同时只需在执行更新和重新安排重复更新提醒前查看是否在线即可。

    + +

    您可以使用同样的方法来延迟需要较高带宽的下载任务。只有在连接 Wi-Fi 后,您才能直接启用用于侦听连接变化和启动下载任务的广播接收器。

    diff --git a/docs/html/intl/zh-CN/training/multiscreen/adaptui.jd b/docs/html/intl/zh-CN/training/multiscreen/adaptui.jd new file mode 100644 index 0000000000000000000000000000000000000000..89908fe46ef9b14962eba8832d3bbe4d0a7fdc82 --- /dev/null +++ b/docs/html/intl/zh-CN/training/multiscreen/adaptui.jd @@ -0,0 +1,212 @@ +page.title=实施自适应用户界面流程 +parent.title=针对多种屏幕进行设计 +parent.link=index.html + +trainingnavtop=true +previous.title=支持各种屏幕密度 +previous.link=screendensities.html + +@jd:body + + + +
    +
    + +

    本教程将指导您

    + +
      +
    1. 确定当前布局
    2. +
    3. 根据当前布局做出响应
    4. +
    5. 重复使用其他活动中的片段
    6. +
    7. 处理屏幕配置变化
    8. +
    + +

    您还应参阅

    + + + +

    试试看

    + +
    +下载示例应用 +

    NewsReader.zip

    +
    + + +
    +
    + +

    根据您的应用当前显示的布局,用户界面流程可能会有所不同。例如,如果您的应用处于双面板模式下,点击左侧面板上的项即可直接在右侧面板上显示相关内容;如果该应用处于单面板模式下,相关内容就应以其他活动的形式在同一面板上显示。

    + + +

    确定当前布局

    + +

    由于每种布局的实施都会稍有不同,因此您可能需要先确定当前向用户显示的布局。例如,您可以了解用户所处的是“单面板”模式还是“双面板”模式。要做到这一点,您可以查询指定视图是否存在以及是否已显示出来。

    + +
    +public class NewsReaderActivity extends FragmentActivity {
    +    boolean mIsDualPane;
    +
    +    @Override
    +    public void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        setContentView(R.layout.main_layout);
    +
    +        View articleView = findViewById(R.id.article);
    +        mIsDualPane = articleView != null && 
    +                        articleView.getVisibility() == View.VISIBLE;
    +    }
    +}
    +
    + +

    请注意,这段代码用于查询“报道”面板是否可用,与针对具体布局的硬编码查询相比,这段代码的灵活性要大得多。

    + +

    再举一个适应各种组件的存在情况的方法示例:在对这些组件执行操作前先查看它们是否可用。例如,新闻阅读器示例应用中有一个用于打开菜单的按钮,但只有在版本低于 3.0 的 Android 上运行该应用时,这个按钮才会存在,因为 API 级别 11 或更高级别中的 {@link android.app.ActionBar} 已取代了该按钮的功能。因此,您可以使用以下代码为此按钮添加事件侦听器:

    + +
    +Button catButton = (Button) findViewById(R.id.categorybutton);
    +OnClickListener listener = /* create your listener here */;
    +if (catButton != null) {
    +    catButton.setOnClickListener(listener);
    +}
    +
    + + +

    根据当前布局做出响应

    + +

    有些操作可能会因当前的具体布局而产生不同的结果。例如,在新闻阅读器示例中,如果用户界面处于双面板模式下,那么点击标题列表中的标题就会在右侧面板中打开相应报道;但如果用户界面处于单面板模式下,那么上述操作就会启动一个独立活动:

    + +
    +@Override
    +public void onHeadlineSelected(int index) {
    +    mArtIndex = index;
    +    if (mIsDualPane) {
    +        /* display article on the right pane */
    +        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    +    } else {
    +        /* start a separate activity */
    +        Intent intent = new Intent(this, ArticleActivity.class);
    +        intent.putExtra("catIndex", mCatIndex);
    +        intent.putExtra("artIndex", index);
    +        startActivity(intent);
    +    }
    +}
    +
    + +

    同样,如果该应用处于双面板模式下,就应设置带导航标签的操作栏;但如果该应用处于单面板模式下,就应使用旋转窗口小部件设置导航栏。因此您的代码还应确定哪种情况比较合适:

    + +
    +final String CATEGORIES[] = { "热门报道", "政治", "经济", "Technology" };
    +
    +public void onCreate(Bundle savedInstanceState) {
    +    ....
    +    if (mIsDualPane) {
    +        /* use tabs for navigation */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
    +        int i;
    +        for (i = 0; i < CATEGORIES.length; i++) {
    +            actionBar.addTab(actionBar.newTab().setText(
    +                CATEGORIES[i]).setTabListener(handler));
    +        }
    +        actionBar.setSelectedNavigationItem(selTab);
    +    }
    +    else {
    +        /* use list navigation (spinner) */
    +        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
    +        SpinnerAdapter adap = new ArrayAdapter(this, 
    +                R.layout.headline_item, CATEGORIES);
    +        actionBar.setListNavigationCallbacks(adap, handler);
    +    }
    +}
    +
    + + +

    重复使用其他活动中的片段

    + +

    多屏幕设计中的重复模式是指,对于某些屏幕配置,已实施界面的一部分会用作面板;但对于其他配置,这部分就会以独立活动的形式存在。例如,在新闻阅读器示例中,对于较大的屏幕,新闻报道文本会显示在右侧面板中;但对于较小的屏幕,这些文本就会以独立活动的形式存在。

    + +

    在类似情况下,您通常可以在多个活动中重复使用相同的 {@link android.app.Fragment} 子类以避免代码重复。例如,您在双面板布局中使用了 ArticleFragment

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    然后又在小屏幕的活动布局中重复使用(无布局)了它 (ArticleActivity):

    + +
    +ArticleFragment frag = new ArticleFragment();
    +getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
    +
    + +

    当然,这与在 XML 布局中声明片段的效果是一样的,但在这种情况下却没必要使用 XML 布局,因为报道片段是此活动中的唯一组件。

    + +

    请务必在设计片段时注意,不要针对具体活动创建强耦合。要做到这一点,您通常可以定义一个界面,该界面概括了相关片段与其主活动交互所需的全部方式,然后让主活动实施该界面:

    + +

    例如,新闻阅读器应用的 HeadlinesFragment 会精确执行以下代码:

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    OnHeadlineSelectedListener mHeadlineSelectedListener = null;
    +
    +    /* Must be implemented by host activity */
    +    public interface OnHeadlineSelectedListener {
    +        public void onHeadlineSelected(int index);
    +    }
    +    ...
    +
    +    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
    +        mHeadlineSelectedListener = listener;
    +    }
    +}
    +
    + +

    然后,如果用户选择某个标题,相关片段就会通知由主活动指定的侦听器(而不是通知某个硬编码的具体活动):

    + +
    +public class HeadlinesFragment extends ListFragment {
    +    ...
    +    @Override
    +    public void onItemClick(AdapterView<?> parent, 
    +                            View view, int position, long id) {
    +        if (null != mHeadlineSelectedListener) {
    +            mHeadlineSelectedListener.onHeadlineSelected(position);
    +        }
    +    }
    +    ...
    +}
    +
    + +

    支持平板电脑和手持设备的指南中进一步介绍了此技术。

    + + +

    处理屏幕配置变化

    + +

    如果您使用独立活动实施界面的独立部分,那么请注意,您可能需要对特定配置变化(例如屏幕方向的变化)做出响应,以便保持界面的一致性。

    + +

    例如,在运行 Android 3.0 或更高版本的标准 7 英寸平板电脑上,如果新闻阅读器示例应用运行在纵向模式下,就会在使用独立活动显示新闻报道;但如果该应用运行在横向模式下,就会使用双面板布局。

    + +

    也就是说,如果用户处于纵向模式下且屏幕上显示的是用于阅读报道的活动,那么您就需要在检测到屏幕方向变化(变成横向模式)后执行相应操作,即停止上述活动并返回主活动,以便在双面板布局中显示相关内容:

    + +
    +public class ArticleActivity extends FragmentActivity {
    +    int mCatIndex, mArtIndex;
    +
    +    @Override
    +    protected void onCreate(Bundle savedInstanceState) {
    +        super.onCreate(savedInstanceState);
    +        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
    +        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
    +
    +        // If should be in two-pane mode, finish to return to main activity
    +        if (getResources().getBoolean(R.bool.has_two_panes)) {
    +            finish();
    +            return;
    +        }
    +        ...
    +}
    +
    + + diff --git a/docs/html/intl/zh-CN/training/multiscreen/index.jd b/docs/html/intl/zh-CN/training/multiscreen/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..35c48e066c24c09b0ddb95f5ffa3e6255ffd6b4d --- /dev/null +++ b/docs/html/intl/zh-CN/training/multiscreen/index.jd @@ -0,0 +1,64 @@ +page.title=针对多种屏幕进行设计 + +trainingnavtop=true +startpage=true +next.title=支持各种屏幕尺寸 +next.link=screensizes.html + +@jd:body + +
    +
    + +

    依存关系和前提条件

    + +
      +
    • Android 1.6 或更高版本(示例应用则需要 2.1 或更高版本)
    • +
    • 活动片段的基本知识
    • +
    • 构建 Android 用户界面的经验
    • +
    • 多个功能需要用到支持库
    • +
    + +

    您还应参阅

    + + + +

    试试看

    + +
    +下载示例应用 +

    NewsReader.zip

    +
    + +
    +
    + +

    Android 支持数百种屏幕尺寸不同的设备,包括小型手机和大型电视机。因此,请务必将您的应用设计为与所有的屏幕尺寸兼容,以便让尽可能多的用户使用该应用。

    + +

    不过,与各种类型的设备兼容还远远不够。由于各种屏幕尺寸对用户互动产生的利弊有所不同,因此要真正满足用户需求并广获好评,您的应用不仅需要支持多种屏幕,还应针对各类屏幕配置的用户体验进行优化。

    + +

    本教程将向您介绍如何针对多种屏幕配置优化和实施相应的用户界面。

    + +

    各教程中都提及了一种来自一个示例应用的代码,该应用展示了关于针对多种分辨率进行优化的最佳实践。您可以在右侧下载该示例,并在自己的应用内重复使用其中的代码。

    + +

    请注意:本教程和相关的示例使用了支持库,以便在 3.0 版以下的 Android 上使用 {@link android.app.Fragment} API。因此,您需要下载该库并将其添加到您的应用,才能使用本教程中涉及的所有 API。

    + + +

    教程

    + +
    +
    支持各种屏幕尺寸
    +
    本教程将向您介绍如何设计可适应多种屏幕尺寸的布局(使用灵活的视图尺寸、 {@link android.widget.RelativeLayout}、屏幕尺寸和屏幕方向限定符、别名过滤器以及自动拉伸位图)。
    + +
    支持各种屏幕密度
    +
    本教程将向您介绍如何支持具有不同像素密度的屏幕(使用非密度制约像素并提供各种密度的相应位图)。
    + +
    实施自适应用户界面流程
    +
    本教程将向您介绍如何以可适应多种屏幕尺寸/屏幕密度组合的方式实施用户界面流程(运行时对当前布局的检测,根据当前布局做出响应,处理屏幕配置变化)。
    +
    diff --git a/docs/html/intl/zh-CN/training/multiscreen/screendensities.jd b/docs/html/intl/zh-CN/training/multiscreen/screendensities.jd new file mode 100644 index 0000000000000000000000000000000000000000..cdb9b7fe54c6ab22d103af9876929ec16ba31ebe --- /dev/null +++ b/docs/html/intl/zh-CN/training/multiscreen/screendensities.jd @@ -0,0 +1,100 @@ +page.title=支持各种屏幕密度 +parent.title=针对多种屏幕进行设计 +parent.link=index.html + +trainingnavtop=true +previous.title=支持各种屏幕尺寸 +previous.link=screensizes.html +next.title=实施自适应用户界面流程 +next.link=adaptui.html + +@jd:body + + + +
    +
    + +

    本教程将指导您

    +
      +
    1. 使用非密度制约像素
    2. +
    3. 提供备用位图
    4. +
    + +

    您还应参阅

    + + + +

    试试看

    + +
    +下载示例应用 +

    NewsReader.zip

    +
    + + +
    +
    + +

    本教程将向您介绍如何通过提供不同资源和使用独立于分辨率的测量单位来支持不同屏幕密度。

    + +

    使用非密度制约像素

    + +

    在设计布局时,大家经常会误使用绝对像素来定义距离或尺寸,您一定要避免犯这种错误。由于各种屏幕的像素密度都有所不同,因此相同数量的像素在不同设备上的实际大小也有所差异,这样使用像素定义布局尺寸就会产生问题。因此,请务必使用 dpsp 单位指定尺寸。dp 是一种非密度制约像素,其尺寸与 160 dpi 像素的实际尺寸相同。sp 也是一种基本单位,但它可根据用户的偏好文字大小进行调整(即尺度独立性像素),因此您应将该测量单位用于定义文字大小(请勿用其定义布局尺寸)。

    + +

    例如,请使用 dp(而非 px)指定两个视图间的间距:

    + +
    +<Button android:layout_width="wrap_content" 
    +    android:layout_height="wrap_content" 
    +    android:text="@string/clickme"
    +    android:layout_marginTop="20dp" />
    +
    + +

    请务必使用 sp 指定文字大小:

    + +
    +<TextView android:layout_width="match_parent" 
    +    android:layout_height="wrap_content" 
    +    android:textSize="20sp" />
    +
    + + +

    提供备用位图

    + +

    由于 Android 可在具有各种屏幕密度的设备上运行,因此您提供的位图资源应始终可以满足各类普遍密度范围的要求:低密度、中等密度、高密度以及超高密度。这将有助于您的图形在所有屏幕密度上都能得到出色的质量和效果。

    + +

    要生成这些图片,您应先提取矢量格式的原始资源,然后根据以下尺寸范围针对各密度生成相应的图片。

    + +

      +
    • xhdpi:2.0 +
    • hdpi:1.5 +
    • mdpi:1.0(最低要求) +
    • ldpi:0.75 +

    + +

    也就是说,如果您为 xhdpi 设备生成了 200x200 尺寸的图片,就应该使用同一资源为 hdpimdpildpi 设备分别生成 150x150、100x100 和 75x75 尺寸的图片。

    + +

    然后,将生成的图片文件放在 res/ 下的相应子目录中(如下所示),系统就会根据运行您应用的设备的屏幕密度自动选择合适的图片:

    + +
    +MyProject/
    +  res/
    +    drawable-xhdpi/
    +        awesomeimage.png
    +    drawable-hdpi/
    +        awesomeimage.png
    +    drawable-mdpi/
    +        awesomeimage.png
    +    drawable-ldpi/
    +        awesomeimage.png
    +
    + +

    这样一来,无论您何时引用 @drawable/awesomeimage,系统都能根据相应屏幕的 dpi 选取合适的位图。

    + +

    有关为您的应用创建图标资产的更多提示和指南,请参阅图标设计指南

    + diff --git a/docs/html/intl/zh-CN/training/multiscreen/screensizes.jd b/docs/html/intl/zh-CN/training/multiscreen/screensizes.jd new file mode 100644 index 0000000000000000000000000000000000000000..904d09790a2100403371befe36c4318f57be7d99 --- /dev/null +++ b/docs/html/intl/zh-CN/training/multiscreen/screensizes.jd @@ -0,0 +1,279 @@ +page.title=支持各种屏幕尺寸 +parent.title=针对多种屏幕进行设计 +parent.link=index.html + +trainingnavtop=true +next.title=支持各种屏幕密度 +next.link=screendensities.html + +@jd:body + + + + + +

    此教程将向您介绍如何通过以下方法支持各种尺寸的屏幕:

    +
      +
    • 确保系统可以适当地调整您布局的尺寸以便适应屏幕
    • +
    • 根据屏幕配置提供合适的用户界面布局
    • +
    • 确保正确的布局应用到了正确的屏幕上
    • +
    • 提供可正确缩放的位图
    • +
    + + +

    使用“wrap_content”和“match_parent”

    + +

    要确保布局的灵活性并适应各种尺寸的屏幕,您应使用 "wrap_content""match_parent" 控制某些视图组件的宽度和高度。如果您使用 "wrap_content",系统就会将视图的宽度或高度设置成所需的最小尺寸以适应视图中的内容,而 "match_parent"(在低于 API 级别 8 的级别中称为 "fill_parent")则会展开组件以匹配其父视图的尺寸。

    + +

    如果使用 "wrap_content""match_parent" 尺寸值而不是硬编码的尺寸,您的视图就会相应地仅使用自身所需的空间或展开以填满可用空间。例如:

    + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    请注意示例中使用 "wrap_content""match_parent" 控制组件尺寸的方法,而不是关注具体的尺寸。此方法可让布局正确适应各种屏幕尺寸和屏幕方向。

    + +

    此视图在纵向模式和横向模式下的显示效果如下所示。请注意,组件的尺寸会自动适应屏幕的高度和宽度:

    + + +

    图 1。纵向模式(左)和横向模式(右)下的新闻阅读器示例应用。

    + + +

    使用相对布局

    + +

    您可以使用 {@link android.widget.LinearLayout} 的嵌套实例并结合 "wrap_content""match_parent" 尺寸,以便构建相当复杂的布局。不过,您无法通过 {@link android.widget.LinearLayout} 精确控制子视图的特殊关系;系统会将 {@link android.widget.LinearLayout} 中的视图直接并排列出。如果您需要将子视图排列出各种效果而不是一条直线,通常更合适的解决方法是使用 {@link android.widget.RelativeLayout},这样您就可以根据各组件之间的特殊关系指定布局了。例如,您可以将某个子视图对齐到屏幕左侧,同时将另一个视图对齐到屏幕右侧。

    + +

    例如:

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:layout_width="match_parent"
    +    android:layout_height="match_parent">
    +    <TextView
    +        android:id="@+id/label"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:text="Type here:"/>
    +    <EditText
    +        android:id="@+id/entry"
    +        android:layout_width="match_parent"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/label"/>
    +    <Button
    +        android:id="@+id/ok"
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_below="@id/entry"
    +        android:layout_alignParentRight="true"
    +        android:layout_marginLeft="10dp"
    +        android:text="OK" />
    +    <Button
    +        android:layout_width="wrap_content"
    +        android:layout_height="wrap_content"
    +        android:layout_toLeftOf="@id/ok"
    +        android:layout_alignTop="@id/ok"
    +        android:text="Cancel" />
    +</RelativeLayout>
    +
    + +

    图 2 展示的是此布局在 QVGA 屏幕上的显示效果。

    + + +

    图 2。QVGA 屏幕(小屏幕)上的截图。

    + +

    图 3 展示的是此布局在较大屏幕上的显示效果。

    + + +

    图 3。WSVGA 屏幕(大屏幕)上的截图。

    + +

    请注意,虽然组件的尺寸有所变化,但它们的空间关系仍会保留,具体由 {@link android.widget.RelativeLayout.LayoutParams} 指定。

    + + +

    使用尺寸限定符

    + +

    上文所述的灵活布局或相对布局可以为您带来的优势就只有这么多了。虽然这些布局可以拉伸组件内外的空间以适应各种屏幕,但它们不一定能为每种屏幕都提供最佳的用户体验。因此,您的应用不仅应实施灵活布局,还应针对各种屏幕配置提供一些备用布局。要做到这一点,您可以使用配置限定符,这样就可以在运行时根据当前的设备配置自动选择合适的资源了(例如根据各种屏幕尺寸选择不同的布局)。

    + +

    例如,很多应用会在较大的屏幕上实施“双面板”模式(相关应用可能会在一个面板上显示项目列表,并在另一面板上显示对应内容)。平板电脑和电视的屏幕已经大到可以同时容纳这两个面板了,但手机屏幕就需要分别显示。因此,您可以使用以下文件以便实施这些布局:

    + +
      +
    • res/layout/main.xml,单面板(默认)布局: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-large/main.xml,双面板布局: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    请注意第二种布局名称目录中的 large 限定符。系统会在属于较大屏幕(例如 7 英寸或更大的平板电脑)的设备上选择此布局。系统会在较小的屏幕上选择其他布局(无限定符)。

    + + +

    使用最小宽度限定符

    + +

    在版本低于 3.2 的 Android 设备上,开发人员遇到的问题之一是“较大”屏幕的尺寸范围,该问题会影响戴尔 Streak、早期的 Galaxy Tab 以及大部分 7 英寸平板电脑。即使这些设备的屏幕属于“较大”的尺寸,但很多应用可能会针对此类别中的各种设备(例如 5 英寸和 7 英寸的设备)显示不同的布局。这就是 Android 3.2 版在引入其他限定符的同时引入“最小宽度”限定符的原因。

    + +

    最小宽度限定符可让您通过指定某个最小宽度(以 dp 为单位)来定位屏幕。例如,标准 7 英寸平板电脑的最小宽度为 600 dp,因此如果您要在此类屏幕上的用户界面中使用双面板(但在较小的屏幕上只显示列表),您可以使用上文中所述的单面板和双面板这两种布局,但您应使用 sw600dp 指明双面板布局仅适用于最小宽度为 600 dp 的屏幕,而不是使用 large 尺寸限定符:

    + +
      +
    • res/layout/main.xml,单面板(默认)布局: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +
    • +
    • res/layout-sw600dp/main.xml,双面板布局: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +
    • +
    + +

    也就是说,对于最小宽度大于等于 600 dp 的设备,系统会选择 layout-sw600dp/main.xml(双面板)布局,否则系统就会选择 layout/main.xml(单面板)布局。

    + +

    但 Android 版本低于 3.2 的设备不支持此技术,原因是这些设备无法将 sw600dp 识别为尺寸限定符,因此您仍需使用 large 限定符。这样一来,就会有一个名称为 res/layout-large/main.xml 的文件(与 res/layout-sw600dp/main.xml 一样)。您将在下一教程中了解到避免此类布局文件出现重复的技术。

    + + +

    使用布局别名

    + +

    最小宽度限定符仅适用于 Android 3.2 及更高版本。因此,您仍需使用与较低版本兼容的概括尺寸范围(小、正常、大和特大)。例如,如果您要将用户界面设计成在手机上显示单面板,但在 7 英寸平板电脑、电视和其他较大的设备上显示多面板,请提供以下文件:

    + +

      +
    • res/layout/main.xml: 单面板布局
    • +
    • res/layout-large: 多面板布局
    • +
    • res/layout-sw600dp: 多面板布局
    • +

    + +

    后两个文件是相同的,因为其中一个用于和 Android 3.2 设备匹配,而另一个则是为使用较低版本 Android 的平板电脑和电视准备的。

    + +

    要避免平板电脑和电视的文件出现重复(以及由此带来的维护问题),您可以使用别名文件。例如,您可以定义以下布局:

    + +
      +
    • res/layout/main.xml,单面板布局
    • +
    • res/layout/main_twopanes.xml,双面板布局
    • +
    + +

    然后添加这两个文件:

    + +

      +
    • res/values-large/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      +
    • + +
    • res/values-sw600dp/layout.xml: +
      +<resources>
      +    <item name="main" type="layout">@layout/main_twopanes</item>
      +</resources>
      +
      + +
    • +

    + +

    后两个文件的内容相同,但它们并未实际定义布局。它们只是将 {@code main} 设置成了 {@code main_twopanes} 的别名。由于这些文件包含 largesw600dp 选择器,因此无论 Android 版本如何,系统都会将这些文件应用到平板电脑和电视上(版本低于 3.2 的平板电脑和电视会匹配 +{@code large},版本低于 3.2 的平板电脑和电视则会匹配 sw600dp)。

    + + +

    使用屏幕方向限定符

    + +

    某些布局会同时支持横向模式和纵向模式,但您可以通过调整优化其中大部分布局的效果。在新闻阅读器示例应用中,每种屏幕尺寸和屏幕方向下的布局行为方式如下所示:

    + +

      +
    • 小屏幕,纵向:单面板,带徽标
    • +
    • 小屏幕,横向:单面板,带徽标
    • +
    • 7 英寸平板电脑,纵向:单面板,带操作栏
    • +
    • 7 英寸平板电脑,横向:双面板,宽,带操作栏
    • +
    • 10 英寸平板电脑,纵向:双面板,窄,带操作栏
    • +
    • 10 英寸平板电脑,横向:双面板,宽,带操作栏
    • +
    • 电视,横向:双面板,宽,带操作栏
    • +

    + +

    因此,这些布局中的每一种都定义在了 res/layout/ 目录下的某个 XML 文件中。为了继续将每个布局分配给各种屏幕配置,该应用会使用布局别名将两者相匹配:

    + +

    res/layout/onepane.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} + +

    res/layout/onepane_with_bar.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +

    res/layout/twopanes.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +

    res/layout/twopanes_narrow.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all} + +

    既然您已定义了所有可能的布局,那就只需使用配置限定符将正确的布局映射到各种配置即可。您现在只需使用布局别名技术即可做到这一点:

    + +

    res/values/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all} + +

    res/values-sw600dp-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml +all} + +

    res/values-sw600dp-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml +all} + +

    res/values-large-land/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all} + +

    res/values-large-port/layouts.xml:

    +{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all} + + + +

    使用自动拉伸位图

    + +

    支持各种屏幕尺寸通常意味着您的图片资源还必须能适应各种尺寸。例如,无论要应用到什么形状的按钮上,按钮背景都必须能适应。

    + +

    如果在可以更改尺寸的组件上使用了简单的图片,您很快就会发现显示效果多少有些不太理想,因为系统会在运行时平均地拉伸或收缩您的图片。解决方法为使用自动拉伸位图,这是一种格式特殊的 PNG 文件,其中会指明可以拉伸以及不可以拉伸的区域。

    + +

    因此,如果设计的是用于尺寸可变的组件上的位图,请务必使用自动拉伸技术。要将某个位图转换成自动拉伸位图,您可以先准备好普通图片(图 4,放大了 4 倍以便清楚显示)。

    + + +

    图 4button.png

    + +

    然后通过 SDK 的 draw9patch 实用工具(位于 tools/ 目录中)运行该图片,您可以在该工具中绘制像素以标出要拉伸的区域以及左侧和顶部的边界。您还可以沿右侧和底部边界绘制像素以标出用于放置内容的区域,具体如图 5 所示。

    + + +

    图 5button.9.png

    + +

    请注意沿边界显示的黑色像素。顶部和左侧边界上的像素用于指定可以拉伸的图片区域,右侧和底部边界上的像素则用于指定放置内容的区域。

    + +

    另请注意 .9.png 的扩展名。您必须使用此扩展名,因为系统框架需要通过此扩展名确定相关图片是自动拉伸位图,而不是普通 PNG 图片。

    + +

    如果您将此背景应用到某个组件(通过设置 android:background="@drawable/button"),系统框架就会正确拉伸图片以适应按钮的尺寸,具体如图 6 中的各种尺寸所示。

    + + +

    图 6。在各种尺寸下使用 button.9.png 自动拉伸位图的按钮。

    + diff --git a/docs/html/legal.jd b/docs/html/legal.jd new file mode 100644 index 0000000000000000000000000000000000000000..575f01640eb4f8b0d7f0a7627c98e923d8a3d91b --- /dev/null +++ b/docs/html/legal.jd @@ -0,0 +1,129 @@ +page.title=Legal Notice +fullpage=1 +@jd:body + +
    + +

    Legal Notice

    + +

    Android is an open platform that's freely available to you as an app developer. You can +immediately download the Android SDK, develop apps, and distribute them to the world without any +registration or fees.

    + +

    Android is developed by Google Inc. and the Open Handset Alliance. We've made it available to you +as a development platform pursuant to our commitment to openness, freedom, and innovation in +mobile.

    + +

    To start developing apps for Android, download the free Android SDK.

    + + + +

    Android Brands

    + +

    The "Android" name and Android logo are trademarks of Google Inc. +You may not use the logo or the logo's custom typeface.

    + +

    You may use the word "Android" in a product name only as a descriptor, such as "for Android" +and the first instance should be followed by a TM symbol, "for Android™." In other +messaging, the word "Android" may be used in text as a descriptor, as long as it is followed by a +proper generic term (for example, "Android™ application"). Any use of the Android name +must include footer attribution in your communications: "Android is a trademark of Google Inc."

    + +

    The Android Robot logo can be used, reproduced, and modified freely +in marketing communications. Our standard color value for print is PMS 376C. Our online hex color is +#A4C639. The Android Robot logo is licensed under the terms of the Creative Commons Attribution license and any +use of it must be attributed as such.

    + +

    For more information about Android brands, see the Android Branding Guidelines.

    + + + +

    Web Site Content

    + +

    We are pleased to license the Android documentation and sample code on this web site under terms +that encourage you to take, modify, reuse, re-purpose, and remix the content as you see fit. The +documentation content on this web site is made available to you as part of the Android Open Source Project. This documentation, including any +code shown in it, is licensed under the Apache +2.0 license. All other content on this site, except the license documents themselves and as +otherwise noted, is licensed under the Creative Commons Attribution 2.5 license. +

    + +

    For more information about licenses provided for the content of this web site and the +restrictions for re-use, read the complete Content License.

    + +

    Your use of this site is subject to Google's Privacy +Policy & Terms of Service.

    + + + +

    Other Android Services

    + +

    Google provides other optional services for your Android apps that have their own legal terms and +restrictions. Such services include:

    + +
    +
    Eclipse Android Developer Tools Plugin
    +
    If you're developing apps with the Eclipse IDE, we offer a free plugin called the +Android Developer Tools (ADT) to speed up your +development and debugging. Certain code within the ADT plugin and other packages available +from the SDK Manager require that you agree to terms and conditions for use, reproduction and +distribution upon installation.
    + +
    Google Play
    +
    Google Play is a publicly available service through which you can distribute your apps for +Android-powered devices. Google Play not only makes your app available to millions of devices, but +also offers your app powerful services such as in-app billing and license verification. In order to +distribute your apps on Google Play and use the associated services, you must agree to the Developer +Distribution Agreement and acquire a valid Developer Account. +

    Developer Distribution +Agreement, Developer Program +Policies

    + +
    Google Maps API
    +
    The Android Maps APIs are a collection of services (including, but not limited to, the +MapView and MapActivity classes) that allow you to include +maps, geocoding, geolocation, and other content from Google and its content providers in your +Android +apps. If you want to develop an Android app that displays Google Maps data, you must agree +to the terms of service, register, and get an API Key. Registration is free. +

    Google Maps Android API Key Signup, Mobile Legal +Notices

    +
    + +
    Android Cloud to Device Messaging
    +
    Android Cloud to Device Messaging (C2DM) is a service that helps you send data from +your servers to your users' Android devices. The service provides a simple, lightweight +mechanism that your servers can use to tell your Android app to contact your server directly to +fetch updated app or user data. Before you can sign up for Android Cloud to Device Messaging, you +must agree to the terms of a legal agreement between you and Google. Registration is free. +

    Android Cloud to Device +Messaging Terms of Service

    +
    + +
    Android Backup Service
    +
    Android Backup Service is integrated with Android's data backup framework to perform data +backup and restore for most devices running Android 2.2 or greater, using Google servers and a +backup transport on the device. Before you can sign up for Android Backup Service, you +must agree to the terms of a legal agreement between you and Google. Registration is free. +

    Android Backup Service +Terms of Service

    +
    +
    + +

    Any and all other services available for Android but not documented on developer.android.com are subject to their own terms, as +documented on their respective web sites.

    + +
    \ No newline at end of file diff --git a/docs/html/license.jd b/docs/html/license.jd index 83cd4709102a9c8cca04b303aa95ef61c3e7baad..a9af038bd6963191cacc6aa39b57a80e806b7ce4 100644 --- a/docs/html/license.jd +++ b/docs/html/license.jd @@ -1,15 +1,13 @@ page.title=Content License -hide_license_footer=true +fullpage=1 @jd:body -
    -

    Content License

    - -

    For the purposes of licensing, the content of this site is divided +

    +

    Content License

    +

    For the purposes of licensing, the content of this web site is divided into two categories:

      -
    • Documentation content, found under the "Dev Guide" and "Reference" - tabs, including both static content 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
    @@ -31,6 +29,10 @@ is licensed under GPLv2 or other license. In those cases, the license covering the source code module will apply to the documentation extracted from it.

    +

    Third-party components of this site such as JavaScript libraries are included in the Android +Open Source Project under the licenses specified by their authors. For information about these +licenses, refer to the source files in the Android Open Source Project.

    +

    All other content on this site, except the license documents themselves and as otherwise noted, is licensed under the Creative Commons @@ -42,17 +44,18 @@ above. For content licensed under Creative Commons Attribution 2.5, we ask that you give proper attribution.

    -

    Terms of Use

    +

    Terms of Use

    We are pleased to license the Android documentation and sample code under terms that encourage you to take, modify, reuse, re-purpose, and remix the -content as you see fit. Except as noted in the Restrictions section below, you +content as you see fit. Except as noted in the Restrictions section +below, you are free to use the documentation content in your own creations. For example, you could quote the text in a book, cut-and-paste sections to your blog, record it as an audiobook for the visually impaired, or even translate it.

    -

    Restrictions

    +

    Restrictions

    • While the documentation itself is available to you under the Apache 2.0 @@ -60,9 +63,11 @@ license, note that proprietary trademarks and brand features are not included in that license.
    • Google's trademarks and other brand features (including the -ANDROID stylized typeface logo) are not included in the license. -Please see -Guidelines for Third Party Use of Google Brand Features for +Android stylized typeface logo) are not included +in the license. +Please see Android Branding Guidelines for information about this usage.
    • In some cases, a page may include content, such as an image, that is not @@ -76,9 +81,8 @@ slide decks that are not covered.
    • documentation is subject to the conditions detailed in the Apache 2.0 license.
    - -

    Attribution

    +

    Attribution

    Proper attribution is required when you reuse or create modified versions of content that appears on a page made available under the @@ -95,49 +99,47 @@ Creative Commons legal code. are producing the work. There are several typical ways in which this might apply:

    -

    Exact Reproductions

    +

    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:

    -
    +

    Portions of this page are reproduced from work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License. -

    +

    Also, please link back to the original source page so that readers can refer there for more information.

    -

    Modified Versions

    +

    Modified Versions

    If your online work shows modified text or images based on the content from this site, please include a paragraph at the bottom of your page that reads:

    -
    +

    Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License. -

    +

    Again, please link back to the original source page so that readers can refer there for more information. This is even more important when the content has been modified.

    -

    Other Media

    +

    Other Media

    If you produce non-hypertext works, such as books, audio, or video, we ask that you make a best effort to include a spoken or written attribution in the spirit of the messages above.

    -
    - - +
    diff --git a/docs/html/live/index.jd b/docs/html/live/index.jd index 3885725eb5c2a906148430c2d42864ac7346558b..972972713400e889de08f070c948e686a453ba3a 100644 --- a/docs/html/live/index.jd +++ b/docs/html/live/index.jd @@ -1,7 +1,8 @@ page.title=Live +fullpage=1 @jd:body -
    +

    Android Developers Live

    @@ -61,4 +62,4 @@ livecasts on YouTube and videos of past sessions or follow us on
    -
    +
    diff --git a/docs/html/mwc2010/index.html b/docs/html/mwc2010/index.html deleted file mode 100644 index c91386f910709e1c42dd66b4f0dd2746bc51309a..0000000000000000000000000000000000000000 --- a/docs/html/mwc2010/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - -Redirecting... - - - - - diff --git a/docs/html/offline.jd b/docs/html/offline.jd index edd8eb09dd2d5ed4e370183917e1a6b8b0fc6f7f..73da7799fdcc21a6a02cafa14aac0b62a7f16744 100644 --- a/docs/html/offline.jd +++ b/docs/html/offline.jd @@ -23,13 +23,13 @@ page.title=Welcome

    Get Started

    @@ -37,7 +37,7 @@ tools

    If you've downloaded the Android SDK for the first time

    -

    Follow the guide to Installing the Android SDK, which +

    Follow the guide to Installing the Android SDK, which will help you setup your development environment.

    If you've installed new SDK components using the Android SDK Manager

    diff --git a/docs/html/resources/articles/avoiding-memory-leaks.jd b/docs/html/resources/articles/avoiding-memory-leaks.jd deleted file mode 100644 index 395f5900979cb448f5a02fcd7dc6d7d90b990d0b..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/avoiding-memory-leaks.jd +++ /dev/null @@ -1,111 +0,0 @@ -page.title=Avoiding Memory Leaks -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -

    Android applications are, at least on the T-Mobile G1, limited -to 16 MB of heap. It's both a lot of memory for a phone and yet very -little for what some developers want to achieve. Even if you do not -plan on using all of this memory, you should use as little as possible -to let other applications run without getting them killed. The more -applications Android can keep in memory, the faster it will be for the -user to switch between his apps. As part of my job, I ran into memory -leaks issues in Android applications and they are most of the time due -to the same mistake: keeping a long-lived reference to a -{@link android.content.Context Context}.

    - -

    On Android, a Context is used for many operations - but mostly to load and access resources. This is why all the widgets -receive a Context parameter in their constructor. In a -regular Android application, you usually have two kinds of -Context, {@link android.app.Activity} and -{@link android.app.Application}. It's usually the first one that -the developer passes to classes and methods that need a Context:

    - -
    @Override
    -protected void onCreate(Bundle state) {
    -  super.onCreate(state);
    -  
    -  TextView label = new TextView(this);
    -  label.setText("Leaks are bad");
    -  
    -  setContentView(label);
    -}
    -
    - -

    This means that views have a reference to the entire activity and -therefore to anything your activity is holding onto; usually the entire -View hierarchy and all its resources. Therefore, if you leak the Context -("leak" meaning you keep a reference to it thus preventing the GC from -collecting it), you leak a lot of memory. Leaking an entire activity -can be really easy if you're not careful.

    - -

    When the screen orientation changes the system will, by default, -destroy the current activity and create a new one while preserving its -state. In doing so, Android will reload the application's UI from the -resources. Now imagine you wrote an application with a large bitmap -that you don't want to load on every rotation. The easiest way to keep -it around and not having to reload it on every rotation is to keep in a -static field:

    - -
    private static Drawable sBackground;
    -  
    -@Override
    -protected void onCreate(Bundle state) {
    -  super.onCreate(state);
    -  
    -  TextView label = new TextView(this);
    -  label.setText("Leaks are bad");
    -  
    -  if (sBackground == null) {
    -    sBackground = getDrawable(R.drawable.large_bitmap);
    -  }
    -  label.setBackgroundDrawable(sBackground);
    -  
    -  setContentView(label);
    -}
    -
    - -

    This code is very fast and also very wrong; it leaks the first activity -created upon the first screen orientation change. When a -{@link android.graphics.drawable.Drawable Drawable} is attached to a view, the view is set as a -{@link android.graphics.drawable.Drawable#setCallback(android.graphics.drawable.Drawable.Callback) callback} -on the drawable. In the code snippet above, this means the drawable has a -reference to the TextView which itself has a reference to the -activity (the Context) which in turns has references to -pretty much anything (depending on your code.)

    - -

    This example is one of the simplest cases of leaking the -Context and you can see how we worked around it in the -Home screen's source code -(look for the unbindDrawables() method) by setting the stored -drawables' callbacks to null when the activity is destroyed. Interestingly -enough, there are cases where you can create a chain of leaked contexts, -and they are bad. They make you run out of memory rather quickly.

    - -

    There are two easy ways to avoid context-related memory leaks. The most -obvious one is to avoid escaping the context outside of its own scope. The -example above showed the case of a static reference but inner classes and -their implicit reference to the outer class can be equally dangerous. The -second solution is to use the Application context. This -context will live as long as your application is alive and does not depend -on the activities life cycle. If you plan on keeping long-lived objects -that need a context, remember the application object. You can obtain it -easily by calling -{@link android.content.Context#getApplicationContext() Context.getApplicationContext()} -or {@link android.app.Activity#getApplication() Activity.getApplication()}.

    - -

    In summary, to avoid context-related memory leaks, remember the following:

    -
      -
    • Do not keep long-lived references to a context-activity (a reference -to an activity should have the same life cycle as the activity itself)
    • -
    • Try using the context-application instead of a context-activity
    • -
    • Avoid non-static inner classes in an activity if you don't control -their life cycle, use a static inner class and make a weak reference to -the activity inside. The solution to this issue is to use a static inner -class with a {@link java.lang.ref.WeakReference WeakReference} to the -outer class, as done in ViewRoot -and its W inner class for instance
    • -
    • A garbage collector is not an insurance against memory leaks
    • -
    diff --git a/docs/html/resources/articles/backward-compatibility.jd b/docs/html/resources/articles/backward-compatibility.jd deleted file mode 100644 index f96d587c006792c79a11dcd54590e7e2a8a7fd22..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/backward-compatibility.jd +++ /dev/null @@ -1,252 +0,0 @@ -page.title=Backward Compatibility for Applications -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -
    -
    - -

    See also

    -
      -
    1. Android API Levels
    2. -
    - -
    -
    - -

    A variety of Android-powered devices are now available to consumers from carriers -in geographies around the world. Across those devices, a range of Android -platform versions are in use, some running the latest version of the platform, -others running older versions. As a developer, you need to consider the approach -to backward compatibility that you will take in your application — do you -want to allow your application to run on all devices, or just those running the -latest software? In some cases it will be useful to employ the newer APIs on -devices that support them, while continuing to support older devices.

    - -

    Setting the minSdkVersion

    -

    If the use of a new API is integral to the application — perhaps you -need to record video using an API introduced in Android 1.5 (API Level 3) -— you should add a <android:minSdkVersion> - to the application's manifest, to ensure your app won't -be installed on older devices. For example, if your application depends on an -API introduced in API Level 3, you would specify "3" as the value of the minimum -SDK version:

    - -
      <manifest>
    -   ...
    -   <uses-sdk android:minSdkVersion="3" />
    -   ...
    -  </manifest>
    - -

    However, if you want to add a useful but non-essential feature, such as -popping up an on-screen keyboard even when a hardware keyboard is available, you -can write your program in a way that allows it to use the newer features without -failing on older devices.

    - -

    Using reflection

    - -

    Suppose there's a simple new call you want to use, like {@link -android.os.Debug#dumpHprofData(java.lang.String) -android.os.Debug.dumpHprofData(String filename)}. The {@link android.os.Debug} -class has existed since Android 1.0, but the method is new in Anroid 1.5 (API -Level 3). If you try to call it directly, your app will fail to run on devices -running Android 1.1 or earlier.

    - -

    The simplest way to call the method is through reflection. This requires -doing a one-time lookup and caching the result in a Method object. -Using the method is a matter of calling Method.invoke and un-boxing -the result. Consider the following:

    - -
    public class Reflect {
    -   private static Method mDebug_dumpHprofData;
    -
    -   static {
    -       initCompatibility();
    -   };
    -
    -   private static void initCompatibility() {
    -       try {
    -           mDebug_dumpHprofData = Debug.class.getMethod(
    -                   "dumpHprofData", new Class[] { String.class } );
    -           /* success, this is a newer device */
    -       } catch (NoSuchMethodException nsme) {
    -           /* failure, must be older device */
    -       }
    -   }
    -
    -   private static void dumpHprofData(String fileName) throws IOException {
    -       try {
    -           mDebug_dumpHprofData.invoke(null, fileName);
    -       } catch (InvocationTargetException ite) {
    -           /* unpack original exception when possible */
    -           Throwable cause = ite.getCause();
    -           if (cause instanceof IOException) {
    -               throw (IOException) cause;
    -           } else if (cause instanceof RuntimeException) {
    -               throw (RuntimeException) cause;
    -           } else if (cause instanceof Error) {
    -               throw (Error) cause;
    -           } else {
    -               /* unexpected checked exception; wrap and re-throw */
    -               throw new RuntimeException(ite);
    -           }
    -       } catch (IllegalAccessException ie) {
    -           System.err.println("unexpected " + ie);
    -       }
    -   }
    -
    -   public void fiddle() {
    -       if (mDebug_dumpHprofData != null) {
    -           /* feature is supported */
    -           try {
    -               dumpHprofData("/sdcard/dump.hprof");
    -           } catch (IOException ie) {
    -               System.err.println("dump failed!");
    -           }
    -       } else {
    -           /* feature not supported, do something else */
    -           System.out.println("dump not supported");
    -       }
    -   }
    -}
    - -

    This uses a static initializer to call initCompatibility, -which does the method lookup. If that succeeds, it uses a private -method with the same semantics as the original (arguments, return -value, checked exceptions) to do the call. The return value (if it had -one) and exception are unpacked and returned in a way that mimics the -original. The fiddle method demonstrates how the -application logic would choose to call the new API or do something -different based on the presence of the new method.

    - -

    For each additional method you want to call, you would add an additional -private Method field, field initializer, and call wrapper to the -class.

    - -

    This approach becomes a bit more complex when the method is declared in a -previously undefined class. It's also much slower to call -Method.invoke() than it is to call the method directly. These -issues can be mitigated by using a wrapper class.

    - -

    Using a wrapper class

    - -

    The idea is to create a class that wraps all of the new APIs exposed by a new -or existing class. Each method in the wrapper class just calls through to the -corresponding real method and returns the same result.

    - -

    If the target class and method exist, you get the same behavior you would get -by calling the class directly, with a small amount of overhead from the -additional method call. If the target class or method doesn't exist, the -initialization of the wrapper class fails, and your application knows that it -should avoid using the newer calls.

    - -

    Suppose this new class were added:

    public class NewClass {
    -   private static int mDiv = 1;
    -
    -   private int mMult;
    -
    -   public static void setGlobalDiv(int div) {
    -       mDiv = div;
    -   }
    -
    -   public NewClass(int mult) {
    -       mMult = mult;
    -   }
    -
    -   public int doStuff(int val) {
    -       return (val * mMult) / mDiv;
    -   }
    -}
    - -

    We would create a wrapper class for it:

    - -
    class WrapNewClass {
    -   private NewClass mInstance;
    -
    -   /* class initialization fails when this throws an exception */
    -   static {
    -       try {
    -           Class.forName("NewClass");
    -       } catch (Exception ex) {
    -           throw new RuntimeException(ex);
    -       }
    -   }
    -
    -   /* calling here forces class initialization */
    -   public static void checkAvailable() {}
    -
    -   public static void setGlobalDiv(int div) {
    -       NewClass.setGlobalDiv(div);
    -   }
    -
    -   public WrapNewClass(int mult) {
    -       mInstance = new NewClass(mult);
    -   }
    -
    -   public int doStuff(int val) {
    -       return mInstance.doStuff(val);
    -   }
    -}
    - -

    This has one method for each constructor and method in the original, plus a -static initializer that tests for the presence of the new class. If the new -class isn't available, initialization of WrapNewClass fails, -ensuring that the wrapper class can't be used inadvertently. The -checkAvailable method is used as a simple way to force class -initialization. We use it like this:

    - -
    public class MyApp {
    -   private static boolean mNewClassAvailable;
    -
    -   /* establish whether the "new" class is available to us */
    -   static {
    -       try {
    -           WrapNewClass.checkAvailable();
    -           mNewClassAvailable = true;
    -       } catch (Throwable t) {
    -           mNewClassAvailable = false;
    -       }
    -   }
    -
    -   public void diddle() {
    -       if (mNewClassAvailable) {
    -           WrapNewClass.setGlobalDiv(4);
    -           WrapNewClass wnc = new WrapNewClass(40);
    -           System.out.println("newer API is available - " + wnc.doStuff(10));
    -       } else {
    -           System.out.println("newer API not available");
    -       }
    -   }
    -}
    - -

    If the call to checkAvailable succeeds, we know the new class is -part of the system. If it fails, we know the class isn't there, and adjust our -expectations accordingly. It should be noted that the call to -checkAvailable will fail before it even starts if the bytecode -verifier decides that it doesn't want to accept a class that has references to a -nonexistent class. The way this code is structured, the end result is the same -whether the exception comes from the verifier or from the call to -Class.forName.

    - -

    When wrapping an existing class that now has new methods, you only need to -put the new methods in the wrapper class. Invoke the old methods directly. The -static initializer in WrapNewClass would be augmented to do a -one-time check with reflection.

    - -

    Testing is key

    - -

    You must test your application on every version of the Android framework that -is expected to support it. By definition, the behavior of your application will -be different on each. Remember the mantra: if you haven't tried it, it doesn't -work.

    - -

    You can test for backward compatibility by running your application in an -emulator that uses an older version of the platform. The Android SDK allows you -to do this easily by creating "Android Virtual Devices" with different API -levels. Once you create the AVDs, you can test your application with old and new -versions of the system, perhaps running them side-by-side to see the -differences. More information about emulator AVDs can be found in Creating and Managing Virtual Devices and -from emulator -help-virtual-device.

    \ No newline at end of file diff --git a/docs/html/resources/articles/can-i-use-this-intent.jd b/docs/html/resources/articles/can-i-use-this-intent.jd deleted file mode 100644 index 7787d31e39cae943a8a69a773f238d3aca2a6c71..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/can-i-use-this-intent.jd +++ /dev/null @@ -1,71 +0,0 @@ -page.title=Can I Use this Intent? -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Android offers a very powerful and yet easy-to-use message type called -an intents. -You can use intents to turn applications into high-level libraries and -make code modular and reusable. The Android Home screen and AnyCut -applications, for instance, use intents extensively to create shortcuts.

    - -

    While it is nice to be able to make use of a loosely coupled -API, there is no guarantee that the intent you send will be received by -another application. This happens in particular with third-party apps, like -Panoramio -and its RADAR intent.

    - -

    This article describes a technique you can use to find out whether the system -contains any application capable of responding to the intent you want to use. -The example below shows a helper method that queries the system package manager -to determine whether there's an app that can respond to a specified intent. Your -application can pass an intent to the method and then, for example, show or hide -user options that the user would normally use to trigger the intent.

    - -
    /**
    - * Indicates whether the specified action can be used as an intent. This
    - * method queries the package manager for installed packages that can
    - * respond to an intent with the specified action. If no suitable package is
    - * found, this method returns false.
    - *
    - * @param context The application's environment.
    - * @param action The Intent action to check for availability.
    - *
    - * @return True if an Intent with the specified action can be sent and
    - *         responded to, false otherwise.
    - */
    -public static boolean isIntentAvailable(Context context, String action) {
    -    final PackageManager packageManager = context.getPackageManager();
    -    final Intent intent = new Intent(action);
    -    List<ResolveInfo> list =
    -            packageManager.queryIntentActivities(intent,
    -                    PackageManager.MATCH_DEFAULT_ONLY);
    -    return list.size() > 0;
    -}
    -
    - -

    Here is how you could use the helper method:

    - -
    @Override
    -public boolean onPrepareOptionsMenu(Menu menu) {
    -    final boolean scanAvailable = isIntentAvailable(this,
    -        "com.google.zxing.client.android.SCAN");
    -
    -    MenuItem item;
    -    item = menu.findItem(R.id.menu_item_add);
    -    item.setEnabled(scanAvailable);
    -
    -    return super.onPrepareOptionsMenu(menu);
    -}
    -
    - -

    In this example, the menu is grayed out if the Barcode Scanner -application is not installed.

    - -

    Another, simpler, way to do this is to catch the -ActivityNotFoundException when calling startActivity() -but it only lets you react to the problem, you cannot predict it and update the -UI accordingly to prevent the user from doing something that won't work. The -technique described here can also be used at startup time to ask the user -whether he'd like to install the missing package, you can then simply redirect -him to Google Play by using the appropriate URI.

    \ No newline at end of file diff --git a/docs/html/resources/articles/contacts.jd b/docs/html/resources/articles/contacts.jd deleted file mode 100644 index 374587b284a5c06a1b7450a88850bbc9adda226e..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/contacts.jd +++ /dev/null @@ -1,424 +0,0 @@ -page.title=Using the Contacts API -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Starting from Android 2.0 (API Level 5), the Android platform provides an -improved Contacts API for managing and integrating contacts from multiple -accounts and from other data sources. To handle overlapping data from multiple -sources, the contacts content provider aggregates similar contacts and presents -them to users as a single entity. This article describes how to use the new API -to manage contacts.

    - -

    The new Contacts API is defined in the -{@link android.provider.ContactsContract android.provider.ContactsContract} -and related classes. The older API is still supported, although deprecated. -If you have an existing application that uses the older API, -see Considerations for legacy apps, below, for ideas -on how to support the Contacts API in your app.

    - -

    If you'd like to look at an applied example of how to use the new Contacts -API, including how to support both the new and older API in a single app, -please see the Business Card -sample application.

    - -

    Data structure of Contacts

    - -

    In the new Contacts API, data is laid out in three primary tables: -contacts, raw contacts, and data, a structure that -is slightly different from that used in the older API. The new structure -allows the system to more easily store and manage information for a -specific contact from multiple contacts sources.

    - - - -
      -
    • Data is a generic table that stores all of the data points -associated with a raw contact. Each row stores data of a specific kind — -for example name, photo, email addresses, phone numbers, and group memberships. -Each row is tagged with a MIME type to identify what type of data it can -contain, across the entire column. Columns are generic and the type of data they -contain is determined by the kind of data stored in each row. For example, if a -row's data kind is Phone.CONTENT_ITEM_TYPE, then the first column -stores the phone number, but if the data kind is -Email.CONTENT_ITEM_TYPE, then the column stores the email address. - -

      The {@link android.provider.ContactsContract.CommonDataKinds ContactsContract.CommonDataKinds} -class provides subclasses corresponding to common MIME types for contacts data. -If needed, your application or other contacts sources can define additional MIME -types for data rows. For more information about the Data table and examples of -how to use it, see {@link android.provider.ContactsContract.Data android.provider.ContactsContract.Data}.

    • - -
    • A row in the RawContacts table represents the set of -Data and other information describing a person and associated with -a single contacts source. For example, a row might define the data associated -with a person's Google or Exchange account or Facebook friend. For more -information, see -{@link android.provider.ContactsContract.RawContacts ContactsContract.RawContacts}.

      - -
    • A row in the Contacts table represents an aggregate of one or -more RawContacts describing the same person (or entity). - -

      As mentioned above, the Contacts content provider automatically aggregates -Raw Contacts into a single Contact entry, where possible, since common data -fields (such as name or email address) are likely to be stored in each raw -contact. Since the aggregation logic maintains the entries in the Contact rows, -the entries can be read but should not be modified. See the section Aggregation of contacts, below, for more details, -including and information on how to -control aggregation.

    • - -
    - -

    When displaying contacts to users, applications should typically operate on -the Contacts level, since it provides a unified, aggregated view of contacts -from various underlying sources.

    - -

    Example: Inserting a Phone Number

    - -

    To insert a phone number using the new APIs you'll need the ID of the Raw -Contact to attach the phone number to, then you'll need to create a Data -row:

    - -
    import android.provider.ContactsContract.CommonDataKinds.Phone;
    -...
    -ContentValues values = new ContentValues();
    -values.put(Phone.RAW_CONTACT_ID, rawContactId);
    -values.put(Phone.NUMBER, phoneNumber);
    -values.put(Phone.TYPE, Phone.TYPE_MOBILE);
    -Uri uri = getContentResolver().insert(Phone.CONTENT_URI, values);
    - - -

    Aggregation of contacts

    - -

    When users sync contacts from multiple sources, several contacts might refer -to the same person or entity, but with slightly different (or overlapping) data. - For example, "Bob Parr" might be a user's co-worker and also his personal -friend, so the user might have his contact information stored in both a -corporate email account and a personal account. To provide a simplified view for -the user, the system locates such overlapping contacts and combines them into a -single, aggregate contact.

    - -

    The system automatically aggregates contacts by default. However, if needed, -your application can control how the system handles aggregation or it can -disable aggregation altogether, as described in the sections below.

    - -

    Automatic aggregation

    - -

    When a raw contact is added or modified, the system looks for matching -(overlapping) raw contacts with which to aggregate it. It may not find any -matching raw contacts, in which case it will create an aggregate contact that -contains just the original raw contact. If it finds a single match, it creates a -new contact that contains the two raw contacts. And it may even find multiple -similar raw contacts, in which case it chooses the closest match.

    - -

    Two raw contacts are considered to be a match if at least one of these -conditions is met:

    - -
      -
    • They have matching names.
    • -
    • Their names consist of the same words but in different order -(for example, "Bob Parr" and "Parr, Bob")
    • -
    • One of them has a common short name for the other (for example, -"Bob Parr" and "Robert Parr")
    • -
    • One of them has just a first or last name and it matches the other -raw contact. This rule is less reliable, so it only applies if the two -raw contacts are also sharing some other data like a phone number, an -email address or a nickname (for example, Helen ["elastigirl"] = Helen -Parr ["elastigirl"])
    • -
    • At least one of the two raw contacts is missing the name altogether -and they are sharing a phone number, an email address or a nickname (for -example, Bob Parr [incredible@android.com] = incredible@android.com).
    • -
    - -

    When comparing names, the system ignores upper/lower case differences -(Bob=BOB=bob) and diacritical marks (Hélène=Helene). When comparing two -phone numbers the system ignores special characters such as "*", "#", -"(", ")", and whitespace. Also if the only difference between two numbers -is that one has a country code and the other does not, then the system -considers those to be a match (except for numbers in the Japan country code).

    - -

    Automatic aggregation is not permanent; any change of a constituent raw -contact may create a new aggregate or break up an existing one.

    - -

    Explicit aggregation

    - -

    In some cases, the system's automatic aggregation may not meet the -requirements of your application or sync adapter. There are two sets of APIs you -can use to control aggregation explicitly: aggregation modes allow you -to control automatic aggregation behaviors and aggregation exceptions -allow you to override automated aggregation entirely. - -

    Aggregation modes

    - -

    You can set an aggregation mode for each raw contact individually. To do so, -add a mode constant as the value of the AGGREGATION_MODE column in -the RawContact row. The mode constants available include:

    - -
      -
    • AGGREGATION_MODE_DEFAULT — normal mode, automatic -aggregation is allowed.
    • -
    • AGGREGATION_MODE_DISABLED — automatic aggregation is not -allowed. The raw contact will not be aggregated.
    • -
    • AGGREGATION_MODE_SUSPENDED — automatic aggregation is -deactivated. If the raw contact is already a part of an aggregated contact when -aggregation mode changes to suspended, it will remain in the aggregate, even if -it changes in such a way that it no longer matches the other raw contacts in the -aggregate.
    • -
    - -

    Aggregation exceptions

    - -

    To keep two raw contacts unconditionally together or unconditionally apart, -you can add a row to the -{@link android.provider.ContactsContract.AggregationExceptions} table. Exceptions -defined in the table override all automatic aggregation rules.

    - - -

    Loookup URI

    - -

    The new Contacts API introduces the notion of a lookup key for a contact. If -your application needs to maintain references to contacts, you should use lookup -keys instead of the traditional row ids. You can acquire a lookup key from the -contact itself, it is a column on the -{@link android.provider.ContactsContract.Contacts} table. Once you have a lookup key, -you can construct a URI in this way:

    - -
    Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey)
    - -

    and use it like you would use a traditional content URI, for example:

    - -
    Cursor c = getContentResolver().query(lookupUri, new String[]{Contacts.DISPLAY_NAME}, ...);
    -try {
    -    c.moveToFirst();
    -    String displayName = c.getString(0);
    -} finally {
    -    c.close();
    -}
    - -

    The reason for this complication is that regular contact row IDs are -inherently volatile. Let's say your app stored a long ID of a contact. Then the -user goes and manually joins the contact with some other contact. Now there is a -single contact where there used to be two, and the stored long contact ID points -nowhere. - -

    The lookup key helps resolve the contact in this case. The key is a string -that concatenates the server-side identities of the raw contacts. Your -application can use that string to find a contact, regardless whether the raw -contact is aggregated with others or not.

    - -

    If performance is a concern for your application, you might want to store -both the lookup and the long ID of a contact and construct a lookup URI out of -both IDs, as shown here:

    - -
    Uri lookupUri = getLookupUri(contactId, lookupKey)
    - -

    When both IDs are present in the URI, the system will try to use the long ID -first. That is a very quick query. If the contact is not found, or if the one -that is found has the wrong lookup key, the content provider will parse the -lookup key and track down the constituent raw contacts. If your app -bulk-processes contacts, you should maintain both IDs. If your app works with a -single contact per user action, you probably don't need to bother with storing -the long ID.

    - -Android itself uses lookup URIs whenever there is a need to reference a contact, -such as with shortcuts or Quick Contact, and also during editing or even viewing -a contact. The latter case is less obvious — why would a contact ID change -while we are simply viewing the contact? It could change because there might be -a sync going in the background, and the contact might get automatically -aggregated with another while being viewed.

    - -

    In summary: whenever you need to reference a contact, we recommend that you -do so by its lookup URI.

    - - -

    Considerations for legacy applications

    - -

    If you have an existing application that uses the older Contacts API, -you should consider upgrading it to use the new API. You have four options:

    - -
      -
    • Leave it as-is and rely on the Contacts compatibility mode.
    • -
    • Upgrade the app and discontinue support of pre-Android 2.0 platforms.
    • -
    • Build a new version of the app for the new API, while keeping the old version available.
    • -
    • Make the app use the right set of APIs depending on the platform where it is deployed.
    • -
    - -

    Let's consider these options one by one.

    - -

    Using compatibility mode

    - -

    Compatibility mode is the easiest option because you just leave the -application as is, and it should run on Android 2.0 as long as it only uses -public APIs. A couple examples of the use of non-public API include the use of -explicit table names in nested queries and the use of columns that were not -declared as public constants in the {@link android.provider.Contacts} class. -

    - -

    Even if the application currently runs, you don't want to leave it like this -for long. The main reason is that it will only have access to contacts from one -account, namely the first Google account on the device. If the user opens other -accounts in addition to or instead of a Google account, your application will -not be able to access those contacts.

    - - -

    Upgrading to the new API and dropping support for older platforms

    - -

    If your application will no longer target platforms older than -Android 2.0, you can upgrade to the new API in this way:

    - -
      -
    • Replace all usages of {@link android.provider.Contacts} with calls to new -API. After you are done, you should not see any deprecation warnings during -application build. The new application will be able to take full advantage of -multiple accounts and other new features of Android 2.0.

      - -
    • In the application's manifest, update (or add) the -android:minSdkVersion attribute to the -<uses-sdk> element. To use the new Contacts API, you should -set the value of the attribute to "5" (or higher, as appropriate). For more -information about android:minSdkVersion, see the documentation for -the <uses-sdk> -element. For more information about the value of the -minSdkVersion, see API Levels.
    • -
    - -

    Maintaining two applications

    - -

    You may decide to have two different applications: one for pre-Android 2.0 -platforms and one for Android 2.0 and beyond. If so, here's what you'll need to do:

    - -
      -
    • Clone your existing app.
    • -
    • Change the old application:
    • -
        -
      • At launch time, check the version of the SDK. The version of the SDK -is available as {@link android.os.Build.VERSION#SDK android.os.Build.VERSION.SDK}.
      • -
      • If the SDK version is greater or equal to 5 (Android 2.0), show a dialog -suggesting to the user that it's time to go to Google Play and find a new version of -the app. You can even provide a link to the new app on Google Play (see Using Intents -to Launch Google Play).
      • -
      -
    • Change the new application:
    • -
        -
      • Replace all usages of the older Contacts API with calls to new API. -The new application will be able to take full advantage of multiple accounts -and other new features of Android 2.0.
      • -
      • Modify that application's AndroidManifest.xml file:
      • -
          -
        • Give the application a new name and a new package name. Currently -Google Play does not allow you to have two applications with the same -name/package.
        • -
        • Update (or add) the android:minSdkVersion attribute -to the <uses-sdk> element. To use the new Contacts API, -you should set the value of the attribute to "5" (or higher, as appropriate).
        • -
        -
      -
    • Publish both apps on Google Play, the old app one as an upgrade and the -other as new. Make sure to explain the difference between the apps in their -descriptions.
    • -
    - -

    This plan has its disadvantages:

    - -
      -
    • The new application will not be able to read the old application's data. -Application data can only be accessed by code living in the same package. So -databases, shared preferences, and so on, will need to be populated from -scratch.
    • -
    • The upgrade process is too clunky for the user. Some users may choose -to either stay with the crippled old version or uninstall altogether.
    • -
    - -

    Supporting the old and new APIs in the same application

    - -

    This is a bit tricky, but the result is worth the effort. You can -build a single package that will work on any platform:

    - -

    Go through the existing application and factor out all access to -{@link android.provider.Contacts} into one class, such as ContactAccessorOldApi. -For example, if you have code like this: - -

        protected void pickContact() {
    -        startActivityForResult(new Intent(Intent.ACTION_PICK, People.CONTENT_URI), 0);
    -    }
    - -

    it will change to:

    - - -
        private final ContactAccessorOldApi mContactAccessor = new ContactAccessorOldApi();
    -
    -    void pickContact() {
    -        startActivityForResult(mContactAccessor.getContactPickerIntent(), 0);
    -    }
    - -

    The corresponding method on ContactAccessorOldApi will look like this:

    - -
        public Intent getContactPickerIntent() {
    -        return new Intent(Intent.ACTION_PICK, People.CONTENT_URI);
    -    }
    - -

    Once you are done, you should see deprecation warnings coming only -from ContactAccessorOldApi.

    - -

    Create a new abstract class ContactAccessor, make sure the abstract -class has all method signatures from ContactAccessorOldApi. Make -ContactAccessorOldApi extend ContactAccessor:

    - -
        public abstract class ContactAccessor {
    -        public abstract Intent getContactPickerIntent();
    -        ...
    -    }
    - -

    Create a new subclass of ContactAccessor, ContactAccessorNewApi and -implement all methods using the new API:

    - -
        public class ContactAccessorNewApi extends ContactAccessor {    
    -        @Override
    -        public Intent getContactPickerIntent() {
    -            return new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
    -        }
    -        ...
    -    }
    - -

    At this point, you have two implementations of the same API, one using the -old API and another using the new API. Let's plug them in. Add this code to -the ContactAccessor class:

    - -
        private static ContactAccessor sInstance;
    -
    -    public static ContactAccessor getInstance() {
    -        if (sInstance == null) {
    -            String className;
    -            int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
    -            if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
    -                className = "ContactAccessorOldApi";
    -            } else {
    -                className = "ContactAccessorNewApi";
    -            }
    -            try {
    -                Class<? extends ContactAccessor> clazz =
    -                        Class.forName(ContactAccessor.class.getPackage() + "." + className)
    -                                .asSubclass(ContactAccessor.class);
    -                sInstance = clazz.newInstance();
    -            } catch (Exception e) {
    -                throw new IllegalStateException(e);
    -            }
    -        }
    -        return sInstance;
    -    }
    - -

    Now replace references to ContactsAccessorOldApi with references to -ContactsAccessor:

    - -
        private final ContactAccessor mContactAccessor = ContactAccessor.getInstance();
    - -

    You are done! Now you will want to test on Android 2.0, 1.6 and 1.5.

    - -

    We hope you like the new features and APIs we've added to Contacts in -Android 2.0, and we can't wait to see what cool things developers do with -the new APIs.

    diff --git a/docs/html/resources/articles/drawable-mutations.jd b/docs/html/resources/articles/drawable-mutations.jd deleted file mode 100644 index c5818fcbafb9d7b2db1e7c2376993602bf2de6d1..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/drawable-mutations.jd +++ /dev/null @@ -1,93 +0,0 @@ -page.title=Drawable Mutations -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Android's drawables are extremely useful to easily build applications. A -{@link android.graphics.drawable.Drawable Drawable} is a pluggable drawing -container that is usually associated with a View. For instance, a -{@link android.graphics.drawable.BitmapDrawable BitmapDrawable} is used to display -images, a {@link android.graphics.drawable.ShapeDrawable ShapeDrawable} to draw -shapes and gradients, and so on. You can even combine them to create complex -renderings.

    - -

    Drawables allow you to easily customize the rendering of the widgets without -subclassing them. As a matter of fact, they are so convenient that most of the -default Android apps and widgets are built using drawables; there are about 700 -drawables used in the core Android framework. Because drawables are used so -extensively throughout the system, Android optimizes them when they are loaded -from resources. For instance, every time you create a -{@link android.widget.Button Button}, a new drawable is loaded from the framework -resources (android.R.drawable.btn_default). This means all buttons -across all the apps use a different drawable instance as their background. -However, all these drawables share a common state, called the "constant state." -The content of this state varies according to the type of drawable you are -using, but it usually contains all the properties that can be defined by a -resource. In the case of a button, the constant state contains a bitmap image. -This way, all buttons across all applications share the same bitmap, which saves -a lot of memory.

    - -

    The following diagram shows what entities are -created when you assign the same image resource as the background of -two different views. As you can see, two drawables are created but they -both share the same constant state, hence the same bitmap:

    - - - -

    This state sharing feature is great to avoid wasting memory but it can cause -problems when you try to modify the properties of a drawable. Imagine an -application with a list of books. Each book has a star next to its name, totally -opaque when the user marks the book as a favorite, and translucent when the book -is not a favorite. To achieve this effect, you would probably write the -following code in your list adapter's getView() method:

    - -
    Book book = ...;
    -TextView listItem = ...;
    -
    -listItem.setText(book.getTitle());
    -
    -Drawable star = context.getResources().getDrawable(R.drawable.star);
    -if (book.isFavorite()) {
    -  star.setAlpha(255); // opaque
    -} else {
    -  star.setAlpha(70); // translucent
    -}
    - -

    Unfortunately, this piece of code yields a rather strange result: -all of the drawables have the same opacity:

    - - - -

    This -result is explained by the constant state. Even though we are getting a -new drawable instance for each list item, the constant state remains -the same and, in the case of BitmapDrawable, the opacity is part of the -constant state. Thus, changing the opacity of one drawable instance -changes the opacity of all the other instances. Even worse, working -around this issue was not easy with Android 1.0 and 1.1.

    - -

    Android 1.5 and higher offers a very easy way to solve this issue -with the new {@link android.graphics.drawable.Drawable#mutate()} method. -When you invoke this method on a drawable, the constant state of the -drawable is duplicated to allow you to change any property without -affecting other drawables. Note that bitmaps are still shared, even -after mutating a drawable. The diagram below shows what happens when -you invoke mutate() on a drawable:

    - - - -

    Let's update our previous piece of code to make use of mutate():

    - -
    Drawable star = context.getResources().getDrawable(R.drawable.star);
    -if (book.isFavorite()) {
    -  star.mutate().setAlpha(255); // opaque
    -} else {
    -  star. mutate().setAlpha(70); // translucent
    -}
    - -

    For convenience, mutate() -returns the drawable itself, which allows to chain method calls. It -does not however create a new drawable instance. With this new piece of -code, our application now behaves correctly:

    - - diff --git a/docs/html/resources/articles/faster-screen-orientation-change.jd b/docs/html/resources/articles/faster-screen-orientation-change.jd deleted file mode 100644 index e7b73bf2d6aed4419450229376123d57959065ab..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/faster-screen-orientation-change.jd +++ /dev/null @@ -1,133 +0,0 @@ -page.title=Faster Screen Orientation Change -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -
    -
    - -

    See also

    -
      -
    1. Handling Runtime -Changes
    2. -
    - -
    -
    - -

    Android is designed to run efficiently on a wide -array of devices, with very different hardware configurations. Some -devices, like the T-Mobile G1, can change their hardware configuration -at runtime. For instance, when you open the keyboard, the screen change -from the portrait orientation to the landscape orientation. - -

    - -

    To make -Android app development easier, the Android system automatically handles -configuration change events and restarts the current activity with the new -configuration. This is the default behavior that lets you declare -resources like layouts and drawables based on the orientation, screen -size, locale, etc.

    - -

    While this behavior is really powerful, since your application adapts -automatically to the device's configuration at runtime, it is sometimes -confusing for new Android developers, who wonder why their activity is -destroyed and recreated.

    - -

    Facing this "issue," some developers choose to handle configuration changes -themselves which is, in general, a short-term solution that will only complicate -their lives later. On the other hand, the system's automatic resource handling -is a very efficient and easy way to adapt an application's user interface to -various devices and devices configurations. It sometimes comes at a price, -though.

    - -

    When your application displays a lot of data, or data that is expensive to fetch, -the automatic destruction/creation of the activities can be lead to a -painful user experience. Take the example of Photostream, -a simple Flickr browsing application. After you launch the application and choose a Flickr account, the -application downloads a set of 6 photos (on a T-Mobile G1) from the -Flickr servers and displays them on screen. To improve the user -experience, the application uses slightly different layouts and drawables in -portrait and landscape modes and this is what the result looks like:

    - -

    - -

    - -

    Photostream lets Android take care of the configuration change when the -screen is rotated. However, can you imagine how painful it would be for the user -to see all the images being downloaded again? The obvious solution to this -problem is to temporarily cache the images. They could be cached on the SD card -(if there's one), in the Application object, in a static field, etc. None of -these techniques is adapted to the current situation: why should we bother -caching the images when the screen is not rotated? Fortunately for us, Android -offers a great API exactly for that purpose.

    - -

    The Activity class has a special method called -{@link android.app.Activity#onRetainNonConfigurationInstance()}. This method -can be used to pass an arbitrary object to your future self and Android -is smart enough to call this method only when needed. In the case of Photostream, -the application used this method -to pass the downloaded images to the future activity on orientation change. -The implementation can be summarized like so:

    - -
    @Override
    -public Object onRetainNonConfigurationInstance() {
    -    final LoadedPhoto[] list = new LoadedPhoto[numberOfPhotos];
    -    keepPhotos(list);
    -    return list;
    -}
    -
    - -

    In the new activity, in onCreate(), all you have to do to -get your object back is to call {@link android.app.Activity#getLastNonConfigurationInstance()}. -In Photostream, this method is invoked -and if the returned value is not null, the grid is loaded with the list of -photos from the previous activity:

    - -
    private void loadPhotos() {
    -    final Object data = getLastNonConfigurationInstance();
    -    
    -    // The activity is starting for the first time, load the photos from Flickr
    -    if (data == null) {
    -        mTask = new GetPhotoListTask().execute(mCurrentPage);
    -    } else {
    -        // The activity was destroyed/created automatically, populate the grid
    -        // of photos with the images loaded by the previous activity
    -        final LoadedPhoto[] photos = (LoadedPhoto[]) data;
    -        for (LoadedPhoto photo : photos) {
    -            addPhoto(photo);
    -        }
    -    }
    -}
    -
    - -

    Be very careful with the object you pass through -onRetainNonConfigurationChange(), though. If the object you -pass is for some reason tied to the Activity/Context, you will leak -all the views and resources of the activity. This means you should -never pass a View, a Drawable, an Adapter, etc. Photostream for -instance extracts the bitmaps from the drawables and pass the bitmaps -only, not the drawables. Finally, remember that -onRetainNonConfigurationChange() should be used only to retain -data that is expensive to load. Otherwise, keep it simple and let Android -do everything.

    - -

    Also read the guide to Handling Runtime -Changes.

    diff --git a/docs/html/resources/articles/future-proofing.jd b/docs/html/resources/articles/future-proofing.jd deleted file mode 100644 index b8aeedf1794ab70c3e2e366cc0418d53da86285e..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/future-proofing.jd +++ /dev/null @@ -1,91 +0,0 @@ -page.title=Future-Proofing Your Apps -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    It's important to implement your application so that it will not break as new -versions of the Android platform are loaded onto the users device. The list -below is based on our observations of five ways that we've seen bad apps fail. -You can think of these as "anti-patterns" (that is, techniques to avoid) for -Android development.

    - -

    If your application uses any of the dubious techniques below, break out -your IDE and duct tape, spackle, and patch up the app.

    - -

    Technique to Avoid, #1: Using Internal APIs

    - -

    Even -though we've always strongly advised against doing so, some developers -have chosen to use unsupported or internal APIs. For instance, many -developers are using the internal brightness control and bluetooth -toggle APIs that were present in 1.0 and 1.1. A bug -- which was -fixed in Android 1.5 -- allowed apps to use those APIs without -requesting permission. As a result, apps that used those APIs broke -on 1.5. If you've used internal APIs in your apps, you need to update -your apps to stop doing so.

    - -

    Technique to Avoid, #2: Directly Manipulating Settings

    - -

    Strictly speaking this one isn't evil, since this is a change in -behavior that we made to Android itself. But we made it because some -developers were doing naughty things: a number of apps were changing -system settings silently without even notifying the user. For instance, -some apps turn on GPS without asking the user, and others might turn on -data roaming.

    - -

    As a result, applications can no longer directly -manipulate the values of certain system Settings, even if they -previously had permission to do so. For instance, apps can no longer -directly turn on or off GPS. These apps won't crash, but the APIs in -question now have no effect, and do nothing. Instead, apps will need to -issue an Intent to launch the appropriate Settings configuration -screen, so that the user can change these settings manually. For -details, see the android.provider.Settings.Secure class, which you can -find in the 1.5_pre SDK documentation (and later). Note that only -Settings that were moved to the Settings.Secure class are affected. -Other, less sensitive, settings will continue to have the same behavior -as in Android 1.1.

    - -

    Technique to Avoid, #3: Going Overboard with Layouts

    - -

    Due to changes in the View rendering infrastructure, unreasonably deep -(more than 10 or so) or broad (more than 30 total) View hierarchies in -layouts are now likely to cause crashes. This was always a risk for -excessively complex layouts, but you can think of Android 1.5 as being -better than 1.1 at exposing this problem. Most developers won't need to -worry about this, but if your app has very complicated layouts, you'll -need to put it on a diet. You can simplify your layouts using the more -advanced layout classes like FrameLayout and TableLayout.

    - -

    Technique to Avoid, #4: Bad Hardware Assumptions

    - -

    Android 1.5 includes support for soft keyboards, and there will soon be many -devices that run Android but do not have physical keyboards. If your -application assumes the presence of a physical keyboard (such as if you -have created a custom View that sinks keypress events) you should make -sure it degrades gracefully on devices that only have soft keyboards. -For more information on this, keep on eye on this blog as we'll be -posting more detailed information about handling the new soft keyboards.

    - -

    Technique to Avoid, #5: Incautious Rotations

    - -

    Devices running Android 1.5 and later can automatically rotate the screen, -depending on how the user orients the device. Some 1.5 devices will do -this by default, and on all others it can be turned on by the user. -This can sometimes result in unpredictable behavior from applications -that do their own reorientations (whether using the accelerometer, or -something else.) This often happens when applications assume that the -screen can only rotate if the physical keyboard is exposed; if the -device lacks a physical keyboard, these apps do not expect to be -reoriented, which is a coding error. Developers should be sure that -their applications can gracefully handle being reoriented at any time.

    - -

    Also, apps that use the accelerometer directly to reorient themselves -sometimes compete with the system doing the same thing, with odd -results. And finally, some apps that use the accelerometer to detect -things like shaking motions and that don't lock their orientation to -portrait or landscape, often end up flipping back and forth between -orientations. This can be irritating to the user. (You can lock your -app's orientation to portrait or landscape using the -android:screenOrientation attribute in the manifest file.)

    - diff --git a/docs/html/resources/articles/gestures.jd b/docs/html/resources/articles/gestures.jd deleted file mode 100644 index 5b8d76068842cbdd84fd26d107137b0fc76bb99c..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/gestures.jd +++ /dev/null @@ -1,213 +0,0 @@ -page.title=Gestures -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Touch screens are a great way to interact with applications on -mobile devices. With a touch screen, users can easily tap, drag, fling, -or slide to quickly perform actions in their favorite applications. -For app developers. the Android framework makes it's easy to -recognize simple actions, like a swipe, but it has been more -difficult to handle complicated gestures, sometimes requiring -developers to write a lot of code.

    - -

    That's why we introduced a new gestures API in Android 1.6. This API, located -in the new package {@link android.gesture}, lets you store, load, draw, and -recognize gestures. This article will show you how you can use the -android.gesture API in your applications. Before going any further, -you should download the source code -of the examples.

    - -

    Creating a gestures library

    - -

    Android 1.6 and higher SDK platforms include a new application pre-installed -on the emulator, called Gestures Builder. You can use this application to create -a set of pre-defined gestures for your own application. It also serves as an -example of how to let the user define his own gestures in your applications. You -can find the source code of Gestures Builders in the samples directory of each -SDK platform. In our example we will use Gestures Builder to generate a set of -gestures for us (make sure to create an AVD with an SD card image to use -Gestures Builder.) The screenshot below shows what the application looks like -after adding a few gestures:

    - - - -

    As you can see, a gesture is always associated with a name. That name is very -important because it identifies each gesture within your application. The names -do not have to be unique. Actually it can be very useful to have several -gestures with the same name to increase the precision of the recognition. Every -time you add or edit a gesture in the Gestures Builder, a file is generated on -the emulator's SD card, /sdcard/gestures. This file contains the -description of all the gestures, and you will need to package it inside your -application inside the resources directory, in -/res/raw.

    - -

    Loading the gestures library

    - -

    Now that you have a set of pre-defined gestures, you must load it inside your -application. This can be achieved in several ways but the easiest is to use the -GestureLibraries class:

    - -
    mLibrary = GestureLibraries.fromRawResource(this, R.raw.spells);
    -if (!mLibrary.load()) {
    -    finish();
    -}
    - -

    In this example, the gesture library is loaded from the file -/res/raw/spells. You can easily load libraries from other sources, -like the SD card, which is very important if you want your application to be -able to save the library; a library loaded from a raw resource is read-only and -cannot be modified. The following diagram shows the structure of a library:

    - - - -

    Recognizing gestures

    - -

    To start recognizing gestures in your application, all you have to do -is add a GestureOverlayView to your XML layout:

    - -
    <android.gesture.GestureOverlayView
    -    android:id="@+id/gestures"
    -    android:layout_width="fill_parent" 
    -    android:layout_height="0dip"
    -    android:layout_weight="1.0" />
    - -

    Notice that the GestureOverlayView -is not part of the usual android.widget package. Therefore, you must -use its fully qualified name. A gesture overlay acts as a simple -drawing board on which the user can draw his gestures. You can tweak -several visual properties, like the color and the width of the stroke -used to draw gestures, and register various listeners to follow what -the user is doing. The most commonly used listener is -GestureOverlayView.OnGesturePerformedListener, -which fires whenever a user is done drawing a gesture:

    - -
    GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);
    -gestures.addOnGesturePerformedListener(this);
    - -

    When the listener fires, you can ask the GestureLibrary -to try to recognize the gesture. In return, you will get a list of -Prediction instances, each with a name - the same name you entered in -the Gestures Builder - and a score. The list is sorted by descending -scores; the higher the score, the more likely the associated gesture is -the one the user intended to draw. The following code snippet -demonstrates how to retrieve the name of the first prediction:

    - -
    public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    -    ArrayList<prediction> predictions = mLibrary.recognize(gesture);
    -
    -    // We want at least one prediction
    -    if (predictions.size() > 0) {
    -        Prediction prediction = predictions.get(0);
    -        // We want at least some confidence in the result
    -        if (prediction.score > 1.0) {
    -            // Show the spell
    -            Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
    -        }
    -    }
    -}
    - -

    In this example, the first prediction is taken into account only if it's -score is greater than 1.0. The threshold you use is entirely up to you -but know that scores lower than 1.0 are typically poor matches. And -this is all the code you need to create a simple application that can -recognize pre-defined gestures (see the source code of the project -GesturesDemo):

    - - - -

    Gestures overlay

    - -

    In the example above, the GestureOverlayView was used -as a normal view, embedded inside a LinearLayout. -However, as its name suggests, it can also be used as an overlay on top -of other views. This can be useful to recognize gestures in a game or -just anywhere in the UI of an application. In the second example, -called GesturesListDemo, we'll create an overlay on top of a list of -contacts. We start again in Gestures Builder to create a new set of -pre-defined gestures:

    - -

    - -

    And here is what the XML layout looks like:

    - -
    <android.gesture.GestureOverlayView
    -    xmlns:android="http://schemas.android.com/apk/res/android"
    -    android:id="@+id/gestures"
    -    android:layout_width="fill_parent"
    -    android:layout_height="fill_parent"
    -    
    -    android:gestureStrokeType="multiple"
    -    android:eventsInterceptionEnabled="true"
    -    android:orientation="vertical">
    -
    -    <ListView
    -        android:id="@android:id/list"  
    -        android:layout_width="fill_parent" 
    -        android:layout_height="fill_parent"  />
    -
    -</android.gesture.GestureOverlayView>
    - -

    In this application, the gestures view is an overlay on top of a regular -ListView. The overlay also specifies a few properties that we did not -need before:

    - -
      -
    • gestureStrokeType: indicates -whether we want to recognize gestures made of a single stroke or -multiple strokes. Since one of our gestures is the "+" symbol, we need -multiple strokes
    • -
    • eventsInterceptionEnabled: when -set to true, this property tells the overlay to steal the events from -its children as soon as it knows the user is really drawing a gesture. -This is useful when there's a scrollable view under the overlay, to -avoid scrolling the underlying child as the user draws his gesture
    • -
    • orientation: -indicates the scroll orientation of the views underneath. In this case -the list scrolls vertically, which means that any horizontal gestures -(like action_delete) can immediately be recognized as a -gesture. Gestures that start with a vertical stroke must contain at -least one horizontal component to be recognized. In other words, a -simple vertical line cannot be recognized as a gesture since it would -conflict with the list's scrolling.
    • -
    - -

    The code used to load and set up the gestures library and overlay is exactly -the same as before. The only difference is that we now check the name of the -predictions to know what the user intended to do:

    - -
    public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    -    ArrayList<Prediction> predictions = mLibrary.recognize(gesture);
    -    if (predictions.size() > 0 && predictions.get(0).score > 1.0) {
    -        String action = predictions.get(0).name;
    -        if ("action_add".equals(action)) {
    -            Toast.makeText(this, "Adding a contact", Toast.LENGTH_SHORT).show();
    -        } else if ("action_delete".equals(action)) {
    -            Toast.makeText(this, "Removing a contact", Toast.LENGTH_SHORT).show();
    -        } else if ("action_refresh".equals(action)) {
    -            Toast.makeText(this, "Reloading contacts", Toast.LENGTH_SHORT).show();
    -        }
    -    }
    -}
    - -

    The user is now able to draw his gestures on top of the list without -interfering with the scrolling:

    - - - -

    The overlay even gives visual clues as to whether the gesture is considered -valid for recognition. In the case of a vertical overlay, for instance, -a single vertical stroke cannot be recognized as a gesture and is -therefore drawn with a translucent color:

    - - - -

    It's your turn

    - -

    Adding support for gestures in your application is easy and can be a valuable -addition. The gestures API does not even have to be used to recognize complex -shapes; it will work equally well to recognize simple swipes. We are very -excited by the possibilities the gestures API offers, and we're eager to see -what cool applications the community will create with it.

    diff --git a/docs/html/resources/articles/glsurfaceview.jd b/docs/html/resources/articles/glsurfaceview.jd deleted file mode 100644 index 45407a96dbe1a03020819468c0e347893866fee9..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/glsurfaceview.jd +++ /dev/null @@ -1,270 +0,0 @@ -page.title=Introducing GLSurfaceView -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -

    The {@link android android.opengl.GLSurfaceView} class makes it -easier for you to use OpenGL ES rendering in your applications by:

    - -
      -
    • Providing the glue code to connect OpenGL ES to the {@link -android.view.View} system.
    • -
    • Providing the glue code to make OpenGL ES work with the {@link -android.app.Activity} life-cycle.
    • -
    • Making it easy to choose an appropriate frame buffer pixel format.
    • -
    • Creating and managing a separate rendering thread, to enable smooth -animation.
    • -
    • Providing easy-to-use debugging tools for tracing OpenGL ES API calls and -checking for errors.
    • -
    - -

    GLSurfaceView is a good base for building an application that uses OpenGL ES -for part or all of its rendering. A 2D or 3D action game would be a good -candidate, as would a 2D or 3D data visualization application such as Google Maps StreetView.

    - -

    A simple GLSurfaceView application

    - -

    Here's the source code to the simplest possible OpenGL ES application:

    - -
    package com.example.android.apis.graphics;
    -
    -import javax.microedition.khronos.egl.EGLConfig;
    -import javax.microedition.khronos.opengles.GL10;
    -
    -import android.app.Activity;
    -import android.opengl.GLSurfaceView;
    -import android.os.Bundle;
    -
    -public class ClearActivity extends Activity {
    -    @Override
    -    protected void onCreate(Bundle savedInstanceState) {
    -        super.onCreate(savedInstanceState);
    -        mGLView = new GLSurfaceView(this);
    -        mGLView.setRenderer(new ClearRenderer());
    -        setContentView(mGLView);
    -    }
    -
    -    @Override
    -    protected void onPause() {
    -        super.onPause();
    -        mGLView.onPause();
    -    }
    -
    -    @Override
    -    protected void onResume() {
    -        super.onResume();
    -        mGLView.onResume();
    -    }
    -
    -    private GLSurfaceView mGLView;
    -}
    -
    -class ClearRenderer implements GLSurfaceView.Renderer {
    -    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    -        // Do nothing special.
    -    }
    -
    -    public void onSurfaceChanged(GL10 gl, int w, int h) {
    -        gl.glViewport(0, 0, w, h);
    -    }
    -
    -    public void onDrawFrame(GL10 gl) {
    -        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    -    }
    -}
    - -

    This program doesn't do much: it clears the screen to black on every frame. -But it is a complete OpenGL application that correctly implements the -Android activity life-cycle. It pauses rendering when the activity is -paused, and resumes it when the activity is resumed. You could use this -application as the basis for non-interactive demonstration programs. -Just add more OpenGL calls to the ClearRenderer.onDrawFrame() method. -Notice that you don't even need to subclass the GLSurfaceView view.

    - -

    The {@link android.opengl.GLSurfaceView.Renderer} interface has three methods:

    - -
      -
    • The -onSurfaceCreated() method is called at the start of rendering, and -whenever the OpenGL ES drawing context has to be recreated. (The -drawing context is typically lost and recreated when the activity is -paused and resumed.) OnSurfaceCreated() is a good place to create -long-lived OpenGL resources such as textures.
    • -
    • The onSurfaceChanged() -method is called when the surface changes size. It's a good place to -set your OpenGL viewport. You may also want to set your camera here, if -it's a fixed camera that doesn't move around the scene.
    • -
    • The onDrawFrame() method is called every frame, and is -responsible for drawing the scene. You would typically start by calling -glClear to clear the framebuffer, followed by other OpenGL ES calls -to draw the current scene.
    • -
    - -

    How about user input?

    - -

    If you want an interactive application (such as a game), you will typically -subclass GLSurfaceView, because that's an easy way of obtaining -input events. Here's a slightly longer example showing how to do that:

    - -
    package com.google.android.ClearTest;
    -
    -import javax.microedition.khronos.egl.EGLConfig;
    -import javax.microedition.khronos.opengles.GL10;
    -
    -import android.app.Activity;
    -import android.content.Context;
    -import android.opengl.GLSurfaceView;
    -import android.os.Bundle;
    -import android.view.MotionEvent;
    -
    -public class ClearActivity extends Activity {
    -    @Override
    -    protected void onCreate(Bundle savedInstanceState) {
    -        super.onCreate(savedInstanceState);
    -        mGLView = new ClearGLSurfaceView(this);
    -        setContentView(mGLView);
    -    }
    -
    -    @Override
    -    protected void onPause() {
    -        super.onPause();
    -        mGLView.onPause();
    -    }
    -
    -    @Override
    -    protected void onResume() {
    -        super.onResume();
    -        mGLView.onResume();
    -    }
    -
    -    private GLSurfaceView mGLView;
    -}
    -
    -class ClearGLSurfaceView extends GLSurfaceView {
    -    public ClearGLSurfaceView(Context context) {
    -        super(context);
    -        mRenderer = new ClearRenderer();
    -        setRenderer(mRenderer);
    -    }
    -
    -    public boolean onTouchEvent(final MotionEvent event) {
    -        queueEvent(new Runnable(){
    -            public void run() {
    -                mRenderer.setColor(event.getX() / getWidth(),
    -                        event.getY() / getHeight(), 1.0f);
    -            }});
    -            return true;
    -        }
    -
    -        ClearRenderer mRenderer;
    -}
    -
    -class ClearRenderer implements GLSurfaceView.Renderer {
    -    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    -        // Do nothing special.
    -    }
    -
    -    public void onSurfaceChanged(GL10 gl, int w, int h) {
    -        gl.glViewport(0, 0, w, h);
    -    }
    -
    -    public void onDrawFrame(GL10 gl) {
    -        gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
    -        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    -    }
    -
    -    public void setColor(float r, float g, float b) {
    -        mRed = r;
    -        mGreen = g;
    -        mBlue = b;
    -    }
    -
    -    private float mRed;
    -    private float mGreen;
    -    private float mBlue;
    -}
    - -

    This application clears the screen for every frame. When you tap on the -screen, it sets the clear color based on the (x,y) coordinates of your touch -event. Note the use of queueEvent() in -ClearGLSurfaceView.onTouchEvent(). The queueEvent() -method is used to safely communicate between the UI thread and the rendering -thread. If you prefer, you can use some other Java cross-thread communication -technique, such as synchronized methods on the Renderer class -itself. However, queueing events is often the simplest way of dealing with -cross-thread communication.

    - -

    Other GLSurfaceView samples

    - -

    Tired -of just clearing the screen? You can find more interesting samples in -the API Demos sample included in the Android SDK. All the OpenGL ES samples have been -converted to use the GLSurfaceView view:

    - -
      -
    • GLSurfaceView - a spinning triangle
    • -
    • Kube - a cube puzzle demo
    • -
    • Translucent GLSurfaceView - shows how to display 3D graphics on a translucent background
    • -
    • Textured Triangle - shows how to draw a textured 3D triangle
    • -
    • Sprite Text - shows how to draw text into a texture and then composite it into a 3D scene
    • -
    • Touch Rotate - shows how to rotate a 3D object in response to user input.
    • -
    - -

    Choosing a surface

    - -

    GLSurfaceView -helps you choose the type of surface to render to. Different Android -devices support different types of surfaces, with no common subset. -This makes it tricky problem to choose the best available surface on -each device.

    - -

    By default, GLSurfaceView tries to find a surface that's as -close as possible to a 16-bit RGB frame buffer with a 16-bit depth -buffer. Depending upon your application's needs you may want to change -this behavior. For example, the Translucent GLSurfaceView sample needs -an Alpha channel in order to render translucent data. GLSurfaceView -provides an overloaded setEGLSurfaceChooser() method to give -you control over which surface type is chosen:

    - -
    -
    setEGLConfigChooser(boolean needDepth)
    -
    Choose a config that's closest to R5G6B5 with or without a 16-bit framebuffer
    -
    setEGLConfigChooser(int redSize, int greenSize,int blueSize, -int alphaSize,int depthSize, int stencilSize)
    -
    Choose the config with the fewest number of bits per pixel that has at least -as many bits-per-channel as specified in the constructor.
    -
    setEGLConfigChooser(EGLConfigChooser configChooser)
    -
    Allow total control over choosing a configuration. You pass in your own -implementation of EGLConfigChooser, which gets to inspect the -device's capabilities and choose a configuration.
    -
    - -

    Continuous rendering versus render-when-dirty

    - -

    Most 3D applications, such as games or simulations, are continuously -animated. But some 3D applications are more reactive: they wait passively until -the user does something, and then react to it. For those types of applications, -the default GLSurfaceView behavior of continuously redrawing the -screen is a waste of time. If you are developing a reactive application, you can -call GLSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY), which -turns off the continuous animation. Then you call -GLSurfaceView.requestRender() whenever you want to re-render.

    - -

    Help With debugging

    - -

    GLSurfaceView has a handy built-in feature for debugging OpenGL ES -applications: the GLSurfaceView.setDebugFlags() method can be used -to enable logging and/or error checking your OpenGL ES calls. Call this method -in your GLSurfaceView's constructor, before calling -setRenderer():

    - -
    public ClearGLSurfaceView(Context context) {
    -    super(context);
    -    // Turn on error-checking and logging
    -    setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
    -    mRenderer = new ClearRenderer();
    -    setRenderer(mRenderer);
    -}
    \ No newline at end of file diff --git a/docs/html/resources/articles/images/File.png b/docs/html/resources/articles/images/File.png deleted file mode 100644 index bc5a2b827329df27da595cd563ebc04275ac441d..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/File.png and /dev/null differ diff --git a/docs/html/resources/articles/images/File_002.png b/docs/html/resources/articles/images/File_002.png deleted file mode 100644 index 39254b30a4d8b725fb65ba228001788a220ea920..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/File_002.png and /dev/null differ diff --git a/docs/html/resources/articles/images/JFlubber.png b/docs/html/resources/articles/images/JFlubber.png deleted file mode 100644 index d95e32b8fbf20ed5a2211b46389ebbd4b17c7175..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/JFlubber.png and /dev/null differ diff --git a/docs/html/resources/articles/images/WikiNotes.png b/docs/html/resources/articles/images/WikiNotes.png deleted file mode 100644 index d52c4fca7bd318fe2803e7910958ed84ec3083dc..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/WikiNotes.png and /dev/null differ diff --git a/docs/html/resources/articles/images/all_drawables_changed.png b/docs/html/resources/articles/images/all_drawables_changed.png deleted file mode 100644 index 04ec4a2d7aa3934cedc31431bf8c234a5823e826..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/all_drawables_changed.png and /dev/null differ diff --git a/docs/html/resources/articles/images/android.png b/docs/html/resources/articles/images/android.png deleted file mode 100644 index 6dc88ccbd170079a5ead602d923fd069ff7d0515..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/android.png and /dev/null differ diff --git a/docs/html/resources/articles/images/buttons.png b/docs/html/resources/articles/images/buttons.png deleted file mode 100644 index 8c220b9523ccbbefe6c8a94f54254dffee7ae126..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/buttons.png and /dev/null differ diff --git a/docs/html/resources/articles/images/contacts-2.png b/docs/html/resources/articles/images/contacts-2.png deleted file mode 100644 index 02f28aaad211c3e1347ecd31152d7f1d477a03f6..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/contacts-2.png and /dev/null differ diff --git a/docs/html/resources/articles/images/contacts.png b/docs/html/resources/articles/images/contacts.png deleted file mode 100644 index d8b067df99b14b6966a45c476bfaf9c1bc8128ff..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/contacts.png and /dev/null differ diff --git a/docs/html/resources/articles/images/correct_drawables.png b/docs/html/resources/articles/images/correct_drawables.png deleted file mode 100644 index 516309b683e88091142fd7bbaef2733f71748b25..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/correct_drawables.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ddms_allocation_tracker.png b/docs/html/resources/articles/images/ddms_allocation_tracker.png deleted file mode 100644 index b9fa0a1db807c17b0416c6217af765965e60782e..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ddms_allocation_tracker.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ddms_allocation_trackerl.png b/docs/html/resources/articles/images/ddms_allocation_trackerl.png deleted file mode 100644 index 5ac8d2a0eddcaad54104e5c981dbc3bcc385057e..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ddms_allocation_trackerl.png and /dev/null differ diff --git a/docs/html/resources/articles/images/device.png b/docs/html/resources/articles/images/device.png deleted file mode 100644 index 186b960bd908ce0b2c438699a6598d6a4b3086c2..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/device.png and /dev/null differ diff --git a/docs/html/resources/articles/images/device_002.png b/docs/html/resources/articles/images/device_002.png deleted file mode 100644 index 4bc3b0c4f14b2e5008b0535bed4897f520a538e5..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/device_002.png and /dev/null differ diff --git a/docs/html/resources/articles/images/gestures.png b/docs/html/resources/articles/images/gestures.png deleted file mode 100644 index fe8f7cdfe2f2e2b965a42616bc09052eb420a54b..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/gestures.png and /dev/null differ diff --git a/docs/html/resources/articles/images/gestures_002.png b/docs/html/resources/articles/images/gestures_002.png deleted file mode 100644 index b20da98fcd227168f9ca2a619309fb7bad0f3df3..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/gestures_002.png and /dev/null differ diff --git a/docs/html/resources/articles/images/gestures_003.png b/docs/html/resources/articles/images/gestures_003.png deleted file mode 100644 index a29593905f37583db51f2f2a607dbdc46ed2ea79..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/gestures_003.png and /dev/null differ diff --git a/docs/html/resources/articles/images/gestures_004.png b/docs/html/resources/articles/images/gestures_004.png deleted file mode 100644 index 3fe5fb1793576eef4ea4c6c2c6b8c25bc960f736..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/gestures_004.png and /dev/null differ diff --git a/docs/html/resources/articles/images/gestures_005.png b/docs/html/resources/articles/images/gestures_005.png deleted file mode 100644 index 3efc519d032612cd3d6d89d23c1abc2016951267..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/gestures_005.png and /dev/null differ diff --git a/docs/html/resources/articles/images/gestures_006.png b/docs/html/resources/articles/images/gestures_006.png deleted file mode 100644 index 399c31d6b51fb8aeef9d900f01e5c801d817697a..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/gestures_006.png and /dev/null differ diff --git a/docs/html/resources/articles/images/grid.png b/docs/html/resources/articles/images/grid.png deleted file mode 100644 index 4713de5f564a92d8b741f5d31299b7ff1233270a..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/grid.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ime.png b/docs/html/resources/articles/images/ime.png deleted file mode 100644 index 57f6df1c3a97c4414bee644fca0e455b8e33e3e2..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ime.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ime_002.png b/docs/html/resources/articles/images/ime_002.png deleted file mode 100644 index 3ec00b2f66d6e8574e5bfbc82c5d396404ca6bd4..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ime_002.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ime_003.png b/docs/html/resources/articles/images/ime_003.png deleted file mode 100644 index a3f57bb701f3b985879a0d6a26a1db858536f8ba..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ime_003.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ime_004.png b/docs/html/resources/articles/images/ime_004.png deleted file mode 100644 index efeddf05b0fa86519c929045c8be2d1ac0636092..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ime_004.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ime_005.png b/docs/html/resources/articles/images/ime_005.png deleted file mode 100644 index a7394e067cf995d3d6828ade13c3497ae00e11cb..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ime_005.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ime_006.png b/docs/html/resources/articles/images/ime_006.png deleted file mode 100644 index 0b55c7962dbfbcd4b83d7d554b454d93e053ab9a..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ime_006.png and /dev/null differ diff --git a/docs/html/resources/articles/images/layouts_comparison_small.png b/docs/html/resources/articles/images/layouts_comparison_small.png deleted file mode 100644 index 0ba4cb8cf9cddb0f8bfa2d9d2f03bac104e88b77..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/layouts_comparison_small.png and /dev/null differ diff --git a/docs/html/resources/articles/images/list01.png b/docs/html/resources/articles/images/list01.png deleted file mode 100644 index e1b7fa8255ef1a2c9455b7ce2cc2f3b1fbb93d7e..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/list01.png and /dev/null differ diff --git a/docs/html/resources/articles/images/list02.png b/docs/html/resources/articles/images/list02.png deleted file mode 100644 index 7f72a3f2899454cd4de95c8e59a27d6f9fc11186..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/list02.png and /dev/null differ diff --git a/docs/html/resources/articles/images/list_fade_1.png b/docs/html/resources/articles/images/list_fade_1.png deleted file mode 100644 index 43013d6b39975501793ccbf603b66486272c1ad6..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/list_fade_1.png and /dev/null differ diff --git a/docs/html/resources/articles/images/list_fade_2.png b/docs/html/resources/articles/images/list_fade_2.png deleted file mode 100644 index 160d3ffe5b3eef00e4dee751f0857e9a2e77f6b7..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/list_fade_2.png and /dev/null differ diff --git a/docs/html/resources/articles/images/list_fade_3.png b/docs/html/resources/articles/images/list_fade_3.png deleted file mode 100644 index 70dca6439c97609d9e9830183b7e1c6c0c436bd4..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/list_fade_3.png and /dev/null differ diff --git a/docs/html/resources/articles/images/list_fade_4.png b/docs/html/resources/articles/images/list_fade_4.png deleted file mode 100644 index 7619fcaeb4033333a7a854afede721754edd6955..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/list_fade_4.png and /dev/null differ diff --git a/docs/html/resources/articles/images/live_wallpapers_small.png b/docs/html/resources/articles/images/live_wallpapers_small.png deleted file mode 100644 index 3b49b2427005c113a7b3f26b450f1a771d8b49f9..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/live_wallpapers_small.png and /dev/null differ diff --git a/docs/html/resources/articles/images/merge1.jpg b/docs/html/resources/articles/images/merge1.jpg deleted file mode 100644 index 114eed697bf568181133f01c24d7a7895e9d5ec1..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/merge1.jpg and /dev/null differ diff --git a/docs/html/resources/articles/images/merge2.png b/docs/html/resources/articles/images/merge2.png deleted file mode 100644 index b4a8d4c26639584477f0019edb7a16aa92f7fcb1..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/merge2.png and /dev/null differ diff --git a/docs/html/resources/articles/images/merge3.png b/docs/html/resources/articles/images/merge3.png deleted file mode 100644 index 61ed983dd50699942c2e42b771efc21822e44340..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/merge3.png and /dev/null differ diff --git a/docs/html/resources/articles/images/merge4.jpg b/docs/html/resources/articles/images/merge4.jpg deleted file mode 100644 index 17b6c20a203244c00ff3807ae0ea73b4783a0f8b..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/merge4.jpg and /dev/null differ diff --git a/docs/html/resources/articles/images/merge5.png b/docs/html/resources/articles/images/merge5.png deleted file mode 100644 index 289f47e0f3eb50a611b32ecafc382c214ada9c03..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/merge5.png and /dev/null differ diff --git a/docs/html/resources/articles/images/mutated_states.png b/docs/html/resources/articles/images/mutated_states.png deleted file mode 100644 index 50518b639136d66e97dcc90bec559ff677a7afe6..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/mutated_states.png and /dev/null differ diff --git a/docs/html/resources/articles/images/on-screen-inputs.png b/docs/html/resources/articles/images/on-screen-inputs.png deleted file mode 100644 index b8b3cf794f36d0299b2306e9c9827760e9949b68..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/on-screen-inputs.png and /dev/null differ diff --git a/docs/html/resources/articles/images/on-screen-inputs_002.png b/docs/html/resources/articles/images/on-screen-inputs_002.png deleted file mode 100644 index a5d21c75f634c0b47eec23d39e5661ddd24d69b4..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/on-screen-inputs_002.png and /dev/null differ diff --git a/docs/html/resources/articles/images/on-screen-inputs_003.png b/docs/html/resources/articles/images/on-screen-inputs_003.png deleted file mode 100644 index 81ee257b6c107486aac39aae960f97735c5a656d..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/on-screen-inputs_003.png and /dev/null differ diff --git a/docs/html/resources/articles/images/on-screen-inputs_004.png b/docs/html/resources/articles/images/on-screen-inputs_004.png deleted file mode 100644 index 651b72a10ba272b1bd334149ee2344d53399ca7d..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/on-screen-inputs_004.png and /dev/null differ diff --git a/docs/html/resources/articles/images/on-screen-inputs_005.png b/docs/html/resources/articles/images/on-screen-inputs_005.png deleted file mode 100644 index 75185ff1bbf0638b526bb891ed40f739564f11f1..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/on-screen-inputs_005.png and /dev/null differ diff --git a/docs/html/resources/articles/images/on-screen-inputs_006.png b/docs/html/resources/articles/images/on-screen-inputs_006.png deleted file mode 100644 index b653d753dc26017300dbe1432ddcb38d9d3542a3..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/on-screen-inputs_006.png and /dev/null differ diff --git a/docs/html/resources/articles/images/photostream_landscape.png b/docs/html/resources/articles/images/photostream_landscape.png deleted file mode 100644 index ad4a0c5a0fdaee0e26723f61bad4f37c936d004b..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/photostream_landscape.png and /dev/null differ diff --git a/docs/html/resources/articles/images/photostream_portrait.png b/docs/html/resources/articles/images/photostream_portrait.png deleted file mode 100644 index 3794f6374439638a99805868c2bbc8b20ba1bcca..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/photostream_portrait.png and /dev/null differ diff --git a/docs/html/resources/articles/images/qsb.png b/docs/html/resources/articles/images/qsb.png deleted file mode 100644 index 4e40af14a53b0273b2a0910be1c3acc1978f2313..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/qsb.png and /dev/null differ diff --git a/docs/html/resources/articles/images/qsb_002.png b/docs/html/resources/articles/images/qsb_002.png deleted file mode 100644 index 8c2f77232270bf2263e6f94c78b86141aa5dc5e1..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/qsb_002.png and /dev/null differ diff --git a/docs/html/resources/articles/images/qsb_003.png b/docs/html/resources/articles/images/qsb_003.png deleted file mode 100644 index 069b6cd31d1e9461df4a81e6478713bbcfcf9325..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/qsb_003.png and /dev/null differ diff --git a/docs/html/resources/articles/images/relativelayout_1.png b/docs/html/resources/articles/images/relativelayout_1.png deleted file mode 100644 index 3360ad85366d1dcf13b1f5e5afe4fb01308baded..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/relativelayout_1.png and /dev/null differ diff --git a/docs/html/resources/articles/images/relativelayout_2.png b/docs/html/resources/articles/images/relativelayout_2.png deleted file mode 100644 index 8e71bb27f20241bd5843265671b32d7dd00f58d1..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/relativelayout_2.png and /dev/null differ diff --git a/docs/html/resources/articles/images/relativelayout_3.png b/docs/html/resources/articles/images/relativelayout_3.png deleted file mode 100644 index 16a9767890d131bad7ee3b5c04f898bda7185c12..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/relativelayout_3.png and /dev/null differ diff --git a/docs/html/resources/articles/images/relativelayout_wire_1.png b/docs/html/resources/articles/images/relativelayout_wire_1.png deleted file mode 100644 index 9cb241df6d4556dd476de7944c9a0e0a998d1b9a..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/relativelayout_wire_1.png and /dev/null differ diff --git a/docs/html/resources/articles/images/relativelayout_wire_2.png b/docs/html/resources/articles/images/relativelayout_wire_2.png deleted file mode 100644 index 4243812e366d68afaac492ac488bec129d0388ea..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/relativelayout_wire_2.png and /dev/null differ diff --git a/docs/html/resources/articles/images/relativelayout_wire_3.png b/docs/html/resources/articles/images/relativelayout_wire_3.png deleted file mode 100644 index 04ce1cefb2bd85ac4ee738623bb07b71ef030db4..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/relativelayout_wire_3.png and /dev/null differ diff --git a/docs/html/resources/articles/images/search01.png b/docs/html/resources/articles/images/search01.png deleted file mode 100644 index 4160a76528d2c33835c70971616082fd2d33aacf..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/search01.png and /dev/null differ diff --git a/docs/html/resources/articles/images/search02.png b/docs/html/resources/articles/images/search02.png deleted file mode 100644 index 63000186b7309598395e8ade2101d73b11a1198e..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/search02.png and /dev/null differ diff --git a/docs/html/resources/articles/images/service-api-changes-starting-with_runningservices.png b/docs/html/resources/articles/images/service-api-changes-starting-with_runningservices.png deleted file mode 100644 index e159fff70efb0045f16fcd989776138a17dd3eab..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/service-api-changes-starting-with_runningservices.png and /dev/null differ diff --git a/docs/html/resources/articles/images/service-api-changes-starting-with_stopservice.png b/docs/html/resources/articles/images/service-api-changes-starting-with_stopservice.png deleted file mode 100644 index cc8f0a2a5fd6693ac1492a0774d404b75083a3ef..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/service-api-changes-starting-with_stopservice.png and /dev/null differ diff --git a/docs/html/resources/articles/images/shared_states.png b/docs/html/resources/articles/images/shared_states.png deleted file mode 100644 index 81bec0958f81e5ae133cb28314baeaa099a8b76c..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/shared_states.png and /dev/null differ diff --git a/docs/html/resources/articles/images/shelves2.png b/docs/html/resources/articles/images/shelves2.png deleted file mode 100644 index 2de239fb413bcc43e479b2547cfb849af707700c..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/shelves2.png and /dev/null differ diff --git a/docs/html/resources/articles/images/speech-input.png b/docs/html/resources/articles/images/speech-input.png deleted file mode 100644 index 78fbc98c4603aa0ef630b0e0608cd0b3197cdc03..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/speech-input.png and /dev/null differ diff --git a/docs/html/resources/articles/images/text_field.png b/docs/html/resources/articles/images/text_field.png deleted file mode 100644 index b9dedecd342a599d901b6551a2ee7c34bec7c549..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/text_field.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ui-1.6.png b/docs/html/resources/articles/images/ui-1.6.png deleted file mode 100644 index bc5a2b827329df27da595cd563ebc04275ac441d..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ui-1.6.png and /dev/null differ diff --git a/docs/html/resources/articles/images/ui-1.6_002.png b/docs/html/resources/articles/images/ui-1.6_002.png deleted file mode 100644 index 39254b30a4d8b725fb65ba228001788a220ea920..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/ui-1.6_002.png and /dev/null differ diff --git a/docs/html/resources/articles/images/viewstub1.png b/docs/html/resources/articles/images/viewstub1.png deleted file mode 100644 index 2de239fb413bcc43e479b2547cfb849af707700c..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/viewstub1.png and /dev/null differ diff --git a/docs/html/resources/articles/images/viewstub2.png b/docs/html/resources/articles/images/viewstub2.png deleted file mode 100644 index 6e6feb978d87e8ff2fa9170c60945310a98943ed..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/viewstub2.png and /dev/null differ diff --git a/docs/html/resources/articles/images/viewstub3.png b/docs/html/resources/articles/images/viewstub3.png deleted file mode 100644 index 5e793e664e62cd6b4b4f8c6b3eb3167a754e2e9f..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/viewstub3.png and /dev/null differ diff --git a/docs/html/resources/articles/images/viewstub4.png b/docs/html/resources/articles/images/viewstub4.png deleted file mode 100644 index cffb9c63761a2a9dd5ac6b776fd323cbcdac94b8..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/viewstub4.png and /dev/null differ diff --git a/docs/html/resources/articles/images/webview.png b/docs/html/resources/articles/images/webview.png deleted file mode 100644 index 92472af527d49c30c408510185b4318e80424a31..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/webview.png and /dev/null differ diff --git a/docs/html/resources/articles/images/window_background.png b/docs/html/resources/articles/images/window_background.png deleted file mode 100644 index 58f4f7edd1489ee2840d2c122888d0137354f274..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/window_background.png and /dev/null differ diff --git a/docs/html/resources/articles/images/window_background_null.png b/docs/html/resources/articles/images/window_background_null.png deleted file mode 100644 index 83f7b45d00533c8d9c0f5183c37de7b5e3ba0f5a..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/window_background_null.png and /dev/null differ diff --git a/docs/html/resources/articles/images/window_background_root.png b/docs/html/resources/articles/images/window_background_root.png deleted file mode 100644 index 95a47c0b60af669cc9febeb184706f1b465f877e..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/articles/images/window_background_root.png and /dev/null differ diff --git a/docs/html/resources/articles/index.jd b/docs/html/resources/articles/index.jd deleted file mode 100644 index 2947e4a2649aa0193ccdaf13f50b687b46484298..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/index.jd +++ /dev/null @@ -1,168 +0,0 @@ -page.title=Technical Articles -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -
    -
    Avoiding Memory Leaks
    -
    Mobile devices often have limited memory, and memory leaks can cause your application to waste this valuable resource without your knowledge. This article provides tips to help you avoid common causes of memory leaks on the Android platform.
    -
    - -
    -
    Backward Compatibility
    -
    The Android platform strives to ensure backwards compatibility. However, sometimes you want to use new features which aren't supported on older platforms. This article discusses strategies for selectively using these features based on availability, allowing you to keep your applications portable across a wide range of devices.
    -
    - -
    -
    Can I Use this Intent?
    -
    Android offers a very powerful and yet easy-to-use message type called an intent. You can use intents to turn applications into high-level libraries and make code modular and reusable. While it is nice to be able to make use of a loosely coupled API, there is no guarantee that the intent you send will be received by another application. This article describes a technique you can use to find out whether the system contains any application capable of responding to the intent you want to use.
    -
    - -
    -
    Creating an Input Method
    -
    Input Method Editors (IMEs) provide the mechanism for entering text into text fields and other Views. Android devices come bundled with at least one IME, but users can install additional IMEs. This article covers the basics of developing an IME for the Android platform.
    -
    - -
    -
    Drawable Mutations
    -
    Drawables are pluggable drawing containers that allow applications to display graphics. This article explains some common pitfalls when trying to modify the properties of multiple Drawables.
    -
    - -
    -
    Faster Screen Orientation Change
    -
    When an Android device changes its orientation, the default behavior is to automatically restart the current activity with a new configuration. However, this can become a bottleneck in applications that access a large amount of external data. This article discusses how to gracefully handle this situation without resorting to manually processing configuration changes.
    -
    - -
    -
    Future-Proofing Your Apps
    -
    A collection of common sense advice to help you ensure that your applications don't break when new versions of the Android platform are released.
    -
    - -
    -
    Gestures
    -
    Touch screens allow users to perform gestures, such as tapping, dragging, flinging, or sliding, to perform various actions. The gestures API enables your application to recognize even complicated gestures with ease. This article explains how to integrate this API into an application.
    -
    - -
    -
    Introducing GLSurfaceView
    -
    This article provides an overview of GLSurfaceView, a class that makes it easy to implement 2D or 3D OpenGL rendering inside of an Android application.
    -
    -
    -
    - - Using the Spell Checker Framework -
    -
    - This article describes how to use the Spell Checker Framework to check spelling in - various ways in your application. -
    -
    -
    -
    Layout Tricks: Creating Reusable UI Components
    -
    Learn how to combine multiple standard UI widgets into a single high-level component, which can be reused throughout your application.
    -
    - -
    -
    Layout Tricks: Creating Efficient Layouts
    -
    Learn how to optimize application layouts as this article walks you through converting a LinearLayout into a RelativeLayout, and analyzes the resulting implications on performance.
    -
    - -
    -
    Layout Tricks: Using ViewStubs
    -
    Learn about using ViewStubs inside an application's layout in order to inflate rarely used UI elements, without the performance implications which would otherwise be caused by using the <include> tag.
    -
    - -
    -
    Layout Tricks: Merging Layouts
    -
    Learn how to use the <merge> tag in your XML layouts in order to avoid unnecessary levels of hierarchy within an application's view tree.
    -
    - -
    -
    ListView Backgrounds: An Optimization
    -
    ListViews are very popular widgets within the Android framework. This article describes some of the optimizations used by the ListView widget, and how to avoid some common issues that this causes when trying to use a custom background.
    -
    - -
    -
    Live Folders
    -
    Live Folders allow users to display any source of data on their home screen without launching an application. This article discusses how to export an application's data in a format suitable for display inside of a live folder.
    -
    - -
    -
    Live Wallpapers
    -
    Live wallpapers are richer, animated, interactive backgrounds that users can display in their home screens. Learn how to create a live wallpaper and bundle it in an application that users can install on their devices.
    -
    - -
    -
    Onscreen Input Methods
    -
    The Input Method Framework (IMF) allows users to take advantage of on-screen input methods, such as software keyboards. This article provides an overview of Input Method Editors (IMEs) and how applications interact with them.
    -
    - -
    -
    Painless Threading
    -
    This article discusses the threading model used by Android applications and how applications can ensure best UI performance by spawning worker threads to handle long-running operations, rather than handling them in the main thread. The article also explains the API that your application can use to interact with Android UI toolkit components running on the main thread and spawn managed worker threads.
    -
    - -
    -
    Quick Search Box
    -
    Quick Search Box (QSB) is a powerful, system-wide search framework. QSB makes it possible for users to quickly and easily find what they're looking for, both on their devices and on the web. This article discusses how to work with the QSB framework to add new search results for an installed application.
    -
    - -
    -
    Touch Mode
    -
    This article explains the touch mode, one of the most important principles of Android's UI toolkit. Whenever a user interacts with a device's touch screen, the system enters touch mode. While simple in concept, there are important implications touch mode that are often overlooked.
    -
    - -
    -
    Tracking Memory Allocations
    -
    This article discusses how to use the Allocation Tracker tool to observe memory allocations and avoid performance problems that would otherwise be caused by ignoring the effect of Dalvik's garbage collector.
    -
    - -
    -
    UI Framework Changes in Android 1.5
    -
    Explore the UI changes that were introduced in Android 1.5, compared with the UI provided in Android 1.0 and 1.1.
    -
    - -
    -
    UI Framework Changes in Android 1.6
    -
    Explore the UI changes that were introduced in Android 1.6, compared with the UI provided in Android 1.5. In particular, this article discusses changes to RelativeLayouts and click listeners.
    -
    - -
    -
    Updating the UI from a Timer
    -
    Learn about how to use Handlers as a more efficient replacement for java.util.Timer on the Android platform.
    -
    - -
    -
    Using Text-to-Speech
    -
    The text-to-speech API lets your application "speak" to users, in any of several languages. This article provides an overview of the TTS API and how you use to add speech capabilities to your application.
    -
    - -
    -
    Using the Contacts API
    -
    This article discusses the improved Contacts API introduced in Android 2.0 and how to use it to manage and integrate contacts from multiple accounts and data sources. The article also discusses techniques for using the new API on devices that support it, while maintaining backward compatibility with the old API on other devices.
    -
    - -
    -
    Using WebViews
    -
    WebViews allow an application to dynamically display HTML and execute JavaScript, without relinquishing control to a separate browser application. This article introduces the WebView classes and provides a sample application that demonstrates its use.
    -
    - -
    -
    WikiNotes: Linkify your Text!
    -
    This article introduces WikiNotes for Android, part of the Apps for Android project. It covers the use of Linkify to turn ordinary text views into richer, link-oriented content that causes Android intents to fire when a link is selected.
    -
    - -
    -
    WikiNotes: Routing Intents
    -
    This article illustrates how an application, in this case the WikiNotes sample app, can use intents to route various types of linked text to the application that handles that type of data. For example, an app can use intents to route a linked telephone number to a dialer app and a web URL to a browser.
    -
    - -
    -
    Window Backgrounds & UI Speed
    -
    Some Android applications need to squeeze every bit of performance out of the UI toolkit and there are many ways to do so. In this article, you will discover how to speed up the drawing and the perceived startup time of your activities. Both of these techniques rely on a single feature, the window's background drawable.
    -
    - -
    -
    Zipalign: an Easy Optimization
    -
    The Android SDK includes a tool called zipalign that optimizes the way an application is packaged. Running zipalign against your application enables Android to interact with it more efficiently at run time and thus has the potential to make it and the overall system run faster. This article provides a high-level overview of the zipalign tool and its use.
    -
    diff --git a/docs/html/resources/articles/layout-tricks-efficiency.jd b/docs/html/resources/articles/layout-tricks-efficiency.jd deleted file mode 100644 index 00b4147e84cb31c517018d4261441dcc1c5d0504..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/layout-tricks-efficiency.jd +++ /dev/null @@ -1,179 +0,0 @@ -page.title=Layout Tricks: Creating Efficient Layouts -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    The Android UI toolkit offers several layout managers that are -rather easy to use and, most of the time, you only need the basic -features of these layout managers to implement a user interface.

    - -

    Sticking to the basic features is unfortunately not the most efficient -way to create user interfaces. A common example is the abuse of -{@link android.widget.LinearLayout}, which leads to a proliferation of -views in the view hierarchy. Every view — or worse, every layout -manager — that you add to your application comes at a cost: -initialization, layout and drawing become slower. The layout pass can be -especially expensive when you nest several LinearLayout -that use the {@link android.R.attr#layout_weight weight} -parameter, which requires the child to be measured twice.

    - -

    Let's consider a very simple and common example of a layout: a list item -with an icon on the left, a title at the top and an optional description -underneath the title. Here is what such an item looks like:

    - -
    Simple list item
    - -

    To clearly understand how the views, one {@link android.widget.ImageView} and -two {@link android.widget.TextView}, are positioned with respect to each other, -here is the wireframe of the layout as captured by HierarchyViewer:

    - -
    Wireframe of the simple list item
    - -

    Implementing this layout is straightforward with LinearLayout. -The item itself is a horizontal LinearLayout with an -ImageView and a vertical LinearLayout, which contains -the two TextView. Here's the source code of this layout:

    - -
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -    android:layout_width="fill_parent"
    -    android:layout_height="?android:attr/listPreferredItemHeight"
    -    
    -    android:padding="6dip">
    -    
    -    <ImageView
    -        android:id="@+id/icon"
    -        
    -        android:layout_width="wrap_content"
    -        android:layout_height="fill_parent"
    -        android:layout_marginRight="6dip"
    -        
    -        android:src="@drawable/icon" />
    -
    -    <LinearLayout
    -        android:orientation="vertical"
    -    
    -        android:layout_width="0dip"
    -        android:layout_weight="1"
    -        android:layout_height="fill_parent">
    -
    -        <TextView
    -            android:layout_width="fill_parent"
    -            android:layout_height="0dip"
    -            android:layout_weight="1"
    -                    
    -            android:gravity="center_vertical"
    -            android:text="My Application" />
    -            
    -        <TextView  
    -            android:layout_width="fill_parent"
    -            android:layout_height="0dip"
    -            android:layout_weight="1" 
    -            
    -            android:singleLine="true"
    -            android:ellipsize="marquee"
    -            android:text="Simple application that shows how to use RelativeLayout" />
    -            
    -    </LinearLayout>
    -
    -</LinearLayout>
    - -

    This layout works but can be wasteful if you instantiate it for every list -item of a {@link android.widget.ListView}. The same layout can be rewritten -using a single {@link android.widget.RelativeLayout}, thus saving one view, and -even better one level in view hierarchy, per list item. The implementation of -the layout with a RelativeLayout remains simple:

    - -
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -    android:layout_width="fill_parent"
    -    android:layout_height="?android:attr/listPreferredItemHeight"
    -    
    -    android:padding="6dip">
    -    
    -    <ImageView
    -        android:id="@+id/icon"
    -        
    -        android:layout_width="wrap_content"
    -        android:layout_height="fill_parent"
    -        
    -        android:layout_alignParentTop="true"
    -        android:layout_alignParentBottom="true"
    -        android:layout_marginRight="6dip"
    -        
    -        android:src="@drawable/icon" />
    -
    -    <TextView  
    -        android:id="@+id/secondLine"
    -
    -        android:layout_width="fill_parent"
    -        android:layout_height="26dip" 
    -        
    -        android:layout_toRightOf="@id/icon"
    -        android:layout_alignParentBottom="true"
    -        android:layout_alignParentRight="true"
    -        
    -        android:singleLine="true"
    -        android:ellipsize="marquee"
    -        android:text="Simple application that shows how to use RelativeLayout" />
    -
    -    <TextView
    -        android:layout_width="fill_parent"
    -        android:layout_height="wrap_content"
    -        
    -        android:layout_toRightOf="@id/icon"
    -        android:layout_alignParentRight="true"
    -        android:layout_alignParentTop="true"
    -        android:layout_above="@id/secondLine"
    -        android:layout_alignWithParentIfMissing="true"
    -                
    -        android:gravity="center_vertical"
    -        android:text="My Application" />
    -
    -</RelativeLayout>
    - -

    This new implementation behaves exactly the same way as the previous -implementation, except in one case. The list item we want to display has two -lines of text: the title and an optional description. When a -description is not available for a given list item, the application would simply -set the visibility of the second TextView to -{@link android.view.View#GONE}. This works perfectly with the LinearLayout -implementation but not with the RelativeLayout version:

    - -
    RelativeLayout and description GONE
    -
    RelativeLayout and description GONE
    - -

    In a RelativeLayout, views are aligned with their parent, with the -RelativeLayout itself, or with other views. For instance, we declared that -the description is aligned with the bottom of the RelativeLayout and -that the title is positioned above the description and anchored to the -parent's top. With the description GONE, RelativeLayout doesn't know -where to position the title's bottom edge. To solve this problem, you -can use a very special layout parameter called -{@link android.R.attr#layout_alignWithParentIfMissing}. -

    - -

    This boolean parameter simply tells RelativeLayout to use its own edges as -anchors when a constraint target is missing. For instance, if you position a -view to the right of a GONE view and set alignWithParentIfMissing -to true, RelativeLayout will instead anchor the view -to its left edge. In our case, using alignWithParentIfMissing will -cause RelativeLayout to align the title's bottom with its own -bottom. The result is the following:

    - -
    RelativeLayout, description GONE and alignWithParentIfMissing
    -
    RelativeLayout, description GONE and alignWithParentIfMissing
    - -

    The -behavior of our layout is now perfect, even when the description is -GONE. Even better, the hierarchy is simpler and because we are not -using LinearLayout's weights it's also more efficient. The difference -between the two implementations becomes obvious when comparing the view -hierarchies in HierarchyViewer:

    - -
    LinearLayout vs RelativeLayout
    - -

    Again, the difference will be much more important when you use such a layout -for every item in a ListView for instance. Hopefully this simple -example showed you that getting to know your layouts is the best way to -learn how to optimize your UI.

    diff --git a/docs/html/resources/articles/layout-tricks-merge.jd b/docs/html/resources/articles/layout-tricks-merge.jd deleted file mode 100644 index 0ca0317d99f4c9a9e0aad161949503f7a6f46cca..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/layout-tricks-merge.jd +++ /dev/null @@ -1,202 +0,0 @@ -page.title=Layout Tricks: Merging Layouts -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    The articles showed you how to use the <include /> tag in XML layouts, to -reuse and share your layout code. This article explains the <merge /> tag and how -it complements the <include /> tag.

    - -

    The <merge /> tag was created for the purpose of -optimizing Android layouts by reducing the number of levels in view trees. It's -easier to understand the problem this tag solves by looking at an example. The -following XML layout declares a layout that shows an image with its title on top -of it. The structure is fairly simple; a {@link android.widget.FrameLayout} is -used to stack a {@link android.widget.TextView} on top of an -{@link android.widget.ImageView}:

    - -
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -    android:layout_width="fill_parent"
    -    android:layout_height="fill_parent">
    -
    -    <ImageView  
    -        android:layout_width="fill_parent" 
    -        android:layout_height="fill_parent" 
    -    
    -        android:scaleType="center"
    -        android:src="@drawable/golden_gate" />
    -    
    -    <TextView
    -        android:layout_width="wrap_content" 
    -        android:layout_height="wrap_content" 
    -        android:layout_marginBottom="20dip"
    -        android:layout_gravity="center_horizontal|bottom"
    -
    -        android:padding="12dip"
    -        
    -        android:background="#AA000000"
    -        android:textColor="#ffffffff"
    -        
    -        android:text="Golden Gate" />
    -
    -</FrameLayout>
    - -

    This layout renders nicely and nothing seems wrong with it:

    - -
    A FrameLayout is used to overlay a title on top of an image
    - -

    Things get more interesting when you inspect the result with HierarchyViewer. -If you look closely at the resulting tree, you will notice that the -FrameLayout defined in our XML file (highlighted in blue below) is -the sole child of another FrameLayout:

    - -
    A layout with only one child of same dimensions can be removed
    - -

    Since our FrameLayout has the same dimension as its parent, by -the virtue of using the fill_parent constraints, and does not -define any background, extra padding or a gravity, it is totally -useless. We only made the UI more complex for no good reason. But how could -we get rid of this FrameLayout? After all, XML documents require a -root tag and tags in XML layouts always represent view instances.

    - -

    That's where the <merge /> tag comes in handy. When the -{@link android.view.LayoutInflater} encounters this tag, it skips it and adds -the <merge /> children to the <merge /> -parent. Confused? Let's rewrite our previous XML layout by replacing the -FrameLayout with <merge />:

    - -
    <merge xmlns:android="http://schemas.android.com/apk/res/android">
    -
    -    <ImageView  
    -        android:layout_width="fill_parent" 
    -        android:layout_height="fill_parent" 
    -    
    -        android:scaleType="center"
    -        android:src="@drawable/golden_gate" />
    -    
    -    <TextView
    -        android:layout_width="wrap_content" 
    -        android:layout_height="wrap_content" 
    -        android:layout_marginBottom="20dip"
    -        android:layout_gravity="center_horizontal|bottom"
    -
    -        android:padding="12dip"
    -        
    -        android:background="#AA000000"
    -        android:textColor="#ffffffff"
    -        
    -        android:text="Golden Gate" />
    -
    -</merge>
    - -

    With this new version, both the TextView and the -ImageView will be added directly to the top-level -FrameLayout. The result will be visually the same but the view -hierarchy is simpler:

    - -
    Optimized view hierarchy using the merge tag
    - -

    Obviously, using <merge /> works in this case because the -parent of an activity's content view is always a FrameLayout. You -could not apply this trick if your layout was using a LinearLayout -as its root tag for instance. The <merge /> can be useful in -other situations though. For instance, it works perfectly when combined with the -<include /> tag. You can also use <merge -/> when you create a custom composite view. Let's see how we can use -this tag to create a new view called OkCancelBar which simply shows -two buttons with customizable labels. You can also download the complete -source code of this example. Here is the XML used to display this custom -view on top of an image:

    - -
    <merge
    -    xmlns:android="http://schemas.android.com/apk/res/android"
    -    xmlns:okCancelBar="http://schemas.android.com/apk/res/com.example.android.merge">
    -
    -    <ImageView  
    -        android:layout_width="fill_parent" 
    -        android:layout_height="fill_parent" 
    -    
    -        android:scaleType="center"
    -        android:src="@drawable/golden_gate" />
    -    
    -    <com.example.android.merge.OkCancelBar
    -        android:layout_width="fill_parent" 
    -        android:layout_height="wrap_content" 
    -        android:layout_gravity="bottom"
    -
    -        android:paddingTop="8dip"
    -        android:gravity="center_horizontal"
    -        
    -        android:background="#AA000000"
    -        
    -        okCancelBar:okLabel="Save"
    -        okCancelBar:cancelLabel="Don't save" />
    -
    -</merge>
    - -

    This new layout produces the following result on a device:

    - -
    Creating a custom view with the merge tag
    - -

    The source code of OkCancelBar is very simple because the two -buttons are defined in an external XML file, loaded using a -LayoutInflate. As you can see in the following snippet, the XML -layout R.layout.okcancelbar is inflated with the -OkCancelBar as the parent:

    - -
    public class OkCancelBar extends LinearLayout {
    -    public OkCancelBar(Context context, AttributeSet attrs) {
    -        super(context, attrs);
    -        setOrientation(HORIZONTAL);
    -        setGravity(Gravity.CENTER);
    -        setWeightSum(1.0f);
    -        
    -        LayoutInflater.from(context).inflate(R.layout.okcancelbar, this, true);
    -        
    -        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OkCancelBar, 0, 0);
    -        
    -        String text = array.getString(R.styleable.OkCancelBar_okLabel);
    -        if (text == null) text = "Ok";
    -        ((Button) findViewById(R.id.okcancelbar_ok)).setText(text);
    -        
    -        text = array.getString(R.styleable.OkCancelBar_cancelLabel);
    -        if (text == null) text = "Cancel";
    -        ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text);
    -        
    -        array.recycle();
    -    }
    -}
    - -

    The two buttons are defined in the following XML layout. As you can see, we -use the <merge /> tag to add the two buttons directly to the -OkCancelBar. Each button is included from the same external XML -layout file to make them easier to maintain; we simply override their id:

    - -
    <merge xmlns:android="http://schemas.android.com/apk/res/android">
    -    <include
    -        layout="@layout/okcancelbar_button"
    -        android:id="@+id/okcancelbar_ok" />
    -        
    -    <include
    -        layout="@layout/okcancelbar_button"
    -        android:id="@+id/okcancelbar_cancel" />
    -</merge>
    - -

    We have created a flexible and easy to maintain custom view that generates -an efficient view hierarchy:

    - -
    The resulting hierarchy is simple and efficient
    - -

    The <merge /> tag is extremely useful and can do wonders -in your code. However, it suffers from a couple of limitations:

    - -
      -
    • <merge /> can only be used as the root tag of an XML layout
    • -
    • When inflating a layout starting with a <merge />, you must -specify a parent ViewGroup and you must set attachToRoot to -true (see the documentation for -{@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)} method)
    • -
    - diff --git a/docs/html/resources/articles/layout-tricks-reuse.jd b/docs/html/resources/articles/layout-tricks-reuse.jd deleted file mode 100644 index 179c1d8e0e3e4a21bdbe52c31088ba1ba5bbaa88..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/layout-tricks-reuse.jd +++ /dev/null @@ -1,81 +0,0 @@ -page.title=Layout Tricks: Creating Reusable UI Components -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    The Android platform offers a wide variety of UI widgets, small -visual construction blocks that you can glue together to present users with -complex and useful interfaces. However applications often need higher-level -visual components. To meet that need, and to do so efficiently, you can -combine multiple standard widgets into a single, reusable component.

    - -

    For example, you could create a reusable component that contains a progress -bar and a cancel button, a panel containing two buttons (positive and negative -actions), a panel with an icon, a title and a description, and so on. You can -create UI components easily by writing a custom View, but you can -do it even more easily using only XML.

    - -

    In Android XML layout files, each tag is mapped to an actual class instance -(the class is always a subclass of {@link android.view.View} The UI toolkit lets -you also use three special tags that are not mapped to a View -instance: <requestFocus />, <merge /> and -<include />. This article shows how to use <include -/> to create pure XML visual components. For information about how to -use <merge />, which can be particularly powerful when -combined with <include />see the Merging Layouts -article.

    - -

    The <include /> element does exactly what its name -suggests; it includes another XML layout. Using this tag is straightforward as -shown in the following example, taken straight from the source code of the Home application -that ships with Android:

    - -
    <com.android.launcher.Workspace
    -    android:id="@+id/workspace"
    -    android:layout_width="fill_parent"
    -    android:layout_height="fill_parent"
    -
    -    launcher:defaultScreen="1">
    -
    -    <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
    -    <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
    -    <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
    -
    -</com.android.launcher.Workspace>
    - -

    In the <include /> only the layout attribute -is required. This attribute, without the android namespace prefix, -is a reference to the layout file you wish to include. In this example, the same -layout is included three times in a row. This tag also lets you override a few -attributes of the included layout. The above example shows that you can use -android:id to specify the id of the root view of the included -layout; it will also override the id of the included layout if one is defined. -Similarly, you can override all the layout parameters. This means that any -android:layout_* attribute can be used with the <include -/> tag. Here is an example in -which the same layout is included twice, but only the first one overrides the layout properties:

    - -
    -<!-- override the layout height and width -->
    -<include layout="@layout/image_holder"
    -    android:layout_height="fill_parent"
    -    android:layout_width="fill_parent" />
    -<!-- do not override layout dimensions; inherit them from image_holder -->
    -<include layout="@layout/image_holder" />
    -
    - -

    Caution: If you want to override the layout dimensions, -you must override both android:layout_height and -android:layout_width—you cannot override only the height or only the width. -If you override only one, it will not take effect. (Other layout properties, such as weight, -are still inherited from the source layout.)

    - -

    This tag is particularly useful when you need to customize only part of your -UI depending on the device's configuration. For instance, the main layout of -your activity can be placed in the layout/ directory and can -include another layout which exists in two flavors, in layout-land/ -and layout-port/. This allows you to share most of the UI in -portrait and landscape.

    \ No newline at end of file diff --git a/docs/html/resources/articles/layout-tricks-stubs.jd b/docs/html/resources/articles/layout-tricks-stubs.jd deleted file mode 100644 index 64f07f981bef064887d9909cfc32aa5ae37e6ce8..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/layout-tricks-stubs.jd +++ /dev/null @@ -1,86 +0,0 @@ -page.title=Layout Tricks: Using ViewStubs -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Sharing and reusing UI components is very easy with Android, thanks to the <include /> tag. Sometimes it's so -easy to create complex UI constructs that your UI ends up with a large number of -views, some of which are rarely used. Thankfully, Android offers a very special -widget called {@link android.view.ViewStub}, which brings you all the benefits -of the <include /> without polluting your user interface with -rarely used views.

    - -

    A ViewStub is a dumb and lightweight view. It has no dimension, -it does not draw anything and does not participate in the layout in any way. -This means that a ViewStub is very cheap to inflate and very cheap -to keep in a view hierarchy. A ViewStub can be best described as a -lazy include. The layout referenced by a ViewStub is -inflated and added to the user interface only when you decide so.

    - -

    The following screenshot comes from the Shelves application. The main purpose of -the activity shown in the screenshot is to present the user with a browsable -list of books:

    - - - -

    The same activity is also used when the user adds or imports new books. -During such an operation, Shelves shows extra bits of user interface. -The screenshot below shows the progress bar and cancel button that -appear at the bottom of the screen during an import:

    - - - -

    Because importing books is not a common operation, at least when compared to -browsing the list of books, the import panel is originally represented -by a ViewStub:

    - - - -

    When the user initiates the import process, the ViewStub is -inflated and replaced by the content of the layout file it references:

    - - - -

    To use a ViewStub, all you need is to specify an -android:id attribute, to later inflate the stub, and an -android:layout attribute, to reference what layout file -to include and inflate. A stub lets you use a third attribute, -android:inflatedId, which can be used to override the -id of the root of the included file. Finally, the layout -parameters specified on the stub will be applied to the roof of the -included layout. Here is an example:

    - -
    <ViewStub
    -  android:id="@+id/stub_import"
    -  android:inflatedId="@+id/panel_import"
    -
    -  android:layout="@layout/progress_overlay"
    -
    -  android:layout_width="fill_parent"
    -  android:layout_height="wrap_content"
    -  android:layout_gravity="bottom" />
    - -

    When you are ready to inflate the stub, simply invoke the -{@link android.view.ViewStub#inflate()} method. You can also simply change the -visibility of the stub to {@link android.view.View#VISIBLE} or -{@link android.view.View#INVISIBLE} and the stub will inflate. Note however that the -inflate() method has the benefit of returning the root -View of the inflate layout:

    - -
    ((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
    -// or
    -View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
    - -

    It is very important to remember that after the stub is inflated, the stub is -removed from the view hierarchy. As such, it is unnecessary to keep a -long-lived reference, for instance in an class instance field, to a -ViewStub.

    - -

    A ViewStub is a great compromise between ease of programming and -efficiency. Instead of inflating views manually and adding them at runtime to -your view hierarchy, simply use a ViewStub. It's cheap and easy. -The only drawback of ViewStub is that it currently does -not support the <merge /> -tag.

    diff --git a/docs/html/resources/articles/listview-backgrounds.jd b/docs/html/resources/articles/listview-backgrounds.jd deleted file mode 100644 index c4037bace625295c17bbdbd507f3db6e156c57b0..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/listview-backgrounds.jd +++ /dev/null @@ -1,88 +0,0 @@ -page.title=ListView Backgrounds: An Optimization -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    {@link android.widget.ListView} is one of Android's most widely used widgets. -It is rather easy to use, very flexible, and incredibly powerful. -ListView can also be difficult to understand at times.

    - -

    One of the most common issues with ListView happens when you try -to use a custom background. By default, like many Android widgets, -ListView has a transparent background which means that you can see -through the default window's background, a very dark gray -(#FF191919 with the current dark theme.) Additionally, -ListView enables the fading edges by default, as you can -see at the top of the following screenshot — the first text item gradually -fades to black. This technique is used throughout the system to indicate that -the container can be scrolled.

    - -
    Android's default ListView
    - -

    The fade effect is implemented using a combination of -{@link android.graphics.Canvas#saveLayerAlpha(float, float, float, float, int, int) Canvas.saveLayerAlpha()} -and the {@link android.graphics.PorterDuff.Mode#DST_OUT Porter-Duff Destination Out blending mode}.

    - -

    Unfortunately, things start to get ugly when you try to use a custom -background on the ListView or when you change the window's -background. The following two screenshots show what happens in an application -when you change the window's background. The left image shows what the list -looks like by default and the right image shows what the list looks like during -a scroll initiated with a touch gesture:

    - -
    -Dark fade -Dark list
    - -

    This rendering issue is caused by an optimization of the Android framework -enabled by default on all instances of ListView. I mentioned -earlier that the fade effect is implemented using a Porter-Duff blending mode. -This implementation works really well but is unfortunately very costly and can -bring down drawing performance by quite a bit as it requires to capture a -portion of the rendering in an offscreen bitmap and then requires extra blending -(which implies readbacks from memory.)

    - -

    Since ListView is most of the time displayed on a solid -background, there is no reason to go down that expensive route. That's why we -introduced an optimization called the "cache color hint." The cache color hint -is an RGB color set by default to the window's background color, that is #191919 -in Android's dark theme. When this hint is set, ListView (actually, -its base class View) knows it will draw on a solid background and -therefore replaces th expensive saveLayerAlpha()/Porter-Duff -rendering with a simple gradient. This gradient goes from fully transparent to -the cache color hint value and this is exactly what you see on the image above, -with the dark gradient at the bottom of the list. However, this still does not -explain why the entire list turns black during a scroll.

    - -

    As mentioned before, ListView has a transparent/translucent -background by default, and so all default widgets in the Android UI toolkit. -This implies that when ListView redraws its children, it has to -blend the children with the window's background. Once again, this requires -costly readbacks from memory that are particularly painful during a scroll or a -fling when drawing happens dozen of times per second.

    - -

    To improve drawing performance during scrolling operations, the Android -framework reuses the cache color hint. When this hint is set, the framework -copies each child of the list in a Bitmap filled with the hint -value (assuming that another optimization, called scrolling cache, is -not turned off). ListView then blits these bitmaps directly on -screen and because these bitmaps are known to be opaque, no blending is -required. Also, since the default cache color hint is #191919, you -get a dark background behind each item during a scroll.

    - -

    To fix this issue, all you have to do is either disable the cache color hint -optimization, if you use a non-solid color background, or set the hint to the -appropriate solid color value. You can do this from code (see -{@link android.widget.AbsListView#setCacheColorHint(int)}) or preferably from -XML, by using the android:cacheColorHint attribute. To disable the -optimization, simply use the transparent color #00000000. The -following screenshot shows a list with -android:cacheColorHint="#00000000" set in the XML layout file:

    - -
    Fade on a custom background
    - -

    As you can see, the fade works perfectly against the custom wooden -background. The cache color hint feature is interesting because it -shows how optimizations can make your life more difficult in -some situations. In this particular case, however, the benefit of the -default behavior outweighs the added complexity..

    diff --git a/docs/html/resources/articles/live-folders.jd b/docs/html/resources/articles/live-folders.jd deleted file mode 100644 index aeab9974c1c65729ca96bd2f4679e975491126ef..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/live-folders.jd +++ /dev/null @@ -1,170 +0,0 @@ -page.title=Live Folders -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Live folders, introduced in Android 1.5 (API Level 3), let you display any source of data -on the Home screen without forcing the user to launch an application. A live -folder is simply a real-time view of a {@link android.content.ContentProvider}. -As such, a live folder can be used to display all of the user's contacts or -bookmarks, email, playlists, an RSS feed, and so on. The possibilities are -endless!

    - -

    The platform includes several standard folders for displaying contacts. For -instance, the screenshot below shows the content of the live folders that -displays all contacts with a phone number:

    - - - -

    If a contacts sync happens in the background while the user is browsing this live -folder, the user will see the change happen in real-time. Live folders are not -only useful, but they are also easy to add to to your application and data. - -This articles shows how to add a live folder to an example application called -Shelves. To better understand how live folders work, you can download the source code of the -application and modify it by following the instructions below.

    - -

    To give the user the option to create a new live folder for an application, -you first need to create a new activity with an intent filter whose action is -android.intent.action.CREATE_LIVE_FOLDER. To do so, simply open -AndroidManifest.xml and add something similar to this:

    - -
    <activity
    -    android:name=".activity.BookShelfLiveFolder"
    -    android:label="BookShelf">
    -    <intent-filter>	
    -        <action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
    -        <category android:name="android.intent.category.DEFAULT" />
    -    </intent-filter>
    -</activity>
    - -

    The label and icon of this activity are what the user will see on the Home -screen when choosing a live folder to create:

    - - - -

    Since you just need an intent filter, it is possible, and sometimes advised, -to reuse an existing activity. In the case of Shelves, we will create a new -activity, org.curiouscreature.android.shelves.activity.BookShelfLiveFolder. -The role of this activity is to send an Intent result to Home -containing the description of the live folder: its name, icon, display mode and -content URI. The content URI is very important as it describes what -ContentProvider will be used to populate the live folder. The code -of the activity is very simple as you can see here:

    - -
    public class BookShelfLiveFolder extends Activity {
    -    public static final Uri CONTENT_URI = Uri.parse("content://shelves/live_folders/books");
    -
    -    @Override
    -    protected void onCreate(Bundle savedInstanceState) {
    -        super.onCreate(savedInstanceState);
    -
    -        final Intent intent = getIntent();
    -        final String action = intent.getAction();
    -
    -        if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
    -            setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
    -                    "Books", R.drawable.ic_live_folder));
    -        } else {
    -            setResult(RESULT_CANCELED);
    -        }
    -
    -        finish();
    -    }
    -
    -    private static Intent createLiveFolder(Context context, Uri uri, String name, int icon) {
    -        final Intent intent = new Intent();
    -
    -        intent.setData(uri);
    -        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
    -        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
    -                Intent.ShortcutIconResource.fromContext(context, icon));
    -        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);
    -
    -        return intent;
    -    }
    -}
    - -

    This activity, when invoked with theACTION_CREATE_LIVE_FOLDER -intent, returns an intent with a URI, -content://shelves/live_folders/books, and three extras to describe -the live folder. There are other extras and constants you can use and you should -refer to the documentation of android.provider.LiveFolders for more -details. When Home receives this intent, a new live folder is created on the -user's desktop, with the name and icon you provided. Then, when the user clicks -on the live folder to open it, Home queries the content provider referenced by -the provided URI.

    - -

    Live folders' content providers must obey specific naming rules. The -Cursor returned by the query() method must have at -least two columns named LiveFolders._ID and -LiveFolders.NAME. The first one is the unique identifier of each -item in the live folder and the second one is the name of the item. There are -other column names you can use to specify an icon, a description, the intent to -associate with the item (fired when the user clicks that item), etc. Again, -refer to the documentation of android.provider.LiveFolders for more -details.

    In our example, all we need to do is modify the existing provider -in Shelves called -org.curiouscreature.android.shelves.provider.BooksProvider. First, -we need to modify the URI_MATCHER to recognize our -content://shelves/live_folders/books content URI:

    - -
    private static final int LIVE_FOLDER_BOOKS = 4;
    -// ...
    -URI_MATCHER.addURI(AUTHORITY, "live_folders/books", LIVE_FOLDER_BOOKS);
    - -

    Then we need to create a new projection map for the cursor. A projection map -can be used to "rename" columns. In our case, we will replace -BooksStore.Book._ID, BooksStore.Book.TITLE and -BooksStore.Book.AUTHORS with LiveFolders._ID, -LiveFolders.TITLE and LiveFolders.DESCRIPTION:

    - -
    private static final HashMap<string, string=""> LIVE_FOLDER_PROJECTION_MAP;
    -static {
    -    LIVE_FOLDER_PROJECTION_MAP = new HashMap<string, string="">();
    -    LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders._ID, BooksStore.Book._ID +
    -            " AS " + LiveFolders._ID);
    -    LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.NAME, BooksStore.Book.TITLE +
    -            " AS " + LiveFolders.NAME);
    -    LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.DESCRIPTION, BooksStore.Book.AUTHORS +
    -            " AS " + LiveFolders.DESCRIPTION);
    -}
    - -

    Because we are providing a title and a description for each row, Home will -automatically display each item of the live folder with two lines of text. -Finally, we implement the query() method by supplying our -projection map to the SQL query builder:

    - -
    public Cursor query(Uri uri, String[] projection, String selection,
    -        String[] selectionArgs, String sortOrder) {
    -
    -    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    -
    -    switch (URI_MATCHER.match(uri)) {
    -        // ...
    -        case LIVE_FOLDER_BOOKS:
    -            qb.setTables("books");
    -            qb.setProjectionMap(LIVE_FOLDER_PROJECTION_MAP);
    -            break;
    -        default:
    -            throw new IllegalArgumentException("Unknown URI " + uri);
    -    }
    -
    -    SQLiteDatabase db = mOpenHelper.getReadableDatabase();
    -    Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, BooksStore.Book.DEFAULT_SORT_ORDER);
    -    c.setNotificationUri(getContext().getContentResolver(), uri);
    -
    -    return c;
    -}
    - -

    You can now compile and deploy the application, go to the Home screen and -try to add a live folder. You can add a books live folder to your Home screen -and when you open it, see the list of all of your books, with their -titles and authors, and all it took was a few lines of code:

    - -

    - -

    The live folders API is extremely simple and relies only on intents and -content URI. If you want to see more examples of live folders -implementation, you can read the source code of the Contacts application and of the Contacts provider.

    You can also download the result of our exercise, the modified version of Shelves with live folders support.

    \ No newline at end of file diff --git a/docs/html/resources/articles/live-wallpapers.jd b/docs/html/resources/articles/live-wallpapers.jd deleted file mode 100644 index 0692a626f766610017675c74d48e89f1eab3f777..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/live-wallpapers.jd +++ /dev/null @@ -1,102 +0,0 @@ -page.title=Live Wallpapers -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -
    -
    - -

    See also

    -
      -
    1. Live Wallpaper -sample
    2. -
    - -
    -
    - -

    Starting with Android 2.1 (API Level 7), users can now enjoy live -wallpapers — richer, animated, interactive backgrounds — on -their home screens. A live wallpaper is very similar to a normal Android -application and has access to all the facilities of the platform: SGL (2D -drawing), OpenGL (3D drawing), GPS, accelerometers, network access, etc. The -live wallpapers included on Nexus One demonstrate the use of some of these APIs -to create fun and interesting user experiences. For instance, the Grass -wallpaper uses the phone's location to compute sunrise and sunset times in order -to display the appropriate sky.

    - - - -

    Creating your own live wallpaper is easy, especially if you have had -previous experience with {@link android.view.SurfaceView} or {@link -android.graphics.Canvas}. -To learn how to create a live wallpaper, you should check out the CubeLiveWallpaper sample code.

    - -

    In terms of implementation, a live wallpaper is very similar to a {@link android.app.Service}. -The only difference is the addition of a new method, {@link -android.service.wallpaper.WallpaperService#onCreateEngine()}, whose goal is to create a {@link -android.service.wallpaper.WallpaperService.Engine}. The engine is responsible for -handling the lifecycle and drawing of a wallpaper. The system provides a surface -on which you can draw, just like you would with a {@link android.view.SurfaceView}. -Drawing a wallpaper can be very expensive so you should optimize your code -as much as possible to avoid using too much CPU, not only for battery life -but also to avoid slowing down the rest of the system. That is also why the -most important part of the lifecycle of a wallpaper is when it becomes visible, as indicated -by a call to {@link android.service.wallpaper.WallpaperService.Engine#onVisibilityChanged -onVisibilityChanged()}. -When invisible, such as when the user launches an application that covers -the home screen, a wallpaper must stop all activity.

    - -

    The engine can also implement several methods to interact with the user -or the home application. For instance, if you want your wallpaper to scroll -along when the user swipes from one home screen to another, you can use -{@link android.service.wallpaper.WallpaperService.Engine#onOffsetsChanged -onOffsetsChanged()}. -To react to touch events, simply implement {@link -android.service.wallpaper.WallpaperService.Engine#onTouchEvent onTouchEvent()}. -Finally, applications can send arbitrary commands to the live wallpaper. -Currently, only the standard home application sends commands to the -{@link android.service.wallpaper.WallpaperService.Engine#onCommand onCommand()} -method of the live wallpaper:

    - -
      -
    • android.wallpaper.tap: When the user taps an empty space -on the workspace. This command is interpreted by the Nexus and Water live -wallpapers to make the wallpaper react to user interaction. For instance, -if you tap an empty space on the Water live wallpaper, new ripples appear -under your finger.
    • -
    • android.home.drop: When the user drops an icon or a widget -on the workspace. This command is also interpreted by the Nexus and Water -live wallpapers.
    • -
    - -

    If you are developing a live wallpaper, remember that the feature is -supported only on Android 2.1 (API level 7) and higher versions of the platform. -To ensure that your application can only be installed on devices that support -live wallpapers, remember to add the following to the application's manifest -before publishing to Google Play:

    - -
      -
    • <uses-sdk android:minSdkVersion="7" />, which indicates -to Google Play and the platform that your application requires Android 2.1 or -higher. For more information, see the API -Levels and the documentation for the -<uses-sdk> -element.
    • -
    • <uses-feature android:name="android.software.live_wallpaper" />, -which tells Google Play that your application includes a live wallpaper -Google Play uses this feature as a filter, when presenting users lists of -available applications. When you declaring this feature, Google Play -displays your application only to users whose devices support live wallpapers, -while hiding it from other devices on which it would not be able to run. For -more information, see the documentation for the -{@code -<uses-feature> -element.
    • -
    - -

    Many great live wallpapers are already available on Google Play and -we can't wait to see more!

    diff --git a/docs/html/resources/articles/multitasking-android-way.jd b/docs/html/resources/articles/multitasking-android-way.jd deleted file mode 100644 index 0dc862728aa3e3362a54cf211b7f88f9154842a0..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/multitasking-android-way.jd +++ /dev/null @@ -1,103 +0,0 @@ -page.title=Multitasking the Android Way -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -
    -
    - -

    See also

    -
      -
    1. Tasks and Back Stack
    2. -
    3. Services
    4. -
    - -

    Key classes

    -
      -
    1. {@link android.app.Service}
    2. -
    3. {@link android.content.BroadcastReceiver}
    4. -
    - -
    -
    - -

    Android is fairly unique in the ways it allows multiple applications to run at the same time. Developers coming from a different platform may find the way it operates surprising. Understanding its behavior is important for designing applications that will work well and integrate seamlessly with the rest of the Android platform. This article covers the reasons for Android's multitasking design, its impact on how applications work, and how you can best take advantage of Android's unique features.

    -

    Design considerations

    -

    Mobile devices have technical limitations and user experience requirements not present in desktop or web systems. Here are the four key constraints we were working under as we designed Android's multitasking:

    -
      -
    • -

      We did not want to require that users close applications when "done" with them. Such a usage pattern does not work well in a mobile environment, where usage tends to involve repeated brief contact with a wide variety of applications throughout the day.

      -
    • -
    • -

      Mobile devices don't have the luxury of swap space, so have fairly hard limits on memory use. Robert Love has a very good article covering the topic.

      -
    • -
    • -

      Application switching on a mobile device is extremely critical; we target significantly less than 1 second to launch a new application. This is especially important when the user is switching between a few applications, such as switching to look at a new SMS message while watching a video, and then returning to that video. A noticeable wait in such situations will quickly make users hate you.

      -
    • -
    • -

      The available APIs must be sufficient for writing the built-in Google applications, as part of our "all applications are created equal" philosophy. This means background music playback, data syncing, GPS navigation, and application downloading must be implemented with the same APIs that are available to third party developers.

      -
    • -
    -

    The first two requirements highlight an interesting conflict. We don't want users to worry about closing their apps, but rather make it appear that all of the applications are always running. At the same time, mobile devices have hard limits on memory use, so that a system will degrade or even start failing very quickly as it needs more RAM than is available; a desktop computer, with swap, in contrast will simply start slowing down as it needs to page RAM to its swap space. These competing constraints were a key motivation for Android's design.

    -

    When does an application "stop"?

    -

    A common misunderstanding about Android multitasking is the difference between a process and an application. In Android these are not tightly coupled entities: applications may seem present to the user without an actual process currently running the app; multiple applications may share processes, or one application may make use of multiple processes depending on its needs; the process(es) of an application may be kept around by Android even when that application is not actively doing something.

    -

    The fact that you can see an application's process "running" does not mean the application is running or doing anything. It may simply be there because Android needed it at some point, and has decided that it would be best to keep it around in case it needs it again. Likewise, you may leave an application for a little bit and return to it from where you left off, and during that time Android may have needed to get rid of the process for other things.

    -

    A key to how Android handles applications in this way is that processes don't shut down cleanly. When the user leaves an application, its process is kept around in the background, allowing it to continue working (for example downloading web pages) if needed, and come immediately to the foreground if the user returns to it. If a device never runs out of memory, then Android will keep all of these processes around, truly leaving all applications "running" all of the time.

    -

    Of course, there is a limited amount of memory, and to accommodate this Android must decide when to get rid of processes that are not needed. This leads to Android's process lifecycle, the rules it uses to decide how important each process is and thus the next one that should be dropped. These rules are based on both how important a process is for the user's current experience, as well as how long it has been since the process was last needed by the user.

    -

    Once Android determines that it needs to remove a process, it does this brutally, simply force-killing it. The kernel can then immediately reclaim all resources needed by the process, without relying on that application being well written and responsive to a polite request to exit. Allowing the kernel to immediately reclaim application resources makes it a lot easier to avoid serious out of memory situations.

    -

    If a user later returns to an application that's been killed, Android needs a way to re-launch it in the same state as it was last seen, to preserve the "all applications are running all of the time" experience. This is done by keeping track of the parts of the application the user is aware of (the Activities), and re-starting them with information about the last state they were seen in. This last state is generated each time the user leaves that part of the application, not when it is killed, so that the kernel can later freely kill it without depending on the application to respond correctly at that point.

    -

    In some ways, Android's process management can be seen as a form of swap space: application processes represent a certain amount of in-use memory; when memory is low, some processes can be killed (swapped out); when those processes are needed again, they can be re-started from their last saved state (swapped in).

    -

    Explicitly running in the background

    -

    So far, we have a way for applications to implicitly do work in the background, as long as the process doesn't get killed by Android as part of its regular memory management. This is fine for things like loading web pages in the background, but what about features with harder requirements? Background music playback, data synchronization, location tracking, alarm clocks, etc.

    -

    -

    For these tasks, the application needs a way to tell Android "I would explicitly like to run at this point." There are two main facilities available to applications for this, represented by two kinds of components they can publish in their manifest: broadcast receivers and services.

    -

    Broadcast Receivers

    -

    A BroadcastReceiver allows an application to run, for a brief amount of time, in the background as a result of something else happening. It can be used in many ways to build higher-level facilities: for example the AlarmManager allows an application to have a broadcast sent at a certain time in the future, and the LocationManager can send a broadcast when it detects interesting changes in location. Because information about the receiver is part of an application's manifest, Android can find and launch the application even if it isn't running; of course if it already has its process available in the background, the broadcast can very efficiently be directly dispatched to it.

    -

    When handling a broadcast, the application is given a fixed set of time (currently 10 seconds) in which to do its work. If it doesn't complete in that time, the application is considered to be misbehaving, and its process immediately tossed into the background state to be killed for memory if needed.

    -

    Broadcast receivers are great for doing small pieces of work in response to an external stimulus, such as posting a notification to the user after being sent a new GPS location report. They are very lightweight, since the application's process only needs to be around while actively receiving the broadcast. Because they are active for a deterministic amount of time, fairly strong guarantees can be made about not killing their process while running. However they are not appropriate for anything of indeterminate length, such as networking.

    -

    Services

    -

    A Service allows an application to implement longer-running background operations. There are actually a lot of other functions that services provide, but for the discussion here their fundamental purpose is for an application to say "hey I would like to continue running even while in the background, until I say I am done." An application controls when its service runs by explicitly starting and stopping the service.

    -

    While services do provide a rich client-server model, its use is optional. Upon starting an application's services, Android simply instantiates the component in the application's process to provide its context. How it is used after that is up to the application: it can put all of the needed code inside of the service itself without interacting with other parts of the application, make calls on other singleton objects shared with other parts of the app, directly retrieve the Service instance from elsewhere if needed, or run it in another process and do a full-blown RPC protocol if that is desired.

    -

    Process management for services is different than broadcast receivers, because an unbounded number of services can ask to be running for an unknown amount of time. There may not be enough RAM to have all of the requesting services run, so as a result no strong guarantees are made about being able to keep them running.

    -

    If there is too little RAM, processes hosting services will be immediately killed like background processes are. However, if appropriate, Android will remember that these services wish to remain running, and restart their process at a later time when more RAM is available. For example, if the user goes to a web page that requires large amounts of RAM, Android may kill background service processes like sync until the browser's memory needs go down.

    -

    Services can further negotiate this behavior by requesting they be considered "foreground." This places the service in a "please don't kill" state, but requires that it include a notification to the user about it actively running. This is useful for services such as background music playback or car navigation, which the user is actively aware of; when you're playing music and using the browser, you can always see the music-playing glyph in the status bar. Android won't try to kill these services, but as a trade-off, ensures the user knows about them and is able to explicitly stop them when desired.

    -

    The value of generic components

    -

    Android's generic broadcast receiver and service components allow developers to create a wide variety of efficient background operations, including things that were never originally considered. In Android 1.0 they were used to implement nearly all of the background behavior that the built-in and proprietary Google apps provided:

    -
      -
    • - Music playback runs in a service to allow it to continue operating after the user leaves the music application. -
    • -
    • - The alarm clock schedules a broadcast receiver with the alarm manager, to go off at the next set alarm time. -
    • -
    • - The calendar application likewise schedules an alarm to display or update its notification at the appropriate time for the next calendar event. -
    • -
    • - Background file download is implemented a service that runs when there are any downloads to process. -
    • -
    • - The e-mail application schedules an alarm to wake up a service at regular intervals that looks for and retrieves any new mail. -
    • -
    • - The Google applications maintain a service to receive push notifications from the network; it in turn sends broadcasts to individual apps when it is told that they need to do things like synchronize contacts.

      -
    • -
    -

    As the platform has evolved, these same basic components have been used to implement many of the major new developer features: -

      -
    • - Input methods are implemented by developers as a Service component that Android manages and works with to display as the current IME. -
    • -
    • - Application widgets are broadcast receivers that Android sends broadcasts to when it needs to interact with them. This allows app widgets to be quite lightweight, by not needing their application's process remain running. -
    • -
    • - Accessibility features are implemented as services that Android keeps running while in use and sends appropriate information to about user interactions. -
    • -
    • - Sync adapters introduced in Android 2.0 are services that are run in the background when a particular data sync needs to be performed. -
    • -
    • - Live wallpapers are a service started by Android when selected by the user. -
    • -
    diff --git a/docs/html/resources/articles/on-screen-inputs.jd b/docs/html/resources/articles/on-screen-inputs.jd deleted file mode 100644 index 6a028c8ea2316bdf54d7d87453d298893eecd754..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/on-screen-inputs.jd +++ /dev/null @@ -1,265 +0,0 @@ -page.title=Onscreen Input Methods -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -
    - -
    - - -

    Starting from Android 1.5, the Android platform offers an Input Method -Framework (IMF) that lets you create on-screen input methods such as software -keyboards. This article provide an overview of what Android input method editors -(IMEs) are and what an application needs to do to work well with them. The IMF -is designed to support new classes of Android devices, such as those without -hardware keyboards, so it is important that your application works well with the -IMF and offers a great experience for users.

    - -

    What is an input method?

    - -

    The Android IMF is designed to support a variety of IMEs, including soft -keyboard, hand-writing recognizers, and hard keyboard translators. Our focus, -however, will be on soft keyboards, since this is the kind of input method that -is currently part of the platform.

    - -

    A user will usually access the current IME by tapping on a text view to -edit, as shown here in the home screen:

    - - - - -

    The soft keyboard is positioned at the bottom of the screen over the -application's window. To organize the available space between the application -and IME, we use a few approaches; the one shown here is called pan and -scan, and simply involves scrolling the application window around so that -the currently focused view is visible. This is the default mode, since it is the -safest for existing applications.

    - -

    Most often the preferred screen layout is a resize, where the -application's window is resized to be entirely visible. An example is shown -here, when composing an e-mail message:

    - - - - -

    The size of the application window is changed so that none of it is hidden by -the IME, allowing full access to both the application and IME. This of course -only works for applications that have a resizeable area that can be reduced to -make enough space, but the vertical space in this mode is actually no less than -what is available in landscape orientation, so very often an application can -already accommodate it.

    - -

    The final major mode is fullscreen or extract -mode. This is used when the IME is too large to reasonably share space -with the underlying application. With the standard IMEs, you will only -encounter this situation when the screen is in a landscape orientation, -although other IMEs are free to use it whenever they desire. In this -case the application window is left as-is, and the IME simply displays -fullscreen on top of it, as shown here:

    - - - - -

    Because the IME is covering the application, it has its own editing area, -which shows the text actually contained in the application. There are also some -limited opportunities the application has to customize parts of the IME (the -"done" button at the top and enter key label at the bottom) to improve the user -experience.

    - -

    Basic XML attributes for controlling IMEs

    - -

    There are a number of things the system does to try to help existing -applications work with IMEs as well as possible, such as:

    - -
      -
    • Use pan and scan mode by default, unless it can reasonably guess that -resize mode will work by the existence of lists, scroll views, etc.
    • -
    • Analyze the various existing TextView attributes to guess at the kind of -content (numbers, plain text, etc) to help the soft keyboard display an -appropriate key layout.
    • -
    • Assign a few default actions to the fullscreen IME, such as "next field" -and "done".
    • -
    - -

    There are also some simple things you can do in your application that will -often greatly improve its user experience. Except where explicitly mentioned, -these will work in any Android platform version, even those previous to Android -1.5 (since they will simply ignore these new options).

    - -

    Specifying each EditText control's input type

    - -

    The most important thing for an application to do is to use the new -android:inputType -attribute on each EditText. The attribute provides much richer -information -about the text content. This attribute actually replaces many existing -attributes (android:password, -android:singleLine, -android:numeric, -android:phoneNumber, -android:capitalize, -android:autoText, and -android:editable). If you specify the older attributes -and the new android:inputType attribute, the system uses -android:inputType and ignores the others.

    - -

    The android:inputType attribute has three pieces:

    - -
      -
    • The class is the overall interpretation of characters. The -currently supported classes are text (plain text), -number (decimal number), phone (phone number), and -datetime (a date or time).
    • -
    • The variation is a further refinement on the class. In the -attribute you will normally specify the class and variant together, with the -class as a prefix. For example, textEmailAddress is a text field -where the user will enter something that is an e-mail address (foo@bar.com) so -the key layout will have an '@' character in easy access, and -numberSigned is a numeric field with a sign. If only the class is -specified, then you get the default/generic variant.
    • -
    • Additional flags can be specified that supply further refinement. -These flags are specific to a class. For example, some flags for the -text class are textCapSentences, -textAutoCorrect, and textMultiline.
    • -
    - -

    As an example, here is the new EditText for the IM application's message text view:

    - -
        <EditText android:id="@+id/edtInput"
    -        android:layout_width="0dip"
    -        android:layout_height="wrap_content"
    -        android:layout_weight="1"
    -        android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine"
    -        android:imeOptions="actionSend|flagNoEnterAction"
    -        android:maxLines="4"
    -        android:maxLength="2000"
    -        android:hint="@string/compose_hint"/>
    - -

    A full description of all of the input types can be found in the -documentation. It is important to make use of the correct input types that are -available, so that the soft keyboard can use the optimal keyboard layout for the -text the user will be entering.

    - -

    Enabling resize mode and other window features

    - -

    The second most important thing for your app to do is to specify the overall -behavior of your window in relation to the input method. The most visible aspect -of this is controlling resize vs. pan and scan mode, but there are other things -you can do as well to improve your user experience.

    - -

    You will usually control this behavior through the -android:windowSoftInputMode attribute on each -<activity> definition in your -AndroidManifest.xml. Like the input type, there are a couple -different pieces of data that can be specified here by combining them -together:

    - -
      -
    • The window adjustment mode is specified with either -adjustResize or adjustPan. It is highly recommended -that you always specify one or the other.
    • -
    • You can further control whether the IME will be shown automatically when -your activity is displayed and other situations where the user moves to it. The -system won't automatically show an IME by default, but in some cases it can be -convenient for the user if an application enables this behavior. You can request -this with stateVisible. There are also a number of other state -options for finer-grained control that you can find in the documentation.
    • -
    - -

    A typical example of this field can be see in the edit contact activity, -which ensures it is resized and automatically displays the IME for the user:

    - -
        <activity name="EditContactActivity"
    -        android:windowSoftInputMode="stateVisible|adjustResize">
    -        ...
    -    </activity>
    - -

    Note:Starting from Android 1.5 (API Level 3), -the platform offers a new method, -{@link android.view.Window#setSoftInputMode(int mode)}, -that non-Activity windows can use to control their behavior. Calling this method -in your will make your application incompatible with previous versions of the -Android platform.

    - -

    Controlling the action buttons

    - -

    The final customization we will look at is the "action" buttons in the IME. -There are currently two types of actions:

    - -
      -
    • The enter key on a soft keyboard is typically bound to an action when not -operating on a mult-line edit text. For example, on the G1 pressing the hard -enter key will typically move to the next field or the application will -intercept it to execute an action; with a soft keyboard, this overloading of the -enter key remains, since the enter button just sends an enter key event.
    • -
    • When in fullscreen mode, an IME may also put an additional action button to -the right of the text being edited, giving the user quick access to a common -application operation.
    • -
    - -

    These options are controlled with the android:imeOptions -attribute on TextView. The value you supply here can be any -combination of:

    - -
      -
    • One of the pre-defined action constants (actionGo, -actionSearch, actionSend, actionNext, -actionDone). If none of these are specified, the system will infer -either actionNext or actionDone depending on whether -there is a focusable field after this one; you can explicitly force no action -with actionNone.
    • -
    • The flagNoEnterAction option tells the IME that the action -should not be available on the enter key, even if the text itself is -not multi-line. This avoids having unrecoverable actions like (send) that can be -accidentally touched by the user while typing.
    • -
    • The flagNoAccessoryAction removes the action button from the -text area, leaving more room for text.
    • The flagNoExtractUi -completely removes the text area, allowing the application to be seen behind -it.
    • -
    - -

    The previous IM application message view also provides an example of an -interesting use of imeOptions, to specify the send action but not -let it be shown on the enter key:

    - -
    android:imeOptions="actionSend|flagNoEnterAction"
    - -

    APIs for controlling IMEs

    - -

    For more advanced control over the IME, there are a variety of new APIs you -can use. Unless special care is taken (such as by using reflection), using these -APIs will cause your application to be incompatible with previous versions of -Android, and you should make sure you specify -android:minSdkVersion="3" in your manifest. For more information, -see the documentation for the <uses-sdk> manifest element.

    - -

    The primary API is the new android.view.inputmethod.InputMethodManager class, which you can retrieve with Context.getSystemService(). -It allows you to interact with the global input method state, such as -explicitly hiding or showing the current IME's input area.

    - -

    There are also new window flags controlling input method interaction, which you can control through the existing Window.addFlags() method and new Window.setSoftInputMode() method. The PopupWindow -class has grown corresponding methods to control these options on its -window. One thing in particular to be aware of is the new WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM constant, which is used to control whether a window is on top of or behind the current IME.

    - -

    Most of the interaction between an active IME and application is done through the android.view.inputmethod.InputConnection -class. This is the API an application implement, which an IME calls to -perform the appropriate edit operations on the application. You won't -normally need to worry about this, since TextView provides its own implementation for itself.

    - -

    There are also a handful of new View APIs, the most important of these being onCreateInputConnection() which creates a new InputConnection for an IME (and fills in an android.view.inputmethod.EditorInfo -structure with your input type, IME options, and other data); again, -most developers won't need to worry about this, since TextView takes -care of it for you.

    \ No newline at end of file diff --git a/docs/html/resources/articles/painless-threading.jd b/docs/html/resources/articles/painless-threading.jd deleted file mode 100644 index fea7ee21d57ee464eac9475497163d0c17500c3b..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/painless-threading.jd +++ /dev/null @@ -1,149 +0,0 @@ -page.title=Painless Threading -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    This article discusses the threading model used by Android applications and how applications can ensure best UI performance by spawning worker threads to handle long-running operations, rather than handling them in the main thread. The article also explains the API that your application can use to interact with Android UI toolkit components running on the main thread and spawn managed worker threads.

    - -

    The UI thread

    - -

    When an application is launched, the system creates a thread called -"main" for the application. The main thread, also called the UI -thread, is very important because it is in charge of dispatching the -events to the appropriate widgets, including drawing events. -It is also the thread where your application interacts with running -components of the Android UI toolkit.

    - -

    For instance, if you touch the a button on screen, the UI thread dispatches -the touch event to the widget, which in turn sets its pressed state and -posts an invalidate request to the event queue. The UI thread dequeues -the request and notifies the widget to redraw itself.

    - -

    This single-thread model can yield poor performance unless your application -is implemented properly. Specifically, if everything is happening in a single -thread, performing long operations such as network access or database -queries on the UI thread will block the whole user interface. No event -can be dispatched, including drawing events, while the long operation -is underway. From the user's perspective, the application appears hung. -Even worse, if the UI thread is blocked for more than a few seconds -(about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog.

    - -

    If you want to see how bad this can look, write a simple application -with a button that invokes Thread.sleep(2000) in its -OnClickListener. -The button will remain in its pressed state for about 2 seconds before -going back to its normal state. When this happens, it is very easy for -the user to perceive the application as slow.

    - -

    To summarize, it's vital to the responsiveness of your application's UI to -keep the UI thread unblocked. If you have long operations to perform, you should -make sure to do them in extra threads (background or worker -threads).

    - -

    Here's an example of a click listener downloading an image over the -network and displaying it in an ImageView:

    - -
    public void onClick(View v) {
    -  new Thread(new Runnable() {
    -    public void run() {
    -      Bitmap b = loadImageFromNetwork();
    -      mImageView.setImageBitmap(b);
    -    }
    -  }).start();
    -}
    - -

    At first, this code seems to be a good solution to your problem, as it does -not block the UI thread. Unfortunately, it violates the single-threaded model -for the UI: the Android UI toolkit is not thread-safe and must always -be manipulated on the UI thread. In this piece of code above, the -ImageView is manipulated on a worker thread, which can cause really -weird problems. Tracking down and fixing such bugs can be difficult and -time-consuming.

    - -

    Android offers several ways to access the UI -thread from other threads. You may already be familiar with some of -them but here is a comprehensive list:

    - -
      -
    • {@link android.app.Activity#runOnUiThread(java.lang.Runnable) Activity.runOnUiThread(Runnable)}
    • -
    • {@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}
    • -
    • {@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable, long)}
    • -
    • {@link android.os.Handler}
    • -
    - -

    You can use any of these classes and methods to correct the previous code example:

    - -
    public void onClick(View v) {
    -  new Thread(new Runnable() {
    -    public void run() {
    -      final Bitmap b = loadImageFromNetwork();
    -      mImageView.post(new Runnable() {
    -        public void run() {
    -          mImageView.setImageBitmap(b);
    -        }
    -      });
    -    }
    -  }).start();
    -}
    - -

    Unfortunately, -these classes and methods could also tend to make your code more complicated -and more difficult to read. It becomes even worse when your implement -complex operations that require frequent UI updates.

    - -

    To remedy this problem, Android 1.5 and later platforms offer a utility class -called {@link android.os.AsyncTask}, that simplifies the creation of -long-running tasks that need to communicate with the user interface.

    - -

    An AsyncTask equivalent is also available for applications that -will run on Android 1.0 and 1.1. The name of the class is UserTask. It offers the -exact same API and all you have to do is copy its source code in your -application.

    - -

    The goal of AsyncTask is to take care of thread management for -you. Our previous example can easily be rewritten with -AsyncTask:

    - -
    public void onClick(View v) {
    -  new DownloadImageTask().execute("http://example.com/image.png");
    -}
    -
    -private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    -     protected Bitmap doInBackground(String... urls) {
    -         return loadImageFromNetwork(urls[0]);
    -     }
    -
    -     protected void onPostExecute(Bitmap result) {
    -         mImageView.setImageBitmap(result);
    -     }
    - }
    - -

    As you can see, AsyncTask must be used by subclassing -it. It is also very important to remember that an AsyncTask -instance has to be created on the UI thread and can be executed only once. You -can read the -AsyncTask documentation for a full understanding on how to use this class, -but here is a quick overview of how it works:

    - - - -

    In addition to the official documentation, you can read several complex examples in the source code of Shelves (ShelvesActivity.java and AddBookActivity.java) and Photostream (LoginActivity.java, PhotostreamActivity.java and ViewPhotoActivity.java). We highly recommend reading the source code of Shelves to see how to persist tasks across configuration changes and how to cancel them properly when the activity is destroyed.

    - -

    Regardless of whether or not you use AsyncTask, -always remember these two rules about the single thread model:

    - -
      -
    1. Do not block the UI thread, and -
    2. Make sure that you access the Android UI toolkit only on the UI thread. -
    - -

    AsyncTask just makes it easier to do both of these things.

    diff --git a/docs/html/resources/articles/qsb.jd b/docs/html/resources/articles/qsb.jd deleted file mode 100644 index 01fb115819ebbf976dcc7dcbd487249818fa82c7..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/qsb.jd +++ /dev/null @@ -1,169 +0,0 @@ -page.title=Quick Search Box -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -
    -
    - -

    See also

    -
      -
    1. Search
    2. -
    3. Searchable Dictionary -sample
    4. -
    - -
    -
    - -
    - -
    - -

    Starting with Android 1.6, the platform includes support for Quick Search -Box (QSB), a powerful, system-wide search framework. Quick Search Box makes it -possible for users to quickly and easily find what they're looking for, both on -their devices and on the web. It suggests content on your device as you type, -like apps, contacts, browser history, and music. It also offers results from the -web search suggestions, local business listings, and other info from -Google, such as stock quotes, weather, and flight status. All of this is -available right from the home screen, by tapping on Quick Search Box.

    - -

    What -we're most excited about with this new feature is the ability for you, -the developers, to leverage the QSB framework to provide quicker and -easier access to the content inside your apps. Your apps can provide -search suggestions that will surface to users in QSB alongside other -search results and suggestions. This makes it possible for users to -access your application's content from outside your application—for -example, from the home screen.

    - -

    Note: The code fragments in this document are -related to a sample app called Searchable Dictionary. The app is -available for Android 1.6 and later platforms.

    - -

    The story before now: searching within your app

    - -

    Platform releases versions previous to Android 1.6 already provided a mechanism -that let you expose search and search suggestions in your app, as described in -the docs for {@link android.app.SearchManager}. That mechanism has not changed -and requires the following two things in your -AndroidManifest.xml:

    - -

    1) In your <activity>, an intent filter, and a reference -to a searchable.xml file (described below):

    - -
    <intent-filter>
    -    <action android:name="android.intent.action.SEARCH" />
    -    <category android:name="android.intent.category.DEFAULT" />
    -</intent-filter>
    -            
    -<meta-data android:name="android.app.searchable"
    -       android:resource="@xml/searchable" />
    - -

    2) A content provider that can provide search suggestions according to the -URIs and column formats specified by the -Search Suggestions -section of the SearchManager docs:

    - -
    <!-- Provides search suggestions for words and their definitions. -->
    -<provider android:name="DictionaryProvider"
    -       android:authorities="dictionary"
    -       android:syncable="false" />
    - -

    In the searchable.xml file, you specify a few things about how -you want the search system to present search for your app, including the -authority of the content provider that provides suggestions for the user as they -type. Here's an example of the searchable.xml of an Android app -that provides search suggestions within its own activities:

    - -
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
    -        android:label="@string/search_label"
    -        android:searchSuggestAuthority="dictionary"
    -        android:searchSuggestIntentAction="android.intent.action.VIEW">
    -</searchable>
    - -

    Note that the android:searchSuggestAuthority attribute refers to -the authority of the content provider we declared in -AndroidManifest.xml.

    - -

    For more details on this, see the -Searchability Metadata -section of the of the SearchManager docs.

    - -

    Including your app in Quick Search Box

    - - - -

    In Android 1.6, we added a new attribute to the metadata for searchables: -android:includeInGlobalSearch. By specifying this as -"true" in your searchable.xml, you allow QSB to pick -up your search suggestion content provider and include its suggestions along -with the rest (if the user enables your suggestions from the system search -settings).

    - -

    You should also specify a string value for -android:searchSettingsDescription, which describes to users what -sorts of suggestions your app provides in the system settings for search.

    - -
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
    -       android:label="@string/search_label"
    -       android:searchSettingsDescription="@string/settings_description"
    -       android:includeInGlobalSearch="true"
    -       android:searchSuggestAuthority="dictionary"
    -       android:searchSuggestIntentAction="android.intent.action.VIEW">
    -</searchable>
    - -

    These new attributes are supported only in Android 1.6 and later.

    - -

    What to expect

    - -

    The -first and most important thing to note is that when a user installs an -app with a suggestion provider that participates in QSB, this new app -will not be enabled for QSB by default. The user can choose -to enable particular suggestion sources from the system settings for -search (by going to "Search" > "Searchable items" in settings).

    - -

    You -should consider how to handle this in your app. Perhaps show a notice -that instructs the user to visit system settings and enable your app's -suggestions.

    - -

    Once the user enables your searchable item, the -app's suggestions will have a chance to show up in QSB, most likely -under the "more results" section to begin with. As your app's -suggestions are chosen more frequently, they can move up in the list.

    - - - - -

    Shortcuts

    - -

    One -of our objectives with QSB is to make it faster for users to access the -things they access most often. One way we've done this is by -'shortcutting' some of the previously chosen search suggestions, so -they will be shown immediately as the user starts typing, instead of -waiting to query the content providers. Suggestions from your app may -be chosen as shortcuts when the user clicks on them.

    - -

    For dynamic suggestions that may wish to change their content (or become invalid) -in the future, you can provide a 'shortcut id'. This tells QSB to query -your suggestion provider for up-to-date content for a suggestion after -it has been displayed. For more details on how to manage shortcuts, see -the Shortcuts section -within the SearchManager docs.

    diff --git a/docs/html/resources/articles/service-api-changes-starting-with.jd b/docs/html/resources/articles/service-api-changes-starting-with.jd deleted file mode 100644 index 7bafd815e96e1e38b2c5a799c8ca627c675ff97c..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/service-api-changes-starting-with.jd +++ /dev/null @@ -1,177 +0,0 @@ -page.title=Service API changes starting with Android 2.0 -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -
    -
    - -

    See also

    -
      -
    1. Services
    2. -
    - -

    Key classes

    -
      -
    1. {@link android.app.Service}
    2. -
    - -
    -
    - -

    Watching developers use the Android platform the last year has shown a number of trouble areas in the Service API as well as growing issues in the ways services operate. As a result, Android 2.0 introduced a number of changes and improvements in this area for both developers and users.

    -

    The three main changes to be aware of are:

    -
      -
    • Service.setForeground() is now deprecated and in 2.0 does nothing.
    • -
    • There were many edge cases in the service lifecycle that made it very easy to accidentally leave a service running; new APIs in 2.0 make this much easier to deal with.
    • -
    • Android 2.0 also introduces a new UI for end users to monitor and manage the running services on their device.
    • -
    -

    Background on services

    -

    Before going into the details of 2.0, it may be useful to go over a quick summary of services. The Service API in Android is one of the key mechanisms for applications to do work in the background. Due to the way Android is designed, once an application is no longer visible to the user it is generally considered expendable and a candidate to be killed by the system if it ever needs memory elsewhere. The main way applications get around this is by starting a Service component, which explicitly tells the system that they are doing some valuable work and would prefer that the system not kill their process if it doesn't truly need to.

    -

    This is a very powerful facility but along with that power comes some responsibility: an actively running service is taking resources away from other things that can run (including inactive processes in the background that don't need to be initialized the next time the user visits them). It is thus important that developers take care when designing their services that they only run when truly needed and avoid any bugs where they may accidentally leave the service running for long durations.

    -

    Redesigning Service.setForeground()

    -

    During the final stabilization period of Android 1.6 we started to see more issues due to an increasing number of applications using the Service.setForeground() API when they shouldn't be. This is an API that we haven't advertised much because it should not be used by most applications and can be very hard on the system: it asks that the service's process be treated as in the foreground, essentially making it unkillable and thus more difficult for the system to recover from low memory situations.

    -

    At that point in 1.6 it was too late to make any significant changes to the behavior here, but in 2.0 we have done so: Service.setForeground() now does nothing. The API was always intended to be something a service would do in conjunction with putting up an ongoing notification for the user; by saying you are in the foreground, the user should be "aware" that the service is running in some way and know how to stop it. Thus in place of the old API Andriod 2.0 introduces two new APIs that require a notification go along with being in the foreground:

    -
    -public final void startForeground(int id, Notification notification);
    -public final void stopForeground(boolean removeNotification);
    -
    -

    This also not coincidentally makes it much easier to manage the notification state along with the service, since the system can now guarantee that there is always a notification while the service is in the foreground, and that the notification goes away whenever the service does.

    -

    Many developers will want to write a service that works on older platforms as well as 2.0 and later; this can be accomplished by using something like the following code to selectively call the new APIs when they are available.

    -
    -private static final Class[] mStartForegroundSignature = new Class[] {
    -    int.class, Notification.class};
    -private static final Class[] mStopForegroundSignature = new Class[] {
    -    boolean.class};
    -
    -private NotificationManager mNM;
    -private Method mStartForeground;
    -private Method mStopForeground;
    -private Object[] mStartForegroundArgs = new Object[2];
    -private Object[] mStopForegroundArgs = new Object[1];
    -
    -@Override
    -public void onCreate() {
    -    mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    -    try {
    -        mStartForeground = getClass().getMethod("startForeground",
    -                mStartForegroundSignature);
    -        mStopForeground = getClass().getMethod("stopForeground",
    -                mStopForegroundSignature);
    -    } catch (NoSuchMethodException e) {
    -        // Running on an older platform.
    -        mStartForeground = mStopForeground = null;
    -    }
    -}
    -
    -/**
    - * This is a wrapper around the new startForeground method, using the older
    - * APIs if it is not available.
    - */
    -void startForegroundCompat(int id, Notification notification) {
    -    // If we have the new startForeground API, then use it.
    -    if (mStartForeground != null) {
    -        mStartForegroundArgs[0] = Integer.valueOf(id);
    -        mStartForegroundArgs[1] = notification;
    -        try {
    -            mStartForeground.invoke(this, mStartForegroundArgs);
    -        } catch (InvocationTargetException e) {
    -            // Should not happen.
    -            Log.w("MyApp", "Unable to invoke startForeground", e);
    -        } catch (IllegalAccessException e) {
    -            // Should not happen.
    -            Log.w("MyApp", "Unable to invoke startForeground", e);
    -        }
    -        return;
    -    }
    -    
    -    // Fall back on the old API.
    -    setForeground(true);
    -    mNM.notify(id, notification);
    -}
    -
    -/**
    - * This is a wrapper around the new stopForeground method, using the older
    - * APIs if it is not available.
    - */
    -void stopForegroundCompat(int id) {
    -    // If we have the new stopForeground API, then use it.
    -    if (mStopForeground != null) {
    -        mStopForegroundArgs[0] = Boolean.TRUE;
    -        try {
    -            mStopForeground.invoke(this, mStopForegroundArgs);
    -        } catch (InvocationTargetException e) {
    -            // Should not happen.
    -            Log.w("MyApp", "Unable to invoke stopForeground", e);
    -        } catch (IllegalAccessException e) {
    -            // Should not happen.
    -            Log.w("MyApp", "Unable to invoke stopForeground", e);
    -        }
    -        return;
    -    }
    -    
    -    // Fall back on the old API.  Note to cancel BEFORE changing the
    -    // foreground state, since we could be killed at that point.
    -    mNM.cancel(id);
    -    setForeground(false);
    -}
    -
    -

    Service lifecycle changes

    -

    Another situation we were increasingly seeing in 1.6 was that, even ignoring the services that inappropriately make themselves foreground, we had a growing number of devices with a large number of services running in the background all fighting each other over the available memory.

    -

    Part of this problem is services that are running more than they should or there simply being too much stuff trying to be done on the device. However, we also found many issues in the interaction between services and the platform that made it easy for an application to leave a service running even when it is trying to do the right thing. Consider this typical scenario:

    -
      -
    1. An application calls startService().
    2. -
    3. That service gets onCreate(), onStart(), and then spawns a background thread to do some work.
    4. -
    5. The system is tight on memory, so has to kill the currently running service.
    6. -
    7. Later when memory is free, the service is restarted, and gets onCreate() called but not onStart() because there has not been another call to startService() with a new Intent command to send it.
    8. -
    -

    Now the service will sit there created, not realizing it used to be doing some work, and so not knowing it should stop itself at some point.

    -

    To address this, in Android 2.0 Service.onStart() as been deprecated (though still exists and operates as it used to in previous versions of the platform). It is replaced with a new {@link android.app.Service#onStartCommand(android.content.Intent, int, int)} callback that allows the service to better control how the system should manage it. The key part here is a new result code returned by the function, telling the system what it should do with the service if its process is killed while it is running:

    -
      -
    • {@link android.app.Service#START_STICKY} is basically the same as the previous behavior, where the service is left "started" and will later be restarted by the system. The only difference from previous versions of the platform is that it if it gets restarted because its process is killed, onStartCommand() will be called on the next instance of the service with a null Intent instead of not being called at all. Services that use this mode should always check for this case and deal with it appropriately.
    • -
    • {@link android.app.Service#START_NOT_STICKY} says that, after returning from onStartCreated(), if the process is killed with no remaining start commands to deliver, then the service will be stopped instead of restarted. This makes a lot more sense for services that are intended to only run while executing commands sent to them. For example, a service may be started every 15 minutes from an alarm to poll some network state. If it gets killed while doing that work, it would be best to just let it be stopped and get started the next time the alarm fires.
    • -
    • {@link android.app.Service#START_REDELIVER_INTENT} is like START_NOT_STICKY, except if the service's process is killed before it calls stopSelf() for a given intent, that intent will be re-delivered to it until it completes (unless after some number of more tries it still can't complete, at which point the system gives up). This is useful for services that are receiving commands of work to do, and want to make sure they do eventually complete the work for each command sent.
    • -
    -

    For compatibility with existing applications, the default return code for applications that are targeting an earlier version of the platform is a special {@link android.app.Service#START_STICKY_COMPATIBILITY} code that provides the old behavior of not calling onStart() with a null intent. Once you start targeting API version 5 or later, the default mode is START_STICKY and you must be prepared to deal with onStart() or onStartCommand() being called with a null Intent.

    -

    You can also easily write a Service that uses both the old and new APIs, depending on the platform. All you need to do is compile against the 2.0 SDK with this code:

    -
    -// This is the old onStart method that will be called on the pre-2.0
    -// platform.  On 2.0 or later we override onStartCommand() so this
    -// method will not be called.
    -@Override
    -public void onStart(Intent intent, int startId) {
    -    handleStart(intent, startId);
    -}
    -
    -@Override
    -public int onStartCommand(Intent intent, int flags, int startId) {
    -    handleStart(intent, startId);
    -    return START_NOT_STICKY;
    -}
    -
    -void handleStart(Intent intent, int startId) {
    -    // do work
    -}
    -
    -

    New "running services" user interface

    -

    Our final issue to address is the case where there are simply too many service running in the amount of memory available on a device. This may be due to bugs or design flaws in installed applications, or the user simply trying to do too much. Historically users have had no visibility into what is going on at this level in the system, but it has become important to expose this, at least for lower-end devices, as the use of services has had an increasing impact on the user experience.

    -

    To help address this, Android 2.0 introduces a new "Running Services" activity available from the Application system settings. When brought up, it looks something like this:

    -Running Services -

    The main content is a list of all running services that may be of interest to the user, organized by the processes they run in. In the example here, we see three services:

    -
      -
    • GTalkService is part of the standard Google application suit; it is running in Google's "gapps" process, which currently consumes 6.8MB. It has been started for 3 hours 55 minutes, which on this device is the time from when it was first booted.
    • -
    • ActivityService is part of the Phonebook app, and its process consumes 4MB. This also has been running since boot.
    • -
    • SoftKeyboard is a third party input method. It has been running since I switched to it, about 4 minutes ago.
    • -
    -

    The user can tap on any of these services to control it; for normal services that are running because they were explicitly started, this will present a dialog allowing the user to explicitly stop it:

    -Stop Service -

    Some other services, like the input method, are running for other reasons. For these, tapping on the service will go to the corresponding UI to manage it (in this case the system's input settings).

    -

    Finally, along the bottom of the screen are some obscure numbers. If you know how to interpret them, this gives you a lot of information on the memory status of your device:

    -
      -
    • Avail: 38MB+114MB in 25 says that the device has 38MB of completely free (or likely used for unrequired caches) memory, and has another 114MB of available memory in 25 background processes it can kill at any time.
    • -
    • Other: 32MB in 3 says that the device has 32MB of unavailable memory in 3 unkillable processes (that is, processes that are currently considered to be foreground and must be kept running)
    • -
    -

    For most users, this new user interface should be a much more effective way to manage the background applications on their device than the existing "task killer" applications. In the vast majority of cases the reason for a slow running device is too many services trying to run. This prevents the system from being able to run any background processes (which speed up app switching), and ultimately can result in thrashing through the services when not even they can all be kept running. The Running Services UI is intended to provide very specific information about the services that are running, to help make a good decision about what should be stopped. It also does not use the API to force stop an application, which can unintentionally break applications in numerous ways.

    -

    For developers, this is an important tool to ensure your services are well behaved. As you develop your app, be sure to keep an eye on Running Services to ensure that you are not accidentally leaving your services running when they shouldn't be. You should also now keep in mind that users may freely stop any of your services as they wish, without your control, and account for that.

    -

    Android's Services are a very powerful tool, but one of the main and subtle ways that application developers can harm the overall experience a user has with their phone.

    diff --git a/docs/html/resources/articles/speech-input.jd b/docs/html/resources/articles/speech-input.jd deleted file mode 100644 index 2f9cd69d4e5818123841900a70a09d5f4f0fc589..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/speech-input.jd +++ /dev/null @@ -1,94 +0,0 @@ -page.title=Speech Input -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    People love their mobile phones because they can stay in touch wherever they -are. That means not just talking, but e-mailing, texting, microblogging, and so -on.

    - -

    Speech input adds another dimension to staying in touch. -Google's Voice Search application, which is pre-installed on many Android devices -and available on Google Play, provides powerful features like "search by voice" -and Voice Actions like "Navigate to." Further -enhancing the voice experience, Android 2.1 introduces a -voice-enabled keyboard, which makes it even easier -to stay connected. Now you can dictate your message instead of typing it. Just -tap the new microphone button on the keyboard, and you can speak in just about -any context in which you would normally type.

    - -

    We believe speech can -fundamentally change the mobile experience. We would like to invite every -Android application developer to consider integrating speech input capabilities -via the Android SDK. One of our favorite apps on Google Play that integrates -speech input is Handcent SMS, -because you can dictate a reply to any SMS with a -quick tap on the SMS popup window. Here is Speech input integrated into -Handcent SMS:

    - - - - -

    The Android SDK makes it easy to integrate speech input directly into your -own application. Just copy and paste from this sample -application to get -started. The sample application first verifies that the target device is able -to recognize speech input:

    -
    -// Check to see if a recognition activity is present
    -PackageManager pm = getPackageManager();
    -List activities = pm.queryIntentActivities(
    -  new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
    -if (activities.size() != 0) {
    -  speakButton.setOnClickListener(this);
    -} else {
    -  speakButton.setEnabled(false);
    -  speakButton.setText("Recognizer not present");
    -}
    -
    -

    -The sample application then uses {@link -android.app.Activity#startActivityForResult(android.content.Intent, int) -startActivityForResult()} to broadcast an intent that requests voice -recognition, including an extra parameter that specifies one of two language -models. The voice recognition application that handles the intent processes the -voice input, then passes the recognized string back to your application by -calling the {@link android.app.Activity#onActivityResult(int, int, -android.content.Intent) onActivityResult()} callback.

    - - -

    Android is an open platform, so your application can potentially make -use of any speech recognition service on the device that's registered to receive -a {@link android.speech.RecognizerIntent}. Google's Voice Search application, -which is pre-installed on -many Android devices, responds to a RecognizerIntent by displaying the -"Speak -now" dialog and streaming audio to Google's servers -- the same servers used -when a user taps the microphone button on the search widget or the voice-enabled -keyboard. You can check whether Voice Search is installed in -Settings > Applications > Manage applications.

    - -

    One important tip: for speech input to be as accurate as possible, it's -helpful to have an idea of what words are likely to be spoken. While a message -like "Mom, I'm writing you this message with my voice!" might be appropriate for -an email or SMS message, you're probably more likely to say something like -"weather in Mountain View" if you're using Google Search. You can make sure your -users have the best experience possible by requesting the appropriate -language model: {@link -android.speech.RecognizerIntent#LANGUAGE_MODEL_FREE_FORM free_form} for -dictation, or {@link android.speech.RecognizerIntent#LANGUAGE_MODEL_WEB_SEARCH -web_search} for shorter, search-like phrases. We developed the "free form" -model to improve dictation accuracy for the voice keyboard, -while the "web search" model is used when users want to search by voice.

    - -

    Google's servers support many languages for voice input, with more arriving -regularly. You can use the -{@link android.speech.RecognizerIntent#ACTION_GET_LANGUAGE_DETAILS} -broadcast intent to query for the list of supported languages. -The web search model is available for all languages, while the free-form model -may not be optimized for all languages. As we work hard to support more models in -more languages, and to improve the accuracy of the speech recognition technology -we use in our products, Android developers who integrate speech capabilities -directly into their applications can reap the benefits as well.

    diff --git a/docs/html/resources/articles/timed-ui-updates.jd b/docs/html/resources/articles/timed-ui-updates.jd deleted file mode 100644 index 7a0804f6fb948a9003f497cd375c7e0b36cddbf3..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/timed-ui-updates.jd +++ /dev/null @@ -1,151 +0,0 @@ -page.title=Updating the UI from a Timer -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - - -

    Background: While developing my first useful -(though small) application for Android, which was a port of an existing -utility I use when podcasting, I needed a way of updating a clock -displayed on the UI at regular intervals, but in a lightweight and CPU -efficient way.

    - -

    Problem: In the original application I used -java.util.Timer to update the clock, but that class is not such a good -choice on Android. Using a Timer introduces a new thread into the -application for a relatively minor reason. Thinking in terms of mobile -applications often means re-considering choices that you might make -differently for a desktop application with relatively richer resources -at its disposal. We would like to find a more efficient way of updating -that clock.

    - -

    The Application: The original application is a -Java Swing and SE application. It is like a stopwatch with a lap timer -that we use when recording podcasts; when you start the recording, you -start the stopwatch. Then for every mistake that someone makes, you hit -the flub button. At the end you can save out the bookmarked mistakes -which can be loaded into the wonderful -Audacity -audio editor as a labels track. You can then see where all of the mistakes -are in the recording and edit them out.

    - -

    The article describing it is: http://www.developer.com/java/ent/print.php/3589961

    - -

    In the original version, the timer code looked like this:

    - -
    class UpdateTimeTask extends TimerTask {
    -   public void run() {
    -       long millis = System.currentTimeMillis() - startTime;
    -       int seconds = (int) (millis / 1000);
    -       int minutes = seconds / 60;
    -       seconds     = seconds % 60;
    -
    -       timeLabel.setText(String.format("%d:%02d", minutes, seconds));
    -   }
    -}

    And in the event listener to start this update, the following Timer() instance is used: -

    if(startTime == 0L) {
    -   startTime = evt.getWhen();
    -   timer = new Timer();
    -   timer.schedule(new UpdateTimeTask(), 100, 200);
    -}
    - -

    In particular, note the 100, 200 parameters. The first parameter -means wait 100 ms before running the clock update task the first time. -The second means repeat every 200ms after that, until stopped. 200 ms -should not be too noticeable if the second resolution happens to fall -close to or on the update. If the resolution was a second, you could -find the clock sometimes not updating for close to 2 seconds, or -possibly skipping a second in the counting, it would look odd).

    - -

    When I ported the application to use the Android SDKs, this code -actually compiled in Eclipse, but failed with a runtime error because -the Timer() class was not available at runtime (fortunately, this was -easy to figure out from the error messages). On a related note, the -String.format method was also not available, so the eventual solution -uses a quick hack to format the seconds nicely as you will see.

    - -

    Fortunately, the role of Timer can be replaced by the -android.os.Handler class, with a few tweaks. To set it up from an event -listener:

    - -
    private Handler mHandler = new Handler();
    -
    -...
    -
    -OnClickListener mStartListener = new OnClickListener() {
    -   public void onClick(View v) {
    -       if (mStartTime == 0L) {
    -            mStartTime = System.currentTimeMillis();
    -            mHandler.removeCallbacks(mUpdateTimeTask);
    -            mHandler.postDelayed(mUpdateTimeTask, 100);
    -       }
    -   }
    -};
    - -

    A couple of things to take note of here. First, the event doesn't -have a .getWhen() method on it, which we handily used to set the start -time for the timer. Instead, we grab the System.currentTimeMillis(). -Also, the Handler.postDelayed() method only takes one time parameter, -it doesn't have a "repeating" field. In this case we are saying to the -Handler "call mUpdateTimeTask() after 100ms", a sort of fire and forget -one time shot. We also remove any existing callbacks to the handler -before adding the new handler, to make absolutely sure we don't get -more callback events than we want.

    - -

    But we want it to repeat, until we tell it to stop. To do this, just -put another postDelayed at the tail of the mUpdateTimeTask run() -method. Note also that Handler requires an implementation of Runnable, -so we change mUpdateTimeTask to implement that rather than extending -TimerTask. The new clock updater, with all these changes, looks like -this:

    - -
    private Runnable mUpdateTimeTask = new Runnable() {
    -   public void run() {
    -       final long start = mStartTime;
    -       long millis = SystemClock.uptimeMillis() - start;
    -       int seconds = (int) (millis / 1000);
    -       int minutes = seconds / 60;
    -       seconds     = seconds % 60;
    -
    -       if (seconds < 10) {
    -           mTimeLabel.setText("" + minutes + ":0" + seconds);
    -       } else {
    -           mTimeLabel.setText("" + minutes + ":" + seconds);            
    -       }
    -     
    -       mHandler.postAtTime(this,
    -               start + (((minutes * 60) + seconds + 1) * 1000));
    -   }
    -};
    - -

    and can be defined as a class member field.

    - -

    The if statement is just a way to make sure the label is set to -10:06 instead of 10:6 when the seconds modulo 60 are less than 10 -(hopefully String.format() will eventually be available). At the end of -the clock update, the task sets up another call to itself from the -Handler, but instead of a hand-wavy 200ms before the update, we can -schedule it to happen at a particular wall-clock time — the line: start -+ (((minutes * 60) + seconds + 1) * 1000) does this.

    - -

    All we need now is a way to stop the timer when the stop button -is pressed. Another button listener defined like this:

    - -
    OnClickListener mStopListener = new OnClickListener() {
    -   public void onClick(View v) {
    -       mHandler.removeCallbacks(mUpdateTimeTask);
    -   }
    -};
    - -

    will make sure that the next callback is removed when the stop button -is pressed, thus interrupting the tail iteration.

    - -

    Handler is actually a better choice than Timer for another reason -too. The Handler runs the update code as a part of your main thread, -avoiding the overhead of a second thread and also making for easy -access to the View hierarchy used for the user interface. Just remember -to keep such tasks small and light to avoid slowing down the user -experience.

    - - diff --git a/docs/html/resources/articles/touch-mode.jd b/docs/html/resources/articles/touch-mode.jd deleted file mode 100644 index 5eae9b9ea1a7d95723aadcb16b2dca5bb46c43d1..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/touch-mode.jd +++ /dev/null @@ -1,140 +0,0 @@ -page.title=Touch Mode -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    This article explains the touch mode, one of the most -important principles of Android's UI toolkit.

    - -

    The touch mode is a state of the view hierarchy that depends solely on the -user interaction with the phone. By itself, the touch mode is something very -easy to understand as it simply indicates whether the last user interaction was -performed with the touch screen. For example, if you are using an -Android-powered device, selecting a widget with the trackball will take you out -of touch mode; however, if you touch a button on the screen with your finger, -you will enter touch mode. When the user is not in touch mode, we talk about the -trackball mode, navigation mode or keyboard navigation, so do not be surprised -if you encounter these terms.

    - -

    There is only one API directly related to touch mode, -{@link android.view.View#isInTouchMode() View.isInTouchMode()}.

    - -

    Sounds easy enough, right? Oddly enough, touch mode is deceivingly simple and -the consequences of entering touch mode are far greater than you might -think. Let's look at some of the reasons why.

    - -

    Touch Mode, Selection, and Focus

    - -

    Designing a UI toolkit for mobile devices is difficult because of the various -interaction mechanisms they provide. Some devices offer only 12 keys, some have -a touch screen, some require a stylus, some have both a touch screen and a -keyboard. Based on the hardware capabilities of the he user can interact with -your application using different mechanisms, so we had to think very hard about -all the possible issues that could arise. One issue led us to create the touch -mode.

    - -

    Imagine a simple application, ApiDemos -for example, that shows a list of text items. The user can freely -navigate through the list using the trackball but also, alternatively, scroll -and fling the list using the touch screen. The issue in this scenario is -how to handle the selection properly when the user manipulates the list -through the touch screen.

    - -

    In this case, if the user selects an item at the top of the list and then -flings the list towards the bottom, what should happen to the selection? Should -it remain on the item and scroll off the screen? What should happen if the user -then decided to move the selection with the trackball? Or worse, what should -happen if the user presses the trackball to act upon the currently selected -item, which is not shown on screen anymore?

    - -

    After careful consideration, we decided to remove the selection altogether, -when the user manipulates the UI through the touch screen.

    - -

    In touch mode, there is no focus and no selection. Any selected item in a -list of in a grid becomes unselected as soon as the user enters touch -mode. Similarly, any focused widgets become unfocused when the user -enters touch mode. The image below illustrates what happens when the -user touches a list after selecting an item with the trackball.

    - - - - -

    To -make things more natural for the user, the framework knows how to -resurrect the selection/focus whenever the user leaves touch mode. For -instance, in the example above, if the user were to use the trackball -again, the selection would reappear on the previously-selected item. -This is why some developers are confused when they create a custom view -and start receiving key events only after moving the trackball once: -their application is in touch mode, and they need to use the trackball -to exit touch mode and resurrect the focus.

    - -

    The relationship between touch mode, selection, and focus means you must not -rely on selection and/or focus to exist in your application. A very common -problem with new Android developers is to rely on -{@link android.widget.AdapterView#getSelectedItemPosition() ListView.getSelectedItemPosition()}. -In touch mode, this method will return -{@link android.widget.AdapterView#INVALID_POSITION INVALID_POSITION}. - You should instead use click listeners (see -{@link android.widget.AdapterView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)}) -or the choice mode (see -{@link android.widget.ListView#setChoiceMode(int)}).

    - -

    Focusable in Touch Mode

    - -

    In general, focus doesn't exist in touch mode. However, focus can exist in -touch mode in a very special way called focusable. This special mode -was created for widgets that receive text input, such as -{@link android.widget.EditText} or, when filtering is enabled, -{@link android.widget.ListView}. The focusable mode is what lets the user enter text -inside a text field on the screen, without first selecting it with the trackball -or their finger.

    - -

    When a user -touches the screen, the application will enter touch mode if it wasn't -in touch mode already. What happens during the transition to -touch mode depends on what the user touched, and what currently has -focus. If the user touches a widget that is focusable in touch -mode, that widget will receive focus. Otherwise, any currently -focused widget will not retain focus unless it is focusable in touch -mode. For instance, in the picture below, when the user touches -the screen, the input text field receives the focus.

    - - - -

    Fousable in touch mode (see -{@link android.view.View#setFocusableInTouchMode(boolean) View.setFocusableInTouchMode}) - is a property that you can set yourself, either from code or from XML. -However, you should use it sparingly and only in very specific situations, -because it breaks consistency with the normal behavior of the Android UI. A game -is a good example of an application that could make good use of the focusable in -touch mode property. MapView, if used in fullscreen as in Google Maps, is -another good example of where you can use focusable in touch mode correctly.

    - -

    Below is another example of a focusable in touch mode widget. When the user -taps an AutoCompleteTextView suggestion with his finger, the focus -remains on the input text field:

    - - - - -

    Developers new to Android often think that focusable in touch mode is the -solution they need to "fix" the problem of "disappearing" selection/focus. We -really encourage you to think very hard before using it. If used incorrectly, it -can make your application behave differently from the rest of the system and -simply throw off the user's habits. The Android framework contains all the tools -you need to handle user interactions without using focusable in touch mode. For -example, instead of trying to make ListView always keep its -selection, simply use the appropriate choice mode, as shown in -{@link android.widget.ListView#setChoiceMode(int)}. - -

    Touch Mode Cheat Sheet

    - -

    Do:

    -
      -
    • Remain consistent with the core applications
    • Use the appropriate feature if you need persistent selection (radio button, check box, the ListView choice mode, etc.)
    • -
    • Use focusable in touch mode if you write a game
    • -
    - -

    Don't:

    -
    • Do not try to keep the focus or selection in touch mode
    diff --git a/docs/html/resources/articles/track-mem.jd b/docs/html/resources/articles/track-mem.jd deleted file mode 100644 index c4184b5764aa116dd5e55e7cde8036e15da1f5f4..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/track-mem.jd +++ /dev/null @@ -1,64 +0,0 @@ -page.title=Tracking Memory Allocations -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Writing efficient mobile applications is not always straightforward. In -particular, Android applications rely on automatic memory management handled by -Dalvik's garbage collector, which can sometimes cause performance issues if you -are not careful with memory allocations.

    - -

    In a performance-sensitive code path, such as the layout or drawing method of -a view or the logic code of a game, any allocation comes at a price. After too -many allocations, the garbage collector will kick in and stop your application -to let it free some memory. Most of the time, garbage collections happen fast -enough for you not to notice. However, if a collection happens while you are -scrolling through a list of items or while you are trying to defeat a foe in a -game, you may suddenly see a drop in performance/responsiveness of the -application. It's not unusual for a garbage collection to take 100 to 200 ms. -For comparison, a smooth animation needs to draw each frame in 16 to 33 ms. If -the animation is suddenly interrupted for 10 frames, you can be certain that -your users will notice.

    - -

    Most of the time, garbage collection occurs because of tons of small, -short-lived objects and some garbage collectors, like generational garbage -collectors, can optimize the collection of these objects so that the application -does not get interrupted too often. The Android garbage collector is -unfortunately not able to perform such optimizations and the creation of -short-lived objects in performance critical code paths is thus very costly for -your application.

    - -

    To help you avoid frequent garbage collections, the Android SDK ships with a -very useful tool called allocation tracker. This tool is part of DDMS, -which you must have already used for debugging purposes. To start using the -allocation tracker, you must first launch the standalone version of DDMS, which -can be found in the tools/ directory of the SDK. The version of -DDMS included in the Eclipse plugin does not offer you ability to use the -allocation tracker yet.

    - -

    Once DDMS is running, simply select your application process and then click -the Allocation Tracker tab. In the new view, click Start -Tracking and then use your application to make it execute the code paths -you want to analyze. When you are ready, click Get Allocations. A list -of allocated objects will be shown in the first table. By clicking on a line you -can see, in the second table, the stack trace that led to the allocation. Not -only you will know what type of object was allocated, but also in which thread, -in which class, in which file and at which line. The following screenshot shows -the allocations performed by Shelves while scrolling a -ListView.

    - - - - - - -

    Even though it is not necessary — and sometimes not possible — to -remove all allocations for your performance critical code paths. the allocation -tracker will help you identify important issues in your code. For instance, a -common mistake I have seen in many applications is to create a new -Paint object on every draw. Moving the paint into an instance field -is a simple fix that helps performance a lot. I highly encourage you to peruse -the Android source code to see how we -reduce allocations in performance-critical code paths. You will also thus -discover the APIs Android provide to help you reuse objects.

    diff --git a/docs/html/resources/articles/tts.jd b/docs/html/resources/articles/tts.jd deleted file mode 100644 index 929d08438f7e8f775d8bae1f197b556482647171..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/tts.jd +++ /dev/null @@ -1,243 +0,0 @@ -page.title=Using Text-to-Speech -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Starting with Android 1.6 (API Level 4), the Android platform includes a new -Text-to-Speech (TTS) capability. Also known as "speech synthesis", TTS enables -your Android device to "speak" text of different languages.

    - -

    Before we explain how to use the TTS API itself, let's first review a few -aspects of the engine that will be important to your TTS-enabled application. We -will then show how to make your Android application talk and how to configure -the way it speaks.

    - -

    Languages and resources

    - -

    The TTS engine that ships with the Android platform supports a number of -languages: English, French, German, Italian and Spanish. Also, depending on -which side of the Atlantic you are on, American and British accents for English -are both supported.

    - -

    The TTS engine needs to know which language to speak, as a word like "Paris", -for example, is pronounced differently in French and English. So the voice and -dictionary are language-specific resources that need to be loaded before the -engine can start to speak.

    - -

    Although all Android-powered devices that support the TTS functionality ship -with the engine, some devices have limited storage and may lack the -language-specific resource files. If a user wants to install those resources, -the TTS API enables an application to query the platform for the availability of -language files and can initiate their download and installation. So upon -creating your activity, a good first step is to check for the presence of the -TTS resources with the corresponding intent:

    - -
    Intent checkIntent = new Intent();
    -checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
    -startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
    - -

    A successful check will be marked by a CHECK_VOICE_DATA_PASS -result code, indicating this device is ready to speak, after the creation of -our -{@link android.speech.tts.TextToSpeech} object. If not, we need to let the user -know to install the data that's required for the device to become a -multi-lingual talking machine! Downloading and installing the data is -accomplished by firing off the ACTION_INSTALL_TTS_DATA intent, which will take -the user to Google Play, and will let her/him initiate the download. -Installation of the data will happen automatically once the download completes. -Here is an example of what your implementation of -onActivityResult() would look like:

    - -
    private TextToSpeech mTts;
    -protected void onActivityResult(
    -        int requestCode, int resultCode, Intent data) {
    -    if (requestCode == MY_DATA_CHECK_CODE) {
    -        if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
    -            // success, create the TTS instance
    -            mTts = new TextToSpeech(this, this);
    -        } else {
    -            // missing data, install it
    -            Intent installIntent = new Intent();
    -            installIntent.setAction(
    -                TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
    -            startActivity(installIntent);
    -        }
    -    }
    -}
    - -

    In the constructor of the TextToSpeech instance we pass a -reference to the Context to be used (here the current Activity), -and to an OnInitListener (here our Activity as well). This listener -enables our application to be notified when the Text-To-Speech engine is fully -loaded, so we can start configuring it and using it.

    - -

    Languages and Locale

    - -

    At Google I/O 2009, we showed an example of TTS where it was used to speak the result of a -translation from and to one of the 5 languages the Android TTS engine currently -supports. Loading a language is as simple as calling for instance:

    - -
    mTts.setLanguage(Locale.US);

    to load and set the language to -English, as spoken in the country "US". A locale is the preferred way to specify -a language because it accounts for the fact that the same language can vary from -one country to another. To query whether a specific Locale is supported, you can -use isLanguageAvailable(), which returns the level of support for -the given Locale. For instance the calls:

    - -
    mTts.isLanguageAvailable(Locale.UK))
    -mTts.isLanguageAvailable(Locale.FRANCE))
    -mTts.isLanguageAvailable(new Locale("spa", "ESP")))
    - -

    will return TextToSpeech.LANG_COUNTRY_AVAILABLE to indicate that the language -AND country as described by the Locale parameter are supported (and the data is -correctly installed). But the calls:

    - -
    mTts.isLanguageAvailable(Locale.CANADA_FRENCH))
    -mTts.isLanguageAvailable(new Locale("spa"))
    - -

    will return TextToSpeech.LANG_AVAILABLE. In the first example, -French is supported, but not the given country. And in the second, only the -language was specified for the Locale, so that's what the match was made on.

    - -

    Also note that besides the ACTION_CHECK_TTS_DATA intent to check -the availability of the TTS data, you can also use -isLanguageAvailable() once you have created your -TextToSpeech instance, which will return -TextToSpeech.LANG_MISSING_DATA if the required resources are not -installed for the queried language.

    - -

    Making the engine speak an Italian string while the engine is set to the -French language will produce some pretty interesting results, but it will -not exactly be something your user would understand So try to match the -language of your application's content and the language that you loaded in your -TextToSpeech instance. Also if you are using -Locale.getDefault() to query the current Locale, make sure that at -least the default language is supported.

    - -

    Making your application speak

    - -

    Now that our TextToSpeech instance is properly initialized and -configured, we can start to make your application speak. The simplest way to do -so is to use the speak() method. Let's iterate on the following -example to make a talking alarm clock:

    - -
    String myText1 = "Did you sleep well?";
    -String myText2 = "I hope so, because it's time to wake up.";
    -mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, null);
    -mTts.speak(myText2, TextToSpeech.QUEUE_ADD, null);
    - -

    The TTS engine manages a global queue of all the entries to synthesize, which -are also known as "utterances". Each TextToSpeech instance can -manage its own queue in order to control which utterance will interrupt the -current one and which one is simply queued. Here the first speak() -request would interrupt whatever was currently being synthesized: the queue is -flushed and the new utterance is queued, which places it at the head of the -queue. The second utterance is queued and will be played after -myText1 has completed.

    - -

    Using optional parameters to change the playback stream type

    - -

    On Android, each audio stream that is played is associated with one stream -type, as defined in -{@link android.media.AudioManager android.media.AudioManager}. For a talking -alarm clock, we would like our text to be played on the -AudioManager.STREAM_ALARM stream type so that it respects the alarm -settings the user has chosen on the device. The last parameter of the speak() -method allows you to pass to the TTS engine optional parameters, specified as -key/value pairs in a HashMap. Let's use that mechanism to change the stream type -of our utterances:

    - -
    HashMap<String, String> myHashAlarm = new HashMap();
    -myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
    -        String.valueOf(AudioManager.STREAM_ALARM));
    -mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
    -mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);
    - -

    Using optional parameters for playback completion callbacks

    - -

    Note that speak() calls are asynchronous, so they will return -well before the text is done being synthesized and played by Android, regardless -of the use of QUEUE_FLUSH or QUEUE_ADD. But you might -need to know when a particular utterance is done playing. For instance you might -want to start playing an annoying music after myText2 has finished -synthesizing (remember, we're trying to wake up the user). We will again use an -optional parameter, this time to tag our utterance as one we want to identify. -We also need to make sure our activity implements the -TextToSpeech.OnUtteranceCompletedListener interface:

    - -
    mTts.setOnUtteranceCompletedListener(this);
    -myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
    -        String.valueOf(AudioManager.STREAM_ALARM));
    -mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
    -myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
    -        "end of wakeup message ID");
    -// myHashAlarm now contains two optional parameters
    -mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);
    - -

    And the Activity gets notified of the completion in the implementation -of the listener:

    - -
    public void onUtteranceCompleted(String uttId) {
    -    if (uttId == "end of wakeup message ID") {
    -        playAnnoyingMusic();
    -    } 
    -}
    - -

    File rendering and playback

    - -

    While the speak() method is used to make Android speak the text -right away, there are cases where you would want the result of the synthesis to -be recorded in an audio file instead. This would be the case if, for instance, -there is text your application will speak often; you could avoid the synthesis -CPU-overhead by rendering only once to a file, and then playing back that audio -file whenever needed. Just like for speak(), you can use an -optional utterance identifier to be notified on the completion of the synthesis -to the file:

    - -
    HashMap<String, String> myHashRender = new HashMap();
    -String wakeUpText = "Are you up yet?";
    -String destFileName = "/sdcard/myAppCache/wakeUp.wav";
    -myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, wakeUpText);
    -mTts.synthesizeToFile(wakuUpText, myHashRender, destFileName);
    - -

    Once you are notified of the synthesis completion, you can play the output -file just like any other audio resource with -{@link android.media.MediaPlayer android.media.MediaPlayer}.

    - -

    But the TextToSpeech class offers other ways of associating -audio resources with speech. So at this point we have a WAV file that contains -the result of the synthesis of "Wake up" in the previously selected language. We -can tell our TTS instance to associate the contents of the string "Wake up" with -an audio resource, which can be accessed through its path, or through the -package it's in, and its resource ID, using one of the two -addSpeech() methods:

    - -
    mTts.addSpeech(wakeUpText, destFileName);
    - -

    This way any call to speak() for the same string content as -wakeUpText will result in the playback of -destFileName. If the file is missing, then speak will behave as if -the audio file wasn't there, and will synthesize and play the given string. But -you can also take advantage of that feature to provide an option to the user to -customize how "Wake up" sounds, by recording their own version if they choose -to. Regardless of where that audio file comes from, you can still use the same -line in your Activity code to ask repeatedly "Are you up yet?":

    - -
    mTts.speak(wakeUpText, TextToSpeech.QUEUE_ADD, myHashAlarm);
    - -

    When not in use...

    The text-to-speech functionality relies on a -dedicated service shared across all applications that use that feature. When you -are done using TTS, be a good citizen and tell it "you won't be needing its -services anymore" by calling mTts.shutdown(), in your Activity -onDestroy() method for instance.

    - -

    Conclusion

    - -

    Android now talks, and so can your apps. Remember that in order for -synthesized speech to be intelligible, you need to match the language you select -to that of the text to synthesize. Text-to-speech can help you push your app in -new directions. Whether you use TTS to help users with disabilities, to enable -the use of your application while looking away from the screen, or simply to -make it cool, we hope you'll enjoy this new feature.

    \ No newline at end of file diff --git a/docs/html/resources/articles/ui-1.5.jd b/docs/html/resources/articles/ui-1.5.jd deleted file mode 100644 index 2edaa2e0e352bf23bd4d22b9e8396efdbb5d8877..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/ui-1.5.jd +++ /dev/null @@ -1,50 +0,0 @@ -page.title=UI Framework Changes in Android 1.5 -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -

    Android 1.5 offers a different default look for -the Android UI framework, in relation to Android 1.0 and 1.1. The -screenshots below show the same activity (creating a new contact) on -Android 1.1 and Android 1.5:

    - - - -

    You -can see in this example that the buttons and checkboxes have a new -appearance. Even though these changes do not affect binary nor source -compatibility, they might still break the UI of your apps. As part of -the UI refresh, the minimum size of some of the widgets has changed. -For instance, Android 1.1 buttons have a minimum size of 44x48 pixels -whereas Android 1.5 buttons now have a minimum size of 24x48 pixels. -The image below compares the sizes of Android 1.1 buttons with Android -1.5 buttons:

    - - - -

    If you rely on the button's minimum size, then the layout of your application -may not be the same in Android 1.5 as it was in Android 1.1 because of this -change. This would happen for instance if you created a grid of buttons using -LinearLayout and relying on the minimum size yielded by -wrap_content to align the buttons properly:

    - - - -

    This layout could easily be fixed by using the -android:layout_weight attribute or by replacing the -LinearLayout containers with a TableLayout.

    - -

    This example is probably the worst-case UI issue you may encounter when -running your application on Android 1.5. Other changes introduced in Android -1.5, especially bug fixes in the layout views, may also impact your -application—especially if it is relying on faulty/buggy behavior of the UI -framework.

    - -

    If you encounter issues when running your application on Android 1.5, please -join us on the Android -developer groups or IRC so that we and the -Android community can help you fix your application.

    - -

    Happy coding!

    diff --git a/docs/html/resources/articles/ui-1.6.jd b/docs/html/resources/articles/ui-1.6.jd deleted file mode 100644 index b3238e3b0fc9c0fa9f87af105f8bfe97d54b9804..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/ui-1.6.jd +++ /dev/null @@ -1,132 +0,0 @@ -page.title=UI Framework Changes in Android 1.6 -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Android 1.6 introduces numerous enhancements and bug fixes in the UI -framework. This article highlights two improvements in particular: more flexible -and robust RelativeLayout and easier click listeners.

    - -

    More flexible, more robust RelativeLayout

    - -

    RelativeLayout is the most versatile layout offered by the Android UI toolkit -and can be successfully used to reduce the number of views created by your -applications. This layout used to suffer from various bugs and limitations, -sometimes making it difficult to use without having some knowledge of its -implementation. To make your life easier, Android 1.6 comes with a revamped -RelativeLayout.

    - -

    This new implementation not only fixes all known bugs in -RelativeLayout but also addresses its major limitation: the -fact that views had to be declared in a particular order. Consider the following -XML layout:

    - -
    <?xml version="1.0" encoding="utf-8"?>
    -
    -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -    android:layout_width="fill_parent"
    -    android:layout_height="64dip"
    -    android:padding="6dip">
    -
    -    <TextView
    -        android:id="@+id/band"  
    -        android:layout_width="fill_parent" 
    -        android:layout_height="26dip" 
    -
    -        android:layout_below="@+id/track"
    -        android:layout_alignLeft="@id/track"
    -        android:layout_alignParentBottom="true"
    -
    -        android:gravity="top"
    -        android:text="The Airborne Toxic Event" />
    -
    -    <TextView
    -        android:id="@id/track"  
    -        android:layout_marginLeft="6dip"
    -        android:layout_width="fill_parent"
    -        android:layout_height="26dip"
    -
    -        android:layout_toRightOf="@+id/artwork"
    -
    -        android:textAppearance="?android:attr/textAppearanceMedium"
    -        android:gravity="bottom"
    -        android:text="Sometime Around Midnight" />
    -        
    -    <ImageView
    -        android:id="@id/artwork"
    -        android:layout_width="56dip"
    -        android:layout_height="56dip"
    -        android:layout_gravity="center_vertical"
    -
    -        android:src="@drawable/artwork" />
    -        
    -</RelativeLayout>
    - -

    This code builds a very simple layout—an image on the left with two lines of -text stacked vertically. This XML layout is perfectly fine and contains no -errors. Unfortunately, Android 1.5's RelativeLayout is incapable of rendering it -correctly, as shown in the screenshot below.

    - - - -

    The problem is that this layout uses forward references. For instance, the -"band" TextView is positioned below the "track" TextView but "track" is declared -after "band" and, in Android 1.5, RelativeLayout does not know how to handle -this case. Now look at the exact same layout running on Android 1.6:

    - - - -

    As you can see Android 1.6 is now better able to handle forward reference. -The result on screen is exactly what you would expect when writing the -layout.

    - -

    Easier click listeners

    - -

    Setting up a click listener on a button is very common task, but -it requires quite a bit of boilerplate code:

    - -
    findViewById(R.id.myButton).setOnClickListener(new View.OnClickListener() {
    -    public void onClick(View v) {
    -        // Do stuff
    -    }
    -});
    - -

    One way to reduce the amount of boilerplate is to share a single click -listener between several buttons. While this technique reduces the -number of classes, it still requires a fair amount of code and it still -requires giving each button an id in your XML layout file:

    - -
    View.OnClickListener handler = View.OnClickListener() {
    -    public void onClick(View v) {
    -        switch (v.getId()) {
    -            case R.id.myButton: // doStuff
    -                break;
    -            case R.id.myOtherButton: // doStuff
    -                break;
    -        }
    -    }
    -}
    -
    -findViewById(R.id.myButton).setOnClickListener(handler);
    -findViewById(R.id.myOtherButton).setOnClickListener(handler);
    - -

    With Android 1.6, none of this is necessary. All you have to do is -declare a public method in your Activity to handle the click -(the method must have one View argument):

    - -
    class MyActivity extends Activity {
    -    public void myClickHandler(View target) {
    -        // Do stuff
    -    }
    -}
    - -

    And then reference this method from your XML layout:

    - -
    <Button android:onClick="myClickHandler" />
    - -

    This new feature reduces both the amount of Java and XML you have to write, -leaving you more time to concentrate on your application.

    - -

    The Android team is committed to helping you write applications in the -easiest and most efficient way possible. We hope you find these improvements -useful and we're excited to see your applications on Google Play.

    diff --git a/docs/html/resources/articles/using-webviews.jd b/docs/html/resources/articles/using-webviews.jd deleted file mode 100644 index 3a2430b9496c2fbfd934bf4b027d0d9465567caa..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/using-webviews.jd +++ /dev/null @@ -1,63 +0,0 @@ -page.title=Using WebViews -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    A small application called WebViewDemo shows how you can add web content to your -application. You can find it in the apps-for-android project. -This application demonstrates how you can embed a {@link android.webkit.WebView} -into an activity and also how you can have two way communication between your -application and the web content.

    - -

    A -WebView uses the same rendering and JavaScript engine as the browser, -but it runs under the control of your application. The WebView can be -full screen or you can mix it with other Views. The content for your -WebView can come from anywhere. The WebView can download content from -the web, or it can come from local files stored in your assets -directory. The content can even be dynamically generated by your -application code. For this example, the HTML comes from a local file -called demo.html.

    - -

    This application does not do very much: when you click on the -android, he raises his arm.

    - -
    - -

    This -could, of course, easily be accomplished with a little bit of -JavaScript. Instead, though, WebViewDemo takes a slightly more -complicated path to illustrate two very powerful features of WebView.

    - -

    First, -JavaScript running inside the WebView can call out to code in your -Activity. You can use this to have your JavaScript trigger actions like -starting a new activity, or it can be used to fetch data from a -database or {@link android.content.ContentProvider}. The API for this -is very simple: just call the -{@link android.webkit.WebView#addJavascriptInterface(java.lang.Object, java.lang.String) addJavascriptInterface()} -method on your WebView. You pass an object whose methods you want to -expose to JavaScript and the name to use when making calls. You can see -the exact syntax in WebViewDemo. -java. Here we are making our DemoJavascriptInterface object available to -JavaScript where it will be called "window.demo".

    - -

    Second, your Activity can invoke JavaScript methods. All you have to do -is call the {@link android.webkit.WebView#loadUrl(java.lang.String) loadUrl} -method with the appropriate JavaScript call:

    - -

    mWebView.loadUrl("javascript:wave()");

    - -

    Our WebViewDemo uses both techniques: when you click on the -android, it calls out to the activity, which then turns around and calls back -into the JavaScript. WebViews are very powerful, and they may be a valuable tool -to help you build your application – especially if you already have a lot of -HTML content. As it happens, we've used exactly this approach in some of the -applications we've written.

    diff --git a/docs/html/resources/articles/wikinotes-intents.jd b/docs/html/resources/articles/wikinotes-intents.jd deleted file mode 100644 index 78fe62e101d10356c6577a935d661db51800b861..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/wikinotes-intents.jd +++ /dev/null @@ -1,257 +0,0 @@ -page.title=WikiNotes: Routing Intents -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -

    In the Linkify! article, we talked about -using Linkify to turn wiki words (those that match a regular expression that we -have defined) into a content: URI and defining a path to data that -matched a note belonging to that wiki word. As an example, a matching word like -ToDoList would be turned into a URI such as -content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList - and then acted upon using the VIEW action from the Linkify class.

    - -

    This article examines how the Android system takes this combination of -VIEW action and content: URI and finds the correct -activity to fire in order to do something with the data. It will also explain -how the other default links created by Linkify, such as web URLs and telephone -numbers, also result in the correct activity to handle that data type being -fired. Finally, this article will start to examine the custom -ContentProvider that has been created to handle WikiNotes data. The -full description of the ContentProvider and what it does will span a couple more -articles as well, because there is a lot to cover.

    - -

    The Linkify-calls-intent Workflow

    - -

    At a high level, the steps for Linkify to invoke an intent, and for the -resulting activity (if any) to handle it, look like this:

    - -
      -
    1. Linkify is invoked on a TextView to turn matching text patterns into Intent links.
    2. -
    3. Linkify takes over monitoring for those Intent links being selected by the user.
    4. -
    5. When the user selects a link, Linkify calls the VIEW action using the content: URI associated with the link.
    6. -
    7. Android takes the content: URI that represents the data, and looks for a -ContentProvider registered in the system that matches the URI.
    8. -
    9. If a match is found, Android queries the ContentProvider using the URI, -and asks what MIME type the data that will be returned from the URI is.
    10. -
    11. Android then looks for an activity registered in the system with an -intent-filter that matches both the VIEW action, and the MIME type for -the data represented by the content: URI.
    12. -
    13. Assuming a match is found, Linkify then invokes the intent for -the URI, at which point the activity takes over, and is handed -the content: URI.
    14. -
    15. The activity can then use the URI to retrieve the data and act on -it.
    16. -
    - -

    This is actually a simpler process than it -sounds, and it is quite lightweight as well. Perhaps a more -understandable statement about how it works might be:

    - -

    Linkify is used to turn matching text into hot-links. When the user -selects a hot-link, Android takes the data locator represented by the -hot-link and looks for a data handler for that data locator. If it -finds one, it asks for what type of data is returned for that locator. -It then looks for something registered with the system that handles -that type of data for the VIEW action, and starts it, including the -data locator in the request.

    - -

    The real key here is the MIME type. MIME stands for Multipurpose Internet Mail -Extensions — a standard for sending attachments over email. The MIME -type (which is the part Android uses) is a way of describing certain kinds of -data. That type is then used to look for an Activity that can do something with -that data type. In this way, ContentProviders and Activities (or other -IntentReceivers) are decoupled, meaning that a given Content URI might have a -different ContentProvider to handle it, but could still use the same MIME type -meaning that the same activity could be called upon to handle the resulting -data.

    - -

    Linkify on a wiki word

    - -

    Using the above workflow, let's take a look at exactly how the process -works in WikiNotes for Android:

    - -

    First, Linkify is used to turn text matching the wiki word regular expression -into a link that provides a Content URI for that wiki word, for example -content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList.

    - -

    When the user clicks on the wiki word link, Linkify invokes the VIEW -action on the Content URI. At this point, the Android system takes over -getting the Intent request to the correct activity.

    - -

    Next, Android looks for a ContentProvider that has been registered -with the system to handle URIs matching our Content URI format.

    - -

    In our case, we have a definition inside -our application's AndroidManifest.xml -file that reads:

    - -
    <provider name="com.google.android.wikinotes.db.WikiNotesProvider" 
    -    android:authorities="com.google.android.wikinotes.db.wikinotes" />
    - -

    This establishes that we have a ContentProvider defined in our application -that provides the "root authority": -com.google.android.wikinotes.db.wikinotes. This is the first part -of the Content URI that we create for a wiki word link. Root Authority is just -another way of thinking about a descriptor that is registered with Android to -allow requests for certain URLs to be routed to the correct class.

    - -

    So, the whole definition is that a class called -com.google.android.wikinotes.db.WikiNotesProvider is registered -with the system as able to handle the -com.google.android.wikinotes.db.wikinotes root authority (i.e. URIs -starting with that identifier).

    - -

    From here, Android takes the rest of the URI and presents it to that -ContentProvider. If you look at the -WikiNotesProvider -class and scroll to the very bottom, in the static block there, you can see -the pattern definitions to match the rest of the URL.

    - -

    In particular, take a look at the two lines:

    - -
    URI_MATCHER.addURI(WikiNote.WIKINOTES_AUTHORITY, "wikinotes", NOTES);
    -URI_MATCHER.addURI(WikiNote.WIKINOTES_AUTHORITY, "wikinotes/*", NOTE_NAME);
    - -

    These are the definitions of URIs that our ContentProvider recognizes and can -handle. The first recognizes a full URI of -content://com.google.android.wikinotes.db.wikinotes/wikinotes and -associates that with a constant called NOTES. This is used elsewhere in the -ContentProvider to provide a list of all of the wiki notes in the database when -the URI is requested.

    - -

    The second line uses a wildcard — '*' — to match a request of the -form that Linkify will create, e.g. -content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList -. In this example, the * matches the ToDoList part of the URI and is -available to the handler of the request, so that it can fish out the matching -note for ToDoList and return it as the data. This also associates that match -with a constant called NOTE_NAME, which again is used as an identifier elsewhere -in the ContentProvider.

    - -

    The other matches in this static block are related to forms of -searching that have been implemented in the WikiNotes for Android -application, and will be covered in later articles. Likewise, how the -data is obtained from this matching pattern will be the subject of the -next article.

    - -

    For right now we are concerned with the MIME type for the URI. This is -defined in the getType() method also in the -WikiNotesProvider -class (about halfway through the file). Take a quick look at this. The key -parts for now are:

    - -
    case NOTES:
    -    return "vnd.android.cursor.dir/vnd.google.wikinote";
    - -

    and

    - -
    case NOTE_NAME:
    -    return "vnd.android.cursor.item/vnd.google.wikinote";
    - -

    These are the same constant names we defined in our pattern -matchers. In the first case, that of the all notes URI, the MIME type -returned is vnd.android.cursor.dir/vnd.google.wikinote -which is like saying an Android list (dir) of Google wiki notes (the -vnd bit is MIME-speak for "vendor specific definition"). Likewise, in -the case of a NOTE_NAME match, the MIME type returned is -vnd.android.cursor.item/vnd.google.wikinote which is -like saying an Android item of Google wiki notes.

    - -

    Note that if you define your own MIME data types like this, the -vnd.android.cursor.dir and vnd.android.cursor.item -categories should be retained, since they have meaning to the Android -system, but the actual item types should be changed to reflect your -particular data type.

    - -

    So far Android has been able to find a ContentProvider that handles -the Content URI supplied by the Linkify Intent call, and has queried -the ContentProvider to find out the MIME types for that URI. The final -step is to find an activity that can handle the VIEW action for that -MIME type. Take a look in the the -AndroidManifest.xml file -again. Inside the WikiNotes activity definition, you will see:

    - -
    <intent-filter>
    -    <action name="android.intent.action.VIEW"/>
    -    <category name="android.intent.category.DEFAULT"/>
    -    <category name="android.intent.category.BROWSABLE"/>
    -    <data mimetype="vnd.android.cursor.item/vnd.google.wikinote"/>
    -</intent-filter>
    - -

    This is the correct combination of matches for the VIEW action on a -WikiNote type that is requested from the LINKIFY class. The DEFAULT -category indicates that the WikiNotes activity should be treated as a -default handler (a primary choice) for this kind of data, and the -BROWSABLE category means it can be invoked from a "browser", in this -case the marked-up Linkified text.

    - -

    Using this information, Android can match up the VIEW action request -for the WikiNotes data type with the WikiNotes activity, and can then -use the WikiNotes activity to handle the request.

    - -

    Why do it like this?

    - -

    It's quite a trip through the system, and there is a lot to absorb -here, but this is one of the main reasons I wanted to write WikiNotes -in the first place. If you follow and understand the steps here, you'll -have a good grasp of the whole Intents mechanism in Android, and how it -helps loosely coupled activities cooperate to get things done.

    - -

    In this case, we could have found another way to detect wiki words -based on a regular expression, and maybe written our own handler to -intercept clicks within the TextView and dig out the right data and -display it. This would seem to accomplish the same functionality just -as easily as using intents, so what is the advantage to using the full -Intents mechanism?

    - -

    In fact there are several advantages:

    - -

    The most obvious is that because we are using the standard Intent -based approach, we are not limited to just linking and navigating to -other wiki notes. We get similar behavior to a number of other data -types as well. For example, a telephone number or web URL in a wiki -note will be marked up by Linkify, and using this same mechanism (VIEW -action on the linked data type) the browser or dialer activities will -be automatically fired.

    - -

    It also means that each operation on a wiki note can be treated as a -separate life cycle by our activity. We are not dealing with swapping -data in and out of an existing activity - each activity works on a -particular wiki note and that's all you have to worry about.

    - -

    Another advantage is that we now have a public activity to handle -VIEW actions in WikiNotes no matter where the request comes from. -Another application could request to view a wiki note (perhaps without -even knowing what kind of data it is) and our activity could start up -and handle it.

    - -

    The backstack is automatically maintained for you too. As you -forward navigate through WikiNotes, Android maintains the history of -notes visited, and so when you hit the back button you go back to the -last note you were on. All this is free because we rely on the Android -intents mechanism.

    - -

    Finally, if you run WikiNotes for Android and then start DDMS to -take a look at the Activity threads in the WikiNotes application while -it is running, you can see that despite what you might think, letting -Android manage the navigation is very efficient. Create a few linked -notes, as many links deep as you like, and then follow them. If you -follow links hundreds of notes deep, you will still only see a handful -of WikiNotes activities. Android is managing the activities, closing -the older ones as necessary and using the life cycle to swap data in -and out.

    - -

    Next Time

    - -

    This was a long article, but necessarily so. It demonstrates the -importance of the Intents mechanism and to reinforce the notion that it -should be used whenever possible for forward navigation, even within a -single application. Illustrating this is one of the primary reasons I -wrote WikiNotes for Android in the first place.

    - -

    In the next article we will look deeper into the ContentProvider and -examine how it turns a Content URI into a row (or several rows) of data -that can be used by an activity.

    diff --git a/docs/html/resources/articles/wikinotes-linkify.jd b/docs/html/resources/articles/wikinotes-linkify.jd deleted file mode 100644 index fb49f8694ee59b4fcec8ae2033b8c10946ef2731..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/wikinotes-linkify.jd +++ /dev/null @@ -1,115 +0,0 @@ -page.title=WikiNotes: Linkify your Text! -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -Linkify example - -

    This article introduces WikiNotes for Android, part of the Apps for Android -project. It covers the use of Linkify to turn ordinary text views -into richer, link-oriented content that causes Android intents to fire -when a link is selected.

    - -

    Linkify: The {@link android.text.util.Linkify} class in the -framework is perfect for creating a wiki note pad. It lets you specify a regular expression -» -to match, and a scheme to prepend. The scheme is a string that, when -the matched text is added, forms a Content URI to allow the correct -data to be looked up.

    - -

    For example, in our case we want to look for a regular expression match for a -WikiWord (that is, a word with camel case » and no -spaces). Linkify can then turn this into a Content URI — something like -content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord, -which can then be used to locate the correct wiki page from a -{@link android.content.ContentProvider}.

    - -

    As a bonus, the Linkify class also defines several default matches, -in particular it is able to turn web URLs, email addresses and -telephone numbers into active links which fire Android intents -automatically.

    - -

    Linkify can be passed any TextView in your application, and will -take care of creating the links and enabling their "clickability" for -you.

    - -

    Default Linkify: Using the set of default active -link options is very straightforward. Simply pass it a handle to a -TextView with content in it, and the Linkify.ALL flag:

    - -
    TextView noteView = (TextView) findViewById(R.id.noteview);
    -noteView.setText(someContent);
    -Linkify.addLinks(noteView, Linkify.ALL);
    - -

    and that's it. The Linkify.ALL flag applies all of the predefined -link actions, and the TextView will be immediately updated with a set -of active links which, if you select them, fire default intents for the -actions (e.g. a web URL will start the browser with that URL, a -telephone number will bring up the phone dialer with that number ready -to call, etc.).

    - -

    Custom Linkify: So what about our WikiWord? There is no -pre-defined action for that, so it needs to be defined and associated with a -scheme.

    - -

    The first task is to define a regular expression that matches the kind of -WikiWords we want to find. The regex in this case is:

    - -
    \b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\b
    - -

    Obvious, no? Well actually this is equivalent to the following -description: "Starting with a word boundary (the \b) find at least one -upper case letter, followed by at least one lower case letter or a -numeric digit, followed by another upper case letter, and then any mix -of upper case, lower case or numeric until the next word boundary (the -final \b)". Regular expressions are not very pretty, but they are an -extremely concise and accurate way of specifying a search pattern.

    - -

    We also need to tell Linkify what to do with a match to the -WikiWord. Linkify will automatically append whatever is matched to a -scheme that is supplied to it, so for the sake of argument let's assume -we have a {@link android.content.ContentProvider} that matches the -following content URI:

    - -
    content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord
    - -

    The WikiWord part will be appended by Linkify when it finds a match, so we -just need the part before that as our scheme.

    - -

    Now that we have these two things, we use Linkify to connect them up:

    - -
    Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b");
    -String wikiViewURL =    "content://com.google.android.wikinotes.db.wikinotes/wikinotes/";
    -Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);
    - -

    Note that the \b's had to be escaped with double backslashes for the Java -Pattern.compile line.

    - -

    Linkify can be used multiple times on the same view to add more -links, so using this after the Default Linkify call means that the -existing active links will be maintained and the new WikiWords will be -added. You could define more Linkify actions and keep applying them to -the same TextView if you wanted to.

    - -

    Now, if we have a WikiWord in the TextView, let's say -MyToDoList, Linkify will turn it into an active link with the -content URI:

    - -
    content://com.google.android.wikinotes.db.wikinotes/wikinotes/MyToDoList
    - -

    and if you click on it, Android will fire the default intent for that content -URI.

    - -

    For this to all work, you will need a ContentProvider that -understands that Content URI, and you will need a default activity -capable of doing something with the resulting data. I plan to cover -these in future blog entries (and soon). In fact, the whole Wiki Note -Pad application is currently undergoing some clean up and review, and -will then hopefully be released as a sample application.

    diff --git a/docs/html/resources/articles/window-bg-speed.jd b/docs/html/resources/articles/window-bg-speed.jd deleted file mode 100644 index c5e5e9095a98b82f1bc252247e9b9cfd8f810b25..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/window-bg-speed.jd +++ /dev/null @@ -1,127 +0,0 @@ -page.title=Window Backgrounds & UI Speed -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    Some Android applications require to squeeze every bit of performance out of -the UI toolkit and there are many ways to do so. In this article, you will -discover how to speed up the drawing and the perceived startup time of -your activities. Both these techniques rely on a single feature, the window's -background drawable.

    - -

    The term window background is a bit misleading, however. When you -setup your user interface by calling setContentView() on an -{@link android.app.Activity}, Android adds your views to the Activity's -window. The window however does not contain only your views, but a few others -created for you. The most important one is, in the current implementation used -on the T-Mobile G1, the DecorView, highlighted in the view -hierarchy below:

    - -
    A typical Android view hierarchy
    - -

    The DecorView is the view that actually holds the -window's background drawable. Calling -{@link android.view.Window#setBackgroundDrawable(android.graphics.drawable.Drawable) getWindow().setBackgroundDrawable()} -from your Activity changes the background of the window by changing -the DecorView's background drawable. As mentioned before, this -setup is very specific to the current implementation of Android and can change -in a future version or even on another device.

    - -

    If you are using the standard Android themes, a default background drawable -is set on your activities. The standard theme currently used on the T-Mobile G1 -uses for instance a {@link android.graphics.drawable.ColorDrawable}. For most -applications, this background drawable works just fine and can be left alone. It -can however impacts your application's drawing performance. Let's take the -example of an application that always draws a full screen opaque picture:

    - -
    An opaque user interface doesn't need a window background
    - -

    You can see on this screenshot that the window's background is invisible, -entirely covered by an ImageView. This application is setup to -redraw as fast as it can and draws at about 44 frames per second, or 22 -milliseconds per frame (note: the number of frames per second -used in this article were obtained on a T-Mobile G1 with my finger on the screen -so as to reduce the drawing speed which would otherwise be capped at 60 fps.) An -easy way to make such an application draw faster is to remove the -background drawable. Since the user interface is entirely opaque, drawing the -background is simply wasteful. Removing the background improves the performance -quite nicely:

    - -
    Remove the background for faster drawing
    - -

    In this new version of the application, the drawing speed went up to 51 -frames per second, or 19 milliseconds per frame. The difference of 3 -milliseconds per is easily explained by the speed of the memory bus on the -T-Mobile G1: it is exactly the time it takes to move the equivalent of a -screenful of pixels on the bus. The difference could be even greater if the -default background was using a more expensive drawable.

    - -

    Removing the window's background can be achieved very easily by using -a custom theme. To do so, first create a file called -res/values/theme.xml containing the following:

    - -
    <resources>
    -    <style name="Theme.NoBackground" parent="android:Theme">
    -        <item name="android:windowBackground">@null</item>
    -    </style>
    -</resources>
    - -

    You then need to apply the theme to your activity by adding the attribute -android:theme="@style/Theme.NoBackground" to your -<activity /> or <application /> tag. This -trick comes in very handy for any app that uses a MapView, a -WebView or any other full screen opaque view.

    - -

    Opaque views and Android: this optimization is currently -necessary because the Android UI toolkit is not smart enough to prevent the -drawing of views hidden by opaque children. The main reason why this -optimization was not implemented is simply because there are usually very few -opaque views in Android applications. This is however something that I -definitely plan on implementing as soon as possible and I can only apologize for -not having been able to do this earlier.

    Using a theme to change the -window's background is also a fantastic way to improve the perceived -startup performance of some of your activities. This particular trick can only -be applied to activities that use a custom background, like a texture or a logo. -The Shelves application is a good -example:

    - -
    Textured backgrounds are good candidates for window's background
    - -

    If this application simply set the wooden background in the XML layout or in -onCreate() the user would see the application startup with the -default theme and its dark background. The wooden texture would only appear -after the inflation of the content view and the first layout/drawing pass. This -causes a jarring effect and gives the user the impression that the application -takes time to load (which can actually be the case.) Instead, the application -defines the wooden background in a theme, picked up by the system as soon as the -application starts. The user never sees the default theme and gets the -impression that the application is up and running right away. To limit the -memory and disk usage, the background is a tiled texture defined in -res/drawable/background_shelf.xml:

    - -
    <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    -    android:src="@drawable/shelf_panel"
    -    android:tileMode="repeat" />

    This drawable is simply referenced by the theme:

    - -
    <resources>
    -    <style name="Theme.Shelves" parent="android:Theme">
    -        <item name="android:windowBackground">@drawable/background_shelf</item>
    -        <item name="android:windowNoTitle">true</item>
    -    </style>
    -</resources>
    - -

    The same exact trick is used in the Google Maps application that ships -with the T-Mobile G1. When the application is launched, the user immediately -sees the loading tiles of MapView. This is only a trick, the theme -is simply using a tiled background that looks exactly like the loading tiles of -MapView.

    - -

    Sometimes the best tricks are also the simplest, so the next time you create -an activity with an opaque UI or a custom background, remember to change the -window's background.

    - -

    Download the source code of the first example.

    - -

    Download the source code of Shelves.

    - - diff --git a/docs/html/resources/articles/zipalign.jd b/docs/html/resources/articles/zipalign.jd deleted file mode 100644 index d3c68a6b690f03835eccacf911aa5628a400b077..0000000000000000000000000000000000000000 --- a/docs/html/resources/articles/zipalign.jd +++ /dev/null @@ -1,100 +0,0 @@ -page.title=Zipalign: an Easy Optimization -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -

    The Android SDK includes a tool called zipalign -that optimizes the way an application is packaged. Running zipalign against your -application enables Android to interact it more efficiently at run time and thus -has the potential to make it and the overall system run faster. We strongly -encourage you to use zipalign on both new and already published -applications and to make the optimized version available — even if your -application targets a previous version of Android. This article describes how -zipalign helps performance and how to use it to optimize your -app.

    - -

    In Android, data files stored in each application's apk are accessed by -multiple processes: the installer reads the manifest to handle the -permissions associated with that application; the Home application -reads resources to get the application's name and icon; the system -server reads resources for a variety of reasons (e.g. to display that -application's notifications); and last but not least, the resource -files are obviously used by the application itself.

    - -

    The resource-handling code in Android can efficiently access resources when -they're aligned on 4-byte boundaries by memory-mapping them. But for resources -that are not aligned (that is, when zipalign hasn't been run on an -apk), it has to fall back to explicitly reading them — which is slower and -consumes additional memory.

    - -

    For an application developer, this fallback mechanism is very -convenient. It provides a lot of flexibility by allowing for several -different development methods, including those that don't include -aligning resources as part of their normal flow.

    - -

    Unfortunately, for users the situation is reversed — reading resources -from unaligned apks is slow and takes a lot of memory. In the best case, the -only visible result is that both the Home application and the unaligned -application launch slower than they otherwise should. In the worst case, -installing several applications with unaligned resources increases memory -pressure, thus causing the system to thrash around by having to constantly start -and kill processes. The user ends up with a slow device with a poor battery -life.

    - -

    Luckily, it's very easy for you to align the resources in your application:

    - -
      -
    • Using ADT:
    • -
    • -
        -
      • The ADT plugin for Eclipse (starting from version 0.9.3) will automatically -align release application packages if the export wizard is used to create them. -To use the wizard, right click the project and choose "Android Tools" > -"Export Signed Application Package..." It can also be accessed from the first -page of the AndroidManifest.xml editor.
      • -
      -
    • -
    • Using Ant:
    • - -
        -
      • The Ant build script (starting from Android 1.6) can align -application packages. Targets for older versions of the Android platform are not -aligned by the Ant build script and need to be manually aligned.
      • -
      • Starting from the Android 1.6 SDK, Ant aligns and signs packages automatically, -when building in debug mode.
      • -
      • In release mode, Ant aligns packages only if it has enough -information to sign the packages, since aligning has to happen after signing. In -order to be able to sign packages, and therefore to align them, Ant -needs to know the location of the keystore and the name of the key in -ant.properties. The name of the properties are -key.store and key.alias respectively. If those -properties are present, the signing tool will prompt to enter the store/key -passwords during the build, and the script will sign and then align the apk -file. If the properties are missing, the release package will not be signed, and -therefore will not get aligned either.
      • -
      -
    • -
    • Manually:
    • -
    • -
        -
      • In order to manually align a package, zipalign -is in the tools/ folder of Android 1.6 and later SDKs. You can use -it to align application packages targeting any version of Android. You should run -it only after signing the apk file, using the following command: -
        zipalign -v 4 source.apk destination.apk
      • -
      -
    • -
    • Verifying alignment:
    • -
    • -
        -
      • The following command verifies that a package is aligned:
        zipalign -c -v 4 application.apk -
      • -
      -
    • -
    - -

    We encourage you manually run zipalign -on your currently published applications and to make the newly aligned -versions available to users. Also, don't forget to align any new -applications going forward!

    diff --git a/docs/html/resources/browser.jd b/docs/html/resources/browser.jd deleted file mode 100644 index 8a0876996ccf1aaa1b3174db132dadbe04b51cec..0000000000000000000000000000000000000000 --- a/docs/html/resources/browser.jd +++ /dev/null @@ -1,49 +0,0 @@ -page.title=Technical Resources -@jd:body - - - - - - -
    -

    Filter:

    -

    Showing all technical resources:

    -
    - - - -
    -
    No results.
    -
    - - diff --git a/docs/html/resources/community-groups.jd b/docs/html/resources/community-groups.jd deleted file mode 100644 index 6bd347c827350d014cf7d13c67a9f8e24baac843..0000000000000000000000000000000000000000 --- a/docs/html/resources/community-groups.jd +++ /dev/null @@ -1,120 +0,0 @@ -community=true -page.title=Developer Forums -@jd:body - - - -

    Welcome to the Android developers community! We're glad you're here and invite you to participate in discussions with other Android application developers on topics that interest you.

    - -

    The lists on this page are primarily for discussion about Android application development. If you are seeking discussion about Android source code (not application development), then please refer to the Open Source Project Mailing lists.

    - -

    Stack Overflow

    - -

    Stack Overflow is a collaboratively edited question and answer site for programmers. It's a great place to ask technical questions about developing and maintaining Android applications. The site is especially useful for asking questions with definite answers, but can also be used for discussing best practices.

    - -

    On the site, questions and answers relating to Android use the 'android' tag. You can look for Android topics by adding '[android]' to your search query, or by visiting the tag page at:

    - -

    http://stackoverflow.com/questions/tagged/android

    - -

    If you want to ask a question on Stack Overflow, you can use this form. Before submitting the form, make sure to add the 'android' tag so that other Android developers will be able to find your question. As always, before submitting a new question, take a look at the existing topics to see whether another developer has already asked or answered the question.

    - -

    If you are getting started with Android development, Stack Overflow may be a great location to ask questions about general Java programming or setting up the Eclipse development environment. Simply tag your questions with the Java or Eclipse tags in these cases.

    - - -

    Mailing lists

    - -

    There are a number of mailing lists, powered by Google Groups, available for discussing Android application development.

    - - -

    Before you post

    -

    Before writing a post, please try the following:

    - -
      - -
    1. Look through the support information available in the 'More' section of this tab. You may find the answer to your question in the Common Tasks, Troubleshooting Tips, or FAQs sections.
    2. -
    3. Type in keywords of your questions in the main Android site's search bar (such as the one above). This search encompasses all previous discussions, across all groups, as well as the full contents of the site, documentation, and blogs. Chances are good that somebody has run into the same issue before.
    4. - -
    - -

    If you can't find your answer, then we encourage you to address the community. -As you write your post, please do the following: -

      -
    1. Read -the mailing list charter that covers the community guidelines. -
    2. -
    3. Select the most appropriate mailing list for your question. There are several different lists for -developers, described below.
    4. -
    5. - Be very clear about your question -in the subject -- it helps everyone, both those trying to answer your -question as well as those who may be looking for information in the -future.
    6. -
    7. Give plenty of details in your post to -help others understand your problem. Code or log snippets, as well as -pointers to screenshots, may also be helpful. For a great guide to -phrasing your questions, read How To Ask Questions The Smart Way. -
    8. -
    - - -

    Using email with the mailing lists

    -

    Instead of using the Google Groups site, you can use your email client of choice to participate in the mailing lists.

    -

    To subscribe to a group without using the Google Groups site, use the link under "subscribe via email" in the lists above.

    -

    To set up how you receive mailing list postings by email:

    - -
    1. Sign into the group via the Google Groups site. For example, for the android-framework group you would visit http://groups.google.com/group/android-framework.
    2. -
    3. Click "Edit my membership" on the right side.
    4. -
    5. Under "How do you want to read this group?" select one of the email options.
    6. -
    - - -

    Application developer mailing lists

    -
      -
    • android-developers -(subscribe)
      -You're now an experienced Android application developer. You've grasped the basics of Android app development, you're comfortable using the SDK, now you want to move to advanced topics. Get help here with troubleshooting applications, advice on implementation, and strategies for improving your application's performance and user experience. This is the not the right place to discuss user issues (use android-discuss for that) or beginner questions with the Android SDK (use android-beginners for that). -
    • - -
    • android-discuss -(subscribe)
      -The "water cooler" of Android discussion. You can discuss just about anything Android-related here, ideas for the Android platform, announcements about your applications, discussions about Android devices, community resources... As long as your discussion is related to Android, it's on-topic here. However, if you have a discussion here that could belong on another list, you are probably not reaching all of your target audience here and may want to consider shifting to a more targeted list. -
    • - -
    • android-ndk -(subscribe)
      -A place for discussing the Android NDK and topics related to using native code in Android applications. -
    • - -
    • android-security-discuss -(subscribe)
      -A place for open discussion on secure development, emerging security concerns, and best practices for and by android developers. Please don't disclose vulnerabilities directly on this list, you'd be putting all Android users at risk. -
    • - -
    • android-security-announce -(subscribe)
      -A low-volume group for security-related announcements by the Android Security Team. -
    • -
    - - -

    Google Play Help Forum

    - -

    The Google Play Help Forum is a web-based discussion forum where you can ask questions or report issues relating to Google Play.

    - -

    http://support.google.com/googleplay

    diff --git a/docs/html/resources/community-more.jd b/docs/html/resources/community-more.jd deleted file mode 100644 index 3089d45aa9b559b246840c9d6213e69410e62f85..0000000000000000000000000000000000000000 --- a/docs/html/resources/community-more.jd +++ /dev/null @@ -1,71 +0,0 @@ -community=true -page.title=IRC, G+, Twitter -@jd:body - -

    In addition to the Android developer forums, you can participate in the Android developer community through IRC and you can follow us on Twitter.

    - -

    IRC

    - -

    Several IRC channels are available for discussions about developing Android applications.

    - - - - - - - - - - - - - - - -
    ChannelHostDescription
    #androidirc.freenode.netGeneral discussion about Android (and Android development).
    #android-devirc.freenode.netDiscussion focused on developing Android apps.
    - -

    If you haven't used IRC before, check http://en.wikipedia.org/wiki/ -List_of_IRC_clients » for a helpful list of IRC clients. Alternatively, you could also use -this web interface », which -does not require any installation, to join discussions on the Android IRC channels.

    - -

    Here are some tips for using IRC: - -

      -
    • Set your nickname before you join the channel.
    • -
    • Registering your nickname prevents others from using your nickname or impersonating you later: -
      /nick <yournickname>
      -/msg nickserv register <password> <email>
      -

      Afterwards, when you connect, you'll need to supply a password:

      -
      /connect irc.freenode.net
      -/nick <yournickname>
      -/msg nickserv identify <password>
      -/join #android-dev
      -
    • -
    - - -

    Google+

    -

    We use a Google+ page to host Hangouts for developers, talk about the latest -releases, development and design tips, and much more.

    - -
    - - -

    Twitter

    -

    You can follow us on Twitter at this account:

    - -

    http://twitter.com/androiddev

    - - - \ No newline at end of file diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd deleted file mode 100644 index 4c55522b743dc6f6e1c0ddddf5ff86c34b665a93..0000000000000000000000000000000000000000 --- a/docs/html/resources/dashboard/opengl.jd +++ /dev/null @@ -1,79 +0,0 @@ -page.title=OpenGL ES Versions -@jd:body - - - -

    This page provides data about the relative number of active devices that support a particular -version of OpenGL ES. Note that support for one particular version of OpenGL ES also implies -support for any lower version (for example, support for version 2.0 also implies support for -1.1).

    - -

    To declare which version of OpenGL ES your application requires, you should use the {@code -android:glEsVersion} attribute of the {@code <uses-feature>} -element. You can also use the {@code -<supports-gl-texture>} element to declare the GL compression formats that your application -uses.

    - -

    Note: This data is based on the number -of Android devices that have accessed Google Play within a 7-day period -ending on the data collection date noted below.

    - - -
    - - - - - - - - - - - - - - -
    OpenGL ES VersionDistribution
    1.1 only -11.9%
    2.0 & 1.1 -88.1%
    - -

    Data collected during a 7-day period ending on April 2, 2012

    -
    - diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd deleted file mode 100644 index 2cbbe99dce6313e74dece1149be11aed356de3d5..0000000000000000000000000000000000000000 --- a/docs/html/resources/dashboard/platform-versions.jd +++ /dev/null @@ -1,117 +0,0 @@ -page.title=Platform Versions -@jd:body - - - -

    This page provides data about the relative number of active devices -running a given version of the Android platform. This can help you -understand the landscape of device distribution and decide how to prioritize -the development of your application features for the devices currently in -the hands of users. For information about how to target your application to devices based on -platform version, see API Levels.

    - - -

    Current Distribution

    - -

    The following pie chart and table is based on the number of Android devices that have accessed -Google Play within a 14-day period ending on the data collection date noted below.

    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PlatformCodenameAPI LevelDistribution
    Android 1.5Cupcake 30.3%
    Android 1.6Donut 40.7%
    Android 2.1Eclair 76.0%
    Android 2.2Froyo 823.1%
    Android 2.3 -
    - Android 2.3.2
    Gingerbread 90.5%
    Android 2.3.3 -
    - Android 2.3.7
    1063.2%
    Android 3.0Honeycomb 110.1%
    Android 3.1121.0%
    Android 3.2132.2%
    Android 4.0 -
    - Android 4.0.2
    Ice Cream Sandwich140.5%
    Android 4.0.3152.4%
    - -

    Data collected during a 14-day period ending on April 2, 2012

    - -
    - - -

    Historical Distribution

    - -

    The following stacked line graph provides a history of the relative number of -active Android devices running different versions of the Android platform. It also provides a -valuable perspective of how many devices your application is compatible with, based on the -platform version.

    - -

    Notice that the platform versions are stacked on top of each other with the oldest active -version at the top. This format indicates the total percent of active devices that are compatible -with a given version of Android. For example, if you develop your application for -the version that is at the very top of the chart, then your application is -compatible with 100% of active devices (and all future versions), because all Android APIs are -forward compatible. Or, if you develop your application for a version lower on the chart, -then it is currently compatible with the percentage of devices indicated on the y-axis, where the -line for that version meets the y-axis on the right.

    - -

    Each dataset in the timeline is based on the number of Android devices that accessed -Google Play within a 14-day period ending on the date indicated on the x-axis.

    - -
    - - - -

    Last historical dataset collected during a 14-day period ending on April 2, 2012

    - - -
    - diff --git a/docs/html/resources/dashboard/screens.jd b/docs/html/resources/dashboard/screens.jd deleted file mode 100644 index e5c79a125d331e22e2a4907a8c3388f20ef74376..0000000000000000000000000000000000000000 --- a/docs/html/resources/dashboard/screens.jd +++ /dev/null @@ -1,101 +0,0 @@ -page.title=Screen Sizes and Densities -@jd:body - - - -

    This page provides data about the relative number of active devices that have a particular -screen configuration, defined by a combination of screen size and density. To simplify the way that -you design your user interfaces for different screen configurations, Android divides the range of -actual screen sizes and densities into:

    - -
      -
    • A set of four generalized sizes: small, normal, -large, and xlarge
    • -
    • A set of four generalized densities: ldpi (low), mdpi -(medium), hdpi (high), and xhdpi (extra high)
    • -
    - -

    For information about how you can support multiple screen configurations in your -application, see Supporting Multiple -Screens.

    - -

    Note: This data is based on the number -of Android devices that have accessed Google Play within a 7-day period -ending on the data collection date noted below.

    - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ldpimdpihdpixhdpi
    small1.9% 2.5%
    normal0.7% 19.6% 64.6% 2.4%
    large0.2% 2.3%
    xlarge 5.8%
    - -

    Data collected during a 7-day period ending on April 2, 2012

    -
    - diff --git a/docs/html/resources/samples/images/ActionBarCompat1.png b/docs/html/resources/images/ActionBarCompat1.png similarity index 100% rename from docs/html/resources/samples/images/ActionBarCompat1.png rename to docs/html/resources/images/ActionBarCompat1.png diff --git a/docs/html/resources/samples/images/ActionBarCompat2.png b/docs/html/resources/images/ActionBarCompat2.png similarity index 100% rename from docs/html/resources/samples/images/ActionBarCompat2.png rename to docs/html/resources/images/ActionBarCompat2.png diff --git a/docs/html/resources/samples/images/BluetoothChat1.png b/docs/html/resources/images/BluetoothChat1.png similarity index 100% rename from docs/html/resources/samples/images/BluetoothChat1.png rename to docs/html/resources/images/BluetoothChat1.png diff --git a/docs/html/resources/samples/images/BluetoothChat2.png b/docs/html/resources/images/BluetoothChat2.png similarity index 100% rename from docs/html/resources/samples/images/BluetoothChat2.png rename to docs/html/resources/images/BluetoothChat2.png diff --git a/docs/html/resources/samples/images/BluetoothHDP.png b/docs/html/resources/images/BluetoothHDP.png similarity index 100% rename from docs/html/resources/samples/images/BluetoothHDP.png rename to docs/html/resources/images/BluetoothHDP.png diff --git a/docs/html/resources/samples/images/BusinessCard1.png b/docs/html/resources/images/BusinessCard1.png similarity index 100% rename from docs/html/resources/samples/images/BusinessCard1.png rename to docs/html/resources/images/BusinessCard1.png diff --git a/docs/html/resources/samples/images/BusinessCard2.png b/docs/html/resources/images/BusinessCard2.png similarity index 100% rename from docs/html/resources/samples/images/BusinessCard2.png rename to docs/html/resources/images/BusinessCard2.png diff --git a/docs/html/resources/samples/images/ContactManager1.png b/docs/html/resources/images/ContactManager1.png similarity index 100% rename from docs/html/resources/samples/images/ContactManager1.png rename to docs/html/resources/images/ContactManager1.png diff --git a/docs/html/resources/samples/images/ContactManager2.png b/docs/html/resources/images/ContactManager2.png similarity index 100% rename from docs/html/resources/samples/images/ContactManager2.png rename to docs/html/resources/images/ContactManager2.png diff --git a/docs/html/resources/samples/images/CubeLiveWallpaper1.png b/docs/html/resources/images/CubeLiveWallpaper1.png similarity index 100% rename from docs/html/resources/samples/images/CubeLiveWallpaper1.png rename to docs/html/resources/images/CubeLiveWallpaper1.png diff --git a/docs/html/resources/samples/images/CubeLiveWallpaper3.png b/docs/html/resources/images/CubeLiveWallpaper3.png similarity index 100% rename from docs/html/resources/samples/images/CubeLiveWallpaper3.png rename to docs/html/resources/images/CubeLiveWallpaper3.png diff --git a/docs/html/resources/samples/images/HomeSample.png b/docs/html/resources/images/HomeSample.png similarity index 100% rename from docs/html/resources/samples/images/HomeSample.png rename to docs/html/resources/images/HomeSample.png diff --git a/docs/html/resources/samples/images/JetBoy.png b/docs/html/resources/images/JetBoy.png similarity index 100% rename from docs/html/resources/samples/images/JetBoy.png rename to docs/html/resources/images/JetBoy.png diff --git a/docs/html/resources/samples/images/KeyChainDemo1.png b/docs/html/resources/images/KeyChainDemo1.png similarity index 100% rename from docs/html/resources/samples/images/KeyChainDemo1.png rename to docs/html/resources/images/KeyChainDemo1.png diff --git a/docs/html/resources/samples/images/KeyChainDemo2.png b/docs/html/resources/images/KeyChainDemo2.png similarity index 100% rename from docs/html/resources/samples/images/KeyChainDemo2.png rename to docs/html/resources/images/KeyChainDemo2.png diff --git a/docs/html/resources/samples/images/KeyChainDemo3.png b/docs/html/resources/images/KeyChainDemo3.png similarity index 100% rename from docs/html/resources/samples/images/KeyChainDemo3.png rename to docs/html/resources/images/KeyChainDemo3.png diff --git a/docs/html/resources/samples/images/KeyChainDemo4.png b/docs/html/resources/images/KeyChainDemo4.png similarity index 100% rename from docs/html/resources/samples/images/KeyChainDemo4.png rename to docs/html/resources/images/KeyChainDemo4.png diff --git a/docs/html/resources/samples/images/MultiResolution.png b/docs/html/resources/images/MultiResolution.png similarity index 100% rename from docs/html/resources/samples/images/MultiResolution.png rename to docs/html/resources/images/MultiResolution.png diff --git a/docs/html/resources/samples/images/NewsReader.png b/docs/html/resources/images/NewsReader.png similarity index 100% rename from docs/html/resources/samples/images/NewsReader.png rename to docs/html/resources/images/NewsReader.png diff --git a/docs/html/resources/samples/images/NfcDemo.png b/docs/html/resources/images/NfcDemo.png similarity index 100% rename from docs/html/resources/samples/images/NfcDemo.png rename to docs/html/resources/images/NfcDemo.png diff --git a/docs/html/resources/samples/images/SampleSyncAdapter1.png b/docs/html/resources/images/SampleSyncAdapter1.png similarity index 100% rename from docs/html/resources/samples/images/SampleSyncAdapter1.png rename to docs/html/resources/images/SampleSyncAdapter1.png diff --git a/docs/html/resources/samples/images/SampleSyncAdapter2.png b/docs/html/resources/images/SampleSyncAdapter2.png similarity index 100% rename from docs/html/resources/samples/images/SampleSyncAdapter2.png rename to docs/html/resources/images/SampleSyncAdapter2.png diff --git a/docs/html/resources/samples/images/SampleSyncAdapter3.png b/docs/html/resources/images/SampleSyncAdapter3.png similarity index 100% rename from docs/html/resources/samples/images/SampleSyncAdapter3.png rename to docs/html/resources/images/SampleSyncAdapter3.png diff --git a/docs/html/resources/samples/images/SearchableDictionary1.png b/docs/html/resources/images/SearchableDictionary1.png similarity index 100% rename from docs/html/resources/samples/images/SearchableDictionary1.png rename to docs/html/resources/images/SearchableDictionary1.png diff --git a/docs/html/resources/samples/images/SearchableDictionary2.png b/docs/html/resources/images/SearchableDictionary2.png similarity index 100% rename from docs/html/resources/samples/images/SearchableDictionary2.png rename to docs/html/resources/images/SearchableDictionary2.png diff --git a/docs/html/resources/samples/images/SipDemo.png b/docs/html/resources/images/SipDemo.png similarity index 100% rename from docs/html/resources/samples/images/SipDemo.png rename to docs/html/resources/images/SipDemo.png diff --git a/docs/html/resources/samples/images/Snake.png b/docs/html/resources/images/Snake.png similarity index 100% rename from docs/html/resources/samples/images/Snake.png rename to docs/html/resources/images/Snake.png diff --git a/docs/html/resources/samples/images/SoftKeyboard.png b/docs/html/resources/images/SoftKeyboard.png similarity index 100% rename from docs/html/resources/samples/images/SoftKeyboard.png rename to docs/html/resources/images/SoftKeyboard.png diff --git a/docs/html/resources/samples/images/SpinnerTest1.png b/docs/html/resources/images/SpinnerTest1.png similarity index 100% rename from docs/html/resources/samples/images/SpinnerTest1.png rename to docs/html/resources/images/SpinnerTest1.png diff --git a/docs/html/resources/samples/images/SpinnerTest2.png b/docs/html/resources/images/SpinnerTest2.png similarity index 100% rename from docs/html/resources/samples/images/SpinnerTest2.png rename to docs/html/resources/images/SpinnerTest2.png diff --git a/docs/html/resources/samples/images/StackWidget.png b/docs/html/resources/images/StackWidget.png similarity index 100% rename from docs/html/resources/samples/images/StackWidget.png rename to docs/html/resources/images/StackWidget.png diff --git a/docs/html/resources/samples/images/TicTacToeLib.png b/docs/html/resources/images/TicTacToeLib.png similarity index 100% rename from docs/html/resources/samples/images/TicTacToeLib.png rename to docs/html/resources/images/TicTacToeLib.png diff --git a/docs/html/resources/samples/images/TicTacToeMain.png b/docs/html/resources/images/TicTacToeMain.png similarity index 100% rename from docs/html/resources/samples/images/TicTacToeMain.png rename to docs/html/resources/images/TicTacToeMain.png diff --git a/docs/html/resources/samples/images/VoicemailProviderDemo.png b/docs/html/resources/images/VoicemailProviderDemo.png similarity index 100% rename from docs/html/resources/samples/images/VoicemailProviderDemo.png rename to docs/html/resources/images/VoicemailProviderDemo.png diff --git a/docs/html/resources/samples/images/WeatherListWidget.png b/docs/html/resources/images/WeatherListWidget.png similarity index 100% rename from docs/html/resources/samples/images/WeatherListWidget.png rename to docs/html/resources/images/WeatherListWidget.png diff --git a/docs/html/resources/samples/images/WifiDirect.png b/docs/html/resources/images/WifiDirect.png similarity index 100% rename from docs/html/resources/samples/images/WifiDirect.png rename to docs/html/resources/images/WifiDirect.png diff --git a/docs/html/resources/samples/images/Wiktionary.png b/docs/html/resources/images/Wiktionary.png similarity index 100% rename from docs/html/resources/samples/images/Wiktionary.png rename to docs/html/resources/images/Wiktionary.png diff --git a/docs/html/resources/samples/images/WiktionarySimple.png b/docs/html/resources/images/WiktionarySimple.png similarity index 100% rename from docs/html/resources/samples/images/WiktionarySimple.png rename to docs/html/resources/images/WiktionarySimple.png diff --git a/docs/html/resources/samples/images/XmlPhotosAdapter.png b/docs/html/resources/images/XmlPhotosAdapter.png similarity index 100% rename from docs/html/resources/samples/images/XmlPhotosAdapter.png rename to docs/html/resources/images/XmlPhotosAdapter.png diff --git a/docs/html/resources/samples/images/XmlRssReader.png b/docs/html/resources/images/XmlRssReader.png similarity index 100% rename from docs/html/resources/samples/images/XmlRssReader.png rename to docs/html/resources/images/XmlRssReader.png diff --git a/docs/html/resources/samples/images/hcgallery-phone1.png b/docs/html/resources/images/hcgallery-phone1.png similarity index 100% rename from docs/html/resources/samples/images/hcgallery-phone1.png rename to docs/html/resources/images/hcgallery-phone1.png diff --git a/docs/html/resources/samples/images/hcgallery-phone2.png b/docs/html/resources/images/hcgallery-phone2.png similarity index 100% rename from docs/html/resources/samples/images/hcgallery-phone2.png rename to docs/html/resources/images/hcgallery-phone2.png diff --git a/docs/html/resources/samples/images/hcgallery.png b/docs/html/resources/images/hcgallery.png similarity index 100% rename from docs/html/resources/samples/images/hcgallery.png rename to docs/html/resources/images/hcgallery.png diff --git a/docs/html/resources/samples/images/randommusicplayer.png b/docs/html/resources/images/randommusicplayer.png similarity index 100% rename from docs/html/resources/samples/images/randommusicplayer.png rename to docs/html/resources/images/randommusicplayer.png diff --git a/docs/html/resources/samples/images/sample_lunarlander.png b/docs/html/resources/images/sample_lunarlander.png similarity index 100% rename from docs/html/resources/samples/images/sample_lunarlander.png rename to docs/html/resources/images/sample_lunarlander.png diff --git a/docs/html/resources/samples/images/sample_note.png b/docs/html/resources/images/sample_note.png similarity index 100% rename from docs/html/resources/samples/images/sample_note.png rename to docs/html/resources/images/sample_note.png diff --git a/docs/html/resources/samples/images/sample_notepad.png b/docs/html/resources/images/sample_notepad.png similarity index 100% rename from docs/html/resources/samples/images/sample_notepad.png rename to docs/html/resources/images/sample_notepad.png diff --git a/docs/html/resources/samples/images/sample_notepadtest_junit.png b/docs/html/resources/images/sample_notepadtest_junit.png similarity index 100% rename from docs/html/resources/samples/images/sample_notepadtest_junit.png rename to docs/html/resources/images/sample_notepadtest_junit.png diff --git a/docs/html/resources/samples/images/vpn-confirmation.png b/docs/html/resources/images/vpn-confirmation.png similarity index 100% rename from docs/html/resources/samples/images/vpn-confirmation.png rename to docs/html/resources/images/vpn-confirmation.png diff --git a/docs/html/resources/index.jd b/docs/html/resources/index.jd deleted file mode 100644 index 9055868840181c80356b55e97f7334cc6fb2e87f..0000000000000000000000000000000000000000 --- a/docs/html/resources/index.jd +++ /dev/null @@ -1,90 +0,0 @@ -page.title=Developer Resources -@jd:body - - - -

    -This section provides articles, tutorials, sample code, and other -information to help you quickly implement the features you want in your -application. To return to this page later, just click the "Resources" -tab while any Resources page is loaded. -

    - -

    Technical Resources

    - - - - - - - - -
    - - - -

    - Sample Code -

    -

    Fully-functioning sample applications that you can build and run - to learn about how Android works. Feel free to reuse any of the code or - techniques in the samples.

    -
    - - - -

    - Articles -

    -

    Focused discussions about Android development subjects, including - optimizations, tips, interesting implementations, "how-tos", - and so on.

    -
    - - - -

    - Tutorials -

    -

    Step-by-step instructions demonstrating how to build an Android application - that has the specific features you want.

    -
    - -

    Other Resources

    - -
    -
    Community
    -
    Links to the Android discussion groups and information about other ways to -collaborate with other developers.
    - -
    Device Dashboard
    -
    Device distribution data, grouped by various dimensions such as screen size -and Android platform version.
    - -
    More
    -
    Quick development tips, troubleshooting information, and frequently asked -questions (FAQs).
    -
    diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js deleted file mode 100644 index fb4225dc8a2d30dad2af5c3163a8236ee5495abe..0000000000000000000000000000000000000000 --- a/docs/html/resources/resources-data.js +++ /dev/null @@ -1,946 +0,0 @@ -var ANDROID_TAGS = { - type: { - 'article': 'Article', - 'tutorial': 'Tutorial', - 'sample': 'Sample', - 'video': 'Video', - 'library': 'Code Library' - }, - topic: { - 'accessibility': 'Accessibility', - 'accountsync': 'Accounts & Sync', - 'bestpractice': 'Best Practices', - 'communication': 'Communication', - 'compatibility': 'Compatibility', - 'data': 'Data Access', - 'drawing': 'Canvas Drawing', - 'gamedev': 'Game Development', - 'gl': 'OpenGL ES', - 'input': 'Input Methods', - 'intent': 'Intents', - 'layout': 'Layouts/Views', - 'media': 'Multimedia', - 'multitasking': 'Multi-tasking', - 'newfeature': 'New Features', - 'performance': 'Performance', - 'search': 'Search', - 'testing': 'Testing', - 'ui': 'User Interface', - 'web': 'Web Content', - 'widgets': 'App Widgets' - }, - misc: { - 'external': 'External', - 'new': 'New', - 'updated': 'Updated' - } -}; - -var ANDROID_RESOURCES = [ - -////////////////////////// -/// TECHNICAL ARTICLES /// -////////////////////////// - - { - tags: ['article', 'performance', 'bestpractice'], - path: 'articles/avoiding-memory-leaks.html', - title: { - en: 'Avoiding Memory Leaks' - }, - description: { - en: 'Mobile devices often have limited memory, and memory leaks can cause your application to waste this valuable resource without your knowledge. This article provides tips to help you avoid common causes of memory leaks on the Android platform.' - } - }, - { - tags: ['article', 'compatibility'], - path: 'articles/backward-compatibility.html', - title: { - en: 'Backward Compatibility' - }, - description: { - en: 'The Android platform strives to ensure backwards compatibility. However, sometimes you want to use new features which aren\'t supported on older platforms. This article discusses strategies for selectively using these features based on availability, allowing you to keep your applications portable across a wide range of devices.' - } - }, - { - tags: ['article', 'intent'], - path: 'articles/can-i-use-this-intent.html', - title: { - en: 'Can I Use this Intent?' - }, - description: { - en: 'Android offers a very powerful and yet easy-to-use message type called an intent. You can use intents to turn applications into high-level libraries and make code modular and reusable. While it is nice to be able to make use of a loosely coupled API, there is no guarantee that the intent you send will be received by another application. This article describes a technique you can use to find out whether the system contains any application capable of responding to the intent you want to use.' - } - }, - { - tags: ['article', 'input'], - path: 'articles/creating-input-method.html', - title: { - en: 'Creating an Input Method' - }, - description: { - en: 'Input Method Editors (IMEs) provide the mechanism for entering text into text fields and other Views. Android devices come bundled with at least one IME, but users can install additional IMEs. This article covers the basics of developing an IME for the Android platform.' - } - }, - { - tags: ['article', 'drawing', 'ui'], - path: 'articles/drawable-mutations.html', - title: { - en: 'Drawable Mutations' - }, - description: { - en: 'Drawables are pluggable drawing containers that allow applications to display graphics. This article explains some common pitfalls when trying to modify the properties of multiple Drawables.' - } - }, - { - tags: ['article', 'bestpractice', 'ui'], - path: 'articles/faster-screen-orientation-change.html', - title: { - en: 'Faster Screen Orientation Change' - }, - description: { - en: 'When an Android device changes its orientation, the default behavior is to automatically restart the current activity with a new configuration. However, this can become a bottleneck in applications that access a large amount of external data. This article discusses how to gracefully handle this situation without resorting to manually processing configuration changes.' - } - }, - { - tags: ['article', 'compatibility'], - path: 'articles/future-proofing.html', - title: { - en: 'Future-Proofing Your Apps' - }, - description: { - en: 'A collection of common sense advice to help you ensure that your applications don\'t break when new versions of the Android platform are released.' - } - }, - { - tags: ['article', 'input'], - path: 'articles/gestures.html', - title: { - en: 'Gestures' - }, - description: { - en: 'Touch screens allow users to perform gestures, such as tapping, dragging, flinging, or sliding, to perform various actions. The gestures API enables your application to recognize even complicated gestures with ease. This article explains how to integrate this API into an application.' - } - }, - { - tags: ['article', 'gamedev', 'gl'], - path: 'articles/glsurfaceview.html', - title: { - en: 'Introducing GLSurfaceView' - }, - description: { - en: 'This article provides an overview of GLSurfaceView, a class that makes it easy to implement 2D or 3D OpenGL rendering inside of an Android application.' - } - }, - { - tags: ['article', 'ui', 'layout'], - path: 'articles/layout-tricks-reuse.html', - title: { - en: 'Layout Tricks: Creating Reusable UI Components' - }, - description: { - en: 'Learn how to combine multiple standard UI widgets into a single high-level component, which can be reused throughout your application.' - } - }, - { - tags: ['article', 'layout', 'ui', 'performance', 'bestpractice'], - path: 'articles/layout-tricks-efficiency.html', - title: { - en: 'Layout Tricks: Creating Efficient Layouts' - }, - description: { - en: 'Learn how to optimize application layouts as this article walks you through converting a LinearLayout into a RelativeLayout, and analyzes the resulting implications on performance.' - } - }, - { - tags: ['article', 'layout', 'ui', 'performance', 'bestpractice'], - path: 'articles/layout-tricks-stubs.html', - title: { - en: 'Layout Tricks: Using ViewStubs' - }, - description: { - en: 'Learn about using ViewStubs inside an application\'s layout in order to inflate rarely used UI elements, without the performance implications which would otherwise be caused by using the <include> tag.' - } - }, - { - tags: ['article', 'layout', 'ui', 'performance', 'bestpractice'], - path: 'articles/layout-tricks-merge.html', - title: { - en: 'Layout Tricks: Merging Layouts' - }, - description: { - en: 'Learn how to use the <merge> tag in your XML layouts in order to avoid unnecessary levels of hierarchy within an application\'s view tree.' - } - }, - { - tags: ['article', 'ui', 'performance'], - path: 'articles/listview-backgrounds.html', - title: { - en: 'ListView Backgrounds: An Optimization' - }, - description: { - en: 'ListViews are very popular widgets within the Android framework. This article describes some of the optimizations used by the ListView widget, and how to avoid some common issues that this causes when trying to use a custom background.' - } - }, - { - tags: ['article', 'ui'], - path: 'articles/live-folders.html', - title: { - en: 'Live Folders' - }, - description: { - en: 'Live Folders allow users to display any source of data on their home screen without launching an application. This article discusses how to export an application\'s data in a format suitable for display inside of a live folder.' - } - }, - { - tags: ['article', 'ui'], - path: 'articles/live-wallpapers.html', - title: { - en: 'Live Wallpapers' - }, - description: { - en: 'Live wallpapers are richer, animated, interactive backgrounds that users can display in their home screens. Learn how to create a live wallpaper and bundle it in an application that users can install on their devices.' - } - }, - { - tags: ['article', 'bestpractice', 'multitasking'], - path: 'articles/multitasking-android-way.html', - title: { - en: 'Multitasking the Android Way' - }, - description: { - en: 'This article describes best practices and user experience guidelines for multi-tasking on Android.' - } - }, - { - tags: ['article', 'input'], - path: 'articles/on-screen-inputs.html', - title: { - en: 'Onscreen Input Methods' - }, - description: { - en: 'The Input Method Framework (IMF) allows users to take advantage of on-screen input methods, such as software keyboards. This article provides an overview of Input Method Editors (IMEs) and how applications interact with them.' - } - }, - { - tags: ['article', 'performance', 'bestpractice'], - path: 'articles/painless-threading.html', - title: { - en: 'Painless Threading' - }, - description: { - en: 'This article discusses the threading model used by Android applications and how applications can ensure best UI performance by spawning worker threads to handle long-running operations, rather than handling them in the main thread. The article also explains the API that your application can use to interact with Android UI toolkit components running on the main thread and spawn managed worker threads.' - } - }, - { - tags: ['article', 'ui', 'search'], - path: 'articles/qsb.html', - title: { - en: 'Quick Search Box' - }, - description: { - en: 'Quick Search Box (QSB) is a powerful, system-wide search framework. QSB makes it possible for users to quickly and easily find what they\'re looking for, both on their devices and on the web. This article discusses how to work with the QSB framework to add new search results for an installed application.' - } - }, - { - tags: ['article', 'input', 'search', 'ui'], - path: 'articles/speech-input.html', - title: { - en: 'Speech Input' - }, - description: { - en: 'This articles describes the basics of integrating speech recognition into Android applications.' - } - }, - { - tags: ['article', 'compatibility', 'multitasking'], - path: 'articles/service-api-changes-starting-with.html', - title: { - en: 'Service API changes starting with Android 2.0' - }, - description: { - en: 'This article describes the changes and improvements to services introduced in Android 2.0, as well as strategies for compatibility with older versions of the platform.' - } - }, - { - tags: ['article', 'input', 'ui'], - path: 'articles/spell-checker-framework.html', - title: { - en: 'The Android Spell Checker Framework' - }, - description: { - en: 'This article describes the Android spell checker framework and how to use to implement spell checking in applications.' - } - }, - - { - tags: ['article', 'ui'], - path: 'articles/touch-mode.html', - title: { - en: 'Touch Mode' - }, - description: { - en: 'This article explains the touch mode, one of the most important principles of Android\'s UI toolkit. Whenever a user interacts with a device\'s touch screen, the system enters touch mode. While simple in concept, there are important implications touch mode that are often overlooked.' - } - }, - { - tags: ['article', 'performance', 'bestpractice'], - path: 'articles/track-mem.html', - title: { - en: 'Tracking Memory Allocations' - }, - description: { - en: 'This article discusses how to use the Allocation Tracker tool to observe memory allocations and avoid performance problems that would otherwise be caused by ignoring the effect of Dalvik\'s garbage collector.' - } - }, - { - tags: ['article'], - path: 'articles/ui-1.5.html', - title: { - en: 'UI Framework Changes in Android 1.5' - }, - description: { - en: 'Explore the UI changes that were introduced in Android 1.5, compared with the UI provided in Android 1.0 and 1.1.' - } - }, - { - tags: ['article'], - path: 'articles/ui-1.6.html', - title: { - en: 'UI Framework Changes in Android 1.6' - }, - description: { - en: 'Explore the UI changes that were introduced in Android 1.6, compared with the UI provided in Android 1.5. In particular, this article discusses changes to RelativeLayouts and click listeners.' - } - }, - { - tags: ['article', 'ui', 'bestpractice'], - path: 'articles/timed-ui-updates.html', - title: { - en: 'Updating the UI from a Timer' - }, - description: { - en: 'Learn about how to use Handlers as a more efficient replacement for java.util.Timer on the Android platform.' - } - }, - { - tags: ['article', 'ui', 'accessibility'], - path: 'articles/tts.html', - title: { - en: 'Using Text-to-Speech' - }, - description: { - en: 'The text-to-speech API lets your application "speak" to users, in any of several languages. This article provides an overview of the TTS API and how you use to add speech capabilities to your application.' - } - }, - { - tags: ['article', 'accountsync', 'data'], - path: 'articles/contacts.html', - title: { - en: 'Using the Contacts API' - }, - description: { - en: 'Android provides a Contacts API for managing and integrating contacts from multiple accounts and data sources and allows apps to read various information about individual contacts.' - } - }, - { - tags: ['article', 'ui', 'web'], - path: 'articles/using-webviews.html', - title: { - en: 'Using WebViews' - }, - description: { - en: 'WebViews allow an application to dynamically display HTML and execute JavaScript, without relinquishing control to a separate browser application. This article introduces the WebView classes and provides a sample application that demonstrates its use.' - } - }, - { - tags: ['article', 'ui'], - path: 'articles/wikinotes-linkify.html', - title: { - en: 'WikiNotes: Linkify your Text!' - }, - description: { - en: 'This article introduces WikiNotes for Android, part of the Apps for Android project. It covers the use of Linkify to turn ordinary text views into richer, link-oriented content that causes Android intents to fire when a link is selected.' - } - }, - { - tags: ['article', 'intent'], - path: 'articles/wikinotes-intents.html', - title: { - en: 'WikiNotes: Routing Intents' - }, - description: { - en: 'This article illustrates how an application, in this case the WikiNotes sample app, can use intents to route various types of linked text to the application that handles that type of data. For example, an app can use intents to route a linked telephone number to a dialer app and a web URL to a browser.' - } - }, - { - tags: ['article', 'ui', 'performance'], - path: 'articles/window-bg-speed.html', - title: { - en: 'Window Backgrounds & UI Speed' - }, - description: { - en: 'Some Android applications need to squeeze every bit of performance out of the UI toolkit and there are many ways to do so. In this article, you will discover how to speed up the drawing and the perceived startup time of your activities. Both of these techniques rely on a single feature, the window\'s background drawable.' - } - }, - { - tags: ['article', 'performance', 'bestpractice'], - path: 'articles/zipalign.html', - title: { - en: 'Zipalign: an Easy Optimization' - }, - description: { - en: 'The Android SDK includes a tool called zipalign that optimizes the way an application is packaged. Running zipalign against your application enables Android to interact with it more efficiently at run time and thus has the potential to make it and the overall system run faster. This article provides a high-level overview of the zipalign tool and its use.' - } - }, - -/////////////////// -/// SAMPLE CODE /// -/////////////////// - - { - tags: ['sample'], - path: 'samples/AccelerometerPlay/index.html', - title: { - en: 'Accelerometer Play' - }, - description: { - en: 'An example of using the accelerometer to integrate the device\'s acceleration to a position using the Verlet method. This is illustrated with a very simple particle system comprised of a few iron balls freely moving on an inclined wooden table. The inclination of the virtual table is controlled by the device\'s accelerometer.' - } - }, - { - tags: ['sample', 'new', 'ui', 'compatibility', 'newfeature'], - path: 'samples/ActionBarCompat/index.html', - title: { - en: 'Action Bar Compatibility' - }, - description: { - en: 'Shows how to use the action bar on both pre-API 11 and API 11+ devices, maximizing code re-use.' - } - }, - { - tags: ['sample', 'new'], - path: 'samples/AndroidBeamDemo/index.html', - title: { - en: 'Android Beam Demo' - }, - description: { - en: 'An example of how to use the Android Beam feature to send messages between two Android-powered devices (API level 14 or later) that support NFC.' - } - }, - { - tags: ['sample', 'layout', 'ui', 'updated'], - path: 'samples/ApiDemos/index.html', - title: { - en: 'API Demos' - }, - description: { - en: 'A variety of small applications that demonstrate an extensive collection of framework topics.' - } - }, - { - tags: ['sample', 'layout', 'ui', 'fragment', 'loader'], - path: 'samples/Support4Demos/index.html', - title: { - en: 'API 4+ Support Demos' - }, - description: { - en: 'A variety of small applications that demonstrate the use of the helper classes in the Android API 4+ Support Library (classes which work down to API level 4 or version 1.6 of the platform).' - } - }, - { - tags: ['sample', 'layout', 'ui'], - path: 'samples/Support13Demos/index.html', - title: { - en: 'API 13+ Support Demos' - }, - description: { - en: 'A variety of small applications that demonstrate the use of the helper classes in the Android API 13+ Support Library (classes which work down to API level 13 or version 3.2 of the platform).' - } - }, - { - tags: ['sample', 'data', 'newfeature', 'accountsync'], - path: 'samples/BackupRestore/index.html', - title: { - en: 'Backup and Restore' - }, - description: { - en: 'Illustrates a few different approaches that an application developer can take when integrating with the Android Backup Manager using the BackupAgent API introduced in Android 2.2.' - } - }, - { - tags: ['sample', 'communication'], - path: 'samples/BluetoothChat/index.html', - title: { - en: 'Bluetooth Chat' - }, - description: { - en: 'An application for two-way text messaging over Bluetooth.' - } - }, - { - tags: ['sample', 'communication', 'new'], - path: 'samples/BluetoothHDP/index.html', - title: { - en: 'Bluetooth HDP Demo' - }, - description: { - en: 'A sample application that demonstrates how to communicate with a Bluetooth Health Device Profile (HDP) device.' - } - }, - { - tags: ['sample', 'accountsync'], - path: 'samples/BusinessCard/index.html', - title: { - en: 'BusinessCard' - }, - description: { - en: 'An application that demonstrates how to launch the built-in contact picker from within an activity. This sample also uses reflection to ensure that the correct version of the contacts API is used, depending on which API level the application is running under.' - } - }, - { - tags: ['sample', 'accountsync'], - path: 'samples/ContactManager/index.html', - title: { - en: 'Contact Manager' - }, - description: { - en: 'An application that demonstrates how to query the system contacts provider using the ContactsContract API, as well as insert contacts into a specific account.' - } - }, - { - tags: ['sample', 'ui'], - path: 'samples/CubeLiveWallpaper/index.html', - title: { - en: 'Cube Live Wallpaper' - }, - description: { - en: 'An application that demonstrates how to create a live wallpaper and bundle it in an application that users can install on their devices.' - } - }, - { - tags: ['sample', 'new'], - path: 'samples/training/device-management-policy/index.html', - title: { - en: 'Device Policy Management' - }, - description: { - en: 'This is a security-aware sample application that demonstrates the enforcement of device administration policies on Android 2.2 or above platforms.' - } - }, - { - tags: ['sample'], - path: 'samples/Home/index.html', - title: { - en: 'Home' - }, - description: { - en: 'A home screen replacement application.' - } - }, - { - tags: ['sample', 'updated', 'newfeature', 'ui'], - path: 'samples/HoneycombGallery/index.html', - title: { - en: 'Honeycomb Gallery' - }, - description: { - en: 'An image gallery application that demonstrates a variety of new APIs in Android 3.0 (Honeycomb). In addition to providing a tablet-optimized design, it also supports handsets running Android 4.0 (Ice Cream Sandwich) and beyond, so is a good example of how to reuse Fragments to support different screen sizes.' - } - }, - { - tags: ['sample', 'gamedev', 'media'], - path: 'samples/JetBoy/index.html', - title: { - en: 'JetBoy' - }, - description: { - en: 'A game that demonstrates the SONiVOX JET interactive music technology, with JetPlayer.' - } - }, - { - tags: ['sample', 'new'], - path: 'samples/KeyChainDemo/index.html', - title: { - en: 'KeyChain Demo' - }, - description: { - en: 'A demo application to demonstrate how to use KeyChain APIs.' - } - }, - { - tags: ['sample', 'gamedev', 'media'], - path: 'samples/LunarLander/index.html', - title: { - en: 'Lunar Lander' - }, - description: { - en: 'A classic Lunar Lander game.' - } - }, - { - tags: ['sample', 'new'], - path: 'samples/training/ads-and-ux/index.html', - title: { - en: 'Mobile Advertisement Integration' - }, - description: { - en: 'This sample demonstrates the integration of a mobile ad SDK with your application.' - } - }, - { - tags: ['sample', 'ui', 'bestpractice', 'layout'], - path: 'samples/MultiResolution/index.html', - title: { - en: 'Multiple Resolutions' - }, - description: { - en: 'A sample application that shows how to use resource directory qualifiers to provide different resources for different screen configurations.' - } - }, - { - tags: ['sample', 'new', 'bestpractices'], - path: 'samples/newsreader/index.html', - title: { - en: 'News Reader' - }, - description: { - en: 'A sample app demonstrating best practices to support multiple screen sizes and densities.' - } - }, - { - tags: ['sample', 'data'], - path: 'samples/NFCDemo/index.html', - title: { - en: 'NFC Demo' - }, - description: { - en: 'An application for reading NFC Forum Type 2 Tags using the NFC APIs' - } - }, - { - tags: ['sample', 'data'], - path: 'samples/NotePad/index.html', - title: { - en: 'Note Pad' - }, - description: { - en: 'An application for saving notes. Similar (but not identical) to the Notepad tutorial.' - } - }, - { - tags: ['sample', 'media', 'updated'], - path: 'samples/RandomMusicPlayer/index.html', - title: { - en: 'Random Music Player' - }, - description: { - en: 'Demonstrates how to write a multimedia application that plays music from the device and from URLs. It manages media playback from a service and can play music in the background, respecting audio focus changes. Also shows how to use the new Remote Control APIs in API level 14.' - } - }, - { - tags: ['sample', 'newfeature', 'performance', 'gamedev', 'gl', 'updated'], - path: 'samples/RenderScript/index.html', - title: { - en: 'RenderScript' - }, - description: { - en: 'A set of samples that demonstrate how to use various features of the RenderScript APIs.' - } - }, - { - tags: ['sample', 'input', 'new'], - path: 'samples/SpellChecker/SampleSpellCheckerService/index.html', - title: { - en: 'Spell Checker Service' - }, - description: { - en: 'An example spell checker service, using the SpellCheckerService.' - } - }, - { - tags: ['sample', 'input', 'new'], - path: 'samples/SpellChecker/HelloSpellChecker/index.html', - title: { - en: 'Spell Checker Client' - }, - description: { - en: 'An example spell checker client, using the TextServicesManager and SpellCheckerSession.' - } - }, - { - tags: ['sample', 'accountsync', 'updated'], - path: 'samples/SampleSyncAdapter/index.html', - title: { - en: 'SampleSyncAdapter' - }, - description: { - en: 'Demonstrates how an application can communicate with a cloud-based service and synchronize its data with data stored locally in a content provider. The sample uses two related parts of the Android framework — the account manager and the synchronization manager (through a sync adapter).' - } - }, - { - tags: ['sample', 'ui', 'search'], - path: 'samples/SearchableDictionary/index.html', - title: { - en: 'Searchable Dictionary v2' - }, - description: { - en: 'A sample application that demonstrates Android\'s search framework, including how to provide search suggestions for Quick Search Box.' - } - }, - { - tags: ['sample'], - path: 'samples/SipDemo/index.html', - title: { - en: 'SIP Demo' - }, - description: { - en: 'A demo application highlighting how to make internet-based calls with the SIP API.' - } - }, - { - tags: ['sample', 'layout', 'ui'], - path: 'samples/Snake/index.html', - title: { - en: 'Snake' - }, - description: { - en: 'An implementation of the classic game "Snake."' - } - }, - { - tags: ['sample', 'input'], - path: 'samples/SoftKeyboard/index.html', - title: { - en: 'Soft Keyboard' - }, - description: { - en: 'An example of writing an input method for a software keyboard.' - } - }, - { - tags: ['sample', 'testing'], - path: 'samples/Spinner/index.html', - title: { - en: 'Spinner' - }, - description: { - en: 'A simple application that serves as an application under test for the SpinnerTest example.' - } - }, - { - tags: ['sample', 'testing'], - path: 'samples/SpinnerTest/index.html', - title: { - en: 'SpinnerTest' - }, - description: { - en: 'The test application for the Activity Testing tutorial. It tests the Spinner example application.' - } - }, - { - tags: ['sample', 'newfeature', 'widgets'], - path: 'samples/StackWidget/index.html', - title: { - en: 'StackView Widget' - }, - description: { - en: 'Demonstrates how to create a simple collection widget containing a StackView.' - } - }, - { - tags: ['sample', 'newfeature'], - path: 'samples/TicTacToeLib/index.html', - title: { - en: 'TicTacToeLib' - }, - description: { - en: 'An example of an Android library project, a type of project that lets you store and manage shared code and resources in one place, then make them available to your other Android applications.' - } - }, - { - tags: ['sample', 'newfeature',], - path: 'samples/TicTacToeMain/index.html', - title: { - en: 'TicTacToeMain' - }, - description: { - en: 'Demonstrates how an application can make use of shared code and resources stored in an Android library project.' - } - }, - { - tags: ['sample', 'communication', 'new'], - path: 'samples/ToyVpn/index.html', - title: { - en: 'Toy VPN Client' - }, - description: { - en: 'A sample application that illustrates the creation of a custom VPN client.' - } - }, - { - tags: ['sample', 'newfeature'], - path: 'samples/USB/index.html', - title: { - en: 'USB' - }, - description: { - en: 'A set of samples that demonstrate how to use various features of the USB APIs.' - } - }, - { - tags: ['sample', 'data', 'new'], - path: 'samples/VoicemailProviderDemo/index.html', - title: { - en: 'Voicemail Provider' - }, - description: { - en: 'A sample application to demonstrate how to use voicemail content provider APIs in Android 4.0.' - } - }, - { - tags: ['sample','newfeature', 'new'], - path: 'samples/WiFiDirectDemo/index.html', - title: { - en: 'Wi-Fi Direct Demo' - }, - description: { - en: 'A demo application to demonstrate how to use Wi-Fi Direct APIs.' - } - }, - { - tags: ['sample', 'ui', 'widgets'], - path: 'samples/Wiktionary/index.html', - title: { - en: 'Wiktionary' - }, - description: { - en: 'An example of creating interactive widgets for display on the Android home screen.' - } - }, - { - tags: ['sample', 'ui', 'widgets'], - path: 'samples/WiktionarySimple/index.html', - title: { - en: 'Wiktionary (Simplified)' - }, - description: { - en: 'A simple Android home screen widgets example.' - } - }, - { - tags: ['sample', 'widgets', 'newfeature'], - path: 'samples/WeatherListWidget/index.html', - title: { - en: 'Weather List Widget' - }, - description: { - en: 'A more complex collection-widget example which uses a ContentProvider as its data source.' - } - }, - { - tags: ['sample', 'layout'], - path: 'samples/XmlAdapters/index.html', - title: { - en: 'XML Adapters' - }, - description: { - en: 'Binding data to views using XML Adapters examples.' - } - }, - { - tags: ['sample', 'new', 'accessibility'], - path: 'samples/TtsEngine/index.html', - title: { - en: 'Text To Speech Engine' - }, - description: { - en: 'An example Text To Speech engine written using the Android text to speech engine API in Android 4.0.' - } - }, - -///////////////// -/// TUTORIALS /// -///////////////// - - { - tags: ['tutorial'], - path: 'tutorials/hello-world.html', - title: { - en: 'Hello World' - }, - description: { - en: 'Beginning basic application development with the Android SDK.' - } - }, - { - tags: ['tutorial', 'ui', 'layout'], - path: 'tutorials/views/index.html', - title: { - en: 'Hello Views' - }, - description: { - en: 'A walk-through of the various types of layouts and views available in the Android SDK.' - } - }, - { - tags: ['tutorial', 'ui', 'bestpractice'], - path: 'tutorials/localization/index.html', - title: { - en: 'Hello Localization' - }, - description: { - en: 'The basics of localizing your applications for multiple languages and locales.' - } - }, - { - tags: ['tutorial', 'data'], - path: 'tutorials/notepad/index.html', - title: { - en: 'Notepad Tutorial' - }, - description: { - en: 'A multi-part tutorial discussing intermediate-level concepts such as data access.' - } - }, - { - tags: ['tutorial', 'gl'], - path: 'tutorials/opengl/opengl-es10.html', - title: { - en: 'OpenGL ES 1.0' - }, - description: { - en: 'The basics of implementing an application using the OpenGL ES 1.0 APIs.' - } - }, - { - tags: ['tutorial', 'gl'], - path: 'tutorials/opengl/opengl-es20.html', - title: { - en: 'OpenGL ES 2.0' - }, - description: { - en: 'The basics of implementing an application using the OpenGL ES 2.0 APIs.' - } - }, - { - tags: ['tutorial', 'testing'], - path: 'tutorials/testing/helloandroid_test.html', - title: { - en: 'Hello Testing' - }, - description: { - en: 'A basic introduction to the Android testing framework.' - } - }, - { - tags: ['tutorial', 'testing'], - path: 'tutorials/testing/activity_test.html', - title: { - en: 'Activity Testing' - }, - description: { - en: 'A more advanced demonstration of the Android testing framework and tools.' - } - } -]; diff --git a/docs/html/resources/samples/get.jd b/docs/html/resources/samples/get.jd deleted file mode 100644 index 751965ff5b99239fcce1d04cceee11c69a6493ab..0000000000000000000000000000000000000000 --- a/docs/html/resources/samples/get.jd +++ /dev/null @@ -1,92 +0,0 @@ -page.title=Getting the Samples -parent.title=Sample Code -parent.link=../browser.html?tag=sample - -@jd:body - -

    Sometimes, the best way to learn how things are done is to look at some -code.

    - -

    To help you get started quickly, the Android SDK includes a variety of sample -code and tutorials that illustrate key concepts and techniques of Android -application development. For example, the samples show the structure of the -manifest file and the use of activities, services, resources, -intents, content providers, and permissions. They also show how to add -specialized capabilities to your apps, such as Bluetooth and Contacts -integration, multiple screens support, Live Wallpaper, and more.

    - -

    The SDK provides the samples both as source code and as browseable HTML, as -described in the sections below. All of the samples included in the SDK are -licensed under the Apache -2.0 license, so feel free to use any of the code in your own applications as -needed!

    - -

    Downloading the Sample Code

    - -

    The SDK sample code is available to you as a set of downloadable SDK -components, each of which contains the samples for a specific Android platform -version. Once you have installed the SDK, you can download one or more samples -component(s) into your SDK environment using the Android SDK Manager -tool, which is pre-installed in the SDK.

    - -

    To download the samples, launch the Android SDK Manager tool and -select one of the samples components from the Available -Packages panel, for example "Samples for SDK API 7". Select -Install Selected, verify and accept the download, then select -Install Accepted to download the component into your SDK. If -you aren't familiar with the Android SDK Manager and how to launch or -use it, please read the Adding -SDK Components document.

    - -

    When the download is complete, you can find the samples sources on your -computer in this location:

    - -

    -<sdk>/samples/android-<level>/ -

    - -

    You can easily create new Android projects with the downloaded samples, modify them -if you'd like, and then run them on an emulator or device.

    - -

    For example, if you are developing in Eclipse with the ADT Plugin, you can -create a project for the "API Demos" sample app by starting a new Android -Project, selecting "Create project from existing source", and then browsing to -the <sdk>/samples/android-<level>/ApiDemos -directory (the samples directory for the platform version you are -using).

    - -

    If you are not working in Eclipse, you can create a project for the API Demos -sample using the android tool, by executing this command:

    - -
    -android update project -s -n API Demos -t <target_ID> -p <path>samples/android-<level>/ApiDemos/
    -
    - -

    Browsing the Sample Code

    - -

    For your convenience, the SDK provides browseable source code for the latest -versions of the samples. You can use your browser to navigate through the -structure of each sample and look at the source code in each of its files.

    - -

    To browse the samples, go to the List of Sample Apps first. -From there you can read a short summary of each sample application and what -types of concepts, features, or APIs it includes. Then, use the links provided -to move through the directories and files of each sample. The browseable source -is generated from the same source code that is downloadable through the Android -SDK Manager, as described above.

    - -

    The browseable samples files are available online, at the Android Developers -site only and are not included in the downloadable offline documentation. -Note that, although samples for several platform versions are available for -download, only the samples for the latest platform version are browseable online. -

    - - -

    More Sample Code

    - -

    If you are looking for more sample code, check out -apps-for-android, a -collection of open source applications that demonstrate various Android APIs.

    - - diff --git a/docs/html/resources/samples/index.jd b/docs/html/resources/samples/index.jd deleted file mode 100644 index acb80e8267814ef14243304a0123f83fa254153c..0000000000000000000000000000000000000000 --- a/docs/html/resources/samples/index.jd +++ /dev/null @@ -1,11 +0,0 @@ -page.title=List of Sample Apps -@jd:body - - - -

    This document has moved. Please go to List of Sample -Apps.

    - diff --git a/docs/html/resources/topics.jd b/docs/html/resources/topics.jd deleted file mode 100644 index b5960ffcbebf90b90680b9e723463c571e38228d..0000000000000000000000000000000000000000 --- a/docs/html/resources/topics.jd +++ /dev/null @@ -1,72 +0,0 @@ -page.title=Technical Resource Topics -@jd:body - - - -

    -You can browse the list of technical resources by topic by clicking on the -links below. Over time, as more topics are added, they will be added to the -list below. -

    - - - - - -
    - - \ No newline at end of file diff --git a/docs/html/resources/tutorials/hello-world.jd b/docs/html/resources/tutorials/hello-world.jd deleted file mode 100644 index 70ba06c002e46add2a21ddf5e4e7d797fdf8f345..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/hello-world.jd +++ /dev/null @@ -1,607 +0,0 @@ -page.title=Hello, World -parent.title=Tutorials -parent.link=../browser.html?tag=tutorial -@jd:body - - -

    As a developer, you know that the first impression of a development framework is how easy it is -to write "Hello, World." Well, on Android, it's pretty easy. It's particularly easy if you're using -Eclipse as your IDE, because we've provided a great plugin that handles your project creation and -management to greatly speed up your development cycles.

    - -

    This tutorial assumes that you're using Eclipse. If you're using the command line, see -Building and Running from the -Command Line. You can then return to this tutorial and ignore anything about Eclipse.

    - -

    Before you start, you should already have the SDK installed, and if you're -using Eclipse, you should have installed the ADT plugin as well. If you have not -installed these, see Installing the -Android SDK and return here when you've completed the installation.

    - -

    Install a Platform

    - -

    To run the Hello World application, you need to install at least one Android -platform in your SDK environment. If you have not already performed this step, -you need to do it now.

    - -

    To install a platform in Eclipse:

    - -
      - -
    1. In the Android SDK Manager, choose Available -Packages in the left panel.
    2. - -
    3. In the right panel, expand the Android Repository list to display -the components available for installation.
    4. - -
    5. Select at least one platform to install, and click Install -Selected. If you aren't sure which platform to install, use the latest -version.
    6. -
    - -

    Create an AVD

    - - - -

    In this tutorial, you will run your application in the Android Emulator. -Before you can launch the emulator, you must create an -Android Virtual Device (AVD). An AVD defines the system image and -device settings used by the emulator.

    - - - -

    To create an AVD:

    -
      -
    1. In Eclipse, select Window > AVD Manager.
    2. -
    3. Select Virtual Devices in the left panel.
    4. - -
    5. Click New.... -

      The Create New AVD dialog appears.

      -
    6. -
    7. Type the name of the AVD, such as "my_avd".
    8. -
    9. Choose a target. -

      The target is the platform (that is, the version of the Android SDK, such as 2.3.3) you want - to run on the emulator. For this tutorial, choose the latest platform that you have installed - and ignore the rest of the fields.

      -
    10. -
    11. Click Create AVD.
    12. -
    -

    Create a New Android Project

    - -

    After you've created an AVD you can move to the next step and start a new Android project in -Eclipse.

    - -
      -
    1. In Eclipse, select File > New > Project.... -

      If the ADT - Plugin for Eclipse has been successfully installed, the resulting dialog - should have a folder labeled "Android" which should contain - "Android Project". (After you create one or more Android projects, an entry for - "Android XML File" will also be available.)

      -
    2. - -
    3. Select "Android Project" and click Next.
      - -
    4. - -
    5. Fill in the project details with the following values: -
        -
      • Project name: HelloAndroid
      • -
      • Build Target: Select a platform version that is equal to or lower than the - target you chose for your AVD.
      • -
      • Application name: Hello, Android
      • -
      • Package name: com.example.helloandroid (or your own private namespace)
      • -
      • Create Activity: HelloAndroid
      • -
      -

      Click Finish.

      - - - -

      Here is a description of each field:

      - -
      -
      Project Name
      -
      This is the Eclipse project name — the name of the directory - that contains the project files.
      -
      Build Target
      -
      This is the version of the Android SDK that you're using to build your - application. For example, if you choose Android 2.1, your application will be - compiled against the Android 2.1 platform library. The target you choose here - does not have to match the target you chose for your AVD; however, the target must - be equal to or lower than the target you chose for your AVD. Android - applications are forward-compatible, which means an application will run on the - platform against which it is built as well as all platforms that are released in the - future. For example, an application that is built against the 2.1 platform library - will run normally on an AVD or device that is running the 2.3.3. The reverse is not - true.
      -
      Application Name
      -
      This is the human-readable title for your application — the name that - appears on the Android device.
      -
      Package Name
      -
      This is the package namespace (following the same rules as for - packages in the Java programming language) that you want all your source code to - reside under. This also sets the package name under which the stub - Activity is generated. -

      Your package name must be unique across - all packages installed on the Android system; for this reason, it's - important to use a standard domain-style package for your - applications. The example above uses the "com.example" namespace, which is - a namespace reserved for example documentation — - when you develop your own applications, you should use a namespace that's - appropriate to your organization or entity.

      -
      Create Activity
      -
      This is the name for the class stub that is generated by the plugin. - This is a subclass of Android's {@link android.app.Activity} class. An - Activity is simply a class that can run and do work. It can create a UI if it - chooses, but it doesn't need to. As the checkbox suggests, this is optional, but an - Activity is almost always used as the basis for an application.
      -
      Min SDK Version
      -
      This value specifies the minimum API Level on which your application will run. - The Min SDK Version should be the same as the Build Target you - chose. For example, if the Build Target is Android 2.1, then the Min - SDK Version should be 7 or lower (it can never be higher than 7). For more - information, see - Android API Levels. -
      -
      - -

      Other fields: The checkbox for "Use default location" allows you to change - the location on disk where the project's files are generated and stored.

      -
    6. -
    - -

    Your Android project is now ready. It should be visible in the Package Explorer on the left. Open -the HelloAndroid.java file, located inside HelloAndroid > src > -com.example.helloandroid). It should look like this:

    - -
    -package com.example.helloandroid;
    -
    -import android.app.Activity;
    -import android.os.Bundle;
    -
    -public class HelloAndroid extends Activity {
    -    /** Called when the activity is first created. */
    -    @Override
    -    public void onCreate(Bundle savedInstanceState) {
    -        super.onCreate(savedInstanceState);
    -        setContentView(R.layout.main);
    -    }
    -}
    - -

    Notice that the class is based on the {@link android.app.Activity} class. An Activity is a -single application entity that is used to perform actions. An application may have many separate -activities, but the user interacts with them one at a time. The -{@link android.app.Activity#onCreate(Bundle) onCreate()} method -is called by the Android system when your Activity starts — -it is where you should perform all initialization and UI setup. An activity is not required to -have a user interface, but usually does.

    - -

    Now let's modify some code!

    - - -

    Construct the UI

    - -

    Take a look at the revised code below and then make the same changes to your HelloAndroid class. -The bold items are lines that have been added.

    - -
    -package com.example.helloandroid;
    -
    -import android.app.Activity;
    -import android.os.Bundle;
    -import android.widget.TextView;
    -
    -public class HelloAndroid extends Activity {
    -   /** Called when the activity is first created. */
    -   @Override
    -   public void onCreate(Bundle savedInstanceState) {
    -       super.onCreate(savedInstanceState);
    -       TextView tv = new TextView(this);
    -       tv.setText("Hello, Android");
    -       setContentView(tv);
    -   }
    -}
    - -

    Tip: An easy way to add import packages to your project is -to press Ctrl-Shift-O (Cmd-Shift-O, on Mac). This is an Eclipse -shortcut that identifies missing packages based on your code and adds them for you. You may have -to expand the import statements in your code for this to work.

    - -

    An Android user interface is composed of hierarchies of objects called -Views. A {@link android.view.View} is a drawable object used as an element in your UI layout, -such as a button, image, or (in this case) a text label. Each of these objects is a subclass -of the View class and the subclass that handles text is {@link android.widget.TextView}.

    - -

    In this change, you create a TextView with the class constructor, which accepts -an Android {@link android.content.Context} instance as its parameter. A -Context is a handle to the system; it provides services like -resolving resources, obtaining access to databases and preferences, and so -on. The Activity class inherits from Context, and because your -HelloAndroid class is a subclass of Activity, it is also a Context. So, you can -pass this as your Context reference to the TextView.

    - -

    Next, you define the text content with -{@link android.widget.TextView#setText(CharSequence) setText()}.

    - -

    Finally, you pass the TextView to -{@link android.app.Activity#setContentView(View) setContentView()} in order to -display it as the content for the Activity UI. If your Activity doesn't -call this method, then no UI is present and the system will display a blank -screen.

    - -

    There it is — "Hello, World" in Android! The next step, of course, is -to see it running.

    - - -

    Run the Application

    - -

    The Eclipse plugin makes it easy to run your applications:

    - -
      -
    1. Select Run > Run.
    2. -
    3. Select "Android Application".
    4. -
    - - - -

    The Eclipse plugin automatically creates a new run configuration for your project -and then launches the Android Emulator. Depending on your environment, the Android -emulator might take several minutes to boot fully, so please be patient. When the -emulator is booted, the Eclipse plugin installs your application -and launches the default Activity. You should now see something like this:

    - - - -

    The "Hello, Android" you see in the grey bar is actually the application title. The Eclipse plugin -creates this automatically (the string is defined in the res/values/strings.xml file and referenced -by your AndroidManifest.xml file). The text below the title is the actual text that you have -created in the TextView object.

    - -

    That concludes the basic "Hello World" tutorial, but you should continue reading for some more -valuable information about developing Android applications.

    - - -

    Upgrade the UI to an XML Layout

    - -

    The "Hello, World" example you just completed uses what is called a "programmatic" -UI layout. This means that you constructed and built your application's UI -directly in source code. If you've done much UI programming, you're -probably familiar with how brittle that approach can sometimes be: small -changes in layout can result in big source-code headaches. It's also -easy to forget to properly connect Views together, which can result in errors in -your layout and wasted time debugging your code.

    - -

    That's why Android provides an alternate UI construction model: XML-based -layout files. The easiest way to explain this concept is to show an -example. Here's an XML layout file that is identical in behavior to the -programmatically-constructed example:

    - -
    <?xml version="1.0" encoding="utf-8"?>
    -<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    -  android:id="@+id/textview"
    -  android:layout_width="fill_parent"
    -  android:layout_height="fill_parent"
    -  android:text="@string/hello"/>
    - -

    The general structure of an Android XML layout file is simple: it's a tree -of XML elements, wherein each node is the name of a View class -(this example, however, is just one View element). You can use the -name of any class that extends {@link android.view.View} as an element in your XML layouts, -including custom View classes you define in your own code. This -structure makes it easy to quickly build up UIs, using a more simple -structure and syntax than you would use in a programmatic layout. This model is inspired -by the web development model, wherein you can separate the presentation of your -application (its UI) from the application logic used to fetch and fill in data.

    - -

    In the above XML example, there's just one View element: the TextView, -which has five XML attributes. Here's a summary of what they mean:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Attribute - - Meaning -
    - xmlns:android - - This is an XML namespace declaration that tells the Android tools that you are going to refer to common attributes defined in the Android namespace. The outermost tag in every Android layout file must have this attribute.
    -
    - android:id - - This attribute assigns a unique identifier to the TextView element. - You can use the assigned ID to reference this View from your source code or from other - XML resource declarations. -
    - android:layout_width - - This attribute defines how much of the available width on the screen this View should consume. - In this case, it's the only View so you want it to take up the entire screen, which is what a value of "fill_parent" means.
    -
    - android:layout_height - - This is just like android:layout_width, except that it refers to available screen height. -
    - android:text - - This sets the text that the TextView should display. In this example, you use a string - resource instead of a hard-coded string value. - The hello string is defined in the res/values/strings.xml file. This is the - recommended practice for inserting strings to your application, because it makes the localization - of your application to other languages graceful, without need to hard-code changes to the layout file. - For more information, see Resources - and Internationalization. -
    - - -

    These XML layout files belong in the res/layout/ directory of your project. The "res" is -short for "resources" and the directory contains all the non-code assets that -your application requires. In addition to layout files, resources also include assets -such as images, sounds, and localized strings.

    - - - -

    The Eclipse plugin automatically creates one of these layout files for you: main.xml. -In the "Hello World" application you just completed, this file was ignored and you created a -layout programmatically. This was meant to teach you more -about the Android framework, but you should almost always define your layout -in an XML file instead of in your code. -The following procedures will instruct you how to change your -existing application to use an XML layout.

    - -
      -
    1. In the Eclipse Package Explorer, expand the -/res/layout/ folder and open main.xml (once opened, you might need to click -the "main.xml" tab at the bottom of the window to see the XML source). Replace the contents with -the following XML: - -
      <?xml version="1.0" encoding="utf-8"?>
      -<TextView xmlns:android="http://schemas.android.com/apk/res/android"
      -  android:id="@+id/textview"
      -  android:layout_width="fill_parent"
      -  android:layout_height="fill_parent"
      -  android:text="@string/hello"/>
      -

      Save the file.

      -
    2. - -
    3. Inside the res/values/ folder, open strings.xml. -This is where you should save all default text strings for your user interface. If you're using Eclipse, then -ADT will have started you with two strings, hello and app_name. -Revise hello to something else. Perhaps "Hello, Android! I am a string resource!" -The entire file should now look like this: -
      -<?xml version="1.0" encoding="utf-8"?>
      -<resources>
      -    <string name="hello">Hello, Android! I am a string resource!</string>
      -    <string name="app_name">Hello, Android</string>
      -</resources>
      -
      -
    4. - -
    5. Now open and modify your HelloAndroid class and use the -XML layout. Edit the file to look like this: -
      -package com.example.helloandroid;
      -
      -import android.app.Activity;
      -import android.os.Bundle;
      -
      -public class HelloAndroid extends Activity {
      -    /** Called when the activity is first created. */
      -    @Override
      -    public void onCreate(Bundle savedInstanceState) {
      -        super.onCreate(savedInstanceState);
      -        setContentView(R.layout.main);
      -    }
      -}
      - -

      When you make this change, type it by hand to try the -code-completion feature. As you begin typing "R.layout.main" the plugin will offer you -suggestions. You'll find that it helps in a lot of situations.

      - -

      Instead of passing setContentView() a View object, you give it a reference -to the layout resource. -The resource is identified as R.layout.main, which is actually a compiled object representation of -the layout defined in /res/layout/main.xml. The Eclipse plugin automatically creates this reference for -you inside the project's R.java class. If you're not using Eclipse, then the R.java class will be generated for you -when you run Ant to build the application. (More about the R class in a moment.)

      -
    6. -
    - -

    Now re-run your application — because you've created a launch configuration, all -you need to do is click the green arrow icon to run, or select -Run > Run History > Android Activity. Other than the change to the TextView -string, the application looks the same. After all, the point was to show that the two different -layout approaches produce identical results.

    - -

    Note: You may have to unlock the screen on the emulator to see -your application — just as you would unlock the screen on a device. If you have problems -running the emulator, see Using the -Android Emulator.

    - -

    Continue reading for an introduction -to debugging and a little more information on using other IDEs. When you're ready to learn more, -read Application -Fundamentals for an introduction to all the elements that make Android applications work. -Also refer to the Developer's Guide -introduction page for an overview of the Dev Guide documentation.

    - - -
    -

    R class

    -

    In Eclipse, open the file named R.java (in the gen/ [Generated Java Files] folder). -It should look something like this:

    - -
    -package com.example.helloandroid;
    -
    -public final class R {
    -    public static final class attr {
    -    }
    -    public static final class drawable {
    -        public static final int icon=0x7f020000;
    -    }
    -    public static final class id {
    -        public static final int textview=0x7f050000;
    -    }
    -    public static final class layout {
    -        public static final int main=0x7f030000;
    -    }
    -    public static final class string {
    -        public static final int app_name=0x7f040001;
    -        public static final int hello=0x7f040000;
    -    }
    -}
    -
    - -

    A project's R.java file is an index into all the resources defined in the -file. You use this class in your source code as a sort of short-hand -way to refer to resources you've included in your project. This is -particularly powerful with the code-completion features of IDEs like Eclipse -because it lets you quickly and interactively locate the specific reference -you're looking for.

    - -

    It's possible yours looks slightly different than this (perhaps the hexadecimal values are -different). -For now, notice the inner class named "layout", and its -member field "main". The Eclipse plugin noticed the XML -layout file named main.xml and generated a class for it here. As you add other -resources to your project (such as strings in the res/values/string.xml file or drawables inside -the res/drawable/ directory) you'll see R.java change to keep up.

    -

    When not using Eclipse, this class file will be generated for you at build time (with the Ant tool).

    -

    You should never edit this file by hand.

    -
    - -

    Debug Your Project

    - -

    The Android Plugin for Eclipse also has excellent integration with the Eclipse -debugger. To demonstrate this, introduce a bug into -your code. Change your HelloAndroid source code to look like this:

    - -
    -package com.example.helloandroid;
    -
    -import android.app.Activity;
    -import android.os.Bundle;
    -
    -public class HelloAndroid extends Activity {
    -    /** Called when the activity is first created. */
    -    @Override
    -    public void onCreate(Bundle savedInstanceState) {
    -        super.onCreate(savedInstanceState);
    -        Object o = null;
    -        o.toString();
    -        setContentView(R.layout.main);
    -    }
    -}
    - -

    This change simply introduces a NullPointerException into your code. If -you run your application again, you'll eventually see this:

    - - - -

    Press "Force Quit" to terminate the application and close the emulator window.

    - -

    To find out more about the error, set a breakpoint in your source code -on the line Object o = null; (double-click on the marker bar next to the source code line). Then select Run > Debug History > Hello, -Android from the menu to enter debug mode. Your app will restart in the -emulator, but this time it will suspend when it reaches the breakpoint you -set. You can then step through the code in Eclipse's Debug Perspective, -just as you would for any other application.

    - - - - -

    Creating the Project without Eclipse

    - -

    If you don't use Eclipse (such as if you prefer another IDE, or simply use text - editors and command line tools) then the Eclipse plugin can't help you. - Don't worry though — you don't lose any functionality just because you don't - use Eclipse.

    - -

    The Android Plugin for Eclipse is really just a wrapper around a set of tools - included with the Android SDK. (These tools, like the emulator, aapt, adb, - ddms, and others are documented elsewhere.) - Thus, it's possible to - wrap those tools with another tool, such as an 'ant' build file.

    - -

    The Android SDK includes a tool named "android" that can be - used to create all the source code and directory stubs for your project, as well - as an ant-compatible build.xml file. This allows you to build your project - from the command line, or integrate it with the IDE of your choice.

    - -

    For example, to create a HelloAndroid project similar to the one created - in Eclipse, use this command:

    - -
    -android create project \
    -    --package com.example.helloandroid \
    -    --activity HelloAndroid \
    -    --target 2 \
    -    --path <path-to-your-project>/HelloAndroid
    -
    - -

    This creates the required folders and files for the project at the location - defined by the path.

    - -

    For more information on how to use the SDK tools to create and build projects, please read -Developing in Other IDEs.

    \ No newline at end of file diff --git a/docs/html/resources/tutorials/index.html b/docs/html/resources/tutorials/index.html deleted file mode 100644 index 4881acf44581bd625a78990ae7e9b844b2a604c3..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -click here if you are not redirected. - - \ No newline at end of file diff --git a/docs/html/resources/tutorials/localization/index.jd b/docs/html/resources/tutorials/localization/index.jd deleted file mode 100755 index de4433b3092a3e6b7288b73582c3c7cde379e03f..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/localization/index.jd +++ /dev/null @@ -1,595 +0,0 @@ -page.title=Hello, L10N -parent.title=Tutorials -parent.link=../../browser.html?tag=tutorial -@jd:body - -
    -
    -

    In this document

    -
      -
    1. Create an Unlocalized App -
        -
      1. Create the Project and Layout
      2. -
      3. Create Default Resources
      4. -
      -
    2. -
    3. Run the Unlocalized App
    4. -
    5. Plan the Localization
    6. -
    7. Localize the App -
        -
      1. Localize the Strings
      2. -
      3. Localize the Images
      4. -
      -
    8. -
    9. Run and Test the Localized App
    10. -
    -

    See also

    -
      -
    1. {@link android.widget.Button}
    2. -
    3. {@link android.widget.TextView}
    4. -
    5. {@link android.app.AlertDialog}
    6. -
    -
    -
    - -

    In this tutorial, we will create a Hello, L10N application that uses the -Android framework to selectively load resources. Then we will localize the -application by adding resources to the res/ directory.

    - -

    This tutorial uses the practices described in the Localization -document.

    - - -

    Create an Unlocalized Application

    - -

    The first version of the Hello, L10N application will use only the default -resource directories (res/drawable, res/layout, and -res/values). These resources are not localized — they are the -graphics, layout, and strings that we expect the application to use most often. -When a user runs the application in the default locale, or in a locale that the -application does not specifically support, the application will load resources -from these default directories.

    - -

    The application consists of a simple user interface that displays two -{@link android.widget.TextView} objects and a {@link android.widget.Button} image with a - background image of a national flag. When clicked, the button displays an -{@link android.app.AlertDialog} object that shows additional text.

    - -

    Create the Project and Layout

    - -

    For this application, the default language will be British English and the -default location the United Kingdom.

    - -
      -
    1. Start a new project and Activity called "HelloL10N." If you are -using Eclipse, fill out these values in the New Android Project wizard: -
        -
      • Project name: HelloL10N
      • -
      • Application name: Hello, L10N
      • -
      • Package name: com.example.hellol10n (or your own private -namespace)
      • -
      • Create Activity: HelloL10N
      • -
      • Min SDK Version: 3
      • -
      -

      The basic project contains a res/ directory with -subdirectories for the three most common types of resources: graphics -(res/drawable/), layouts (res/layout/) and strings -(res/values/). Most of the localization work you do later in this -tutorial will involve adding more subdirectories to the res/ -directory.

      - plain project -
    2. -
    3. Open the res/layout/main.xml file and replace it with the -following code: -
      <?xml version="1.0" encoding="utf-8"?>
      -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -    android:orientation="vertical"
      -    android:layout_width="fill_parent"
      -    android:layout_height="fill_parent"
      -    >
      -<TextView
      -    android:layout_width="fill_parent" 
      -    android:layout_height="wrap_content"
      -    android:gravity="center_horizontal"
      -    android:text="@string/text_a"
      -    />
      -<TextView
      -    android:layout_width="fill_parent"
      -    android:layout_height="wrap_content"
      -    android:gravity="center_horizontal"
      -    android:text="@string/text_b"
      -    />
      -<Button
      -    android:id="@+id/flag_button"
      -    android:layout_width="wrap_content"
      -    android:layout_height="wrap_content"
      -    android:layout_gravity="center"
      -    />
      -</LinearLayout>
      -    
      - -

      The LinearLayout has two {@link android.widget.TextView} objects that will -display localized text and one {@link android.widget.Button} that shows a flag. -

      -
    4. -
    - -

    Create Default Resources

    - -

    The layout refers to resources that need to be defined.

    - -
      -
    1. Create default text strings. To do this, open the res/values/strings.xml file and replace it with the following code:
      -
      <?xml version="1.0" encoding="utf-8"?>
      -<resources>
      -    <string name="app_name">Hello, L10N</string>
      -    <string name="text_a">Shall I compare thee to a summer"'"s day?</string>
      -    <string name="text_b">Thou art more lovely and more temperate.</string>
      -    <string name="dialog_title">No Localisation</string>
      -    <string name="dialog_text">This dialog box"'"s strings are not localised. For every locale, the text here will come from values/strings.xml.</string>
      -</resources>
      - -

      This code provides British English text for each string that the application -will use. When we localize this application, we will provide alternate text in -German, French, and Japanese for some of the strings.

      -
    2. -
    3. Add a default flag graphic to the res/drawable folder by -saving flag.png as -res/drawable/flag.png. When the application is not localized, it -will show a British flag.
      - -
    4. -
    5. Open HelloL10N.java (in the src/ directory) and add the -following code inside the onCreate() method (after -setContentView). - -
      // assign flag.png to the button, loading correct flag image for current locale
      -Button b;
      -(b = (Button)findViewById(R.id.flag_button)).setBackgroundDrawable(this.getResources().getDrawable(R.drawable.flag));
      -
      -// build dialog box to display when user clicks the flag
      -AlertDialog.Builder builder = new AlertDialog.Builder(this);
      -builder.setMessage(R.string.dialog_text)
      -    .setCancelable(false)
      -    .setTitle(R.string.dialog_title)
      -    .setPositiveButton("Done", new DialogInterface.OnClickListener() {
      -        public void onClick(DialogInterface dialog, int id) {
      -        dialog.dismiss();
      -        }
      -    });
      -final AlertDialog alert = builder.create();
      -
      -// set click listener on the flag to show the dialog box 
      -b.setOnClickListener(new View.OnClickListener() {
      -    public void onClick(View v) {
      -	alert.show();
      -    }
      -    });
      - -

      Tip: In Eclipse, use -Ctrl-Shift-O (Cmd-Shift-O, on Mac) to find and -add missing import packages to your project, then save the HelloL10N.java -file.

      - -

      The code that you added does the following:

      - -
        -
      • It assigns the correct flag icon to the button. - For now, no resources are defined other than the default, so this code -will always assign the contents of res/drawable/flag.png (the -British flag) as the flag icon, no matter what the locale. Once we add more -flags for different locales, this code will sometimes assign a different flag. -
      • -
      • It creates an {@link android.app.AlertDialog} object and sets a click listener so that when the -user clicks the button, the AlertDialog will display. - We will not localize the dialog text; -the AlertDialog will always display the dialog_text that is located -within res/values/strings.xml.
      • -
      - -
    6. -
    - -

    The project structure now looks like this:

    - - nonlocalized - -

    Tip: If you will want to run the application on -a device and not just on an emulator, open AndroidManifest.xml and -add android:debuggable="true" inside the -<application> element. For information about setting up the -device itself so it can run applications from your system, see Developing on a Device.

    - - -

    Run the Unlocalized Application

    - -

    Save the project and run the application to see how it works. No matter what -locale your device or emulator is set to, the application runs the same way. It -should look something like this:

    - - - - - - - - - - -
    The unlocalized application, running in any locale:After clicking the flag, in any locale:
    nonlocalized2
    -

    Plan the Localization

    -

    The first step in localizing an application is to plan how the application -will render differently in different locales. In this application, the default -locale will be the United Kingdom. We will add some locale-specific information -for Germany, France, Canada, Japan, and the United States. Table 1 shows the -plan for how the application will appear in different locales.

    - -

    Table 1

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Region /
    - Language
    United KingdomGermanyFranceCanadaJapanUnited StatesOther Location

    - English
    British English text; British flag (default)-- British English text; Canadian flag- British English text; U.S. flag British English text; British flag (default)
    German-German text for app_name, text_a and -text_b; German flag----German text for app_name, text_a and -text_b; British flag
    French--French text for app_name, text_a and -text_b; French flagFrench text for app_name, text_a and -text_b; Canadian flag--French text for app_name, text_a and -text_b; British flag
    Japanese----Japanese text for text_a and text_b; Japanese -flag-Japanese text for text_a and text_b; British -flag
    Other Language------ British English text; British flag (default)
    - -

    Note that other behaviors are possible; for example, the -application could support Canadian English or U.S. English text. But given the -small amount of text involved, adding more versions of English would not make -this application more useful.

    - -

    As shown in the table above, the plan calls for five flag icons in addition -to the British flag that is already in the res/drawable/ folder. It -also calls for three sets of text strings other than the text that is in -res/values/strings.xml.

    - -

    Table 2 shows where the needed text strings and flag icons will go, and -specifies which ones will be loaded for which locales. (For more about the -locale codes, see -Alternate Resources.)

    -

    Table 2

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Locale CodeLanguage / CountryLocation of strings.xmlLocation of flag.png
    DefaultEnglish / United Kingdomres/values/res/drawable/
    de-rDEGerman / Germanyres/values-de/res/drawable-de-rDE/
    fr-rFRFrench / Franceres/values-fr/res/drawable-fr-rFR/
    fr-rCAFrench / Canadares/values-fr/res/drawable-fr-rCA/
    en-rCAEnglish / Canada(res/values/)res/drawable-en-rCA/
    ja-rJPJapanese / Japanres/values-ja/res/drawable-ja-rJP/
    en-rUSEnglish / United States(res/values/)res/drawable-en-rUS/
    - -

    Tip: A folder qualifer cannot specify a region -without a language. Having a folder named res/drawable-rCA/, -for example, will prevent the application from compiling.

    - -

    At run time, the application will select a set of resources to load based on the locale -that is set in the user's device. In cases where no locale-specific resources -are available, the application will fall back on the defaults.

    - -

    For example, assume that the device's language is set to German and its -location to Switzerland. Because this application does not have a -res/drawable-de-rCH/ directory with a flag.png file in it, the system -will fall back on the default, which is the UK flag located in -res/drawable/flag.png. The language used will be German. Showing a -British flag to German speakers in Switzerland is not ideal, but for now we will -just leave the behavior as it is. There are several ways you could improve this -application's behavior if you wanted to:

    - -
      -
    • Use a generic default icon. In this application, it might be something -that represents Shakespeare.
    • -
    • Create a res/drawable-de/ folder that includes an icon that -the application will use whenever the language is set to German but the location -is not Germany.
    • -
    - - -

    Localize the Application

    - -

    Localize the Strings

    - -

    The application requires three more strings.xml files, one -each for German, French, and Japanese. To create these resource files within -Eclipse:

    - -
      -
    1. Select File > New > Android -XML File to open the New Android XML File wizard. You can also open -the wizard by clicking its icon in the toolbar:
      -
    2. -
    3. Select L10N for the Project field, and type strings.xml into -the File field. In the left-hand list, select Language, then click the right arrow.
      -res_file_copy
    4. -
    5. Type de in the Language box and click Finish.
      - res_file_copy -

      A new file, res/values-de/strings.xml, now appears among the project -files.

    6. -
    7. Repeat the steps twice more, for the language codes fr and - ja. -Now the project includes these new skeleton files:
      - res/values-de/strings.xml
      - res/values-fr/strings.xml
      - res/values-ja/strings.xml
      -
    8. -
    9. Add localized text to the new files. To do -this, open the res/values-<qualifier>/strings.xml files and -replace the code as follows:
    10. -
    - - - - - - - - - - - - - - - - - - -
    FileReplace the contents with the following code:
    res/values-de/strings.xml
    <?xml version="1.0" encoding="utf-8"?>
    -<resources>
    -    <string name="app_name">Hallo, Lokalisierung</string>
    -    <string name="text_a">Soll ich dich einem Sommertag vergleichen,</string>
    -    <string name="text_b">Der du viel lieblicher und sanfter bist?</string>
    -</resources>
    res/values-fr/strings.xml
    <?xml version="1.0" encoding="utf-8"?>
    -<resources>
    -    <string name="app_name">Bonjour, Localisation</string>
    -    <string name="text_a">Irai-je te comparer au jour d'été?</string>
    -    <string name="text_b">Tu es plus tendre et bien plus tempéré.</string>
    -</resources> 
    res/values-ja/strings.xml -
    <?xml version="1.0" encoding="utf-8"?>
    -<resources>
    -    <string name="text_a">あなたをなにかにたとえるとしたら夏の一日でしょうか?</string>
    -    <string name="text_b">だがあなたはもっと美しく、もっとおだやかです。</string>
    -</resources>
    - -

    Tip: In the -values-<qualifier>/strings.xml files, you only need to -include text for strings that are different from the default strings. For -example, when the application runs on a device that is configured for Japanese, -the plan is for text_a and text_b to be in Japanese -while all the other text is in English, so -res/values-ja/strings.xml only needs to include text_a -and text_b.

    - -

    Localize the Images

    - -

    As shown in Table 2, the application needs six more -drawable folders, each containing a flag.png icon. Add the needed -icons and folders to your project:

    - -
      -
    1. Save this German flag icon -as res/drawable-de-rDE/flag.png in the application's project -workspace. -

      For example:

      -
        -
      1. Click the link to open the flag image.
      2. -
      3. Save the image in -your-workspace/HelloL10N/res/drawable-de-rDE/ .
      4. -
      -
    2. -
    3. Save this French flag icon -as res/drawable-fr-rFR/flag.png in the application's project -workspace.
    4. -
    5. Save this Canadian flag icon -as res/drawable-fr-rCA/flag.png in the project workspace.
    6. -
    7. Save the Canadian flag icon -again, this time as res/drawable-en-rCA/flag.png in the project -workspace. (Why not have just one folder that contains the Canadian -flag? Because a folder qualifer cannot specify a region without a language. -You cannot have a folder named drawable-rCA/; instead you must -create two separate folders, one for each of the Canadian languages represented -in the application.)
    8. -
    9. Save this Japanese flag icon -as res/drawable-ja-rJP/flag.png in the project workspace.
    10. -
    11. Save this United States flag -icon as res/drawable-en-rUS/flag.png in the project workspace. -
    12. -
    - -

    If you are using Eclipse, refresh the project (F5). The new -res/drawable-<qualifier>/ folders should appear in the -project view.

    - - -

    Run and Test the Localized Application

    - -

    Once you've added the localized string and image resources, you are ready to - run the application and test its handling of them. To change the locale - on a device or in the emulator, use the Settings -application (Home > Menu > Settings > Locale & text > Select -locale). Depending on how a device was configured, it might not offer any -alternate locales via the Settings application, or might offer only a few. The -emulator, on the other hand, will offer a selection of all the locales that are -available in the Android system image.

    - -

    To set the emulator to a locale that is not available in the system image, -use the Custom Locale application, which is available in the Application -tab:

    - -

    custom locale app

    - -

    To switch to a new locale, long-press a locale name:

    - -

    using custom locale

    - -

    For a list of locales available on different versions of the Android platform, -refer to the platform notes documents, listed under "Downloadable SDK Components" -in the "SDK" tab. For example, Android 2.0 locales.

    - -

    Run the application for each of the expected locales, plus one unexpected -locale. Here are some of the results you should see:

    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    LocaleOpening screen of application
    German / Germany -
    Specifically supported by the Hello, L10N application.
    custom locale app
    French / Canada -
    Specifically supported by the Hello, L10N application.
    custom locale app
    German / Switzerland -
    Only the language is specifically supported by -the Hello, L10N application.
    custom locale app`
    Japanese -
    Specifically supported by the Hello, L10N application. -
    custom locale app`
    Romansh / Switzerland (custom locale rm_CH) -
    Not specifically supported by the Hello, L10N -application, so the application uses the default resources.
    custom locale app
    diff --git a/docs/html/resources/tutorials/notepad/index.jd b/docs/html/resources/tutorials/notepad/index.jd index dd9218451a0c185d26d7f5ceb51353559cd6840b..1f37c410a55adb7b97e4db4bec565cb051cc34a7 100644 --- a/docs/html/resources/tutorials/notepad/index.jd +++ b/docs/html/resources/tutorials/notepad/index.jd @@ -44,11 +44,11 @@ steps in your environment.

    The tutorial assumes that you have some familiarity with basic Android application concepts and terminology. If you are not, you -should read Application +should read Application Fundamentals before continuing.

    This tutorial also builds on the introductory information provided in the -Hello World +Building Your First App tutorial, which explains how to set up your Eclipse environment for building Android applications. We recommend you complete the Hello World tutorial before starting this one.

    diff --git a/docs/html/resources/tutorials/notepad/notepad-ex1.jd b/docs/html/resources/tutorials/notepad/notepad-ex1.jd index cf7765e1693a8035ad8b1b2f89fee7dd673f8ad3..13ab0a6ac33137d16d1f3f6a3608df6a6b7f115b 100644 --- a/docs/html/resources/tutorials/notepad/notepad-ex1.jd +++ b/docs/html/resources/tutorials/notepad/notepad-ex1.jd @@ -33,7 +33,7 @@ selections.

    Notepadv1 is a project that is provided as a starting point. It takes care of some of the boilerplate work that you have already seen if you - followed the Hello, + followed the Hello, World tutorial.

      diff --git a/docs/html/resources/tutorials/notepad/notepad-ex3.jd b/docs/html/resources/tutorials/notepad/notepad-ex3.jd index 557738e4c105b9c6c1ef2c5d02358f1980f6a297..e31ecda2e20b871197963696d51180cdd4c2d975 100644 --- a/docs/html/resources/tutorials/notepad/notepad-ex3.jd +++ b/docs/html/resources/tutorials/notepad/notepad-ex3.jd @@ -204,7 +204,7 @@ and populate the View elements with them.

      state it was in when it was killed.

      Activities have a well-defined life +href="{@docRoot}guide/components/activities.html#Lifecycle">well-defined life cycle. Lifecycle events can happen even if you are not handing off control to another Activity explicitly. For example, perhaps a call comes in to the diff --git a/docs/html/resources/tutorials/notepad/notepad-extra-credit.jd b/docs/html/resources/tutorials/notepad/notepad-extra-credit.jd index 0d59b56b7a7b44fc2addd7d4d74c8f5ca0d326e4..d5fd7716d2621a6fbe40dd51d398307d4c7614a3 100644 --- a/docs/html/resources/tutorials/notepad/notepad-extra-credit.jd +++ b/docs/html/resources/tutorials/notepad/notepad-extra-credit.jd @@ -65,6 +65,6 @@ when.

      The Android Eclipse plugin not only offers excellent debugging support for your application development, but also superb profiling support. You can also -try using Traceview to profile your application. If your application is running too slow, this can help you +try using Traceview to profile your application. If your application is running too slow, this can help you find the bottlenecks and fix them.

      diff --git a/docs/html/resources/tutorials/opengl/opengl-es10.jd b/docs/html/resources/tutorials/opengl/opengl-es10.jd deleted file mode 100644 index 2b446205921704a9a3d0cee0570627d96bff76c1..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/opengl/opengl-es10.jd +++ /dev/null @@ -1,532 +0,0 @@ -page.title=OpenGL ES 1.0 -parent.title=Tutorials -parent.link=../../browser.html?tag=tutorial -@jd:body - - - - -

      This tutorial shows you how to create a simple Android application that uses the OpenGL ES 1.0 -API to perform some basic graphics operations. You'll learn how to:

      - -
        -
      • Create an activity using {@link android.opengl.GLSurfaceView} and {@link -android.opengl.GLSurfaceView.Renderer}
      • -
      • Create and draw a graphic object
      • -
      • Define a projection to correct for screen geometry
      • -
      • Define a camera view
      • -
      • Rotate a graphic object
      • -
      • Make graphics touch-interactive
      • -
      - -

      The Android framework supports both the OpenGL ES 1.0/1.1 and OpenGL ES 2.0 APIs. You should -carefully consider which version of the OpenGL ES API (1.0/1.1 or 2.0) is most appropriate for your -needs. For more information, see -Choosing an OpenGL API -Version. If you would prefer to use OpenGL ES 2.0, see the OpenGL ES 2.0 tutorial.

      - -

      Before you start, you should understand how to create a basic Android application. If you do not -know how to create an app, follow the Hello -World Tutorial to familiarize yourself with the process.

      - -

      Create an Activity with GLSurfaceView

      - -

      To get started using OpenGL, you must implement both a {@link android.opengl.GLSurfaceView} and a -{@link android.opengl.GLSurfaceView.Renderer}. The {@link android.opengl.GLSurfaceView} is the main -view type for applications that use OpenGL and the {@link android.opengl.GLSurfaceView.Renderer} -controls what is drawn within that view. (For more information about these classes, see the 3D with OpenGL document.)

      - -

      To create an activity using {@code GLSurfaceView}:

      - -
        -
      1. Start a new Android project that targets Android 1.6 (API Level 4) or higher. -
      2. -
      3. Name the project HelloOpenGLES10 and make sure it includes an activity called -{@code HelloOpenGLES10}. -
      4. -
      5. Modify the {@code HelloOpenGLES10} class as follows: -
        -package com.example.android.apis.graphics;
        -
        -import android.app.Activity;
        -import android.content.Context;
        -import android.opengl.GLSurfaceView;
        -import android.os.Bundle;
        -
        -public class HelloOpenGLES10 extends Activity {
        -  
        -    private GLSurfaceView mGLView;
        -  
        -    @Override
        -    public void onCreate(Bundle savedInstanceState) {
        -        super.onCreate(savedInstanceState);
        -        
        -        // Create a GLSurfaceView instance and set it
        -        // as the ContentView for this Activity.
        -        mGLView = new HelloOpenGLES10SurfaceView(this);
        -        setContentView(mGLView);
        -    }
        -    
        -    @Override
        -    protected void onPause() {
        -        super.onPause();
        -        // The following call pauses the rendering thread.
        -        // If your OpenGL application is memory intensive,
        -        // you should consider de-allocating objects that
        -        // consume significant memory here.
        -        mGLView.onPause();
        -    }
        -    
        -    @Override
        -    protected void onResume() {
        -        super.onResume();
        -        // The following call resumes a paused rendering thread.
        -        // If you de-allocated graphic objects for onPause()
        -        // this is a good place to re-allocate them.
        -        mGLView.onResume();
        -    }
        -}
        -  
        -class HelloOpenGLES10SurfaceView extends GLSurfaceView {
        -
        -    public HelloOpenGLES10SurfaceView(Context context){
        -        super(context);
        -        
        -        // Set the Renderer for drawing on the GLSurfaceView
        -        setRenderer(new HelloOpenGLES10Renderer());
        -    }
        -}
        -
        -

        Note: You will get a compile error for the {@code -HelloOpenGLES10Renderer} class reference. That's expected; you will fix this error in the next step. -

        - -

        As shown above, this activity uses a single {@link android.opengl.GLSurfaceView} for its -view. Notice that this activity implements crucial lifecycle callbacks for pausing and resuming its -work.

        - -

        The {@code HelloOpenGLES10SurfaceView} class in this example code above is just a thin wrapper -for an instance of {@link android.opengl.GLSurfaceView} and is not strictly necessary for this -example. However, if you want your application to monitor and respond to touch screen -events—and we are guessing you do—you must extend {@link android.opengl.GLSurfaceView} -to add touch event listeners, which you will learn how to do in the Reponding to -Touch Events section.

        - -

        In order to draw graphics in the {@link android.opengl.GLSurfaceView}, you must define an -implementation of {@link android.opengl.GLSurfaceView.Renderer}. In the next step, you create -a renderer class to complete this OpenGL application.

        -
      6. - -
      7. Create a new file for the following class {@code HelloOpenGLES10Renderer}, which implements -the {@link android.opengl.GLSurfaceView.Renderer} interface: - -
        -package com.example.android.apis.graphics;
        -
        -import javax.microedition.khronos.egl.EGLConfig;
        -import javax.microedition.khronos.opengles.GL10;
        -
        -import android.opengl.GLSurfaceView;
        -
        -public class HelloOpenGLES10Renderer implements GLSurfaceView.Renderer {
        -
        -    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        -        // Set the background frame color
        -        gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        -    }
        -    
        -    public void onDrawFrame(GL10 gl) {
        -        // Redraw background color
        -        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        -    }
        -    
        -    public void onSurfaceChanged(GL10 gl, int width, int height) {
        -        gl.glViewport(0, 0, width, height);
        -    }
        -  
        -}
        -
        -

        This minimal implementation of {@link android.opengl.GLSurfaceView.Renderer} provides the -code structure needed to use OpenGL drawing methods: -

          -
        • {@link - android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(javax.microedition.khronos.opengles.GL10, - javax.microedition.khronos.egl.EGLConfig) onSurfaceCreated()} is called once to set up the -{@link android.opengl.GLSurfaceView} -environment.
        • -
        • {@link - android.opengl.GLSurfaceView.Renderer#onDrawFrame(javax.microedition.khronos.opengles.GL10) - onDrawFrame()} is called for each redraw of the {@link -android.opengl.GLSurfaceView}.
        • -
        • {@link - android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(javax.microedition.khronos.opengles.GL10, - int, int) onSurfaceChanged()} is called if the geometry of the {@link -android.opengl.GLSurfaceView} changes, for example when the device's screen orientation -changes.
        • -
        -

        -

        For more information about these methods, see the 3D with OpenGL document. -

        -
      8. -
      - -

      The code example above creates a simple Android application that displays a grey screen using -OpenGL ES 1.0 calls. While this application does not do anything very interesting, by creating these -classes, you have layed the foundation needed to start drawing graphic elements with OpenGL ES -1.0.

      - -

      If you are familiar with the OpenGL ES APIs, these classes should give you enough information -to use the OpenGL ES 1.0 API and create graphics. However, if you need a bit more help getting -started with OpenGL, head on to the next sections for a few more hints.

      - -

      Draw a Shape on GLSurfaceView

      - -

      Once you have implemented a {@link android.opengl.GLSurfaceView.Renderer}, the next step is to -draw something with it. This section shows you how to define and draw a triangle.

      - -

      Define a Triangle

      - -

      OpenGL allows you to define objects using coordinates in three-dimensional space. So, before you - can draw a triangle, you must define its coordinates. In OpenGL, the typical way to do this is to - define a vertex array for the coordinates.

      - -

      By default, OpenGL ES assumes a coordinate system where [0,0,0] (X,Y,Z) specifies the center of - the {@link android.opengl.GLSurfaceView} frame, [1,1,0] is the top right corner of the frame and -[-1,-1,0] is bottom left corner of the frame.

      - -

      To define a vertex array for a triangle:

      - -
        -
      1. In your {@code HelloOpenGLES10Renderer} class, add new member variable to contain the -vertices of a triangle shape: -
        -    private FloatBuffer triangleVB;
        -
        -
      2. - -
      3. Create a method, {@code initShapes()} which populates this member variable: -
        -    private void initShapes(){
        -    
        -        float triangleCoords[] = {
        -            // X, Y, Z
        -            -0.5f, -0.25f, 0,
        -             0.5f, -0.25f, 0,
        -             0.0f,  0.559016994f, 0
        -        }; 
        -        
        -        // initialize vertex Buffer for triangle  
        -        ByteBuffer vbb = ByteBuffer.allocateDirect(
        -                // (# of coordinate values * 4 bytes per float)
        -                triangleCoords.length * 4); 
        -        vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order
        -        triangleVB = vbb.asFloatBuffer();  // create a floating point buffer from the ByteBuffer
        -        triangleVB.put(triangleCoords);    // add the coordinates to the FloatBuffer
        -        triangleVB.position(0);            // set the buffer to read the first coordinate
        -    
        -    }
        -
        -

        This method defines a two-dimensional triangle with three equal sides.

        -
      4. -
      5. Modify your {@code onSurfaceCreated()} method to initialize your triangle: -
        -    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        -    
        -        // Set the background frame color
        -        gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        -        
        -        // initialize the triangle vertex array
        -        initShapes();
        -    }
        -
        -

        Caution: Shapes and other static objects should be initialized - once in your {@code onSurfaceCreated()} method for best performance. Avoid initializing the - new objects in {@code onDrawFrame()}, as this causes the system to re-create the objects - for every frame redraw and slows down your application. -

        -
      6. - -
      - -

      You have now defined a triangle shape, but if you run the application, nothing appears. What?! -You also have to tell OpenGL to draw the triangle, which you'll do in the next section. -

      - - -

      Draw the Triangle

      - -

      Before you can draw your triangle, you must tell OpenGL that you are using vertex arrays. After -that setup step, you can call the drawing APIs to display the triangle.

      - -

      To draw the triangle:

      - -
        -
      1. Add the {@code glEnableClientState()} method to the end of {@code onSurfaceCreated()} to -enable vertex arrays. -
        -        // Enable use of vertex arrays
        -        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        -
        -

        At this point, you are ready to draw the triangle object in the OpenGL view.

        -
      2. - -
      3. Add the following code to the end of your {@code onDrawFrame()} method to draw the triangle. -
        -        // Draw the triangle
        -        gl.glColor4f(0.63671875f, 0.76953125f, 0.22265625f, 0.0f);
        -        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleVB);
        -        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
        -
        -
      4. -
      5. Run the app! Your application should look something like this: -
      6. -
      - - -

      - Figure 1. Triangle drawn without a projection or camera view. -

      - -

      There are a few problems with this example. First of all, it is not going to impress your -friends. Secondly, the triangle is a bit squashed and changes shape when you change the screen -orientation of the device. The reason the shape is skewed is due to the fact that the object is -being rendered in a frame which is not perfectly square. You'll fix that problem using a projection -and camera view in the next section.

      - -

      Lastly, because the triangle is stationary, the system is redrawing the object repeatedly in -exactly the same place, which is not the most efficient use of the OpenGL graphics pipeline. In the -Add Motion section, you'll make this shape rotate and justify -this use of processing power.

      - -

      Apply Projection and Camera View

      - -

      One of the basic problems in displaying graphics is that Android device displays are typically -not square and, by default, OpenGL happily maps a perfectly square, uniform coordinate -system onto your typically non-square screen. To solve this problem, you can apply an OpenGL -projection mode and camera view (eye point) to transform the coordinates of your graphic objects -so they have the correct proportions on any display. For more information about OpenGL coordinate -mapping, see Mapping -Coordinates for Drawn Objects.

      - -

      To apply projection and camera view transformations to your triangle: -

      -
        -
      1. Modify your {@code onSurfaceChanged()} method to enable {@link - javax.microedition.khronos.opengles.GL10#GL_PROJECTION GL10.GL_PROJECTION} mode, calculate the - screen ratio and apply the ratio as a transformation of the object coordinates. -
        -  public void onSurfaceChanged(GL10 gl, int width, int height) {
        -      gl.glViewport(0, 0, width, height);
        -      
        -      // make adjustments for screen ratio
        -      float ratio = (float) width / height;
        -      gl.glMatrixMode(GL10.GL_PROJECTION);        // set matrix to projection mode
        -      gl.glLoadIdentity();                        // reset the matrix to its default state
        -      gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);  // apply the projection matrix
        -  }  
        -
        -
      2. - -
      3. Next, modify your {@code onDrawFrame()} method to apply the {@link -javax.microedition.khronos.opengles.GL10#GL_MODELVIEW GL_MODELVIEW} mode and set -a view point using {@link android.opengl.GLU#gluLookAt(javax.microedition.khronos.opengles.GL10, -float, float, float, float, float, float, float, float, float) GLU.gluLookAt()}. -
        -    public void onDrawFrame(GL10 gl) {
        -        // Redraw background color
        -        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        -        
        -        // Set GL_MODELVIEW transformation mode
        -        gl.glMatrixMode(GL10.GL_MODELVIEW);
        -        gl.glLoadIdentity();   // reset the matrix to its default state
        -        
        -        // When using GL_MODELVIEW, you must set the view point
        -        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);        
        -        
        -        // Draw the triangle
        -        ...
        -    }
        -
        -
      4. -
      5. Run the updated application and you should see something like this:
      6. -
      - - -

      - Figure 2. Triangle drawn with a projection and camera view applied. -

      - -

      Now that you have applied this transformation, the triangle has three equal sides, instead of the -squashed triangle in the earlier version.

      - -

      Add Motion

      - -

      While it may be an interesting exercise to create static graphic objects with OpenGL ES, chances -are you want at least some of your objects to move. In this section, you'll add motion to -your triangle by rotating it.

      - -

      To add rotation to your triangle:

      -
        -
      1. Modify your {@code onDrawFrame()} method to rotate the triangle object: -
        -    public void onDrawFrame(GL10 gl) {
        -        ...    
        -        // When using GL_MODELVIEW, you must set the view point
        -        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);        
        -    
        -        // Create a rotation for the triangle
        -        long time = SystemClock.uptimeMillis() % 4000L;
        -        float angle = 0.090f * ((int) time);
        -        gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);        
        -        
        -        // Draw the triangle
        -        ...
        -    }
        -
        -
      2. -
      3. Run the application and your triangle should rotate around its center.
      4. -
      - - -

      Respond to Touch Events

      -

      Making objects move according to a preset program like the rotating triangle is useful for -getting some attention, but what if you want to have users interact with your OpenGL graphics? In -this section, you'll learn how listen for touch events to let users interact with objects in your -{@code HelloOpenGLES10SurfaceView}.

      - -

      The key to making your OpenGL application touch interactive is expanding your implementation of -{@link android.opengl.GLSurfaceView} to override the {@link -android.view.View#onTouchEvent(android.view.MotionEvent) onTouchEvent()} to listen for touch events. -Before you do that, however, you'll modify the renderer class to expose the rotation angle of the -triangle. Afterwards, you'll modify the {@code HelloOpenGLES10SurfaceView} to process touch events -and pass that data to your renderer.

      - -

      To make your triangle rotate in response to touch events:

      - -
        -
      1. Modify your {@code HelloOpenGLES10Renderer} class to include a new, public member so that -your {@code HelloOpenGLES10SurfaceView} class is able to pass new rotation values your renderer: -
        -    public float mAngle;
        -
        -
      2. -
      3. In your {@code onDrawFrame()} method, comment out the code that generates an angle and -replace the {@code angle} variable with {@code mAngle}. -
        -        // Create a rotation for the triangle (Boring! Comment this out:)
        -        // long time = SystemClock.uptimeMillis() % 4000L;
        -        // float angle = 0.090f * ((int) time);
        -
        -        // Use the mAngle member as the rotation value
        -        gl.glRotatef(mAngle, 0.0f, 0.0f, 1.0f); 
        -
        -
      4. -
      5. In your {@code HelloOpenGLES10SurfaceView} class, add the following member variables. -
        -    private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
        -    private HelloOpenGLES10Renderer mRenderer;
        -    private float mPreviousX;
        -    private float mPreviousY;
        -
        -
      6. -
      7. In the constructor method for {@code HelloOpenGLES10SurfaceView}, set the {@code mRenderer} -member so you have a handle to pass in rotation input and set the render mode to {@link -android.opengl.GLSurfaceView#RENDERMODE_WHEN_DIRTY}. -
        -    public HelloOpenGLES10SurfaceView(Context context){
        -        super(context);
        -        // set the mRenderer member
        -        mRenderer = new HelloOpenGLES10Renderer();
        -        setRenderer(mRenderer);
        -        
        -        // Render the view only when there is a change
        -        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        -    }
        -
        -
      8. -
      9. In your {@code HelloOpenGLES10SurfaceView} class, override the {@link -android.view.View#onTouchEvent(android.view.MotionEvent) onTouchEvent()} method to listen for touch -events and pass them to your renderer. -
        -    @Override 
        -    public boolean onTouchEvent(MotionEvent e) {
        -        // MotionEvent reports input details from the touch screen
        -        // and other input controls. In this case, you are only
        -        // interested in events where the touch position changed.
        -
        -        float x = e.getX();
        -        float y = e.getY();
        -        
        -        switch (e.getAction()) {
        -            case MotionEvent.ACTION_MOVE:
        -    
        -                float dx = x - mPreviousX;
        -                float dy = y - mPreviousY;
        -    
        -                // reverse direction of rotation above the mid-line
        -                if (y > getHeight() / 2) {
        -                  dx = dx * -1 ;
        -                }
        -    
        -                // reverse direction of rotation to left of the mid-line
        -                if (x < getWidth() / 2) {
        -                  dy = dy * -1 ;
        -                }
        -              
        -                mRenderer.mAngle += (dx + dy) * TOUCH_SCALE_FACTOR;
        -                requestRender();
        -        }
        -
        -        mPreviousX = x;
        -        mPreviousY = y;
        -        return true;
        -    } 
        -
        -

        Note: Touch events return pixel coordinates which are not the -same as OpenGL coordinates. Touch coordinate [0,0] is the bottom-left of the screen and the -highest value [max_X, max_Y] is the top-right corner of the screen. To match touch events to OpenGL -graphic objects, you must translate touch coordinates into OpenGL coordinates.

        -
      10. -
      11. Run the application and drag your finger or cursor around the screen to rotate the -triangle.
      12. -
      -

      For another example of OpenGL touch event functionality, see TouchRotateActivity.

      \ No newline at end of file diff --git a/docs/html/resources/tutorials/opengl/opengl-es20.jd b/docs/html/resources/tutorials/opengl/opengl-es20.jd deleted file mode 100644 index dd23dbf2051cbcf9a44a9592920b1f7bcc41b35f..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/opengl/opengl-es20.jd +++ /dev/null @@ -1,652 +0,0 @@ -page.title=OpenGL ES 2.0 -parent.title=Tutorials -parent.link=../../browser.html?tag=tutorial -@jd:body - - - - -

      This tutorial shows you how to create a simple Android application that uses the OpenGL ES 2.0 -API to perform some basic graphics operations. You'll learn how to:

      - -
        -
      • Create an activity using {@link android.opengl.GLSurfaceView} and {@link -android.opengl.GLSurfaceView.Renderer}
      • -
      • Create and draw a graphic object
      • -
      • Define a projection to correct for screen geometry
      • -
      • Define a camera view
      • -
      • Rotate a graphic object
      • -
      • Make graphics touch interactive
      • -
      - -

      The Android framework supports both the OpenGL ES 1.0/1.1 and OpenGL ES 2.0 APIs. You should -carefully consider which version of the OpenGL ES API (1.0/1.1 or 2.0) is most appropriate for your -needs. For more information, see -Choosing an OpenGL API -Version. If you would prefer to use OpenGL ES 1.0, see the OpenGL ES 1.0 tutorial.

      - -

      Before you start, you should understand how to create a basic Android application. If you do not -know how to create an app, follow the Hello -World Tutorial to familiarize yourself with the process.

      - -

      Caution: OpenGL ES 2.0 is currently not supported by -the Android Emulator. You must have a physical test device running Android 2.2 (API Level 8) or -higher in order to run and test the example code in this tutorial.

      - -

      Create an Activity with GLSurfaceView

      - -

      To get started using OpenGL, you must implement both a {@link android.opengl.GLSurfaceView} and a -{@link android.opengl.GLSurfaceView.Renderer}. The {@link android.opengl.GLSurfaceView} is the main -view type for applications that use OpenGL and the {@link android.opengl.GLSurfaceView.Renderer} -controls what is drawn within that view. (For more information about these classes, see the 3D with OpenGL document.)

      - -

      To create an activity using {@code GLSurfaceView}:

      - -
        -
      1. Start a new Android project that targets Android 2.2 (API Level 8) or higher. -
      2. -
      3. Name the project HelloOpenGLES20 and make sure it includes an activity called -{@code HelloOpenGLES20}. -
      4. -
      5. Modify the {@code HelloOpenGLES20} class as follows: -
        -package com.example.android.apis.graphics;
        -
        -import android.app.Activity;
        -import android.content.Context;
        -import android.opengl.GLSurfaceView;
        -import android.os.Bundle;
        -
        -public class HelloOpenGLES20 extends Activity {
        -  
        -    private GLSurfaceView mGLView;
        -  
        -    @Override
        -    public void onCreate(Bundle savedInstanceState) {
        -        super.onCreate(savedInstanceState);
        -        
        -        // Create a GLSurfaceView instance and set it
        -        // as the ContentView for this Activity
        -        mGLView = new HelloOpenGLES20SurfaceView(this);
        -        setContentView(mGLView);
        -    }
        -    
        -    @Override
        -    protected void onPause() {
        -        super.onPause();
        -        // The following call pauses the rendering thread.
        -        // If your OpenGL application is memory intensive,
        -        // you should consider de-allocating objects that
        -        // consume significant memory here.
        -        mGLView.onPause();
        -    }
        -    
        -    @Override
        -    protected void onResume() {
        -        super.onResume();
        -        // The following call resumes a paused rendering thread.
        -        // If you de-allocated graphic objects for onPause()
        -        // this is a good place to re-allocate them.
        -        mGLView.onResume();
        -    }
        -}
        -  
        -class HelloOpenGLES20SurfaceView extends GLSurfaceView {
        -
        -    public HelloOpenGLES20SurfaceView(Context context){
        -        super(context);
        -        
        -        // Create an OpenGL ES 2.0 context.
        -        setEGLContextClientVersion(2);
        -        // Set the Renderer for drawing on the GLSurfaceView
        -        setRenderer(new HelloOpenGLES20Renderer());
        -    }
        -}
        -
        -

        Note: You will get a compile error for the {@code -HelloOpenGLES20Renderer} class reference. That's expected; you will fix this error in the next step. -

        - -

        As shown above, this activity uses a single {@link android.opengl.GLSurfaceView} for its -view. Notice that this activity implements crucial lifecycle callbacks for pausing and resuming its -work.

        - -

        The {@code HelloOpenGLES20SurfaceView} class in this example code above is just a thin wrapper -for an instance of {@link android.opengl.GLSurfaceView} and is not strictly necessary for this -example. However, if you want your application to monitor and respond to touch screen -events—and we are guessing you do—you must extend {@link android.opengl.GLSurfaceView} -to add touch event listeners, which you will learn how to do in the Reponding to -Touch Events section.

        - -

        In order to draw graphics in the {@link android.opengl.GLSurfaceView}, you must define an -implementation of {@link android.opengl.GLSurfaceView.Renderer}. In the next step, you create -a renderer class to complete this OpenGL application.

        -
      6. - -
      7. Create a new file for the following class {@code HelloOpenGLES20Renderer}, which implements -the {@link android.opengl.GLSurfaceView.Renderer} interface: - -
        -package com.example.android.apis.graphics;
        -
        -import javax.microedition.khronos.egl.EGLConfig;
        -import javax.microedition.khronos.opengles.GL10;
        -
        -import android.opengl.GLES20;
        -import android.opengl.GLSurfaceView;
        -
        -public class HelloOpenGLES20Renderer implements GLSurfaceView.Renderer {
        -  
        -    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        -    
        -        // Set the background frame color
        -        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        -    }
        -    
        -    public void onDrawFrame(GL10 unused) {
        -    
        -        // Redraw background color
        -        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        -    }
        -    
        -    public void onSurfaceChanged(GL10 unused, int width, int height) {
        -        GLES20.glViewport(0, 0, width, height);
        -    }
        -  
        -}
        -
        -

        This minimal implementation of {@link android.opengl.GLSurfaceView.Renderer} provides the -code structure needed to use OpenGL drawing methods: -

          -
        • {@link - android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(javax.microedition.khronos.opengles.GL10, - javax.microedition.khronos.egl.EGLConfig) onSurfaceCreated()} is called once to set up the -{@link android.opengl.GLSurfaceView} -environment.
        • -
        • {@link - android.opengl.GLSurfaceView.Renderer#onDrawFrame(javax.microedition.khronos.opengles.GL10) - onDrawFrame()} is called for each redraw of the {@link -android.opengl.GLSurfaceView}.
        • -
        • {@link - android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(javax.microedition.khronos.opengles.GL10, - int, int) onSurfaceChanged()} is called if the geometry of the {@link -android.opengl.GLSurfaceView} changes, for example when the device's screen orientation -changes.
        • -
        -

        -

        For more information about these methods, see the 3D with OpenGL document. -

        -
      8. -
      - -

      The code example above creates a simple Android application that displays a grey screen using -OpenGL ES 2.0 calls. While this application does not do anything very interesting, by creating these -classes, you have layed the foundation needed to start drawing graphic elements with OpenGL ES -2.0.

      - -

      If you are familiar with the OpenGL ES APIs, these classes should give you enough information -to use the OpenGL ES 2.0 API and create graphics. However, if you need a bit more help getting -started with OpenGL, head on to the next sections for a few more hints.

      - -

      Note: If your application requires OpenGL 2.0, make sure you -declare this in your manifest:

      -
      -    <!-- Tell the system this app requires OpenGL ES 2.0. -->
      -    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
      -
      -

      For more information, see OpenGL manifest declarations in the -3D with OpenGL document.

      - - -

      Draw a Shape on GLSurfaceView

      - -

      Once you have implemented a {@link android.opengl.GLSurfaceView.Renderer}, the next step is to -draw something with it. This section shows you how to define and draw a triangle.

      - -

      Define a Triangle

      - -

      OpenGL allows you to define objects using coordinates in three-dimensional space. So, before you - can draw a triangle, you must define its coordinates. In OpenGL, the typical way to do this is to - define a vertex array for the coordinates.

      - -

      By default, OpenGL ES assumes a coordinate system where [0,0,0] (X,Y,Z) specifies the center of - the {@link android.opengl.GLSurfaceView} frame, [1,1,0] is the top-right corner of the frame and -[-1,-1,0] is bottom-left corner of the frame.

      - -

      To define a vertex array for a triangle:

      - -
        -
      1. In your {@code HelloOpenGLES20Renderer} class, add new member variable to contain the -vertices of a triangle shape: -
        -    private FloatBuffer triangleVB;
        -
        -
      2. - -
      3. Create a method, {@code initShapes()} which populates this member variable: -
        -    private void initShapes(){
        -    
        -        float triangleCoords[] = {
        -            // X, Y, Z
        -            -0.5f, -0.25f, 0,
        -             0.5f, -0.25f, 0,
        -             0.0f,  0.559016994f, 0
        -        }; 
        -        
        -        // initialize vertex Buffer for triangle  
        -        ByteBuffer vbb = ByteBuffer.allocateDirect(
        -                // (# of coordinate values * 4 bytes per float)
        -                triangleCoords.length * 4); 
        -        vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order
        -        triangleVB = vbb.asFloatBuffer();  // create a floating point buffer from the ByteBuffer
        -        triangleVB.put(triangleCoords);    // add the coordinates to the FloatBuffer
        -        triangleVB.position(0);            // set the buffer to read the first coordinate
        -    
        -    }
        -
        -

        This method defines a two-dimensional triangle shape with three equal sides.

        -
      4. -
      5. Modify your {@code onSurfaceCreated()} method to initialize your triangle: -
        -    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        -    
        -        // Set the background frame color
        -        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        -        
        -        // initialize the triangle vertex array
        -        initShapes();
        -    }
        -
        -

        Caution: Shapes and other static objects should be initialized - once in your {@code onSurfaceCreated()} method for best performance. Avoid initializing the - new objects in {@code onDrawFrame()}, as this causes the system to re-create the objects - for every frame redraw and slows down your application. -

        -
      6. - -
      - -

      You have now defined a triangle shape, but if you run the application, nothing appears. What?! -You also have to tell OpenGL to draw the triangle, which you'll do in the next section. -

      - - -

      Draw the Triangle

      - -

      The OpenGL ES 2.0 requires a bit more code than OpenGL ES 1.0/1.1 in order to draw objects. In -this section, you'll create vertex and fragment shaders, a shader loader, apply the shaders, enable -the use of vertex arrays for your triangle and, finally, draw it on screen.

      - -

      To draw the triangle:

      - -
        -
      1. In your {@code HelloOpenGLES20Renderer} class, define a vertex shader and a fragment -shader. Shader code is defined as a string which is compiled and run by the OpenGL ES 2.0 rendering -engine. -
        -    private final String vertexShaderCode = 
        -        "attribute vec4 vPosition; \n" +
        -        "void main(){              \n" +
        -        " gl_Position = vPosition; \n" +
        -        "}                         \n";
        -    
        -    private final String fragmentShaderCode = 
        -        "precision mediump float;  \n" +
        -        "void main(){              \n" +
        -        " gl_FragColor = vec4 (0.63671875, 0.76953125, 0.22265625, 1.0); \n" +
        -        "}                         \n";
        -
        -

        The vertex shader controls how OpenGL positions and draws the vertices of shapes in space. -The fragment shader controls what OpenGL draws between the vertices of shapes.

        -
      2. -
      3. In your {@code HelloOpenGLES20Renderer} class, create a method for loading the shaders. -
        -    private int loadShader(int type, String shaderCode){
        -    
        -        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
        -        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
        -        int shader = GLES20.glCreateShader(type); 
        -        
        -        // add the source code to the shader and compile it
        -        GLES20.glShaderSource(shader, shaderCode);
        -        GLES20.glCompileShader(shader);
        -        
        -        return shader;
        -    }
        -
        -
      4. - -
      5. Add the following members to your {@code HelloOpenGLES20Renderer} class for an OpenGL -Program and the positioning control for your triangle. -
        -    private int mProgram;
        -    private int maPositionHandle;
        -
        -

        In OpenGL ES 2.0, you attach vertex and fragment shaders to a Program and then -apply the program to the OpenGL graphics pipeline.

        -
      6. - -
      7. Add the following code to the end of your {@code onSurfaceCreated()} method to load the -shaders and attach them to an OpenGL Program. -
        -        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        -        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
        -        
        -        mProgram = GLES20.glCreateProgram();             // create empty OpenGL Program
        -        GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
        -        GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
        -        GLES20.glLinkProgram(mProgram);                  // creates OpenGL program executables
        -        
        -        // get handle to the vertex shader's vPosition member
        -        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        -
        -

        At this point, you are ready to draw the triangle object in the OpenGL view.

        -
      8. - -
      9. Add the following code to the end of your {@code onDrawFrame()} method apply the OpenGL -program you created, load the triangle object and draw the triangle. -
        -        // Add program to OpenGL environment
        -        GLES20.glUseProgram(mProgram);
        -        
        -        // Prepare the triangle data
        -        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 12, triangleVB);
        -        GLES20.glEnableVertexAttribArray(maPositionHandle);
        -        
        -        // Draw the triangle
        -        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
        -
        -
      10. -
      11. Run the app! Your application should look something like this: -
      12. -
      - - -

      - Figure 1. Triangle drawn without a projection or camera view. -

      - -

      There are a few problems with this example. First of all, it is not going to impress your -friends. Secondly, the triangle is a bit squashed and changes shape when you change the screen -orientation of the device. The reason the shape is skewed is due to the fact that the object is -being rendered in a frame which is not perfectly square. You'll fix that problem using a projection -and camera view in the next section.

      - -

      Lastly, because the triangle is stationary, the system is redrawing the object repeatedly in -exactly the same place, which is not the most efficient use of the OpenGL graphics pipeline. In the -Add Motion section, you'll make this shape rotate and justify -this use of processing power.

      - -

      Apply Projection and Camera View

      - -

      One of the basic problems in displaying graphics is that Android device displays are typically -not square and, by default, OpenGL happily maps a perfectly square, uniform coordinate -system onto your typically non-square screen. To solve this problem, you can apply an OpenGL -projection mode and camera view (eye point) to transform the coordinates of your graphic objects -so they have the correct proportions on any display. For more information about OpenGL coordinate -mapping, see Mapping -Coordinates for Drawn Objects.

      - -

      To apply projection and camera view transformations to your triangle: -

      -
        -
      1. Add the following members to your {@code HelloOpenGLES20Renderer} class. -
        -    private int muMVPMatrixHandle;
        -    private float[] mMVPMatrix = new float[16];
        -    private float[] mMMatrix = new float[16];
        -    private float[] mVMatrix = new float[16];
        -    private float[] mProjMatrix = new float[16];
        -
        -
      2. -
      3. Modify your {@code vertexShaderCode} string to add a variable for a model view -projection matrix. -
        -    private final String vertexShaderCode = 
        -        // This matrix member variable provides a hook to manipulate
        -        // the coordinates of the objects that use this vertex shader
        -        "uniform mat4 uMVPMatrix;   \n" +
        -        
        -        "attribute vec4 vPosition;  \n" +
        -        "void main(){               \n" +
        -        
        -        // the matrix must be included as a modifier of gl_Position
        -        " gl_Position = uMVPMatrix * vPosition; \n" +
        -        
        -        "}  \n";
        -
        -
      4. -
      5. Modify the {@code onSurfaceChanged()} method to calculate the device screen ratio and -create a projection matrix. -
        -    public void onSurfaceChanged(GL10 unused, int width, int height) {
        -        GLES20.glViewport(0, 0, width, height);
        -        
        -        float ratio = (float) width / height;
        -        
        -        // this projection matrix is applied to object coodinates
        -        // in the onDrawFrame() method
        -        Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
        -    }  
        -
        -
      6. -
      7. Add the following code to the end of your {@code onSurfaceChanged()} method to -reference the {@code uMVPMatrix} shader matrix variable you added in step 2. -
        -        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        -
        -
      8. -
      9. Add the following code to the end of your {@code onSurfaceChanged()} method to define -a camera view matrix. -
        -        Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        -
        -
      10. -
      11. Finally, modify your {@code onDrawFrame()} method to combine the projection and -camera view matrices and then apply the combined transformation to the OpenGL rendering pipeline. -
        -    public void onDrawFrame(GL10 unused) {
        -        ...
        -        // Apply a ModelView Projection transformation
        -        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
        -        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
        -        
        -        // Draw the triangle
        -        ...
        -    }
        -
        -
      12. -
      13. Run the updated application and you should see something like this:
      14. -
      - - -

      - Figure 2. Triangle drawn with a projection and camera view applied. -

      - -

      Now that you have applied this transformation, the triangle has three equal sides, instead of the -squashed triangle in the earlier version.

      - -

      Add Motion

      - -

      While it may be an interesting exercise to create static graphic objects with OpenGL ES, chances -are you want at least some of your objects to move. In this section, you'll add motion to -your triangle by rotating it.

      - -

      To add rotation to your triangle:

      -
        -
      1. Add an additional tranformation matrix member to your {@code HelloOpenGLES20Renderer} -class. -
        -      private float[] mMMatrix = new float[16];
        -    
        -
      2. -
      3. Modify your {@code onDrawFrame()} method to rotate the triangle object. -
        -    public void onDrawFrame(GL10 gl) {
        -        ...
        -    
        -        // Create a rotation for the triangle
        -        long time = SystemClock.uptimeMillis() % 4000L;
        -        float angle = 0.090f * ((int) time);
        -        Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f);
        -        Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
        -        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
        -        
        -        // Apply a ModelView Projection transformation
        -        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
        -        
        -        // Draw the triangle
        -        ...
        -    }
        -
        -
      4. -
      5. Run the application and your triangle should rotate around its center.
      6. -
      - - -

      Respond to Touch Events

      -

      Making objects move according to a preset program like the rotating triangle is useful for -getting some attention, but what if you want to have users interact with your OpenGL graphics? In -this section, you'll learn how listen for touch events to let users interact with objects in your -{@code HelloOpenGLES20SurfaceView}.

      - -

      The key to making your OpenGL application touch interactive is expanding your implementation of -{@link android.opengl.GLSurfaceView} to override the {@link -android.view.View#onTouchEvent(android.view.MotionEvent) onTouchEvent()} to listen for touch events. -Before you do that, however, you'll modify the renderer class to expose the rotation angle of the -triangle. Afterwards, you'll modify the {@code HelloOpenGLES20SurfaceView} to process touch events -and pass that data to your renderer.

      - -

      To make your triangle rotate in response to touch events:

      - -
        -
      1. Modify your {@code HelloOpenGLES20Renderer} class to include a new, public member so that -your {@code HelloOpenGLES10SurfaceView} class is able to pass new rotation values your renderer: -
        -    public float mAngle;
        -
        -
      2. -
      3. In your {@code onDrawFrame()} method, comment out the code that generates an angle and -replace the {@code angle} variable with {@code mAngle}. -
        -        // Create a rotation for the triangle (Boring! Comment this out:)
        -        // long time = SystemClock.uptimeMillis() % 4000L;
        -        // float angle = 0.090f * ((int) time);
        -
        -        // Use the mAngle member as the rotation value
        -        Matrix.setRotateM(mMMatrix, 0, mAngle, 0, 0, 1.0f);
        -
        -
      4. -
      5. In your {@code HelloOpenGLES20SurfaceView} class, add the following member variables. -
        -    private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
        -    private HelloOpenGLES20Renderer mRenderer;
        -    private float mPreviousX;
        -    private float mPreviousY;
        -
        -
      6. -
      7. In the constructor method for {@code HelloOpenGLES20SurfaceView}, set the {@code mRenderer} -member so you have a handle to pass in rotation input and set the render mode to {@link -android.opengl.GLSurfaceView#RENDERMODE_WHEN_DIRTY}.
        -    public HelloOpenGLES20SurfaceView(Context context){
        -        super(context);
        -        // Create an OpenGL ES 2.0 context.
        -        setEGLContextClientVersion(2);
        -            
        -        // set the mRenderer member
        -        mRenderer = new HelloOpenGLES20Renderer();
        -        setRenderer(mRenderer);
        -        
        -        // Render the view only when there is a change
        -        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        -    }
        -
        -
      8. -
      9. In your {@code HelloOpenGLES20SurfaceView} class, override the {@link -android.view.View#onTouchEvent(android.view.MotionEvent) onTouchEvent()} method to listen for touch -events and pass them to your renderer. -
        -    @Override 
        -    public boolean onTouchEvent(MotionEvent e) {
        -        // MotionEvent reports input details from the touch screen
        -        // and other input controls. In this case, you are only
        -        // interested in events where the touch position changed.
        -
        -        float x = e.getX();
        -        float y = e.getY();
        -        
        -        switch (e.getAction()) {
        -            case MotionEvent.ACTION_MOVE:
        -    
        -                float dx = x - mPreviousX;
        -                float dy = y - mPreviousY;
        -    
        -                // reverse direction of rotation above the mid-line
        -                if (y > getHeight() / 2) {
        -                  dx = dx * -1 ;
        -                }
        -    
        -                // reverse direction of rotation to left of the mid-line
        -                if (x < getWidth() / 2) {
        -                  dy = dy * -1 ;
        -                }
        -              
        -                mRenderer.mAngle += (dx + dy) * TOUCH_SCALE_FACTOR;
        -                requestRender();
        -        }
        -
        -        mPreviousX = x;
        -        mPreviousY = y;
        -        return true;
        -    } 
        -
        -

        Note: Touch events return pixel coordinates which are not the -same as OpenGL coordinates. Touch coordinate [0,0] is the bottom-left of the screen and the -highest value [max_X, max_Y] is the top-right corner of the screen. To match touch events to OpenGL -graphic objects, you must translate touch coordinates into OpenGL coordinates.

        -
      10. -
      11. Run the application and drag your finger or cursor around the screen to rotate the -triangle.
      12. -
      -

      For another example of OpenGL touch event functionality, see TouchRotateActivity.

      \ No newline at end of file diff --git a/docs/html/resources/tutorials/testing/helloandroid_test.jd b/docs/html/resources/tutorials/testing/helloandroid_test.jd deleted file mode 100644 index 4d949c86b0797cee348202f5e53dac9a22a7339c..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/testing/helloandroid_test.jd +++ /dev/null @@ -1,508 +0,0 @@ -page.title=Hello, Testing -parent.title=Tutorials -parent.link=../../browser.html?tag=tutorial -@jd:body -
      -
      -

      In this document

      -
        -
      1. - Creating the Test Project -
      2. -
      3. - Creating the Test Case Class -
          -
        1. - Adding the test case class file -
        2. -
        3. - Adding the test case constructor -
        4. -
        5. - Adding a setup method -
        6. -
        7. - Adding a preconditions test -
        8. -
        9. - Adding a unit test -
        10. -
        11. - The finished test case class -
        12. -
        -
      4. -
      5. - Running the Tests and Seeing the Results -
      6. -
      7. - Next Steps -
      8. -
      -

      Related Tutorials

      -
        -
      1. - Hello, World -
      2. -
      3. - Activity Testing -
      4. -
      -

      See Also

      -
        -
      1. - Testing Android Applications -
      2. -
      3. - {@link android.test.ActivityInstrumentationTestCase2} -
      4. -
      5. - {@link android.test.InstrumentationTestRunner} -
      6. -
      - -
      -
      -

      - Android offers a powerful but easy-to-use testing framework that is well integrated with the SDK tools. Because writing - tests is an important part of any development effort, this tutorial introduces the basics of testing and helps you get started testing quickly. - - To keep things simple, this tutorial builds on the Hello World tutorial, which you may have already completed. - It guides you through the process of setting up a test project, adding a test, and running the test against the Hello World application, all from inside the Eclipse environment. - Of course, when you are done with this tutorial, you will want to create a test project for your own app and add various types of tests to it. -

      -

      - If you'd like to read an overview of the test and instrumentation framework and the core test case classes available, look at - the Testing Android Applications topic. - If you prefer a more advanced testing tutorial, try the - Activity Testing tutorial. -

      -

      Prerequisites

      -

      - This tutorial and its code depend on the Hello World tutorial. If you haven't completed that tutorial already, - do so now. You will learn the fundamentals of Android application development, and you will - have an Android application that is ready to be tested. The tutorial guides you through the - setup of an Android test project using the ADT Plugin for Eclipse and other SDK tools. - You will need an SDK development platform that is version 1.5 - (API level 3) or higher. -

      -

      - If you aren't developing in Eclipse with ADT or you would like to run tests directly from the - command line, please see the topic Testing in Other IDEs - for instructions. -

      -

      Creating the Test Project

      -

      - In the Hello World tutorial you created Android application project called - HelloAndroid. A test of an Android application is also an Android - application, and you create it within an Eclipse project. The Eclipse with ADT - New Android Test Project dialog creates a new test project and the - framework of a new test application at the same time. -

      -

      - To create the test project and test application framework in Eclipse with ADT, follow these steps -

      -
        -
      1. - In Eclipse, select New > Project > Android > Android Test Project. -

        - - New Android Test Project menu - -

        -

        - The New Android Test Project dialog appears. -

        -
      2. -
      3. - Set the following values: -
          -
        • - Test Project Name: "HelloAndroidTest" -
        • -
        • - Test Target: Set "An existing Android project", click Browse, and then - select "HelloAndroid" from the list of projects. -
        • -
        • - Build Target: Set a target whose platform is Android 1.5 or above. -
        • -
        • - Application name: "HelloAndroidTest" -
        • -
        • - Package name: "com.example.helloandroid.test" -
        • -
        -

        - The dialog should now look like this: -

        - - New Android Test Project dialog with entries - -
      4. -
      5. - Click Finish. The new project appears in the Package Explorer. -
      6. -
      -

      Creating the Test Case Class

      -

      - You now have a test project HelloAndroidTest, and the basic structure of a test application - also called HelloAndroidTest. The basic structure includes all the files and directories you - need to build and run a test application, except for the class that contains - your tests (the test case class). -

      -

      - The next step is to define the test case class. In this tutorial, you define a test case class - that extends one of Android's test case classes designed for Activities. The class contains - definitions for four methods: -

      -
        -
      1. - HelloAndroidTest: This defines the constructor for the class. It is - required by the Android testing framework. -
      2. -
      3. - setUp(): This overrides the JUnit setUp() method. You use - it to initialize the environment before each test runs. -
      4. -
      5. - testPreconditions(): This defines a small test that ensures the Hello, Android - application starts up correctly. -
      6. -
      7. - testText(): This tests that what is displayed on the screen is the - same as what is contained in the application's string resources. It is an example of - a real unit test you would perform against an application's UI. -
      8. -
      -

      - The following sections contain the code for the test case class and its methods. -

      - -

      Adding the test case class file

      -

      - To add the Java file for the test case class, follow these steps -

      -
        -
      1. - In Eclipse, open the HelloAndroidTest project if it is not already open. -
      2. -
      3. - Within HelloAndroidTest, expand the src/ folder and - then find the package icon for com.example.helloandroid.test. - Right-click on the package icon and select New > Class: -

        - - Menu for creating a new class in the test application - -

        -

        - The New Java Class dialog appears. -

        -
      4. -
      5. - In the dialog, enter the following: -
          -
        • - Name: "HelloAndroidTest". This becomes the name of your test class. -
        • -
        • - Superclass: "android.test.ActivityInstrumentationTestCase2<HelloAndroid>". - The superclass is parameterized by an Activity class name. -

          - The dialog should now look like this: -

          - - New Java Class dialog with entries - -
        • -
        -

        - Do not change any of the other settings. Click Finish. -

        -
      6. -
      7. - You now have a new file HelloAndroidTest.java in the project. - This file contains the class HelloAndroidTest, - which extends the Activity test case class - ActivityInstrumentationTestCase2<T>. You parameterize the - class with HelloAndroid, which is the class name of the activity under test. -
      8. -
      9. - Open HelloAndroidTest.java. It should look like this: -
        -package com.example.helloandroid.test;
        -
        -import android.test.ActivityInstrumentationTestCase2;
        -
        -public class HelloAndroidTest extends ActivityInstrumentationTestCase2<HelloAndroid> {
        -}
        -
        -
      10. -
      11. - The test case class depends on the HelloAndroid class, which is not - yet imported. To import the class, add the following line just before the current - import statement: -
        -import com.example.helloandroid.HelloAndroid;
        -
        -
      12. -
      -

      Adding the test case constructor

      -

      - The test case class constructor is used by the Android testing framework when you run the test. - It calls the super constructor with parameters that tell the framework what Android application - should be tested. -

      -

      - Add the following constructor method immediately after the class definition: -

      -
      -    public HelloAndroidTest() {
      -      super("com.example.helloandroid", HelloAndroid.class);
      -    }
      -
      -

      - Save the file HelloAndroidTest.java. -

      -

      Adding a setup method

      -

      - The setUp() method overrides the JUnit {@link junit.framework.TestCase#setUp() setUp()} - method, which the Android testing framework calls prior to running each test method. You use - setUp() to initialize variables and prepare the test environment. For this - test case, the setUp() method starts the Hello, Android application, - retrieves the text being displayed on the screen, and retrieves the text string in the - resource file. -

      -

      - First, add the following code immediately after the constructor method: -

      -
      -    @Override
      -    protected void setUp() throws Exception {
      -        super.setUp();
      -        mActivity = this.getActivity();
      -        mView = (TextView) mActivity.findViewById(com.example.helloandroid.R.id.textview);
      -        resourceString = mActivity.getString(com.example.helloandroid.R.string.hello);
      -    }
      -
      -

      - For this code to work, you must also add some class members and another import statement. To - add the class members, add the following code immediately after the class definition: -

      -
      -    private HelloAndroid mActivity;
      -    private TextView mView;
      -    private String resourceString;
      -
      -

      - To add the import statement, add the following statement just after the import for - android.test.ActivityInstrumentationTestCase2: -

      -
      -  import android.widget.TextView;
      -
      -

      Adding a preconditions test

      -

      - A preconditions test checks the initial application conditions prior to executing other tests. - It's similar to setUp(), but with less overhead, since it only runs once. -

      -

      - Although a preconditions test can check for a variety of different conditions, - in this application it only needs to check whether the application under test is - initialized properly and the target TextView exists. - To do this, it calls the inherited - {@link junit.framework.Assert#assertNotNull(Object) assertNotNull()} - method, passing a reference to the TextView. - The test succeeds only if the object reference is not null. -

      -
      -    public void testPreconditions() {
      -      assertNotNull(mView);
      -    }
      -
      -

      Adding a unit test

      -

      - Now add a simple unit test to the test case class. - The method testText() will call a - {@link junit.framework.Assert JUnit Assert} - method to check whether the target TextView is displaying the expected text. -

      -

      - For this example, the test expects that the TextView is - displaying the string resource that was originally declared for it in HelloAndroid's - main.xml file, referred to by the resource ID hello. - The call to - {@link junit.framework.Assert#assertEquals(String, String) assertEquals(String,String)} - compares the expected value, read directly from the hellostring resource, - to the text displayed by the TextView, obtained from the - TextView's getText() method. The test succeeds only if the strings match. -

      -

      - To add this test, add the following code - immediately after the testPreconditions() method: -

      -
      -    public void testText() {
      -      assertEquals(resourceString,(String)mView.getText());
      -    }
      -
      -

      The finished test case class

      -

      - You have now finished writing the test. This is what the complete test case class - should look like: -

      -
      -package com.example.helloandroid.test;
      -
      -import com.example.helloandroid.HelloAndroid;
      -import android.test.ActivityInstrumentationTestCase2;
      -import android.widget.TextView;
      -
      -public class HelloAndroidTest extends ActivityInstrumentationTestCase2<HelloAndroid> {
      -    private HelloAndroid mActivity;  // the activity under test
      -    private TextView mView;          // the activity's TextView (the only view)
      -    private String resourceString;
      -
      -    public HelloAndroidTest() {
      -      super("com.example.helloandroid", HelloAndroid.class);
      -    }
      -    @Override
      -    protected void setUp() throws Exception {
      -        super.setUp();
      -        mActivity = this.getActivity();
      -        mView = (TextView) mActivity.findViewById(com.example.helloandroid.R.id.textview);
      -        resourceString = mActivity.getString(com.example.helloandroid.R.string.hello);
      -    }
      -    public void testPreconditions() {
      -      assertNotNull(mView);
      -    }
      -    public void testText() {
      -      assertEquals(resourceString,(String)mView.getText());
      -    }
      -}
      -
      -

      Running the Tests and Seeing the Results

      -

      - You can now run the tests you've created against the Hello, Android application. In Eclipse with - ADT, you run a test application as an Android JUnit test rather than a regular - Android application. -

      -

      - To run the test application as an Android JUnit test, in the Package Explorer right-click - the HelloAndroidTest project and select Run As > Android JUnit Test -

      - - Menu to run Hello, World as an Android JUnit test - -

      - The ADT plugin then launches the test application and the application - under test on a the target emulator or device. When both applications are running, - the testing framework runs the tests and reports the results in the JUnit view of Eclipse, - which appears by default as a tab next to the Package Explorer. -

      -

      - As shown below, the JUnit view shows test results in two separate panes: - an upper pane summarizes the tests that were run and a lower pane reports the failure traces - for the tests. In this case, the tests in this example have run successfully, so there is no - failure reported in the view: -

      - - JUnit test run success - -

      - The upper pane summarizes the test: -

      -
        -
      • - "Finished after x seconds": How long the test took to run. -
      • -
      • - "Runs": The number of tests run. -
      • -
      • - "Errors:": The number of program errors and exceptions encountered during - the test run. -
      • -
      • - "Failures:": The number of assertion failures encountered during the - test run. -
      • -
      • - A progress bar. The progress bar extends from left to right as the tests run. -

        - If all the tests succeed, the bar remains green. - If a test fails, the bar turns from green to red. -

        -
      • -
      • - A test method summary. Below the bar, you see a line for each class in the - test application, labeled by its fully-qualified class name. - To look at the results for the individual methods in a test case class, - click the arrow at the left of the class to expand the line. - You see the name of each test method. To the right of the method name, you see the - time needed to run that method. You can look at the method's code by - double-clicking its name. -
      • -
      -

      - The lower pane contains the failure trace. If all the tests are successful, - this pane is empty. If some tests fail, then if you select a failed test in the - upper pane, the lower view contains a stack trace for the test. -

      -

      Next Steps

      -

      - This simple example test application has shown you how to create a test project, - create a test class and test cases, and then run the tests against a target application. - Now that you are familiar with these fundamentals, here are some suggested next steps: -

      -

      - Learn more about testing on Android -

      -
        -
      • - The - Testing Android Applications - document in the Dev Guide provides an overview of how testing on Android works. - If you are just getting started with Android testing, reading that document will - help you understand the tools available to you, so that you can develop effective - tests. -
      • -
      -

      - Learn more about the testing classes available in Android -

      -
        -
      • - For an overview of the types of testing classes you can use, - browse through the reference documentation for - {@link android.test.ActivityInstrumentationTestCase2}, - {@link android.test.ProviderTestCase2}, - {@link android.test.ServiceTestCase}, and - {@link junit.framework.Assert}. -
      • -
      -

      - Explore the Android instrumentation framework -

      -
        -
      • - The {@link android.test.InstrumentationTestRunner} class contains the code that Android uses - to run tests against an application. The {@link android.test.InstrumentationTestCase} class - is the base class for test case classes that use additional instrumentation features. -
      • -
      -

      - Follow the Activity Testing tutorial -

      -
        -
      • - The Activity Testing - tutorial is an excellent follow-up to this tutorial. - It guides you through a more complex testing scenario that you develop against a - more realistic application. -
      • -
      diff --git a/docs/html/resources/tutorials/views/hello-autocomplete.jd b/docs/html/resources/tutorials/views/hello-autocomplete.jd deleted file mode 100644 index e26683de19e6ac34f17bf93f433c88ba837dd916..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-autocomplete.jd +++ /dev/null @@ -1,173 +0,0 @@ -page.title=Auto Complete -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      To create a text entry widget that provides auto-complete suggestions, use -the {@link android.widget.AutoCompleteTextView} widget. Suggestions are received from a -collection of strings associated with the widget through an {@link -android.widget.ArrayAdapter}.

      - -

      In this tutorial, you will create a {@link android.widget.AutoCompleteTextView} widget that -provides suggestions for a country name.

      - - -
        -
      1. Start a new project named HelloAutoComplete.
      2. -
      3. Create an XML file named list_item.xml and save it inside the -res/layout/ folder. Edit the file to look like this: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:layout_width="fill_parent"
        -    android:layout_height="fill_parent"
        -    android:padding="10dp"
        -    android:textSize="16sp"
        -    android:textColor="#000">
        -</TextView>
        -
        -

        This file defines a simple {@link android.widget.TextView} that will be used for each -item that appears in the list of suggestions.

        -
      4. -
      5. Open the res/layout/main.xml file and insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
        -    android:orientation="horizontal"
        -    android:layout_width="fill_parent" 
        -    android:layout_height="wrap_content"
        -    android:padding="5dp">
        -    <TextView
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:text="Country" />
        -    <AutoCompleteTextView android:id="@+id/autocomplete_country"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:layout_marginLeft="5dp"/>
        -</LinearLayout>
        -
        -

        The {@link android.widget.TextView} is a label that introduces the {@link -android.widget.AutoCompleteTextView} widget. -

      6. - -
      7. Open HelloAutoComplete.java and insert the following code for the {@link -android.app.Activity#onCreate(Bundle) onCreate()} method: -
        -@Override
        -protected void onCreate(Bundle savedInstanceState) {
        -    super.onCreate(savedInstanceState);
        -    setContentView(R.layout.main);
        -
        -    AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autocomplete_country);
        -    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, COUNTRIES);
        -    textView.setAdapter(adapter);
        -}
        -
        - -

        After the content view is set to the main.xml layout, the {@link -android.widget.AutoCompleteTextView} widget is captured from the layout with {@link -android.app.Activity#findViewById(int)}. A new {@link -android.widget.ArrayAdapter} is then initialized to bind the list_item.xml layout -to each list item in the COUNTRIES string array (defined in the next step). -Finally, {@link android.widget.AutoCompleteTextView#setAdapter(T) setAdapter()} is called to -associate the {@link android.widget.ArrayAdapter} with the -{@link android.widget.AutoCompleteTextView} widget so that the string array will populate -the list of suggestions.

        -
      8. - -
      9. Inside the HelloAutoComplete class, add the string array: -
        -static final String[] COUNTRIES = new String[] {
        -  "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
        -  "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
        -  "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
        -  "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
        -  "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
        -  "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",
        -  "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
        -  "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
        -  "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
        -  "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
        -  "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
        -  "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
        -  "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
        -  "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
        -  "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
        -  "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
        -  "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
        -  "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
        -  "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
        -  "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
        -  "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
        -  "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
        -  "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
        -  "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
        -  "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
        -  "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
        -  "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
        -  "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
        -  "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
        -  "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
        -  "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
        -  "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
        -  "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
        -  "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
        -  "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
        -  "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
        -  "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
        -  "Ukraine", "United Arab Emirates", "United Kingdom",
        -  "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
        -  "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
        -  "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
        -};
        -
        -

        This is the list of suggestions that will be provided in a drop-down list when the user types into -the {@link android.widget.AutoCompleteTextView} widget.

        -
      10. - -
      11. Run the application.
      12. -
      -

      As you type, you should see something like this:

      - - - -

      More Information

      - -

      Note that using a hard-coded string array is not a recommended design practice because your -application code should focus on behavior, not content. Application content such as strings -should be externalized from the code in order to make modifications to the content easier and -facilitate localization of the content. The hard-coded strings are used in this tutorial only to -make it simple and focus on the {@link android.widget.AutoCompleteTextView} widget. -Instead, your application should declare such string arrays in an XML file. This can be done -with a {@code <string-array<} resource in your project {@code res/values/strings.xml} file. -For example:

      -
      -<?xml version="1.0" encoding="utf-8"?>
      -<resources>
      -    <string-array name="countries_array">
      -        <item>Bahrain</item>
      -        <item>Bangladesh</item>
      -        <item>Barbados</item>
      -        <item>Belarus</item>
      -        <item>Belgium</item>
      -        <item>Belize</item>
      -        <item>Benin</item>
      -    </string-array>
      -</resources>
      -
      -

      To use these resource strings for the {@link android.widget.ArrayAdapter}, replace the original -{@link android.widget.ArrayAdapter} constructor line with the following:

      -
      -String[] countries = getResources().getStringArray(R.array.countries_array);
      -ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, countries);
      -
      - - -

      References

      -
        -
      • {@link android.widget.ArrayAdapter}
      • -
      • {@link android.widget.AutoCompleteTextView}
      • -
      - - diff --git a/docs/html/resources/tutorials/views/hello-datepicker.jd b/docs/html/resources/tutorials/views/hello-datepicker.jd deleted file mode 100644 index c50d6500f58be4d301955b922deb94cc5724fa67..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-datepicker.jd +++ /dev/null @@ -1,173 +0,0 @@ -page.title=Date Picker -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      To provide a widget for selecting a date, use the {@link android.widget.DatePicker} -widget, which allows the user to select the month, day, and year, in a familiar interface.

      - -

      In this tutorial, you'll create a {@link android.app.DatePickerDialog}, which presents the -date picker in a floating dialog box at the press of a button. When the date is set by -the user, a {@link android.widget.TextView} will update with the new date.

      - -
        -
      1. Start a new project named HelloDatePicker.
      2. -
      3. Open the res/layout/main.xml file and insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:layout_width="wrap_content"
        -    android:layout_height="wrap_content"
        -    android:orientation="vertical">
        -    <TextView android:id="@+id/dateDisplay"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:text=""/>
        -    <Button android:id="@+id/pickDate"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:text="Change the date"/>
        -</LinearLayout>
        -
        -

        This creates a basic {@link android.widget.LinearLayout} with a {@link android.widget.TextView} - that will display the date and a {@link android.widget.Button} that will open the {@link - android.app.DatePickerDialog}.

        -
      4. - -
      5. Open HelloDatePicker.java and add the following members to the class: -
        -    private TextView mDateDisplay;
        -    private Button mPickDate;
        -    private int mYear;
        -    private int mMonth;
        -    private int mDay;
        -
        -    static final int DATE_DIALOG_ID = 0;
        -
        -

        The first group of members define variables for the layout {@link android.view.View}s and the -date items. The DATE_DIALOG_ID is a static integer that uniquely identifies the {@link -android.app.Dialog} that will display the date picker.

        -
      6. - -
      7. Now add the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} -method: -
        -    protected void onCreate(Bundle savedInstanceState) {
        -        super.onCreate(savedInstanceState);
        -        setContentView(R.layout.main);
        -
        -        // capture our View elements
        -        mDateDisplay = (TextView) findViewById(R.id.dateDisplay);
        -        mPickDate = (Button) findViewById(R.id.pickDate);
        -
        -        // add a click listener to the button
        -        mPickDate.setOnClickListener(new View.OnClickListener() {
        -            public void onClick(View v) {
        -                showDialog(DATE_DIALOG_ID);
        -            }
        -        });
        -
        -        // get the current date
        -        final Calendar c = Calendar.getInstance();
        -        mYear = c.get(Calendar.YEAR);
        -        mMonth = c.get(Calendar.MONTH);
        -        mDay = c.get(Calendar.DAY_OF_MONTH);
        -
        -        // display the current date (this method is below)
        -        updateDisplay();
        -    }
        -
        - -

        First, the content is set to the main.xml layout. Then the {@link -android.widget.TextView} and {@link android.widget.Button} elements are captured from the layout -with {@link android.app.Activity#findViewById(int)}. A -new {@link android.view.View.OnClickListener} is created for the -{@link android.widget.Button}, so that when it is clicked, it -will call {@link android.app.Activity#showDialog(int)}, passing the unique integer ID for -the date picker dialog. Using {@link android.app.Activity#showDialog(int)} allows the {@link -android.app.Activity} to manage the life-cycle of the dialog and will call the {@link -android.app.Activity#onCreateDialog(int)} callback method to request the {@link android.app.Dialog} -that should be displayed (which you'll -define later). After the on-click listener is set, a new {@link java.util.Calendar} is created -and the current year, month and day are acquired. Finally, the private -updateDisplay() method is called in order to fill the {@link android.widget.TextView} -with the current date.

        -
      8. - -
      9. Add the updateDisplay() method: -
        -    // updates the date in the TextView
        -    private void updateDisplay() {
        -        mDateDisplay.setText(
        -            new StringBuilder()
        -                    // Month is 0 based so add 1
        -                    .append(mMonth + 1).append("-")
        -                    .append(mDay).append("-")
        -                    .append(mYear).append(" "));
        -    }
        -
        -

        This method uses the member date values declared for the class to write the date to the layout's -{@link android.widget.TextView}, {@code mDateDisplay}, which was also declared and initialized -above.

        -
      10. - -
      11. Initialize a new {@link android.app.DatePickerDialog.OnDateSetListener} as a member of the -HelloDatePicker class: -
        -    // the callback received when the user "sets" the date in the dialog
        -    private DatePickerDialog.OnDateSetListener mDateSetListener =
        -            new DatePickerDialog.OnDateSetListener() {
        -
        -                public void onDateSet(DatePicker view, int year, 
        -                                      int monthOfYear, int dayOfMonth) {
        -                    mYear = year;
        -                    mMonth = monthOfYear;
        -                    mDay = dayOfMonth;
        -                    updateDisplay();
        -                }
        -            };
        -
        -

        The {@link android.app.DatePickerDialog.OnDateSetListener} listens for when the user -has set the date (by clicking the "Set" button). At that time, the {@link -android.app.DatePickerDialog.OnDateSetListener#onDateSet(DatePicker,int,int,int) onDateSet()} -callback method is called, which is defined to update the {@code mYear}, {@code mMonth}, and -{@code mDay} member fields with the new date then call the private updateDisplay() -method to update the {@link android.widget.TextView}.

        -
      12. - -
      13. Now add the {@link android.app.Activity#onCreateDialog(int)} callback method to the {@code -HelloDatePicker} class: -
        -@Override
        -protected Dialog onCreateDialog(int id) {
        -    switch (id) {
        -    case DATE_DIALOG_ID:
        -        return new DatePickerDialog(this,
        -                    mDateSetListener,
        -                    mYear, mMonth, mDay);
        -    }
        -    return null;
        -}
        -
        -

        This is an {@link android.app.Activity} callback method that is passed the integer ID given to -{@link android.app.Activity#showDialog(int)} (which is called by the button's {@link -android.view.View.OnClickListener}). When the ID matches the switch case defined here, a {@link -android.app.DatePickerDialog} is instantiated with the {@link -android.app.DatePickerDialog.OnDateSetListener} created in the previous -step, along with the date variables to initialize the widget date.

        -
      14. - -
      15. Run the application.
      16. -
      -

      When you press the "Change the date" button, you should see the following:

      - - -

      References

      -
        -
      • {@link android.app.DatePickerDialog}
      • -
      • {@link android.app.DatePickerDialog.OnDateSetListener}
      • -
      • {@link android.widget.Button}
      • -
      • {@link android.widget.TextView}
      • -
      • {@link java.util.Calendar}
      • -
      - diff --git a/docs/html/resources/tutorials/views/hello-formstuff.jd b/docs/html/resources/tutorials/views/hello-formstuff.jd deleted file mode 100644 index 1ddd1df7fe84431500d1d73ca3393d6baac3d258..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-formstuff.jd +++ /dev/null @@ -1,400 +0,0 @@ -page.title=Form Stuff -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      This tutorial introduces a variety of widgets that are useful when creating forms, such as -image buttons, text fields, checkboxes and radio buttons.

      - - -
        -
      1. Start a new project named HelloFormStuff.
      2. -
      3. Your res/layout/main.xml file should already have a basic {@link -android.widget.LinearLayout}: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:orientation="vertical"
        -    android:layout_width="fill_parent"
        -    android:layout_height="fill_parent" >
        -</LinearLayout>
        -
        -

        For each widget you want to add, just put the respective View inside this {@link -android.widget.LinearLayout}.

        -
      4. -
      -

      Each section below also assumes that your HelloFormStuff Activity has the following -default implementation of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:

      -
      -public void onCreate(Bundle savedInstanceState) {
      -    super.onCreate(savedInstanceState);
      -    setContentView(R.layout.main);
      -}
      -
      - -

      Now select which kind of form widget you'd like to create:

      - - - - -

      Custom Button

      - -

      In this section, you will create a button with a custom image instead of text, using the {@link -android.widget.Button} widget and an XML file that defines three different images to use for the -different button states. When the button is pressed, a short message will be displayed.

      - - - - -
        -
      1. Copy the images on the right into the res/drawable/ directory of -your project. These will be used for the different button states.
      2. -
      3. Create a new file in the res/drawable/ directory named -android_button.xml. -Insert the following XML: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<selector xmlns:android="http://schemas.android.com/apk/res/android">
        -    <item android:drawable="@drawable/android_pressed"
        -          android:state_pressed="true" />
        -    <item android:drawable="@drawable/android_focused"
        -          android:state_focused="true" />
        -    <item android:drawable="@drawable/android_normal" />
        -</selector>
        -
        -

        This defines a single drawable resource, which will change its image based on the current -state of the button. The first <item> defines -android_pressed.png as the image when the button is pressed (it's been -activated); the second <item> defines android_focused.png as the image -when the button is focused (when the button is highlighted using the trackball or directional -pad); and the third <item> defines android_normal.png as the image -for the normal state (when neither pressed nor focused). This XML file now represents a single -drawable resource and when referenced by a {@link android.widget.Button} for its background, -the image displayed will change based on these three states.

        -

        Note: The order of the <item> elements is -important. When this drawable is referenced, the <item>s are traversed in-order to -determine which one is appropriate for the current button state. Because the "normal" image is last, -it is only applied when the conditions android:state_pressed and -android:state_focused have both evaluated false.

      4. -
      5. Open the res/layout/main.xml file and add the {@link -android.widget.Button} element: -
        -    <Button
        -        android:id="@+id/button"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:padding="10dp"
        -        android:background="@drawable/android_button"
        -        android:onClick="onButtonClicked"/>
        -
        -

        The android:background attribute specifies the drawable resource to use for the -button background (which, when saved at res/drawable/android.xml, is -referenced as @drawable/android). This replaces the normal background image -applied by the system with the drawable created above, which changes its image based on -the button state.

        -

        The attribute android:onClick specifies the name of a method in your activity -that the system should call when the user clicks the button. You'll create that method next.

        -
      6. - -
      7. To make the button do something when pressed, add the following -method inside your {@link android.app.Activity} class: -
        -public void onButtonClicked(View v) {
        -    // Do something when the button is clicked
        -    Toast.makeText(HelloFormStuff.this, "Button clicked", Toast.LENGTH_SHORT).show();
        -}
        -
        -

        When you specify this kind of method, which is used in your layout file with the {@code -android:onClick} attribute, the method must be public, have a void return -value, and accept a single {@code android.view.View} parameter. When the system calls this method, -it passes the {@code android.view.View} that was clicked.

        -
      8. -
      9. Now run the application.
      10. -
      - - - -

      Edit Text

      - -

      In this section, you will create a text field for user input, using the {@link -android.widget.EditText} widget. Once text has been entered into the field, the "Enter" key will -display the text in a toast message.

      - -
        -
      1. Open the res/layout/main.xml file and add the {@link android.widget.EditText} -element (inside the {@link android.widget.LinearLayout}): -
        -    <EditText
        -        android:id="@+id/edittext"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"/>
        -
        -
      2. -
      3. To do something with the text that the user types, add the following code -to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method: -
        -final EditText edittext = (EditText) findViewById(R.id.edittext);
        -edittext.setOnKeyListener(new OnKeyListener() {
        -    public boolean onKey(View v, int keyCode, KeyEvent event) {
        -        // If the event is a key-down event on the "enter" button
        -        if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
        -            (keyCode == KeyEvent.KEYCODE_ENTER)) {
        -          // Perform action on key press
        -          Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show();
        -          return true;
        -        }
        -        return false;
        -    }
        -});
        -
        -

        This captures the {@link android.widget.EditText} element from the layout and adds an {@link -android.view.View.OnKeyListener}. The {@link android.view.View.OnKeyListener} must implement the -{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent)} method, which -defines the action to be made when a key is pressed while the widget has focus. In this case, the -method is defined to listen for the Enter key (when pressed down), then pop up a {@link -android.widget.Toast} message with the text that has been entered. The {@link -android.view.View.OnKeyListener#onKey(View,int,KeyEvent)} method should always return -true if the event has been handled, so that the event doesn't bubble-up (which would -result in a carriage return in the text field).

        -
      4. -
      5. Run the application.
      6. -
      - - - -

      Checkbox

      - -

      In this section, you will create a checkbox for selecting items, using the {@link -android.widget.CheckBox} widget. When the checkbox is pressed, a toast message will -indicate the current state of the checkbox.

      - -
        -
      1. Open the res/layout/main.xml file and add the {@link android.widget.CheckBox} -element (inside the {@link android.widget.LinearLayout}): -
        -    <CheckBox android:id="@+id/checkbox"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:text="check it out"
        -        android:onClick="onCheckboxClicked"/>
        -
        -

        The attribute android:onClick specifies the name of a method in your activity -that the system should call when the user clicks the check box. You'll create that method next.

        -
      2. -
      3. To do something when the state is changed, add the following method inside your {@link -android.app.Activity} class:

        - -
        -public void onCheckboxClicked(View v) {
        -    // Perform action on clicks, depending on whether it's now checked
        -    if (((CheckBox) v).isChecked()) {
        -        Toast.makeText(HelloFormStuff.this, "Selected", Toast.LENGTH_SHORT).show();
        -    } else {
        -        Toast.makeText(HelloFormStuff.this, "Not selected", Toast.LENGTH_SHORT).show();
        -    }
        -}
        -
        - -

        When you specify this kind of method, which is used in your layout file with the {@code -android:onClick} -attribute, the method must be public, have a void return value, and -accept a single {@code android.view.View} parameter. When the system calls this method, it -passes the {@code android.view.View} that was clicked. In this example, the {@code -android.view.View} is cast to a {@link android.widget.CheckBox} to determine whether the widget -has been checked or unchecked. The {@link android.widget.CheckBox} widget -handles its own state changes, so you only need to query the current state.

        -
      4. -
      5. Run it.
      6. -
      -

      Tip: If you need to change the state -yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), -use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link -android.widget.CompoundButton#toggle()} method.

      - - - -

      Radio Buttons

      - -

      In this section, you will create two mutually-exclusive radio buttons (enabling one disables -the other), using the {@link android.widget.RadioGroup} and {@link android.widget.RadioButton} -widgets. When either radio button is pressed, a toast message will be displayed.

      - -
        -
      1. Open the res/layout/main.xml file and add two {@link -android.widget.RadioButton}s, nested in a {@link android.widget.RadioGroup} (inside the {@link -android.widget.LinearLayout}): -
        -    <RadioGroup
        -      android:layout_width="fill_parent"
        -      android:layout_height="wrap_content"
        -      android:orientation="vertical">
        -      <RadioButton android:id="@+id/radio_red"
        -          android:layout_width="wrap_content"
        -          android:layout_height="wrap_content"
        -          android:text="Red"
        -          android:onClick="onRadioButtonClicked"/>
        -      <RadioButton android:id="@+id/radio_blue"
        -          android:layout_width="wrap_content"
        -          android:layout_height="wrap_content"
        -          android:text="Blue"
        -          android:onClick="onRadioButtonClicked"/>
        -    </RadioGroup>
        -
        -

        It's important that the {@link android.widget.RadioButton}s are grouped together by the {@link -android.widget.RadioGroup} element so that no more than one can be selected at a time. This logic -is automatically handled by the Android system. When one {@link android.widget.RadioButton} within -a group is selected, all others are automatically deselected.

        -

        The attribute android:onClick specifies the name of a method in your activity -that the system should call when the user clicks the radio button. You'll create that method -next.

        -
      2. - -
      3. To do something when each {@link android.widget.RadioButton} is selected, add the following -method inside your {@link android.app.Activity} class:

        - -
        -public void onRadioButtonClicked(View v) {
        -    // Perform action on clicks
        -    RadioButton rb = (RadioButton) v;
        -    Toast.makeText(HelloFormStuff.this, rb.getText(), Toast.LENGTH_SHORT).show();
        -}
        -
        - -

        When you specify this kind of method, which is used in your layout file with the {@code -android:onClick} -attribute, the method must be public, have a void return value, and -accept a single {@code android.view.View} parameter. When the system calls this method, it -passes the {@code android.view.View} that was clicked.

        -

        Because each {@link android.widget.RadioButton} widget is grouped into a {@link -android.widget.RadioGroup}, each widget handles its own state changes when a new button is -selected.

        -
      4. -
      5. Run the application.
      6. -
      - -

      Tip: If you need to change the state -yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), -use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link -android.widget.CompoundButton#toggle()} method.

      - - - -

      Toggle Button

      - -

      In this section, you'll create a button used specifically for toggling between two -states, using the {@link android.widget.ToggleButton} widget. This widget is an excellent -alternative to radio buttons if you have two simple states that are mutually exclusive ("on" and -"off", for example).

      - -
        -
      1. Open the res/layout/main.xml file and add the {@link android.widget.ToggleButton} -element (inside the {@link android.widget.LinearLayout}): -
        -    <ToggleButton android:id="@+id/togglebutton"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:textOn="Vibrate on"
        -        android:textOff="Vibrate off"
        -        android:onClick="onToggleClicked"/>
        -
        -

        The attributes android:textOn and android:textOff specify the text -for the button when the button has been toggled on or off. The default values are "ON" and -"OFF".

        -

        The attribute android:onClick specifies the name of a method in your activity -that the system should call when the user clicks the button. You'll create that method next.

        -
      2. -
      3. To do something when the user clicks the button, add the following -method inside your {@link android.app.Activity} class:

        - -
        -public void onToggleClicked(View v) {
        -    // Perform action on clicks
        -    if (((ToggleButton) v).isChecked()) {
        -        Toast.makeText(HelloFormStuff.this, "Toggle on", Toast.LENGTH_SHORT).show();
        -    } else {
        -        Toast.makeText(HelloFormStuff.this, "Toggle off", Toast.LENGTH_SHORT).show();
        -    }
        -}
        -
        - -

        When you specify this kind of method, which is used in your layout file with the {@code -android:onClick} -attribute, the method must be public, have a void return value, and -accept a single {@code android.view.View} parameter. When the system calls this method, it -passes the {@code android.view.View} that was clicked.

        -

        In this example, the callback -method checks the new state of the button, then shows a {@link android.widget.Toast} message that -indicates the current state.

        - -

        Notice that the {@link android.widget.ToggleButton} handles its own state change between checked -and unchecked, so you just ask which it is.

        -
      4. Run the application.
      5. -
      - -

      Tip: If you need to change the state -yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), -use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link -android.widget.CompoundButton#toggle()} method.

      - - - - -

      Rating Bar

      - -

      In this section, you'll create a widget that allows the user to provide a rating, -with the {@link android.widget.RatingBar} widget.

      - -
        -
      1. Open the res/layout/main.xml file and add the {@link android.widget.RatingBar} -element (inside the {@link android.widget.LinearLayout}): -
        -    <RatingBar android:id="@+id/ratingbar"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:numStars="5"
        -        android:stepSize="1.0"/>
        -
        -

        The android:numStars attribute defines how many stars to display for the rating -bar. The android:stepSize attribute defines the granularity for each -star (for example, a value of 0.5 would allow half-star ratings).

        -
      2. -
      3. To do something when a new rating has been set, add the following code -to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method: -
        -final RatingBar ratingbar = (RatingBar) findViewById(R.id.ratingbar);
        -ratingbar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
        -    public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
        -        Toast.makeText(HelloFormStuff.this, "New Rating: " + rating, Toast.LENGTH_SHORT).show();
        -    }
        -});
        -
        -

        This captures the {@link android.widget.RatingBar} widget from the layout with {@link -android.app.Activity#findViewById(int)} and then sets an {@link -android.widget.RatingBar.OnRatingBarChangeListener}. The {@link -android.widget.RatingBar.OnRatingBarChangeListener#onRatingChanged(RatingBar,float,boolean) -onRatingChanged()} callback method then defines the action to perform when the user sets a rating. -In this case, a simple {@link android.widget.Toast} message displays the new rating.

        - -
      4. Run the application.
      5. -
      - -

      If you've added all the form widgets above, your application should look like this:

      - - -

      References

      -
        -
      • {@link android.widget.ImageButton}
      • -
      • {@link android.widget.EditText}
      • -
      • {@link android.widget.CheckBox}
      • -
      • {@link android.widget.RadioButton}
      • -
      • {@link android.widget.ToggleButton}
      • -
      • {@link android.widget.RatingBar}
      • -
      - diff --git a/docs/html/resources/tutorials/views/hello-gallery.jd b/docs/html/resources/tutorials/views/hello-gallery.jd deleted file mode 100644 index 5f2ed32b6ff660620102ab5ef4479cea5598ef5e..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-gallery.jd +++ /dev/null @@ -1,171 +0,0 @@ -page.title=Gallery -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      {@link android.widget.Gallery} is a layout widget used to display items in a -horizontally scrolling list and positions the current selection at the center of the view.

      - -

      In this tutorial, you'll create a gallery of photos and then display a toast message each time a -gallery item is selected.

      - - -
        -
      1. Start a new project named HelloGallery.
      2. -
      3. Find some photos you'd like to use, or use these sample images. Save the images into the project's -res/drawable/ directory.
      4. -
      5. Open the res/layout/main.xml file and insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<Gallery xmlns:android="http://schemas.android.com/apk/res/android" 
        -    android:id="@+id/gallery"
        -    android:layout_width="fill_parent"
        -    android:layout_height="wrap_content"
        -/>
        -
        -
      6. - -
      7. Open the HelloGallery.java file and insert the following code for the -{@link android.app.Activity#onCreate(Bundle) onCreate()} method: -
        -@Override
        -public void onCreate(Bundle savedInstanceState) {
        -    super.onCreate(savedInstanceState);
        -    setContentView(R.layout.main);
        -
        -    Gallery gallery = (Gallery) findViewById(R.id.gallery);
        -    gallery.setAdapter(new ImageAdapter(this));
        -
        -    gallery.setOnItemClickListener(new OnItemClickListener() {
        -        public void onItemClick(AdapterView parent, View v, int position, long id) {
        -            Toast.makeText(HelloGallery.this, "" + position, Toast.LENGTH_SHORT).show();
        -        }
        -    });
        -}
        -
        -

        This starts by setting the {@code main.xml} layout as the content view and then capturing the -{@link android.widget.Gallery} from -the layout with {@link -android.app.Activity#findViewById(int)}. A custom {@link android.widget.BaseAdapter} called -ImageAdapter is -instantiated and applied to the {@link android.widget.Gallery} with {@link -android.widget.AdapterView#setAdapter(T) setAdapter()}. (The ImageAdapter class is -defined next.) -Then an anonymous {@link android.widget.AdapterView.OnItemClickListener} is instantiated. The -{@link android.widget.AdapterView.OnItemClickListener#onItemClick(AdapterView,View,int,long)} -callback method receives the {@link android.widget.AdapterView} where the click occurred, the -specific {@link android.view.View} that received the click, the -position of the {@link android.view.View} clicked (zero-based), and the row ID of the item clicked -(if applicable). In this example, all that's needed is the position of the click to show a {@link -android.widget.Toast} message that says the position of the item, using -{@link android.widget.Toast#makeText(Context,CharSequence,int)} and {@link -android.widget.Toast#show()} (in a real world scenario, this ID could be used to get the full sized -image for some other task). -

        -
      8. -
      9. Create a new XML file in the res/values/ directory named attrs.xml. -Insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<resources>
        -    <declare-styleable name="HelloGallery">
        -        <attr name="android:galleryItemBackground" />
        -    </declare-styleable>
        -</resources>
        -
        -

        This is a custom styleable resource that can be applied to a layout. In this case, it will be -applied to the individual items placed into the {@link android.widget.Gallery} widget. The -<attr> element defines a specific attribute for the styleable, and in this case, it -refers to an existing platform attribute, {@link android.R.attr#galleryItemBackground}, which -defines a border styling for gallery items. In the next step, you'll -see how this attribute is referenced and then later applied to each item in the gallery.

        -
      10. - -
      11. Go back to the HelloGallery.java file. After the {@link - android.app.Activity#onCreate(Bundle)} method, define the custom ImageAdapter class: -
        -public class ImageAdapter extends BaseAdapter {
        -    int mGalleryItemBackground;
        -    private Context mContext;
        -
        -    private Integer[] mImageIds = {
        -            R.drawable.sample_1,
        -            R.drawable.sample_2,
        -            R.drawable.sample_3,
        -            R.drawable.sample_4,
        -            R.drawable.sample_5,
        -            R.drawable.sample_6,
        -            R.drawable.sample_7
        -    };
        -
        -    public ImageAdapter(Context c) {
        -        mContext = c;
        -        TypedArray attr = mContext.obtainStyledAttributes(R.styleable.HelloGallery);
        -        mGalleryItemBackground = attr.getResourceId(
        -                R.styleable.HelloGallery_android_galleryItemBackground, 0);
        -        attr.recycle();
        -    }
        -
        -    public int getCount() {
        -        return mImageIds.length;
        -    }
        -
        -    public Object getItem(int position) {
        -        return position;
        -    }
        -
        -    public long getItemId(int position) {
        -        return position;
        -    }
        -
        -    public View getView(int position, View convertView, ViewGroup parent) {
        -        ImageView imageView = new ImageView(mContext);
        -
        -        imageView.setImageResource(mImageIds[position]);
        -        imageView.setLayoutParams(new Gallery.LayoutParams(150, 100));
        -        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        -        imageView.setBackgroundResource(mGalleryItemBackground);
        -
        -        return imageView;
        -    }
        -}
        -
        -

        First, there are a few member variables, including an array of IDs that reference -the images saved in the drawable resources directory ({@code res/drawable/}).

        -

        Next is the class constructor, where the {@link android.content.Context} for an {@code -ImageAdapter} instance is defined and the styleable -resource defined in the last step is acquired and saved to a local field. At the end of the -constructor, {@link android.content.res.TypedArray#recycle()} is called on the {@link -android.content.res.TypedArray} so it can be re-used by the system.

        -

        The methods {@link android.widget.Adapter#getCount()}, {@link -android.widget.Adapter#getItem(int)}, and {@link android.widget.Adapter#getItemId(int)} are methods -that must be implemented for simple queries on the {@link android.widget.Adapter}. -The {@link android.widget.Adapter#getView(int,View,ViewGroup) method does the -work to apply an image to an {@link android.widget.ImageView} that will be embedded in the -{@link android.widget.Gallery}. In this method, the member {@link android.content.Context} is used -to create a new {@link android.widget.ImageView}. The {@link android.widget.ImageView} is prepared -by applying an image from the local array of drawable resources, setting the {@link -android.widget.Gallery.LayoutParams} height and width for the image, setting the scale to fit the -{@link android.widget.ImageView} dimensions, and then finally setting the background to use the -styleable attribute acquired in the constructor.

        - -

        See {@link android.widget.ImageView.ScaleType} for other image scaling options.

        -
      12. - -
      13. Run the application.
      14. -
      - -

      You should see something like this:

      - - - -

      References

      -
        -
      • {@link android.widget.BaseAdapter}
      • -
      • {@link android.widget.Gallery}
      • -
      • {@link android.widget.ImageView}
      • -
      • {@link android.widget.AdapterView.OnItemClickListener}
      • -
      - - diff --git a/docs/html/resources/tutorials/views/hello-linearlayout.jd b/docs/html/resources/tutorials/views/hello-linearlayout.jd deleted file mode 100644 index 8e072b14e1823c80a4e583501b2665d2bdedc4c7..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-linearlayout.jd +++ /dev/null @@ -1,133 +0,0 @@ -page.title=Linear Layout -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      {@link android.widget.LinearLayout} is a {@link android.view.ViewGroup} that displays child -{@link android.view.View} elements in a linear direction, either vertically or horizontally.

      - -

      You should be careful about over-using the {@link android.widget.LinearLayout}. If you begin -nesting multiple {@link android.widget.LinearLayout}s, you may want to consider using a {@link -android.widget.RelativeLayout} instead.

      - -
        -
      1. Start a new project named HelloLinearLayout.
      2. -
      3. Open the res/layout/main.xml file and insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:orientation="vertical"
        -    android:layout_width="fill_parent"
        -    android:layout_height="fill_parent">
        -
        -  <LinearLayout
        -      android:orientation="horizontal"
        -      android:layout_width="fill_parent"
        -      android:layout_height="fill_parent"
        -      android:layout_weight="1">
        -      <TextView
        -          android:text="red"
        -          android:gravity="center_horizontal"
        -          android:background="#aa0000"
        -          android:layout_width="wrap_content"
        -          android:layout_height="fill_parent"
        -          android:layout_weight="1"/>
        -      <TextView
        -          android:text="green"
        -          android:gravity="center_horizontal"
        -          android:background="#00aa00"
        -          android:layout_width="wrap_content"
        -          android:layout_height="fill_parent"
        -          android:layout_weight="1"/>
        -      <TextView
        -          android:text="blue"
        -          android:gravity="center_horizontal"
        -          android:background="#0000aa"
        -          android:layout_width="wrap_content"
        -          android:layout_height="fill_parent"
        -          android:layout_weight="1"/>
        -      <TextView
        -          android:text="yellow"
        -          android:gravity="center_horizontal"
        -          android:background="#aaaa00"
        -          android:layout_width="wrap_content"
        -          android:layout_height="fill_parent"
        -          android:layout_weight="1"/>
        -  </LinearLayout>
        -	
        -  <LinearLayout
        -    android:orientation="vertical"
        -    android:layout_width="fill_parent"
        -    android:layout_height="fill_parent"
        -    android:layout_weight="1">
        -    <TextView
        -        android:text="row one"
        -        android:textSize="15pt"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:layout_weight="1"/>
        -    <TextView
        -        android:text="row two"
        -        android:textSize="15pt"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:layout_weight="1"/>
        -    <TextView
        -        android:text="row three"
        -        android:textSize="15pt"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:layout_weight="1"/>
        -    <TextView
        -        android:text="row four"
        -        android:textSize="15pt"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:layout_weight="1"/>
        -  </LinearLayout>
        -
        -</LinearLayout>
        -
        - -

        Carefully inspect this XML. There is a root {@link android.widget.LinearLayout} that defines -its orientation to be vertical—all child {@link android.view.View}s (of which it has two) will -be stacked vertically. The first child is -another {@link android.widget.LinearLayout} that uses a horizontal orientation and the second child -is a {@link android.widget.LinearLayout} that uses a vertical orientation. Each of these nested -{@link android.widget.LinearLayout}s contain several {@link android.widget.TextView} elements, which -are oriented with each other in the manner defined by their parent {@link -android.widget.LinearLayout}.

        -
      4. -
      5. Now open HelloLinearLayout.java and be sure it loads the -res/layout/main.xml layout in the -{@link android.app.Activity#onCreate(Bundle) onCreate()} method:

        -
        -public void onCreate(Bundle savedInstanceState) {
        -    super.onCreate(savedInstanceState);
        -    setContentView(R.layout.main);
        -}
        -
        -

        The {@link android.app.Activity#setContentView(int)} method loads the -layout file for the {@link android.app.Activity}, specified by the resource -ID — R.layout.main refers to the res/layout/main.xml layout -file.

        -
      6. -
      7. Run the application.
      8. -
      -

      You should see the following:

      - - -

      Notice how the XML attributes define each View's behavior. Try -experimenting with different values for android:layout_weight to see how the screen -real estate is distributed based on the weight of each element. See the Common Layout Objects -document for more about how {@link android.widget.LinearLayout} handles the -android:layout_weight attribute.

      - -

      References

      -
        -
      • {@link android.widget.LinearLayout}
      • -
      • {@link android.widget.TextView}
      • -
      - - diff --git a/docs/html/resources/tutorials/views/hello-listview.jd b/docs/html/resources/tutorials/views/hello-listview.jd deleted file mode 100644 index 194258ed838d53555da1577f449d7f35e3920139..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-listview.jd +++ /dev/null @@ -1,170 +0,0 @@ -page.title=List View -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      {@link android.widget.ListView} is a {@link android.view.ViewGroup} that creates a list of -scrollable items. The list items are automatically inserted to the list using a {@link -android.widget.ListAdapter}.

      - -

      In this tutorial, you'll create a scrollable list of country names that are read from a string array. -When a list item is selected, a toast message will display the position of the item in the list.

      - -
        -
      1. Start a new project named HelloListView.
      2. -
      3. Create an XML file named list_item.xml and save it inside the -res/layout/ folder. Insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:layout_width="fill_parent"
        -    android:layout_height="fill_parent"
        -    android:padding="10dp"
        -    android:textSize="16sp" >
        -</TextView>
        -
        -

        This file defines the layout for each item that will be placed in the {@link -android.widget.ListView}.

        -
      4. - -
      5. Open the HelloListView.java and make the class extend {@link -android.app.ListActivity} (instead of {@link android.app.Activity}): -
        public class HelloListView extends ListActivity {
        -
      6. -
      7. Insert the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} -method: -
        -@Override
        -public void onCreate(Bundle savedInstanceState) {
        -  super.onCreate(savedInstanceState);
        -
        -  setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, COUNTRIES));
        -
        -  ListView lv = getListView();
        -  lv.setTextFilterEnabled(true);
        -
        -  lv.setOnItemClickListener(new OnItemClickListener() {
        -    public void onItemClick(AdapterView<?> parent, View view,
        -        int position, long id) {
        -      // When clicked, show a toast with the TextView text
        -      Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
        -          Toast.LENGTH_SHORT).show();
        -    }
        -  });
        -}
        -
        -

        Notice that this does not load a layout file for the Activity (which you usually do with {@link -android.app.Activity#setContentView(int)}). Instead, {@link -android.app.ListActivity#setListAdapter(ListAdapter)} automatically -adds a {@link android.widget.ListView} to fill the entire screen of the {@link -android.app.ListActivity}. This method takes an {@link android.widget.ArrayAdapter}, which -manages the array of list items that will be placed into the {@link android.widget.ListView}. The -{@link android.widget.ArrayAdapter} constructor takes the application {@link -android.content.Context}, the -layout description for each list item (created in -the previous step), and a {@link java.util.List} of objects to insert in the {@link -android.widget.ListView} (defined next).

        - -

        The {@link android.widget.ListView#setTextFilterEnabled(boolean)} method turns on text filtering -for the {@link android.widget.ListView}, so that when the user begins typing, the list will be -filtered.

        - -

        The {@link android.widget.ListView#setOnItemClickListener(OnItemClickListener)} method defines -the on-click listener for each item. When an item in the {@link android.widget.ListView} is clicked, -the {@link android.widget.AdapterView.OnItemClickListener#onItemClick(AdapterView,View,int,long) -onItemClick()} method is called and a {@link android.widget.Toast} message is displayed, using the -text from the clicked item.

        - -

        Tip: You can use list item designs provided by the platform -instead of defining your own layout file for the {@link android.widget.ListAdapter}. For example, -try using android.R.layout.simple_list_item_1 instead of -R.layout.list_item.

        -
      8. - -
      9. After the {@link android.app.Activity#onCreate(Bundle) onCreate()} method, add the string -array: -
        -  static final String[] COUNTRIES = new String[] {
        -    "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
        -    "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
        -    "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
        -    "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
        -    "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
        -    "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",
        -    "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
        -    "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
        -    "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
        -    "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
        -    "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
        -    "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
        -    "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
        -    "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
        -    "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
        -    "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
        -    "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
        -    "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
        -    "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
        -    "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
        -    "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
        -    "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
        -    "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
        -    "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
        -    "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
        -    "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
        -    "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
        -    "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
        -    "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
        -    "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
        -    "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
        -    "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
        -    "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
        -    "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
        -    "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
        -    "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
        -    "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
        -    "Ukraine", "United Arab Emirates", "United Kingdom",
        -    "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
        -    "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
        -    "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
        -  };
        -
        -

        This is the array of strings that will be placed into the {@link android.widget.ListView}.

        -
      10. -
      11. Run the application.
      12. -
      -

      You can scroll the list, or type to filter it, then click an item to see a message. You -should see something like this:

      - - -

      Note that using a hard-coded string array is not the best design practice. One is -used in this tutorial for simplicity, in order to demonstrate the {@link -android.widget.ListView} widget. The better practice is to reference a string array -defined by an external resource, such as with a {@code <string-array>} -resource in your project {@code res/values/strings.xml} file. For example:

      -
      -<?xml version="1.0" encoding="utf-8"?>
      -<resources>
      -    <string-array name="countries_array">
      -        <item>Bahrain</item>
      -        <item>Bangladesh</item>
      -        <item>Barbados</item>
      -        <item>Belarus</item>
      -        <item>Belgium</item>
      -        <item>Belize</item>
      -        <item>Benin</item>
      -    </string-array>
      -</resources>
      -
      -

      To use these resource strings for the {@link android.widget.ArrayAdapter}, replace the original -{@link android.app.ListActivity#setListAdapter(ListAdapter)} line with the following:

      -
      -String[] countries = getResources().getStringArray(R.array.countries_array);
      -setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, countries));
      -
      - -

      References

      -
        -
      • {@link android.widget.ListView}
      • -
      • {@link android.widget.ListAdapter}
      • -
      - diff --git a/docs/html/resources/tutorials/views/hello-mapview.jd b/docs/html/resources/tutorials/views/hello-mapview.jd deleted file mode 100644 index 7a0bedf5dd699dfcfbca1d64072abf8e562c879f..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-mapview.jd +++ /dev/null @@ -1,303 +0,0 @@ -page.title=Google Map View -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      Using the Google Maps library, you can create your own map-viewing Activity. In this -tutorial, you'll create a simple map application in two parts. In Part 1, you'll create an app that -shows a map the user can pan and zoom. In Part 2, you'll add overlay items that mark -points of interest.

      - -
      -

      This tutorial requires that you have the external Google Maps library -installed in your SDK environment. The Maps library is included with the Google APIs -add-on, which you can install using the Android SDK and -AVD Manager. To learn how, see Adding SDK -Components.

      - -

      After installing the Google APIs add-on in your SDK, set your project properties to use the build -target called "Google APIs by Google Inc.". See the instructions for setting a build -target in -Creating and Managing Projects in Eclipse or -Creating and Managing Projects on the Command Line, as appropriate for your environment.

      - -

      You will also need to set up a new AVD that uses the same Google APIs deployment target. See Creating and Managing Virtual Devices for -more information.

      - -

      For reference material, see the Google Maps -library documentation.

      - -
      - -

      Part 1: Creating a Map Activity

      - -
        -
      1. Start a new project named HelloGoogleMaps.
      2. - -
      3. Because the Maps library is not a part of the standard Android library, you must - declare it in the Android Manifest. Open the AndroidManifest.xml - file and add the following as a child of the <application> element: -
        <uses-library android:name="com.google.android.maps" />
        -
      4. - -
      5. You also need access to the Internet in order to retrieve map tiles, - so you must also request the {@link android.Manifest.permission#INTERNET} permission. - In the manifest file, add the following as a child of the <manifest> element: -
        <uses-permission android:name="android.permission.INTERNET" />
        -
      6. - -
      7. While you're in the manifest, give the map some more space by getting rid of the title bar -with the "NoTitleBar" theme: -
        -<activity android:name=".HelloGoogleMaps" android:label="@string/app_name"
        -     android:theme="@android:style/Theme.NoTitleBar">
        -
        -
      8. - - -
      9. Open the res/layout/main.xml file and add a single - {@code com.google.android.maps.MapView} as the root node: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<com.google.android.maps.MapView
        -    xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:id="@+id/mapview"
        -    android:layout_width="fill_parent"
        -    android:layout_height="fill_parent"
        -    android:clickable="true"
        -    android:apiKey="Your Maps API Key goes here"
        -/>
        -
        -

        The android:clickable attribute defines whether you want to allow - user-interaction with the map. If this is "false" then touching the map does nothing.

        - -

        The android:apiKey attribute holds the Maps API Key for your - application, which proves your application and signer certificate has been registered with the - Maps service. This is required in order to receive the map data, even while you are - developing. Registration to the service is free and it only takes a couple - minutes to register your certificate and get a Maps API Key.

        -

        Go now to get a key. For instructions, read - Obtaining a Maps API - Key. For the purpose of this tutorial, you should register - with the SDK debug certificate, which will only be valid while your application is signed - with the debug key (once you sign with your private key, you will need a new API key). - When you get your key, insert it for the value of android:apiKey.

        -
      10. - -
      11. Now open the HelloGoogleMaps.java file. For this Activity, extend - {@code MapActivity} (instead of {@code android.app.Activity}):

        - -
        public class HelloGoogleMaps extends MapActivity {
        -

        This is a special sub-class of {@link android.app.Activity}, provided by the Maps - library, which provides important map capabilities.

        - -
      12. Inside every {@code MapActivity}, the isRouteDisplayed() method is required, so - override this method: -
        -@Override
        -protected boolean isRouteDisplayed() {
        -    return false;
        -}
        -
        -

        This method is required for some accounting from the Maps service to see if you're currently -displaying any route information. In this case, you're not, so return false.

        -
      13. - -
      14. Now add the standard {@link android.app.Activity#onCreate(Bundle) onCreate()} callback method -to the class: -
        -@Override
        -public void onCreate(Bundle savedInstanceState) {
        -    super.onCreate(savedInstanceState);
        -    setContentView(R.layout.main);
        -}
        -
        -

        This loads the layout file created above. In fact, this is now a workable application that will -display map tiles and allow the user to pan around the map. But there's no ability to zoom. -Fortunately, there's a very simple zoom feature built into the {@code MapView} class, which you can -summon with {@code setBuiltInZoomControls(boolean)}. Do this at the end of the {@link -android.app.Activity#onCreate(Bundle) onCreate()} method:

        -
        -    MapView mapView = (MapView) findViewById(R.id.mapview);
        -    mapView.setBuiltInZoomControls(true);
        -
        -
      15. -
      16. That's all there is to it. Run the application. (Remember, you must have an AVD configured to use the Google APIs -target, or be using a development device that includes the Maps library.)
      17. -
      - -

      Part 2: Adding Overlay Items

      - -

      So, now you have a map, but in many cases you'll also want to create your own map -markers and lay-overs. That's what you'll do now. In order to do so, you must implement the -{@code ItemizedOverlay} class, which can manage a whole set of {@code Overlay} (which are the -individual items placed on the map).

      - -
        -
      1. Create a new Java class named HelloItemizedOverlay that implements - {@code ItemizedOverlay}. - -

        When using Eclipse, right-click the package name in the Eclipse Package Explorer, and - select New > Class. Fill-in - the Name field as HelloItemizedOverlay. For the Superclass, enter - "com.google.android.maps.ItemizedOverlay". Click the checkbox for Constructors from - superclass. Click Finish.

      2. - -
      3. First, you need an OverlayItem {@link java.util.ArrayList}, in which you'll put - each of the OverlayItem objects you want on the map. Add this at the top of the - HelloItemizedOverlay class: - -
        private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
        -
      4. - -
      5. Now define the HelloItemizedOverlay constructors. The constructor must - define the default marker for each of the {@code OverlayItem}s. In order for the {@link - android.graphics.drawable.Drawable} to actually get drawn, it must have its bounds defined. Most - commonly, you want the center-point at the bottom of the image to be the point at which it's - attached to the map coordinates. This is handled for you with the {@code boundCenterBottom()} - method. Wrap this around our defaultMarker, so the super constructor call looks like this: -
        -public HelloItemizedOverlay(Drawable defaultMarker) {
        -  super(boundCenterBottom(defaultMarker));
        -}
        -
        -
      6. - -
      7. In order to add new {@code OverlayItem}s to the ArrayList, you need a new method: -
        -public void addOverlay(OverlayItem overlay) {
        -    mOverlays.add(overlay);
        -    populate();
        -}
        -

        Each time you add a new {@code OverlayItem} to the ArrayList, you must call - populate() for the {@code ItemizedOverlay}, which will read each of the - {@code OverlayItem}s and prepare them to be drawn.

        -
      8. - -
      9. When the populate() method executes, it will call createItem(int) in - the {@code ItemizedOverlay} to retrieve each {@code OverlayItem}. You must override this method to - properly read from the ArrayList and return the {@code OverlayItem} from the position specified - by the given integer. Your override method should look like this: - -
        -@Override
        -protected OverlayItem createItem(int i) {
        -  return mOverlays.get(i);
        -}
        -
        -
      10. - -
      11. You must also override the size() method to return the current number of - items in the ArrayList: -
        -@Override
        -public int size() {
        -  return mOverlays.size();
        -}
        -
        -
      12. - -
      13. Now set up the ability to handle touch events on the overlay items. First, you're - going to need a reference to the application {@link android.content.Context} as a member of - this class. So add {@code Context mContext} as a class member, then initialize it with a - new class constructor: -
        -public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
        -  super(boundCenterBottom(defaultMarker));
        -  mContext = context;
        -}
        -
        -

        This passes the {@code defaultMarker} up to the default constructor to bound its coordinates - and then initialize {@code mContext} with the given {@link android.content.Context}.

        - -

        Then override the {@code onTap(int)} callback method, which will handle the event - when an item is tapped by the user:

        -
        -@Override
        -protected boolean onTap(int index) {
        -  OverlayItem item = mOverlays.get(index);
        -  AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
        -  dialog.setTitle(item.getTitle());
        -  dialog.setMessage(item.getSnippet());
        -  dialog.show();
        -  return true;
        -}
        -
        -

        This uses the member {@code android.content.Context} to create a new {@link -android.app.AlertDialog.Builder} and uses the tapped {@code OverlayItem}'s title and snippet for -the dialog's title and message text. (You'll see the {@code OverlayItem} title and snippet defined -when you create it below.)

        -
      14. - -
      - -

      You're now done with the HelloItemizedOverlay class and can start using it -to add items on the map.

      - -

      Go back to the HelloGoogleMaps class. In the following procedure, you'll create an -{@code OverlayItem} and add it to an instance of the HelloItemizedOverlay class, then -add the HelloItemizedOverlay to the MapView using a {@code GeoPoint} -to define its coordinates on the map.

      - - -
        -
      1. First, you need the image for the map overlay. If you don't have one handy, use the Android on - the right. Drag this image (or your own) into the res/drawable/ directory of your - project.
      2. - -
      3. At the end of your existing {@code onCreate()} method, instantiate : - -
        -List<Overlay> mapOverlays = mapView.getOverlays();
        -Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker);
        -HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable, this);
        - -

        All overlay elements on a map are held by the {@code MapView}, so when you want to add some, - you have to get a list from the getOverlays() method. Then instantiate the {@link - android.graphics.drawable.Drawable} used for the map marker, which was saved in the {@code - res/drawable/} directory. The constructor for {@code HelloItemizedOverlay} (your custom {@code - ItemizedOverlay}) takes the Drawable in order to set the default marker for all overlay - items.

        -
      4. - -
      5. Now create a {@code GeoPoint} that defines the map coordinates for the first overlay item, - and pass it to a new {@code OverlayItem}: -
        -GeoPoint point = new GeoPoint(19240000,-99120000);
        -OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "I'm in Mexico City!");
        -
        - -

        {@code GeoPoint} coordinates are specified in microdegrees (degrees * 1e6). The - {@code OverlayItem} constructor accepts the {@code GeoPoint} location, a string for the - item's title, and a string for the item's snippet text, respectively.

        -
      6. - -
      7. All that's left is to add this {@code OverlayItem} to your collection in the - {@code HelloItemizedOverlay} instance, then add the {@code HelloItemizedOverlay} to the MapView: -
        -itemizedoverlay.addOverlay(overlayitem);
        -mapOverlays.add(itemizedoverlay);
        -
        -
      8. - -
      9. Now run the application.
      10. -
      - -

      You should see the following:

      - -

      When you tap the overlay item, you'll see the dialog appear.

      - -

      Because the {@code ItemizedOverlay} class uses an {@code java.util.ArrayList} for all of the -{@code OverlayItem}s, it's easy to add more. Try adding another one. Before the -addOverlay() method is called, add these lines:

      -
      -GeoPoint point2 = new GeoPoint(35410000, 139460000);
      -OverlayItem overlayitem2 = new OverlayItem(point2, "Sekai, konichiwa!", "I'm in Japan!");
      -
      -

      Run the application again. (You probably need to move the map to find the new overlay item.)

      - diff --git a/docs/html/resources/tutorials/views/hello-relativelayout.jd b/docs/html/resources/tutorials/views/hello-relativelayout.jd deleted file mode 100644 index adc117946d21a526fd5bc7999954de465a66aa1c..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-relativelayout.jd +++ /dev/null @@ -1,89 +0,0 @@ -page.title=Relative Layout -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      {@link android.widget.RelativeLayout} is a {@link android.view.ViewGroup} that displays -child {@link android.view.View} elements in relative positions. The position of a {@link -android.view.View} can be specified as relative to sibling elements (such as to the left-of or below -a given element) or in positions relative to the {@link android.widget.RelativeLayout} area (such as -aligned to the bottom, left of center).

      - -

      A {@link android.widget.RelativeLayout} is a very powerful utility for designing a user -interface because it can eliminate nested {@link android.view.ViewGroup}s. If you find -yourself using several nested {@link android.widget.LinearLayout} groups, you may be able to -replace them with a single {@link android.widget.RelativeLayout}.

      - -
        -
      1. Start a new project named HelloRelativeLayout.
      2. -
      3. Open the res/layout/main.xml file and insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:layout_width="fill_parent"
        -    android:layout_height="fill_parent">
        -    <TextView
        -        android:id="@+id/label"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:text="Type here:"/>
        -    <EditText
        -        android:id="@+id/entry"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:background="@android:drawable/editbox_background"
        -        android:layout_below="@id/label"/>
        -    <Button
        -        android:id="@+id/ok"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:layout_below="@id/entry"
        -        android:layout_alignParentRight="true"
        -        android:layout_marginLeft="10dip"
        -        android:text="OK" />
        -    <Button
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:layout_toLeftOf="@id/ok"
        -        android:layout_alignTop="@id/ok"
        -        android:text="Cancel" />
        -</RelativeLayout>
        -
        -

        Notice each of the android:layout_* attributes, such as layout_below, -layout_alignParentRight, and layout_toLeftOf. When using a {@link -android.widget.RelativeLayout}, you can use these attributes to describe -how you want to position each {@link android.view.View}. Each one of these attributes define a -different kind -of relative position. Some attributes use the resource ID of a sibling {@link android.view.View} -to define its own relative position. For example, the last {@link android.widget.Button} is -defined to lie to the left-of and aligned-with-the-top-of the {@link android.view.View} -identified by the ID ok (which is the previous {@link android.widget.Button}).

        -

        All of the available layout attributes are defined in {@link -android.widget.RelativeLayout.LayoutParams}.

        -
      4. -
      5. Make sure you load this layout in the -{@link android.app.Activity#onCreate(Bundle) onCreate()} method:

        -
        -public void onCreate(Bundle savedInstanceState) {
        -    super.onCreate(savedInstanceState);
        -    setContentView(R.layout.main);
        -}
        -
        -

        The {@link android.app.Activity#setContentView(int)} method loads the -layout file for the {@link android.app.Activity}, specified by the resource -ID — R.layout.main refers to the res/layout/main.xml layout -file.

        -
      6. -
      7. Run the application.
      8. -
      -

      You should see the following layout:

      - - -

      Resources

      -
        -
      • {@link android.widget.RelativeLayout}
      • -
      • {@link android.widget.RelativeLayout.LayoutParams}
      • -
      • {@link android.widget.TextView}
      • -
      • {@link android.widget.EditText}
      • -
      • {@link android.widget.Button}
      • -
      diff --git a/docs/html/resources/tutorials/views/hello-spinner.jd b/docs/html/resources/tutorials/views/hello-spinner.jd deleted file mode 100644 index e9dc20fb7ba898014533dc31368412c270cbf199..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-spinner.jd +++ /dev/null @@ -1,149 +0,0 @@ -page.title=Spinner -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      {@link android.widget.Spinner} is a widget similar to a drop-down list for selecting items.

      - -

      In this tutorial, you'll create -a simple spinner widget that displays a list of planets. When one is selected, a toast message -will display the selected item.

      - -
        -
      1. Start a new project named HelloSpinner.
      2. -
      3. Open the res/layout/main.xml file and insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:orientation="vertical"
        -    android:padding="10dip"
        -    android:layout_width="fill_parent"
        -    android:layout_height="wrap_content">
        -    <TextView
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:layout_marginTop="10dip"
        -        android:text="@string/planet_prompt"
        -    />
        -    <Spinner 
        -        android:id="@+id/spinner"
        -        android:layout_width="fill_parent"
        -        android:layout_height="wrap_content"
        -        android:prompt="@string/planet_prompt"
        -    />
        -</LinearLayout>
        -
        -

        Notice that the {@link android.widget.TextView}'s android:text attribute and the -{@link android.widget.Spinner}'s android:prompt attribute both reference the same -string resource. This text behaves as a title for the widget. When applied to the {@link -android.widget.Spinner}, the title text will appear -in the selection dialog that appears upon selecting the widget.

        -
      4. - -
      5. Create a strings.xml file in res/values/ and edit the file to look -like this: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<resources>
        -    <string name="planet_prompt">Choose a planet</string>
        -    <string-array name="planets_array">
        -        <item>Mercury</item>
        -        <item>Venus</item>
        -        <item>Earth</item>
        -        <item>Mars</item>
        -        <item>Jupiter</item>
        -        <item>Saturn</item>
        -        <item>Uranus</item>
        -        <item>Neptune</item>
        -    </string-array>
        -</resources>
        -
        -

        The {@code <string>} element defines the title string referenced by the {@link -android.widget.TextView} and {@link android.widget.Spinner} in the layout above. The {@code -<string-array} element defines the list of strings that will be displayed as the list in -the {@link android.widget.Spinner} widget.

        -
      6. - -
      7. Now open the HelloSpinner.java file and insert the following code for the {@link -android.app.Activity#onCreate(Bundle) onCreate()} method: -
        -@Override
        -public void onCreate(Bundle savedInstanceState) {
        -    super.onCreate(savedInstanceState);
        -    setContentView(R.layout.main);
        -
        -    Spinner spinner = (Spinner) findViewById(R.id.spinner);
        -    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
        -            this, R.array.planets_array, android.R.layout.simple_spinner_item);
        -    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        -    spinner.setAdapter(adapter);
        -}
        -
        -

        After the {@code main.xml} layout is set as the content view, the {@link -android.widget.Spinner} widget is captured from the layout with {@link -android.app.Activity#findViewById(int)}. The {@link -android.widget.ArrayAdapter#createFromResource(Context,int,int) createFromResource()} method then -creates a new {@link android.widget.ArrayAdapter}, which binds each item in the string array -to the initial appearance for the {@link android.widget.Spinner} (which is how each item will -appear in the spinner when selected). The {@code -R.array.planets_array} ID references the {@code string-array} defined above and the -{@code android.R.layout.simple_spinner_item} ID references a layout for the standard spinner -appearance, defined by the platform. Then {@link -android.widget.ArrayAdapter#setDropDownViewResource(int)} is called to define the appearance for -each item when the widget is opened ({@code simple_spinner_dropdown_item} is -another standard layout defined by the platform). Finally, the {@link android.widget.ArrayAdapter} -is set to associate all of its items with the {@link android.widget.Spinner} by calling {@link -android.widget.AdapterView#setAdapter(T)}.

        -
      8. - -
      9. Now create a nested class that implements {@link -android.widget.AdapterView.OnItemSelectedListener}. This will provide a callback method that will -notify your application when an item has been selected from the {@link -android.widget.Spinner}. Here's what this class should look like: -
        -public class MyOnItemSelectedListener implements OnItemSelectedListener {
        -
        -    public void onItemSelected(AdapterView<?> parent,
        -        View view, int pos, long id) {
        -      Toast.makeText(parent.getContext(), "The planet is " +
        -          parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
        -    }
        -
        -    public void onNothingSelected(AdapterView parent) {
        -      // Do nothing.
        -    }
        -}
        -
        -

        The {@link android.widget.AdapterView.OnItemSelectedListener} requires the {@link -android.widget.AdapterView.OnItemSelectedListener#onItemSelected(AdapterView,View,int,long) -onItemSelected()} and {@link -android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(AdapterView) -onNothingSelected()} callback methods. The former is called when an item from the {@link -android.widget.AdapterView} is selected, in which case, a short {@link android.widget.Toast} -message displays the selected text; and the latter is called when a selection disappears from the -{@link android.widget.AdapterView}, which doesn't happen in this case, so it's ignored.

        -
      10. - -
      11. Now the {@code MyOnItemSelectedListener} needs to be applied to the {@link -android.widget.Spinner}. Go back to the {@link android.app.Activity#onCreate(Bundle) onCreate()} -method and add the following line to the end: -
        -    spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
        -
        -

        This creates a new anonymous instance of the {@code MyOnItemSelectedListener} and sets it as the -listener for the {@link android.widget.Spinner}.

        -
      12. - -
      13. Run the application.
      14. -
      -

      It should look like this:

      - - - -

      Resources

      -
        -
      • {@link android.R.layout}
      • -
      • {@link android.widget.ArrayAdapter}
      • -
      • {@link android.widget.Spinner}
      • -
      - diff --git a/docs/html/resources/tutorials/views/hello-timepicker.jd b/docs/html/resources/tutorials/views/hello-timepicker.jd deleted file mode 100644 index cf16c8ecd32ab697a50a469aab96369b20a2a371..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-timepicker.jd +++ /dev/null @@ -1,167 +0,0 @@ -page.title=Time Picker -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      To provide a widget for selecting a time, use the {@link android.widget.TimePicker} -widget, which allows the user to select the hour and minute in a familiar interface.

      - -

      In this tutorial, you'll create a {@link android.app.TimePickerDialog}, which presents the -time picker in a floating dialog box at the press of a button. When the time is set by -the user, a {@link android.widget.TextView} will update with the new date.

      - -
        -
      1. Start a new project named HelloTimePicker.
      2. -
      3. Open the res/layout/main.xml file and insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:layout_width="wrap_content"
        -    android:layout_height="wrap_content"
        -    android:orientation="vertical">
        -    <TextView android:id="@+id/timeDisplay"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:text=""/>
        -    <Button android:id="@+id/pickTime"
        -        android:layout_width="wrap_content"
        -        android:layout_height="wrap_content"
        -        android:text="Change the time"/>
        -</LinearLayout>
        -
        -

        This is a basic {@link android.widget.LinearLayout} with a {@link android.widget.TextView} -that will display the time and a {@link android.widget.Button} that will open the {@link -android.app.TimePickerDialog}.

        -
      4. - -
      5. Open HelloTimePicker.java and insert the following class members: -
        -    private TextView mTimeDisplay;
        -    private Button mPickTime;
        -
        -    private int mHour;
        -    private int mMinute;
        -
        -    static final int TIME_DIALOG_ID = 0;
        -
        -

        This declares variables for the layout elements and time fields. -The TIME_DIALOG_ID is a static integer that uniquely identifies the dialog.

        -
      6. -
      7. Now insert the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} -method: -
        -    @Override
        -    protected void onCreate(Bundle savedInstanceState) {
        -        super.onCreate(savedInstanceState);
        -        setContentView(R.layout.main);
        -
        -        // capture our View elements
        -        mTimeDisplay = (TextView) findViewById(R.id.timeDisplay);
        -        mPickTime = (Button) findViewById(R.id.pickTime);
        -
        -        // add a click listener to the button
        -        mPickTime.setOnClickListener(new View.OnClickListener() {
        -            public void onClick(View v) {
        -                showDialog(TIME_DIALOG_ID);
        -            }
        -        });
        -
        -        // get the current time
        -        final Calendar c = Calendar.getInstance();
        -        mHour = c.get(Calendar.HOUR_OF_DAY);
        -        mMinute = c.get(Calendar.MINUTE);
        -
        -        // display the current date
        -        updateDisplay();
        -    }
        -
        - -

        First, the content is set to the main.xml layout and then the {@link -android.widget.TextView} and {@link android.widget.Button} are captured with {@link -android.app.Activity#findViewById(int)}. -Then an {@link android.view.View.OnClickListener} is created for the {@link android.widget.Button}, -so that when clicked, it will call {@link -android.app.Activity#showDialog(int)}, passing the unique integer ID for the time picker -dialog. Using {@link android.app.Activity#showDialog(int)} allows the {@link -android.app.Activity} to manage the life-cycle of the dialog and will call the {@link -android.app.Activity#onCreateDialog(int)} callback method to request the {@link android.app.Dialog} -that should be displayed (which you'll define later). After the on-click listener is set, a new -{@link java.util.Calendar} is created to get the current hour and minute. Finally, the -private updateDisplay() method is called in order to fill the {@link -android.widget.TextView} with the current time.

        -
      8. - -
      9. Add the updateDisplay() and pad() methods: -
        -// updates the time we display in the TextView
        -private void updateDisplay() {
        -    mTimeDisplay.setText(
        -        new StringBuilder()
        -                .append(pad(mHour)).append(":")
        -                .append(pad(mMinute)));
        -}
        -
        -private static String pad(int c) {
        -    if (c >= 10)
        -        return String.valueOf(c);
        -    else
        -        return "0" + String.valueOf(c);
        -}
        -
        -

        The updateDisplay() method uses the member fields for the time and inserts them in -the mTimeDisplay {@link android.widget.TextView}. The pad() method returns -the appropriate string representation of the hour or minute—it will prefix a zero to the -number if it's a single digit.

        -
      10. - -
      11. Add a class member for a {@link android.app.TimePickerDialog.OnTimeSetListener} that will be -called when the user sets a new time: -
        -// the callback received when the user "sets" the time in the dialog
        -private TimePickerDialog.OnTimeSetListener mTimeSetListener =
        -    new TimePickerDialog.OnTimeSetListener() {
        -        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        -            mHour = hourOfDay;
        -            mMinute = minute;
        -            updateDisplay();
        -        }
        -    };
        -
        -

        When the user is done setting the time (clicks the "Set" button), the -onTimeSet() method is called and it updates the member fields with -the new time and updates the layout's {@link android.widget.TextView}.

        -
      12. - -
      13. Add the {@link android.app.Activity#onCreateDialog(int)} callback method: -
        -@Override
        -protected Dialog onCreateDialog(int id) {
        -    switch (id) {
        -    case TIME_DIALOG_ID:
        -        return new TimePickerDialog(this,
        -                mTimeSetListener, mHour, mMinute, false);
        -    }
        -    return null;
        -}
        -
        -

        This is an {@link android.app.Activity} callback that is passed the identifier you passed to -{@link android.app.Activity#showDialog(int)}, in the {@link android.widget.Button}'s on-click -listener. When the ID matches, this initializes the {@link android.app.TimePickerDialog} with the -member variables initialized at the end of onCreate() and the {@link -android.app.TimePickerDialog.OnTimeSetListener} created in the previous step.

        -
      14. - -
      15. Run the application.
      16. -
      -

      When you press the "Change the time" button, you should see the following:

      - - -

      References

      -
        -
      1. {@link android.widget.TimePicker}
      2. -
      3. {@link android.app.TimePickerDialog.OnTimeSetListener}
      4. -
      5. {@link android.widget.Button}
      6. -
      7. {@link android.widget.TextView}
      8. -
      9. {@link java.util.Calendar}
      10. -
      - diff --git a/docs/html/resources/tutorials/views/hello-webview.jd b/docs/html/resources/tutorials/views/hello-webview.jd deleted file mode 100644 index f6a6a7188b26728f254bc92d3b8f83677fb90d76..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/hello-webview.jd +++ /dev/null @@ -1,131 +0,0 @@ -page.title=Web View -parent.title=Hello, Views -parent.link=index.html -@jd:body - -

      {@link android.webkit.WebView} allows you to create your own window for viewing web pages (or even -develop a complete browser). In this tutorial, you'll create a simple {@link android.app.Activity} -that can view and navigate web pages.

      - -
        -
      1. Create a new project named HelloWebView.
      2. -
      3. Open the res/layout/main.xml file and insert the following: -
        -<?xml version="1.0" encoding="utf-8"?>
        -<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
        -    android:id="@+id/webview"
        -    android:layout_width="fill_parent"
        -    android:layout_height="fill_parent"
        -/>
        -
        -
      4. - -
      5. Now open the HelloWebView.java file. - At the top of the class, declare a {@link android.webkit.WebView} object: -
        WebView mWebView;
        -

        Then use the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} - method:

        -
        -public void onCreate(Bundle savedInstanceState) {
        -    super.onCreate(savedInstanceState);
        -    setContentView(R.layout.main);
        -
        -    mWebView = (WebView) findViewById(R.id.webview);
        -    mWebView.getSettings().setJavaScriptEnabled(true);
        -    mWebView.loadUrl("http://www.google.com");
        -}
        -
        -

        This initializes the member {@link android.webkit.WebView} with the one from the - {@link android.app.Activity} layout; requests a {@link android.webkit.WebSettings} object with - {@link android.webkit.WebView#getSettings()}; and enables JavaScript for the {@link - android.webkit.WebView} with {@link android.webkit.WebSettings#setJavaScriptEnabled(boolean)}. - Finally, an initial web page is loaded with {@link - android.webkit.WebView#loadUrl(String)}.

        -
      6. - -
      7. Because this application needs access to the Internet, you need to add the appropriate - permissions to the Android manifest file. Open the AndroidManifest.xml file - and add the following as a child of the <manifest> element: - -
        <uses-permission android:name="android.permission.INTERNET" />
      8. - -
      9. While you're in the manifest, give some more space for web pages by removing the title - bar, with the "NoTitleBar" theme: -
        -<activity android:name=".HelloWebView" android:label="@string/app_name"
        -     android:theme="@android:style/Theme.NoTitleBar">
        -
        -
      10. - -
      11. Now run the application. -

        You now have a simplest web page viewer. - It's not quite a browser yet because as soon as you click a link, the default Android Browser - handles the Intent to view a web page, because this {@link android.app.Activity} isn't - technically enabled to do so. Instead of adding an intent filter to view web pages, you can - override the {@link android.webkit.WebViewClient} class and enable this {@link - android.app.Activity} to handle its own URL requests.

        -
      12. - -
      13. In the HelloAndroid Activity, add this nested class: -
        -private class HelloWebViewClient extends WebViewClient {
        -    @Override
        -    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        -        view.loadUrl(url);
        -        return true;
        -    }
        -}
        -
        -
      14. -
      15. Then towards the end of the {@link android.app.Activity#onCreate(Bundle)} method, set an - instance of the HelloWebViewClient as the {@link android.webkit.WebViewClient}: -
        mWebView.setWebViewClient(new HelloWebViewClient());
        - -

        This line can go anywhere following the initialization of the {@link - android.webkit.WebView} object.

        -

        This creates a {@link android.webkit.WebViewClient} that will load any URL selected from this - {@link android.webkit.WebView} into the same {@link android.webkit.WebView}. The - {@link android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String)} method is passed -the current {@link android.webkit.WebView} and the URL requested, so all it needs to do is load -the URL in the given view. Returning true says that the method has handled the URL -and the event should not propagate (in which case, an Intent would be created that's handled by -the Browser application).

        -

        If you run the application again, new pages will now load in this Activity. - However, you can't navigate back to previous pages. To do this, you need to handle the BACK - button on the device, so that it will return to the previous page, rather than exit the - application.

        -
      16. - -
      17. To handle the BACK button key press, add the following method inside the - HelloWebView Activity: -
         
        -@Override
        -public boolean onKeyDown(int keyCode, KeyEvent event) {
        -    if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
        -        mWebView.goBack();
        -        return true;
        -    }
        -    return super.onKeyDown(keyCode, event);
        -}
        -
        -

        This {@link android.app.Activity#onKeyDown(int,KeyEvent)} callback method will be called - anytime a button is pressed while in the Activity. The condition inside uses the {@link - android.view.KeyEvent} to check whether the key pressed is the BACK button and whether the - {@link android.webkit.WebView} is actually capable of navigating back (if it has a history). If - both are true, then the {@link android.webkit.WebView#goBack()} method is called, - which will navigate back one step in the {@link android.webkit.WebView} - history.Returning true indicates that the event has been handled. If this condition - is not met, then the event is sent back to the system.

        -
      18. -
      19. Run the application again. You'll now be able to follow links and navigate back through the -page history.
      20. -
      -

      When you open the application, it should look like this:

      - - -

      Resource

      -
        -
      • {@link android.webkit.WebView}
      • -
      • {@link android.webkit.WebViewClient}
      • -
      • {@link android.view.KeyEvent}
      • -
      diff --git a/docs/html/resources/tutorials/views/images/android.png b/docs/html/resources/tutorials/views/images/android.png deleted file mode 100755 index 39a1ac729394b5f97674af47e2c04f37baf6be90..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/android.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/androidmarker.png b/docs/html/resources/tutorials/views/images/androidmarker.png deleted file mode 100755 index 8c43d4668218c55294e23d28b7f5872bc1dc2257..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/androidmarker.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-autocomplete.png b/docs/html/resources/tutorials/views/images/hello-autocomplete.png deleted file mode 100644 index 0b3e6803bb1fbc2c3b4ea5b68ec4c8cc30a314dd..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-autocomplete.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-datepicker.png b/docs/html/resources/tutorials/views/images/hello-datepicker.png deleted file mode 100755 index 2075066bfdc17e38f02d8705509dd337d2e59ef7..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-datepicker.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-formstuff.png b/docs/html/resources/tutorials/views/images/hello-formstuff.png deleted file mode 100644 index 949319f7c2d407684863e7e5ffe8139c2f473b5b..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-formstuff.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-gallery.png b/docs/html/resources/tutorials/views/images/hello-gallery.png deleted file mode 100755 index 22d1eaf6d145d8769e900143d3e11cc7999bf137..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-gallery.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-gridview.png b/docs/html/resources/tutorials/views/images/hello-gridview.png deleted file mode 100755 index 2def0df666a4490300b0e4310764d36849d4f972..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-gridview.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-linearlayout.png b/docs/html/resources/tutorials/views/images/hello-linearlayout.png deleted file mode 100755 index dfef819ef9d188439eecbdea0e8ab2f4bc5a6882..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-linearlayout.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-relativelayout.png b/docs/html/resources/tutorials/views/images/hello-relativelayout.png deleted file mode 100755 index ec4d9d44b0c6ff50035765b38d1ecdc301f0964f..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-relativelayout.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-spinner.png b/docs/html/resources/tutorials/views/images/hello-spinner.png deleted file mode 100755 index 42e2a915cb47f1e21f2f69640c7a88aeaba2865a..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-spinner.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-tablelayout.png b/docs/html/resources/tutorials/views/images/hello-tablelayout.png deleted file mode 100755 index 3d80e7f8a55a8a0d0388bfb122fa6be03634cade..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-tablelayout.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/images/hello-timepicker.png b/docs/html/resources/tutorials/views/images/hello-timepicker.png deleted file mode 100755 index bd5a1eeadaae59fd84601092564bee83f86feeb8..0000000000000000000000000000000000000000 Binary files a/docs/html/resources/tutorials/views/images/hello-timepicker.png and /dev/null differ diff --git a/docs/html/resources/tutorials/views/index.jd b/docs/html/resources/tutorials/views/index.jd deleted file mode 100644 index bba833070958d9564f1312875ddf9a7c48a0371e..0000000000000000000000000000000000000000 --- a/docs/html/resources/tutorials/views/index.jd +++ /dev/null @@ -1,121 +0,0 @@ -page.title=Hello, Views -parent.title=Tutorials -parent.link=../../browser.html?tag=tutorial -@jd:body - - - -

      This is a collection of "Hello World"-style tutorials designed -to get you started quickly with common Android layouts and widgets.

      - -

      A certain amount of knowledge is assumed for these tutorials. Before you start, -you should have completed the Hello, -World tutorial—it will teach you several things about basic -Android development. More specifically, you should know:

      -
        -
      • How to create an Android project and run it
      • -
      • The basic structure of an Android project (resource files, layout files, etc.)
      • -
      • The basic components of an {@link android.app.Activity}
      • -
      - -

      Note: In order to make these tutorials as simple as possible, -some code may not conform to best practices for coding Android applications. In particular, -hard-coded strings are used in places, when the better practice is to reference strings from a -res/values/strings.xml resource file.

      - -

      Tip: After you have pasted sample code into an Eclipse project, -press Ctrl (or Cmd) + Shift + O to import the required packages.

      - -

      Layouts

      - - - - - - - -
      -Grid View
      - -
      - - - -
      -List View
      - -
      - -

       

      - -

      Widgets & Other Views

      - - - - - - - -
      -Spinner
      - -
      - - - -
      -Gallery
      - -
      - - - -
      -Web View
      - -
      - - -

      -There are plenty more layouts and widgets available. See the {@link android.view.View} class -for more on View layouts, and the {@link android.widget widget package} -for more useful widgets. And for more raw code samples, visit the -Api -Demos.

      - diff --git a/docs/html/sdk/OLD_RELEASENOTES.jd b/docs/html/sdk/OLD_RELEASENOTES.jd index 77516818c047a9e112e0c3c3c54857ca6db04fbb..6865db235c0bb3ac9d594204974c5d7d1dc4f7c9 100644 --- a/docs/html/sdk/OLD_RELEASENOTES.jd +++ b/docs/html/sdk/OLD_RELEASENOTES.jd @@ -173,9 +173,9 @@ specify which port the emulator should bind to for the console. <port> mus

      The SDK includes several new development tools, such as

        -
      • HierarchyViewer is a visual tool for inspecting and debugging your user interfaces and layout.
      • -
      • Draw 9-patch allows you to easily create a NinePatch graphic using a WYSIWYG editor.
      • -
      • The UI/Application Exerciser Monkey generates pseudo-random system and user events, for testing your application.
      • +
      • HierarchyViewer is a visual tool for inspecting and debugging your user interfaces and layout.
      • +
      • Draw 9-patch allows you to easily create a NinePatch graphic using a WYSIWYG editor.
      • +
      • The UI/Application Exerciser Monkey generates pseudo-random system and user events, for testing your application.

      Application Signing @@ -326,7 +326,7 @@ specify which port the emulator should bind to for the console. <port> mus

      traceview

        -
      • The traceview tool is now included in the SDK.
      • +
      • The traceview tool is now included in the SDK.

      Resolved Issues

      @@ -387,13 +387,13 @@ specify which port the emulator should bind to for the console. <port> mus
      • Now provides support for emulating inbound SMS messages. The ADT plugin and DDMS provide integrated access to this capability. For more information about how to emulate inbound SMS from the console, -see SMS Emulation.
      • +see SMS Emulation.

      Emulator

      • The default emulator skin has been changed to HVGA-P from QVGA-L. For information about emulator skins and how to load a specific skin when starting the emulator, see -Using Emulator Skins.
      • +Using Emulator Skins.

      Resolved Issues

      diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd index 91eb57f48582be2080d59ca172ac541334bd7036..c7ece4230b1b807cdfef79c7f95105efa38ade5b 100644 --- a/docs/html/sdk/RELEASENOTES.jd +++ b/docs/html/sdk/RELEASENOTES.jd @@ -37,15 +37,15 @@ now available from the "SDK" tab, under "Downloadable SDK Components."

      To get started with the SDK, review the Quick Start summary on the Android SDK download page or read Installing the SDK for detailed +href="{@docRoot}sdk/installing/index.html">Installing the SDK for detailed installation instructions.

      @@ -64,7 +64,7 @@ changes include:

      skins.
    1. Android SDK and AVD Manager, a graphical UI to let you manage your SDK and AVD environments more easily. The tool lets you create and manage -your Android Virtual +your Android Virtual Devices and download new SDK packages (such as platform versions and add-ons) into your environment.
    2. Improved support for test packages in New Project Wizard
    3. @@ -72,7 +72,7 @@ add-ons) into your environment. capability that lets you display only the parts of the API that are actually available to your application, based on the android:minSdkVersion value the application declares in its manifest. For more information, see -Android API Levels +Android API Levels

      For details about the Android platforms included in the SDK — including @@ -109,7 +109,7 @@ Plugin (0.9.3 or higher).

      The new version of ADT is downloadable from the usual remote update site or is separately downloadable as a .zip archive. For instructions on how to download the plugin, please see ADT Plugin for Eclipse.

      +href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin for Eclipse.

      Android SDK and AVD Manager

      @@ -222,7 +222,7 @@ skins, including:

      density for each skin, to create any combination of resolution/density (WVGA with medium density, for instance). To do so, use the android tool command line to create a new AVD that uses a custom hardware configuration. See -Creating an +Creating an AVD for more information.

      Other Notes and Resolved Issues

      @@ -330,7 +330,7 @@ changes include:

      Android 1.5). The tools are updated to let you deploy your application on any platform in the SDK, which helps you ensure forward-compatibility and, if applicable, backward-compatibility. -
    4. Introduces Android +
    5. Introduces Android Virtual Devices — (AVD) configurations of options that you run in the emulator to better model actual devices. Each AVD gets its own dedicated storage area, making it much easier to work with multiple emulators @@ -352,7 +352,7 @@ Android project.
    6. For details about the Android platforms included in the SDK — including bug fixes, features, and API changes — please read the Android 1.5 version notes.

      +href="{@docRoot}about/versions/android-1.5.html">Android 1.5 version notes.

      Installation and Upgrade Notes

      @@ -407,7 +407,7 @@ that can run in the emulator. available to use.

      For more information about AVDs, see Creating and Managing Virtual Devices +href="{@docRoot}tools/devices/index.html">Creating and Managing Virtual Devices

      Other Notes

      @@ -491,7 +491,7 @@ as well as a few minor API changes from the 1.0 version.

      For details about the Android 1.1 system image included in the SDK — including bug fixes, features, and API changes — please read the Android 1.1 version notes.

      +href="{@docRoot}about/versions/android-1.1.html">Android 1.1 version notes.

      App Versioning for Android 1.1

      @@ -545,7 +545,7 @@ testing.

      Plugin for Eclipse is 0.8.0. If you are using a previous version of ADT, you should update to the latest version for use with this SDK. For information about how to update your ADT plugin, see -ADT Plugin for Eclipse.

      +ADT Plugin for Eclipse.

      Installation and Upgrade Notes

      @@ -585,7 +585,7 @@ these USB drivers that you can install, to let you develop on the device:

      The USB driver files are located in the <SDK>/usb_driver directory. For details and installation instructions, see Connecting Hardware Devices.

      +href="{@docRoot}tools/device.html#setting-up">Connecting Hardware Devices.

      Resolved Issues, Changes

      @@ -650,7 +650,7 @@ added.

      Development Tools (ADT) Plugin for Eclipse is 0.8.0. If you are using a previous version of ADT, you should update to the latest version for use with this SDK. For information about how to update your ADT plugin, see ADT Plugin for Eclipse.

      +href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin for Eclipse.

      Other Notes

      diff --git a/docs/html/sdk/adding-components.jd b/docs/html/sdk/adding-components.jd deleted file mode 100644 index 599b2a831f62c8ed41a44bed113c5aad5354c0e9..0000000000000000000000000000000000000000 --- a/docs/html/sdk/adding-components.jd +++ /dev/null @@ -1,209 +0,0 @@ -page.title=Adding SDK Packages -@jd:body - - -
      -
      -

      Quickview

      -
        -
      • Use the Android SDK Manager to - set up your SDK and keep it up-to-date.
      • -
      - -

      In this document

      -
        -
      1. Launching the Android SDK Manager -
      2. Installing SDK Packages -
      3. Updating SDK Packages -
      4. Package Dependencies
      5. -
      6. Adding New Sites
      7. -
      8. Troubleshooting
      9. -
      -
      -
      - -

      Adding and updating packages in your Android SDK is fast and easy. To add or -update the individual SDK packages that you need, use the Android SDK -Manager (included in the SDK Tools).

      - -

      It only takes a couple of clicks to install individual versions of the -Android platform, new development tools, new documentation, and SDK add-ons. The -new SDK packages are automatically installed into your existing SDK directory, -so you don't need to update your development environment to specify a new SDK -location.

      - -

      If you're setting up your Android SDK for the first time, -see Installing the SDK for information about -what packages to install.

      - -

      Note: If you develop in Eclipse, you might also need -to update your ADT plugin when you update your development tools. See the revisions listed in the -ADT Plugin for Eclipse document.

      - - -

      Figure 1. The Android SDK Manager's -Available Packages panel, which shows the SDK packages that are -available for you to download into your environment.

      -
    - -

    Launching the Android SDK Manager

    - -

    The Android SDK Manager is the tool that you use to install and -upgrade SDK packages in your development environment.

    - -

    You can launch the Android SDK Manager in one of the following ways.

    - -

    Launching from Eclipse/ADT

    - -

    If you are developing in Eclipse and have already installed the ADT Plugin, -follow these steps to access the Android SDK Manager tool:

    - -
      -
    1. Open Eclipse
    2. -
    3. Select Window > Android SDK -Manager.
    4. -
    - -

    Launching from the SDK Manager script (Windows only)

    - -

    For Windows only, the SDK includes a script that invokes the Android SDK Manager. To launch the -tool using the script, double-click {@code SDK -Manager.exe} at the root of the the SDK directory.

    - -

    Launching from a command line

    - -

    In all development environments, follow these steps to access the Android SDK Manager tool from -the command line:

    - -
      -
    1. Navigate to the <sdk>/tools/ directory.
    2. -
    3. Execute the {@code android} tool command with no options. -
      $ android
    4. -
    - - -

    Installing SDK Packages

    - -

    Caution: Before you install SDK packages, -we recommend that you disable any antivirus software that may be running on -your computer. There are cases in which antivirus software on Windows is known to interfere with the -installation process, so we suggest you disable your antivirus until installation is -complete.

    - -

    Follow these steps to install new SDK packages in your environment:

    - -
      -
    1. Launch the Android SDK Manager as described in the section above.
    2. -
    3. Select Available Packages in the left panel. - This will reveal all of the packages that are currently available for download - from the SDK repository.
    4. -
    5. Select the package(s) you'd like to install and click Install - Selected. (If you aren't sure which packages to select, read Recommended Packages.)
    6. -
    7. Verify and accept the packages you want (ensure each one is selected with a green -checkmark) and click Install. The packages will now be installed into -your existing Android SDK directories.
    8. -
    - -

    New platforms are automatically saved into the -<sdk>/platforms/ directory of your SDK; -new add-ons are saved in the <sdk>/add-ons/ -directory; samples are saved in the -<sdk>/samples/android-<level>/; -and new documentation is saved in the existing -<sdk>/docs/ directory (old docs are replaced).

    - - -

    Updating SDK Packages

    - -

    From time to time, new revisions of existing SDK packages are released and -made available to you through the SDK repository. In most cases, if you have those -packages installed in your environment, you will want -to download the new revisions as soon as possible.

    - -

    You can learn about the release of new revisions in two ways:

    - -
      -
    • You can watch for updates listed in the "SDK" tab of the Android Developers -site, in the "Downloadable SDK Packages" section.
    • -
    • You can watch for updates listed in the Available Packages -panel of the Android SDK Manager.
    • -
    - -

    When you see that a new revision is available, you can use the Android SDK Manager to quickly -download it to your environment. Follow the same -procedure as given in Installing SDK Packages, above. The new -package is installed in place of the old, but without impacting your -applications.

    - -

    Tip: -Use the "Display updates only" checkbox to show only the packages -you do not have.

    - - -

    SDK Package Dependencies

    - -

    In some cases, an SDK package may require a specific minimum revision of -another package or SDK tool. Where such dependencies exist, they are -documented in the revision notes for each package, available from the links in -the "Downloadable SDK packages" section at left.

    - -

    For example, there may be a dependency between the ADT Plugin for Eclipse and -the SDK Tools package. When you install the SDK Tools -package, you should also upgrade to the required version of ADT (if you -are developing in Eclipse). In this case, the major version number for your ADT plugin should -always match the revision number of your SDK Tools (for example, ADT 8.x requires SDK Tools r8). -

    - -

    Also make sure that, each time you install a new version of the Android platform, you have -the latest version of the SDK Platform-tools package. The SDK Platform-tools contain -tools that are backward compatible with all versions of the Android platform and are -often updated to support new features in the latest version of the Android platform.

    - -

    The development tools will notify you with debug warnings if there is dependency that you need to -address. The Android SDK Manager also enforces dependencies by requiring that you download any -packages that are needed by those you have selected.

    - - -

    Adding New Sites

    - -

    By default, Available Packages displays packages available from the -Android Repository and Third party Add-ons. You can add other sites that host -their own Android SDK add-ons, then download the SDK add-ons -from those sites.

    - -

    For example, a mobile carrier or device manufacturer might offer additional -API libraries that are supported by their own Android-powered devices. In order -to develop using their libraries, you must install their Android SDK add-on, if it's not already -available under Third party Add-ons.

    - -

    If a carrier or device manufacturer has hosted an SDK add-on repository file -on their web site, follow these steps to add their site to the Android SDK -Manager:

    - -
      -
    1. Select Available Packages in the left panel.
    2. -
    3. Click Add Add-on Site and enter the URL of the -{@code repository.xml} file. Click OK.
    4. -
    -

    Any SDK packages available from the site will now be listed under a new item named -User Add-ons.

    - - -

    Troubleshooting

    - -

    Problems connecting to the SDK repository

    - -

    If you are using the Android SDK Manager to download packages and are encountering -connection problems, try connecting over http, rather than https. To switch the -protocol used by the Android SDK Manager, follow these steps:

    - -
      -
    1. With the Android SDK Manager window open, select "Settings" in the - left pane.
    2. -
    3. On the right, in the "Misc" section, check the checkbox labeled "Force - https://... sources to be fetched using http://..."
    4. -
    5. Click Save & Apply.
    6. -
    - - diff --git a/docs/html/sdk/android-2.3.4.jd b/docs/html/sdk/android-2.3.4.jd deleted file mode 100644 index 4bfdabdb6a4af76bf70f660f1c330d94f9932890..0000000000000000000000000000000000000000 --- a/docs/html/sdk/android-2.3.4.jd +++ /dev/null @@ -1,381 +0,0 @@ -page.title=Android 2.3.4 Platform -sdk.platform.version=2.3.4 -sdk.platform.apiLevel=10 - - -@jd:body - - - -

    -API Level: {@sdkPlatformApiLevel}

    - -

    Android 2.3.4 is a maintenance release that adds several bug fixes and patches -to the Android 2.3 platform, without any API changes from Android 2.3.3. Additionally, -Android 2.3.4 brings support for the Open Accessory API to mobile devices, -through the optional Open Accessory Library.

    - -

    For developers, the Android {@sdkPlatformVersion} platform and the Open -Accessory Library are available together in the latest version of the Google -APIs Add-On, a downloadable component for the Android SDK.

    - -

    To get started developing or testing against Android {@sdkPlatformVersion}, -use the Android SDK Manager to download the latest version of the Google APIs -Add-On into your SDK. For more information, see Adding SDK Components. If you -are new to Android, download the SDK Starter -Package first.

    - -

    For a high-level introduction to Android 2.3, see the Platform Highlights.

    - - -

    Revisions

    - -

    The sections below provide notes about successive releases of -the Android {@sdkPlatformVersion} platform component for the Android SDK, as denoted by -revision number. To determine what revision(s) of the Android -{@sdkPlatformVersion} platforms are installed in your SDK environment, refer to -the "Installed Packages" listing in the Android SDK and AVD Manager.

    - - - - -
    - - - Android {@sdkPlatformVersion}, Revision 1 (May 2011) -
    -
    -
    Dependencies:
    -
    -

    Requires SDK Tools r11 or higher.

    -
    - -
    -
    -
    - - -

    API Overview

    - -

    Android 2.3.4 provides the same framework API to applications as Android 2.3.3 -(API level 10). For a summary of the API, see the -Android 2.3.3 version notes.

    - - -

    Open Accessory Library

    - -

    Open Accessory is a new capability for integrating -connected peripherals with applications running on the platform. The capability -is based on a USB (Universal Serial Bus) stack built into the platform and an -API exposed to applications. Peripherals that attach to Android-powered devices -as accessories connect as USB hosts.

    - -

    Open Accessory is introduced in Android 3.1 (API level 12), but is -made available to devices running Android 2.3.4 by means of an optional external -library, the Open Accessory Library. The library exposes a framework API that -lets applications discover, communicate with, and manage a variety of device -types connected over USB. It also provides the implementation of the API against -parts of the Android platform that are not directly exposed to applications in -Android 2.3.4.

    - -

    The Open Accessory Library is optional on any given device. Device -manufacturers may choose whether to include the Open Accessory Library in their -products or exclude it. The library is forward-compatible with Android 3.1, so -applications developed against Android 2.3.4 will run properly on devices -running Android 3.1, if those devices support USB accessories.

    - -

    The API provided by the Open Accessory Library is based on the Open Accessory -API provided in Android 3.1. In most areas, you can use the same techniques and -APIs. However, developing for the Open Accessory Library on Android 2.3.4 differs -from the standard USB API in these ways: - -

      -
    • Obtaining a {@link android.hardware.usb.UsbManager} object — To obtain -a {@link android.hardware.usb.UsbManager} object when using the add-on library, -use the helper method getInstance() rather than {@link -android.content.Context#getSystemService(java.lang.String) getSystemService()} -For example: - -
      UsbManager manager = UsbManager.getInstance(this);
    • - -
    • Obtaining a {@link android.hardware.usb.UsbAccessory} from a filtered intent -— When you filter for a connected device or accessory with an intent -filter, the {@link android.hardware.usb.UsbAccessory} object is contained -inside the intent that is passed to your application. If you are using the -add-on library, you can get the {@link android.hardware.usb.UsbAccessory} object -in the following manner: - -
      UsbAccessory accessory = UsbManager.getAccessory(intent)
    • - -
    • No USB host support — Android 2.3.4 and the Open Accessory Library do -not support USB host mode (for example, through {@link -android.hardware.usb.UsbDevice}), although USB host mode is supported in Android -3.1. An Android-powered device running Android 2.3.4 can not function as a USB -host. The library enables the Android-powered device to function as -a peripheral only, with the connected accessory functioning as USB host -(through {@link android.hardware.usb.UsbAccessory}).
    • -
    - -

    To develop apps using the Open Accessory Library, you need:

    - -
      -
    • The latest version of the Android SDK tools
    • -
    • The latest version of the Google APIs add-on, which includes the library -itself (for linking)
    • -
    • An actual hardware device running Android 2.3.4 (or Android 3.1) with USB -accessories support, for runtime testing against connected devices
    • -
    - -

    For a full discussion of how to develop applications that interact with USB -accessories, please see the related developer documentation.

    - -

    Additionally, developers can request filtering on Google Play, such that -their applications are not available to users whose devices do not provide the -appropriate accessory support. To request filtering, add the element below -to the application manifest:

    - -
    <uses-feature
    -  android:name="android.hardware.usb.accessory"
    -  android:required="true">
    - - -

    API Level

    - -

    The Android 2.3.4 platform does not increment the API level — -it uses the same API level as Android 2.3.3, API level 10. - -

    To use APIs introduced in API level 10 in your application, -you need compile the application against the Android library that is provided in -the latest version of the Google APIs Add-On, which also includes the Open -Accessory Library.

    - -

    Depending on your needs, you might -also need to add an android:minSdkVersion="{@sdkPlatformApiLevel}" -attribute to the <uses-sdk> element in the application's -manifest. If your application is designed to run only on Android 2.3.3 and higher, -declaring the attribute prevents the application from being installed on earlier -versions of the platform.

    - -

    For more information about how to use API Level, see the API Levels document.

    - -

    Built-in Applications

    - -

    The system image included in the downloadable platform provides these -built-in applications:

    - - - - - - -
    -
      -
    • Browser
    • -
    • Calculator
    • -
    • Camera
    • -
    • Clock
    • -
    • Contacts
    • -
    • Custom Locale
    • -
    • Dev Tools
    • -
    • Downloads
    • -
    • Email
    • -
    -
    -
      -
    • Gallery
    • -
    • IMEs for Japanese, Chinese, and Latin text input
    • -
    • Messaging
    • -
    • Music
    • -
    • Phone
    • -
    • Search
    • -
    • Settings
    • -
    • Spare Parts (developer app)
    • -
    • Speech Recorder
    • -
    -
    - - -

    Locales

    - -

    The system image included in the downloadable SDK platform provides a variety of -built-in locales. In some cases, region-specific strings are available for the -locales. In other cases, a default version of the language is used. The -languages that are available in the Android {@sdkPlatformVersion} system -image are listed below (with language_country/region locale -descriptor).

    - - - - - - -
    -
      -
    • Arabic, Egypt (ar_EG)
    • -
    • Arabic, Israel (ar_IL)
    • -
    • Bulgarian, Bulgaria (bg_BG)
    • -
    • Catalan, Spain (ca_ES)
    • -
    • Czech, Czech Republic (cs_CZ)
    • -
    • Danish, Denmark(da_DK)
    • -
    • German, Austria (de_AT)
    • -
    • German, Switzerland (de_CH)
    • -
    • German, Germany (de_DE)
    • -
    • German, Liechtenstein (de_LI)
    • -
    • Greek, Greece (el_GR)
    • -
    • English, Australia (en_AU)
    • -
    • English, Canada (en_CA)
    • -
    • English, Britain (en_GB)
    • -
    • English, Ireland (en_IE)
    • -
    • English, India (en_IN)
    • -
    • English, New Zealand (en_NZ)
    • -
    • English, Singapore(en_SG)
    • -
    • English, US (en_US)
    • -
    • English, South Africa (en_ZA)
    • -
    • Spanish (es_ES)
    • -
    • Spanish, US (es_US)
    • -
    • Finnish, Finland (fi_FI)
    • -
    • French, Belgium (fr_BE)
    • -
    • French, Canada (fr_CA)
    • -
    • French, Switzerland (fr_CH)
    • -
    • French, France (fr_FR)
    • -
    • Hebrew, Israel (he_IL)
    • -
    • Hindi, India (hi_IN)
    • -
    -
    -
      -
    • Croatian, Croatia (hr_HR)
    • -
    • Hungarian, Hungary (hu_HU)
    • -
    • Indonesian, Indonesia (id_ID)
    • -
    • Italian, Switzerland (it_CH)
    • -
    • Italian, Italy (it_IT)
    • -
    • Japanese (ja_JP)
    • -
    • Korean (ko_KR)
    • -
    • Lithuanian, Lithuania (lt_LT)
    • -
    • Latvian, Latvia (lv_LV)
    • -
    • Norwegian-Bokmol, Norway(nb_NO)
    • -
    • Dutch, Belgium (nl_BE)
    • -
    • Dutch, Netherlands (nl_NL)
    • -
    • Polish (pl_PL)
    • -
    • Portuguese, Brazil (pt_BR)
    • -
    • Portuguese, Portugal (pt_PT)
    • -
    • Romanian, Romania (ro_RO)
    • -
    • Russian (ru_RU)
    • -
    • Slovak, Slovakia (sk_SK)
    • -
    • Slovenian, Slovenia (sl_SI)
    • -
    • Serbian (sr_RS)
    • -
    • Swedish, Sweden (sv_SE)
    • -
    • Thai, Thailand (th_TH)
    • -
    • Tagalog, Philippines (tl_PH)
    • -
    • Turkish, Turkey (tr_TR)
    • -
    • Ukrainian, Ukraine (uk_UA)
    • -
    • Vietnamese, Vietnam (vi_VN)
    • -
    • Chinese, PRC (zh_CN)
    • -
    • Chinese, Taiwan (zh_TW)
    • -
    -
    - -

    Note: The Android platform may support more -locales than are included in the SDK system image. All of the supported locales -are available in the Android Open Source -Project.

    - -

    Emulator Skins

    - -

    The downloadable platform includes a set of emulator skins that you can use -for modeling your application in different screen sizes and resolutions. The -emulator skins are:

    - -
      -
    • - QVGA (240x320, low density, small screen) -
    • -
    • - WQVGA400 (240x400, low density, normal screen) -
    • -
    • - WQVGA432 (240x432, low density, normal screen) -
    • -
    • - HVGA (320x480, medium density, normal screen) -
    • -
    • - WVGA800 (480x800, high density, normal screen) -
    • -
    • - WVGA854 (480x854 high density, normal screen) -
    • -
    - -

    For more information about how to develop an application that displays -and functions properly on all Android-powered devices, see Supporting Multiple -Screens.

    diff --git a/docs/html/sdk/api_diff/10/changes/changes-summary.html b/docs/html/sdk/api_diff/10/changes/changes-summary.html index dbb28813cf7a61b2cc02691d011d893a77759b07..ff0e47982522797338c15667a1a786e5c0e2ccee 100644 --- a/docs/html/sdk/api_diff/10/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/10/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/11/changes/changes-summary.html b/docs/html/sdk/api_diff/11/changes/changes-summary.html index b6af9ae7a321bda05073e02069a52d26a4996b5c..18e9f5d30590f264bf4cd99b8f0ffc9a01961568 100644 --- a/docs/html/sdk/api_diff/11/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/11/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/12/changes/changes-summary.html b/docs/html/sdk/api_diff/12/changes/changes-summary.html index 2a630c25d5d05ce6223eb5513aff93b9779c66a0..e069d3d157766b022e8ba214f4d3934dddf95c22 100644 --- a/docs/html/sdk/api_diff/12/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/12/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/13/changes/changes-summary.html b/docs/html/sdk/api_diff/13/changes/changes-summary.html index 082fcfb64abc96ddf3575f4630e9247bc89a70da..3b1c55ad96eec96db5ba5b4f5dc3085622d6c7a1 100644 --- a/docs/html/sdk/api_diff/13/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/13/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/14/changes/changes-summary.html b/docs/html/sdk/api_diff/14/changes/changes-summary.html index ccb5d26f5e1e21956deb891e6c75999c25cd1fd5..0cec8777bc5d732e87c09324c011cd6318ae0cdd 100644 --- a/docs/html/sdk/api_diff/14/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/14/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/15/changes/changes-summary.html b/docs/html/sdk/api_diff/15/changes/changes-summary.html index 0acb973bcc67450abcb4e5fd5ac7c7bc8af7d8eb..7f00168c1fbb6a2c2358e7c783acfea7c165ffc8 100644 --- a/docs/html/sdk/api_diff/15/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/15/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/3/changes/changes-summary.html b/docs/html/sdk/api_diff/3/changes/changes-summary.html index 65a37f8d3b316e7136c4fbaaf8c7b2815b9bcee4..4c0012a5ffe050d24bd3d5225d1e2d661bc6ef81 100644 --- a/docs/html/sdk/api_diff/3/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/3/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/4/changes/changes-summary.html b/docs/html/sdk/api_diff/4/changes/changes-summary.html index 88b8be6820fd9e786d733bdc87f7a7c821121d27..bbed016d3936b964f19bd9af440b023d9a87b305 100644 --- a/docs/html/sdk/api_diff/4/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/4/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/5/changes/changes-summary.html b/docs/html/sdk/api_diff/5/changes/changes-summary.html index 3a06d9871cab412ee28d5a72523a91bd604b26b2..1f10f255d0d6289d5b1ed487ca55f1c477743a1d 100644 --- a/docs/html/sdk/api_diff/5/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/5/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/6/changes/changes-summary.html b/docs/html/sdk/api_diff/6/changes/changes-summary.html index 77ceb255c35cd6b582fc80a07b5b956e7e612db6..a1c39853509c98341e3f5bb52cf7a9b1cb7c5071 100644 --- a/docs/html/sdk/api_diff/6/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/6/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/7/changes/changes-summary.html b/docs/html/sdk/api_diff/7/changes/changes-summary.html index 330f7270e7884eb757bc5dd8c689a8ad716f1c9d..34d4d2543d60f631c1034a07c0f432f79bb77b6e 100644 --- a/docs/html/sdk/api_diff/7/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/7/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/8/changes/changes-summary.html b/docs/html/sdk/api_diff/8/changes/changes-summary.html index f5fa7e64a112ab58b395436fdda0702b96007690..504118258ac1e161e9b866a9c69a1cbc6493c352 100644 --- a/docs/html/sdk/api_diff/8/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/8/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/api_diff/9/changes/changes-summary.html b/docs/html/sdk/api_diff/9/changes/changes-summary.html index f81cea152f9b735cd6be15900bb96eb09bcca183..4bccfe5e3975665a3125731448fc3ebb6835eeb5 100644 --- a/docs/html/sdk/api_diff/9/changes/changes-summary.html +++ b/docs/html/sdk/api_diff/9/changes/changes-summary.html @@ -73,7 +73,7 @@ body{overflow:auto;}

    Android API Differences Report

    This report details the changes in the core Android framework API between two API Level +href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels" target="_top">API Level specifications. 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 Android API specifications diff --git a/docs/html/sdk/exploring.jd b/docs/html/sdk/exploring.jd new file mode 100644 index 0000000000000000000000000000000000000000..8272b061a0c93e5ecce96242ae4abfc60b2a5d01 --- /dev/null +++ b/docs/html/sdk/exploring.jd @@ -0,0 +1,166 @@ +page.title=Exploring the SDK +walkthru=1 + +@jd:body + + +

    The Android SDK is composed of modular packages that you can download separately using +the Android SDK Manager. For example, when the SDK Tools are updated or a new version of +the Android platform is released, you can use the SDK Manager to quickly download them to +your environment. Simply follow the procedures described in Adding Platforms and Packages.

    + +

    There are several different packages available for the Android SDK. The table below describes +most of the available packages and where they're located once you download them.

    + + +

    Available Packages

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PackageDescriptionFile Location
    SDK ToolsContains tools for debugging and testing, plus other +utilities that are required to develop an app. If you've just installed the SDK starter package, +then you already have the latest version of this package. Make sure you keep this up to date.{@code <sdk>/tools/}
    SDK Platform-toolsContains platform-dependent tools for developing and debugging +your application. These tools support the latest features of the Android platform and are typically +updated only when a new platform becomes available. These tools are always backward compatible with +older platforms, but you must be sure that you have the latest version of these tools when you +install a new SDK platform.{@code <sdk>/platform-tools/}
    DocumentationAn offline copy of the latest documentation for the Android +platform APIs.{@code <sdk>/docs/}
    SDK PlatformThere's one SDK Platform available for each version of Android. It includes an {@code +android.jar} file with a fully compliant Android library. In order to build an Android app, you must +specify an SDK platform as your build target.{@code <sdk>/platforms/<android-version>/}
    System ImagesEach platform version offers one or more different system images (such as for ARM +and x86). The Android emulator requires a system image to operate. You should always test your +app on the latest version of Android and using the emulator with the latest system image is a +good way to do so.{@code <sdk>/platforms/<android-version>/}
    Sources for Android SDKA copy of the Android platform source code that's useful for +stepping through the code while debugging your app.{@code <sdk>/sources/}
    Samples for SDKA collection of sample apps that demonstrate a variety of the +platform APIs. These are a great resource to browse Android app code. The API Demos app in +particular provides a huge number of small demos you should explore.{@code <sdk>/platforms/<android-version>/samples/}
    Google APIsAn SDK add-on that provides both a platform you can use to develop an app +using special Google APIs and a system image for the emulator so you can test your app using the +Google APIs.{@code <sdk>/add-ons/}
    Android SupportA static library you can include in your app sources in order to use powerful +APIs that aren't available in the standard platform. For example, the support library +contains versions of the {@link android.support.v4.app.Fragment} class that's compatible with +Android 1.6 and higher (the class was originally introduced in Android 3.0) and the {@link +android.support.v4.view.ViewPager} APIs that allow you to easily build a side-swipeable UI.{@code <sdk>/extras/android/support/}
    Google Play BillingProvides the static libraries and samples that allow you to +integrate billing services in your app with Google Play.{@code <sdk>/extras/google/}
    Google Play LicensingProvides the static libraries and samples that allow you to perform license verification for +your app when distributing with Google Play.{@code <sdk>/extras/google/}
    + +

    The above table is not comprehensive and you can add new sites to download additional packages from third-parties.

    + +

    In some cases, an SDK package may require a specific minimum revision of +another package or SDK tool. For example, there may be a dependency between the ADT Plugin for +Eclipse and +the SDK Tools package. When you install the SDK Tools +package, you should also upgrade to the required version of ADT (if you +are developing in Eclipse). In this case, the major version number for your ADT plugin should +always match the revision number of your SDK Tools (for example, ADT 8.x requires SDK Tools r8). +

    + +

    The development tools will notify you with debug warnings if there is dependency that you need to +address. The Android SDK Manager also enforces dependencies by requiring that you download any +packages that are needed by those you have selected.

    + + + + + +

    Adding New Sites

    + +

    By default, Available Packages displays packages available from the +Android Repository and Third party Add-ons. You can add other sites that host +their own Android SDK add-ons, then download the SDK add-ons +from those sites.

    + +

    For example, a mobile carrier or device manufacturer might offer additional +API libraries that are supported by their own Android-powered devices. In order +to develop using their libraries, you must install their Android SDK add-on, if it's not already +available under Third party Add-ons.

    + +

    If a carrier or device manufacturer has hosted an SDK add-on repository file +on their web site, follow these steps to add their site to the Android SDK +Manager:

    + +
      +
    1. Select Available Packages in the left panel.
    2. +
    3. Click Add Add-on Site and enter the URL of the +repository.xml file. Click OK.
    4. +
    +

    Any SDK packages available from the site will now be listed under a new item named +User Add-ons.

    + + + + +

    Troubleshooting

    + +

    Problems connecting to the SDK repository

    + +

    If you are using the Android SDK Manager to download packages and are encountering +connection problems, try connecting over http, rather than https. To switch the +protocol used by the Android SDK Manager, follow these steps:

    + +
      +
    1. With the Android SDK Manager window open, select "Settings" in the + left pane.
    2. +
    3. On the right, in the "Misc" section, check the checkbox labeled "Force + https://... sources to be fetched using http://..."
    4. +
    5. Click Save & Apply.
    6. +
    + + + + diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd index b56ccdbd83f0e76b5d83941bfad5afd02898b0f0..e788ffeb96737372865e5d383bb65af9acfd0ea4 100644 --- a/docs/html/sdk/index.jd +++ b/docs/html/sdk/index.jd @@ -1,6 +1,6 @@ page.title=Android SDK +header.hide=1 page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices. -sdk.redirect=0 sdk.win_installer=installer_r18-windows.exe sdk.win_installer_bytes=37456234 @@ -20,28 +20,119 @@ sdk.linux_checksum=6cd716d0e04624b865ffed3c25b3485c @jd:body -
    -

    Here's an overview of the steps you must follow to set up the Android SDK:

    + -
      -
    1. Prepare your development computer and ensure it meets the system requirements.
    2. -
    3. Install the SDK starter package from the table above. (If you're on Windows, download the -installer for help with the initial setup.)
    4. -
    5. Install the ADT Plugin for Eclipse (if you'll be developing in Eclipse).
    6. -
    7. Add Android platforms and other packages to your SDK.
    8. -
    9. Explore the contents of the Android SDK (optional).
    10. -
    +
    -

    To get started, download the appropriate package from the table above, -then read the guide to Installing the SDK.

    +
     
    + +
    + +
    + + +
    + +
    +

    Get the Android SDK

    + + +

    The Android SDK provides you the API libraries and developer tools necessary to build, test, + and debug apps for Android.

    + + +

    +To get the latest Android SDK, please visit the web site at developer.android.com/sdk/ +

    + + + + +
    - - -

    For more information about how to set up your -development environment, read the guide to Installing the SDK.

    + + +
    + + +
     
    + + + + + + +
    + diff --git a/docs/html/sdk/installing/adding-packages.jd b/docs/html/sdk/installing/adding-packages.jd new file mode 100644 index 0000000000000000000000000000000000000000..7765343b2e5068c797fd1d05521f407b6029959e --- /dev/null +++ b/docs/html/sdk/installing/adding-packages.jd @@ -0,0 +1,78 @@ +page.title=Adding Platforms and Packages +walkthru=1 + +@jd:body + + +

    The Android SDK separates different parts of the SDK into separately downloadable packages. The +SDK starter package that you've installed includes only the SDK Tools. To develop an Android app, +you also need to download at least one Android platform and the latest SDK Platform-tools.

    + +

    You can update and install SDK packages at any time using the Android SDK Manager.

    + +

    If you've used the Windows installer to install the SDK tools, you should already have the +Android SDK Manager open. Otherwise, you can launch the Android SDK Manager in one of the following +ways:

    +
      +
    • On Windows, double-click the SDK Manager.exe file at the root of the Android +SDK directory.
    • +
    • On Mac or Linux, open a terminal and navigate to the tools/ directory in the +Android SDK, then execute android sdk.
    • +
    + +

    When you open the Android SDK Manager, it automatically selects a set of recommended packages. +Simply click Install to install the recommended packages. The Android SDK Manager +installs the selected packages into +your Android SDK environment. The following sections describe some of the available SDK +packages and more about which ones we recommend you install.

    + +

    Once you have installed your packages, continue to the next page.

    + + +

    Figure 1. The Android SDK Manager shows the +SDK packages that are available, already installed, or for which an update is available.

    + + + + + + +

    Here's an outlines of the packages required and those we recommend you use: +

    + +
    +
    SDK Tools
    +
    Required. Your new SDK installation already has the latest version. Make sure +you keep this up to date.
    +
    SDK Platform-tools
    +
    Required. You must install this package when you install the SDK for +the first time.
    +
    SDK Platform
    +
    Required.You need to download at least one platform into your environment so you're +able to compile your application. In order to provide the best user experience on the latest +devices, we recommend that you use the latest platform version as your build target. You'll +still be able to run your app on older versions, but you must build against the latest version +in order to use new features when running on devices with the latest version of Android.
    +
    System Image
    +
    Recommended. Although you might have one or more Android-powered devices on which to test + your app, it's unlikely you have a device for every version of Android your app supports. It's +a good practice to download a system image for each version of Android you support and use them +to test your app on the Android emulator.
    +
    SDK Samples
    +
    Recommended. The samples give you source code that you can use to learn about +Android, load as a project and run, or reuse in your own app. Note that multiple +samples packages are available — one for each Android platform version. When +you are choosing a samples package to download, select the one whose API Level +matches the API Level of the Android platform that you plan to use.
    +
    Android Support
    +
    Recommended. The APIs available in this static library allow you to use a variety of new +framework features (including some not available in even the latest version) on devices running +a platform version as old as Android 1.6. For more information, read Support Library.
    +
    + + +

    Tip: For easy access to the SDK tools from a command line, add the +location of the SDK's tools/ and +platform-tools to your PATH environment variable.

    diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..2ae6bedeb151117c73f7f290fa6eab01609ba9a4 --- /dev/null +++ b/docs/html/sdk/installing/index.jd @@ -0,0 +1,133 @@ +page.title=Installing the SDK +walkthru=1 + +@jd:body + + +

    You should have already downloaded the Android SDK. Now +you need to set up your development environment.

    + +

    The SDK you've downloaded is not the complete SDK environment. It includes only the core SDK tools, which you can +use to download the rest of the SDK packages (such as the latest system image).

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

    Other platforms

    + + diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd new file mode 100644 index 0000000000000000000000000000000000000000..29252728d72d74a6bc4164db06871d3f33a80d0f --- /dev/null +++ b/docs/html/sdk/installing/installing-adt.jd @@ -0,0 +1,206 @@ +page.title=Installing the Eclipse Plugin +walkthru=1 +adt.zip.version=18.0.0 +adt.zip.download=ADT-18.0.0.zip +adt.zip.bytes=12834793 +adt.zip.checksum=b446fa157ed97af79d1e21629201efbb + +@jd:body + + + +

    Android offers a custom plugin for the Eclipse IDE, called Android +Development Tools (ADT). This plugin is designed to give you a powerful, integrated +environment in which to develop Android apps. It extends the capabilites +of Eclipse to let you quickly set up new Android projects, build an app +UI, debug your app, and export signed (or unsigned) app packages (APKs) for distribution. +

    + +

    If you will be developing in Eclipse with the ADT Plugin, first make sure that you have a +suitable version of Eclipse +installed on your computer as described by the +system requirements.

    + +

    If you need to install Eclipse, you can download it from http://www.eclipse.org/downloads/. +We recommend the "Eclipse Classic" version. Otherwise, you should use a Java or +RCP version of Eclipse.

    + + +

    Note: If you prefer to work in a different IDE, you do not need to +install Eclipse or ADT. Instead, you can directly use the SDK tools to build and +debug your application. So if you're not using Eclipse, continue to the next page by clicking +the Next link on the right.

    + + + +

    Download the ADT Plugin

    + + +
      +
    1. Start Eclipse, then select Help > Install New +Software....
    2. +
    3. Click Add, in the top-right corner.
    4. +
    5. In the Add Repository dialog that appears, enter "ADT Plugin" for the Name and the +following URL for the Location: +
      https://dl-ssl.google.com/android/eclipse/
      +
    6. +
    7. Click OK +

      Note: If you have trouble acquiring the plugin, try using "http" in the Location URL, +instead of "https" (https is preferred for security reasons).

    8. +
    9. In the Available Software dialog, select the checkbox next to Developer Tools and click +Next.
    10. +
    11. In the next window, you'll see a list of the tools to be downloaded. Click +Next.
    12. +
    13. Read and accept the license agreements, then click Finish. +

      Note: If you get a security warning saying that the authenticity or validity of +the software can't be established, click OK.

    14. +
    15. When the installation completes, restart Eclipse.
    16. +
    + + + + +

    Configure the ADT Plugin

    + +

    After you've installed ADT and restarted Eclipse, you + must specify the location of your Android SDK directory:

    + +
      +
    1. Select Window > Preferences... to open the Preferences + panel (on Mac OS X, select Eclipse > Preferences).
    2. +
    3. Select Android from the left panel.
    4. +

      You may see a dialog asking whether you want to send usage statistics to Google. If so, +make your choice and click Proceed.

      +
    5. For the SDK Location in the main panel, click Browse... and + locate your downloaded Android SDK directory (such as android-sdk-windows).
    6. +
    7. Click Apply, then OK.
    8. +
    + + +

    If you haven't encountered any errors, you're done setting up ADT + and can continue to the next step of the SDK installation.

    + + + + +

    Updating the ADT Plugin

    + +

    From time to time, a new revision of the ADT Plugin becomes available, with +new features and bug fixes. Generally, when a new revision of ADT is available, +you should update to it as soon as convenient.

    + +

    In some cases, a new revision of ADT will have a dependency on a specific +revision of the Android SDK Tools. If such dependencies exist, you will need to +update the SDK Tools package of the SDK after installing the new revision of +ADT. To update the SDK Tools package, use the Android SDK Manager, as +described in Exploring the SDK.

    + +

    To learn about new features of each ADT revision and also any dependencies on +the SDK Tools, see the listings in the Revisions +section. To determine the version currently installed, open the +Eclipse Installed Software window using Help +> Software Updates and refer to the version listed for +"Android Development Tools".

    + +

    Follow the steps below to check whether an update is available and, if so, +to install it.

    + +
      +
    1. Select Help > Check for Updates. +

      If there are no updates available, a dialog will say so and you're done.

    2. +
    3. If there are updates available, select Android DDMS, Android Development Tools, + and Android Hierarchy Viewer, then click Next.
    4. +
    5. In the Update Details dialog, click Next.
    6. +
    7. Read and accept the license agreement and then click Finish. + This will download and install the latest version of Android DDMS and + Android Development Tools.
    8. +
    9. Restart Eclipse.
    10. +
    + + +

    If you encounter problems during the update, remove the existing ADT plugin from Eclipse, then +perform a fresh installation, using the instructions for Installing the ADT +Plugin.

    + + + +

    Troubleshooting

    + +

    If you are having trouble downloading the ADT plugin after following the +steps above, here are some suggestions:

    + +
      +
    • If Eclipse can not find the remote update site containing the ADT plugin, +try changing the remote site URL to use http, rather than https. That is, set +the Location for the remote site to: +
      http://dl-ssl.google.com/android/eclipse/
    • +
    • If you are behind a firewall (such as a corporate firewall), make sure that +you have properly configured your proxy settings in Eclipse. In Eclipse, +you can configure proxy information from the main Eclipse menu in +Window (on Mac OS X, Eclipse) > +Preferences > General > Network +Connections.
    • +
    + +

    If you are still unable to use Eclipse to download the ADT plugin as a +remote update site, you can download the ADT zip file to your local machine and +manually install it:

    + +
      +
    1. Download the current ADT Plugin zip file from the table below (do not unpack it). + + + + + + + + + + + + + + +
      NamePackageSizeMD5 Checksum
      ADT {@adtZipVersion} + {@adtZipDownload} + {@adtZipBytes} bytes{@adtZipChecksum}
      +
    2. + + +
    3. Follow steps 1 and 2 in the default install + instructions (above).
    4. +
    5. In the Add Site dialog, click Archive.
    6. +
    7. Browse and select the downloaded zip file.
    8. +
    9. Enter a name for the local update site (e.g., + "Android Plugin") in the "Name" field.
    10. +
    11. Click OK. +
    12. Follow the remaining procedures as listed for + default installation above, + starting from step 4.
    13. +
    + +

    To update your plugin once you've installed using the zip file, you will have +to follow these steps again instead of the default update instructions.

    + +

    Other install errors

    + +

    Note that there are features of ADT that require some optional +Eclipse packages (for example, WST). If you encounter an error when +installing ADT, your Eclipse installion might not include these packages. +For information about how to quickly add the necessary packages to your +Eclipse installation, see the troubleshooting topic +ADT +Installation Error: "requires plug-in org.eclipse.wst.sse.ui".

    + +

    For Linux users

    +

    If you encounter this error when installing the ADT Plugin for Eclipse: +

    +An error occurred during provisioning.
    +Cannot connect to keystore.
    +JKS
    +

    +...then your development machine lacks a suitable Java VM. Installing Sun +Java 6 will resolve this issue and you can then reinstall the ADT +Plugin.

    diff --git a/docs/html/sdk/installing/next.jd b/docs/html/sdk/installing/next.jd new file mode 100644 index 0000000000000000000000000000000000000000..b1da7c69dc24b031c50392f44e79026ed2a3ced5 --- /dev/null +++ b/docs/html/sdk/installing/next.jd @@ -0,0 +1,52 @@ +page.title=Next Steps +walkthru=1 + +@jd:body + + +

    Now that you've installed the Android SDK, here are are a few ways to learn Android +and start developing:

    + +

    Start coding

    +
      +
    • Follow the training class for Building Your First App. +

      This class is an essential first step for new Android developers.

      +

      It gives you step by step instructions for building a simple app. You’ll learn how to +create an Android project and run a debuggable version of the app. You'll also learn some +fundamentals of Android app design, including how to build a simple user interface and handle user +input.

      +
    • +
    + + +

    Learn how to design your app

    +
      +
    • Learn the best practices for Android design and user experience by reading the Android Design guidelines.
    • +
    + + +

    Read up on the API framework

    +
      +
    • Start reading about fundamental framework topics in the collection of API Guides.
    • +
    • Browse the API specifications in the Reference.
    • +
    + + +

    Explore the development tools

    +
      +
    • Learn about developing an app with the Android Developer Tools plugin for Eclipse + and other tools from the Workflow.
    • +
    + + +

    Explore some code

    + +
      +
    • Browse the sample apps available from the Android SDK Manager. You'll find them in +<sdk>/samples/<platform-version>/.
    • +
    diff --git a/docs/html/sdk/older_releases.jd b/docs/html/sdk/older_releases.jd index 870ff04df37d2b70fe08f5bbeca238189dc928d0..bb274b67aa7ab979f47e1e95701c262fc91623bd 100644 --- a/docs/html/sdk/older_releases.jd +++ b/docs/html/sdk/older_releases.jd @@ -15,7 +15,7 @@ development and testing.

    If you already have an Android SDK for platform version 1.6 or newer, then you do not need to install a new SDK—especially not one from this page. You should install older platforms as components of your existing SDK. -See Adding SDK Components.

    +See Exploring the SDK.

    diff --git a/docs/html/sdk/preview/features.jd b/docs/html/sdk/preview/features.jd deleted file mode 100644 index d7ecc47ce8f4714e3b8b82f1af59485cacf492f7..0000000000000000000000000000000000000000 --- a/docs/html/sdk/preview/features.jd +++ /dev/null @@ -1,8 +0,0 @@ -@jd:body - - - -

    You should have already been redirected by your browser. Please go to the -Android 3.0 Platform.

    \ No newline at end of file diff --git a/docs/html/sdk/preview/installing.jd b/docs/html/sdk/preview/installing.jd deleted file mode 100644 index 94c6f2f9ab956c8f525f58849db3beab3fa7aac9..0000000000000000000000000000000000000000 --- a/docs/html/sdk/preview/installing.jd +++ /dev/null @@ -1,8 +0,0 @@ -@jd:body - - - -

    You should have already been redirected by your browser. Please go to -Installing the SDK.

    \ No newline at end of file diff --git a/docs/html/sdk/requirements.jd b/docs/html/sdk/requirements.jd deleted file mode 100644 index c76e8c8b82a3964721290f66da75bb8209066a8e..0000000000000000000000000000000000000000 --- a/docs/html/sdk/requirements.jd +++ /dev/null @@ -1,114 +0,0 @@ -page.title=System Requirements -@jd:body - -

    The sections below describe the system and software requirements for developing -Android applications using the Android SDK.

    - -

    Supported Operating Systems

    -
      -
    • Windows XP (32-bit), Vista (32- or 64-bit), or Windows 7 (32- or 64-bit)
    • -
    • Mac OS X 10.5.8 or later (x86 only)
    • -
    • Linux (tested on Ubuntu Linux, Lucid Lynx) -
        -
      • GNU C Library (glibc) 2.7 or later is required.
      • -
      • On Ubuntu Linux, version 8.04 or later is required.
      • -
      • 64-bit distributions must be capable of running 32-bit applications. - For information about how to add support for 32-bit applications, see - the Ubuntu Linux - installation notes.
      • -
      -
    • -
    - -

    Supported Development Environments

    - -

    Eclipse IDE

    -
      -
    • Eclipse 3.6.2 (Helios) or greater -

      Note: Eclipse 3.5 (Galileo) is no longer -supported with the latest version of ADT.

    • -
    • Eclipse JDT plugin (included -in most Eclipse IDE packages)
    • -
    • If you need to install or update Eclipse, you can download it from http://www.eclipse.org/downloads/. - -

      Several types of Eclipse packages are available for each platform. For -developing Android applications, we recommend that you install one of these -packages:

      -
        -
      • Eclipse IDE for Java Developers
      • -
      • Eclipse Classic
      • -
      • Eclipse IDE for Java EE Developers
      • -
      -
    • -
    • JDK 6 - (JRE alone is not sufficient)
    • -
    • Android Development Tools plugin -(recommended)
    • -
    • Not compatible with Gnu Compiler for Java (gcj)
    • -
    - - -

    Other development environments or IDEs

    -
      -
    • JDK 6 - (JRE alone is not sufficient)
    • -
    • Apache Ant 1.8 or later
    • -
    • Not compatible with Gnu Compiler for Java (gcj)
    • -
    - - - -

    Note: If JDK is already installed on your development computer, please take a moment to make sure that it meets the version requirements listed above. In -particular, note that some Linux distributions may include JDK 1.4 or Gnu Compiler for Java, both of which are not supported for Android development.

    - -

    Hardware requirements

    - -

    The Android SDK requires disk storage for all of the components that you choose to install. The table below provides a rough idea of the disk-space requirements to expect, based on the components that you plan to use.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Component typeApproximate sizeComments
    SDK Tools35 MBRequired.
    SDK Platform-tools6 MBRequired.
    Android platform (each)150 MBAt least one platform is required.
    SDK Add-on (each)100 MBOptional.
    USB Driver for Windows10 MBOptional. For Windows only.
    Samples (per platform)10MOptional.
    Offline documentation250 MBOptional.
    - -

    Note that the disk-space requirements above are in addition to those of the Eclipse IDE, JDK, or other prerequisite tools that you may need to install on your development computer.

    - - diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs deleted file mode 100644 index e994d9516448e4c71fc758d05c64443eca8a1dde..0000000000000000000000000000000000000000 --- a/docs/html/sdk/sdk_toc.cs +++ /dev/null @@ -1,228 +0,0 @@ - - - - - diff --git a/docs/html/sdk/terms.jd b/docs/html/sdk/terms.jd deleted file mode 100644 index 614a438ef17c5335dfc268bc3237d355d68b4c73..0000000000000000000000000000000000000000 --- a/docs/html/sdk/terms.jd +++ /dev/null @@ -1,207 +0,0 @@ -page.title=Terms and Conditions -hide_license_footer=true -@jd:body - -

    This is the Android Software Development Kit License Agreement.

    - -

    - 1. Introduction -

    -

    - 1.1 The Android Software Development Kit (referred to in this 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 this License Agreement. This License Agreement forms a legally binding contract between you and Google in relation to your use of the SDK. - -

    -

    - 1.2 "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 this License Agreement. You may not use the SDK if you do not accept this License Agreement. -

    -

    - 2.2 You can accept this License Agreement by: -

    -

    - (A) clicking to accept or agree to this License Agreement, where this option is made available to you; or -

    -

    - (B) by actually using the SDK. In this case, you agree that use of the SDK constitutes acceptance of the Licensing Agreement from that point onwards. -

    -

    - 2.3 You may not use the SDK and may not accept the Licensing 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 this 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 this License Agreement. If you do not have the requisite authority, you may not accept the Licensing 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 this License Agreement, Google grants you a limited, worldwide, royalty-free, non- assignable and non-exclusive license to use the SDK solely to develop applications to run on the Android platform. -

    -

    - 3.2 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.3 Except to the extent required by applicable third party licenses, you may not 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. Except to the extent required by applicable third party licenses, you may not 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.4 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 this License Agreement. -

    -

    - 3.5 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.6 Nothing in this 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.7 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 this 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) this 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, your 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 the Android platform and/or applications for the Android platform, 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 this 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 for the Android Platform -

    -

    - 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, this 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 This License Agreement will continue to apply until terminated by either you or Google as set out below. -

    -

    - 9.2 If you want to terminate this 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 this License Agreement with you if: -

    -

    - (A) you have breached any provision of this 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 providing 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 this 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 this 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 this 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 This License Agreement constitute the whole legal agreement between you and Google and govern your use of the SDK (excluding any services which Google may provide to you under a separate written agreement), and completely replace 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 this 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 this License Agreement is invalid, then that provision will be removed from this License Agreement without affecting the rest of this License Agreement. The remaining provisions of this 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 this License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of this 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 this 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 this 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 this License Agreement without the prior written approval of the other party. -

    -

    - 14.7 This License Agreement, and your relationship with Google under this 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 this 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. -

    -

    - April 10, 2009 -

    diff --git a/docs/html/sdk/terms_body.html b/docs/html/sdk/terms_body.html deleted file mode 100644 index 8c55b37bc61d510526786bae20fd698aae452e38..0000000000000000000000000000000000000000 --- a/docs/html/sdk/terms_body.html +++ /dev/null @@ -1,336 +0,0 @@ - - -

    This is the Android Software Development Kit License Agreement.

    - -

    - 1. Introduction -

    -

    - 1.1 The Android Software Development Kit (referred to in this 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 this License Agreement. This License Agreement forms a -legally binding contract between you and Google in relation to your use of the SDK. - -

    -

    - 1.2 "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 this License Agreement. You may not use -the SDK if you do not accept this License Agreement. -

    -

    - 2.2 You can accept this License Agreement by: -

    -

    - (A) clicking to accept or agree to this License Agreement, where this option is made -available to you; or -

    -

    - (B) by actually using the SDK. In this case, you agree that use of the SDK constitutes -acceptance of the Licensing Agreement from that point onwards. -

    -

    - 2.3 You may not use the SDK and may not accept the Licensing 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 this 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 this License Agreement. If you do not have the requisite authority, you may not -accept the Licensing 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 this License Agreement, Google grants you a limited, worldwide, -royalty-free, non- assignable and non-exclusive license to use the SDK solely to develop -applications to run on the Android platform. -

    -

    - 3.2 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.3 Except to the extent required by applicable third party licenses, you may not 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. Except to the extent required by -applicable third party licenses, you may not 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.4 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 this License Agreement. -

    -

    - 3.5 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.6 Nothing in this 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.7 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 this 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) this 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, your 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 the Android platform and/or applications for the Android platform, 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 this 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 for the Android Platform -

    -

    - 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, -this 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 This License Agreement will continue to apply until terminated by either you or Google -as set out below. -

    -

    - 9.2 If you want to terminate this 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 this License Agreement with you if: -

    -

    - (A) you have breached any provision of this 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 providing 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 this 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 this 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 this 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 This License Agreement constitute the whole legal agreement between you and Google and -govern your use of the SDK (excluding any services which Google may provide to you under a separate -written agreement), and completely replace 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 this 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 this License Agreement is invalid, then that provision will be removed from this -License Agreement without affecting the rest of this License Agreement. The remaining provisions of -this 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 this License Agreement and that such other -companies shall be entitled to directly enforce, and rely upon, any provision of this 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 this 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 this 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 this License Agreement -without the prior written approval of the other party. -

    -

    - 14.7 This License Agreement, and your relationship with Google under this 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 this 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. -

    -

    - April 10, 2009 -

    \ No newline at end of file diff --git a/docs/html/sdk/win-usb.jd b/docs/html/sdk/win-usb.jd index 3be0faf99bfc3f97177507bc26b4a53756922a57..802615e3849d60edfc96e330f424545465849a18 100644 --- a/docs/html/sdk/win-usb.jd +++ b/docs/html/sdk/win-usb.jd @@ -10,7 +10,7 @@ page.title=Google USB Driver

    See also

      -
    1. Installing a USB Driver
    2. +
    3. Installing a USB Driver
    4. Using Hardware Devices
    5. Adding SDK Packages
    @@ -30,7 +30,7 @@ following devices:

    * Or similar hardware on other carriers

    All other devices require Windows drivers provided by the hardware manufacturer, as listed in -the OEM USB Drivers document. The Galaxy Nexus +the OEM USB Drivers document. The Galaxy Nexus driver is also distributed by Samsung (listed as model SCH-I515).

    @@ -169,4 +169,4 @@ included with the Android SDK:

    downloaded into the <sdk>\extras\google\usb_driver\ directory. -

    For installation information, read Installing a USB Driver.

    +

    For installation information, read Installing a USB Driver.

    diff --git a/docs/html/search.jd b/docs/html/search.jd deleted file mode 100644 index 407bc86b570b22fbba03dfa155572aa3fe0ab9c9..0000000000000000000000000000000000000000 --- a/docs/html/search.jd +++ /dev/null @@ -1,148 +0,0 @@ -page.title=Search Results -@jd:body - - - - - -
    -

    search results

    - -

    -
    Loading...
    -
    diff --git a/docs/html/shareables/training/CustomView.zip b/docs/html/shareables/training/CustomView.zip new file mode 100644 index 0000000000000000000000000000000000000000..f8c1c7aa7c1cc89973331eb83bc705ad5de99ad1 Binary files /dev/null and b/docs/html/shareables/training/CustomView.zip differ diff --git a/docs/html/shareables/training/FragmentBasics.zip b/docs/html/shareables/training/FragmentBasics.zip index ff5b7f120ca115ad51ef7535b205880ca3612875..b5b19d03ba5a3b3ac14863d8d6e3099b4ab101c6 100644 Binary files a/docs/html/shareables/training/FragmentBasics.zip and b/docs/html/shareables/training/FragmentBasics.zip differ diff --git a/docs/html/shareables/training/NetworkUsage.zip b/docs/html/shareables/training/NetworkUsage.zip new file mode 100644 index 0000000000000000000000000000000000000000..8c7fbef9fb49a8c4ed7d1afb7118a3ee4ea5677c Binary files /dev/null and b/docs/html/shareables/training/NetworkUsage.zip differ diff --git a/docs/html/shareables/training/OpenGLES.zip b/docs/html/shareables/training/OpenGLES.zip new file mode 100644 index 0000000000000000000000000000000000000000..862ae1f879846fa2d83f1c8b6328b067bf3e2d01 Binary files /dev/null and b/docs/html/shareables/training/OpenGLES.zip differ diff --git a/docs/html/sitemap-intl.txt b/docs/html/sitemap-intl.txt index ded0554b3c4109a1f956f29994d2297b8fa4ba85..9041581db6e8142457d125d728ffd0ba536366a5 100644 --- a/docs/html/sitemap-intl.txt +++ b/docs/html/sitemap-intl.txt @@ -1,11 +1,11 @@ http://developer.android.com/ja/sdk/1.5_r3/installing.html http://developer.android.com/ja/community/index.html http://developer.android.com/ja/index.html -http://developer.android.com/ja/guide/publishing/versioning.html -http://developer.android.com/ja/guide/publishing/app-signing.html -http://developer.android.com/ja/guide/publishing/preparing.html +http://developer.android.com/ja/tools/publishing/versioning.html +http://developer.android.com/ja/tools/publishing/app-signing.html +http://developer.android.com/ja/tools/publishing/preparing.html http://developer.android.com/ja/guide/tutorials/hello-world.html -http://developer.android.com/ja/guide/topics/fundamentals.html +http://developer.android.com/ja/guide/components/fundamentals.html http://developer.android.com/ja/guide/index.html http://developer.android.com/ja/guide/basics/what-is-android.html http://developer.android.com/ja/guide/developing/other-ide.html diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt index 3f26dd06362539dad86c3922532c1a95be26ec3e..ee85bd436fa606fcff8c5821c9794d4cccb58769 100644 --- a/docs/html/sitemap.txt +++ b/docs/html/sitemap.txt @@ -5,32 +5,32 @@ http://developer.android.com/guide/index.html http://developer.android.com/reference/packages.html http://developer.android.com/resources/index.html http://developer.android.com/videos/index.html -http://developer.android.com/resources/dashboard/platform-versions.html +http://developer.android.com/about/dashboards/index.html http://developer.android.com/license.html -http://developer.android.com/sdk/installing.html -http://developer.android.com/sdk/android-3.0-highlights.html +http://developer.android.com/sdk/installing/index.html +http://developer.android.com/about/versions/android-3.0-highlights.html http://developer.android.com/sdk/preview/index.html -http://developer.android.com/sdk/adding-components.html -http://developer.android.com/sdk/android-2.3.html -http://developer.android.com/sdk/android-2.3-highlights.html +http://developer.android.com/sdk/exploring.html +http://developer.android.com/about/versions/android-2.3.html +http://developer.android.com/about/versions/android-2.3-highlights.html http://developer.android.com/sdk/api_diff/9/changes.html -http://developer.android.com/sdk/android-2.2.html -http://developer.android.com/sdk/android-2.1.html -http://developer.android.com/sdk/android-1.6.html -http://developer.android.com/sdk/android-1.5.html -http://developer.android.com/sdk/android-2.0.1.html -http://developer.android.com/sdk/android-2.0.html -http://developer.android.com/sdk/android-1.1.html -http://developer.android.com/sdk/tools-notes.html +http://developer.android.com/about/versions/android-2.2.html +http://developer.android.com/about/versions/android-2.1.html +http://developer.android.com/about/versions/android-1.6.html +http://developer.android.com/about/versions/android-1.5.html +http://developer.android.com/about/versions/android-2.0.1.html +http://developer.android.com/about/versions/android-2.0.html +http://developer.android.com/about/versions/android-1.1.html +http://developer.android.com/tools/sdk/tools-notes.html http://developer.android.com/sdk/win-usb.html http://developer.android.com/sdk/eclipse-adt.html http://developer.android.com/sdk/ndk/index.html http://developer.android.com/sdk/ndk/overview.html -http://developer.android.com/sdk/oem-usb.html +http://developer.android.com/tools/extras/oem-usb.html http://developer.android.com/sdk/requirements.html http://developer.android.com/sdk/older_releases.html http://developer.android.com/guide/basics/what-is-android.html -http://developer.android.com/guide/topics/fundamentals.html +http://developer.android.com/guide/components/fundamentals.html http://developer.android.com/guide/topics/ui/index.html http://developer.android.com/guide/topics/ui/declaring-layout.html http://developer.android.com/guide/topics/ui/menus.html @@ -58,7 +58,7 @@ http://developer.android.com/guide/topics/resources/menu-resource.html http://developer.android.com/guide/topics/resources/string-resource.html http://developer.android.com/guide/topics/resources/style-resource.html http://developer.android.com/guide/topics/resources/more-resources.html -http://developer.android.com/guide/topics/intents/intents-filters.html +http://developer.android.com/guide/components/intents-filters.html http://developer.android.com/guide/topics/data/data-storage.html http://developer.android.com/guide/topics/data/backup.html http://developer.android.com/guide/topics/providers/content-providers.html @@ -93,62 +93,62 @@ http://developer.android.com/guide/topics/graphics/2d-graphics.html http://developer.android.com/guide/topics/graphics/opengl.html http://developer.android.com/guide/topics/media/index.html http://developer.android.com/guide/topics/location/index.html -http://developer.android.com/guide/topics/location/obtaining-user-location.html +http://developer.android.com/guide/topics/location/strategies.html http://developer.android.com/guide/topics/appwidgets/index.html -http://developer.android.com/guide/topics/wireless/bluetooth.html +http://developer.android.com/guide/topics/connectivity/bluetooth.html http://developer.android.com/guide/topics/search/index.html http://developer.android.com/guide/topics/search/search-dialog.html http://developer.android.com/guide/topics/search/adding-recent-query-suggestions.html http://developer.android.com/guide/topics/search/adding-custom-suggestions.html http://developer.android.com/guide/topics/search/searchable-config.html http://developer.android.com/guide/topics/admin/device-admin.html -http://developer.android.com/guide/topics/testing/index.html -http://developer.android.com/guide/topics/testing/testing_android.html -http://developer.android.com/guide/topics/testing/activity_testing.html -http://developer.android.com/guide/topics/testing/contentprovider_testing.html -http://developer.android.com/guide/topics/testing/service_testing.html -http://developer.android.com/guide/topics/testing/what_to_test.html -http://developer.android.com/guide/market/licensing/index.html -http://developer.android.com/guide/market/billing/index.html -http://developer.android.com/guide/market/billing/billing_about.html -http://developer.android.com/guide/market/billing/billing_overview.html -http://developer.android.com/guide/market/billing/billing_integrate.html -http://developer.android.com/guide/market/billing/billing_best_practices.html -http://developer.android.com/guide/market/billing/billing_testing.html -http://developer.android.com/guide/market/billing/billing_admin.html -http://developer.android.com/guide/market/billing/billing_reference.html -http://developer.android.com/guide/appendix/market-filters.html +http://developer.android.com/tools/testing/index.html +http://developer.android.com/tools/testing/testing_android.html +http://developer.android.com/tools/testing/activity_testing.html +http://developer.android.com/tools/testing/contentprovider_testing.html +http://developer.android.com/tools/testing/service_testing.html +http://developer.android.com/tools/testing/what_to_test.html +http://developer.android.com/guide/google/play/licensing/index.html +http://developer.android.com/guide/google/play/billing/index.html +http://developer.android.com/guide/google/play/billing/billing_about.html +http://developer.android.com/guide/google/play/billing/billing_overview.html +http://developer.android.com/guide/google/play/billing/billing_integrate.html +http://developer.android.com/guide/google/play/billing/billing_best_practices.html +http://developer.android.com/guide/google/play/billing/billing_testing.html +http://developer.android.com/guide/google/play/billing/billing_admin.html +http://developer.android.com/guide/google/play/billing/billing_reference.html +http://developer.android.com/guide/google/play/filters.html http://developer.android.com/guide/developing/eclipse-adt.html http://developer.android.com/guide/developing/other-ide.html -http://developer.android.com/guide/developing/device.html +http://developer.android.com/tools/device.html http://developer.android.com/guide/developing/debug-tasks.html -http://developer.android.com/guide/developing/testing/index.html -http://developer.android.com/guide/developing/testing/testing_eclipse.html -http://developer.android.com/guide/developing/testing/testing_otheride.html -http://developer.android.com/guide/developing/tools/index.html -http://developer.android.com/guide/developing/tools/aapt.html -http://developer.android.com/guide/developing/tools/adb.html -http://developer.android.com/guide/developing/tools/othertools.html -http://developer.android.com/guide/developing/tools/aidl.html -http://developer.android.com/guide/developing/tools/avd.html -http://developer.android.com/guide/developing/tools/bmgr.html -http://developer.android.com/guide/developing/tools/ddms.html -http://developer.android.com/guide/developing/tools/draw9patch.html -http://developer.android.com/guide/developing/tools/emulator.html -http://developer.android.com/guide/developing/tools/hierarchy-viewer.html -http://developer.android.com/guide/developing/tools/layoutopt.html -http://developer.android.com/guide/developing/tools/monkey.html -http://developer.android.com/guide/developing/tools/monkeyrunner_concepts.html -http://developer.android.com/guide/developing/tools/MonkeyDevice.html -http://developer.android.com/guide/developing/tools/MonkeyImage.html -http://developer.android.com/guide/developing/tools/MonkeyRunner.html -http://developer.android.com/guide/developing/tools/proguard.html -http://developer.android.com/guide/developing/tools/traceview.html -http://developer.android.com/guide/developing/tools/zipalign.html -http://developer.android.com/guide/publishing/app-signing.html -http://developer.android.com/guide/publishing/versioning.html -http://developer.android.com/guide/publishing/preparing.html -http://developer.android.com/guide/publishing/publishing.html +http://developer.android.com/tools/testing/index.html +http://developer.android.com/tools/testing/testing_eclipse.html +http://developer.android.com/tools/testing/testing_otheride.html +http://developer.android.com/tools/index.html +http://developer.android.com/tools/aapt.html +http://developer.android.com/tools/help/adb.html +http://developer.android.com/tools/othertools.html +http://developer.android.com/tools/aidl.html +http://developer.android.com/tools/avd.html +http://developer.android.com/tools/bmgr.html +http://developer.android.com/tools/ddms.html +http://developer.android.com/tools/draw9patch.html +http://developer.android.com/tools/help/emulator.html +http://developer.android.com/tools/hierarchy-viewer.html +http://developer.android.com/tools/help/layoutopt.html +http://developer.android.com/tools/monkey.html +http://developer.android.com/tools/monkeyrunner_concepts.html +http://developer.android.com/tools/MonkeyDevice.html +http://developer.android.com/tools/MonkeyImage.html +http://developer.android.com/tools/MonkeyRunner.html +http://developer.android.com/tools/proguard.html +http://developer.android.com/tools/traceview.html +http://developer.android.com/tools/zipalign.html +http://developer.android.com/tools/publishing/app-signing.html +http://developer.android.com/tools/publishing/versioning.html +http://developer.android.com/tools/publishing/preparing.html +http://developer.android.com/tools/publishing/publishing.html http://developer.android.com/guide/practices/compatibility.html http://developer.android.com/guide/practices/screens_support.html http://developer.android.com/guide/practices/ui_guidelines/index.html @@ -160,15 +160,15 @@ http://developer.android.com/guide/practices/ui_guidelines/icon_design_tab.html http://developer.android.com/guide/practices/ui_guidelines/icon_design_dialog.html http://developer.android.com/guide/practices/ui_guidelines/icon_design_list.html http://developer.android.com/guide/practices/ui_guidelines/widget_design.html -http://developer.android.com/guide/practices/design/performance.html -http://developer.android.com/guide/practices/design/responsiveness.html -http://developer.android.com/guide/practices/design/seamlessness.html +http://developer.android.com/guide/practices/performance.html +http://developer.android.com/guide/practices/responsiveness.html +http://developer.android.com/guide/practices/seamlessness.html http://developer.android.com/guide/webapps/index.html http://developer.android.com/guide/webapps/targeting.html http://developer.android.com/guide/webapps/webview.html http://developer.android.com/guide/webapps/debugging.html http://developer.android.com/guide/webapps/best-practices.html -http://developer.android.com/guide/appendix/api-levels.html +http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels http://developer.android.com/guide/appendix/install-location.html http://developer.android.com/guide/appendix/media-formats.html http://developer.android.com/guide/appendix/g-app-intents.html @@ -209,12 +209,12 @@ http://developer.android.com/resources/articles/wikinotes-linkify.html http://developer.android.com/resources/articles/wikinotes-intents.html http://developer.android.com/resources/articles/window-bg-speed.html http://developer.android.com/resources/articles/zipalign.html -http://developer.android.com/resources/tutorials/hello-world.html +http://developer.android.com/training/basics/firstapp/index.html http://developer.android.com/resources/tutorials/views/index.html http://developer.android.com/resources/tutorials/localization/index.html http://developer.android.com/resources/tutorials/testing/helloandroid_test.html http://developer.android.com/resources/tutorials/notepad/index.html -http://developer.android.com/resources/tutorials/testing/activity_test.html +http://developer.android.com/tools/testing/activity_test.html http://developer.android.com/resources/samples/get.html http://developer.android.com/resources/samples/index.html http://developer.android.com/resources/samples/AccelerometerPlay/index.html @@ -404,7 +404,7 @@ http://developer.android.com/reference/android/app/NativeActivity.html http://developer.android.com/reference/android/opengl/GLSurfaceView.html http://developer.android.com/reference/android/graphics/Bitmap.html http://developer.android.com/sdk/api_diff/3/changes.html -http://developer.android.com/sdk/android-1.5-highlights.html +http://developer.android.com/about/versions/android-1.5-highlights.html http://developer.android.com/reference/android/widget/SlidingDrawer.html http://developer.android.com/reference/android/widget/HorizontalScrollView.html http://developer.android.com/reference/android/provider/LiveFolders.html @@ -412,7 +412,7 @@ http://developer.android.com/reference/android/inputmethodservice/InputMethodSer http://developer.android.com/reference/android/speech/RecognizerIntent.html http://developer.android.com/reference/android/hardware/SensorManager.html http://developer.android.com/sdk/api_diff/6/changes.html -http://developer.android.com/sdk/android-2.0-highlights.html +http://developer.android.com/about/versions/android-2.0-highlights.html http://developer.android.com/reference/android/widget/QuickContactBadge.html http://developer.android.com/reference/android/content/Intent.html http://developer.android.com/reference/android/content/Context.html @@ -503,7 +503,7 @@ http://developer.android.com/reference/java/lang/String.html http://developer.android.com/reference/java/text/Normalizer.html http://developer.android.com/reference/java/text/Normalizer.Form.html http://developer.android.com/sdk/api_diff/8/changes.html -http://developer.android.com/sdk/android-2.2-highlights.html +http://developer.android.com/about/versions/android-2.2-highlights.html http://developer.android.com/reference/android/opengl/ETC1.html http://developer.android.com/reference/android/opengl/ETC1Util.html http://developer.android.com/reference/android/opengl/ETC1Util.ETC1Texture.html @@ -540,7 +540,7 @@ http://developer.android.com/reference/android/os/Process.html http://developer.android.com/reference/android/widget/TextView.html http://developer.android.com/reference/android/Manifest.permission.html http://developer.android.com/sdk/api_diff/4/changes.html -http://developer.android.com/sdk/android-1.6-highlights.html +http://developer.android.com/about/versions/android-1.6-highlights.html http://developer.android.com/reference/android/view/View.OnClickListener.html http://developer.android.com/reference/android/app/SearchManager.html http://developer.android.com/reference/android/telephony/SmsManager.html @@ -942,7 +942,7 @@ http://developer.android.com/reference/android/net/http/SslError.html http://developer.android.com/reference/org/apache/http/impl/client/DefaultHttpClient.html http://developer.android.com/reference/org/apache/http/HttpRequestInterceptor.html http://developer.android.com/reference/android/content/pm/PackageItemInfo.html -http://developer.android.com/guide/developing/tools/adt.html +http://developer.android.com/tools/adt.html http://developer.android.com/reference/android/graphics/NinePatch.html http://developer.android.com/reference/android/preference/Preference.OnPreferenceChangeListener.html http://developer.android.com/reference/android/preference/Preference.OnPreferenceClickListener.html @@ -5020,7 +5020,7 @@ http://developer.android.com/sdk/api_diff/4/changes/fields_index_changes.html http://developer.android.com/resources/samples/MultiResolution/res/drawable-ldpi-v6/ic_launcher.html http://developer.android.com/reference/android/app/package-descr.html http://developer.android.com/resources/samples/TicTacToeLib/res/layout/lib_game.html -http://developer.android.com/guide/market/billing/billing-intents +http://developer.android.com/guide/google/play/billing/billing-intents http://developer.android.com/resources/samples/TicTacToeLib/res/values/strings.html http://developer.android.com/resources/samples/ApiDemos/res/values-normal-notlong/strings.html http://developer.android.com/resources/samples/TicTacToeMain/src/com/example/android/index.html diff --git a/docs/html/support.jd b/docs/html/support.jd new file mode 100644 index 0000000000000000000000000000000000000000..89acd5db45c0010abbb6e4f479b5723da0b0359f --- /dev/null +++ b/docs/html/support.jd @@ -0,0 +1,74 @@ +page.title=Developer Support +fullpage=1 +@jd:body + +
    + +

    Developer Support Resources

    + +
    + +
    +

    Code-Level Support

    + +
    Community and Office Hours
    +

    + +android-developers support forum
    +android-ndk support forum
    +android-security-discuss support forum
    + + #android, #android-dev (IRC via irc.freenode.net)
    + +Android Developers Office Hours (Wednesdays 2 PM PST (UTC-7))
    +

    + + +
    Send Feedback
    +

    + Report documentation bug
    + Report device bug
    + Report platform bug
    + +

    + + + + +
    \ No newline at end of file diff --git a/docs/html/guide/developing/tools/aidl.jd b/docs/html/tools/aidl.jd similarity index 97% rename from docs/html/guide/developing/tools/aidl.jd rename to docs/html/tools/aidl.jd index 731aef7e77515c0ab79774be9ea199b65f02a03d..805b7ec216d216611d62e06ff891c01d07b22c5c 100644 --- a/docs/html/guide/developing/tools/aidl.jd +++ b/docs/html/tools/aidl.jd @@ -19,7 +19,7 @@ page.title=Android Interface Definition Language (AIDL)

    See also

      -
    1. Bound Services
    2. +
    3. Bound Services
    @@ -38,12 +38,12 @@ do that marshalling is tedious to write, so Android handles it for you with AIDL different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a +href="{@docRoot}guide/components/bound-services.html#Binder">implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. +href="{@docRoot}guide/components/bound-services.html#Messenger">using a Messenger. Regardless, be sure that you understand Bound Services before +href="{@docRoot}guide/components/bound-services.html">Bound Services before implementing an AIDL.

    Before you begin designing your AIDL interface, be aware that calls to an AIDL interface are @@ -57,7 +57,7 @@ this is your main UI thread, that thread continues to execute in the AIDL interf another thread, that is the one that executes your code in the service. Thus, if only local threads are accessing the service, you can completely control which threads are executing in it (but if that is the case, then you shouldn't be using AIDL at all, but should instead create the -interface by implementing a +interface by implementing a Binder).

  • Calls from a remote process are dispatched from a thread pool the platform maintains inside of @@ -456,7 +456,7 @@ android.content.Context#unbindService(android.content.ServiceConnection)

    For more information about binding to a service, read the Bound Services +href="{@docRoot}guide/components/bound-services.html#Binding">Bound Services document.

    Here is some sample code demonstrating calling an AIDL-created service, taken diff --git a/docs/html/guide/developing/tools/avd.html b/docs/html/tools/avd.html similarity index 56% rename from docs/html/guide/developing/tools/avd.html rename to docs/html/tools/avd.html index c8455db1bcb33849e6a37dc4d62929a2e4226519..1d314a10c71491e3d8252515213720b9672ef27a 100644 --- a/docs/html/guide/developing/tools/avd.html +++ b/docs/html/tools/avd.html @@ -1,10 +1,10 @@ - + Redirecting...

    You should be redirected. Please click here.

    +href="http://developer.android.com/tools/devices/index.html">click here.

    \ No newline at end of file diff --git a/docs/html/guide/developing/building/building-cmdline.jd b/docs/html/tools/building/building-cmdline.jd similarity index 94% rename from docs/html/guide/developing/building/building-cmdline.jd rename to docs/html/tools/building/building-cmdline.jd index fd90b1a5a7f14bc88979aed77c311f05a7b24cc8..6154d96e63536521a028c2035b6238f07e1ce455 100644 --- a/docs/html/guide/developing/building/building-cmdline.jd +++ b/docs/html/tools/building/building-cmdline.jd @@ -22,11 +22,11 @@ parent.link=index.html

    See also

      -
    1. Managing AVDs from +
    2. Managing AVDs from the Command Line
    3. -
    4. Using the Android +
    5. Using the Android Emulator
    6. -
    7. Signing Your Applications
    8. +
    9. Signing Your Applications
  • @@ -46,7 +46,7 @@ Emulator must manually sign it with your own private key, using Keytool and Jarsigner.

    It's important that you read and understand Signing Your Applications, particularly once + "{@docRoot}tools/publishing/app-signing.html">Signing Your Applications, particularly once you're ready to release your application and share it with end-users. That document describes the procedure for generating a private key and then using it to sign your .apk file. If you're just getting started, however, you can quickly run your applications on an emulator or your own @@ -84,7 +84,7 @@ ant debug

    This creates your debug .apk file inside the project bin/ directory, named <your_project_name>-debug.apk. The file is already signed with the debug key and has been aligned with - zipalign. + zipalign.

    @@ -132,7 +132,7 @@ ant release

    Once you have created the unsigned .apk, your next step is to sign the .apk with your private key and then align it with {@code zipalign}. To complete this procedure, read Signing Your Applications.

    + "{@docRoot}tools/publishing/app-signing.html">Signing Your Applications.

    When your .apk has been signed and aligned, it's ready to be distributed to end-users. You should test the final build on different devices or AVDs to ensure that it @@ -151,7 +151,7 @@ ant release your keystore and alias password being visible on screen, then you may prefer to perform the application signing manually, via Jarsigner (or a similar tool). To instead perform the signing procedure manually, build unsigned and then continue with - Signing Your Applications.

    + Signing Your Applications.

    To specify your keystore and alias, open the project {@code ant.properties} file (found in the root of the project directory) and add entries for {@code key.store} and {@code key.alias}. @@ -196,7 +196,7 @@ ant release

    Running on the Emulator

    Before you can run your application on the Android Emulator, you must create an AVD.

    + "{@docRoot}tools/devices/managing-avds.html">create an AVD.

    To run your application:

    @@ -267,7 +267,7 @@ adb -s emulator-5554 install path/to/your/app.apk
  • Ensure that your development computer can detect your device when connected via USB
  • -

    Read Setting up a Device for +

    Read Setting up a Device for Development for more information.

    Once your device is set up and connected via USB, navigate to your SDK's platform-tools/ @@ -282,11 +282,11 @@ adb -d install path/to/your/app.apk

    For more information on the tools used above, please see the following documents:

    Application Signing

    @@ -309,7 +309,7 @@ adb -d install path/to/your/app.apk you intend to publish your application, you must sign the application with your own private key, rather than the debug key generated by the SDK tools.

    -

    Please read Signing Your +

    Please read Signing Your Applications, which provides a thorough guide to application signing on Android and what it means to you as an Android application developer. The document also includes a guide to exporting and signing your application with the ADT's Export Wizard.

    diff --git a/docs/html/guide/developing/building/building-eclipse.jd b/docs/html/tools/building/building-eclipse.jd similarity index 96% rename from docs/html/guide/developing/building/building-eclipse.jd rename to docs/html/tools/building/building-eclipse.jd index 6ebc49ef57e34c9335cf45944b18bec9097deaa6..c73fe974410d8d111f758a768ce7af37a7df123a 100644 --- a/docs/html/guide/developing/building/building-eclipse.jd +++ b/docs/html/tools/building/building-eclipse.jd @@ -34,12 +34,12 @@ parent.link=index.html

    This document shows you how to run your application on an emulator or a real device from Eclipse—all of which is done using the debug version of your application. For more information about how to sign your application with a private key for release, see Signing Your Applications

    + "{@docRoot}tools/publishing/app-signing.html#ExportWizard">Signing Your Applications

    Running on the emulator

    Before you can run your application on the Android Emulator, you must create an AVD.

    + "{@docRoot}tools/devices/managing-avds.html">create an AVD.

    To run (or debug) your application, select Run > Run (or Run > Debug) from the Eclipse menu bar. The ADT plugin will @@ -90,7 +90,7 @@ parent.link=index.html

  • Ensure that your development computer can detect your device when connected via USB
  • -

    Read Using Hardware Devices +

    Read Using Hardware Devices for more information.

    Once set up and your device is connected via USB, install your application on the device by @@ -127,7 +127,7 @@ parent.link=index.html

    You can specify any emulator options to the Additional Emulator Command Line Options field. For example, you could add -scale 96dpi to scale the AVD's screen to an accurate size, based on the dpi of your computer monitor. For a full list of emulator - options, see the Android + options, see the Android Emulator document.

    diff --git a/docs/html/guide/developing/building/index.jd b/docs/html/tools/building/index.jd similarity index 98% rename from docs/html/guide/developing/building/index.jd rename to docs/html/tools/building/index.jd index 569cd28387b8ae6608585889478a26a714750635..c64942ff7d2548ebea71fb695d05c9d1fbb0f4ae 100644 --- a/docs/html/guide/developing/building/index.jd +++ b/docs/html/tools/building/index.jd @@ -33,7 +33,7 @@ page.title=Building and Running

    Fortunately, Eclipse or your Ant build script signs the application for you in debug mode when you build your application. You can also easily setup Eclipse or your Ant build to sign your application in release mode as well. For more information on signing applications, see Signing Your Applications.

    + "{@docRoot}tools/publishing/app-signing.html">Signing Your Applications.

    The following diagram depicts the components involved in building and running an application:

    diff --git a/docs/html/guide/developing/debug-tasks.html b/docs/html/tools/debug-tasks.html similarity index 55% rename from docs/html/guide/developing/debug-tasks.html rename to docs/html/tools/debug-tasks.html index 4e738041a315b681747b13e088ba4dffc14587fd..2a5bc511242e3445e6f6d9d6cbce4ef3238eae04 100644 --- a/docs/html/guide/developing/debug-tasks.html +++ b/docs/html/tools/debug-tasks.html @@ -1,10 +1,10 @@ - + Redirecting...

    You should be redirected. Please click here.

    +href="http://developer.android.com/tools/debugging/index.html">click here.

    \ No newline at end of file diff --git a/docs/html/guide/developing/debugging/ddms.jd b/docs/html/tools/debugging/ddms.jd similarity index 97% rename from docs/html/guide/developing/debugging/ddms.jd rename to docs/html/tools/debugging/ddms.jd index 9892e49f1eece3c48a2d1c1801d95a69a5d54b24..3d6324b7a7e958cbba8ab32e5315ae365aa1bc3e 100644 --- a/docs/html/guide/developing/debugging/ddms.jd +++ b/docs/html/tools/debugging/ddms.jd @@ -51,7 +51,7 @@ parent.link=index.html

    On Android, every application runs in its own process, each of which runs in its own virtual machine (VM). Each VM exposes a unique port that a debugger can attach to.

    -

    When DDMS starts, it connects to adb. +

    When DDMS starts, it connects to adb. When a device is connected, a VM monitoring service is created between adb and DDMS, which notifies DDMS when a VM on the device is started or terminated. Once a VM is running, DDMS retrieves the the VM's process ID (pid), via adb, and opens a connection to the @@ -82,7 +82,7 @@ parent.link=index.html Screenshot of DDMS

    If you are not using Eclipse and ADT, read Configuring + "{@docRoot}tools/debugging/debugging-projects-cmdline.html#debuggingPort">Configuring your IDE to attach to the debugging port, for more information on attaching your debugger.

    @@ -208,7 +208,7 @@ parent.link=index.html
  • Interact with your application to start the methods that you want to profile.
  • Click the Stop Method Profiling button. DDMS stops profiling your - application and opens Traceview + application and opens Traceview with the method profiling information that was collected between the time you clicked on Start Method Profiling and Stop Method Profiling.
  • @@ -279,7 +279,7 @@ displayed on devices running Android 4.0.3 or higher.

    LogCat is integrated into DDMS, and outputs the messages that you print out using the {@link android.util.Log} class along with other system messages such as stack traces when exceptions are thrown. View the - Reading and + Reading and Writing Log Messages. topic for more information on how to log messages to the LogCat.

    When you have set up your logging, you can use the LogCat feature of DDMS to filter certain @@ -353,5 +353,5 @@ displayed on devices running Android 4.0.3 or higher.

    For more information about providing mock location data, see - Obtaining User Location. + Location Strategies. diff --git a/docs/html/guide/developing/debugging/debugging-devtools.jd b/docs/html/tools/debugging/debugging-devtools.jd similarity index 84% rename from docs/html/guide/developing/debugging/debugging-devtools.jd rename to docs/html/tools/debugging/debugging-devtools.jd index 157d62e6c2d985a20ef12ee2a1cf02a57a2a93b5..3a051200422b62b51c7918778f086cd4dcda3cb8 100644 --- a/docs/html/guide/developing/debugging/debugging-devtools.jd +++ b/docs/html/tools/debugging/debugging-devtools.jd @@ -7,18 +7,10 @@ parent.link=index.html so you can use it with the Android Emulator. With the Dev Tools application, you can enable a number of settings on your device that will make it easier to test and debug your applications.

    -

    If you'd like to install the Dev Tools application - on a real development device, you can copy the application from your emulator and then install it - on your device using ADB. To copy the application from a running emulator, execute:

    -
    -adb -e pull /system/app/Development.apk ./Development.apk
    -
    - -

    This copies the .apk file into the current directory. Then install it on your connected device - with:

    -
    -adb -d install Development.apk
    -
    +

    The Dev Tools application relies on a number of permissions that are not available for + third party applications. If you'd like to install the Dev Tools application + on a real development device, you'd have to build a system image for that device and sign + the Dev Tools application with the same key as used for the system image.

    To get started, launch the Dev Tools application and select Development Settings. This will open the Development Settings page with the following options (among others):

    @@ -62,7 +54,7 @@ adb -d install Development.apk android.app.Activity#onCreate(android.os.Bundle)} code path, which would otherwise be difficult to force. Choosing this option will probably reveal a number of problems in your application due to not saving state. For more information about saving an activity's state, see the - Activities + Activities document.
    Show CPU usage
    diff --git a/docs/html/guide/developing/debugging/debugging-log.jd b/docs/html/tools/debugging/debugging-log.jd similarity index 99% rename from docs/html/guide/developing/debugging/debugging-log.jd rename to docs/html/tools/debugging/debugging-log.jd index b5b626e9bf3a59dc2ae2093b3e625a02443e8dfe..d2baaf26ce84c31de99c1856c01876c449c66dbd 100644 --- a/docs/html/guide/developing/debugging/debugging-log.jd +++ b/docs/html/tools/debugging/debugging-log.jd @@ -59,7 +59,7 @@ I/MyActivity( 1557): MyClass.getView() — get item number 1

    Using LogCat

    You can use LogCat from within DDMS or call it on an ADB shell. For more information on how to - use LogCat within DDMS, see Using + use LogCat within DDMS, see Using DDMS. To run LogCat, through the ADB shell, the general usage is:

     [adb] logcat [<option>] ... [<filter-spec>] ...
    diff --git a/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd b/docs/html/tools/debugging/debugging-projects-cmdline.jd
    similarity index 95%
    rename from docs/html/guide/developing/debugging/debugging-projects-cmdline.jd
    rename to docs/html/tools/debugging/debugging-projects-cmdline.jd
    index 3b5ceabaf3ba82ba8e9667c60a5fce58ba21e105..0b79575903a3726002882bca2d0c407d6dce54f6 100644
    --- a/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd
    +++ b/docs/html/tools/debugging/debugging-projects-cmdline.jd
    @@ -22,9 +22,9 @@ parent.link=index.html
       the Android SDK provides for debugging. A basic debugging environment consists of:

    diff --git a/docs/html/guide/developing/debugging/debugging-projects.jd b/docs/html/tools/debugging/debugging-projects.jd similarity index 100% rename from docs/html/guide/developing/debugging/debugging-projects.jd rename to docs/html/tools/debugging/debugging-projects.jd diff --git a/docs/html/guide/developing/debugging/debugging-tracing.jd b/docs/html/tools/debugging/debugging-tracing.jd similarity index 99% rename from docs/html/guide/developing/debugging/debugging-tracing.jd rename to docs/html/tools/debugging/debugging-tracing.jd index 72f64982d9a892e871b5b945dc545b756d90f786..f0d0c0b52d6e1b517bdbc6e29c09b1fdca6c6927 100644 --- a/docs/html/guide/developing/debugging/debugging-tracing.jd +++ b/docs/html/tools/debugging/debugging-tracing.jd @@ -295,7 +295,7 @@ traceview /tmp/calc

    Note: If you are trying to view the trace logs of an application that is built with ProGuard enabled (release mode build), some method and member names might be obfuscated. You can use the Proguard mapping.txt file to figure out the original unobfuscated names. For more information - on this file, see the Proguard documentation.

    + on this file, see the Proguard documentation.

    Using dmtracdedump

    diff --git a/docs/html/guide/developing/debugging/debugging-ui.jd b/docs/html/tools/debugging/debugging-ui.jd similarity index 97% rename from docs/html/guide/developing/debugging/debugging-ui.jd rename to docs/html/tools/debugging/debugging-ui.jd index 22748be93cddd94f4fdf5dfed6ccd86b7b2cb0cc..c1976b8de2ea3e85f5b85ba73e282da71ce2fdcd 100644 --- a/docs/html/guide/developing/debugging/debugging-ui.jd +++ b/docs/html/tools/debugging/debugging-ui.jd @@ -1,4 +1,4 @@ -page.title=Debugging and Profiling User Interfaces +page.title=Optimizing Your UI parent.title=Debugging parent.link=index.html @jd:body @@ -10,7 +10,7 @@ parent.link=index.html
    1. - Debugging and Optimizing User Interfaces with Hierarchy Viewer + Using Hierarchy Viewer
      1. Running Hierarchy Viewer and choosing a window
      2. @@ -22,27 +22,27 @@ parent.link=index.html
      3. - Examining and Designing User Interfaces with Pixel Perfect + Using Pixel Perfect
        1. About the Pixel Perfect window
        2. Working with Pixel Perfect overlays
      4. -
      5. Optimizing Layouts with layoutopt
      6. +
      7. Using layoutopt

      Related videos