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.findphone;
18 
19 import android.app.IntentService;
20 import android.content.Intent;
21 import android.os.Bundle;
22 import android.util.Log;
23 
24 import com.google.android.gms.common.ConnectionResult;
25 import com.google.android.gms.common.api.GoogleApiClient;
26 import com.google.android.gms.wearable.DataItemBuffer;
27 import com.google.android.gms.wearable.DataMap;
28 import com.google.android.gms.wearable.PutDataMapRequest;
29 import com.google.android.gms.wearable.Wearable;
30 
31 import java.util.concurrent.TimeUnit;
32 
33 /**
34  * Creates a sound on the paired phone to find it.
35  */
36 public class FindPhoneService extends IntentService implements GoogleApiClient.ConnectionCallbacks,
37         GoogleApiClient.OnConnectionFailedListener {
38 
39     private static final String TAG = "ExampleFindPhoneApp";
40 
41     private static final String FIELD_ALARM_ON = "alarm_on";
42     private static final String PATH_SOUND_ALARM = "/sound_alarm";
43     public static final String ACTION_TOGGLE_ALARM = "action_toggle_alarm";
44     public static final String ACTION_CANCEL_ALARM = "action_alarm_off";
45 
46     // Timeout for making a connection to GoogleApiClient (in milliseconds).
47     private static final long CONNECTION_TIME_OUT_MS = 100;
48     private GoogleApiClient mGoogleApiClient;
49 
FindPhoneService()50     public FindPhoneService() {
51         super(FindPhoneService.class.getSimpleName());
52     }
53 
54     @Override
onCreate()55     public void onCreate() {
56         super.onCreate();
57         mGoogleApiClient = new GoogleApiClient.Builder(this)
58                 .addApi(Wearable.API)
59                 .addConnectionCallbacks(this)
60                 .addOnConnectionFailedListener(this)
61                 .build();
62     }
63 
64     @Override
onHandleIntent(Intent intent)65     protected void onHandleIntent(Intent intent) {
66         mGoogleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
67         if (Log.isLoggable(TAG, Log.VERBOSE)) {
68             Log.v(TAG, "FindPhoneService.onHandleIntent");
69         }
70         if (mGoogleApiClient.isConnected()) {
71             // Set the alarm off by default.
72             boolean alarmOn = false;
73             if (intent.getAction().equals(ACTION_TOGGLE_ALARM)) {
74                 // Get current state of the alarm.
75                 DataItemBuffer result = Wearable.DataApi.getDataItems(mGoogleApiClient).await();
76                 try {
77                     if (result.getStatus().isSuccess()) {
78                         if (result.getCount() == 1) {
79                             alarmOn = DataMap.fromByteArray(result.get(0).getData())
80                                     .getBoolean(FIELD_ALARM_ON, false);
81                         } else {
82                             Log.e(TAG, "Unexpected number of DataItems found.\n"
83                                     + "\tExpected: 1\n"
84                                     + "\tActual: " + result.getCount());
85                         }
86                     } else if (Log.isLoggable(TAG, Log.DEBUG)) {
87                         Log.d(TAG, "onHandleIntent: failed to get current alarm state");
88                     }
89                 } finally {
90                     result.release();
91                 }
92                 // Toggle alarm.
93                 alarmOn = !alarmOn;
94                 // Change notification text based on new value of alarmOn.
95                 String notificationText = alarmOn ? getString(R.string.turn_alarm_off)
96                         : getString(R.string.turn_alarm_on);
97                 FindPhoneActivity.updateNotification(this, notificationText);
98             }
99             // Use alarmOn boolean to update the DataItem - phone will respond accordingly
100             // when it receives the change.
101             PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(PATH_SOUND_ALARM);
102             putDataMapRequest.getDataMap().putBoolean(FIELD_ALARM_ON, alarmOn);
103             putDataMapRequest.setUrgent();
104             Wearable.DataApi.putDataItem(mGoogleApiClient, putDataMapRequest.asPutDataRequest())
105                     .await();
106         } else {
107             Log.e(TAG, "Failed to toggle alarm on phone - Client disconnected from Google Play "
108                     + "Services");
109         }
110         mGoogleApiClient.disconnect();
111     }
112 
113     @Override
onConnected(Bundle connectionHint)114     public void onConnected(Bundle connectionHint) {
115     }
116 
117     @Override
onConnectionSuspended(int cause)118     public void onConnectionSuspended(int cause) {
119     }
120 
121     @Override
onConnectionFailed(ConnectionResult result)122     public void onConnectionFailed(ConnectionResult result) {
123     }
124 
125 }
126