upload android base code part7
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.android.wearable.findphone">
|
||||
|
||||
<uses-sdk android:minSdkVersion="18"
|
||||
android:targetSdkVersion="23" />
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.Holo.Light"
|
||||
android:allowBackup="true">
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.version"
|
||||
android:value="@integer/google_play_services_version" />
|
||||
|
||||
<service
|
||||
android:name="com.example.android.wearable.findphone.SoundAlarmListenerService" >
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
</application>
|
||||
</manifest>
|
After Width: | Height: | Size: 1,000 B |
After Width: | Height: | Size: 196 B |
After Width: | Height: | Size: 696 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.9 KiB |
|
@ -0,0 +1,24 @@
|
|||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,25 @@
|
|||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Widget.SampleMessage">
|
||||
<item name="android:textAppearance">?android:textAppearanceLarge</item>
|
||||
<item name="android:lineSpacingMultiplier">1.2</item>
|
||||
<item name="android:shadowDy">-6.5</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,22 @@
|
|||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
<style name="Theme.Base" parent="android:Theme.Material.Light">
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="app_name">FindMyPhone</string>
|
||||
<string name="intro_message">
|
||||
<![CDATA[
|
||||
|
||||
|
||||
This sample application notifies you when you may have left your phone behind
|
||||
(specifically, when your companion and wearable disconnect). If you have misplaced your phone, but
|
||||
it is still connected to your wearable, you can also start an activity on the wearable to sound an
|
||||
alarm on your phone.
|
||||
|
||||
|
||||
]]>
|
||||
</string>
|
||||
</resources>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
</resources>
|
|
@ -0,0 +1,32 @@
|
|||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
|
||||
|
||||
<dimen name="margin_tiny">4dp</dimen>
|
||||
<dimen name="margin_small">8dp</dimen>
|
||||
<dimen name="margin_medium">16dp</dimen>
|
||||
<dimen name="margin_large">32dp</dimen>
|
||||
<dimen name="margin_huge">64dp</dimen>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,42 @@
|
|||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
|
||||
<style name="Theme.Base" parent="android:Theme.Light" />
|
||||
|
||||
<style name="Theme.Sample" parent="Theme.Base" />
|
||||
|
||||
<style name="AppTheme" parent="Theme.Sample" />
|
||||
<!-- Widget styling -->
|
||||
|
||||
<style name="Widget" />
|
||||
|
||||
<style name="Widget.SampleMessage">
|
||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
||||
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.SampleMessageTile">
|
||||
<item name="android:background">@drawable/tile</item>
|
||||
<item name="android:shadowColor">#7F000000</item>
|
||||
<item name="android:shadowDy">-3.5</item>
|
||||
<item name="android:shadowRadius">2</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,7 @@
|
|||
<resources>
|
||||
<string-array name="android_wear_capabilities">
|
||||
<!-- declaring that phone provides find_me capability -->
|
||||
<item>find_me</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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.findphone;
|
||||
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.wearable.DataEvent;
|
||||
import com.google.android.gms.wearable.DataEventBuffer;
|
||||
import com.google.android.gms.wearable.DataMap;
|
||||
import com.google.android.gms.wearable.WearableListenerService;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Listens for disconnection from home device.
|
||||
*/
|
||||
public class SoundAlarmListenerService extends WearableListenerService {
|
||||
|
||||
private static final String TAG = "ExampleFindPhoneApp";
|
||||
|
||||
private static final String FIELD_ALARM_ON = "alarm_on";
|
||||
|
||||
private AudioManager mAudioManager;
|
||||
private static int mOrigVolume;
|
||||
private int mMaxVolume;
|
||||
private Uri mAlarmSound;
|
||||
private MediaPlayer mMediaPlayer;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
|
||||
mOrigVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
|
||||
mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
|
||||
mAlarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
|
||||
mMediaPlayer = new MediaPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// Reset the alarm volume to the user's original setting.
|
||||
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mOrigVolume, 0);
|
||||
mMediaPlayer.release();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataChanged(DataEventBuffer dataEvents) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "onDataChanged: " + dataEvents + " for " + getPackageName());
|
||||
}
|
||||
for (DataEvent event : dataEvents) {
|
||||
if (event.getType() == DataEvent.TYPE_DELETED) {
|
||||
Log.i(TAG, event + " deleted");
|
||||
} else if (event.getType() == DataEvent.TYPE_CHANGED) {
|
||||
Boolean alarmOn =
|
||||
DataMap.fromByteArray(event.getDataItem().getData()).get(FIELD_ALARM_ON);
|
||||
if (alarmOn) {
|
||||
mOrigVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
|
||||
mMediaPlayer.reset();
|
||||
// Sound alarm at max volume.
|
||||
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mMaxVolume, 0);
|
||||
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
|
||||
try {
|
||||
mMediaPlayer.setDataSource(getApplicationContext(), mAlarmSound);
|
||||
mMediaPlayer.prepare();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to prepare media player to play alarm.", e);
|
||||
}
|
||||
mMediaPlayer.start();
|
||||
} else {
|
||||
// Reset the alarm volume to the user's original setting.
|
||||
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mOrigVolume, 0);
|
||||
if (mMediaPlayer.isPlaying()) {
|
||||
mMediaPlayer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.android.wearable.findphone" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="20"
|
||||
android:targetSdkVersion="22" />
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-feature android:name="android.hardware.type.watch" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.DeviceDefault" >
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.version"
|
||||
android:value="@integer/google_play_services_version" />
|
||||
|
||||
<service android:name=".DisconnectListenerService" >
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service android:name="com.example.android.wearable.findphone.FindPhoneService"/>
|
||||
|
||||
<activity
|
||||
android:name=".FindPhoneActivity"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 1,000 B |
After Width: | Height: | Size: 696 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.9 KiB |
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<string name="app_name">Find My Phone</string>
|
||||
<string name="left_phone_title">Forgetting something?</string>
|
||||
<string name="left_phone_content">You may have left your phone behind.</string>
|
||||
<string name="turn_alarm_on">Tap to sound an alarm on phone.</string>
|
||||
<string name="turn_alarm_off">Tap to stop the alarm.</string>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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.findphone;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.common.api.ResultCallback;
|
||||
import com.google.android.gms.wearable.CapabilityApi;
|
||||
import com.google.android.gms.wearable.CapabilityInfo;
|
||||
import com.google.android.gms.wearable.Node;
|
||||
import com.google.android.gms.wearable.Wearable;
|
||||
import com.google.android.gms.wearable.WearableListenerService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Listens for changes in connectivity between this wear device and the phone. More precisely, we
|
||||
* need to distinguish the case that the wear device and the phone are connected directly from all
|
||||
* other possible cases. To this end, the phone app has registered itself to provide the "find_me"
|
||||
* capability and we need to look for connected nodes that provide this capability AND are nearby,
|
||||
* to exclude a connection through the cloud. The proper way would have been to use the
|
||||
* {@code onCapabilitiesChanged()} callback but currently that callback cannot discover the case
|
||||
* where a connection switches from wifi to direct; this shortcoming will be addressed in future
|
||||
* updates but for now we will use the {@code onConnectedNodes()} callback.
|
||||
*/
|
||||
public class DisconnectListenerService extends WearableListenerService
|
||||
implements GoogleApiClient.ConnectionCallbacks {
|
||||
|
||||
private static final String TAG = "ExampleFindPhoneApp";
|
||||
|
||||
private static final int FORGOT_PHONE_NOTIFICATION_ID = 1;
|
||||
|
||||
/* the capability that the phone app would provide */
|
||||
private static final String FIND_ME_CAPABILITY_NAME = "find_me";
|
||||
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mGoogleApiClient = new GoogleApiClient.Builder(this)
|
||||
.addApi(Wearable.API)
|
||||
.addConnectionCallbacks(this)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectedNodes(List<Node> connectedNodes) {
|
||||
// After we are notified by this callback, we need to query for the nodes that provide the
|
||||
// "find_me" capability and are directly connected.
|
||||
if (mGoogleApiClient.isConnected()) {
|
||||
setOrUpdateNotification();
|
||||
} else if (!mGoogleApiClient.isConnecting()) {
|
||||
mGoogleApiClient.connect();
|
||||
}
|
||||
}
|
||||
|
||||
private void setOrUpdateNotification() {
|
||||
Wearable.CapabilityApi.getCapability(
|
||||
mGoogleApiClient, FIND_ME_CAPABILITY_NAME,
|
||||
CapabilityApi.FILTER_REACHABLE).setResultCallback(
|
||||
new ResultCallback<CapabilityApi.GetCapabilityResult>() {
|
||||
@Override
|
||||
public void onResult(CapabilityApi.GetCapabilityResult result) {
|
||||
if (result.getStatus().isSuccess()) {
|
||||
updateFindMeCapability(result.getCapability());
|
||||
} else {
|
||||
Log.e(TAG,
|
||||
"setOrUpdateNotification() Failed to get capabilities, "
|
||||
+ "status: "
|
||||
+ result.getStatus().getStatusMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateFindMeCapability(CapabilityInfo capabilityInfo) {
|
||||
Set<Node> connectedNodes = capabilityInfo.getNodes();
|
||||
if (connectedNodes.isEmpty()) {
|
||||
setupLostConnectivityNotification();
|
||||
} else {
|
||||
for (Node node : connectedNodes) {
|
||||
// we are only considering those nodes that are directly connected
|
||||
if (node.isNearby()) {
|
||||
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
|
||||
.cancel(FORGOT_PHONE_NOTIFICATION_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a notification to inform user that the connectivity to phone has been lost (possibly
|
||||
* left the phone behind).
|
||||
*/
|
||||
private void setupLostConnectivityNotification() {
|
||||
Notification.Builder notificationBuilder = new Notification.Builder(this)
|
||||
.setContentTitle(getString(R.string.left_phone_title))
|
||||
.setContentText(getString(R.string.left_phone_content))
|
||||
.setVibrate(new long[]{0, 200}) // Vibrate for 200 milliseconds.
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setLocalOnly(true)
|
||||
.setPriority(Notification.PRIORITY_MAX);
|
||||
Notification card = notificationBuilder.build();
|
||||
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
|
||||
.notify(FORGOT_PHONE_NOTIFICATION_ID, card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(Bundle bundle) {
|
||||
setOrUpdateNotification();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int cause) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()) {
|
||||
mGoogleApiClient.disconnect();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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.findphone;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.Notification.Action;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
|
||||
public class FindPhoneActivity extends Activity {
|
||||
|
||||
private static final int FIND_PHONE_NOTIFICATION_ID = 2;
|
||||
private static Notification.Builder notification;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Create a notification with an action to toggle an alarm on the phone.
|
||||
Intent toggleAlarmOperation = new Intent(this, FindPhoneService.class);
|
||||
toggleAlarmOperation.setAction(FindPhoneService.ACTION_TOGGLE_ALARM);
|
||||
PendingIntent toggleAlarmIntent = PendingIntent.getService(this, 0, toggleAlarmOperation,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
Action alarmAction = new Action(R.drawable.alarm_action_icon, "", toggleAlarmIntent);
|
||||
// This intent turns off the alarm if the user dismisses the card from the wearable.
|
||||
Intent cancelAlarmOperation = new Intent(this, FindPhoneService.class);
|
||||
cancelAlarmOperation.setAction(FindPhoneService.ACTION_CANCEL_ALARM);
|
||||
PendingIntent cancelAlarmIntent = PendingIntent.getService(this, 0, cancelAlarmOperation,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
// Use a spannable string for the notification title to resize it.
|
||||
SpannableString title = new SpannableString(getString(R.string.app_name));
|
||||
title.setSpan(new RelativeSizeSpan(0.85f), 0, title.length(), Spannable.SPAN_POINT_MARK);
|
||||
notification = new Notification.Builder(this)
|
||||
.setContentTitle(title)
|
||||
.setContentText(getString(R.string.turn_alarm_on))
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setVibrate(new long[] {0, 50}) // Vibrate to bring card to top of stream.
|
||||
.setDeleteIntent(cancelAlarmIntent)
|
||||
.extend(new Notification.WearableExtender()
|
||||
.addAction(alarmAction)
|
||||
.setContentAction(0)
|
||||
.setHintHideIcon(true))
|
||||
.setLocalOnly(true)
|
||||
.setPriority(Notification.PRIORITY_MAX);
|
||||
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
|
||||
.notify(FIND_PHONE_NOTIFICATION_ID, notification.build());
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the text on the wearable notification. This is used so the notification reflects the
|
||||
* current state of the alarm on the phone. For instance, if the alarm is turned on, the
|
||||
* notification text indicates that the user can tap it to turn it off, and vice-versa.
|
||||
*
|
||||
* @param context
|
||||
* @param notificationText The new text to display on the wearable notification.
|
||||
*/
|
||||
public static void updateNotification(Context context, String notificationText) {
|
||||
notification.setContentText(notificationText);
|
||||
((NotificationManager) context.getSystemService(NOTIFICATION_SERVICE))
|
||||
.notify(FIND_PHONE_NOTIFICATION_ID, notification.build());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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.findphone;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.wearable.DataItemBuffer;
|
||||
import com.google.android.gms.wearable.DataMap;
|
||||
import com.google.android.gms.wearable.PutDataMapRequest;
|
||||
import com.google.android.gms.wearable.Wearable;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Creates a sound on the paired phone to find it.
|
||||
*/
|
||||
public class FindPhoneService extends IntentService implements GoogleApiClient.ConnectionCallbacks,
|
||||
GoogleApiClient.OnConnectionFailedListener {
|
||||
|
||||
private static final String TAG = "ExampleFindPhoneApp";
|
||||
|
||||
private static final String FIELD_ALARM_ON = "alarm_on";
|
||||
private static final String PATH_SOUND_ALARM = "/sound_alarm";
|
||||
public static final String ACTION_TOGGLE_ALARM = "action_toggle_alarm";
|
||||
public static final String ACTION_CANCEL_ALARM = "action_alarm_off";
|
||||
|
||||
// Timeout for making a connection to GoogleApiClient (in milliseconds).
|
||||
private static final long CONNECTION_TIME_OUT_MS = 100;
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
|
||||
public FindPhoneService() {
|
||||
super(FindPhoneService.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mGoogleApiClient = new GoogleApiClient.Builder(this)
|
||||
.addApi(Wearable.API)
|
||||
.addConnectionCallbacks(this)
|
||||
.addOnConnectionFailedListener(this)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
mGoogleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "FindPhoneService.onHandleIntent");
|
||||
}
|
||||
if (mGoogleApiClient.isConnected()) {
|
||||
// Set the alarm off by default.
|
||||
boolean alarmOn = false;
|
||||
if (intent.getAction().equals(ACTION_TOGGLE_ALARM)) {
|
||||
// Get current state of the alarm.
|
||||
DataItemBuffer result = Wearable.DataApi.getDataItems(mGoogleApiClient).await();
|
||||
try {
|
||||
if (result.getStatus().isSuccess()) {
|
||||
if (result.getCount() == 1) {
|
||||
alarmOn = DataMap.fromByteArray(result.get(0).getData())
|
||||
.getBoolean(FIELD_ALARM_ON, false);
|
||||
} else {
|
||||
Log.e(TAG, "Unexpected number of DataItems found.\n"
|
||||
+ "\tExpected: 1\n"
|
||||
+ "\tActual: " + result.getCount());
|
||||
}
|
||||
} else if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "onHandleIntent: failed to get current alarm state");
|
||||
}
|
||||
} finally {
|
||||
result.release();
|
||||
}
|
||||
// Toggle alarm.
|
||||
alarmOn = !alarmOn;
|
||||
// Change notification text based on new value of alarmOn.
|
||||
String notificationText = alarmOn ? getString(R.string.turn_alarm_off)
|
||||
: getString(R.string.turn_alarm_on);
|
||||
FindPhoneActivity.updateNotification(this, notificationText);
|
||||
}
|
||||
// Use alarmOn boolean to update the DataItem - phone will respond accordingly
|
||||
// when it receives the change.
|
||||
PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(PATH_SOUND_ALARM);
|
||||
putDataMapRequest.getDataMap().putBoolean(FIELD_ALARM_ON, alarmOn);
|
||||
putDataMapRequest.setUrgent();
|
||||
Wearable.DataApi.putDataItem(mGoogleApiClient, putDataMapRequest.asPutDataRequest())
|
||||
.await();
|
||||
} else {
|
||||
Log.e(TAG, "Failed to toggle alarm on phone - Client disconnected from Google Play "
|
||||
+ "Services");
|
||||
}
|
||||
mGoogleApiClient.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(Bundle connectionHint) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int cause) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionFailed(ConnectionResult result) {
|
||||
}
|
||||
|
||||
}
|
13
android/development/samples/browseable/FindMyPhone/_index.jd
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
page.tags="FindMyPhone"
|
||||
sample.group=Wearable
|
||||
@jd:body
|
||||
|
||||
<p>
|
||||
|
||||
This sample application notifies you when you may have left your phone behind
|
||||
(specifically, when your companion and wearable disconnect). If you have misplaced your phone, but
|
||||
it is still connected to your wearable, you can also start an activity on the wearable to sound an
|
||||
alarm on your phone.
|
||||
|
||||
</p>
|