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 21 import android.app.Activity; 22 import android.content.Intent; 23 import android.content.IntentSender; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.util.Log; 27 import android.view.View; 28 import android.widget.ScrollView; 29 import android.widget.TextView; 30 31 import com.google.android.gms.common.ConnectionResult; 32 import com.google.android.gms.common.api.GoogleApiClient; 33 import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; 34 import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; 35 import com.google.android.gms.common.api.ResultCallback; 36 import com.google.android.gms.common.data.FreezableUtils; 37 import com.google.android.gms.wearable.DataApi; 38 import com.google.android.gms.wearable.DataItem; 39 import com.google.android.gms.wearable.DataItemBuffer; 40 import com.google.android.gms.wearable.Node; 41 import com.google.android.gms.wearable.NodeApi; 42 import com.google.android.gms.wearable.Wearable; 43 44 import java.util.List; 45 46 public class MainActivity extends Activity implements NodeApi.NodeListener, ConnectionCallbacks, 47 OnConnectionFailedListener { 48 49 /** Request code for launching the Intent to resolve Google Play services errors. */ 50 private static final int REQUEST_RESOLVE_ERROR = 1000; 51 52 private GoogleApiClient mGoogleApiClient; 53 private boolean mResolvingError = false; 54 55 private TextView mLogTextView; 56 ScrollView mScroller; 57 58 @Override 59 protected void onCreate(Bundle savedInstanceState) { 60 super.onCreate(savedInstanceState); 61 62 setContentView(R.layout.main); 63 mLogTextView = (TextView) findViewById(R.id.log); 64 mScroller = (ScrollView) findViewById(R.id.scroller); 65 mGoogleApiClient = new GoogleApiClient.Builder(this) 66 .addApi(Wearable.API) 67 .addConnectionCallbacks(this) 68 .addOnConnectionFailedListener(this) 69 .build(); 70 } 71 72 @Override 73 protected void onStart() { 74 super.onStart(); 75 if (!mResolvingError) { 76 mGoogleApiClient.connect(); 77 } 78 } 79 80 @Override 81 protected void onStop() { 82 if (mGoogleApiClient.isConnected()) { 83 Wearable.NodeApi.removeListener(mGoogleApiClient, this); 84 } 85 mGoogleApiClient.disconnect(); 86 super.onStop(); 87 } 88 89 public void onGetEventsClicked(View v) { 90 startService(new Intent(this, CalendarQueryService.class)); 91 } 92 93 public void onDeleteEventsClicked(View v) { 94 if (mGoogleApiClient.isConnected()) { 95 Wearable.DataApi.getDataItems(mGoogleApiClient) 96 .setResultCallback(new ResultCallback<DataItemBuffer>() { 97 @Override 98 public void onResult(DataItemBuffer result) { 99 if (result.getStatus().isSuccess()) { 100 deleteDataItems(result); 101 } else { 102 if (Log.isLoggable(TAG, Log.DEBUG)) { 103 Log.d(TAG, "onDeleteEventsClicked(): failed to get Data Items"); 104 } 105 } 106 result.close(); 107 } 108 }); 109 } else { 110 Log.e(TAG, "Failed to delete data items" 111 + " - Client disconnected from Google Play Services"); 112 } 113 } 114 115 private void deleteDataItems(DataItemBuffer dataItems) { 116 if (mGoogleApiClient.isConnected()) { 117 // Store the DataItem URIs in a List and close the buffer. Then use these URIs 118 // to delete the DataItems. 119 final List<DataItem> dataItemList = FreezableUtils.freezeIterable(dataItems); 120 dataItems.close(); 121 for (final DataItem dataItem : dataItemList) { 122 final Uri dataItemUri = dataItem.getUri(); 123 // In a real calendar application, this might delete the corresponding calendar 124 // event from the calendar data provider. In this sample, we simply delete the 125 // DataItem, but leave the phone's calendar data intact. 126 Wearable.DataApi.deleteDataItems(mGoogleApiClient, dataItemUri) 127 .setResultCallback(new ResultCallback<DataApi.DeleteDataItemsResult>() { 128 @Override 129 public void onResult(DataApi.DeleteDataItemsResult deleteResult) { 130 if (deleteResult.getStatus().isSuccess()) { 131 appendLog("Successfully deleted data item: " + dataItemUri); 132 } else { 133 appendLog("Failed to delete data item:" + dataItemUri); 134 } 135 } 136 }); 137 } 138 } else { 139 Log.e(TAG, "Failed to delete data items" 140 + " - Client disconnected from Google Play Services"); 141 } 142 } 143 144 private void appendLog(final String s) { 145 mLogTextView.post(new Runnable() { 146 @Override 147 public void run() { 148 mLogTextView.append(s); 149 mLogTextView.append("\n"); 150 mScroller.fullScroll(View.FOCUS_DOWN); 151 } 152 }); 153 } 154 155 @Override 156 public void onPeerConnected(Node peer) { 157 appendLog("Device connected"); 158 } 159 160 @Override 161 public void onPeerDisconnected(Node peer) { 162 appendLog("Device disconnected"); 163 } 164 165 @Override 166 public void onConnected(Bundle connectionHint) { 167 if (Log.isLoggable(TAG, Log.DEBUG)) { 168 Log.d(TAG, "Connected to Google Api Service"); 169 } 170 mResolvingError = false; 171 Wearable.NodeApi.addListener(mGoogleApiClient, this); 172 } 173 174 @Override 175 public void onConnectionSuspended(int cause) { 176 // Ignore 177 } 178 179 @Override 180 public void onConnectionFailed(ConnectionResult result) { 181 if (Log.isLoggable(TAG, Log.DEBUG)) { 182 Log.d(TAG, "Disconnected from Google Api Service"); 183 } 184 if (null != Wearable.NodeApi) { 185 Wearable.NodeApi.removeListener(mGoogleApiClient, this); 186 } 187 if (mResolvingError) { 188 // Already attempting to resolve an error. 189 return; 190 } else if (result.hasResolution()) { 191 try { 192 mResolvingError = true; 193 result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR); 194 } catch (IntentSender.SendIntentException e) { 195 // There was an error with the resolution intent. Try again. 196 mGoogleApiClient.connect(); 197 } 198 } else { 199 mResolvingError = false; 200 } 201 } 202 } 203