Skip to content

Most visited

Recently visited

navigation
AgendaData / Application / src / com.example.android.wearable.agendadata /

MainActivity.java

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.Manifest;
22
import android.content.Intent;
23
import android.content.IntentSender;
24
import android.content.pm.PackageManager;
25
import android.net.Uri;
26
import android.os.Bundle;
27
import android.support.annotation.NonNull;
28
import android.support.design.widget.Snackbar;
29
import android.support.v4.app.ActivityCompat;
30
import android.support.v7.app.AppCompatActivity;
31
import android.util.Log;
32
import android.view.View;
33
import android.widget.ScrollView;
34
import android.widget.TextView;
35
 
36
import com.google.android.gms.common.ConnectionResult;
37
import com.google.android.gms.common.api.GoogleApiClient;
38
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
39
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
40
import com.google.android.gms.common.api.ResultCallback;
41
import com.google.android.gms.wearable.DataApi;
42
import com.google.android.gms.wearable.DataItem;
43
import com.google.android.gms.wearable.DataItemBuffer;
44
import com.google.android.gms.wearable.Wearable;
45
 
46
/**
47
 * Syncs or deletes calendar events (event time, description, and background image) to your
48
 * Wearable via the Wearable DataApi at the click of a button. Includes code to handle dynamic M+
49
 * permissions as well.
50
 */
51
public class MainActivity extends AppCompatActivity implements
52
        ConnectionCallbacks,
53
        OnConnectionFailedListener,
54
        ActivityCompat.OnRequestPermissionsResultCallback {
55
 
56
    /* Request code for launching the Intent to resolve Google Play services errors. */
57
    private static final int REQUEST_RESOLVE_ERROR = 1000;
58
 
59
    /* Id to identify calendar and contact permissions request. */
60
    private static final int REQUEST_CALENDAR_AND_CONTACTS = 0;
61
 
62
 
63
    private GoogleApiClient mGoogleApiClient;
64
    private boolean mResolvingError = false;
65
 
66
    private View mLayout;
67
 
68
    private TextView mLogTextView;
69
    private ScrollView mScroller;
70
 
71
    @Override
72
    protected void onCreate(Bundle savedInstanceState) {
73
        super.onCreate(savedInstanceState);
74
 
75
        setContentView(R.layout.main);
76
        mLayout = findViewById(R.id.main_layout);
77
 
78
        mLogTextView = (TextView) findViewById(R.id.log);
79
        mScroller = (ScrollView) findViewById(R.id.scroller);
80
 
81
        mGoogleApiClient = new GoogleApiClient.Builder(this)
82
                .addApi(Wearable.API)
83
                .addConnectionCallbacks(this)
84
                .addOnConnectionFailedListener(this)
85
                .build();
86
    }
87
 
88
    @Override
89
    protected void onStart() {
90
        super.onStart();
91
        if (!mResolvingError) {
92
            mGoogleApiClient.connect();
93
        }
94
    }
95
 
96
    @Override
97
    protected void onStop() {
98
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
99
            mGoogleApiClient.disconnect();
100
        }
101
 
102
        super.onStop();
103
    }
104
 
105
    public void onGetEventsClicked(View view) {
106
 
107
        Log.i(TAG, "onGetEventsClicked(): Checking permission.");
108
 
110
        // Check if the Calendar permission is already available.
111
        boolean calendarApproved =
112
                ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR)
113
                        == PackageManager.PERMISSION_GRANTED;
114
 
115
        boolean contactsApproved =
116
                ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
117
                        == PackageManager.PERMISSION_GRANTED;
118
 
119
        if (!calendarApproved || !contactsApproved) {
120
            // Calendar and/or Contact permissions have not been granted.
121
           requestCalendarAndContactPermissions();
122
 
123
        } else {
124
            // Calendar permissions is already available, start service
125
            Log.i(TAG, "Permissions already granted. Starting service.");
126
            pushCalendarToWear();
127
        }
129
 
130
    }
131
 
132
    /*
133
     * Requests Calendar and Contact permissions.
134
     * If the permission has been denied previously, a SnackBar will prompt the user to grant the
135
     * permission, otherwise it is requested directly.
136
     */
137
    private void requestCalendarAndContactPermissions() {
138
        Log.i(TAG, "CALENDAR permission has NOT been granted. Requesting permission.");
139
 
141
 
142
        boolean showCalendarPermissionRationale =
143
                ActivityCompat.shouldShowRequestPermissionRationale(this,
144
                        Manifest.permission.READ_CALENDAR);
145
        boolean showContactsPermissionRationale =
146
                ActivityCompat.shouldShowRequestPermissionRationale(this,
147
                        Manifest.permission.READ_CONTACTS);
148
 
149
        if (showCalendarPermissionRationale || showContactsPermissionRationale) {
150
            /*
151
             * Provide an additional rationale to the user if the permission was not granted and
152
             * the user would benefit from additional context for the use of the permission. For
153
             * example, if the user has previously denied the permission.
154
             */
155
            Log.i(TAG, "Display calendar & contact permissions rationale for additional context.");
156
 
157
            Snackbar.make(mLayout, R.string.permissions_rationale,
158
                    Snackbar.LENGTH_INDEFINITE)
159
                    .setAction(R.string.ok, new View.OnClickListener() {
160
                        @Override
161
                        public void onClick(View view) {
162
                            ActivityCompat.requestPermissions(MainActivity.this,
163
                                    new String[] {
164
                                            Manifest.permission.READ_CALENDAR,
165
                                            Manifest.permission.READ_CONTACTS},
166
                                    REQUEST_CALENDAR_AND_CONTACTS);
167
                        }
168
                    })
169
                    .show();
170
 
171
 
172
        } else {
173
 
174
            // Calendar/Contact permissions have not been granted yet. Request it directly.
175
            ActivityCompat.requestPermissions(
176
                    this,
177
                    new String[]{
178
                            Manifest.permission.READ_CALENDAR,
179
                            Manifest.permission.READ_CONTACTS
180
                    },
181
                    REQUEST_CALENDAR_AND_CONTACTS);
182
        }
184
    }
185
 
186
    private void pushCalendarToWear() {
187
        startService(new Intent(this, CalendarQueryService.class));
188
    }
189
 
190
    public void onDeleteEventsClicked(View view) {
191
        if (mGoogleApiClient.isConnected()) {
192
            Wearable.DataApi.getDataItems(mGoogleApiClient)
193
                    .setResultCallback(new ResultCallback<DataItemBuffer>() {
194
                        @Override
195
                        public void onResult(DataItemBuffer result) {
196
                            try {
197
                                if (result.getStatus().isSuccess()) {
198
                                    deleteDataItems(result);
199
                                } else {
200
                                    if (Log.isLoggable(TAG, Log.DEBUG)) {
201
                                        Log.d(TAG, "onDeleteEventsClicked(): failed to get Data "
202
                                                + "Items");
203
                                    }
204
                                }
205
                            } finally {
206
                                result.release();
207
                            }
208
                        }
209
                    });
210
        } else {
211
            Log.e(TAG, "Failed to delete data items"
212
                    + " - Client disconnected from Google Play Services");
213
        }
214
    }
215
 
216
    private void deleteDataItems(final DataItemBuffer dataItemList) {
217
        if (mGoogleApiClient.isConnected()) {
218
            for (final DataItem dataItem : dataItemList) {
219
                final Uri dataItemUri = dataItem.getUri();
220
                /*
221
                 * In a real calendar application, this might delete the corresponding calendar
222
                 * events from the calendar data provider. However, we simply delete the DataItem,
223
                 * but leave the phone's calendar data intact for this simple sample.
224
                 */
225
                Wearable.DataApi.deleteDataItems(mGoogleApiClient, dataItemUri)
226
                        .setResultCallback(new ResultCallback<DataApi.DeleteDataItemsResult>() {
227
                            @Override
228
                            public void onResult(DataApi.DeleteDataItemsResult deleteResult) {
229
                                if (deleteResult.getStatus().isSuccess()) {
230
                                    appendLog("Successfully deleted data item: " + dataItemUri);
231
                                } else {
232
                                    appendLog("Failed to delete data item:" + dataItemUri);
233
                                }
234
                            }
235
                        });
236
            }
237
        } else {
238
            Log.e(TAG, "Failed to delete data items"
239
                     + " - Client disconnected from Google Play Services");
240
        }
241
    }
242
 
243
    @Override
244
    public void onConnected(Bundle connectionHint) {
245
        if (Log.isLoggable(TAG, Log.DEBUG)) {
246
            Log.d(TAG, "Connected to Google Api Service.");
247
        }
248
        mResolvingError = false;
249
    }
250
 
251
    @Override
252
    public void onConnectionSuspended(int cause) {
253
        if (Log.isLoggable(TAG, Log.DEBUG)) {
254
            Log.d(TAG, "onConnectionSuspended(): Cause id: " + cause);
255
        }
256
    }
257
 
258
    @Override
259
    public void onConnectionFailed(ConnectionResult result) {
260
        if (Log.isLoggable(TAG, Log.DEBUG)) {
261
            Log.d(TAG, "Disconnected from Google Api Service");
262
        }
263
 
264
        if (mResolvingError) {
265
            // Already attempting to resolve an error.
266
            return;
267
        } else if (result.hasResolution()) {
268
            try {
269
                mResolvingError = true;
270
                result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
271
            } catch (IntentSender.SendIntentException e) {
272
                // There was an error with the resolution intent. Try again.
273
                mResolvingError = false;
274
                mGoogleApiClient.connect();
275
            }
276
        } else {
277
            mResolvingError = false;
278
        }
279
    }
280
 
281
    @Override
282
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
283
        super.onActivityResult(requestCode, resultCode, data);
284
        if (Log.isLoggable(TAG, Log.DEBUG)) {
285
            Log.d(TAG, "onActivityResult request/result codes: " + requestCode + "/" + resultCode);
286
        }
287
 
288
        if (requestCode == REQUEST_RESOLVE_ERROR) {
289
            mResolvingError = false;
290
            if (resultCode == RESULT_OK) {
291
                // Make sure the app is not already connected or attempting to connect
292
                if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) {
293
                    mGoogleApiClient.connect();
294
                }
295
            }
296
        }
297
    }
298
 
299
    /**
300
     * Callback received when a permissions request has been completed.
301
     */
302
    @Override
303
    public void onRequestPermissionsResult(
304
            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
305