From 9fd71d61f262bfe238b58c60fab6e6494b028356 Mon Sep 17 00:00:00 2001 From: Dan Aminzade Date: Sun, 22 Jun 2014 16:46:26 -0700 Subject: [PATCH] Add new SynchronizedNotifications sample. This sample demonstrates how to use DataItems to construct linked phone- and wearable-side notifications. Change-Id: I6defa7fad671ba2ec0de25c8913abd66d07846a2 --- build/sdk.atree | 31 +-- .../Application/build.gradle | 28 +++ .../Application/proguard-rules.txt | 17 ++ .../Application/src/main/AndroidManifest.xml | 32 +++ .../DismissListener.java | 125 ++++++++++++ .../PhoneActivity.java | 191 ++++++++++++++++++ .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 297 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 254 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 342 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 471 bytes .../src/main/res/layout/activity_phone.xml | 41 ++++ .../src/main/res/values/dimens.xml | 5 + .../src/main/res/values/strings.xml | 11 + .../Common/build.gradle | 20 ++ .../Common/proguard-rules.txt | 17 ++ .../Common/src/main/AndroidManifest.xml | 8 + .../common/Constants.java | 38 ++++ .../Common/src/main/res/values/strings.xml | 3 + .../Wearable/build.gradle | 28 +++ .../Wearable/proguard-rules.txt | 17 ++ .../Wearable/src/main/AndroidManifest.xml | 34 ++++ .../NotificationUpdateService.java | 164 +++++++++++++++ .../WearableActivity.java | 29 +++ .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 297 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 254 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 342 bytes .../src/main/res/layout/activity_wearable.xml | 7 + .../Wearable/src/main/res/values/strings.xml | 6 + .../SynchronizedNotifications/build.gradle | 14 ++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + .../SynchronizedNotifications/gradlew | 164 +++++++++++++++ .../SynchronizedNotifications/gradlew.bat | 90 +++++++++ .../SynchronizedNotifications/settings.gradle | 1 + samples/wearable/build.gradle | 1 + 35 files changed, 1113 insertions(+), 15 deletions(-) create mode 100644 samples/wearable/SynchronizedNotifications/Application/build.gradle create mode 100644 samples/wearable/SynchronizedNotifications/Application/proguard-rules.txt create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/AndroidManifest.xml create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/java/com/example/android/wearable/synchronizednotifications/DismissListener.java create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/java/com/example/android/wearable/synchronizednotifications/PhoneActivity.java create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/res/layout/activity_phone.xml create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/res/values/dimens.xml create mode 100644 samples/wearable/SynchronizedNotifications/Application/src/main/res/values/strings.xml create mode 100644 samples/wearable/SynchronizedNotifications/Common/build.gradle create mode 100644 samples/wearable/SynchronizedNotifications/Common/proguard-rules.txt create mode 100644 samples/wearable/SynchronizedNotifications/Common/src/main/AndroidManifest.xml create mode 100644 samples/wearable/SynchronizedNotifications/Common/src/main/java/com/example/android/wearable/synchronizednotifications/common/Constants.java create mode 100644 samples/wearable/SynchronizedNotifications/Common/src/main/res/values/strings.xml create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/build.gradle create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/proguard-rules.txt create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/src/main/AndroidManifest.xml create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/src/main/java/com/example/android/wearable/synchronizednotifications/NotificationUpdateService.java create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/src/main/java/com/example/android/wearable/synchronizednotifications/WearableActivity.java create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/src/main/res/layout/activity_wearable.xml create mode 100644 samples/wearable/SynchronizedNotifications/Wearable/src/main/res/values/strings.xml create mode 100644 samples/wearable/SynchronizedNotifications/build.gradle create mode 100644 samples/wearable/SynchronizedNotifications/gradle/wrapper/gradle-wrapper.jar create mode 100644 samples/wearable/SynchronizedNotifications/gradle/wrapper/gradle-wrapper.properties create mode 100755 samples/wearable/SynchronizedNotifications/gradlew create mode 100644 samples/wearable/SynchronizedNotifications/gradlew.bat create mode 100644 samples/wearable/SynchronizedNotifications/settings.gradle diff --git a/build/sdk.atree b/build/sdk.atree index a8b68888f..14d5fc835 100644 --- a/build/sdk.atree +++ b/build/sdk.atree @@ -270,21 +270,22 @@ developers/build/prebuilts/gradle/SwipeRefreshMultipleViews sam developers/build/prebuilts/gradle/MediaRouter samples/${PLATFORM_NAME}/media/MediaRouter # Wearable sample tree -development/samples/wearable/AgendaData samples/${PLATFORM_NAME}/wearable/AgendaData -development/samples/wearable/DataLayer samples/${PLATFORM_NAME}/wearable/DataLayer -development/samples/wearable/DelayedConfirmation samples/${PLATFORM_NAME}/wearable/DelayedConfirmation -development/samples/wearable/ElizaChat samples/${PLATFORM_NAME}/wearable/ElizaChat -development/samples/wearable/FindMyPhone samples/${PLATFORM_NAME}/wearable/FindMyPhone -development/samples/wearable/Flashlight samples/${PLATFORM_NAME}/wearable/Flashlight -development/samples/wearable/Geofencing samples/${PLATFORM_NAME}/wearable/Geofencing -development/samples/wearable/GridViewPager samples/${PLATFORM_NAME}/wearable/GridViewPager -development/samples/wearable/JumpingJack samples/${PLATFORM_NAME}/wearable/JumpingJack -development/samples/wearable/Notifications samples/${PLATFORM_NAME}/wearable/Notifications -development/samples/wearable/Quiz samples/${PLATFORM_NAME}/wearable/Quiz -development/samples/wearable/RecipeAssistant samples/${PLATFORM_NAME}/wearable/RecipeAssistant -development/samples/wearable/SkeletonWearableApp samples/${PLATFORM_NAME}/wearable/SkeletonWearableApp -development/samples/wearable/Timer samples/${PLATFORM_NAME}/wearable/Timer -development/samples/wearable/WatchViewStub samples/${PLATFORM_NAME}/wearable/WatchViewStub +development/samples/wearable/AgendaData samples/${PLATFORM_NAME}/wearable/AgendaData +development/samples/wearable/DataLayer samples/${PLATFORM_NAME}/wearable/DataLayer +development/samples/wearable/DelayedConfirmation samples/${PLATFORM_NAME}/wearable/DelayedConfirmation +development/samples/wearable/ElizaChat samples/${PLATFORM_NAME}/wearable/ElizaChat +development/samples/wearable/FindMyPhone samples/${PLATFORM_NAME}/wearable/FindMyPhone +development/samples/wearable/Flashlight samples/${PLATFORM_NAME}/wearable/Flashlight +development/samples/wearable/Geofencing samples/${PLATFORM_NAME}/wearable/Geofencing +development/samples/wearable/GridViewPager samples/${PLATFORM_NAME}/wearable/GridViewPager +development/samples/wearable/JumpingJack samples/${PLATFORM_NAME}/wearable/JumpingJack +development/samples/wearable/Notifications samples/${PLATFORM_NAME}/wearable/Notifications +development/samples/wearable/Quiz samples/${PLATFORM_NAME}/wearable/Quiz +development/samples/wearable/RecipeAssistant samples/${PLATFORM_NAME}/wearable/RecipeAssistant +development/samples/wearable/SkeletonWearableApp samples/${PLATFORM_NAME}/wearable/SkeletonWearableApp +development/samples/wearable/SynchronizedNotifications samples/${PLATFORM_NAME}/wearable/SynchronizedNotifications +development/samples/wearable/Timer samples/${PLATFORM_NAME}/wearable/Timer +development/samples/wearable/WatchViewStub samples/${PLATFORM_NAME}/wearable/WatchViewStub # Old sample tree development/samples/AccelerometerPlay samples/${PLATFORM_NAME}/legacy/AccelerometerPlay diff --git a/samples/wearable/SynchronizedNotifications/Application/build.gradle b/samples/wearable/SynchronizedNotifications/Application/build.gradle new file mode 100644 index 000000000..a850a8d61 --- /dev/null +++ b/samples/wearable/SynchronizedNotifications/Application/build.gradle @@ -0,0 +1,28 @@ +apply plugin: 'android' + +android { + compileSdkVersion 19 + buildToolsVersion '20' + defaultConfig { + minSdkVersion 18 + targetSdkVersion 19 + versionCode 1 + versionName '1.0' + } + buildTypes { + release { + runProguard false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } + lintOptions { + abortOnError false + } +} + +dependencies { + compile 'com.google.android.gms:play-services:5.0.+@aar' + compile 'com.android.support:support-v13:20.0.+' + compile project(':Common') + wearApp project(':Wearable') +} diff --git a/samples/wearable/SynchronizedNotifications/Application/proguard-rules.txt b/samples/wearable/SynchronizedNotifications/Application/proguard-rules.txt new file mode 100644 index 000000000..5b86c0858 --- /dev/null +++ b/samples/wearable/SynchronizedNotifications/Application/proguard-rules.txt @@ -0,0 +1,17 @@ +# 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 proguardFiles +# directive in build.gradle. +# +# 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 *; +#} diff --git a/samples/wearable/SynchronizedNotifications/Application/src/main/AndroidManifest.xml b/samples/wearable/SynchronizedNotifications/Application/src/main/AndroidManifest.xml new file mode 100644 index 000000000..60960a8a8 --- /dev/null +++ b/samples/wearable/SynchronizedNotifications/Application/src/main/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/wearable/SynchronizedNotifications/Application/src/main/java/com/example/android/wearable/synchronizednotifications/DismissListener.java b/samples/wearable/SynchronizedNotifications/Application/src/main/java/com/example/android/wearable/synchronizednotifications/DismissListener.java new file mode 100644 index 000000000..98747f55b --- /dev/null +++ b/samples/wearable/SynchronizedNotifications/Application/src/main/java/com/example/android/wearable/synchronizednotifications/DismissListener.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 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. + */ + +package com.example.android.wearable.synchronizednotifications; + +import static com.google.android.gms.wearable.PutDataRequest.WEAR_URI_SCHEME; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.NotificationManagerCompat; +import android.util.Log; + +import com.example.android.wearable.synchronizednotifications.common.Constants; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.ResultCallback; +import com.google.android.gms.wearable.DataApi; +import com.google.android.gms.wearable.DataEvent; +import com.google.android.gms.wearable.DataEventBuffer; +import com.google.android.gms.wearable.PutDataMapRequest; +import com.google.android.gms.wearable.Wearable; +import com.google.android.gms.wearable.WearableListenerService; + +/** + * A {@link com.google.android.gms.wearable.WearableListenerService} that is invoked when certain + * notifications are dismissed from either the phone or watch. + */ +public class DismissListener extends WearableListenerService + implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, + ResultCallback { + + private static final String TAG = "DismissListener"; + private GoogleApiClient mGoogleApiClient; + + @Override + public void onCreate() { + super.onCreate(); + mGoogleApiClient = new GoogleApiClient.Builder(this) + .addApi(Wearable.API) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .build(); + } + + @Override + public void onDataChanged(DataEventBuffer dataEvents) { + for (DataEvent dataEvent : dataEvents) { + if (dataEvent.getType() == DataEvent.TYPE_DELETED) { + if (Constants.BOTH_PATH.equals(dataEvent.getDataItem().getUri().getPath())) { + // notification on the phone should be dismissed + NotificationManagerCompat.from(this).cancel(Constants.BOTH_ID); + } + } + } + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (null != intent) { + String action = intent.getAction(); + if (Constants.ACTION_DISMISS.equals(action)) { + // We need to dismiss the wearable notification. We delete the DataItem that + // created the notification to inform the wearable. + int notificationId = intent.getIntExtra(Constants.KEY_NOTIFICATION_ID, -1); + if (notificationId == Constants.BOTH_ID) { + dismissWearableNotification(notificationId); + } + } + } + return super.onStartCommand(intent, flags, startId); + } + + /** + * Removes the DataItem that was used to create a notification on the watch. By deleting the + * data item, a {@link com.google.android.gms.wearable.WearableListenerService} on the watch + * will be notified and the notification on the watch will be removed. + * + * @param id The ID of the notification that should be removed + */ + private void dismissWearableNotification(final int id) { + mGoogleApiClient.connect(); + } + + @Override // ConnectionCallbacks + public void onConnected(Bundle bundle) { + final Uri dataItemUri = + new Uri.Builder().scheme(WEAR_URI_SCHEME).path(Constants.BOTH_PATH).build(); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Deleting Uri: " + dataItemUri.toString()); + } + Wearable.DataApi.deleteDataItems( + mGoogleApiClient, dataItemUri).setResultCallback(this); + } + + @Override // ConnectionCallbacks + public void onConnectionSuspended(int i) { + } + + @Override // OnConnectionFailedListener + public void onConnectionFailed(ConnectionResult connectionResult) { + Log.e(TAG, "Failed to connect to the Google API client"); + } + + @Override // ResultCallback + public void onResult(DataApi.DeleteDataItemsResult deleteDataItemsResult) { + if (!deleteDataItemsResult.getStatus().isSuccess()) { + Log.e(TAG, "dismissWearableNotification(): failed to delete DataItem"); + } + mGoogleApiClient.disconnect(); + } +} diff --git a/samples/wearable/SynchronizedNotifications/Application/src/main/java/com/example/android/wearable/synchronizednotifications/PhoneActivity.java b/samples/wearable/SynchronizedNotifications/Application/src/main/java/com/example/android/wearable/synchronizednotifications/PhoneActivity.java new file mode 100644 index 000000000..2cac13751 --- /dev/null +++ b/samples/wearable/SynchronizedNotifications/Application/src/main/java/com/example/android/wearable/synchronizednotifications/PhoneActivity.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 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. + */ + +package com.example.android.wearable.synchronizednotifications; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; +import android.util.Log; +import android.view.View; + +import com.example.android.wearable.synchronizednotifications.common.Constants; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.ResultCallback; +import com.google.android.gms.wearable.DataApi; +import com.google.android.gms.wearable.PutDataMapRequest; +import com.google.android.gms.wearable.PutDataRequest; +import com.google.android.gms.wearable.Wearable; + +import java.text.DateFormat; +import java.util.Date; + +/** + * A simple activity that presents three buttons that would trigger three different combinations of + * notifications on the handset and the watch: + *
    + *
  • The first button builds a simple local-only notification on the handset.
  • + *
  • The second one creates a wearable-only notification by putting a data item in the shared data + * store and having a {@link com.google.android.gms.wearable.WearableListenerService} listen for + * that on the wearable
  • + *
  • The third one creates a local notification and a wearable notification by combining the above + * two. It, however, demonstrates how one can set things up so that the dismissal of one + * notification results in the dismissal of the other one.
  • + *
+ */ +public class PhoneActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, + GoogleApiClient.OnConnectionFailedListener { + + private static final String TAG = "PhoneActivity"; + private GoogleApiClient mGoogleApiClient; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_phone); + mGoogleApiClient = new GoogleApiClient.Builder(this) + .addApi(Wearable.API) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .build(); + } + + /** + * Builds a local-only notification for the handset. This is achieved by using + * setLocalOnly(true). If withDismissal is set to true, a + * {@link android.app.PendingIntent} will be added to handle the dismissal of notification to + * be able to remove the mirrored notification on the wearable. + */ + private void buildLocalOnlyNotification(String title, String content, int notificationId, + boolean withDismissal) { + NotificationCompat.Builder builder = new NotificationCompat.Builder(this); + builder.setContentTitle(title) + .setContentText(content) + .setLocalOnly(true) + .setSmallIcon(R.drawable.ic_launcher); + + if (withDismissal) { + Intent dismissIntent = new Intent(Constants.ACTION_DISMISS); + dismissIntent.putExtra(Constants.KEY_NOTIFICATION_ID, Constants.BOTH_ID); + PendingIntent pendingIntent = PendingIntent + .getService(this, 0, dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT); + builder.setDeleteIntent(pendingIntent); + } + NotificationManagerCompat.from(this).notify(notificationId, builder.build()); + } + + /** + * Builds a DataItem that on the wearable will be interpreted as a request to show a + * notification. The result will be a notification that only shows up on the wearable. + */ + private void buildWearableOnlyNotification(String title, String content, String path) { + if (mGoogleApiClient.isConnected()) { + PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(path); + putDataMapRequest.getDataMap().putString(Constants.KEY_CONTENT, content); + putDataMapRequest.getDataMap().putString(Constants.KEY_TITLE, title); + PutDataRequest request = putDataMapRequest.asPutDataRequest(); + Wearable.DataApi.putDataItem(mGoogleApiClient, request) + .setResultCallback(new ResultCallback() { + @Override + public void onResult(DataApi.DataItemResult dataItemResult) { + if (!dataItemResult.getStatus().isSuccess()) { + Log.e(TAG, "buildWatchOnlyNotification(): Failed to set the data, " + + "status: " + dataItemResult.getStatus().getStatusCode()); + } + } + }); + } else { + Log.e(TAG, "buildWearableOnlyNotification(): no Google API Client connection"); + } + } + + /** + * Builds a local notification and sets a DataItem that will be interpreted by the wearable as + * a request to build a notification on the wearable as as well. The two notifications show + * different messages. + * Dismissing either of the notifications will result in dismissal of the other; this is + * achieved by creating a {@link android.app.PendingIntent} that results in removal of + * the DataItem that created the watch notification. The deletion of the DataItem is observed on + * both sides, using WearableListenerService callbacks, and is interpreted on each side as a + * request to dismiss the corresponding notification. + */ + private void buildMirroredNotifications(String phoneTitle, String watchTitle, String content) { + if (mGoogleApiClient.isConnected()) { + // Wearable notification + buildWearableOnlyNotification(watchTitle, content, Constants.BOTH_PATH); + + // Local notification, with a pending intent for dismissal + buildLocalOnlyNotification(phoneTitle, content, Constants.BOTH_ID, true); + } + } + + @Override + protected void onStart() { + super.onStart(); + mGoogleApiClient.connect(); + } + + @Override + protected void onStop() { + mGoogleApiClient.disconnect(); + super.onStop(); + } + + @Override + public void onConnected(Bundle bundle) { + } + + @Override + public void onConnectionSuspended(int i) { + } + + @Override + public void onConnectionFailed(ConnectionResult connectionResult) { + Log.e(TAG, "Failed to connect to Google API Client"); + } + + /** + * Returns a string built from the current time + */ + private String now() { + DateFormat dateFormat = android.text.format.DateFormat.getTimeFormat(this); + return dateFormat.format(new Date()); + } + + /** + * Handles button clicks in the UI. + */ + public void onClick(View view) { + int id = view.getId(); + switch (id) { + case R.id.phone_only: + buildLocalOnlyNotification(getString(R.string.phone_only), now(), + Constants.PHONE_ONLY_ID, false); + break; + case R.id.wear_only: + buildWearableOnlyNotification(getString(R.string.wear_only), now(), + Constants.WATCH_ONLY_PATH); + break; + case R.id.different_notifications: + buildMirroredNotifications(getString(R.string.phone_both), getString(R.string.watch_both), now()); + break; + } + } +} diff --git a/samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-hdpi/ic_launcher.png b/samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..f7dd9a0bdaeb7e010c69b396cd228e41b4b8b4a7 GIT binary patch literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!A3R+gLn>~)y`{)^$Uvn1qb&RO z?`j;Alp78$^boj{{MPRv?}iKyj^hrC)dhr?vO5Sk?cV$Lx9WfHn#OHOu8cqvz#xay zPrp$A_hhq*$p7{eu2;tx*e;Ll+3fk5dy||-s?6ucpyP(J8tyWi8;gz_N@}Fb6gL(f zHxyqnt@dC0qvZ~M{vRKf`fU03-Qj7HMB}WYY44uu@iPf#d}@3maDHLvq{_-${3bV| zdmPf3Vjtgsc<1$=J8G34_4PBtofMdQO((41w(w%=`p>%_i#?vDF3`x~qQE5B;ZV!A l>B~o_wZ(SkFn1=T+}rZSZO(qKH;N!d?vwPBVKJdVGZ+|L zg|5tPF2BAeFtSWwf_sfhO82f@3)97kTqU}8s~cQD-eg(RbzWtIx%R(c2fmHgtGAqZ zy8YehGZnr2I9HsReE;Jn=K~3B?+mvuSy4Sr;lg3IU#kzK2yT&^{d}v8*ZfBP|7(5y znF?jsyis!EN^q>mK5mX`;zGV3dHqv^>bP0l+XkK%O+r_ literal 0 HcmV?d00001 diff --git a/samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-xhdpi/ic_launcher.png b/samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..f2fb03cdd67e6451094514c67e07173870261435 GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>V3hTAaSW-r_4c-*7qg>C!^5{l zGU-Z7zKebP$nmZ0ox}%*Z_BQRZP>hV(^rmfO;gWWiBAyVn0a&0`)2oBCx0gz>!e5k z&4L1se5uQ6TAA6e?&#|G%P)9x-fFVv`O9as6djg4<-SnylgT8m?gc|~UDm!o8yKr1 z>&`I9+LS$Fdy(^VBU8zaKNgHuv2_y|^6%=^yEojgivD5uYs#162h!)A@9RJQ$2&o8 z_MGQt>sbUG7#LXu6v`S5>#v@l&h}aFK<3^GVW8l%AJP-zUO&`NGggh?$-4EA-0aWB zK$SolzB2A#E86$ZJ3FQ3z0@lytp)}r4h0nA4M)MN`e51VuNh&UVPN?7fjwV}v*AKr Q%`%Xnr>mdKI;Vst0F2OtDgXcg literal 0 HcmV?d00001 diff --git a/samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-xxhdpi/ic_launcher.png b/samples/wearable/SynchronizedNotifications/Application/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..944042ca80c2b3741dfb9d0b93672c9f025dd2cd GIT binary patch literal 471 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$farfpMOvi(^Q|t+%&y{g@pY+8$n& zusG%8%i2`XXC=bfaq3<|nJ^36K}C-pOdKZcD_Gc9sIi#(M_liXuLpv;r!oQ!|hR~(8q|HzS{Uj6Q^ z{@QpBjhs_+x1I^M$j;KV;at(y5L9zg+`ank-fbT=6c{-@9GHYAG_a^ZnE~~Td#A@f zH;ggen)`#PNa(Ff6i5M7nG}yk&L<0N-F|hk>rAhn$Yi*`zut_{3^yl~UBvEG-s#WM z-0PWseREu7*(nB>Q$tvq!c=sT6>75)<4m|guM`)!&UmdKI;Vst0HKkUUjP6A literal 0 HcmV?d00001 diff --git a/samples/wearable/SynchronizedNotifications/Application/src/main/res/layout/activity_phone.xml b/samples/wearable/SynchronizedNotifications/Application/src/main/res/layout/activity_phone.xml new file mode 100644 index 000000000..140c4e8c3 --- /dev/null +++ b/samples/wearable/SynchronizedNotifications/Application/src/main/res/layout/activity_phone.xml @@ -0,0 +1,41 @@ + + +