Home | History | Annotate | Download | only in com.example.android.wearable.delayedconfirmation
      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.delayedconfirmation;
     18 
     19 import android.app.Activity;
     20 import android.app.Notification;
     21 import android.app.NotificationManager;
     22 import android.os.Bundle;
     23 import android.support.wearable.view.DelayedConfirmationView;
     24 import android.util.Log;
     25 import android.view.View;
     26 import android.widget.Toast;
     27 
     28 import com.google.android.gms.common.ConnectionResult;
     29 import com.google.android.gms.common.api.GoogleApiClient;
     30 import com.google.android.gms.common.api.ResultCallback;
     31 import com.google.android.gms.wearable.CapabilityApi;
     32 import com.google.android.gms.wearable.CapabilityInfo;
     33 import com.google.android.gms.wearable.MessageApi;
     34 import com.google.android.gms.wearable.Node;
     35 import com.google.android.gms.wearable.Wearable;
     36 
     37 import java.util.Set;
     38 
     39 public class MainActivity extends Activity implements
     40         DelayedConfirmationView.DelayedConfirmationListener,
     41         GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks,
     42         CapabilityApi.CapabilityListener {
     43 
     44     private static final String TAG = "DelayedConfirmation";
     45     private static final int NUM_SECONDS = 5;
     46 
     47     private static final String TIMER_SELECTED_PATH = "/timer_selected";
     48     private static final String TIMER_FINISHED_PATH = "/timer_finished";
     49 
     50     /* name of the capability that the phone side provides */
     51     private static final String CONFIRMATION_HANDLER_CAPABILITY_NAME = "confirmation_handler";
     52 
     53     private DelayedConfirmationView delayedConfirmationView;
     54     private GoogleApiClient mGoogleApiClient;
     55 
     56     /* the preferred note that can handle the confirmation capability */
     57     private Node mConfirmationHandlerNode;
     58 
     59     @Override
     60     public void onCreate(Bundle b) {
     61         super.onCreate(b);
     62         setContentView(R.layout.main_activity);
     63         delayedConfirmationView = (DelayedConfirmationView) findViewById(R.id.delayed_confirmation);
     64         delayedConfirmationView.setTotalTimeMs(NUM_SECONDS * 1000);
     65         mGoogleApiClient = new GoogleApiClient.Builder(this)
     66                 .addApi(Wearable.API)
     67                 .addOnConnectionFailedListener(this)
     68                 .addConnectionCallbacks(this)
     69                 .build();
     70     }
     71 
     72     @Override
     73     protected void onResume() {
     74         super.onResume();
     75         if (!mGoogleApiClient.isConnected()) {
     76             mGoogleApiClient.connect();
     77         }
     78     }
     79 
     80     @Override
     81     protected void onPause() {
     82         if (mGoogleApiClient.isConnected()) {
     83             Wearable.CapabilityApi.removeCapabilityListener(mGoogleApiClient, this,
     84                     CONFIRMATION_HANDLER_CAPABILITY_NAME);
     85             mGoogleApiClient.disconnect();
     86         }
     87         super.onPause();
     88     }
     89 
     90     /**
     91      * Starts the DelayedConfirmationView when user presses "Start Timer" button.
     92      */
     93     public void onStartTimer(View view) {
     94         delayedConfirmationView.start();
     95         delayedConfirmationView.setListener(this);
     96     }
     97 
     98     @Override
     99     public void onTimerSelected(View v) {
    100         v.setPressed(true);
    101         Notification notification = new Notification.Builder(this)
    102                 .setSmallIcon(R.drawable.ic_launcher)
    103                 .setContentTitle(getString(R.string.notification_title))
    104                 .setContentText(getString(R.string.notification_timer_selected))
    105                 .build();
    106         ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).notify(0, notification);
    107         sendMessageToCompanion(TIMER_SELECTED_PATH);
    108         // Prevent onTimerFinished from being heard.
    109         ((DelayedConfirmationView) v).setListener(null);
    110         finish();
    111     }
    112 
    113     @Override
    114     public void onTimerFinished(View v) {
    115         Notification notification = new Notification.Builder(this)
    116                 .setSmallIcon(R.drawable.ic_launcher)
    117                 .setContentTitle(getString(R.string.notification_title))
    118                 .setContentText(getString(R.string.notification_timer_finished))
    119                 .build();
    120         ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).notify(0, notification);
    121         sendMessageToCompanion(TIMER_FINISHED_PATH);
    122         finish();
    123     }
    124 
    125     @Override
    126     public void onConnectionFailed(ConnectionResult connectionResult) {
    127         Log.e(TAG, "Failed to connect to Google Api Client");
    128         mConfirmationHandlerNode = null;
    129     }
    130 
    131     private void sendMessageToCompanion(final String path) {
    132         if (mConfirmationHandlerNode != null) {
    133             Wearable.MessageApi.sendMessage(mGoogleApiClient, mConfirmationHandlerNode.getId(),
    134                     path, new byte[0])
    135                     .setResultCallback(getSendMessageResultCallback(mConfirmationHandlerNode));
    136         } else {
    137             Toast.makeText(this, R.string.no_device_found, Toast.LENGTH_SHORT).show();
    138         }
    139     }
    140 
    141     private ResultCallback<MessageApi.SendMessageResult> getSendMessageResultCallback(
    142             final Node node) {
    143         return new ResultCallback<MessageApi.SendMessageResult>() {
    144             @Override
    145             public void onResult(MessageApi.SendMessageResult sendMessageResult) {
    146                 if (!sendMessageResult.getStatus().isSuccess()) {
    147                     Log.e(TAG, "Failed to send message with status "
    148                             + sendMessageResult.getStatus());
    149                 } else {
    150                     Log.d(TAG, "Sent confirmation message to node " + node.getDisplayName());
    151                 }
    152             }
    153         };
    154     }
    155 
    156     private void setupConfirmationHandlerNode() {
    157         Wearable.CapabilityApi.addCapabilityListener(
    158                 mGoogleApiClient, this, CONFIRMATION_HANDLER_CAPABILITY_NAME);
    159 
    160         Wearable.CapabilityApi.getCapability(
    161                 mGoogleApiClient, CONFIRMATION_HANDLER_CAPABILITY_NAME,
    162                 CapabilityApi.FILTER_REACHABLE).setResultCallback(
    163                 new ResultCallback<CapabilityApi.GetCapabilityResult>() {
    164                     @Override
    165                     public void onResult(CapabilityApi.GetCapabilityResult result) {
    166                         if (!result.getStatus().isSuccess()) {
    167                             Log.e(TAG, "setupConfirmationHandlerNode() Failed to get capabilities, "
    168                                     + "status: " + result.getStatus().getStatusMessage());
    169                             return;
    170                         }
    171                         updateConfirmationCapability(result.getCapability());
    172                     }
    173                 });
    174     }
    175 
    176     private void updateConfirmationCapability(CapabilityInfo capabilityInfo) {
    177         Set<Node> connectedNodes = capabilityInfo.getNodes();
    178         if (connectedNodes.isEmpty()) {
    179             mConfirmationHandlerNode = null;
    180         } else {
    181             mConfirmationHandlerNode = pickBestNode(connectedNodes);
    182         }
    183     }
    184 
    185     /**
    186      * We pick a node that is capabale of handling the confirmation. If there is more than one,
    187      * then we would prefer the one that is directly connected to this device. In general,
    188      * depending on the situation and requirements, the "best" node might be picked based on other
    189      * criteria.
    190      */
    191     private Node pickBestNode(Set<Node> connectedNodes) {
    192         Node best = null;
    193         if (connectedNodes != null) {
    194             for (Node node : connectedNodes) {
    195                 if (node.isNearby()) {
    196                     return node;
    197                 }
    198                 best = node;
    199             }
    200         }
    201         return best;
    202     }
    203 
    204     @Override
    205     public void onConnected(Bundle bundle) {
    206         setupConfirmationHandlerNode();
    207     }
    208 
    209     @Override
    210     public void onConnectionSuspended(int cause) {
    211         mConfirmationHandlerNode = null;
    212     }
    213 
    214     @Override
    215     public void onCapabilityChanged(CapabilityInfo capabilityInfo) {
    216         updateConfirmationCapability(capabilityInfo);
    217     }
    218 }
    219