diff options
22 files changed, 1329 insertions, 40 deletions
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java index b8575d7..68ea9e9 100644 --- a/core/java/android/app/backup/WallpaperBackupHelper.java +++ b/core/java/android/app/backup/WallpaperBackupHelper.java @@ -39,6 +39,11 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu private static final String TAG = "WallpaperBackupHelper"; private static final boolean DEBUG = false; + // If 'true', then apply an acceptable-size heuristic at restore time, dropping back + // to the factory default wallpaper if the restored one differs "too much" from the + // device's preferred wallpaper image dimensions. + private static final boolean REJECT_OUTSIZED_RESTORE = false; + // This path must match what the WallpaperManagerService uses // TODO: Will need to change if backing up non-primary user's wallpaper public static final String WALLPAPER_IMAGE = @@ -130,27 +135,36 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu if (DEBUG) Slog.d(TAG, "Restoring wallpaper image w=" + options.outWidth + " h=" + options.outHeight); - // We accept any wallpaper that is at least as wide as our preference - // (i.e. wide enough to fill the screen), and is within a comfortable - // factor of the target height, to avoid significant clipping/scaling/ - // letterboxing. - final double heightRatio = mDesiredMinHeight / options.outHeight; - if (options.outWidth >= mDesiredMinWidth - && heightRatio > 0 && heightRatio < 1.33) { - // sufficiently close to our resolution; go ahead and use it - Slog.d(TAG, "Applying restored wallpaper image."); - f.renameTo(new File(WALLPAPER_IMAGE)); - // TODO: spin a service to copy the restored image to sd/usb storage, - // since it does not exist anywhere other than the private wallpaper - // file. - } else { - Slog.i(TAG, "Restored image dimensions (w=" - + options.outWidth + ", h=" + options.outHeight - + ") too far off target (tw=" - + mDesiredMinWidth + ", th=" + mDesiredMinHeight - + "); falling back to default wallpaper."); - f.delete(); + if (REJECT_OUTSIZED_RESTORE) { + // We accept any wallpaper that is at least as wide as our preference + // (i.e. wide enough to fill the screen), and is within a comfortable + // factor of the target height, to avoid significant clipping/scaling/ + // letterboxing. + final double heightRatio = mDesiredMinHeight / options.outHeight; + if (options.outWidth < mDesiredMinWidth + || heightRatio <= 0 + || heightRatio >= 1.33) { + // Not wide enough for the screen, or too short/tall to be a good fit + // for the height of the screen, broken image file, or the system's + // desires for wallpaper size are in a bad state. Probably one of the + // first two. + Slog.i(TAG, "Restored image dimensions (w=" + + options.outWidth + ", h=" + options.outHeight + + ") too far off target (tw=" + + mDesiredMinWidth + ", th=" + mDesiredMinHeight + + "); falling back to default wallpaper."); + f.delete(); + return; + } } + + // We passed the acceptable-dimensions test (if any), so we're going to + // use the restored image. + // TODO: spin a service to copy the restored image to sd/usb storage, + // since it does not exist anywhere other than the private wallpaper + // file. + Slog.d(TAG, "Applying restored wallpaper image."); + f.renameTo(new File(WALLPAPER_IMAGE)); } } else if (key.equals(WALLPAPER_INFO_KEY)) { // XML file containing wallpaper info diff --git a/docs/html/sdk/download.jd b/docs/html/sdk/download.jd index 4329102..52432cf 100644 --- a/docs/html/sdk/download.jd +++ b/docs/html/sdk/download.jd @@ -14,9 +14,9 @@ hide_license_footer=true if (location.indexOf('?v=') != -1) { var filename = location.substring(location.indexOf('=')+1,location.length); if (document.getElementById('checkbox').checked) { - document.location = "http://dl.google.com/android/" + filename; + document.location = "https://dl.google.com/android/" + filename; } - document.getElementById('click-download').setAttribute("href", "http://dl.google.com/android/" + document.getElementById('click-download').setAttribute("href", "https://dl.google.com/android/" + filename); $("#terms-form").hide(500); $("#next-steps").show(500); diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd index 469d11f..deafed5 100644 --- a/docs/html/tools/sdk/eclipse-adt.jd +++ b/docs/html/tools/sdk/eclipse-adt.jd @@ -70,8 +70,8 @@ href="http://tools.android.com/knownissues">http://tools.android.com/knownissues <li>Java 1.6 or higher is required if you are targeting other releases.</li> <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li> <li>This version of ADT is designed for use with - <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r23.0.4</a>. - If you haven't already installed SDK Tools r23.0.4 into your SDK, use the + <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r23.0.2</a>. + If you haven't already installed SDK Tools r23.0.2 into your SDK, use the Android SDK Manager to do so.</li> </ul> </dd> diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 4dd57ab..5443c56 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -784,6 +784,34 @@ include the action bar on devices running Android 2.1 or higher." <li class="nav-section"> <div class="nav-section-header"> + <a href="<?cs var:toroot ?>training/wearables/ui/index.html" + description="How to create custom user interfaces for wearable apps." + >Creating Custom UIs</a> + </div> + <ul> + <li> + <a href="<?cs var:toroot ?>training/wearables/ui/layouts.html">Defining Layouts</a> + </li> + <li> + <a href="<?cs var:toroot ?>training/wearables/ui/cards.html">Creating Cards</a> + </li> + <li> + <a href="<?cs var:toroot ?>training/wearables/ui/lists.html">Creating Lists</a> + </li> + <li> + <a href="<?cs var:toroot ?>training/wearables/ui/2d-picker.html">Creating a 2D Picker</a> + </li> + <li> + <a href="<?cs var:toroot ?>training/wearables/ui/confirm.html">Showing Confirmations</a> + </li> + <li> + <a href="<?cs var:toroot ?>training/wearables/ui/exit.html">Exiting Full-Screen Activities</a> + </li> + </ul> + </li> + + <li class="nav-section"> + <div class="nav-section-header"> <a href="<?cs var:toroot ?>training/wearables/data-layer/index.html" description="How to sync data between handhelds and wearables." >Sending and Syncing Data</a> diff --git a/docs/html/training/wearables/ui/2d-picker.jd b/docs/html/training/wearables/ui/2d-picker.jd new file mode 100644 index 0000000..8f4d8af --- /dev/null +++ b/docs/html/training/wearables/ui/2d-picker.jd @@ -0,0 +1,181 @@ +page.title=Creating a 2D Picker + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#add-page-grid">Add a Page Grid</a></li> + <li><a href="#implement-adapter">Implement a Page Adapter</a></li> +</ol> +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li> +</ul> +</div> +</div> + +<p>The <a href="{@docRoot}design/wear/structure.html#2DPicker">2D Picker</a> pattern in Android +Wear allows users to navigate and choose from a set of items shown as pages. The Wearable UI +Library lets you easily implement this pattern using a page grid, which is a layout manager +that allows users to scroll vertically and horizontally through pages of data.</p> + +<p>To implement this pattern, you add a <code>GridViewPager</code> element to the layout +of your activity and implement an adapter that provides a set of pages by extending +the <code>FragmentGridPagerAdapter</code> class.</p> + +<p class="note"><strong>Note:</strong> The <em>GridViewPager</em> sample in the Android SDK +demonstrates how to use the <code>GridViewPager</code> layout in your apps. This sample is +located in the <code>android-sdk/samples/android-20/wearable/GridViewPager</code> directory.</p> + + +<h2 id="add-page-grid">Add a Page Grid</h2> + +<p>Add a <code>GridViewPager</code> element to your layout definition as follows:</p> + +<pre> +<android.support.wearable.view.GridViewPager + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent" /> +</pre> + +<p>You can use any of the techniques described in +<a href="{@docRoot}training/wearables/ui/layouts.html">Defining Layouts</a> to ensure that +your 2D picker works on both round and square devices.</p> + + +<h2 id="implement-adapter">Implement a Page Adapter</h2> + +<p>A page adapter provides a set of pages to populate a <code>GridViewPager</code> component. To +implement this adapter, you extend the <code>FragmentGridPageAdapter</code> class from the +Wearable UI Library</p> + +<p>For example, the <em>GridViewPager</em> sample in the Android SDK contains +the following adapter implementation that provides a set of static cards with custom background +images:</p> + +<pre> +public class SampleGridPagerAdapter extends FragmentGridPagerAdapter { + + private final Context mContext; + + public SampleGridPagerAdapter(Context ctx, FragmentManager fm) { + super(fm); + mContext = ctx; + } + + static final int[] BG_IMAGES = new int[] { + R.drawable.debug_background_1, ... + R.drawable.debug_background_5 + }; + + // A simple container for static data in each page + private static class Page { + // static resources + int titleRes; + int textRes; + int iconRes; + ... + } + + // Create a static set of pages in a 2D array + private final Page[][] PAGES = { ... }; + + // Override methods in FragmentGridPagerAdapter + ... +} +</pre> + +<p>The picker calls <code>getFragment</code> and <code>getBackground</code> to retrieve the content +to display at each position of the grid:</p> + +<pre> +// Obtain the UI fragment at the specified position +@Override +public Fragment getFragment(int row, int col) { + Page page = PAGES[row][col]; + String title = + page.titleRes != 0 ? mContext.getString(page.titleRes) : null; + String text = + page.textRes != 0 ? mContext.getString(page.textRes) : null; + CardFragment fragment = CardFragment.create(title, text, page.iconRes); + + // Advanced settings (card gravity, card expansion/scrolling) + fragment.setCardGravity(page.cardGravity); + fragment.setExpansionEnabled(page.expansionEnabled); + fragment.setExpansionDirection(page.expansionDirection); + fragment.setExpansionFactor(page.expansionFactor); + return fragment; +} + +// Obtain the background image for the page at the specified position +@Override +public ImageReference getBackground(int row, int column) { + return ImageReference.forDrawable(BG_IMAGES[row % BG_IMAGES.length]); +} +</pre> + +<p>The <code>getRowCount</code> method tells the picker how many rows of content are +available, and the <code>getColumnCount</code> method tells the picker how many columns +of content are available for each of the rows.</p> + +<pre> +// Obtain the number of pages (vertical) +@Override +public int getRowCount() { + return PAGES.length; +} + +// Obtain the number of pages (horizontal) +@Override +public int getColumnCount(int rowNum) { + return PAGES[rowNum].length; +} +</pre> + +<p>The adapter implementation details depend on your particular set of pages. Each page provided +by the adapter is of type <code>Fragment</code>. In this example, each page is a +<code>CardFragment</code> instance that uses one of the default card layouts. However, you can +combine different types of pages in the same 2D picker, such as cards, action icons, and custom +layouts depending on your use cases.</p> + +<div style="float:right;margin-left:25px;width:250px"> +<img src="{@docRoot}wear/images/07_uilib.png" width="250" height="250" alt=""/> +<p class="img-caption" style="text-align:center"><strong>Figure 1:</strong> +The <em>GridViewPager</em> sample.</p> +</div> + +<p>Not all rows need to have the same number of pages. Notice that in this example the number of +colums is different for each row. You can also use a <code>GridViewPager</code> component to +implement a 1D picker with only one row or only one column.</p> + +<p><code>GridViewPager</code> provides support for scrolling in cards whose content does not fit +the device screen. This example configures each card to expand as required, so users can scroll +through the card's content. When users reach the end of a scrollable card, a swipe in the same +direction shows the next page on the grid, if one is available.</p> + +<p>You can specify a custom background for each page with the <code>getBackground()</code> method. +When users swipe to navigate across pages, <code>GridViewPager</code> applies parallax +and crossfade effects between different backgrounds automatically.</p> + +<h3>Assign an adapter instance to the page grid</h3> + +<p>In your activity, assign an instance of your adapter implementation to the +<code>GridViewPager</code> component:</p> + +<pre> +public class MainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + ... + final GridViewPager pager = (GridViewPager) findViewById(R.id.pager); + pager.setAdapter(new SampleGridPagerAdapter(this, getFragmentManager())); + } +} +</pre> diff --git a/docs/html/training/wearables/ui/cards.jd b/docs/html/training/wearables/ui/cards.jd new file mode 100644 index 0000000..0633720 --- /dev/null +++ b/docs/html/training/wearables/ui/cards.jd @@ -0,0 +1,169 @@ +page.title=Creating Cards + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#card-fragment">Create a Card Fragment</a></li> + <li><a href="#card-layout">Add a Card to Your Layout</a></li> +</ol> +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li> +</ul> +</div> +</div> + + +<p>Cards present information to users with a consistent look and feel across different apps. +This lesson shows you how to create cards in your Android Wear apps.</p> + +<p>The Wearable UI Library provides implementations of cards specifically designed for wearable +devices. This library contains the <code>CardFrame</code> class, which wraps views inside +a card-styled frame with a white background, rounded corners, and a light-drop shadow. +<code>CardFrame</code> can only contain one direct child, usually a layout manager, to which +you can add other views to customize the content inside the card.</p> + +<p>You can add cards to your app in two ways:</p> + +<ul> + <li>Use or extend the <code>CardFragment</code> class.</li> + <li>Add a card inside a <code>CardScrollView</code> in your layout.</li> +</ul> + +<p class="note"><strong>Note:</strong> This lesson shows you how to add cards to Android Wear +activities. Android notifications on wearable devices are also displayed as cards. For more +information, see <a href="{@docRoot}training/wearables/notifications/index.html">Adding Wearable +Features to Notifications</a>.</p> + + +<h2 id="card-fragment">Create a Card Fragment</h2> + +<p>The <code>CardFragment</code> class provides a default card layout with a title, a +description, and an icon. Use this approach to add cards to your app if the default card layout +shown in figure 1 meets your needs.</p> + +<img src="{@docRoot}wear/images/05_uilib.png" width="500" height="245" alt=""/> +<p class="img-caption"><strong>Figure 1.</strong> The default <code>CardFragment</code> layout.</p> + +<p>To add a <code>CardFragment</code> to your app:</p> + +<ol> +<li>In your layout, assign an ID to the element that contains the card</li> +<li>Create a <code>CardFragment</code> instance in your activity</li> +<li>Use the fragment manager to add the <code>CardFragment</code> instance to its container</li> +</ol> + +<p>The following sample code shows the code for the screen display shown in Figure 1:</p> + +<pre> +<android.support.wearable.view.BoxInsetLayout +xmlns:android="http://schemas.android.com/apk/res/android" +xmlns:app="http://schemas.android.com/apk/res-auto" +android:background="@drawable/robot_background" +android:layout_height="match_parent" +android:layout_width="match_parent"> + + <FrameLayout + <strong>android:id="@+id/frame_layout"</strong> + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_box="bottom"> + + </FrameLayout> +</android.support.wearable.view.BoxInsetLayout> +</pre> + +<p>The following code adds the <code>CardFragment</code> instance to the activity in Figure 1:</p> + +<pre> +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_wear_activity2); + + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + CardFragment cardFragment = CardFragment.create(getString(R.string.cftitle), + getString(R.string.cfdesc), + R.drawable.p); + fragmentTransaction.add(R.id.frame_layout, cardFragment); + fragmentTransaction.commit(); +} +</pre> + +<p>To create a card with a custom layout using <code>CardFragment</code>, extend this class +and override its <code>onCreateContentView</code> method.</p> + + +<h2 id="card-layout">Add a CardFrame to Your Layout</h2> + +<p>You can also add a card directly to your layout definition, as shown in figure 2. Use this +approach when you want to define a custom layout for the card inside a layout definition file.</p> + +<img src="{@docRoot}wear/images/04_uilib.png" width="500" height="248" alt=""/> +<p class="img-caption"><strong>Figure 2.</strong> Adding a <code>CardFrame</code> to your +layout.</p> + +<p>The following layout code sample demonstrates a vertical linear layout with two elements. You +can create more complex layouts to fit the needs of your app.</p> + +<pre> +<android.support.wearable.view.BoxInsetLayout +xmlns:android="http://schemas.android.com/apk/res/android" +xmlns:app="http://schemas.android.com/apk/res-auto" +android:background="@drawable/robot_background" +android:layout_height="match_parent" +android:layout_width="match_parent"> + + <<strong>android.support.wearable.view.CardScrollView</strong> + android:id="@+id/card_scroll_view" + android:layout_height="match_parent" + android:layout_width="match_parent" + app:layout_box="bottom"> + + <<strong>android.support.wearable.view.CardFrame</strong> + android:layout_height="wrap_content" + android:layout_width="fill_parent"> + + <LinearLayout + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:orientation="vertical" + android:paddingLeft="5dp"> + <TextView + android:fontFamily="sans-serif-light" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/custom_card" + android:textColor="@color/black" + android:textSize="20sp"/> + <TextView + android:fontFamily="sans-serif-light" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/description" + android:textColor="@color/black" + android:textSize="14sp"/> + </LinearLayout> + </android.support.wearable.view.CardFrame> + </android.support.wearable.view.CardScrollView> +</android.support.wearable.view.BoxInsetLayout> +</pre> + +<p>The <code>CardScrollView</code> element in the example layout above lets you assign gravity to +the card when its content is smaller than the container. This example aligns the card to the +bottom of the screen:</p> + +<pre> +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_wear_activity2); + + CardScrollView cardScrollView = + (CardScrollView) findViewById(R.id.card_scroll_view); + cardScrollView.setCardGravity(Gravity.BOTTOM); +} +</pre> diff --git a/docs/html/training/wearables/ui/confirm.jd b/docs/html/training/wearables/ui/confirm.jd new file mode 100644 index 0000000..36330a6 --- /dev/null +++ b/docs/html/training/wearables/ui/confirm.jd @@ -0,0 +1,166 @@ +page.title=Showing Confirmations + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#confirmation-timers">Use Automatic Confirmation Timers</a></li> + <li><a href="#show-confirmation">Show Confirmation Animations</a></li> +</ol> +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li> +</ul> +</div> +</div> + + +<p><a href="{@docRoot}design/wear/patterns.html#Countdown">Confirmations</a> in Android Wear apps +use the whole screen or a larger portion of it than those in handheld apps. This ensures that +users can see these confirmations by just glancing at the screen and that they have large enough +touch targets to cancel an action.</p> + +<p>The Wearable UI Library helps you show confirmation animations and timers in your +Android Wear apps:</p> + +<dl> +<dt><em>Confirmation timers</em></dt> + <dd>Automatic confirmation timers show users an animated timer that lets them cancel an action + they just performed.</dd> +<dt><em>Confirmation animations</em></dt> + <dd>Confirmation animations give users visual feedback when they complete an action.</dd> +</dl> + +<p>The following sections show you how to implement these patterns.</p> + + +<h2 id="confirmation-timers">Use Automatic Confirmation Timers</h2> + +<div style="float:right;margin-left:25px;width:230px;margin-top:10px"> +<img src="{@docRoot}wear/images/09_uilib.png" width="230" height="230" alt=""/> +<p class="img-caption" style="text-align:center"><strong>Figure 1:</strong> +A confirmation timer.</p> +</div> + +<p>Automatic confirmation timers let users cancel an action they just performed. When the user +performs the action, your app shows a button to cancel the action with a timer animation and +starts the timer. The user has the option to cancel the action until the timer finishes. Your app +gets notified if the user cancels the action and when the timer expires.</p> + +<p>To show a confirmation timer when users complete an action in your app:</p> + +<ol> +<li>Add a <code>DelayedConfirmationView</code> element to your layout.</li> +<li>Implement the <code>DelayedConfirmationListener</code> interface in your activity.</li> +<li>Set the duration of the timer and start it when the user completes an action.</li> +</ol> + +<p>Add the <code>DelayedConfirmationView</code> element to your layout as follows:</p> + +<pre> +<android.support.wearable.view.DelayedConfirmationView + android:id="@+id/delayed_confirm" + android:layout_width="40dp" + android:layout_height="40dp" + android:src="@drawable/cancel_circle" + app:circle_border_color="@color/lightblue" + app:circle_border_width="4dp" + app:circle_radius="16dp"> +</android.support.wearable.view.DelayedConfirmationView> +</pre> + +<p>You can assign a drawable resource to display inside the circle with the +<code>android:src</code> attribute and configure the parameters of the circle directly on the +layout definition.</p> + +<p>To be notified when the timer finishes or when users tap on it, implement the corresponding +listener methods in your activity:</p> + +<pre> +public class WearActivity extends Activity implements + DelayedConfirmationView.DelayedConfirmationListener { + + private DelayedConfirmationView mDelayedView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_wear_activity); + + mDelayedView = + (DelayedConfirmationView) findViewById(R.id.delayed_confirm); + mDelayedView.setListener(this); + } + + @Override + public void onTimerFinished(View view) { + // User didn't cancel, perform the action + } + + @Override + public void onTimerSelected(View view) { + // User canceled, abort the action + } +} +</pre> + +<p>To start the timer, add the following code to the point in your activity where users select +an action:</p> + +<pre> +// Two seconds to cancel the action +mDelayedView.setTotalTimeMs(2000); +// Start the timer +mDelayedView.start(); +</pre> + + +<h2 id="show-confirmation">Show Confirmation Animations</h2> + +<div style="float:right;margin-left:25px;width:200px"> +<img src="{@docRoot}wear/images/08_uilib.png" width="200" height="200" alt=""/> +<p class="img-caption" style="text-align:center"><strong>Figure 2:</strong> +A confirmation animation.</p> +</div> + +<p>To show a confirmation animation when users complete an action in your app, create an intent +that starts <code>ConfirmationActivity</code> from one of your activities. You can specify +one of the these animations with the <code>EXTRA_ANIMATION_TYPE</code> intent extra:</p> + +<ul> +<li><code>SUCCESS_ANIMATION</code></li> +<li><code>FAILURE_ANIMATION</code></li> +<li><code>OPEN_ON_PHONE_ANIMATION</code></li> +</ul> + +<p>You can also add a message that appears under the confirmation icon.</p> + +<p>To use the <code>ConfirmationActivity</code> in your app, first declare this activity in your +manifest file:</p> + +<pre> +<manifest> + <application> + ... + <activity + android:name="android.support.wearable.activity.ConfirmationActivity"> + </activity> + </application> +</manifest> +</pre> + +<p>Then determine the result of the user action and start the activity with an intent:</p> + +<pre> +Intent intent = new Intent(this, ConfirmationActivity.class); +intent.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, + ConfirmationActivity.SUCCESS_ANIMATION); +intent.putExtra(ConfirmationActivity.EXTRA_MESSAGE, + getString(R.string.msg_sent)); +startActivity(intent); +</pre> + +<p>After showing the confirmation animation, <code>ConfirmationActivity</code> finishes and your +activity resumes.</p> diff --git a/docs/html/training/wearables/ui/exit.jd b/docs/html/training/wearables/ui/exit.jd new file mode 100644 index 0000000..b89711a --- /dev/null +++ b/docs/html/training/wearables/ui/exit.jd @@ -0,0 +1,110 @@ +page.title=Exiting Full-Screen Activities + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#disable-swipe">Disable the Swipe-To-Dismiss Gesture</a></li> + <li><a href="#long-press">Implement the Long Press to Dismiss Pattern</a></li> +</ol> +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li> +</ul> +</div> +</div> + + +<p>By default, users exit Android Wear activities by swiping from left to right. If the app +contains horizontally scrollable content, users first have to navigate to the edge of the +content and then swipe again from left to right to exit the app.</p> + +<p>For more immersive experiences, like an app that can scroll a map in any direction, you can +disable the swipe to exit gesture in your app. However, if you disable it, you must implement +the long-press-to-dismiss UI pattern to let users exit your app using the +<code>DismissOverlayView</code> class from the Wearable UI Library. +You must also inform your users the first time they run your app that they can exit using +a long press.</p> + +<p>For design guidelines on exiting Android Wear activities, see +<a href="{@docRoot}design/wear/structure.html#Custom">Breaking out of the card</a>.</p> + + +<h2 id="disable-swipe">Disable the Swipe-To-Dismiss Gesture</h2> + +<p>If the user interaction model of your app interferes with the swipe-to-dismiss gesture, +you can disable it for your app. To disable the swipe-to-dismiss gesture in your app, extend +the default theme and set the <code>android:windowSwipeToDismiss</code> attribute to +<code>false</code>:</p> + +<pre> +<style name="AppTheme" parent="Theme.DeviceDefault"> + <item name="android:windowSwipeToDismiss">false</item> +</style> +</pre> + +<p>If you disable this gesture, you must implement the long-press-to-dismiss UI pattern to let users +exit your app, as described in the next section.</p> + + +<h2 id="long-press">Implement the Long Press to Dismiss Pattern</h2> + +<p>To use the <code>DissmissOverlayView</code> class in your activity, add this element to +your layout definition such that it covers the whole screen and is placed above all other views. +For example:</p> + +<pre> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="match_parent" + android:layout_width="match_parent"> + + <!-- other views go here --> + + <android.support.wearable.view.DismissOverlayView + android:id="@+id/dismiss_overlay" + android:layout_height="match_parent" + android:layout_width="match_parent"/> +<FrameLayout> +</pre> + +<p>In your activity, obtain the <code>DismissOverlayView</code> element and set some introductory +text. This text is shown to users the first time they run your app to inform them that they +can exit the app using a long press gesture. Then use a <code>GestureDetector</code> to detect +a long press:</p> + +<pre> +public class WearActivity extends Activity { + + private DismissOverlayView mDismissOverlay; + private GestureDetector mDetector; + + public void onCreate(Bundle savedState) { + super.onCreate(savedState); + setContentView(R.layout.wear_activity); + + // Obtain the DismissOverlayView element + mDismissOverlay = (DismissOverlayView) findViewById(R.id.dismiss_overlay); + mDismissOverlay.setIntroText(R.string.long_press_intro); + mDismissOverlay.showIntroIfNecessary(); + + // Configure a gesture detector + mDetector = new GestureDetector(this, new SimpleOnGestureListener() { + public void onLongPress(MotionEvent ev) { + mDismissOverlay.show(); + } + }); + } + + // Capture long presses + @Override + public boolean onTouchEvent(MotionEvent ev) { + return mDetector.onTouchEvent(ev) || super.onTouchEvent(ev); + } +} +</pre> + +<p>When the system detects a long press gesture, <code>DismissOverlayView</code> shows an +<strong>Exit</strong> button, which terminates your activity if the user presses it.</p>
\ No newline at end of file diff --git a/docs/html/training/wearables/ui/index.jd b/docs/html/training/wearables/ui/index.jd new file mode 100644 index 0000000..8ef6fe7 --- /dev/null +++ b/docs/html/training/wearables/ui/index.jd @@ -0,0 +1,57 @@ +page.title=Creating Custom UIs for Wear Devices + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + <h2>Dependencies and Prerequisites</h2> + <ul> + <li>Android Studio 0.8 or later and Gradle 0.12 or later</li> + </ul> +</div> +</div> + +<p>User interfaces for wearable apps differ significantly from those built for handheld devices. +Apps for wearables should follow the Android Wear <a href="{@docRoot}design/wear/index.html">design +principles</a> and implement the recommended <a href="{@docRoot}design/wear/patterns.html">UI +patterns</a>, which ensure a consistent user experience across apps that is optimized for +wearables.</a> + +<p>This class teaches you how to create custom UIs for your +<a href="{@docRoot}training/wearables/apps/creating.html">wearable apps</a> and +<a href="{@docRoot}training/wearables/apps/layouts.html#CustomNotifications">custom +notifications</a> that look good on any Android Wear device by implementing these +UI patterns:</p> + +<ul> +<li>Cards</li> +<li>Countdowns and confirmations</li> +<li>Long press to dismiss</li> +<li>2D Pickers</li> +<li>Selection lists</li> +</ul> + +<p>The Wearable UI Library, which is part of the Google Repository in the Android SDK, +provides classes that help you implement these patterns and create layouts that work on +both round and square Android Wear devices.</p> + +<p class="note"><b>Note:</b> We recommend using Android Studio for Android Wear development +as it provides project setup, library inclusion, and packaging conveniences that aren't available +in ADT. This training assumes you are using Android Studio.</p> + +<h2>Lessons</h2> + +<dl> + <dt><a href="{@docRoot}training/wearables/ui/layouts.html">Defining Layouts</a></dt> + <dd>Learn how to create layouts that look good on round and square Android Wear devices.</dd> + <dt><a href="{@docRoot}training/wearables/ui/cards.html">Creating Cards</a></dt> + <dd>Learn how to create cards with custom layouts.</dd> + <dt><a href="{@docRoot}training/wearables/ui/lists.html">Creating Lists</a></dt> + <dd>Learn how to create lists that are optimized for wearable devices.</dd> + <dt><a href="{@docRoot}training/wearables/ui/2d-picker.html">Creating a 2D Picker</a></dt> + <dd>Learn how to implement the 2D Picker UI pattern to navigate through pages of data.</dd> + <dt><a href="{@docRoot}training/wearables/ui/confirm.html">Showing Confirmations</a></dt> + <dd>Learn how to display confirmation animations when users complete actions.</dd> + <dt><a href="{@docRoot}training/wearables/ui/exit.html">Exiting Full-Screen Activities</a></dt> + <dd>Learn how to implement the long-press-to-dismiss UI pattern to exit full-screen activities.</dd> +</dl>
\ No newline at end of file diff --git a/docs/html/training/wearables/ui/layouts.jd b/docs/html/training/wearables/ui/layouts.jd new file mode 100644 index 0000000..14b9403 --- /dev/null +++ b/docs/html/training/wearables/ui/layouts.jd @@ -0,0 +1,261 @@ +page.title=Defining Layouts + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#add-library">Add the Wearable UI Library</a></li> + <li><a href="#different-layouts">Specify Different Layouts for Square and Round Screens</a></li> + <li><a href="#same-layout">Use a Shape-Aware Layout</a></li> +</ol> +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li> +</ul> +<h2>Video</h2> +<ul> + <li><a href="https://www.youtube.com/watch?v=naf_WbtFAlY">Full Screen Apps for Android Wear</a></li> +</ul> +</div> +</div> + +<p>Wearables use the same layout techniques as handheld Android devices, but need to be designed +with specific constraints. Do not port functionality and the UI from a handheld app and expect a +good experience. For more information on how to design great wearable apps, read the +<a href="{@docRoot}design/wear/index.html">Android Wear Design Guidelines</a>.</p> + +<p>When you create layouts for Android Wear apps, you need to account for devices with square +and round screens. Any content placed near the corners of the screen may be cropped on round +Android Wear devices, so layouts designed for square screens do not work well on round devices. +For a demonstration of this type of problem, see the video +<a href="https://www.youtube.com/watch?v=naf_WbtFAlY">Full Screen Apps for Android Wear</a>.</p> + +<p>For example, figure 1 shows how the following layout looks on square and round screens:</p> + +<img src="{@docRoot}wear/images/01_uilib.png" alt="" width="500" height="261"/> +<p class="img-caption"><strong>Figure 1.</strong> Demonstration of how a layout designed for +square screens does not work well on round screens.</p> + +<pre> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <TextView + android:id="@+id/text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/hello_square" /> +</LinearLayout> +</pre> + +<p>The text does not display correctly on devices with round screens.</p> + +<p>The Wearable UI Library provides two different approaches to solve this problem:</p> + +<ul> +<li>Define different layouts for square and round devices. Your app detects the shape + of the device screen and inflates the correct layout at runtime.</li> +<li>Use a special layout included in the library for both square and round devices. This layout + applies different window insets depending on the shape of the device screen.</li> +</ul> + +<p>You typically use the first approach when you want your app to look different depending on +the shape of the device screen. You use the second approach when you want to use a similar layout +on both screen shapes without having views cropped near the edges of round screens.</p> + + +<h2 id="add-library">Add the Wearable UI Library</h2> + +<p>Android Studio includes the Wearable UI Library on your <code>wear</code> module by default +when you use the Project Wizard. To compile your project with this library, ensure that the +<em>Extras</em> > <em>Google Repository</em> package is installed in +the Android SDK manager and that the following dependency is included in the +<code>build.gradle</code> file of your <code>wear</code> module:</p> + +<pre> +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + <strong>compile 'com.google.android.support:wearable:+'</strong> + compile 'com.google.android.gms:play-services-wearable:+' +} +</pre> + +<p>The <code>'com.google.android.support:wearable'</code> dependency is required to implement +the layout techniques shown in the following sections.</p> + +<p><a href="/shareables/training/wearable-support-docs.zip">Download the full API +reference documentation</a> for the Wearable UI Library classes.</p> + + +<h2 id="different-layouts">Specify Different Layouts for Square and Round Screens</h2> + +<p>The <code>WatchViewStub</code> class included in the Wearable UI Library lets you specify +different layout definitions for square and round screens. This class detects the screen shape +at runtime and inflates the corresponding layout.</p> + +<p>To use this class for handling different screen shapes in your app:</p> + +<ol> +<li>Add <code>WatchViewStub</code> as the main element of your activity's layout.</li> +<li>Specify a layout definition file for square screens with the <code>rectLayout</code> + attribute.</li> +<li>Specify a layout definition file for round screens with the <code>roundLayout</code> + attribute.</li> +</ol> + +<p>Define your activity's layout as follows:</p> + +<pre> +<android.support.wearable.view.WatchViewStub + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/watch_view_stub" + android:layout_width="match_parent" + android:layout_height="match_parent" + <strong>app:rectLayout="@layout/rect_activity_wear"</strong> + <strong>app:roundLayout="@layout/round_activity_wear"</strong>> +</android.support.wearable.view.WatchViewStub> +</pre> + +<p>Inflate this layout in your activity:</p> + +<pre> +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_wear); +} +</pre> + +<p>Then create different layout definition files for square and round screens. In this example, +you need to create the files <code>res/layout/rect_activity_wear.xml</code> and +<code>res/layout/round_activity_wear.xml</code>. You define these layouts in the same way that +you create layouts for handheld apps, but taking into account the constraints of wearable devices. +The system inflates the correct layout at runtime depending on the screen shape.</p> + +<h3>Accessing layout views</h3> + +<p>The layouts that you specify for square or round screens are not inflated until +<code>WatchViewStub</code> detects the shape of the screen, so your app cannot access their views +immediately. To access these views, set a listener in your activity to be notified when +the shape-specific layout has been inflated:</p> + +<pre> +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_wear); + + WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub); + stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() { + @Override public void onLayoutInflated(WatchViewStub stub) { + // Now you can access your views + TextView tv = (TextView) stub.findViewById(R.id.text); + ... + } + }); +} +</pre> + + +<h2 id="same-layout">Use a Shape-Aware Layout</h2> + +<div style="float:right;margin-left:25px;width:250px"> +<img src="{@docRoot}wear/images/02_uilib.png" width="250" height="250" alt=""/> +<p class="img-caption"><strong>Figure 2.</strong> Window insets on a round screen.</p> +</div> + +<p>The <code>BoxInsetLayout</code> class included in the Wearable UI Library extends +{@link android.widget.FrameLayout} and lets you define a single layout that works for both square +and round screens. This class applies the required window insets depending on the screen shape +and lets you easily align views on the center or near the edges of the screen.</p> + +<p>The gray square in figure 2 shows the area where <code>BoxInsetLayout</code> can automatically +place its child views on round screens after applying the required window insets. To be displayed +inside this area, children views specify the <code>layout_box</code> atribute with these values: +</p> + +<ul> +<li>A combination of <code>top</code>, <code>bottom</code>, <code>left</code>, and + <code>right</code>. For example, <code>"left|top"</code> positions the child's left and top + edges inside the gray square in figure 2.</li> +<li>The <code>all</code> value positions all the child's content inside the gray square in + figure 2.</li> +</ul> + +<p>On square screens, the window insets are zero and the <code>layout_box</code> attribute is +ignored.</p> + +<img src="{@docRoot}wear/images/03_uilib.png" width="500" height="253" alt=""/> +<p class="img-caption"><strong>Figure 3.</strong> A layout definition that works on both +square and round screens.</p> + +<p>The layout shown in figure 3 uses <code>BoxInsetLayout</code> and works on square and +round screens:</p> + +<pre> +<<strong>android.support.wearable.view.BoxInsetLayout</strong> + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + <strong>android:background="@drawable/robot_background"</strong> + android:layout_height="match_parent" + android:layout_width="match_parent" + <strong>android:padding="15dp"</strong>> + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + <strong>android:padding="5dp"</strong> + <strong>app:layout_box="all"</strong>> + + <TextView + android:gravity="center" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/sometext" + android:textColor="@color/black" /> + + <ImageButton + android:background="@null" + android:layout_gravity="bottom|left" + android:layout_height="50dp" + android:layout_width="50dp" + android:src="@drawable/ok" /> + + <ImageButton + android:background="@null" + android:layout_gravity="bottom|right" + android:layout_height="50dp" + android:layout_width="50dp" + android:src="@drawable/cancel" /> + </FrameLayout> +</android.support.wearable.view.BoxInsetLayout> +</pre> + +<p>Notice the parts of the layout marked in bold:</p> + +<ul> +<li> + <p><code>android:padding="15dp"</code></p> + <p>This line assigns padding to the <code>BoxInsetLayout</code> element. Because the window + insets on round devices are larger than 15dp, this padding only applies to square screens.</p> +</li> +<li> + <p><code>android:padding="5dp"</code></p> + <p>This line assigns padding to the inner <code>FrameLayout</code> element. This padding applies + to both square and round screens. The total padding between the buttons and the window insets + is 20 dp on square screens (15+5) and 5 dp on round screens.</p> +</li> +<li> + <p><code>app:layout_box="all"</code></p> + <p>This line ensures that the <code>FrameLayout</code> element and its children are boxed inside + the area defined by the window insets on round screens. This line has no effect on square + screens.</p> +</li> +</ul>
\ No newline at end of file diff --git a/docs/html/training/wearables/ui/lists.jd b/docs/html/training/wearables/ui/lists.jd new file mode 100644 index 0000000..5458541 --- /dev/null +++ b/docs/html/training/wearables/ui/lists.jd @@ -0,0 +1,304 @@ +page.title=Creating Lists + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#add-list">Add a List View</a></li> + <li><a href="#layout-impl">Create a Layout Implementation for List Items</a></li> + <li><a href="#layout-def">Create a Layout Definition for Items</a></li> + <li><a href="#adapter">Create an Adapter to Populate the List</a></li> + <li><a href="#adapter-listener">Associate the Adapter and Set a Click Listener</a></li> +</ol> +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li> +</ul> +</div> +</div> + + +<p>Lists let users select an item from a set of choices easily on wearable devices. This lesson +shows you how to create lists in your Android Wear apps.</p> + +<p>The Wearable UI Library includes the <code>WearableListView</code> class, which is a list +implementation optimized for wearable devices..</p> + +<p class="note"><strong>Note:</strong> The <em>Notifications</em> sample in the Android SDK +demonstrates how to use <code>WearableListView</code> in your apps. This sample is located in +the <code>android-sdk/samples/android-20/wearable/Notifications</code> directory.</p> + +<p>To create a list in your Android Wear apps:</p> + +<ol> +<li>Add a <code>WearableListView</code> element to your activity's layout definition.</li> +<li>Create a custom layout implementation for your list items.</li> +<li>Use this implementation to create a layout definition file for your list items.</li> +<div style="float:right;margin-left:25px;width:215px;margin-top:-20px"> +<img src="{@docRoot}wear/images/06_uilib.png" width="200" height="200" alt=""/> +<p class="img-caption" style="text-align:center"><strong>Figure 3:</strong> +A list view on Android Wear.</p> +</div> +<li>Create an adapter to populate the list.</li> +<li>Assign the adapter to the <code>WearableListView</code> element.</li> +</ol> + +<p>These steps are described in detail in the following sections.</p> + + +<h2 id="add-list">Add a List View</h2> + +<p>The following layout adds a list view to an activity using a <code>BoxInsetLayout</code>, so +the list is displayed properly on both round and square devices:</p> + +<pre> +<android.support.wearable.view.BoxInsetLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:background="@drawable/robot_background" + android:layout_height="match_parent" + android:layout_width="match_parent"> + + <FrameLayout + android:id="@+id/frame_layout" + android:layout_height="match_parent" + android:layout_width="match_parent" + app:layout_box="left|bottom|right"> + + <<strong>android.support.wearable.view.WearableListView</strong> + android:id="@+id/wearable_list" + android:layout_height="match_parent" + android:layout_width="match_parent"> + </android.support.wearable.view.WearableListView> + </FrameLayout> +</android.support.wearable.view.BoxInsetLayout> +</pre> + + +<h2 id="layout-impl">Create a Layout Implementation for List Items</h2> + +<p>In many cases, each list item consists of an icon and a description. The +<em>Notifications</em> sample from the Android SDK implements a custom layout that extends +{@link android.widget.LinearLayout} to incorporate these two elements inside each list item. +This layout also implements the methods in the <code>WearableListView.Item</code> interface +to animate the item's icon and fade the text in response to events from +<code>WearableListView</code> as the user scrolls through the list.</p> + +<pre> +public class WearableListItemLayout extends LinearLayout + implements WearableListView.Item { + + private final float mFadedTextAlpha; + private final int mFadedCircleColor; + private final int mChosenCircleColor; + private ImageView mCircle; + private float mScale; + private TextView mName; + + public WearableListItemLayout(Context context) { + this(context, null); + } + + public WearableListItemLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public WearableListItemLayout(Context context, AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); + mFadedTextAlpha = getResources() + .getInteger(R.integer.action_text_faded_alpha) / 100f; + mFadedCircleColor = getResources().getColor(R.color.grey); + mChosenCircleColor = getResources().getColor(R.color.blue); + } + + // Get references to the icon and text in the item layout definition + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + // These are defined in the layout file for list items + // (see next section) + mCircle = (ImageView) findViewById(R.id.circle); + mName = (TextView) findViewById(R.id.name); + } + + // Provide scaling values for WearableListView animations + @Override + public float getProximityMinValue() { + return 1f; + } + + @Override + public float getProximityMaxValue() { + return 1.6f; + } + + @Override + public float getCurrentProximityValue() { + return mScale; + } + + // Scale the icon for WearableListView animations + @Override + public void setScalingAnimatorValue(float scale) { + mScale = scale; + mCircle.setScaleX(scale); + mCircle.setScaleY(scale); + } + + // Change color of the icon, remove fading from the text + @Override + public void onScaleUpStart() { + mName.setAlpha(1f); + ((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor); + } + + // Change the color of the icon, fade the text + @Override + public void onScaleDownStart() { + ((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor); + mName.setAlpha(mFadedTextAlpha); + } +} +</pre> + + +<h2 id="layout-def">Create a Layout Definition for Items</h2> + +<p>After you implement a custom layout for list items, you provide a layout definition file that +specifies the layout parameters of each of the components inside a list item. The following layout +definition uses the custom layout implementation from the previous section and defines an icon +and a text view whose IDs match those in the layout implementation class:</p> + +<pre> +<-- res/layout/list_item.xml --> +<com.example.android.support.wearable.notifications.WearableListItemLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:gravity="center_vertical" + android:layout_width="match_parent" + android:layout_height="80dp"> + <ImageView + android:id="@+id/circle" + android:layout_height="20dp" + android:layout_margin="16dp" + android:layout_width="20dp" + android:src="@drawable/wl_circle"/> + <TextView + android:id="@+id/name" + android:gravity="center_vertical|left" + android:layout_width="wrap_content" + android:layout_marginRight="16dp" + android:layout_height="match_parent" + android:fontFamily="sans-serif-condensed-light" + android:lineSpacingExtra="-4sp" + android:textColor="@color/text_color" + android:textSize="16sp"/> +</com.example.android.support.wearable.notifications.WearableListItemLayout> +</pre> + + +<h2 id="adapter">Create an Adapter to Populate the List</h2> + +<p>The adapter populates the <code>WearableListView</code> with content. The following simple +adapter populates the list with elements based on an array of strings:</p> + +<pre> +private static final class Adapter extends WearableListView.Adapter { + private String[] mDataset; + private final Context mContext; + private final LayoutInflater mInflater; + + // Provide a suitable constructor (depends on the kind of dataset) + public Adapter(Context context, String[] dataset) { + mContext = context; + mInflater = LayoutInflater.from(context); + mDataset = dataset; + } + + // Provide a reference to the type of views you're using + public static class ItemViewHolder extends WearableListView.ViewHolder { + private TextView textView; + public ItemViewHolder(View itemView) { + super(itemView); + // find the text view within the custom item's layout + textView = (TextView) itemView.findViewById(R.id.name); + } + } + + // Create new views for list items + // (invoked by the WearableListView's layout manager) + @Override + public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, + int viewType) { + // Inflate our custom layout for list items + return new ItemViewHolder(mInflater.inflate(R.layout.list_item, null)); + } + + // Replace the contents of a list item + // Instead of creating new views, the list tries to recycle existing ones + // (invoked by the WearableListView's layout manager) + @Override + public void onBindViewHolder(WearableListView.ViewHolder holder, + int position) { + // retrieve the text view + ItemViewHolder itemHolder = (ItemViewHolder) holder; + TextView view = itemHolder.textView; + // replace text contents + view.setText(mDataset[position]); + // replace list item's metadata + holder.itemView.setTag(position); + } + + // Return the size of your dataset + // (invoked by the WearableListView's layout manager) + @Override + public int getItemCount() { + return mDataset.length; + } +} +</pre> + + +<h2 id="adapter-listener">Associate the Adapter and Set a Click Listener</h2> + +<p>In your activity, obtain a reference to the <code>WearableListView</code> element from +your layout, assign an instance of the adapter to populate the list, and set a click listener +to complete an action when the user selects a particular list item.</p> + +<pre> +public class WearActivity extends Activity + implements WearableListView.ClickListener { + + // Sample dataset for the list + String[] elements = { "List Item 1", "List Item 2", ... }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.my_list_activity); + + // Get the list component from the layout of the activity + WearableListView listView = + (WearableListView) findViewById(R.id.wearable_list); + + // Assign an adapter to the list + listView.setAdapter(new Adapter(this, elements)); + + // Set a click listener + listView.setClickListener(this); + } + + // WearableListView click listener + @Override + public void onClick(WearableListView.ViewHolder v) { + Integer tag = (Integer) v.itemView.getTag(); + // use this data to complete some action ... + } + + @Override + public void onTopEmptyRegionClick() { + } +} +</pre> diff --git a/docs/html/wear/images/01_uilib.png b/docs/html/wear/images/01_uilib.png Binary files differnew file mode 100644 index 0000000..14484d6 --- /dev/null +++ b/docs/html/wear/images/01_uilib.png diff --git a/docs/html/wear/images/02_uilib.png b/docs/html/wear/images/02_uilib.png Binary files differnew file mode 100644 index 0000000..39896a1 --- /dev/null +++ b/docs/html/wear/images/02_uilib.png diff --git a/docs/html/wear/images/03_uilib.png b/docs/html/wear/images/03_uilib.png Binary files differnew file mode 100644 index 0000000..ebf635d --- /dev/null +++ b/docs/html/wear/images/03_uilib.png diff --git a/docs/html/wear/images/04_uilib.png b/docs/html/wear/images/04_uilib.png Binary files differnew file mode 100644 index 0000000..e5a29a0 --- /dev/null +++ b/docs/html/wear/images/04_uilib.png diff --git a/docs/html/wear/images/05_uilib.png b/docs/html/wear/images/05_uilib.png Binary files differnew file mode 100644 index 0000000..25d2e34 --- /dev/null +++ b/docs/html/wear/images/05_uilib.png diff --git a/docs/html/wear/images/06_uilib.png b/docs/html/wear/images/06_uilib.png Binary files differnew file mode 100644 index 0000000..257bb82 --- /dev/null +++ b/docs/html/wear/images/06_uilib.png diff --git a/docs/html/wear/images/07_uilib.png b/docs/html/wear/images/07_uilib.png Binary files differnew file mode 100644 index 0000000..ce1a80c --- /dev/null +++ b/docs/html/wear/images/07_uilib.png diff --git a/docs/html/wear/images/08_uilib.png b/docs/html/wear/images/08_uilib.png Binary files differnew file mode 100644 index 0000000..b44522b --- /dev/null +++ b/docs/html/wear/images/08_uilib.png diff --git a/docs/html/wear/images/09_uilib.png b/docs/html/wear/images/09_uilib.png Binary files differnew file mode 100644 index 0000000..f8234e1 --- /dev/null +++ b/docs/html/wear/images/09_uilib.png diff --git a/location/java/android/location/package.html b/location/java/android/location/package.html index 81fcea4..2355e72 100644 --- a/location/java/android/location/package.html +++ b/location/java/android/location/package.html @@ -1,22 +1,20 @@ <html> <body> -<p>Contains the framework API classes that define Android location-based and related services.</p> -<p class="note"> - <strong>Note:</strong> The Google Location Services API, part of Google Play - Services, provides a more powerful, high-level framework that automates tasks such as - location provider choice and power management. Location Services also provides new - features such as activity detection that aren't available in the framework API. Developers who - are using the framework API, as well as developers who are just now adding location-awareness - to their apps, should strongly consider using the Location Services API. -<br/> - To learn more about the Location Services API, see - <a href="{@docRoot}google/play-services/location.html">Location APIs</a>. +<p>Contains the framework API classes that define Android location-based and + related services.</p> +<p class="warning"> +<strong>This API is not the recommended method for accessing Android location.</strong><br> +The +<a href="{@docRoot}reference/com/google/android/gms/location/package-summary.html">Google Location Services API</a>, +part of Google Play services, is the preferred way to add location-awareness to +your app. It offers a simpler API, higher accuracy, low-power geofencing, and +more. If you are currently using the android.location API, you are strongly +encouraged to switch to the Google Location Services API as soon as +possible. +<br><br> +To learn more about the Google Location Services API, see the +<a href="{@docRoot}google/play-services/location.html">Location API overview</a>. </p> - -<p>For more information about the framework API, see the -<a href="{@docRoot}guide/topics/location/index.html">Location and Maps</a> guide.</p> -{@more} - </body> </html> diff --git a/services/core/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java index 11ed5d2..9f9bafd 100644 --- a/services/core/java/com/android/server/pm/PackageKeySetData.java +++ b/services/core/java/com/android/server/pm/PackageKeySetData.java @@ -41,6 +41,7 @@ public class PackageKeySetData { } PackageKeySetData(PackageKeySetData original) { + mProperSigningKeySet = original.mProperSigningKeySet; mSigningKeySets = ArrayUtils.cloneOrNull(original.mSigningKeySets); mUpgradeKeySets = ArrayUtils.cloneOrNull(original.mUpgradeKeySets); mDefinedKeySets = ArrayUtils.cloneOrNull(original.mDefinedKeySets); |