Add first wearable sample to sdk samples distribution
Wearable samples sometimes have special gradle setups that nest one application within another. As such, inclusion in the existing samples generator may be tricky. Instead, just prepare the sample for direct inclusion into the sdk distribution. Create a convenience gradle build to build all wearable samples at once. Bug: 15591212 Change-Id: I6e03f7c5cc87909430b927aca4b403ded77917ab
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
|
||||