Home | History | Annotate | Download | only in com.example.android.wearable.agendadata
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.wearable.agendadata;
     18 
     19 import static com.example.android.wearable.agendadata.Constants.TAG;
     20 import static com.example.android.wearable.agendadata.Constants.EXTRA_SILENT;
     21 
     22 import static com.example.android.wearable.agendadata.Constants.ALL_DAY;
     23 import static com.example.android.wearable.agendadata.Constants.BEGIN;
     24 import static com.example.android.wearable.agendadata.Constants.DESCRIPTION;
     25 import static com.example.android.wearable.agendadata.Constants.END;
     26 import static com.example.android.wearable.agendadata.Constants.PROFILE_PIC;
     27 import static com.example.android.wearable.agendadata.Constants.TITLE;
     28 
     29 import android.app.Notification;
     30 import android.app.NotificationManager;
     31 import android.app.PendingIntent;
     32 import android.content.Intent;
     33 import android.graphics.Bitmap;
     34 import android.graphics.BitmapFactory;
     35 import android.net.Uri;
     36 import android.text.TextUtils;
     37 import android.text.format.DateFormat;
     38 import android.util.Log;
     39 
     40 import com.google.android.gms.common.api.GoogleApiClient;
     41 import com.google.android.gms.wearable.Asset;
     42 import com.google.android.gms.wearable.DataApi;
     43 import com.google.android.gms.wearable.DataEvent;
     44 import com.google.android.gms.wearable.DataEventBuffer;
     45 import com.google.android.gms.wearable.DataItem;
     46 import com.google.android.gms.wearable.DataMap;
     47 import com.google.android.gms.wearable.DataMapItem;
     48 import com.google.android.gms.wearable.MessageEvent;
     49 import com.google.android.gms.wearable.Wearable;
     50 import com.google.android.gms.wearable.WearableListenerService;
     51 
     52 import java.util.Date;
     53 import java.util.HashMap;
     54 import java.util.Map;
     55 
     56 /**
     57  * Listens to DataItem events on the home device.
     58  */
     59 public class HomeListenerService extends WearableListenerService {
     60 
     61     private static final Map<Uri, Integer> sNotificationIdByDataItemUri =
     62             new HashMap<Uri, Integer>();
     63     private static int sNotificationId = 1;
     64     private GoogleApiClient mGoogleApiClient;
     65 
     66     @Override
     67     public void onDataChanged(DataEventBuffer dataEvents) {
     68         if (Log.isLoggable(TAG, Log.DEBUG)) {
     69             Log.d(TAG, "onDataChanged: " + dataEvents + " for " + getPackageName());
     70         }
     71         for (DataEvent event : dataEvents) {
     72             if (event.getType() == DataEvent.TYPE_DELETED) {
     73                 deleteDataItem(event.getDataItem());
     74             } else if (event.getType() == DataEvent.TYPE_CHANGED) {
     75                 UpdateNotificationForDataItem(event.getDataItem());
     76             }
     77         }
     78         dataEvents.close();
     79     }
     80 
     81     @Override
     82     public void onCreate() {
     83         super.onCreate();
     84         mGoogleApiClient = new GoogleApiClient.Builder(this.getApplicationContext())
     85                 .addApi(Wearable.API)
     86                 .build();
     87         mGoogleApiClient.connect();
     88     }
     89 
     90     /**
     91      * Posts a local notification to show calendar card.
     92      */
     93     private void UpdateNotificationForDataItem(DataItem dataItem) {
     94         DataMapItem mapDataItem = DataMapItem.fromDataItem(dataItem);
     95         DataMap data = mapDataItem.getDataMap();
     96 
     97         String description = data.getString(DESCRIPTION);
     98         if (TextUtils.isEmpty(description)) {
     99             description = "";
    100         } else {
    101             // Add a space between the description and the time of the event.
    102             description += " ";
    103         }
    104         String contentText;
    105         if (data.getBoolean(ALL_DAY)) {
    106             contentText = getString(R.string.desc_all_day, description);
    107         } else {
    108             String startTime = DateFormat.getTimeFormat(this).format(new Date(data.getLong(BEGIN)));
    109             String endTime = DateFormat.getTimeFormat(this).format(new Date(data.getLong(END)));
    110             contentText = getString(R.string.desc_time_period, description, startTime, endTime);
    111         }
    112 
    113         Intent deleteOperation = new Intent(this, DeleteService.class);
    114         // Use a unique identifier for the delete action.
    115         String deleteAction = "action_delete" + dataItem.getUri().toString() + sNotificationId;
    116         deleteOperation.setAction(deleteAction);
    117         deleteOperation.setData(dataItem.getUri());
    118         PendingIntent deleteIntent = PendingIntent.getService(this, 0, deleteOperation,
    119                 PendingIntent.FLAG_ONE_SHOT);
    120         PendingIntent silentDeleteIntent = PendingIntent.getService(this, 1,
    121                 deleteOperation.putExtra(EXTRA_SILENT, true), PendingIntent.FLAG_ONE_SHOT);
    122 
    123         Notification.Builder notificationBuilder = new Notification.Builder(this)
    124                 .setContentTitle(data.getString(TITLE))
    125                 .setContentText(contentText)
    126                 .setSmallIcon(R.drawable.ic_launcher)
    127                 .addAction(R.drawable.ic_menu_delete, getText(R.string.delete), deleteIntent)
    128                 .setDeleteIntent(silentDeleteIntent)  // Delete DataItem if notification dismissed.
    129                 .setLocalOnly(true)
    130                 .setPriority(Notification.PRIORITY_MIN);
    131 
    132         // Set the event owner's profile picture as the notification background.
    133         Asset asset = data.getAsset(PROFILE_PIC);
    134         if (null != asset) {
    135             if (mGoogleApiClient.isConnected()) {
    136                 DataApi.GetFdForAssetResult assetFdResult =
    137                         Wearable.DataApi.getFdForAsset(mGoogleApiClient, asset).await();
    138                 if (assetFdResult.getStatus().isSuccess()) {
    139                     Bitmap profilePic = BitmapFactory.decodeStream(assetFdResult.getInputStream());
    140                     notificationBuilder.extend(new Notification.WearableExtender()
    141                             .setBackground(profilePic));
    142                 } else if (Log.isLoggable(TAG, Log.DEBUG)) {
    143                     Log.d(TAG, "asset fetch failed with statusCode: "
    144                             + assetFdResult.getStatus().getStatusCode());
    145                 }
    146             } else {
    147                 Log.e(TAG, "Failed to set notification background"
    148                          + " - Client disconnected from Google Play Services");
    149             }
    150         }
    151         Notification card = notificationBuilder.build();
    152 
    153         ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
    154                 .notify(sNotificationId, card);
    155 
    156         sNotificationIdByDataItemUri.put(dataItem.getUri(), sNotificationId++);
    157     }
    158 
    159     /**
    160      * Deletes the calendar card associated with the data item.
    161      */
    162     private void deleteDataItem(DataItem dataItem) {
    163         if (Log.isLoggable(TAG, Log.VERBOSE)) {
    164             Log.v(TAG, "onDataItemDeleted:DataItem=" + dataItem.getUri());
    165         }
    166         Integer notificationId = sNotificationIdByDataItemUri.remove(dataItem.getUri());
    167         if (notificationId != null) {
    168             ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(notificationId);
    169         }
    170     }
    171 
    172     @Override
    173     public void onMessageReceived(MessageEvent messageEvent) {
    174         if (Log.isLoggable(TAG, Log.DEBUG)) {
    175             Log.d(TAG, "onMessageReceived: " + messageEvent.getPath()
    176                      + " " + messageEvent.getData() + " for " + getPackageName());
    177         }
    178     }
    179 
    180 }
    181