Merge "Deletes the wear samples that have been commited in the wrong place. Updates the location of wear samples in sdk.atree Adds SpeedTracker wear sample (https://googleplex-android-review.git.corp.google.com/564608)" into lmp-dev

This commit is contained in:
Joe Fernandez
2014-10-22 20:25:18 +00:00
committed by Android (Google) Code Review
698 changed files with 18 additions and 22248 deletions

View File

@@ -302,23 +302,24 @@ developers/build/prebuilts/gradle/RevealEffectBasic sam
developers/build/prebuilts/androidtv samples/${PLATFORM_NAME}/androidtv
# Wearable sample tree
development/samples/wearable/AgendaData samples/${PLATFORM_NAME}/wearable/AgendaData
development/samples/wearable/DataLayer samples/${PLATFORM_NAME}/wearable/DataLayer
development/samples/wearable/DelayedConfirmation samples/${PLATFORM_NAME}/wearable/DelayedConfirmation
development/samples/wearable/ElizaChat samples/${PLATFORM_NAME}/wearable/ElizaChat
development/samples/wearable/EmbeddedApp samples/${PLATFORM_NAME}/wearable/EmbeddedApp
development/samples/wearable/FindMyPhone samples/${PLATFORM_NAME}/wearable/FindMyPhone
development/samples/wearable/Flashlight samples/${PLATFORM_NAME}/wearable/Flashlight
development/samples/wearable/Geofencing samples/${PLATFORM_NAME}/wearable/Geofencing
development/samples/wearable/GridViewPager samples/${PLATFORM_NAME}/wearable/GridViewPager
development/samples/wearable/JumpingJack samples/${PLATFORM_NAME}/wearable/JumpingJack
development/samples/wearable/Notifications samples/${PLATFORM_NAME}/wearable/Notifications
development/samples/wearable/Quiz samples/${PLATFORM_NAME}/wearable/Quiz
development/samples/wearable/RecipeAssistant samples/${PLATFORM_NAME}/wearable/RecipeAssistant
development/samples/wearable/SkeletonWearableApp samples/${PLATFORM_NAME}/wearable/SkeletonWearableApp
development/samples/wearable/SynchronizedNotifications samples/${PLATFORM_NAME}/wearable/SynchronizedNotifications
development/samples/wearable/Timer samples/${PLATFORM_NAME}/wearable/Timer
development/samples/wearable/WatchViewStub samples/${PLATFORM_NAME}/wearable/WatchViewStub
developers/build/prebuilts/gradle/AgendaData samples/${PLATFORM_NAME}/wearable/AgendaData
developers/build/prebuilts/gradle/DataLayer samples/${PLATFORM_NAME}/wearable/DataLayer
developers/build/prebuilts/gradle/DelayedConfirmation samples/${PLATFORM_NAME}/wearable/DelayedConfirmation
developers/build/prebuilts/gradle/ElizaChat samples/${PLATFORM_NAME}/wearable/ElizaChat
developers/build/prebuilts/gradle/EmbeddedApp samples/${PLATFORM_NAME}/wearable/EmbeddedApp
developers/build/prebuilts/gradle/FindMyPhone samples/${PLATFORM_NAME}/wearable/FindMyPhone
developers/build/prebuilts/gradle/Flashlight samples/${PLATFORM_NAME}/wearable/Flashlight
developers/build/prebuilts/gradle/Geofencing samples/${PLATFORM_NAME}/wearable/Geofencing
developers/build/prebuilts/gradle/GridViewPager samples/${PLATFORM_NAME}/wearable/GridViewPager
developers/build/prebuilts/gradle/JumpingJack samples/${PLATFORM_NAME}/wearable/JumpingJack
developers/build/prebuilts/gradle/Notifications samples/${PLATFORM_NAME}/wearable/Notifications
developers/build/prebuilts/gradle/Quiz samples/${PLATFORM_NAME}/wearable/Quiz
developers/build/prebuilts/gradle/RecipeAssistant samples/${PLATFORM_NAME}/wearable/RecipeAssistant
developers/build/prebuilts/gradle/SkeletonWearableApp samples/${PLATFORM_NAME}/wearable/SkeletonWearableApp
developers/build/prebuilts/gradle/SpeedTracker samples/${PLATFORM_NAME}/wearable/SpeedTracker
developers/build/prebuilts/gradle/SynchronizedNotifications samples/${PLATFORM_NAME}/wearable/SynchronizedNotifications
developers/build/prebuilts/gradle/Timer samples/${PLATFORM_NAME}/wearable/Timer
developers/build/prebuilts/gradle/WatchViewStub samples/${PLATFORM_NAME}/wearable/WatchViewStub
# Old sample tree
development/samples/AccelerometerPlay samples/${PLATFORM_NAME}/legacy/AccelerometerPlay

View File

@@ -1,42 +0,0 @@
# built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
out/
src/common
src/template
_index.jd
README.txt
# Libraries used by the app
# Can explicitly add if we want, but shouldn't do so blindly. Licenses, bloat, etc.
/libs
# Build stuff (auto-generated by android update project ...)
ant.properties
local.properties
# Eclipse project files
.classpath
.project
# idea project files
.idea/
.idea/.name
*.iml
*.ipr
*.iws
##Gradle-based build
.gradle
build/

View File

@@ -1,26 +0,0 @@
apply plugin: 'android'
android {
compileSdkVersion 18
buildToolsVersion '20'
defaultConfig {
minSdkVersion 18
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.google.android.gms:play-services:5.0.+'
compile "com.android.support:support-v4:20.0.+"
wearApp project(':Wearable')
}

View File

@@ -1,28 +0,0 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-dontwarn android.support.wearable.view.DelayedConfirmationView
-dontwarn android.support.wearable.view.CircledImageView
-keep class android.support.wearable.view.WearableListView {
private void setScrollAnimator(int);
protected void setScrollVertically(int);
}

View File

@@ -1,14 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19

View File

@@ -1,45 +0,0 @@
<?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.agendadata">
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light"
android:allowBackup="false">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name="com.example.android.wearable.agendadata.MainActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="com.example.android.wearable.agendadata.CalendarQueryService"/>
</application>
</manifest>

View File

@@ -1,267 +0,0 @@
/*
* 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.agendadata;
import static com.example.android.wearable.agendadata.Constants.TAG;
import static com.example.android.wearable.agendadata.Constants.CONNECTION_TIME_OUT_MS;
import static com.example.android.wearable.agendadata.Constants.CAL_DATA_ITEM_PATH_PREFIX;
import static com.example.android.wearable.agendadata.Constants.ALL_DAY;
import static com.example.android.wearable.agendadata.Constants.BEGIN;
import static com.example.android.wearable.agendadata.Constants.DATA_ITEM_URI;
import static com.example.android.wearable.agendadata.Constants.DESCRIPTION;
import static com.example.android.wearable.agendadata.Constants.END;
import static com.example.android.wearable.agendadata.Constants.EVENT_ID;
import static com.example.android.wearable.agendadata.Constants.ID;
import static com.example.android.wearable.agendadata.Constants.PROFILE_PIC;
import static com.example.android.wearable.agendadata.Constants.TITLE;
import android.app.IntentService;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.text.format.Time;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.Wearable;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Queries calendar events using Android Calendar Provider API and creates a data item for each
* event.
*/
public class CalendarQueryService extends IntentService
implements ConnectionCallbacks, OnConnectionFailedListener {
private static final String[] INSTANCE_PROJECTION = {
CalendarContract.Instances._ID,
CalendarContract.Instances.EVENT_ID,
CalendarContract.Instances.TITLE,
CalendarContract.Instances.BEGIN,
CalendarContract.Instances.END,
CalendarContract.Instances.ALL_DAY,
CalendarContract.Instances.DESCRIPTION,
CalendarContract.Instances.ORGANIZER
};
private static final String[] CONTACT_PROJECTION = new String[] { Data._ID, Data.CONTACT_ID };
private static final String CONTACT_SELECTION = Email.ADDRESS + " = ?";
private GoogleApiClient mGoogleApiClient;
public CalendarQueryService() {
super(CalendarQueryService.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);
// Query calendar events in the next 24 hours.
Time time = new Time();
time.setToNow();
long beginTime = time.toMillis(true);
time.monthDay++;
time.normalize(true);
long endTime = time.normalize(true);
List<Event> events = queryEvents(this, beginTime, endTime);
for (Event event : events) {
final PutDataMapRequest putDataMapRequest = event.toPutDataMapRequest();
if (mGoogleApiClient.isConnected()) {
Wearable.DataApi.putDataItem(
mGoogleApiClient, putDataMapRequest.asPutDataRequest()).await();
} else {
Log.e(TAG, "Failed to send data item: " + putDataMapRequest
+ " - Client disconnected from Google Play Services");
}
}
mGoogleApiClient.disconnect();
}
private static String makeDataItemPath(long eventId, long beginTime) {
return CAL_DATA_ITEM_PATH_PREFIX + eventId + "/" + beginTime;
}
private static List<Event> queryEvents(Context context, long beginTime, long endTime) {
ContentResolver contentResolver = context.getContentResolver();
Uri.Builder builder = CalendarContract.Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, beginTime);
ContentUris.appendId(builder, endTime);
Cursor cursor = contentResolver.query(builder.build(), INSTANCE_PROJECTION,
null /* selection */, null /* selectionArgs */, null /* sortOrder */);
try {
int idIdx = cursor.getColumnIndex(CalendarContract.Instances._ID);
int eventIdIdx = cursor.getColumnIndex(CalendarContract.Instances.EVENT_ID);
int titleIdx = cursor.getColumnIndex(CalendarContract.Instances.TITLE);
int beginIdx = cursor.getColumnIndex(CalendarContract.Instances.BEGIN);
int endIdx = cursor.getColumnIndex(CalendarContract.Instances.END);
int allDayIdx = cursor.getColumnIndex(CalendarContract.Instances.ALL_DAY);
int descIdx = cursor.getColumnIndex(CalendarContract.Instances.DESCRIPTION);
int ownerEmailIdx = cursor.getColumnIndex(CalendarContract.Instances.ORGANIZER);
List<Event> events = new ArrayList<Event>(cursor.getCount());
while (cursor.moveToNext()) {
Event event = new Event();
event.id = cursor.getLong(idIdx);
event.eventId = cursor.getLong(eventIdIdx);
event.title = cursor.getString(titleIdx);
event.begin = cursor.getLong(beginIdx);
event.end = cursor.getLong(endIdx);
event.allDay = cursor.getInt(allDayIdx) != 0;
event.description = cursor.getString(descIdx);
String ownerEmail = cursor.getString(ownerEmailIdx);
Cursor contactCursor = contentResolver.query(Data.CONTENT_URI,
CONTACT_PROJECTION, CONTACT_SELECTION, new String[] {ownerEmail}, null);
int ownerIdIdx = contactCursor.getColumnIndex(Data.CONTACT_ID);
long ownerId = -1;
if (contactCursor.moveToFirst()) {
ownerId = contactCursor.getLong(ownerIdIdx);
}
contactCursor.close();
// Use event organizer's profile picture as the notification background.
event.ownerProfilePic = getProfilePicture(contentResolver, context, ownerId);
events.add(event);
}
return events;
} finally {
cursor.close();
}
}
@Override
public void onConnected(Bundle connectionHint) {
}
@Override
public void onConnectionSuspended(int cause) {
}
@Override
public void onConnectionFailed(ConnectionResult result) {
}
private static Asset getDefaultProfile(Resources res) {
Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.nobody);
return Asset.createFromBytes(toByteArray(bitmap));
}
private static Asset getProfilePicture(ContentResolver contentResolver, Context context,
long contactId) {
if (contactId != -1) {
// Try to retrieve the profile picture for the given contact.
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
InputStream inputStream = Contacts.openContactPhotoInputStream(contentResolver,
contactUri, true /*preferHighres*/);
if (null != inputStream) {
try {
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap != null) {
return Asset.createFromBytes(toByteArray(bitmap));
} else {
Log.e(TAG, "Cannot decode profile picture for contact " + contactId);
}
} finally {
closeQuietly(inputStream);
}
}
}
// Use a default background image if the user has no profile picture or there was an error.
return getDefaultProfile(context.getResources());
}
private static byte[] toByteArray(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
closeQuietly(stream);
return byteArray;
}
private static void closeQuietly(Closeable closeable) {
try {
closeable.close();
} catch (IOException e) {
Log.e(TAG, "IOException while closing closeable.", e);
}
}
private static class Event {
public long id;
public long eventId;
public String title;
public long begin;
public long end;
public boolean allDay;
public String description;
public Asset ownerProfilePic;
public PutDataMapRequest toPutDataMapRequest(){
final PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(
makeDataItemPath(eventId, begin));
DataMap data = putDataMapRequest.getDataMap();
data.putString(DATA_ITEM_URI, putDataMapRequest.getUri().toString());
data.putLong(ID, id);
data.putLong(EVENT_ID, eventId);
data.putString(TITLE, title);
data.putLong(BEGIN, begin);
data.putLong(END, end);
data.putBoolean(ALL_DAY, allDay);
data.putString(DESCRIPTION, description);
data.putAsset(PROFILE_PIC, ownerProfilePic);
return putDataMapRequest;
}
}
}

View File

@@ -1,39 +0,0 @@
/*
* 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.agendadata;
/** Constants used in companion app. */
public final class Constants {
private Constants() {
}
public static final String TAG = "AgendaDataSample";
public static final String CAL_DATA_ITEM_PATH_PREFIX = "/event";
// Timeout for making a connection to GoogleApiClient (in milliseconds).
public static final long CONNECTION_TIME_OUT_MS = 100;
public static final String EVENT_ID = "event_id";
public static final String ID = "id";
public static final String TITLE = "title";
public static final String DESCRIPTION = "description";
public static final String BEGIN = "begin";
public static final String END = "end";
public static final String DATA_ITEM_URI = "data_item_uri";
public static final String ALL_DAY = "all_day";
public static final String PROFILE_PIC = "profile_pic";
}

View File

@@ -1,202 +0,0 @@
/*
* 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.agendadata;
import static com.example.android.wearable.agendadata.Constants.TAG;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ScrollView;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.data.FreezableUtils;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataItem;
import com.google.android.gms.wearable.DataItemBuffer;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import java.util.List;
public class MainActivity extends Activity implements NodeApi.NodeListener, ConnectionCallbacks,
OnConnectionFailedListener {
/** Request code for launching the Intent to resolve Google Play services errors. */
private static final int REQUEST_RESOLVE_ERROR = 1000;
private GoogleApiClient mGoogleApiClient;
private boolean mResolvingError = false;
private TextView mLogTextView;
ScrollView mScroller;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mLogTextView = (TextView) findViewById(R.id.log);
mScroller = (ScrollView) findViewById(R.id.scroller);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onStart() {
super.onStart();
if (!mResolvingError) {
mGoogleApiClient.connect();
}
}
@Override
protected void onStop() {
if (mGoogleApiClient.isConnected()) {
Wearable.NodeApi.removeListener(mGoogleApiClient, this);
}
mGoogleApiClient.disconnect();
super.onStop();
}
public void onGetEventsClicked(View v) {
startService(new Intent(this, CalendarQueryService.class));
}
public void onDeleteEventsClicked(View v) {
if (mGoogleApiClient.isConnected()) {
Wearable.DataApi.getDataItems(mGoogleApiClient)
.setResultCallback(new ResultCallback<DataItemBuffer>() {
@Override
public void onResult(DataItemBuffer result) {
if (result.getStatus().isSuccess()) {
deleteDataItems(result);
} else {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onDeleteEventsClicked(): failed to get Data Items");
}
}
result.close();
}
});
} else {
Log.e(TAG, "Failed to delete data items"
+ " - Client disconnected from Google Play Services");
}
}
private void deleteDataItems(DataItemBuffer dataItems) {
if (mGoogleApiClient.isConnected()) {
// Store the DataItem URIs in a List and close the buffer. Then use these URIs
// to delete the DataItems.
final List<DataItem> dataItemList = FreezableUtils.freezeIterable(dataItems);
dataItems.close();
for (final DataItem dataItem : dataItemList) {
final Uri dataItemUri = dataItem.getUri();
// In a real calendar application, this might delete the corresponding calendar
// event from the calendar data provider. In this sample, we simply delete the
// DataItem, but leave the phone's calendar data intact.
Wearable.DataApi.deleteDataItems(mGoogleApiClient, dataItemUri)
.setResultCallback(new ResultCallback<DataApi.DeleteDataItemsResult>() {
@Override
public void onResult(DataApi.DeleteDataItemsResult deleteResult) {
if (deleteResult.getStatus().isSuccess()) {
appendLog("Successfully deleted data item: " + dataItemUri);
} else {
appendLog("Failed to delete data item:" + dataItemUri);
}
}
});
}
} else {
Log.e(TAG, "Failed to delete data items"
+ " - Client disconnected from Google Play Services");
}
}
private void appendLog(final String s) {
mLogTextView.post(new Runnable() {
@Override
public void run() {
mLogTextView.append(s);
mLogTextView.append("\n");
mScroller.fullScroll(View.FOCUS_DOWN);
}
});
}
@Override
public void onPeerConnected(Node peer) {
appendLog("Device connected");
}
@Override
public void onPeerDisconnected(Node peer) {
appendLog("Device disconnected");
}
@Override
public void onConnected(Bundle connectionHint) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Connected to Google Api Service");
}
mResolvingError = false;
Wearable.NodeApi.addListener(mGoogleApiClient, this);
}
@Override
public void onConnectionSuspended(int cause) {
// Ignore
}
@Override
public void onConnectionFailed(ConnectionResult result) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Disconnected from Google Api Service");
}
if (null != Wearable.NodeApi) {
Wearable.NodeApi.removeListener(mGoogleApiClient, this);
}
if (mResolvingError) {
// Already attempting to resolve an error.
return;
} else if (result.hasResolution()) {
try {
mResolvingError = true;
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
} else {
mResolvingError = false;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,58 +0,0 @@
<?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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/get_events"
android:onClick="onGetEventsClicked"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/delete_events"
android:onClick="onDeleteEventsClicked"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"
android:layout_marginTop="6dp"
android:padding="6dp"
android:text="@string/log"
android:textAllCaps="true"
android:textColor="@android:color/white"
android:background="@android:color/black"/>
<ScrollView
android:id="@+id/scroller"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/log"
android:fontFamily="courier"
android:textColor="@android:color/white"
android:background="@android:color/black"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
</LinearLayout>

View File

@@ -1,22 +0,0 @@
<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Android Wear AgendaData Example Application</string>
<string name="get_events">Sync calendar events to wearable</string>
<string name="delete_events">Delete calendar events from wearable</string>
<string name="log">Log</string>
</resources>

View File

@@ -1,26 +0,0 @@
<?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>
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<item name="android:windowAnimationStyle">@null</item>
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
</resources>

View File

@@ -1,25 +0,0 @@
apply plugin: 'android'
android {
compileSdkVersion 20
buildToolsVersion '20'
defaultConfig {
minSdkVersion 20
targetSdkVersion 20
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.google.android.gms:play-services-wearable:+'
compile "com.google.android.support:wearable:1.0.+"
}

View File

@@ -1,22 +0,0 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-dontwarn android.support.wearable.view.DelayedConfirmationView
-dontwarn android.support.wearable.view.CircledImageView

View File

@@ -1,14 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19

View File

@@ -1,43 +0,0 @@
<?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.agendadata" >
<uses-feature android:name="android.hardware.type.watch" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:allowBackup="false">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<service
android:name="com.example.android.wearable.agendadata.HomeListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<service android:name="com.example.android.wearable.agendadata.DeleteService"/>
<activity android:name="android.support.wearable.activity.ConfirmationActivity"/>
</application>
</manifest>

View File

@@ -1,35 +0,0 @@
/*
* 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.agendadata;
/** Constants used in wearable app. */
public final class Constants {
private Constants() {
}
public static final String TAG = "AgendaDataSample";
public static final String TITLE = "title";
public static final String DESCRIPTION = "description";
public static final String BEGIN = "begin";
public static final String END = "end";
public static final String ALL_DAY = "all_day";
public static final String PROFILE_PIC = "profile_pic";
public static final String EXTRA_SILENT = "silent";
}

View File

@@ -1,118 +0,0 @@
/*
* 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.agendadata;
import static com.example.android.wearable.agendadata.Constants.TAG;
import static com.example.android.wearable.agendadata.Constants.EXTRA_SILENT;
import android.app.IntentService;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.wearable.activity.ConfirmationActivity;
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.DataApi;
import com.google.android.gms.wearable.Wearable;
import java.util.concurrent.TimeUnit;
/**
* Handles "Delete" button on calendar event card.
*/
public class DeleteService extends IntentService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
/* Timeout for making a connection to GoogleApiClient (in milliseconds) */
private static final long TIME_OUT = 100;
private GoogleApiClient mGoogleApiClient;
public DeleteService() {
super(DeleteService.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(TIME_OUT, TimeUnit.MILLISECONDS);
Uri dataItemUri = intent.getData();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "DeleteService.onHandleIntent=" + dataItemUri);
}
if (mGoogleApiClient.isConnected()) {
DataApi.DeleteDataItemsResult result = Wearable.DataApi
.deleteDataItems(mGoogleApiClient, dataItemUri).await();
if (result.getStatus().isSuccess() && !intent.getBooleanExtra(EXTRA_SILENT, false)) {
// Show the success animation on the watch unless Silent extra is true.
startConfirmationActivity(ConfirmationActivity.SUCCESS_ANIMATION,
getString(R.string.delete_successful));
} else {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "DeleteService.onHandleIntent: Failed to delete dataItem:"
+ dataItemUri);
}
// Show the failure animation on the watch unless Silent extra is true.
if (!intent.getBooleanExtra(EXTRA_SILENT, false)) {
startConfirmationActivity(ConfirmationActivity.FAILURE_ANIMATION,
getString(R.string.delete_unsuccessful));
}
}
} else {
Log.e(TAG, "Failed to delete data item: " + dataItemUri
+ " - Client disconnected from Google Play Services");
// Show the failure animation on the watch unless Silent extra is true.
if (!intent.getBooleanExtra(EXTRA_SILENT, false)) {
startConfirmationActivity(ConfirmationActivity.FAILURE_ANIMATION,
getString(R.string.delete_unsuccessful));
}
}
mGoogleApiClient.disconnect();
}
private void startConfirmationActivity(int animationType, String message) {
Intent confirmationActivity = new Intent(this, ConfirmationActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION)
.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, animationType)
.putExtra(ConfirmationActivity.EXTRA_MESSAGE, message);
startActivity(confirmationActivity);
}
@Override
public void onConnected(Bundle connectionHint) {
}
@Override
public void onConnectionSuspended(int cause) {
}
@Override
public void onConnectionFailed(ConnectionResult result) {
}
}

View File

@@ -1,180 +0,0 @@
/*
* 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.agendadata;
import static com.example.android.wearable.agendadata.Constants.TAG;
import static com.example.android.wearable.agendadata.Constants.EXTRA_SILENT;
import static com.example.android.wearable.agendadata.Constants.ALL_DAY;
import static com.example.android.wearable.agendadata.Constants.BEGIN;
import static com.example.android.wearable.agendadata.Constants.DESCRIPTION;
import static com.example.android.wearable.agendadata.Constants.END;
import static com.example.android.wearable.agendadata.Constants.PROFILE_PIC;
import static com.example.android.wearable.agendadata.Constants.TITLE;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Log;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataItem;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Listens to DataItem events on the home device.
*/
public class HomeListenerService extends WearableListenerService {
private static final Map<Uri, Integer> sNotificationIdByDataItemUri =
new HashMap<Uri, Integer>();
private static int sNotificationId = 1;
private GoogleApiClient mGoogleApiClient;
@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) {
deleteDataItem(event.getDataItem());
} else if (event.getType() == DataEvent.TYPE_CHANGED) {
UpdateNotificationForDataItem(event.getDataItem());
}
}
dataEvents.close();
}
@Override
public void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this.getApplicationContext())
.addApi(Wearable.API)
.build();
mGoogleApiClient.connect();
}
/**
* Posts a local notification to show calendar card.
*/
private void UpdateNotificationForDataItem(DataItem dataItem) {
DataMapItem mapDataItem = DataMapItem.fromDataItem(dataItem);
DataMap data = mapDataItem.getDataMap();
String description = data.getString(DESCRIPTION);
if (TextUtils.isEmpty(description)) {
description = "";
} else {
// Add a space between the description and the time of the event.
description += " ";
}
String contentText;
if (data.getBoolean(ALL_DAY)) {
contentText = getString(R.string.desc_all_day, description);
} else {
String startTime = DateFormat.getTimeFormat(this).format(new Date(data.getLong(BEGIN)));
String endTime = DateFormat.getTimeFormat(this).format(new Date(data.getLong(END)));
contentText = getString(R.string.desc_time_period, description, startTime, endTime);
}
Intent deleteOperation = new Intent(this, DeleteService.class);
// Use a unique identifier for the delete action.
String deleteAction = "action_delete" + dataItem.getUri().toString() + sNotificationId;
deleteOperation.setAction(deleteAction);
deleteOperation.setData(dataItem.getUri());
PendingIntent deleteIntent = PendingIntent.getService(this, 0, deleteOperation,
PendingIntent.FLAG_ONE_SHOT);
PendingIntent silentDeleteIntent = PendingIntent.getService(this, 1,
deleteOperation.putExtra(EXTRA_SILENT, true), PendingIntent.FLAG_ONE_SHOT);
Notification.Builder notificationBuilder = new Notification.Builder(this)
.setContentTitle(data.getString(TITLE))
.setContentText(contentText)
.setSmallIcon(R.drawable.ic_launcher)
.addAction(R.drawable.ic_menu_delete, getText(R.string.delete), deleteIntent)
.setDeleteIntent(silentDeleteIntent) // Delete DataItem if notification dismissed.
.setLocalOnly(true)
.setPriority(Notification.PRIORITY_MIN);
// Set the event owner's profile picture as the notification background.
Asset asset = data.getAsset(PROFILE_PIC);
if (null != asset) {
if (mGoogleApiClient.isConnected()) {
DataApi.GetFdForAssetResult assetFdResult =
Wearable.DataApi.getFdForAsset(mGoogleApiClient, asset).await();
if (assetFdResult.getStatus().isSuccess()) {
Bitmap profilePic = BitmapFactory.decodeStream(assetFdResult.getInputStream());
notificationBuilder.extend(new Notification.WearableExtender()
.setBackground(profilePic));
} else if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "asset fetch failed with statusCode: "
+ assetFdResult.getStatus().getStatusCode());
}
} else {
Log.e(TAG, "Failed to set notification background"
+ " - Client disconnected from Google Play Services");
}
}
Notification card = notificationBuilder.build();
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.notify(sNotificationId, card);
sNotificationIdByDataItemUri.put(dataItem.getUri(), sNotificationId++);
}
/**
* Deletes the calendar card associated with the data item.
*/
private void deleteDataItem(DataItem dataItem) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "onDataItemDeleted:DataItem=" + dataItem.getUri());
}
Integer notificationId = sNotificationIdByDataItemUri.remove(dataItem.getUri());
if (notificationId != null) {
((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(notificationId);
}
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onMessageReceived: " + messageEvent.getPath()
+ " " + messageEvent.getData() + " for " + getPackageName());
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -1,24 +0,0 @@
<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Android Wear AgendaData Example Application</string>
<string name="delete">Delete</string>
<string name="desc_all_day">%s(All day)</string>
<string name="desc_time_period">%1$s(%2$s - %3$s)</string>
<string name="delete_successful">Event deleted</string>
<string name="delete_unsuccessful">Unable to delete event</string>
</resources>

View File

@@ -1,17 +0,0 @@
<p><b>About:</b> Syncs calendar events to your wearable at the press of a button, using the Wearable
DataApi to transmit data such as event time, description, and background image. The DataItems can be
deleted individually via an action on the event notifications, or all at once via a button on the
companion. When deleted using the notification action, a ConfirmationActivity is used to indicate
success or failure.</p>
<p><b>How to run:</b> Install the Application APK on the companion, and the Wearable APK on the
wearable. Start the sample by running the AgendaData application on the companion.</p>
<p><b>Wearable APIs used:</b> DataApi, NodeApi, WearableListenerService, ConfirmationActivity</p>
<p><b>Screenshots:</b>
<figure>
<img src="screenshots/companion_agenda_data.png" alt="Companion AgendaData" width="216"
height="384">
<img src="screenshots/dummy_calendar_event.png" alt="Dummy Calendar Event" width="160"
height="160">
<figcaption>Companion app and wearable app communicate with each other.</figcaption>
</figure>
</p>

View File

@@ -1,14 +0,0 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.+'
}
}
allprojects {
repositories {
mavenCentral()
}
}

View File

@@ -1,18 +0,0 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Settings specified in this file will override any Gradle settings
# configured through the IDE.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

View File

@@ -1,6 +0,0 @@
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip

View File

@@ -1,164 +0,0 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@@ -1,90 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -1 +0,0 @@
include 'Wearable', 'Application'

View File

@@ -1,26 +0,0 @@
apply plugin: 'android'
android {
compileSdkVersion 18
buildToolsVersion '20'
defaultConfig {
minSdkVersion 18
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.google.android.gms:play-services:5.0.+'
compile "com.android.support:support-v4:20.0.+"
wearApp project(':Wearable')
}

View File

@@ -1,20 +0,0 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@@ -1,41 +0,0 @@
<?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.datalayer" >
<uses-feature android:name="android.hardware.camera" android:required="false" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,484 +0,0 @@
/*
* 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.datalayer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.data.FreezableUtils;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataApi.DataItemResult;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.MessageApi.SendMessageResult;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Receives its own events using a listener API designed for foreground activities. Updates a data
* item every second while it is open. Also allows user to take a photo and send that as an asset to
* the paired wearable.
*/
public class MainActivity extends Activity implements DataApi.DataListener,
MessageApi.MessageListener, NodeApi.NodeListener, ConnectionCallbacks,
OnConnectionFailedListener {
private static final String TAG = "MainActivity";
/** Request code for launching the Intent to resolve Google Play services errors. */
private static final int REQUEST_RESOLVE_ERROR = 1000;
private static final String START_ACTIVITY_PATH = "/start-activity";
private static final String COUNT_PATH = "/count";
private static final String IMAGE_PATH = "/image";
private static final String IMAGE_KEY = "photo";
private static final String COUNT_KEY = "count";
private GoogleApiClient mGoogleApiClient;
private boolean mResolvingError = false;
private boolean mCameraSupported = false;
private ListView mDataItemList;
private Button mTakePhotoBtn;
private Button mSendPhotoBtn;
private ImageView mThumbView;
private Bitmap mImageBitmap;
private View mStartActivityBtn;
private DataItemAdapter mDataItemListAdapter;
private Handler mHandler;
// Send DataItems.
private ScheduledExecutorService mGeneratorExecutor;
private ScheduledFuture<?> mDataItemGeneratorFuture;
static final int REQUEST_IMAGE_CAPTURE = 1;
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
mHandler = new Handler();
LOGD(TAG, "onCreate");
mCameraSupported = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
setContentView(R.layout.main_activity);
setupViews();
// Stores DataItems received by the local broadcaster or from the paired watch.
mDataItemListAdapter = new DataItemAdapter(this, android.R.layout.simple_list_item_1);
mDataItemList.setAdapter(mDataItemListAdapter);
mGeneratorExecutor = new ScheduledThreadPoolExecutor(1);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
mImageBitmap = (Bitmap) extras.get("data");
mThumbView.setImageBitmap(mImageBitmap);
}
}
@Override
protected void onStart() {
super.onStart();
if (!mResolvingError) {
mGoogleApiClient.connect();
}
}
@Override
public void onResume() {
super.onResume();
mDataItemGeneratorFuture = mGeneratorExecutor.scheduleWithFixedDelay(
new DataItemGenerator(), 1, 5, TimeUnit.SECONDS);
}
@Override
public void onPause() {
super.onPause();
mDataItemGeneratorFuture.cancel(true /* mayInterruptIfRunning */);
}
@Override
protected void onStop() {
if (!mResolvingError) {
Wearable.DataApi.removeListener(mGoogleApiClient, this);
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
Wearable.NodeApi.removeListener(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
super.onStop();
}
@Override //ConnectionCallbacks
public void onConnected(Bundle connectionHint) {
LOGD(TAG, "Google API Client was connected");
mResolvingError = false;
mStartActivityBtn.setEnabled(true);
mSendPhotoBtn.setEnabled(mCameraSupported);
Wearable.DataApi.addListener(mGoogleApiClient, this);
Wearable.MessageApi.addListener(mGoogleApiClient, this);
Wearable.NodeApi.addListener(mGoogleApiClient, this);
}
@Override //ConnectionCallbacks
public void onConnectionSuspended(int cause) {
LOGD(TAG, "Connection to Google API client was suspended");
mStartActivityBtn.setEnabled(false);
mSendPhotoBtn.setEnabled(false);
}
@Override //OnConnectionFailedListener
public void onConnectionFailed(ConnectionResult result) {
if (mResolvingError) {
// Already attempting to resolve an error.
return;
} else if (result.hasResolution()) {
try {
mResolvingError = true;
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
} else {
Log.e(TAG, "Connection to Google API client has failed");
mResolvingError = false;
mStartActivityBtn.setEnabled(false);
mSendPhotoBtn.setEnabled(false);
Wearable.DataApi.removeListener(mGoogleApiClient, this);
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
Wearable.NodeApi.removeListener(mGoogleApiClient, this);
}
}
@Override //DataListener
public void onDataChanged(DataEventBuffer dataEvents) {
LOGD(TAG, "onDataChanged: " + dataEvents);
final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
dataEvents.close();
runOnUiThread(new Runnable() {
@Override
public void run() {
for (DataEvent event : events) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
mDataItemListAdapter.add(
new Event("DataItem Changed", event.getDataItem().toString()));
} else if (event.getType() == DataEvent.TYPE_DELETED) {
mDataItemListAdapter.add(
new Event("DataItem Deleted", event.getDataItem().toString()));
}
}
}
});
}
@Override //MessageListener
public void onMessageReceived(final MessageEvent messageEvent) {
LOGD(TAG, "onMessageReceived() A message from watch was received:" + messageEvent
.getRequestId() + " " + messageEvent.getPath());
mHandler.post(new Runnable() {
@Override
public void run() {
mDataItemListAdapter.add(new Event("Message from watch", messageEvent.toString()));
}
});
}
@Override //NodeListener
public void onPeerConnected(final Node peer) {
LOGD(TAG, "onPeerConnected: " + peer);
mHandler.post(new Runnable() {
@Override
public void run() {
mDataItemListAdapter.add(new Event("Connected", peer.toString()));
}
});
}
@Override //NodeListener
public void onPeerDisconnected(final Node peer) {
LOGD(TAG, "onPeerDisconnected: " + peer);
mHandler.post(new Runnable() {
@Override
public void run() {
mDataItemListAdapter.add(new Event("Disconnected", peer.toString()));
}
});
}
/**
* A View Adapter for presenting the Event objects in a list
*/
private static class DataItemAdapter extends ArrayAdapter<Event> {
private final Context mContext;
public DataItemAdapter(Context context, int unusedResource) {
super(context, unusedResource);
mContext = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(android.R.layout.two_line_list_item, null);
convertView.setTag(holder);
holder.text1 = (TextView) convertView.findViewById(android.R.id.text1);
holder.text2 = (TextView) convertView.findViewById(android.R.id.text2);
} else {
holder = (ViewHolder) convertView.getTag();
}
Event event = getItem(position);
holder.text1.setText(event.title);
holder.text2.setText(event.text);
return convertView;
}
private class ViewHolder {
TextView text1;
TextView text2;
}
}
private class Event {
String title;
String text;
public Event(String title, String text) {
this.title = title;
this.text = text;
}
}
private Collection<String> getNodes() {
HashSet<String> results = new HashSet<String>();
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
for (Node node : nodes.getNodes()) {
results.add(node.getId());
}
return results;
}
private void sendStartActivityMessage(String node) {
Wearable.MessageApi.sendMessage(
mGoogleApiClient, node, START_ACTIVITY_PATH, new byte[0]).setResultCallback(
new ResultCallback<SendMessageResult>() {
@Override
public void onResult(SendMessageResult sendMessageResult) {
if (!sendMessageResult.getStatus().isSuccess()) {
Log.e(TAG, "Failed to send message with status code: "
+ sendMessageResult.getStatus().getStatusCode());
}
}
}
);
}
private class StartWearableActivityTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... args) {
Collection<String> nodes = getNodes();
for (String node : nodes) {
sendStartActivityMessage(node);
}
return null;
}
}
/** Sends an RPC to start a fullscreen Activity on the wearable. */
public void onStartWearableActivityClick(View view) {
LOGD(TAG, "Generating RPC");
// Trigger an AsyncTask that will query for a list of connected nodes and send a
// "start-activity" message to each connected node.
new StartWearableActivityTask().execute();
}
/** Generates a DataItem based on an incrementing count. */
private class DataItemGenerator implements Runnable {
private int count = 0;
@Override
public void run() {
PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(COUNT_PATH);
putDataMapRequest.getDataMap().putInt(COUNT_KEY, count++);
PutDataRequest request = putDataMapRequest.asPutDataRequest();
LOGD(TAG, "Generating DataItem: " + request);
if (!mGoogleApiClient.isConnected()) {
return;
}
Wearable.DataApi.putDataItem(mGoogleApiClient, request)
.setResultCallback(new ResultCallback<DataItemResult>() {
@Override
public void onResult(DataItemResult dataItemResult) {
if (!dataItemResult.getStatus().isSuccess()) {
Log.e(TAG, "ERROR: failed to putDataItem, status code: "
+ dataItemResult.getStatus().getStatusCode());
}
}
});
}
}
/**
* Dispatches an {@link android.content.Intent} to take a photo. Result will be returned back
* in onActivityResult().
*/
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
/**
* Builds an {@link com.google.android.gms.wearable.Asset} from a bitmap. The image that we get
* back from the camera in "data" is a thumbnail size. Typically, your image should not exceed
* 320x320 and if you want to have zoom and parallax effect in your app, limit the size of your
* image to 640x400. Resize your image before transferring to your wearable device.
*/
private static Asset toAsset(Bitmap bitmap) {
ByteArrayOutputStream byteStream = null;
try {
byteStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
return Asset.createFromBytes(byteStream.toByteArray());
} finally {
if (null != byteStream) {
try {
byteStream.close();
} catch (IOException e) {
// ignore
}
}
}
}
/**
* Sends the asset that was created form the photo we took by adding it to the Data Item store.
*/
private void sendPhoto(Asset asset) {
PutDataMapRequest dataMap = PutDataMapRequest.create(IMAGE_PATH);
dataMap.getDataMap().putAsset(IMAGE_KEY, asset);
dataMap.getDataMap().putLong("time", new Date().getTime());
PutDataRequest request = dataMap.asPutDataRequest();
Wearable.DataApi.putDataItem(mGoogleApiClient, request)
.setResultCallback(new ResultCallback<DataItemResult>() {
@Override
public void onResult(DataItemResult dataItemResult) {
LOGD(TAG, "Sending image was successful: " + dataItemResult.getStatus()
.isSuccess());
}
});
}
public void onTakePhotoClick(View view) {
dispatchTakePictureIntent();
}
public void onSendPhotoClick(View view) {
if (null != mImageBitmap && mGoogleApiClient.isConnected()) {
sendPhoto(toAsset(mImageBitmap));
}
}
/**
* Sets up UI components and their callback handlers.
*/
private void setupViews() {
mTakePhotoBtn = (Button) findViewById(R.id.takePhoto);
mSendPhotoBtn = (Button) findViewById(R.id.sendPhoto);
// Shows the image received from the handset
mThumbView = (ImageView) findViewById(R.id.imageView);
mDataItemList = (ListView) findViewById(R.id.data_item_list);
mStartActivityBtn = findViewById(R.id.start_wearable_activity);
}
/**
* As simple wrapper around Log.d
*/
private static void LOGD(final String tag, String message) {
if (Log.isLoggable(tag, Log.DEBUG)) {
Log.d(tag, message);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 896 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,20 +0,0 @@
<?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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="2dip"/>
<solid android:color="#ffffffff"/>
</shape>

View File

@@ -1,86 +0,0 @@
<?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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="10dp">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/take_photo"
android:id="@+id/takePhoto"
android:onClick="onTakePhotoClick"
android:layout_marginLeft="39dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/send_photo"
android:id="@+id/sendPhoto"
android:layout_alignRight="@+id/takePhoto"
android:layout_marginLeft="39dp"
android:enabled="false"
android:onClick="onSendPhotoClick"
android:layout_alignParentStart="true"
android:layout_below="@+id/takePhoto" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:layout_marginLeft="29dp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:src="@drawable/ic_content_picture" />
</RelativeLayout>
<View
style="@style/Divider"
android:id="@+id/divider"
android:layout_below="@+id/top"
android:layout_marginTop="5dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp" />
<Button
android:id="@+id/start_wearable_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:onClick="onStartWearableActivityClick"
android:text="@string/start_wearable_activity"
android:enabled="false"
android:layout_below="@+id/divider"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp" />
<ListView
android:id="@+id/data_item_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/start_wearable_activity"
android:transcriptMode="alwaysScroll" />
</RelativeLayout>

View File

@@ -1,23 +0,0 @@
<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Data Layer Sample App</string>
<string name="start_wearable_activity">Start Wearable Activity</string>
<string name="start">Start</string>
<string name="take_photo">Take a Photo</string>
<string name="send_photo">Send Photo</string>
</resources>

View File

@@ -1,23 +0,0 @@
<?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>
<style name="Divider">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">3dp</item>
<item name="android:background">?android:attr/listDivider</item>
</style>
</resources>

View File

@@ -1,24 +0,0 @@
apply plugin: 'android'
android {
compileSdkVersion 20
buildToolsVersion '20'
defaultConfig {
minSdkVersion 20
targetSdkVersion 20
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.google.android.gms:play-services-wearable:+'
}

View File

@@ -1,20 +0,0 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@@ -1,52 +0,0 @@
<?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.datalayer" >
<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=".DataLayerListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="com.example.android.wearable.datalayer.EXAMPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,120 +0,0 @@
/*
* 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.datalayer;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.data.FreezableUtils;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.MessageEvent;
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.concurrent.TimeUnit;
/**
* Listens to DataItems and Messages from the local node.
*/
public class DataLayerListenerService extends WearableListenerService {
private static final String TAG = "DataLayerListenerServic";
private static final String START_ACTIVITY_PATH = "/start-activity";
private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";
public static final String COUNT_PATH = "/count";
public static final String IMAGE_PATH = "/image";
public static final String IMAGE_KEY = "photo";
private static final String COUNT_KEY = "count";
private static final int MAX_LOG_TAG_LENGTH = 23;
GoogleApiClient mGoogleApiClient;
@Override
public void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.build();
mGoogleApiClient.connect();
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
LOGD(TAG, "onDataChanged: " + dataEvents);
final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
dataEvents.close();
if(!mGoogleApiClient.isConnected()) {
ConnectionResult connectionResult = mGoogleApiClient
.blockingConnect(30, TimeUnit.SECONDS);
if (!connectionResult.isSuccess()) {
Log.e(TAG, "DataLayerListenerService failed to connect to GoogleApiClient.");
return;
}
}
// Loop through the events and send a message back to the node that created the data item.
for (DataEvent event : events) {
Uri uri = event.getDataItem().getUri();
String path = uri.getPath();
if (COUNT_PATH.equals(path)) {
// Get the node id of the node that created the data item from the host portion of
// the uri.
String nodeId = uri.getHost();
// Set the data of the message to be the bytes of the Uri.
byte[] payload = uri.toString().getBytes();
// Send the rpc
Wearable.MessageApi.sendMessage(mGoogleApiClient, nodeId, DATA_ITEM_RECEIVED_PATH,
payload);
}
}
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
LOGD(TAG, "onMessageReceived: " + messageEvent);
// Check to see if the message is to start an activity
if (messageEvent.getPath().equals(START_ACTIVITY_PATH)) {
Intent startIntent = new Intent(this, MainActivity.class);
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startIntent);
}
}
@Override
public void onPeerConnected(Node peer) {
LOGD(TAG, "onPeerConnected: " + peer);
}
@Override
public void onPeerDisconnected(Node peer) {
LOGD(TAG, "onPeerDisconnected: " + peer);
}
public static void LOGD(final String tag, String message) {
if (Log.isLoggable(tag, Log.DEBUG)) {
Log.d(tag, message);
}
}
}

View File

@@ -1,255 +0,0 @@
/*
* 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.datalayer;
import static com.example.android.wearable.datalayer.DataLayerListenerService.LOGD;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.data.FreezableUtils;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import java.io.InputStream;
import java.util.List;
/**
* Shows events and photo from the Wearable APIs.
*/
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener, DataApi.DataListener, MessageApi.MessageListener,
NodeApi.NodeListener {
private static final String TAG = "MainActivity";
private GoogleApiClient mGoogleApiClient;
private ListView mDataItemList;
private TextView mIntroText;
private DataItemAdapter mDataItemListAdapter;
private View mLayout;
private Handler mHandler;
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
mHandler = new Handler();
LOGD(TAG, "onCreate");
setContentView(R.layout.main_activity);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mDataItemList = (ListView) findViewById(R.id.dataItem_list);
mIntroText = (TextView) findViewById(R.id.intro);
mLayout = findViewById(R.id.layout);
// Stores data events received by the local broadcaster.
mDataItemListAdapter = new DataItemAdapter(this, android.R.layout.simple_list_item_1);
mDataItemList.setAdapter(mDataItemListAdapter);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onResume() {
super.onResume();
mGoogleApiClient.connect();
}
@Override
protected void onPause() {
super.onPause();
Wearable.DataApi.removeListener(mGoogleApiClient, this);
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
Wearable.NodeApi.removeListener(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
@Override
public void onConnected(Bundle connectionHint) {
LOGD(TAG, "onConnected(): Successfully connected to Google API client");
Wearable.DataApi.addListener(mGoogleApiClient, this);
Wearable.MessageApi.addListener(mGoogleApiClient, this);
Wearable.NodeApi.addListener(mGoogleApiClient, this);
}
@Override
public void onConnectionSuspended(int cause) {
LOGD(TAG, "onConnectionSuspended(): Connection to Google API client was suspended");
}
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.e(TAG, "onConnectionFailed(): Failed to connect, with result: " + result);
}
private void generateEvent(final String title, final String text) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mIntroText.setVisibility(View.INVISIBLE);
mDataItemListAdapter.add(new Event(title, text));
}
});
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
LOGD(TAG, "onDataChanged(): " + dataEvents);
final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
dataEvents.close();
for (DataEvent event : events) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
String path = event.getDataItem().getUri().getPath();
if (DataLayerListenerService.IMAGE_PATH.equals(path)) {
DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
Asset photo = dataMapItem.getDataMap()
.getAsset(DataLayerListenerService.IMAGE_KEY);
final Bitmap bitmap = loadBitmapFromAsset(mGoogleApiClient, photo);
mHandler.post(new Runnable() {
@Override
public void run() {
Log.d(TAG, "Setting background image..");
mLayout.setBackground(new BitmapDrawable(getResources(), bitmap));
}
});
} else if (DataLayerListenerService.COUNT_PATH.equals(path)) {
LOGD(TAG, "Data Changed for COUNT_PATH");
generateEvent("DataItem Changed", event.getDataItem().toString());
} else {
LOGD(TAG, "Unrecognized path: " + path);
}
} else if (event.getType() == DataEvent.TYPE_DELETED) {
generateEvent("DataItem Deleted", event.getDataItem().toString());
} else {
generateEvent("Unknown data event type", "Type = " + event.getType());
}
}
}
/**
* Extracts {@link android.graphics.Bitmap} data from the
* {@link com.google.android.gms.wearable.Asset}
*/
private Bitmap loadBitmapFromAsset(GoogleApiClient apiClient, Asset asset) {
if (asset == null) {
throw new IllegalArgumentException("Asset must be non-null");
}
InputStream assetInputStream = Wearable.DataApi.getFdForAsset(
apiClient, asset).await().getInputStream();
if (assetInputStream == null) {
Log.w(TAG, "Requested an unknown Asset.");
return null;
}
return BitmapFactory.decodeStream(assetInputStream);
}
@Override
public void onMessageReceived(MessageEvent event) {
LOGD(TAG, "onMessageReceived: " + event);
generateEvent("Message", event.toString());
}
@Override
public void onPeerConnected(Node node) {
generateEvent("Node Connected", node.getId());
}
@Override
public void onPeerDisconnected(Node node) {
generateEvent("Node Disconnected", node.getId());
}
private static class DataItemAdapter extends ArrayAdapter<Event> {
private final Context mContext;
public DataItemAdapter(Context context, int unusedResource) {
super(context, unusedResource);
mContext = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(android.R.layout.two_line_list_item, null);
convertView.setTag(holder);
holder.text1 = (TextView) convertView.findViewById(android.R.id.text1);
holder.text2 = (TextView) convertView.findViewById(android.R.id.text2);
} else {
holder = (ViewHolder) convertView.getTag();
}
Event event = getItem(position);
holder.text1.setText(event.title);
holder.text2.setText(event.text);
return convertView;
}
private class ViewHolder {
TextView text1;
TextView text2;
}
}
private class Event {
String title;
String text;
public Event(String title, String text) {
this.title = title;
this.text = text;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,39 +0,0 @@
<?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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="@+id/dataItem_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transcriptMode="alwaysScroll"/>
<TextView
android:id="@+id/intro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="20sp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:gravity="center"
android:fontFamily="sans-serif-condensed-light"
android:text="@string/intro" />
</RelativeLayout>

View File

@@ -1,20 +0,0 @@
<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Data Layer Sample Wearable App</string>
<string name="intro">Waiting for data to arrive\u2026</string>
</resources>

View File

@@ -1,15 +0,0 @@
<p><b>About:</b> You can cause the wearable to start an activity by pressing a button in the
companion app UI. You can also take a picture on the companion device, which will be transmitted as
an Asset for display on the wearable.</p>
<p><b>How to run:</b> Install the Application APK on the companion, and the Wearable APK on the
wearable. Start the sample by running the DataLayer application on the companion.</p>
<p><b>Wearable APIs used:</b> DataApi, MessageApi, NodeApi, WearableListenerService</p>
<p><b>Screenshots:</b>
<figure>
<img src="screenshots/phone_image.png" alt="Phone Image" width="216" height="384">
<img src="screenshots/wearable_background_image.png" alt="Wearable Background Image"
width="140" height="140">
<figcaption>Image captured on the phone, followed by the same image on the wearable.
</figcaption>
</figure>
</p>

View File

@@ -1,14 +0,0 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.+'
}
}
allprojects {
repositories {
mavenCentral()
}
}

View File

@@ -1,6 +0,0 @@
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip

View File

@@ -1,164 +0,0 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@@ -1,90 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

View File

@@ -1 +0,0 @@
include 'Application', 'Wearable'

View File

@@ -1,25 +0,0 @@
apply plugin: 'android'
android {
compileSdkVersion 18
buildToolsVersion '20'
defaultConfig {
minSdkVersion 18
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.google.android.gms:play-services:5.0.+'
wearApp project(':Wearable')
}

View File

@@ -1,20 +0,0 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@@ -1,39 +0,0 @@
<?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.delayedconfirmation" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,134 +0,0 @@
/*
* 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.delayedconfirmation;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
/**
* Has a single button, used to start the Wearable MainActivity.
*/
public class MainActivity extends Activity implements MessageApi.MessageListener,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "DelayedConfirmation";
private static final String START_ACTIVITY_PATH = "/start-activity";
private static final String TIMER_SELECTED_PATH = "/timer_selected";
private static final String TIMER_FINISHED_PATH = "/timer_finished";
private GoogleApiClient mGoogleApiClient;
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.main_activity);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onResume() {
super.onResume();
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
@Override
protected void onDestroy() {
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
super.onDestroy();
}
@Override
public void onConnected(Bundle bundle) {
Wearable.MessageApi.addListener(mGoogleApiClient, this);
}
@Override
public void onConnectionSuspended(int i) {
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
}
@Override
public void onMessageReceived(final MessageEvent messageEvent) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (messageEvent.getPath().equals(TIMER_SELECTED_PATH)) {
Toast.makeText(getApplicationContext(), R.string.toast_timer_selected,
Toast.LENGTH_SHORT).show();
} else if (messageEvent.getPath().equals(TIMER_FINISHED_PATH)) {
Toast.makeText(getApplicationContext(), R.string.toast_timer_finished,
Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "Failed to connect to Google Api Client with error code "
+ connectionResult.getErrorCode());
}
/**
* Sends a message to Wearable MainActivity when button is pressed.
*/
public void onStartWearableActivityClick(View view) {
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(
new ResultCallback<NodeApi.GetConnectedNodesResult>() {
@Override
public void onResult(NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
for (final Node node : getConnectedNodesResult.getNodes()) {
Wearable.MessageApi.sendMessage(
mGoogleApiClient, node.getId(), START_ACTIVITY_PATH, new byte[0])
.setResultCallback(getSendMessageResultCallback());
}
}
});
}
private ResultCallback<MessageApi.SendMessageResult> getSendMessageResultCallback() {
return new ResultCallback<MessageApi.SendMessageResult>() {
@Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
if (!sendMessageResult.getStatus().isSuccess()) {
Log.e(TAG, "Failed to connect to Google Api Client with status "
+ sendMessageResult.getStatus());
}
}
};
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,34 +0,0 @@
<?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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/text_start_wearable_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="@string/start_wearable_activity" />
<Button
android:id="@+id/start_wearable_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="150dp"
android:onClick="onStartWearableActivityClick"
android:text="@string/start"/>
</LinearLayout>

View File

@@ -1,24 +0,0 @@
<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Delayed Confirmation Sample App</string>
<string name="start_wearable_activity">Start Wearable Activity</string>
<string name="start">Start</string>
<string name="toast_timer_selected">Timer Selected</string>
<string name="toast_timer_finished">Timer Finished</string>
</resources>

View File

@@ -1,25 +0,0 @@
apply plugin: 'android'
android {
compileSdkVersion 20
buildToolsVersion '20'
defaultConfig {
minSdkVersion 20
targetSdkVersion 20
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.google.android.gms:play-services-wearable:+'
compile "com.google.android.support:wearable:1.0.+"
}

View File

@@ -1,21 +0,0 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-dontwarn android.support.wearable.view.DelayedConfirmationView

View File

@@ -1,44 +0,0 @@
<?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.delayedconfirmation" >
<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=".WearableMessageListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<activity
android:name=".MainActivity"
android:label="@string/app_name">
</activity>
</application>
</manifest>

View File

@@ -1,143 +0,0 @@
/*
* 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.delayedconfirmation;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.os.Bundle;
import android.support.wearable.view.DelayedConfirmationView;
import android.util.Log;
import android.view.View;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
public class MainActivity extends Activity implements
DelayedConfirmationView.DelayedConfirmationListener,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "DelayedConfirmation";
private static final int NUM_SECONDS = 5;
private static final String TIMER_SELECTED_PATH = "/timer_selected";
private static final String TIMER_FINISHED_PATH = "/timer_finished";
private DelayedConfirmationView delayedConfirmationView;
private GoogleApiClient mGoogleApiClient;
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.main_activity);
delayedConfirmationView = (DelayedConfirmationView) findViewById(R.id.delayed_confirmation);
delayedConfirmationView.setTotalTimeMs(NUM_SECONDS * 1000);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onResume() {
super.onResume();
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
@Override
protected void onDestroy() {
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
super.onDestroy();
}
/**
* Starts the DelayedConfirmationView when user presses "Start Timer" button.
*/
public void onStartTimer(View view) {
delayedConfirmationView.start();
delayedConfirmationView.setListener(this);
}
@Override
public void onTimerSelected(View v) {
v.setPressed(true);
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getString(R.string.notification_title))
.setContentText(getString(R.string.notification_timer_selected))
.build();
((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).notify(0, notification);
sendMessageToCompanion(TIMER_SELECTED_PATH);
// Prevent onTimerFinished from being heard.
((DelayedConfirmationView) v).setListener(null);
finish();
}
@Override
public void onTimerFinished(View v) {
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getString(R.string.notification_title))
.setContentText(getString(R.string.notification_timer_finished))
.build();
((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).notify(0, notification);
sendMessageToCompanion(TIMER_FINISHED_PATH);
finish();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "Failed to connect to Google Api Client");
}
private void sendMessageToCompanion(final String path) {
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(
new ResultCallback<NodeApi.GetConnectedNodesResult>() {
@Override
public void onResult(NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
for (final Node node : getConnectedNodesResult.getNodes()) {
Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), path,
new byte[0]).setResultCallback(getSendMessageResultCallback());
}
}
}
);
}
private ResultCallback<MessageApi.SendMessageResult> getSendMessageResultCallback() {
return new ResultCallback<MessageApi.SendMessageResult>() {
@Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
if (!sendMessageResult.getStatus().isSuccess()) {
Log.e(TAG, "Failed to connect to Google Api Client with status "
+ sendMessageResult.getStatus());
}
}
};
}
}

View File

@@ -1,38 +0,0 @@
/*
* 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.delayedconfirmation;
import android.content.Intent;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.WearableListenerService;
/**
* Listens for a message telling it to start the Wearable MainActivity.
*/
public class WearableMessageListenerService extends WearableListenerService {
private static final String START_ACTIVITY_PATH = "/start-activity";
@Override
public void onMessageReceived(MessageEvent event) {
if (event.getPath().equals(START_ACTIVITY_PATH)) {
Intent startIntent = new Intent(this, MainActivity.class);
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startIntent);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,50 +0,0 @@
<?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.
-->
<android.support.wearable.view.BoxInsetLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/grey"
app:layout_box="top">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onStartTimer"
android:text="@string/start_timer"/>
<android.support.wearable.view.DelayedConfirmationView
android:id="@+id/delayed_confirmation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_launcher"
app:circle_color="@color/blue"
app:circle_radius="@dimen/circle_radius"
app:circle_radius_pressed="@dimen/circle_radius_pressed"
app:circle_padding="@dimen/circle_padding"
app:circle_border_width="@dimen/circle_border_normal_width"
app:circle_border_color="@color/white"/>
</LinearLayout>
</android.support.wearable.view.BoxInsetLayout>

View File

@@ -1,22 +0,0 @@
<?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>
<dimen name="circle_border_normal_width">10dp</dimen>
<dimen name="circle_padding">5dp</dimen>
<dimen name="circle_radius">60dp</dimen>
<dimen name="circle_radius_pressed">55dp</dimen>
</resources>

Some files were not shown because too many files have changed in this diff Show More