/*
* Copyright (C) 2015 Google Inc. All Rights Reserved.
*
* 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.runtimepermissions;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import com.example.android.wearable.runtimepermissions.common.Constants;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.io.File;
import java.util.concurrent.TimeUnit;
/**
* Handles all incoming requests for phone data (and permissions) from wear devices.
*/
public class IncomingRequestPhoneService extends WearableListenerService {
private static final String TAG = "IncomingRequestService";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate()");
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
Log.d(TAG, "onMessageReceived(): " + messageEvent);
String messagePath = messageEvent.getPath();
if (messagePath.equals(Constants.MESSAGE_PATH_PHONE)) {
DataMap dataMap = DataMap.fromByteArray(messageEvent.getData());
int requestType = dataMap.getInt(Constants.KEY_COMM_TYPE, 0);
if (requestType == Constants.COMM_TYPE_REQUEST_PROMPT_PERMISSION) {
promptUserForStoragePermission(messageEvent.getSourceNodeId());
} else if (requestType == Constants.COMM_TYPE_REQUEST_DATA) {
respondWithStorageInformation(messageEvent.getSourceNodeId());
}
}
}
private void promptUserForStoragePermission(String nodeId) {
boolean storagePermissionApproved =
ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED;
if (storagePermissionApproved) {
DataMap dataMap = new DataMap();
dataMap.putInt(Constants.KEY_COMM_TYPE,
Constants.COMM_TYPE_RESPONSE_USER_APPROVED_PERMISSION);
sendMessage(nodeId, dataMap);
} else {
// Launch Phone Activity to grant storage permissions.
Intent startIntent = new Intent(this, PhonePermissionRequestActivity.class);
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
/* This extra is included to alert MainPhoneActivity to send back the permission
* results after the user has made their decision in PhonePermissionRequestActivity
* and it finishes.
*/
startIntent.putExtra(MainPhoneActivity.EXTRA_PROMPT_PERMISSION_FROM_WEAR, true);
startActivity(startIntent);
}
}
private void respondWithStorageInformation(String nodeId) {
boolean storagePermissionApproved =
ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED;
if (!storagePermissionApproved) {
DataMap dataMap = new DataMap();
dataMap.putInt(Constants.KEY_COMM_TYPE,
Constants.COMM_TYPE_RESPONSE_PERMISSION_REQUIRED);
sendMessage(nodeId, dataMap);
} else {
/* To keep the sample simple, we are only displaying the top level list of directories.
* Otherwise, it will return a message that the media wasn't available.
*/
StringBuilder stringBuilder = new StringBuilder();
if (isExternalStorageReadable()) {
File externalStorageDirectory = Environment.getExternalStorageDirectory();
String[] fileList = externalStorageDirectory.list();
if (fileList.length > 0) {
stringBuilder.append("List of directories on phone:\n");
for (String file : fileList) {
stringBuilder.append(" - " + file + "\n");
}
} else {
stringBuilder.append("No files in external storage.");
}
} else {
stringBuilder.append("No external media is available.");
}
// Send valid results
DataMap dataMap = new DataMap();
dataMap.putInt(Constants.KEY_COMM_TYPE,
Constants.COMM_TYPE_RESPONSE_DATA);
dataMap.putString(Constants.KEY_PAYLOAD, stringBuilder.toString());
sendMessage(nodeId, dataMap);
}
}
private void sendMessage(String nodeId, DataMap dataMap) {
Log.d(TAG, "sendMessage() Node: " + nodeId);
GoogleApiClient client = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.build();
client.blockingConnect(Constants.CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
PendingResult<MessageApi.SendMessageResult> pendingMessageResult =
Wearable.MessageApi.sendMessage(
client,
nodeId,
Constants.MESSAGE_PATH_WEAR,
dataMap.toByteArray());
MessageApi.SendMessageResult sendMessageResult =
pendingMessageResult.await(
Constants.CONNECTION_TIME_OUT_MS,
TimeUnit.MILLISECONDS);
if (!sendMessageResult.getStatus().isSuccess()) {
Log.d(TAG, "Sending message failed, status: "
+ sendMessageResult.getStatus());
} else {
Log.d(TAG, "Message sent successfully");
}
client.disconnect();
}
private boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state)
|| Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
}
}