am b6bca953: Add first wearable sample to sdk samples distribution

* commit 'b6bca953909d42a6284de4128d767eff8c9862ee':
  Add first wearable sample to sdk samples distribution
This commit is contained in:
Griff Hazen
2014-06-21 20:15:51 +00:00
committed by Android Git Automerger
88 changed files with 3355 additions and 0 deletions

42
samples/wearable/.gitignore vendored Normal file
View File

@@ -0,0 +1,42 @@
# built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
out/
src/common
src/template
_index.jd
README.txt
# Libraries used by the app
# Can explicitly add if we want, but shouldn't do so blindly. Licenses, bloat, etc.
/libs
# Build stuff (auto-generated by android update project ...)
ant.properties
local.properties
# Eclipse project files
.classpath
.project
# idea project files
.idea/
.idea/.name
*.iml
*.ipr
*.iws
##Gradle-based build
.gradle
build/

View File

@@ -0,0 +1,24 @@
<p>This sample phone application provides a showcase of available notification
styles and demonstrates various features of the Android Wear notifications
API. Running the sample on your phone allows you to select between various
notification styles and to see how these notifications are displayed, both in
a phone's notification shade and on the wearable. The sample allows you to
create the following types of notifications:</p>
<ul>
<li>Basic notification</li>
<li>"Inbox style" notification: multiple lines of text</li>
<li>"Big picture style" notification: a full-screen background image for the
card on the wearable</li>
<li>"Big text style" notification: a tall card that is collapsed and can be
expanded with a tap</li>
<li>"Big action style" notification: tapping anywhere on the card triggers the
notification content intent</li>
<li>Notification with multiple pages: swipe horizontally to view the second
page</li>
<li>Bundled Notifications: a stack of cards that can be individually
expanded</li>
</ul>
<p>This sample also allows you to toggle other attributes for each of these
notification types, including whether a content intent or action are included,
and whether the notification is marked as "local only," indicating that it
should not be bridged between devices.</p>

View File

@@ -0,0 +1,29 @@
apply plugin: 'android'
android {
compileSdkVersion 19
buildToolsVersion "19.1"
defaultConfig {
minSdkVersion 18
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
aaptOptions {
noCompress 'apk'
}
}
dependencies {
compile "com.android.support:support-v4:20.0.+"
wearApp project(':Wearable')
}

View File

@@ -0,0 +1,22 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-dontwarn android.support.wearable.view.DelayedConfirmationView
-dontwarn android.support.wearable.view.CircledImageView

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.support.wearable.notifications" >
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="19"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".NotificationIntentReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.example.android.support.wearable.notifications.ACTION_EXAMPLE" />
<action android:name="com.example.android.support.wearable.notifications.ACTION_ENABLE_MESSAGES" />
<action android:name="com.example.android.support.wearable.notifications.ACTION_DISABLE_MESSAGES" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1,17 @@
package com.example.android.support.wearable.notifications;
import android.content.Context;
import android.support.v4.app.NotificationCompat;
/**
* Base class for notification actions presets.
*/
public abstract class ActionsPreset extends NamedPreset {
public ActionsPreset(int nameResId) {
super(nameResId);
}
/** Apply the priority to a notification builder */
public abstract void apply(Context context, NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions);
}

View File

@@ -0,0 +1,142 @@
package com.example.android.support.wearable.notifications;
import android.content.Context;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.RemoteInput;
/**
* Collection of notification actions presets.
*/
public class ActionsPresets {
public static final ActionsPreset NO_ACTIONS_PRESET = new NoActionsPreset();
public static final ActionsPreset SINGLE_ACTION_PRESET = new SingleActionPreset();
public static final ActionsPreset[] PRESETS = new ActionsPreset[] {
NO_ACTIONS_PRESET,
SINGLE_ACTION_PRESET,
new ReplyActionPreset(),
new ReplyWithChoicesActionPreset(),
new DifferentActionsOnPhoneAndWearable(),
new LongTitleActionPreset()
};
private static class NoActionsPreset extends ActionsPreset {
public NoActionsPreset() {
super(R.string.no_actions);
}
@Override
public void apply(Context context, NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions) {
}
}
private static class SingleActionPreset extends ActionsPreset {
public SingleActionPreset() {
super(R.string.single_action);
}
@Override
public void apply(Context context, NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions) {
builder.addAction(R.drawable.ic_full_action,
context.getString(R.string.example_action),
NotificationUtil.getExamplePendingIntent(context,
R.string.example_action_clicked))
.build();
}
}
private static class LongTitleActionPreset extends ActionsPreset {
public LongTitleActionPreset() {
super(R.string.long_title_action);
}
@Override
public void apply(Context context, NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions) {
builder.addAction(R.drawable.ic_full_action,
context.getString(R.string.example_action_long_title),
NotificationUtil.getExamplePendingIntent(context,
R.string.example_action_clicked))
.build();
}
}
private static class ReplyActionPreset extends ActionsPreset {
public ReplyActionPreset() {
super(R.string.reply_action);
}
@Override
public void apply(Context context, NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions) {
RemoteInput remoteInput = new RemoteInput.Builder(NotificationUtil.EXTRA_REPLY)
.setLabel(context.getString(R.string.example_reply_label))
.build();
NotificationCompat.Action action = new NotificationCompat.Action.Builder(
R.drawable.ic_full_reply,
context.getString(R.string.example_reply_action),
NotificationUtil.getExamplePendingIntent(context,
R.string.example_reply_action_clicked))
.addRemoteInput(remoteInput)
.build();
builder.addAction(action);
}
}
private static class ReplyWithChoicesActionPreset extends ActionsPreset {
public ReplyWithChoicesActionPreset() {
super(R.string.reply_action_with_choices);
}
@Override
public void apply(Context context, NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions) {
RemoteInput remoteInput = new RemoteInput.Builder(NotificationUtil.EXTRA_REPLY)
.setLabel(context.getString(R.string.example_reply_answer_label))
.setChoices(new String[] { context.getString(R.string.yes),
context.getString(R.string.no), context.getString(R.string.maybe) })
.build();
NotificationCompat.Action action = new NotificationCompat.Action.Builder(
R.drawable.ic_full_reply,
context.getString(R.string.example_reply_action),
NotificationUtil.getExamplePendingIntent(context,
R.string.example_reply_action_clicked))
.addRemoteInput(remoteInput)
.build();
wearableOptions.addAction(action);
}
}
private static class DifferentActionsOnPhoneAndWearable extends ActionsPreset {
public DifferentActionsOnPhoneAndWearable() {
super(R.string.different_actions_on_phone_and_wearable);
}
@Override
public void apply(Context context, NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions) {
NotificationCompat.Action phoneAction = new NotificationCompat.Action.Builder(
R.drawable.ic_full_action,
context.getString(R.string.phone_action),
NotificationUtil.getExamplePendingIntent(context,
R.string.phone_action_clicked))
.build();
builder.addAction(phoneAction);
RemoteInput remoteInput = new RemoteInput.Builder(NotificationUtil.EXTRA_REPLY)
.setLabel(context.getString(R.string.example_reply_label))
.build();
NotificationCompat.Action wearableAction = new NotificationCompat.Action.Builder(
R.drawable.ic_full_reply,
context.getString(R.string.wearable_action),
NotificationUtil.getExamplePendingIntent(context,
R.string.wearable_action_clicked))
.addRemoteInput(remoteInput)
.build();
wearableOptions.addAction(wearableAction);
}
}
}

View File

@@ -0,0 +1,124 @@
package com.example.android.support.wearable.notifications;
import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Manages the background image pickers.
*/
public class BackgroundPickers {
public interface OnBackgroundPickersChangedListener {
public void onBackgroundPickersChanged(BackgroundPickers pickers);
}
private final ViewGroup mContainer;
private final OnPickedListener mOnPickedListener;
private final List<ViewGroup> mPickers;
private final OnBackgroundPickersChangedListener listener;
public BackgroundPickers(ViewGroup container, OnBackgroundPickersChangedListener listener) {
this.mContainer = container;
this.mOnPickedListener = new OnPickedListener();
this.mPickers = new ArrayList<ViewGroup>();
this.listener = listener;
}
/**
* Generates the pickers as necessary.
*/
public void generatePickers(int count) {
// Clear existing containers.
clear();
// Fill in new pickers.
LayoutInflater inflater = LayoutInflater.from(mContainer.getContext());
Resources res = mContainer.getResources();
for (int i = 0; i < count; i++) {
View picker = inflater.inflate(R.layout.background_picker, mContainer, false);
TextView label = (TextView) picker.findViewById(R.id.bg_picker_label);
label.setText(String.format(res.getString(R.string.bg_picker_label), i+1));
ViewGroup pickerBox = (ViewGroup) picker.findViewById(R.id.bg_picker_container);
mPickers.add(pickerBox);
for (int j = 0; j < pickerBox.getChildCount(); j++) {
ImageView img = (ImageView) pickerBox.getChildAt(j);
img.setOnClickListener(mOnPickedListener);
}
mContainer.addView(picker);
}
}
/**
* Returns the background resource for the picker at the given index.
* @param position Index of the background picker.
* @return Id of the background image resource. null if no image is picked.
*/
public Integer getRes(int position) {
String tag = (String) mPickers.get(position).getTag();
if (tag == null) {
return null;
}
Context context = mContainer.getContext();
return context.getResources().getIdentifier(tag, "drawable", context.getPackageName());
}
/**
* Returns the all the background resources for the pickers managed by this object. Returns null
* if no pickers exist.
*/
public Integer[] getRes() {
if (mPickers.size() == 0) {
return null;
}
Integer[] res = new Integer[mPickers.size()];
for (int i = 0; i < mPickers.size(); i++) {
res[i] = getRes(i);
}
return res;
}
/**
* Clears the pickers.
*/
public void clear() {
mContainer.removeAllViews();
mPickers.clear();
}
public int getCount() {
return mPickers.size();
}
private class OnPickedListener implements View.OnClickListener {
@Override
public void onClick(View view) {
ImageView pickedView = (ImageView) view;
ViewGroup pickerBox = (ViewGroup) view.getParent();
// Clear old selection.
for (int i = 0; i < pickerBox.getChildCount(); i++) {
ImageView childView = (ImageView) pickerBox.getChildAt(i);
childView.setBackgroundResource(R.drawable.unselected_background);
}
// Set new selection.
pickedView.setBackgroundResource(R.drawable.selected_background);
pickerBox.setTag(pickedView.getTag());
if (listener != null) {
listener.onBackgroundPickersChanged(BackgroundPickers.this);
}
}
}
}

View File

@@ -0,0 +1,336 @@
package com.example.android.support.wearable.notifications;
import android.app.Activity;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationManagerCompat;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.Arrays;
/**
* Main activity which posts a notification when resumed, and allows customization
* of that notification via controls.
*/
public class MainActivity extends Activity implements Handler.Callback {
private static final int MSG_POST_NOTIFICATIONS = 0;
private static final long POST_NOTIFICATIONS_DELAY_MS = 200;
private Handler mHandler;
private Spinner mPresetSpinner;
private EditText mTitleEditText;
private EditText mTextEditText;
private TextWatcher mTextChangedListener;
private Spinner mPrioritySpinner;
private Spinner mActionsSpinner;
private CheckBox mIncludeLargeIconCheckbox;
private CheckBox mLocalOnlyCheckbox;
private CheckBox mIncludeContentIntentCheckbox;
private CheckBox mVibrateCheckbox;
private BackgroundPickers mBackgroundPickers;
private int postedNotificationCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler(this);
mTextChangedListener = new UpdateNotificationsOnTextChangeListener();
initPresetSpinner();
initTitleEditText();
initTextEditText();
initPrioritySpinner();
initActionsSpinner();
initIncludeLargeIconCheckbox();
initLocalOnlyCheckbox();
initIncludeContentIntentCheckbox();
initVibrateCheckbox();
initBackgroundPickers();
NotificationPreset preset = NotificationPresets.PRESETS[
mPresetSpinner.getSelectedItemPosition()];
updateTextEditors(preset);
}
@Override
protected void onResume() {
super.onResume();
updateNotifications(false /* cancelExisting */);
}
private void initPresetSpinner() {
mPresetSpinner = (Spinner) findViewById(R.id.preset_spinner);
mPresetSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
NotificationPresets.PRESETS));
mPresetSpinner.post(new Runnable() {
@Override
public void run() {
mPresetSpinner.setOnItemSelectedListener(new PresetSpinnerListener());
}
});
}
private void initTitleEditText() {
mTitleEditText = (EditText) findViewById(R.id.title_editor);
}
private void initTextEditText() {
mTextEditText = (EditText) findViewById(R.id.text_editor);
}
private void initPrioritySpinner() {
mPrioritySpinner = (Spinner) findViewById(R.id.priority_spinner);
mPrioritySpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
PriorityPresets.PRESETS));
mPrioritySpinner.setSelection(Arrays.asList(PriorityPresets.PRESETS)
.indexOf(PriorityPresets.DEFAULT));
mPrioritySpinner.post(new Runnable() {
@Override
public void run() {
mPrioritySpinner.setOnItemSelectedListener(
new UpdateNotificationsOnItemSelectedListener(true /* cancelExisting */));
}
});
}
private void initActionsSpinner() {
mActionsSpinner = (Spinner) findViewById(R.id.actions_spinner);
mActionsSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
ActionsPresets.PRESETS));
mActionsSpinner.post(new Runnable() {
@Override
public void run() {
mActionsSpinner.setOnItemSelectedListener(
new UpdateNotificationsOnItemSelectedListener(false /* cancelExisting */));
}
});
}
private void initIncludeLargeIconCheckbox() {
mIncludeLargeIconCheckbox = (CheckBox) findViewById(R.id.include_large_icon_checkbox);
mIncludeLargeIconCheckbox.setOnCheckedChangeListener(
new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
}
private void initLocalOnlyCheckbox() {
mLocalOnlyCheckbox = (CheckBox) findViewById(R.id.local_only_checkbox);
mLocalOnlyCheckbox.setOnCheckedChangeListener(
new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
}
private void initIncludeContentIntentCheckbox() {
mIncludeContentIntentCheckbox = (CheckBox) findViewById(
R.id.include_content_intent_checkbox);
mIncludeContentIntentCheckbox.setOnCheckedChangeListener(
new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
}
private void initVibrateCheckbox() {
mVibrateCheckbox = (CheckBox) findViewById(R.id.vibrate_checkbox);
mVibrateCheckbox.setOnCheckedChangeListener(
new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
}
private void initBackgroundPickers() {
mBackgroundPickers = new BackgroundPickers(
(ViewGroup) findViewById(R.id.background_pickers),
new BackgroundPickerListener());
}
private void updateTextEditors(NotificationPreset preset) {
if (preset == NotificationPresets.BASIC) {
findViewById(R.id.title_edit_field).setVisibility(View.VISIBLE);
mTitleEditText.setText(getString(preset.titleResId));
mTitleEditText.addTextChangedListener(mTextChangedListener);
findViewById(R.id.text_edit_field).setVisibility(View.VISIBLE);
mTextEditText.setText(getString(preset.textResId));
mTextEditText.addTextChangedListener(mTextChangedListener);
} else {
findViewById(R.id.title_edit_field).setVisibility(View.GONE);
mTitleEditText.removeTextChangedListener(mTextChangedListener);
findViewById(R.id.text_edit_field).setVisibility(View.GONE);
mTextEditText.removeTextChangedListener(mTextChangedListener);
}
}
/**
* Begin to re-post the sample notification(s).
*/
private void updateNotifications(boolean cancelExisting) {
// Disable messages to skip notification deleted messages during cancel.
sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_DISABLE_MESSAGES)
.setClass(this, NotificationIntentReceiver.class));
if (cancelExisting) {
// Cancel all existing notifications to trigger fresh-posting behavior: For example,
// switching from HIGH to LOW priority does not cause a reordering in Notification Shade.
NotificationManagerCompat.from(this).cancelAll();
postedNotificationCount = 0;
// Post the updated notifications on a delay to avoid a cancel+post race condition
// with notification manager.
mHandler.removeMessages(MSG_POST_NOTIFICATIONS);
mHandler.sendEmptyMessageDelayed(MSG_POST_NOTIFICATIONS, POST_NOTIFICATIONS_DELAY_MS);
} else {
postNotifications();
}
}
/**
* Post the sample notification(s) using current options.
*/
private void postNotifications() {
sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_ENABLE_MESSAGES)
.setClass(this, NotificationIntentReceiver.class));
NotificationPreset preset = NotificationPresets.PRESETS[
mPresetSpinner.getSelectedItemPosition()];
CharSequence titlePreset = mTitleEditText.getText();
CharSequence textPreset = mTextEditText.getText();
PriorityPreset priorityPreset = PriorityPresets.PRESETS[
mPrioritySpinner.getSelectedItemPosition()];
ActionsPreset actionsPreset = ActionsPresets.PRESETS[
mActionsSpinner.getSelectedItemPosition()];
if (preset.actionsRequired() && actionsPreset == ActionsPresets.NO_ACTIONS_PRESET) {
// If actions are required, but the no-actions preset was selected, change presets.
actionsPreset = ActionsPresets.SINGLE_ACTION_PRESET;
mActionsSpinner.setSelection(Arrays.asList(ActionsPresets.PRESETS).indexOf(
actionsPreset), true);
}
NotificationPreset.BuildOptions options = new NotificationPreset.BuildOptions(
titlePreset,
textPreset,
priorityPreset,
actionsPreset,
mIncludeLargeIconCheckbox.isChecked(),
mLocalOnlyCheckbox.isChecked(),
mIncludeContentIntentCheckbox.isChecked(),
mVibrateCheckbox.isChecked(),
mBackgroundPickers.getRes());
Notification[] notifications = preset.buildNotifications(this, options);
// Post new notifications
for (int i = 0; i < notifications.length; i++) {
NotificationManagerCompat.from(this).notify(i, notifications[i]);
}
// Cancel any that are beyond the current count.
for (int i = notifications.length; i < postedNotificationCount; i++) {
NotificationManagerCompat.from(this).cancel(i);
}
postedNotificationCount = notifications.length;
}
@Override
public boolean handleMessage(Message message) {
switch (message.what) {
case MSG_POST_NOTIFICATIONS:
postNotifications();
return true;
}
return false;
}
private class PresetSpinnerListener implements AdapterView.OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
NotificationPreset preset = NotificationPresets.PRESETS[position];
mBackgroundPickers.generatePickers(preset.countBackgroundPickersRequired());
updateTextEditors(preset);
updateNotifications(false /* cancelExisting */);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
private class UpdateNotificationsOnTextChangeListener implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
updateNotifications(false /* cancelExisting */);
}
}
private class UpdateNotificationsOnItemSelectedListener
implements AdapterView.OnItemSelectedListener {
private final boolean mCancelExisting;
public UpdateNotificationsOnItemSelectedListener(boolean cancelExisting) {
mCancelExisting = cancelExisting;
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateNotifications(mCancelExisting);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
private class UpdateNotificationsOnCheckedChangeListener
implements CompoundButton.OnCheckedChangeListener {
private final boolean mCancelExisting;
public UpdateNotificationsOnCheckedChangeListener(boolean cancelExisting) {
mCancelExisting = cancelExisting;
}
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
updateNotifications(mCancelExisting);
}
}
private class BackgroundPickerListener
implements BackgroundPickers.OnBackgroundPickersChangedListener {
@Override
public void onBackgroundPickersChanged(BackgroundPickers pickers) {
updateNotifications(false /* cancelExisting */);
}
}
private class NamedPresetSpinnerArrayAdapter extends ArrayAdapter<NamedPreset> {
public NamedPresetSpinnerArrayAdapter(Context context, NamedPreset[] presets) {
super(context, R.layout.simple_spinner_item, presets);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getDropDownView(position, convertView, parent);
view.setText(getString(getItem(position).nameResId));
return view;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) getLayoutInflater().inflate(
android.R.layout.simple_spinner_item, parent, false);
view.setText(getString(getItem(position).nameResId));
return view;
}
}
}

View File

@@ -0,0 +1,12 @@
package com.example.android.support.wearable.notifications;
/**
* Base class for presets that have a simple name to display.
*/
public abstract class NamedPreset {
public final int nameResId;
public NamedPreset(int nameResId) {
this.nameResId = nameResId;
}
}

View File

@@ -0,0 +1,44 @@
package com.example.android.support.wearable.notifications;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.RemoteInput;
import android.widget.Toast;
/**
* Broadcast receiver to post toast messages in response to notification intents firing.
*/
public class NotificationIntentReceiver extends BroadcastReceiver {
public static final String ACTION_EXAMPLE =
"com.example.android.support.wearable.notifications.ACTION_EXAMPLE";
public static final String ACTION_ENABLE_MESSAGES =
"com.example.android.support.wearable.notifications.ACTION_ENABLE_MESSAGES";
public static final String ACTION_DISABLE_MESSAGES =
"com.example.android.support.wearable.notifications.ACTION_DISABLE_MESSAGES";
private boolean mEnableMessages = true;
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_EXAMPLE)) {
if (mEnableMessages) {
String message = intent.getStringExtra(NotificationUtil.EXTRA_MESSAGE);
Bundle remoteInputResults = RemoteInput.getResultsFromIntent(intent);
CharSequence replyMessage = null;
if (remoteInputResults != null) {
replyMessage = remoteInputResults.getCharSequence(NotificationUtil.EXTRA_REPLY);
}
if (replyMessage != null) {
message = message + ": \"" + replyMessage + "\"";
}
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
} else if (intent.getAction().equals(ACTION_ENABLE_MESSAGES)) {
mEnableMessages = true;
} else if (intent.getAction().equals(ACTION_DISABLE_MESSAGES)) {
mEnableMessages = false;
}
}
}

View File

@@ -0,0 +1,58 @@
package com.example.android.support.wearable.notifications;
import android.app.Notification;
import android.content.Context;
/**
* Base class for notification preset generators.
*/
public abstract class NotificationPreset extends NamedPreset {
public final int titleResId;
public final int textResId;
public NotificationPreset(int nameResId, int titleResId, int textResId) {
super(nameResId);
this.titleResId = titleResId;
this.textResId = textResId;
}
public static class BuildOptions {
public final CharSequence titlePreset;
public final CharSequence textPreset;
public final PriorityPreset priorityPreset;
public final ActionsPreset actionsPreset;
public final boolean includeLargeIcon;
public final boolean isLocalOnly;
public final boolean hasContentIntent;
public final boolean vibrate;
public final Integer[] backgroundIds;
public BuildOptions(CharSequence titlePreset, CharSequence textPreset,
PriorityPreset priorityPreset, ActionsPreset actionsPreset,
boolean includeLargeIcon, boolean isLocalOnly, boolean hasContentIntent,
boolean vibrate, Integer[] backgroundIds) {
this.titlePreset = titlePreset;
this.textPreset = textPreset;
this.priorityPreset = priorityPreset;
this.actionsPreset = actionsPreset;
this.includeLargeIcon = includeLargeIcon;
this.isLocalOnly = isLocalOnly;
this.hasContentIntent = hasContentIntent;
this.vibrate = vibrate;
this.backgroundIds = backgroundIds;
}
}
/** Build a notification with this preset and the provided options */
public abstract Notification[] buildNotifications(Context context, BuildOptions options);
/** Whether actions are required to use this preset. */
public boolean actionsRequired() {
return false;
}
/** Number of background pickers required */
public int countBackgroundPickersRequired() {
return 0;
}
}

View File

@@ -0,0 +1,463 @@
package com.example.android.support.wearable.notifications;
import android.app.Notification;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Typeface;
import android.support.v4.app.NotificationCompat;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TypefaceSpan;
import android.text.style.UnderlineSpan;
import android.view.Gravity;
/**
* Collection of notification builder presets.
*/
public class NotificationPresets {
private static final String EXAMPLE_GROUP_KEY = "example";
public static final NotificationPreset BASIC = new BasicNotificationPreset();
public static final NotificationPreset STYLIZED_TEXT = new StylizedTextNotificationPreset();
public static final NotificationPreset INBOX = new InboxNotificationPreset();
public static final NotificationPreset BIG_PICTURE = new BigPictureNotificationPreset();
public static final NotificationPreset BIG_TEXT = new BigTextNotificationPreset();
public static final NotificationPreset BOTTOM_ALIGNED = new BottomAlignedNotificationPreset();
public static final NotificationPreset GRAVITY = new GravityNotificationPreset();
public static final NotificationPreset CONTENT_ACTION = new ContentActionNotificationPreset();
public static final NotificationPreset CONTENT_ICON = new ContentIconNotificationPreset();
public static final NotificationPreset MULTIPLE_PAGE = new MultiplePageNotificationPreset();
public static final NotificationPreset BUNDLE = new NotificationBundlePreset();
public static final NotificationPreset[] PRESETS = new NotificationPreset[] {
BASIC,
STYLIZED_TEXT,
INBOX,
BIG_PICTURE,
BIG_TEXT,
BOTTOM_ALIGNED,
GRAVITY,
CONTENT_ACTION,
CONTENT_ICON,
MULTIPLE_PAGE,
BUNDLE
};
private static NotificationCompat.Builder applyBasicOptions(Context context,
NotificationCompat.Builder builder, NotificationCompat.WearableExtender wearableOptions,
NotificationPreset.BuildOptions options) {
builder.setContentTitle(options.titlePreset)
.setContentText(options.textPreset)
.setSmallIcon(R.mipmap.ic_launcher)
.setDeleteIntent(NotificationUtil.getExamplePendingIntent(
context, R.string.example_notification_deleted));
options.actionsPreset.apply(context, builder, wearableOptions);
options.priorityPreset.apply(builder, wearableOptions);
if (options.includeLargeIcon) {
builder.setLargeIcon(BitmapFactory.decodeResource(
context.getResources(), R.drawable.example_large_icon));
}
if (options.isLocalOnly) {
builder.setLocalOnly(true);
}
if (options.hasContentIntent) {
builder.setContentIntent(NotificationUtil.getExamplePendingIntent(context,
R.string.content_intent_clicked));
}
if (options.vibrate) {
builder.setVibrate(new long[] {0, 100, 50, 100} );
}
return builder;
}
private static class BasicNotificationPreset extends NotificationPreset {
public BasicNotificationPreset() {
super(R.string.basic_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, builder, wearableOptions, options);
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
}
private static class StylizedTextNotificationPreset extends NotificationPreset {
public StylizedTextNotificationPreset() {
super(R.string.stylized_text_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
SpannableStringBuilder title = new SpannableStringBuilder();
appendStyled(title, "Stylized", new StyleSpan(Typeface.BOLD_ITALIC));
title.append(" title");
SpannableStringBuilder text = new SpannableStringBuilder("Stylized text: ");
appendStyled(text, "C", new ForegroundColorSpan(Color.RED));
appendStyled(text, "O", new ForegroundColorSpan(Color.GREEN));
appendStyled(text, "L", new ForegroundColorSpan(Color.BLUE));
appendStyled(text, "O", new ForegroundColorSpan(Color.YELLOW));
appendStyled(text, "R", new ForegroundColorSpan(Color.MAGENTA));
appendStyled(text, "S", new ForegroundColorSpan(Color.CYAN));
text.append("; ");
appendStyled(text, "1.25x size", new RelativeSizeSpan(1.25f));
text.append("; ");
appendStyled(text, "0.75x size", new RelativeSizeSpan(0.75f));
text.append("; ");
appendStyled(text, "underline", new UnderlineSpan());
text.append("; ");
appendStyled(text, "strikethrough", new StrikethroughSpan());
text.append("; ");
appendStyled(text, "bold", new StyleSpan(Typeface.BOLD));
text.append("; ");
appendStyled(text, "italic", new StyleSpan(Typeface.ITALIC));
text.append("; ");
appendStyled(text, "sans-serif-thin", new TypefaceSpan("sans-serif-thin"));
text.append("; ");
appendStyled(text, "monospace", new TypefaceSpan("monospace"));
text.append("; ");
appendStyled(text, "sub", new SubscriptSpan());
text.append("script");
appendStyled(text, "super", new SuperscriptSpan());
style.setBigContentTitle(title);
style.bigText(text);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setStyle(style);
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, builder, wearableOptions, options);
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
private void appendStyled(SpannableStringBuilder builder, String str, Object... spans) {
builder.append(str);
for (Object span : spans) {
builder.setSpan(span, builder.length() - str.length(), builder.length(), 0);
}
}
}
private static class InboxNotificationPreset extends NotificationPreset {
public InboxNotificationPreset() {
super(R.string.inbox_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();
style.addLine(context.getString(R.string.inbox_style_example_line1));
style.addLine(context.getString(R.string.inbox_style_example_line2));
style.addLine(context.getString(R.string.inbox_style_example_line3));
style.setBigContentTitle(context.getString(R.string.inbox_style_example_title));
style.setSummaryText(context.getString(R.string.inbox_style_example_summary_text));
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setStyle(style);
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, builder, wearableOptions, options);
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
}
private static class BigPictureNotificationPreset extends NotificationPreset {
public BigPictureNotificationPreset() {
super(R.string.big_picture_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
R.drawable.example_big_picture));
style.setBigContentTitle(context.getString(R.string.big_picture_style_example_title));
style.setSummaryText(context.getString(
R.string.big_picture_style_example_summary_text));
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setStyle(style);
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, builder, wearableOptions, options);
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
}
private static class BigTextNotificationPreset extends NotificationPreset {
public BigTextNotificationPreset() {
super(R.string.big_text_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
style.bigText(context.getString(R.string.big_text_example_big_text));
style.setBigContentTitle(context.getString(R.string.big_text_example_title));
style.setSummaryText(context.getString(R.string.big_text_example_summary_text));
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setStyle(style);
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, builder, wearableOptions, options);
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
}
private static class BottomAlignedNotificationPreset extends NotificationPreset {
public BottomAlignedNotificationPreset() {
super(R.string.bottom_aligned_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, builder, wearableOptions, options);
NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context);
secondPageBuilder.setContentTitle(
context.getString(R.string.second_page_content_title));
secondPageBuilder.setContentText(context.getString(R.string.big_text_example_big_text));
secondPageBuilder.extend(new NotificationCompat.WearableExtender()
.setStartScrollBottom(true));
wearableOptions.addPage(secondPageBuilder.build());
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
}
private static class GravityNotificationPreset extends NotificationPreset {
public GravityNotificationPreset() {
super(R.string.gravity_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, builder, wearableOptions, options);
NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context)
.setContentTitle(options.titlePreset)
.setContentText(options.textPreset)
.extend(new NotificationCompat.WearableExtender()
.setGravity(Gravity.CENTER_VERTICAL));
wearableOptions.addPage(secondPageBuilder.build());
NotificationCompat.Builder thirdPageBuilder = new NotificationCompat.Builder(context)
.setContentTitle(options.titlePreset)
.setContentText(options.textPreset)
.extend(new NotificationCompat.WearableExtender()
.setGravity(Gravity.TOP));
wearableOptions.addPage(thirdPageBuilder.build());
wearableOptions.setGravity(Gravity.BOTTOM);
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
}
private static class ContentActionNotificationPreset extends NotificationPreset {
public ContentActionNotificationPreset() {
super(R.string.content_action_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
Notification secondPage = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.second_page_content_title))
.setContentText(context.getString(R.string.second_page_content_text))
.extend(new NotificationCompat.WearableExtender()
.setContentAction(1))
.build();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
NotificationCompat.Action action = new NotificationCompat.Action.Builder(
R.drawable.ic_result_open, null, NotificationUtil.getExamplePendingIntent(
context, R.string.example_content_action_clicked)).build();
NotificationCompat.Action action2 = new NotificationCompat.Action.Builder(
R.drawable.ic_result_open, null, NotificationUtil.getExamplePendingIntent(
context, R.string.example_content_action2_clicked)).build();
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender()
.addAction(action)
.addAction(action2)
.addPage(secondPage)
.setContentAction(0)
.setHintHideIcon(true);
applyBasicOptions(context, builder, wearableOptions, options);
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
@Override
public boolean actionsRequired() {
return true;
}
}
private static class ContentIconNotificationPreset extends NotificationPreset {
public ContentIconNotificationPreset() {
super(R.string.content_icon_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
Notification secondPage = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.second_page_content_title))
.setContentText(context.getString(R.string.second_page_content_text))
.extend(new NotificationCompat.WearableExtender()
.setContentIcon(R.drawable.content_icon_small)
.setContentIconGravity(Gravity.START))
.build();
Notification thirdPage = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.third_page_content_title))
.setContentText(context.getString(R.string.third_page_content_text))
.extend(new NotificationCompat.WearableExtender()
.setContentIcon(R.drawable.content_icon_large))
.build();
Notification fourthPage = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.fourth_page_content_title))
.setContentText(context.getString(R.string.fourth_page_content_text))
.extend(new NotificationCompat.WearableExtender()
.setContentIcon(R.drawable.content_icon_large)
.setContentIconGravity(Gravity.START))
.build();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
NotificationCompat.WearableExtender wearableOptions =
new NotificationCompat.WearableExtender()
.setHintHideIcon(true)
.setContentIcon(R.drawable.content_icon_small)
.addPage(secondPage)
.addPage(thirdPage)
.addPage(fourthPage);
applyBasicOptions(context, builder, wearableOptions, options);
builder.extend(wearableOptions);
return new Notification[] { builder.build() };
}
}
private static class MultiplePageNotificationPreset extends NotificationPreset {
public MultiplePageNotificationPreset() {
super(R.string.multiple_page_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.second_page_content_title))
.setContentText(context.getString(R.string.second_page_content_text));
NotificationCompat.Builder firstPageBuilder = new NotificationCompat.Builder(context);
NotificationCompat.WearableExtender firstPageWearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, firstPageBuilder, firstPageWearableOptions, options);
Integer firstBackground = options.backgroundIds == null
? null : options.backgroundIds[0];
if (firstBackground != null) {
NotificationCompat.BigPictureStyle style =
new NotificationCompat.BigPictureStyle();
style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
firstBackground));
firstPageBuilder.setStyle(style);
}
Integer secondBackground = options.backgroundIds == null
? null : options.backgroundIds[1];
if (secondBackground != null) {
NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
secondBackground));
secondPageBuilder.setStyle(style);
}
firstPageBuilder.extend(
firstPageWearableOptions.addPage(secondPageBuilder.build()));
return new Notification[]{ firstPageBuilder.build() };
}
@Override
public int countBackgroundPickersRequired() {
return 2; // This sample does 2 pages notifications.
}
}
private static class NotificationBundlePreset extends NotificationPreset {
public NotificationBundlePreset() {
super(R.string.bundle_example, R.string.example_content_title,
R.string.example_content_text);
}
@Override
public Notification[] buildNotifications(Context context, BuildOptions options) {
NotificationCompat.Builder childBuilder1 = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.first_child_content_title))
.setContentText(context.getString(R.string.first_child_content_text))
.setSmallIcon(R.mipmap.ic_launcher)
.setLocalOnly(options.isLocalOnly)
.setGroup(EXAMPLE_GROUP_KEY)
.setSortKey("0");
NotificationCompat.Builder childBuilder2 = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.second_child_content_title))
.setContentText(context.getString(R.string.second_child_content_text))
.setSmallIcon(R.mipmap.ic_launcher)
.addAction(R.mipmap.ic_launcher,
context.getString(R.string.second_child_action),
NotificationUtil.getExamplePendingIntent(
context, R.string.second_child_action_clicked))
.setLocalOnly(options.isLocalOnly)
.setGroup(EXAMPLE_GROUP_KEY)
.setSortKey("1");
NotificationCompat.Builder summaryBuilder = new NotificationCompat.Builder(context)
.setGroup(EXAMPLE_GROUP_KEY)
.setGroupSummary(true);
NotificationCompat.WearableExtender summaryWearableOptions =
new NotificationCompat.WearableExtender();
applyBasicOptions(context, summaryBuilder, summaryWearableOptions, options);
summaryBuilder.extend(summaryWearableOptions);
return new Notification[] { summaryBuilder.build(), childBuilder1.build(),
childBuilder2.build() };
}
}
}

View File

@@ -0,0 +1,20 @@
package com.example.android.support.wearable.notifications;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
public class NotificationUtil {
public static final String EXTRA_MESSAGE =
"com.example.android.support.wearable.notifications.MESSAGE";
public static final String EXTRA_REPLY =
"com.example.android.support.wearable.notifications.REPLY";
public static PendingIntent getExamplePendingIntent(Context context, int messageResId) {
Intent intent = new Intent(NotificationIntentReceiver.ACTION_EXAMPLE)
.setClass(context, NotificationIntentReceiver.class);
intent.putExtra(EXTRA_MESSAGE, context.getString(messageResId));
return PendingIntent.getBroadcast(context, messageResId /* requestCode */, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
}

View File

@@ -0,0 +1,16 @@
package com.example.android.support.wearable.notifications;
import android.support.v4.app.NotificationCompat;
/**
* Base class for notification priority presets.
*/
public abstract class PriorityPreset extends NamedPreset {
public PriorityPreset(int nameResId) {
super(nameResId);
}
/** Apply the priority to a notification builder */
public abstract void apply(NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions);
}

View File

@@ -0,0 +1,39 @@
package com.example.android.support.wearable.notifications;
import android.app.Notification;
import android.support.v4.app.NotificationCompat;
/**
* Collection of notification priority presets.
*/
public class PriorityPresets {
public static final PriorityPreset DEFAULT = new SimplePriorityPreset(
R.string.default_priority, Notification.PRIORITY_DEFAULT);
public static final PriorityPreset[] PRESETS = new PriorityPreset[] {
new SimplePriorityPreset(R.string.min_priority, Notification.PRIORITY_MIN),
new SimplePriorityPreset(R.string.low_priority, Notification.PRIORITY_LOW),
DEFAULT,
new SimplePriorityPreset(R.string.high_priority, Notification.PRIORITY_HIGH),
new SimplePriorityPreset(R.string.max_priority, Notification.PRIORITY_MAX)
};
/**
* Simple notification priority preset that sets a priority using
* {@link android.support.v4.app.NotificationCompat.Builder#setPriority}
*/
private static class SimplePriorityPreset extends PriorityPreset {
private final int mPriority;
public SimplePriorityPreset(int nameResId, int priority) {
super(nameResId);
mPriority = priority;
}
@Override
public void apply(NotificationCompat.Builder builder,
NotificationCompat.WearableExtender wearableOptions) {
builder.setPriority(mPriority);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<padding
android:top="4dp"
android:bottom="4dp"
android:left="4dp"
android:right="4dp"/>
<stroke
android:width="4dp"
android:color="@android:color/holo_blue_bright" />
</shape>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<padding
android:top="4dp"
android:bottom="4dp"
android:left="4dp"
android:right="4dp"/>
<stroke
android:width="4dp"
android:color="#ff000000" />
</shape>

View File

@@ -0,0 +1,157 @@
<ScrollView 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.android.support.wearable.notifications.MainActivity"
tools:ignore="MergeRootFrame">
<LinearLayout android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/layout_divider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="@dimen/editor_spinner_caption_min_width"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:gravity="center_vertical"
android:text="@string/preset" />
<Spinner android:id="@+id/preset_spinner"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="@dimen/editor_spinner_caption_min_width"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:gravity="center_vertical"
android:text="@string/priority" />
<Spinner android:id="@+id/priority_spinner"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="@dimen/editor_spinner_caption_min_width"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:gravity="center_vertical"
android:text="@string/actions" />
<Spinner android:id="@+id/actions_spinner"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/title_edit_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="@dimen/editor_spinner_caption_min_width"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:gravity="center_vertical"
android:text="@string/title" />
<EditText android:id="@+id/title_editor"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/text_edit_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="@dimen/editor_spinner_caption_min_width"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:gravity="center_vertical"
android:text="@string/text" />
<EditText android:id="@+id/text_editor"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<CheckBox android:id="@+id/include_large_icon_checkbox"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingTop="@dimen/editor_item_padding_top"
android:paddingBottom="@dimen/editor_item_padding_bottom"
android:text="@string/include_large_icon" />
<CheckBox android:id="@+id/local_only_checkbox"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingTop="@dimen/editor_item_padding_top"
android:paddingBottom="@dimen/editor_item_padding_bottom"
android:text="@string/local_only" />
<CheckBox android:id="@+id/include_content_intent_checkbox"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingTop="@dimen/editor_item_padding_top"
android:paddingBottom="@dimen/editor_item_padding_bottom"
android:text="@string/include_content_intent" />
<CheckBox android:id="@+id/vibrate_checkbox"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingTop="@dimen/editor_item_padding_top"
android:paddingBottom="@dimen/editor_item_padding_bottom"
android:text="@string/vibrate" />
<LinearLayout android:id="@+id/background_pickers"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/bg_picker_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/editor_item_padding_top"
android:paddingTop="@dimen/editor_item_padding_top"
android:paddingBottom="@dimen/editor_item_padding_top"
android:text="@string/bg_picker_label"/>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/bg_picker_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/bg_none"
android:background="@drawable/selected_background"
style="@style/bg_picker"
android:layout_width="@dimen/image_picker_item_side"
android:layout_height="@dimen/image_picker_item_side"
android:src="@android:color/background_light"/>
<ImageView
android:id="@+id/bg1"
style="@style/bg_picker"
android:layout_width="@dimen/image_picker_item_side"
android:layout_height="@dimen/image_picker_item_side"
android:tag="bg_1"
android:src="@drawable/bg_1"/>
<ImageView
android:id="@+id/bg2"
style="@style/bg_picker"
android:layout_width="@dimen/image_picker_item_side"
android:layout_height="@dimen/image_picker_item_side"
android:tag="bg_2"
android:src="@drawable/bg_2"/>
<ImageView
android:id="@+id/bg3"
style="@style/bg_picker"
android:layout_width="@dimen/image_picker_item_side"
android:layout_height="@dimen/image_picker_item_side"
android:tag="bg_3"
android:src="@drawable/bg_3"/>
<ImageView
android:id="@+id/bg4"
style="@style/bg_picker"
android:layout_width="@dimen/image_picker_item_side"
android:layout_height="@dimen/image_picker_item_side"
android:tag="bg_4"
android:src="@drawable/bg_4"/>
<ImageView
android:id="@+id/bg5"
style="@style/bg_picker"
android:layout_width="@dimen/image_picker_item_side"
android:layout_height="@dimen/image_picker_item_side"
android:tag="bg_5"
android:src="@drawable/bg_5"/>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/divider_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:textAllCaps="true"
android:textColor="@color/divider_text"
android:textSize="@dimen/editor_text_size"
android:text="@string/properties"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="3dp"
android:background="@color/divider_text" />
</LinearLayout>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeightSmall" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="divider_text">@android:color/holo_blue_bright</color>
</resources>

View File

@@ -0,0 +1,13 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="editor_text_size">12dp</dimen>
<dimen name="editor_item_padding_top">8dp</dimen>
<dimen name="editor_item_padding_bottom">8dp</dimen>
<dimen name="editor_spinner_caption_min_width">50dp</dimen>
<dimen name="image_picker_item_side">48dp</dimen>
</resources>

View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Wearable Notifications</string>
<string name="properties">Properties</string>
<string name="preset">Preset</string>
<string name="text">Text</string>
<string name="title">Title</string>
<string name="priority">Priority</string>
<string name="actions">Actions</string>
<string name="include_large_icon">Include large icon</string>
<string name="local_only">Local only</string>
<string name="include_content_intent">Include content intent</string>
<string name="vibrate">Vibrate</string>
<string name="basic_example">Basic example</string>
<string name="stylized_text_example">Stylized text example</string>
<string name="inbox_example">Inbox example</string>
<string name="big_picture_example">Big picture example</string>
<string name="big_text_example">Big text example</string>
<string name="bottom_aligned_example">Bottom-aligned example</string>
<string name="gravity_example">Gravity example</string>
<string name="content_action_example">Content action example</string>
<string name="content_icon_example">Content icon example</string>
<string name="multiple_page_example">Multiple page example</string>
<string name="bundle_example">Bundle example</string>
<string name="min_priority">Min priority</string>
<string name="low_priority">Low priority</string>
<string name="default_priority">Default priority</string>
<string name="high_priority">High priority</string>
<string name="max_priority">Max priority</string>
<string name="no_actions">No actions</string>
<string name="single_action">Single action</string>
<string name="long_title_action">Single action with a long title</string>
<string name="reply_action">Reply action</string>
<string name="reply_action_with_choices">Reply action with choices</string>
<string name="different_actions_on_phone_and_wearable">Different on phone and wearable</string>
<string name="example_action">Example action</string>
<string name="example_action_long_title">Example action with a long title which wraps</string>
<string name="example_reply_action">Example reply action</string>
<string name="phone_action">Phone action</string>
<string name="wearable_action">Wearable action</string>
<string name="example_action_clicked">Example action clicked</string>
<string name="example_reply_action_clicked">Example reply action clicked</string>
<string name="phone_action_clicked">Phone action clicked</string>
<string name="wearable_action_clicked">Wearable action clicked</string>
<string name="second_child_action_clicked">Second child action clicked</string>
<string name="content_intent_clicked">Content intent clicked</string>
<string name="example_content_action_clicked">Example content action clicked</string>
<string name="example_content_action2_clicked">Example content action 2 clicked</string>
<string name="example_notification_deleted">Example notification deleted</string>
<string name="example_content_title">Basic example title</string>
<string name="example_content_text">Basic example text</string>
<string name="big_text_example_title">Big text example title</string>
<string name="big_text_example_summary_text">Big text example summary</string>
<string name="big_text_example_big_text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
</string>
<string name="inbox_style_example_title">Inbox style example title</string>
<string name="inbox_style_example_summary_text">Inbox style example summary</string>
<string name="inbox_style_example_line1">Inbox style example line 1</string>
<string name="inbox_style_example_line2">Inbox style example line 2</string>
<string name="inbox_style_example_line3">Inbox style example line 3</string>
<string name="big_picture_style_example_title">Big picture style example title</string>
<string name="big_picture_style_example_summary_text">Big picture style example summary</string>
<string name="second_page_content_title">Second page title</string>
<string name="second_page_content_text">Second page text</string>
<string name="third_page_content_title">Third page title</string>
<string name="third_page_content_text">Third page text</string>
<string name="fourth_page_content_title">Fourth page title</string>
<string name="fourth_page_content_text">Fourth page text</string>
<string name="first_child_content_title">First child title</string>
<string name="first_child_content_text">
First child text. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.</string>
<string name="second_child_content_title">Second child title</string>
<string name="second_child_content_text">
Second child text. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.</string>
<string name="second_child_action">Second child action</string>
<string name="example_reply_label">Message?</string>
<string name="example_reply_answer_label">Answer?</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="maybe">Maybe</string>
<string name="bg_picker_label">Page %s background: </string>
</resources>

View File

@@ -0,0 +1,13 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo">
<!-- Customize your theme here. -->
</style>
<style name="bg_picker">
<item name="android:layout_marginLeft">16dp</item>
<item name="android:background">@drawable/unselected_background</item>
</style>
</resources>

View File

@@ -0,0 +1,25 @@
apply plugin: 'android'
android {
compileSdkVersion 20
buildToolsVersion "19.1"
defaultConfig {
minSdkVersion 20
targetSdkVersion 20
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile "com.android.support:support-v13:20.0.+"
compile "com.google.android.support:wearable:1.0.+"
}

View File

@@ -0,0 +1,22 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-dontwarn android.support.wearable.view.DelayedConfirmationView
-dontwarn android.support.wearable.view.CircledImageView

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.support.wearable.notifications" >
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault.Light" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".BasicNotificationDisplayActivity"
android:exported="true"
android:allowEmbedded="true"
android:label="@string/app_name"
android:taskAffinity="" />
<activity
android:name=".AnimatedNotificationDisplayActivity"
android:exported="true"
android:allowEmbedded="true"
android:label="@string/app_name"
android:taskAffinity="" />
</application>
</manifest>

View File

@@ -0,0 +1,122 @@
package com.example.android.support.wearable.notifications;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Random;
/**
* Custom display activity for an animated sample notification.
*/
public class AnimatedNotificationDisplayActivity extends Activity {
public static final String EXTRA_TITLE = "title";
private static final int BASE_ANIMATION_DURATION_MS = 2000;
private Random mRandom;
private int mAnimationRange;
private ImageView mImageView;
private Animator mAnimation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animated_notification_display);
mRandom = new Random(System.currentTimeMillis());
mAnimationRange = getResources().getDimensionPixelSize(R.dimen.animation_range);
String title = getIntent().getStringExtra(EXTRA_TITLE);
((TextView) findViewById(R.id.title)).setText(title);
mImageView = new ImageView(this);
mImageView.setImageResource(R.drawable.example_big_picture);
ImageZoomView zoomView = new ImageZoomView(this, mImageView, mAnimationRange);
zoomView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
((FrameLayout) findViewById(R.id.container)).addView(zoomView, 0);
createNextAnimation(false);
}
private void createNextAnimation(boolean start) {
float startX = mImageView.getTranslationX();
float startY = mImageView.getTranslationY();
float endX = -mRandom.nextInt(mAnimationRange);
float endY = -mRandom.nextInt(mAnimationRange);
float distance = (float) Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
mAnimation = ObjectAnimator.ofPropertyValuesHolder(mImageView,
PropertyValuesHolder.ofFloat("translationX", startX, endX),
PropertyValuesHolder.ofFloat("translationY", startY, endY));
mAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
mAnimation.setDuration(Math.max(BASE_ANIMATION_DURATION_MS / 10,
(int) (distance * BASE_ANIMATION_DURATION_MS / mAnimationRange)));
mAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
createNextAnimation(true);
}
});
if (start) {
mAnimation.start();
}
}
@Override
protected void onResume() {
super.onResume();
mAnimation.start();
}
@Override
protected void onPause() {
mAnimation.pause();
super.onPause();
}
/** Helper view that zooms in on a child image view */
private static class ImageZoomView extends ViewGroup {
private final int mZoomLength;
public ImageZoomView(Context context, ImageView imageView, int zoomLength) {
super(context);
addView(imageView);
mZoomLength = zoomLength;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
ImageView imageView = (ImageView) getChildAt(0);
// Resize the image view to be at least mZoomLength pixels larger in both
// dimensions than the containing view.
int imageWidth = imageView.getDrawable().getIntrinsicWidth();
int imageHeight = imageView.getDrawable().getIntrinsicHeight();
int minSize = Math.max(right - left, bottom - top) + mZoomLength;
if (imageWidth > imageHeight) {
imageWidth = minSize * imageWidth / imageHeight;
imageHeight = minSize;
} else {
imageHeight = minSize * imageHeight / imageWidth;
imageWidth = minSize;
}
imageView.layout(left, top, left + imageWidth, top + imageHeight);
}
}
}

View File

@@ -0,0 +1,22 @@
package com.example.android.support.wearable.notifications;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
/**
* Custom display activity for a sample notification.
*/
public class BasicNotificationDisplayActivity extends Activity {
public static final String EXTRA_TITLE = "title";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification_display);
String title = getIntent().getStringExtra(EXTRA_TITLE);
((TextView) findViewById(R.id.title)).setText(title);
}
}

View File

@@ -0,0 +1,89 @@
package com.example.android.support.wearable.notifications;
import android.app.Notification;
import android.app.RemoteInput;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.NotificationManagerCompat;
import android.support.wearable.activity.WatchActivity;
import android.support.wearable.view.WearableListView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends WatchActivity implements WearableListView.ClickListener {
private static final int SAMPLE_NOTIFICATION_ID = 0;
public static final String KEY_REPLY = "reply";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WearableListView listView = (WearableListView) findViewById(R.id.list);
listView.setAdapter(new Adapter(this));
listView.setClickListener(this);
}
@Override
protected void onResume() {
super.onResume();
if (getIntent() != null) {
Bundle inputResults = RemoteInput.getResultsFromIntent(getIntent());
if (inputResults != null) {
CharSequence replyText = inputResults.getCharSequence(KEY_REPLY);
if (replyText != null) {
Toast.makeText(this, TextUtils.concat(getString(R.string.reply_was), replyText),
Toast.LENGTH_LONG).show();
}
}
}
}
/** Post a new or updated notification using the selected notification options. */
private void updateNotification(int presetIndex) {
NotificationPreset preset = NotificationPresets.PRESETS[presetIndex];
Notification notif = preset.buildNotification(this);
NotificationManagerCompat.from(this).notify(SAMPLE_NOTIFICATION_ID, notif);
finish();
}
@Override
public void onClick(WearableListView.ViewHolder v) {
updateNotification((Integer) v.itemView.getTag());
}
@Override
public void onTopEmptyRegionClick() {
}
private static final class Adapter extends WearableListView.Adapter {
private final Context mContext;
private final LayoutInflater mInflater;
private Adapter(Context context) {
mContext = context;
mInflater = LayoutInflater.from(context);
}
@Override
public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new WearableListView.ViewHolder(
mInflater.inflate(R.layout.notif_preset_list_item, null));
}
@Override
public void onBindViewHolder(WearableListView.ViewHolder holder, int position) {
TextView view = (TextView) holder.itemView.findViewById(R.id.name);
view.setText(mContext.getString(NotificationPresets.PRESETS[position].nameResId));
holder.itemView.setTag(position);
}
@Override
public int getItemCount() {
return NotificationPresets.PRESETS.length;
}
}
}

View File

@@ -0,0 +1,18 @@
package com.example.android.support.wearable.notifications;
import android.app.Notification;
import android.content.Context;
/**
* Base class for notification preset generators.
*/
public abstract class NotificationPreset {
public final int nameResId;
public NotificationPreset(int nameResId) {
this.nameResId = nameResId;
}
/** Start building a notification with this preset */
public abstract Notification buildNotification(Context context);
}

View File

@@ -0,0 +1,298 @@
package com.example.android.support.wearable.notifications;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TypefaceSpan;
import android.text.style.UnderlineSpan;
import android.util.TypedValue;
import android.view.Gravity;
/**
* Collection of notification builder presets.
*/
public class NotificationPresets {
public static final NotificationPreset[] PRESETS = new NotificationPreset[] {
new BasicPreset(),
new StylizedTextPreset(),
new DisplayIntentPreset(),
new MultiSizeDisplayIntentPreset(),
new AnimatedDisplayIntentPreset(),
new ContentIconPreset()
};
private static Notification.Builder buildBasicNotification(Context context) {
return new Notification.Builder(context)
.setContentTitle(context.getString(R.string.example_content_title))
.setContentText(context.getString(R.string.example_content_text))
// Set a content intent to return to this sample
.setContentIntent(PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0))
.setSmallIcon(R.mipmap.ic_launcher);
}
private static class BasicPreset extends NotificationPreset {
public BasicPreset() {
super(R.string.basic_example);
}
@Override
public Notification buildNotification(Context context) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
Notification page2 = buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setHintShowBackgroundOnly(true)
.setBackground(BitmapFactory.decodeResource(context.getResources(),
R.drawable.example_big_picture)))
.build();
Notification page3 = buildBasicNotification(context)
.setContentTitle(context.getString(R.string.third_page))
.setContentText(null)
.extend(new Notification.WearableExtender()
.setContentAction(0 /* action A */))
.build();
SpannableStringBuilder choice2 = new SpannableStringBuilder(
"This choice is best");
choice2.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 5, 11, 0);
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_a), pendingIntent))
.addAction(new Notification.Action.Builder(R.mipmap.ic_launcher,
context.getString(R.string.reply), pendingIntent)
.addRemoteInput(new RemoteInput.Builder(MainActivity.KEY_REPLY)
.setChoices(new CharSequence[] {
context.getString(R.string.choice_1),
choice2 })
.build())
.build())
.addPage(page2)
.addPage(page3))
.build();
}
}
private static class StylizedTextPreset extends NotificationPreset {
public StylizedTextPreset() {
super(R.string.stylized_text_example);
}
@Override
public Notification buildNotification(Context context) {
Notification.Builder builder = buildBasicNotification(context);
Notification.BigTextStyle style = new Notification.BigTextStyle();
SpannableStringBuilder title = new SpannableStringBuilder();
appendStyled(title, "Stylized", new StyleSpan(Typeface.BOLD_ITALIC));
title.append(" title");
SpannableStringBuilder text = new SpannableStringBuilder("Stylized text: ");
appendStyled(text, "C", new ForegroundColorSpan(Color.RED));
appendStyled(text, "O", new ForegroundColorSpan(Color.GREEN));
appendStyled(text, "L", new ForegroundColorSpan(Color.BLUE));
appendStyled(text, "O", new ForegroundColorSpan(Color.YELLOW));
appendStyled(text, "R", new ForegroundColorSpan(Color.MAGENTA));
appendStyled(text, "S", new ForegroundColorSpan(Color.CYAN));
text.append("; ");
appendStyled(text, "1.25x size", new RelativeSizeSpan(1.25f));
text.append("; ");
appendStyled(text, "0.75x size", new RelativeSizeSpan(0.75f));
text.append("; ");
appendStyled(text, "underline", new UnderlineSpan());
text.append("; ");
appendStyled(text, "strikethrough", new StrikethroughSpan());
text.append("; ");
appendStyled(text, "bold", new StyleSpan(Typeface.BOLD));
text.append("; ");
appendStyled(text, "italic", new StyleSpan(Typeface.ITALIC));
text.append("; ");
appendStyled(text, "sans-serif-thin", new TypefaceSpan("sans-serif-thin"));
text.append("; ");
appendStyled(text, "monospace", new TypefaceSpan("monospace"));
text.append("; ");
appendStyled(text, "sub", new SubscriptSpan());
text.append("script");
appendStyled(text, "super", new SuperscriptSpan());
style.setBigContentTitle(title);
style.bigText(text);
builder.setStyle(style);
return builder.build();
}
private void appendStyled(SpannableStringBuilder builder, String str, Object... spans) {
builder.append(str);
for (Object span : spans) {
builder.setSpan(span, builder.length() - str.length(), builder.length(), 0);
}
}
}
private static class DisplayIntentPreset extends NotificationPreset {
public DisplayIntentPreset() {
super(R.string.display_intent_example);
}
@Override
public Notification buildNotification(Context context) {
Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class);
displayIntent.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(nameResId));
PendingIntent displayPendingIntent = PendingIntent.getActivity(context,
0, displayIntent, PendingIntent.FLAG_UPDATE_CURRENT);
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(displayPendingIntent))
.build();
}
}
private static class MultiSizeDisplayIntentPreset extends NotificationPreset {
public MultiSizeDisplayIntentPreset() {
super(R.string.multisize_display_intent_example);
}
@Override
public Notification buildNotification(Context context) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(R.string.xsmall_sized_display));
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.addPage(createPageForSizePreset(context,
Notification.WearableExtender.SIZE_SMALL,
R.string.small_sized_display, 0))
.addPage(createPageForSizePreset(context,
Notification.WearableExtender.SIZE_MEDIUM,
R.string.medium_sized_display, 1))
.addPage(createPageForSizePreset(context,
Notification.WearableExtender.SIZE_LARGE,
R.string.large_sized_display, 2))
.addPage(createPageForSizePreset(context,
Notification.WearableExtender.SIZE_FULL_SCREEN,
R.string.full_screen_display, 3))
.addPage(createPageForCustomHeight(context, 256,
R.string.dp256_height_display))
.addPage(createPageForCustomHeight(context, 512,
R.string.dp512_height_display))
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_a), pendingIntent))
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_b), pendingIntent))
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_c), pendingIntent))
.addAction(new Notification.Action(R.mipmap.ic_launcher,
context.getString(R.string.action_d), pendingIntent))
.setCustomSizePreset(Notification.WearableExtender.SIZE_XSMALL))
.build();
}
private Notification createPageForCustomHeight(Context context, int heightDisplayDp,
int pageNameResId) {
int contentHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
heightDisplayDp, context.getResources().getDisplayMetrics());
Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
.setData(Uri.fromParts("example", "height/" + heightDisplayDp, null))
.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(pageNameResId));
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setCustomContentHeight(contentHeight))
.build();
}
private Notification createPageForSizePreset(Context context, int sizePreset,
int pageNameResId, int contentAction) {
Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
.setData(Uri.fromParts("example", "size/" + sizePreset, null))
.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(pageNameResId));
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setCustomSizePreset(sizePreset)
.setContentAction(contentAction))
.build();
}
}
private static class AnimatedDisplayIntentPreset extends NotificationPreset {
public AnimatedDisplayIntentPreset() {
super(R.string.animated_display_intent_example);
}
@Override
public Notification buildNotification(Context context) {
Intent displayIntent = new Intent(context, AnimatedNotificationDisplayActivity.class);
displayIntent.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
context.getString(nameResId));
PendingIntent displayPendingIntent = PendingIntent.getActivity(context,
0, displayIntent, 0);
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setDisplayIntent(displayPendingIntent))
.build();
}
}
private static class ContentIconPreset extends NotificationPreset {
public ContentIconPreset() {
super(R.string.content_icon_example);
}
@Override
public Notification buildNotification(Context context) {
Notification page2 = buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setContentIcon(R.drawable.content_icon_small)
.setContentIconGravity(Gravity.START))
.build();
Notification page3 = buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setContentIcon(R.drawable.content_icon_large))
.build();
Notification page4 = buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setContentIcon(R.drawable.content_icon_large)
.setContentIconGravity(Gravity.START))
.build();
return buildBasicNotification(context)
.extend(new Notification.WearableExtender()
.setHintHideIcon(true)
.setContentIcon(R.drawable.content_icon_small)
.addPage(page2)
.addPage(page3)
.addPage(page4))
.build();
}
}
}

View File

@@ -0,0 +1,75 @@
package com.example.android.support.wearable.notifications;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.support.wearable.view.WearableListView;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
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.wl_gray);
mChosenCircleColor = getResources().getColor(R.color.wl_blue);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mCircle = (ImageView) findViewById(R.id.circle);
mName = (TextView) findViewById(R.id.name);
}
@Override
public float getProximityMinValue() {
return 1f;
}
@Override
public float getProximityMaxValue() {
return 1.6f;
}
@Override
public float getCurrentProximityValue() {
return mScale;
}
@Override
public void setScalingAnimatorValue(float scale) {
mScale = scale;
mCircle.setScaleX(scale);
mCircle.setScaleY(scale);
}
@Override
public void onScaleUpStart() {
mName.setAlpha(1f);
((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor);
}
@Override
public void onScaleDownStart() {
((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor);
mName.setAlpha(mFadedTextAlpha);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/wl_gray"/>
</shape>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="16sp"
android:padding="8dp"
android:gravity="center_vertical|center_horizontal"
android:textColor="#FF3333"
android:shadowColor="#992222"
android:shadowRadius="2"
android:shadowDx="1"
android:shadowDy="1" />
</FrameLayout>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.WearableListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:dividerHeight="0dp"/>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="16sp"
android:padding="8dp"
android:gravity="center_vertical|center_horizontal"
android:textColor="#7777FF"
android:shadowColor="#222299"
android:shadowRadius="2"
android:shadowDx="1"
android:shadowDy="1"
/>
</LinearLayout>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="wl_blue">#2878ff</color>
<color name="wl_gray">#c1c1c1</color>
<color name="text_color">#434343</color>
</resources>

View File

@@ -0,0 +1,7 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="animation_range">60dp</dimen>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="action_text_faded_alpha">40</integer>
</resources>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Wearable Notifications</string>
<string name="basic_example">Basic example</string>
<string name="stylized_text_example">Stylized text example</string>
<string name="display_intent_example">Display intent example</string>
<string name="multisize_display_intent_example">Multiple-sized display intent example</string>
<string name="animated_display_intent_example">Animated display intent example</string>
<string name="content_icon_example">Content icon example</string>
<string name="example_content_title">Example content title</string>
<string name="example_content_text">Example content text</string>
<string name="xsmall_sized_display">X-Small sized display</string>
<string name="small_sized_display">Small sized display</string>
<string name="medium_sized_display">Medium sized display</string>
<string name="large_sized_display">Large sized display</string>
<string name="full_screen_display">Full-Screen display</string>
<string name="dp256_height_display">256dp height display</string>
<string name="dp512_height_display">512dp height display</string>
<string name="action_a">Action A</string>
<string name="action_b">Action B</string>
<string name="action_c">Action C</string>
<string name="action_d">Action D</string>
<string name="reply">Reply</string>
<string name="reply_was">Reply was: </string>
<string name="third_page">Third page</string>
<string name="choice_1">Choice #1</string>
</resources>

View File

@@ -0,0 +1,14 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.11.+'
}
}
allprojects {
repositories {
mavenCentral()
}
}

View File

@@ -0,0 +1,18 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Settings specified in this file will override any Gradle settings
# configured through the IDE.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Fri Mar 14 14:02:22 PDT 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-all.zip

164
samples/wearable/Notifications/gradlew vendored Executable file
View File

@@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
samples/wearable/Notifications/gradlew.bat vendored Executable file
View File

@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1 @@
include 'Wearable', 'Application'

View File

@@ -0,0 +1,30 @@
buildscript {
ext.topDir = file('../../../../../')
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.11.+'
}
}
List<String> samples = [
"Notifications"
]
List<String> taskNames = [
"clean",
"build",
]
taskNames.each { taskName ->
def task = project.hasProperty(taskName) ? project.tasks[taskName] : project.task(taskName)
samples.each { sample ->
File sampleDir = new File(sample)
task.dependsOn project.task([type: GradleBuild], "${sample}_${taskName}", {
buildFile = "${sample}/build.gradle"
dir = sample
tasks = [taskName]
})
}
}

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Fri Mar 14 14:02:22 PDT 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-all.zip

174
samples/wearable/gradlew vendored Executable file
View File

@@ -0,0 +1,174 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Change the project's .gradle to the android out dir.
ANDROID_GRADLE_ROOT="$APP_HOME/../../../../out/host/gradle/tools/updater"
if [[ -z "$ANDROID_CACHE_DIR" ]]; then
ANDROID_CACHE_DIR="$ANDROID_GRADLE_ROOT/.gradle"
fi
# Change the local user directories to be under the android out dir
export GRADLE_USER_HOME="$ANDROID_GRADLE_ROOT/.gradle"
export M2_HOME="$ANDROID_GRADLE_ROOT/.m2"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
samples/wearable/gradlew.bat vendored Executable file
View File

@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File