am b6bca953: Add first wearable sample to sdk samples distribution
* commit 'b6bca953909d42a6284de4128d767eff8c9862ee': Add first wearable sample to sdk samples distribution
42
samples/wearable/.gitignore
vendored
Normal 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/
|
||||
|
||||
24
samples/wearable/Notifications/Application/_index.html
Normal 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>
|
||||
29
samples/wearable/Notifications/Application/build.gradle
Normal 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')
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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() };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 915 B |
|
After Width: | Height: | Size: 794 KiB |
|
After Width: | Height: | Size: 608 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 798 KiB |
|
After Width: | Height: | Size: 635 KiB |
|
After Width: | Height: | Size: 655 B |
|
After Width: | Height: | Size: 399 B |
|
After Width: | Height: | Size: 405 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 632 B |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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" />
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="divider_text">@android:color/holo_blue_bright</color>
|
||||
</resources>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
25
samples/wearable/Notifications/Wearable/build.gradle
Normal 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.+"
|
||||
}
|
||||
22
samples/wearable/Notifications/Wearable/proguard-rules.txt
Normal 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
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 655 B |
|
After Width: | Height: | Size: 399 B |
|
After Width: | Height: | Size: 405 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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"/>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<integer name="action_text_faded_alpha">40</integer>
|
||||
</resources>
|
||||
@@ -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>
|
||||
14
samples/wearable/Notifications/build.gradle
Normal file
@@ -0,0 +1,14 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:0.11.+'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
18
samples/wearable/Notifications/gradle.properties
Normal 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
|
||||
BIN
samples/wearable/Notifications/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
samples/wearable/Notifications/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
@@ -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
@@ -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
|
||||
1
samples/wearable/Notifications/settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
include 'Wearable', 'Application'
|
||||
30
samples/wearable/build.gradle
Normal 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]
|
||||
})
|
||||
}
|
||||
}
|
||||
BIN
samples/wearable/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
samples/wearable/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
@@ -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
@@ -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
|
||||