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