Skip to content

Most visited

Recently visited

navigation
FindMyPhone / Wearable / src / com.example.android.wearable.findphone /

DisconnectListenerService.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.findphone;
18
 
19
import android.app.Notification;
20
import android.app.NotificationManager;
21
import android.os.Bundle;
22
import android.util.Log;
23
 
24
import com.google.android.gms.common.api.GoogleApiClient;
25
import com.google.android.gms.common.api.ResultCallback;
26
import com.google.android.gms.wearable.CapabilityApi;
27
import com.google.android.gms.wearable.CapabilityInfo;
28
import com.google.android.gms.wearable.Node;
29
import com.google.android.gms.wearable.Wearable;
30
import com.google.android.gms.wearable.WearableListenerService;
31
 
32
import java.util.List;
33
import java.util.Set;
34
 
35
/**
36
 * Listens for changes in connectivity between this wear device and the phone. More precisely, we
37
 * need to distinguish the case that the wear device and the phone are connected directly from all
38
 * other possible cases. To this end, the phone app has registered itself to provide the "find_me"
39
 * capability and we need to look for connected nodes that provide this capability AND are nearby,
40
 * to exclude a connection through the cloud. The proper way would have been to use the
41
 * {@code onCapabilitiesChanged()} callback but currently that callback cannot discover the case
42
 * where a connection switches from wifi to direct; this shortcoming will be addressed in future
43
 * updates but for now we will use the {@code onConnectedNodes()} callback.
44
 */
45
public class DisconnectListenerService extends WearableListenerService
46
        implements GoogleApiClient.ConnectionCallbacks {
47
 
48
    private static final String TAG = "ExampleFindPhoneApp";
49
 
50
    private static final int FORGOT_PHONE_NOTIFICATION_ID = 1;
51
 
52
    /* the capability that the phone app would provide */
53
    private static final String FIND_ME_CAPABILITY_NAME = "find_me";
54
 
55
    private GoogleApiClient mGoogleApiClient;
56
 
57
    @Override
58
    public void onCreate() {
59
        super.onCreate();
60
        mGoogleApiClient = new GoogleApiClient.Builder(this)
61
                .addApi(Wearable.API)
62
                .addConnectionCallbacks(this)
63
                .build();
64
    }
65
 
66
    @Override
67
    public void onConnectedNodes(List<Node> connectedNodes) {
68
        // After we are notified by this callback, we need to query for the nodes that provide the
69
        // "find_me" capability and are directly connected.
70
        if (mGoogleApiClient.isConnected()) {
71
            setOrUpdateNotification();
72
        } else if (!mGoogleApiClient.isConnecting()) {
73
            mGoogleApiClient.connect();
74
        }
75
    }
76
 
77
    private void setOrUpdateNotification() {
78
        Wearable.CapabilityApi.getCapability(
79
                mGoogleApiClient, FIND_ME_CAPABILITY_NAME,
80
                CapabilityApi.FILTER_REACHABLE).setResultCallback(
81
                new ResultCallback<CapabilityApi.GetCapabilityResult>() {
82
                    @Override
83
                    public void onResult(CapabilityApi.GetCapabilityResult result) {
84
                        if (result.getStatus().isSuccess()) {
85
                            updateFindMeCapability(result.getCapability());
86
                        } else {
87
                            Log.e(TAG,
88
                                    "setOrUpdateNotification() Failed to get capabilities, "
89
                                            + "status: "
90
                                            + result.getStatus().getStatusMessage());
91
                        }
92
                    }
93
                });
94
    }
95
 
96
    private void updateFindMeCapability(CapabilityInfo capabilityInfo) {
97
        Set<Node> connectedNodes = capabilityInfo.getNodes();
98
        if (connectedNodes.isEmpty()) {
99
            setupLostConnectivityNotification();
100
        } else {
101
            for (Node node : connectedNodes) {
102
                // we are only considering those nodes that are directly connected
103
                if (node.isNearby()) {
104
                    ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
105
                            .cancel(FORGOT_PHONE_NOTIFICATION_ID);
106
                }
107
            }
108
        }
109
    }
110
 
111
    /**
112
     * Creates a notification to inform user that the connectivity to phone has been lost (possibly
113
     * left the phone behind).
114
     */
115
    private void setupLostConnectivityNotification() {
116
        Notification.Builder notificationBuilder = new Notification.Builder(this)
117
                .setContentTitle(getString(R.string.left_phone_title))
118
                .setContentText(getString(R.string.left_phone_content))
119
                .setVibrate(new long[]{0, 200})  // Vibrate for 200 milliseconds.
120
                .setSmallIcon(R.drawable.ic_launcher)
121
                .setLocalOnly(true)
122
                .setPriority(Notification.PRIORITY_MAX);
123
        Notification card = notificationBuilder.build();
124
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
125
                .notify(FORGOT_PHONE_NOTIFICATION_ID, card);
126
    }
127
 
128
    @Override
129
    public void onConnected(Bundle bundle) {
130
        setOrUpdateNotification();
131
    }
132
 
133
    @Override
134
    public void onConnectionSuspended(int cause) {
135
 
136
    }
137
 
138
    @Override
139
    public void onDestroy() {
140
        if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()) {
141
            mGoogleApiClient.disconnect();
142
        }
143
        super.onDestroy();
144
    }
145
}
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.