am f420ff0d: Add browseable samples for Clockwork Beryl
* commit 'f420ff0d80e9e44e1744602e832d29563d28312d': Add browseable samples for Clockwork Beryl
@@ -0,0 +1,48 @@
|
||||
<?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.agendadata">
|
||||
|
||||
<uses-sdk android:minSdkVersion="19"
|
||||
android:targetSdkVersion="19" />
|
||||
|
||||
<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"
|
||||
>
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.version"
|
||||
android:value="@integer/google_play_services_version" />
|
||||
|
||||
<activity
|
||||
android:name="com.example.android.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.agendadata.CalendarQueryService"/>
|
||||
</application>
|
||||
</manifest>
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 196 B |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 20 KiB |
36
samples/browseable/AgendaData/Application/res/layout/activity_main.xml
Executable file
@@ -0,0 +1,36 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout style="@style/Widget.SampleMessageTile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView style="@style/Widget.SampleMessage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/horizontal_page_margin"
|
||||
android:layout_marginRight="@dimen/horizontal_page_margin"
|
||||
android:layout_marginTop="@dimen/vertical_page_margin"
|
||||
android:layout_marginBottom="@dimen/vertical_page_margin"
|
||||
android:text="@string/intro_message" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Widget.SampleMessage">
|
||||
<item name="android:textAppearance">?android:textAppearanceLarge</item>
|
||||
<item name="android:lineSpacingMultiplier">1.2</item>
|
||||
<item name="android:shadowDy">-6.5</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">AgendaData</string>
|
||||
<string name="intro_message">
|
||||
<![CDATA[
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
]]>
|
||||
</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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="get_events">Sync calendar events to wearable</string>
|
||||
<string name="delete_events">Delete calendar events from wearable</string>
|
||||
<string name="log">Log</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
|
||||
|
||||
<dimen name="margin_tiny">4dp</dimen>
|
||||
<dimen name="margin_small">8dp</dimen>
|
||||
<dimen name="margin_medium">16dp</dimen>
|
||||
<dimen name="margin_large">32dp</dimen>
|
||||
<dimen name="margin_huge">64dp</dimen>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,42 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
|
||||
<style name="Theme.Base" parent="android:Theme.Light" />
|
||||
|
||||
<style name="Theme.Sample" parent="Theme.Base" />
|
||||
|
||||
<style name="AppTheme" parent="Theme.Sample" />
|
||||
<!-- Widget styling -->
|
||||
|
||||
<style name="Widget" />
|
||||
|
||||
<style name="Widget.SampleMessage">
|
||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
||||
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.SampleMessageTile">
|
||||
<item name="android:background">@drawable/tile</item>
|
||||
<item name="android:shadowColor">#7F000000</item>
|
||||
<item name="android:shadowDy">-3.5</item>
|
||||
<item name="android:shadowRadius">2</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* 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.agendadata;
|
||||
|
||||
|
||||
import static com.example.android.agendadata.Constants.TAG;
|
||||
import static com.example.android.agendadata.Constants.CONNECTION_TIME_OUT_MS;
|
||||
import static com.example.android.agendadata.Constants.CAL_DATA_ITEM_PATH_PREFIX;
|
||||
import static com.example.android.agendadata.Constants.ALL_DAY;
|
||||
import static com.example.android.agendadata.Constants.BEGIN;
|
||||
import static com.example.android.agendadata.Constants.DATA_ITEM_URI;
|
||||
import static com.example.android.agendadata.Constants.DESCRIPTION;
|
||||
import static com.example.android.agendadata.Constants.END;
|
||||
import static com.example.android.agendadata.Constants.EVENT_ID;
|
||||
import static com.example.android.agendadata.Constants.ID;
|
||||
import static com.example.android.agendadata.Constants.PROFILE_PIC;
|
||||
import static com.example.android.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.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";
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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.agendadata;
|
||||
|
||||
import static com.example.android.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.common.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import com.example.android.common.logger.Log;
|
||||
import com.example.android.common.logger.LogWrapper;
|
||||
|
||||
/**
|
||||
* Base launcher activity, to handle most of the common plumbing for samples.
|
||||
*/
|
||||
public class SampleActivityBase extends FragmentActivity {
|
||||
|
||||
public static final String TAG = "SampleActivityBase";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
initializeLogging();
|
||||
}
|
||||
|
||||
/** Set up targets to receive log data */
|
||||
public void initializeLogging() {
|
||||
// Using Log, front-end to the logging chain, emulates android.util.log method signatures.
|
||||
// Wraps Android's native log framework
|
||||
LogWrapper logWrapper = new LogWrapper();
|
||||
Log.setLogNode(logWrapper);
|
||||
|
||||
Log.i(TAG, "Ready");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.common.logger;
|
||||
|
||||
/**
|
||||
* Helper class for a list (or tree) of LoggerNodes.
|
||||
*
|
||||
* <p>When this is set as the head of the list,
|
||||
* an instance of it can function as a drop-in replacement for {@link android.util.Log}.
|
||||
* Most of the methods in this class server only to map a method call in Log to its equivalent
|
||||
* in LogNode.</p>
|
||||
*/
|
||||
public class Log {
|
||||
// Grabbing the native values from Android's native logging facilities,
|
||||
// to make for easy migration and interop.
|
||||
public static final int NONE = -1;
|
||||
public static final int VERBOSE = android.util.Log.VERBOSE;
|
||||
public static final int DEBUG = android.util.Log.DEBUG;
|
||||
public static final int INFO = android.util.Log.INFO;
|
||||
public static final int WARN = android.util.Log.WARN;
|
||||
public static final int ERROR = android.util.Log.ERROR;
|
||||
public static final int ASSERT = android.util.Log.ASSERT;
|
||||
|
||||
// Stores the beginning of the LogNode topology.
|
||||
private static LogNode mLogNode;
|
||||
|
||||
/**
|
||||
* Returns the next LogNode in the linked list.
|
||||
*/
|
||||
public static LogNode getLogNode() {
|
||||
return mLogNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LogNode data will be sent to.
|
||||
*/
|
||||
public static void setLogNode(LogNode node) {
|
||||
mLogNode = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the LogNode to print the log data provided. Other LogNodes can
|
||||
* be chained to the end of the LogNode as desired.
|
||||
*
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void println(int priority, String tag, String msg, Throwable tr) {
|
||||
if (mLogNode != null) {
|
||||
mLogNode.println(priority, tag, msg, tr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the LogNode to print the log data provided. Other LogNodes can
|
||||
* be chained to the end of the LogNode as desired.
|
||||
*
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
*/
|
||||
public static void println(int priority, String tag, String msg) {
|
||||
println(priority, tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at VERBOSE priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void v(String tag, String msg, Throwable tr) {
|
||||
println(VERBOSE, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at VERBOSE priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void v(String tag, String msg) {
|
||||
v(tag, msg, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints a message at DEBUG priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void d(String tag, String msg, Throwable tr) {
|
||||
println(DEBUG, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at DEBUG priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void d(String tag, String msg) {
|
||||
d(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at INFO priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void i(String tag, String msg, Throwable tr) {
|
||||
println(INFO, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at INFO priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void i(String tag, String msg) {
|
||||
i(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void w(String tag, String msg, Throwable tr) {
|
||||
println(WARN, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void w(String tag, String msg) {
|
||||
w(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void w(String tag, Throwable tr) {
|
||||
w(tag, null, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ERROR priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void e(String tag, String msg, Throwable tr) {
|
||||
println(ERROR, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ERROR priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void e(String tag, String msg) {
|
||||
e(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void wtf(String tag, String msg, Throwable tr) {
|
||||
println(ASSERT, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void wtf(String tag, String msg) {
|
||||
wtf(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void wtf(String tag, Throwable tr) {
|
||||
wtf(tag, null, tr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.common.logger;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
/**
|
||||
* Simple fraggment which contains a LogView and uses is to output log data it receives
|
||||
* through the LogNode interface.
|
||||
*/
|
||||
public class LogFragment extends Fragment {
|
||||
|
||||
private LogView mLogView;
|
||||
private ScrollView mScrollView;
|
||||
|
||||
public LogFragment() {}
|
||||
|
||||
public View inflateViews() {
|
||||
mScrollView = new ScrollView(getActivity());
|
||||
ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
mScrollView.setLayoutParams(scrollParams);
|
||||
|
||||
mLogView = new LogView(getActivity());
|
||||
ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
|
||||
logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
mLogView.setLayoutParams(logParams);
|
||||
mLogView.setClickable(true);
|
||||
mLogView.setFocusable(true);
|
||||
mLogView.setTypeface(Typeface.MONOSPACE);
|
||||
|
||||
// Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
|
||||
int paddingDips = 16;
|
||||
double scale = getResources().getDisplayMetrics().density;
|
||||
int paddingPixels = (int) ((paddingDips * (scale)) + .5);
|
||||
mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
|
||||
mLogView.setCompoundDrawablePadding(paddingPixels);
|
||||
|
||||
mLogView.setGravity(Gravity.BOTTOM);
|
||||
mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
|
||||
|
||||
mScrollView.addView(mLogView);
|
||||
return mScrollView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View result = inflateViews();
|
||||
|
||||
mLogView.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public LogView getLogView() {
|
||||
return mLogView;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.common.logger;
|
||||
|
||||
/**
|
||||
* Basic interface for a logging system that can output to one or more targets.
|
||||
* Note that in addition to classes that will output these logs in some format,
|
||||
* one can also implement this interface over a filter and insert that in the chain,
|
||||
* such that no targets further down see certain data, or see manipulated forms of the data.
|
||||
* You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
|
||||
* it received to HTML and sent it along to the next node in the chain, without printing it
|
||||
* anywhere.
|
||||
*/
|
||||
public interface LogNode {
|
||||
|
||||
/**
|
||||
* Instructs first LogNode in the list to print the log data provided.
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public void println(int priority, String tag, String msg, Throwable tr);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.common.logger;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.util.*;
|
||||
import android.widget.TextView;
|
||||
|
||||
/** Simple TextView which is used to output log data received through the LogNode interface.
|
||||
*/
|
||||
public class LogView extends TextView implements LogNode {
|
||||
|
||||
public LogView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LogView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LogView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the log data and prints it out to the LogView.
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
@Override
|
||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
||||
|
||||
|
||||
String priorityStr = null;
|
||||
|
||||
// For the purposes of this View, we want to print the priority as readable text.
|
||||
switch(priority) {
|
||||
case android.util.Log.VERBOSE:
|
||||
priorityStr = "VERBOSE";
|
||||
break;
|
||||
case android.util.Log.DEBUG:
|
||||
priorityStr = "DEBUG";
|
||||
break;
|
||||
case android.util.Log.INFO:
|
||||
priorityStr = "INFO";
|
||||
break;
|
||||
case android.util.Log.WARN:
|
||||
priorityStr = "WARN";
|
||||
break;
|
||||
case android.util.Log.ERROR:
|
||||
priorityStr = "ERROR";
|
||||
break;
|
||||
case android.util.Log.ASSERT:
|
||||
priorityStr = "ASSERT";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Handily, the Log class has a facility for converting a stack trace into a usable string.
|
||||
String exceptionStr = null;
|
||||
if (tr != null) {
|
||||
exceptionStr = android.util.Log.getStackTraceString(tr);
|
||||
}
|
||||
|
||||
// Take the priority, tag, message, and exception, and concatenate as necessary
|
||||
// into one usable line of text.
|
||||
final StringBuilder outputBuilder = new StringBuilder();
|
||||
|
||||
String delimiter = "\t";
|
||||
appendIfNotNull(outputBuilder, priorityStr, delimiter);
|
||||
appendIfNotNull(outputBuilder, tag, delimiter);
|
||||
appendIfNotNull(outputBuilder, msg, delimiter);
|
||||
appendIfNotNull(outputBuilder, exceptionStr, delimiter);
|
||||
|
||||
// In case this was originally called from an AsyncTask or some other off-UI thread,
|
||||
// make sure the update occurs within the UI thread.
|
||||
((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Display the text we just generated within the LogView.
|
||||
appendToLog(outputBuilder.toString());
|
||||
}
|
||||
})));
|
||||
|
||||
if (mNext != null) {
|
||||
mNext.println(priority, tag, msg, tr);
|
||||
}
|
||||
}
|
||||
|
||||
public LogNode getNext() {
|
||||
return mNext;
|
||||
}
|
||||
|
||||
public void setNext(LogNode node) {
|
||||
mNext = node;
|
||||
}
|
||||
|
||||
/** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
|
||||
* the logger takes so many arguments that might be null, this method helps cut out some of the
|
||||
* agonizing tedium of writing the same 3 lines over and over.
|
||||
* @param source StringBuilder containing the text to append to.
|
||||
* @param addStr The String to append
|
||||
* @param delimiter The String to separate the source and appended strings. A tab or comma,
|
||||
* for instance.
|
||||
* @return The fully concatenated String as a StringBuilder
|
||||
*/
|
||||
private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
|
||||
if (addStr != null) {
|
||||
if (addStr.length() == 0) {
|
||||
delimiter = "";
|
||||
}
|
||||
|
||||
return source.append(addStr).append(delimiter);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
// The next LogNode in the chain.
|
||||
LogNode mNext;
|
||||
|
||||
/** Outputs the string as a new line of log data in the LogView. */
|
||||
public void appendToLog(String s) {
|
||||
append("\n" + s);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.common.logger;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Helper class which wraps Android's native Log utility in the Logger interface. This way
|
||||
* normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
|
||||
*/
|
||||
public class LogWrapper implements LogNode {
|
||||
|
||||
// For piping: The next node to receive Log data after this one has done its work.
|
||||
private LogNode mNext;
|
||||
|
||||
/**
|
||||
* Returns the next LogNode in the linked list.
|
||||
*/
|
||||
public LogNode getNext() {
|
||||
return mNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LogNode data will be sent to..
|
||||
*/
|
||||
public void setNext(LogNode node) {
|
||||
mNext = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints data out to the console using Android's native log mechanism.
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
@Override
|
||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
||||
// There actually are log methods that don't take a msg parameter. For now,
|
||||
// if that's the case, just convert null to the empty string and move on.
|
||||
String useMsg = msg;
|
||||
if (useMsg == null) {
|
||||
useMsg = "";
|
||||
}
|
||||
|
||||
// If an exeption was provided, convert that exception to a usable string and attach
|
||||
// it to the end of the msg method.
|
||||
if (tr != null) {
|
||||
msg += "\n" + Log.getStackTraceString(tr);
|
||||
}
|
||||
|
||||
// This is functionally identical to Log.x(tag, useMsg);
|
||||
// For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
|
||||
Log.println(priority, tag, useMsg);
|
||||
|
||||
// If this isn't the last node in the chain, move things along.
|
||||
if (mNext != null) {
|
||||
mNext.println(priority, tag, msg, tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.common.logger;
|
||||
|
||||
/**
|
||||
* Simple {@link LogNode} filter, removes everything except the message.
|
||||
* Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
|
||||
* just easy-to-read message updates as they're happening.
|
||||
*/
|
||||
public class MessageOnlyLogFilter implements LogNode {
|
||||
|
||||
LogNode mNext;
|
||||
|
||||
/**
|
||||
* Takes the "next" LogNode as a parameter, to simplify chaining.
|
||||
*
|
||||
* @param next The next LogNode in the pipeline.
|
||||
*/
|
||||
public MessageOnlyLogFilter(LogNode next) {
|
||||
mNext = next;
|
||||
}
|
||||
|
||||
public MessageOnlyLogFilter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
||||
if (mNext != null) {
|
||||
getNext().println(Log.NONE, null, msg, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next LogNode in the chain.
|
||||
*/
|
||||
public LogNode getNext() {
|
||||
return mNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LogNode data will be sent to..
|
||||
*/
|
||||
public void setNext(LogNode node) {
|
||||
mNext = node;
|
||||
}
|
||||
|
||||
}
|
||||
25
samples/browseable/AgendaData/Shared/AndroidManifest.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.android.agendadata.common">
|
||||
|
||||
<application android:allowBackup="true"
|
||||
android:label="@string/app_name">
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
18
samples/browseable/AgendaData/Shared/res/values/strings.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">Shared</string>
|
||||
</resources>
|
||||
46
samples/browseable/AgendaData/Wearable/AndroidManifest.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?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.agendadata" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="20"
|
||||
android:targetSdkVersion="20" />
|
||||
|
||||
<uses-feature android:name="android.hardware.type.watch" />
|
||||
|
||||
<application
|
||||
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" />
|
||||
|
||||
<service
|
||||
android:name="com.example.android.agendadata.HomeListenerService" >
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service android:name="com.example.android.agendadata.DeleteService"/>
|
||||
|
||||
<activity android:name="android.support.wearable.activity.ConfirmationActivity"/>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 967 B |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,24 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.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";
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.agendadata;
|
||||
|
||||
import static com.example.android.agendadata.Constants.TAG;
|
||||
import static com.example.android.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) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.agendadata;
|
||||
|
||||
import static com.example.android.agendadata.Constants.TAG;
|
||||
import static com.example.android.agendadata.Constants.EXTRA_SILENT;
|
||||
|
||||
import static com.example.android.agendadata.Constants.ALL_DAY;
|
||||
import static com.example.android.agendadata.Constants.BEGIN;
|
||||
import static com.example.android.agendadata.Constants.DESCRIPTION;
|
||||
import static com.example.android.agendadata.Constants.END;
|
||||
import static com.example.android.agendadata.Constants.PROFILE_PIC;
|
||||
import static com.example.android.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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
13
samples/browseable/AgendaData/_index.jd
Normal file
@@ -0,0 +1,13 @@
|
||||
page.tags="AgendaData"
|
||||
sample.group=Wearable
|
||||
@jd:body
|
||||
|
||||
<p>
|
||||
|
||||
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>
|
||||
44
samples/browseable/DataLayer/Application/AndroidManifest.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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.datalayer" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="19"
|
||||
android:targetSdkVersion="19" />
|
||||
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
BIN
samples/browseable/DataLayer/Application/res/drawable-hdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 196 B |
|
After Width: | Height: | Size: 896 B |
BIN
samples/browseable/DataLayer/Application/res/drawable-mdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
BIN
samples/browseable/DataLayer/Application/res/drawable-xhdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
BIN
samples/browseable/DataLayer/Application/res/drawable-xxhdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,20 @@
|
||||
<?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>
|
||||
36
samples/browseable/DataLayer/Application/res/layout/activity_main.xml
Executable file
@@ -0,0 +1,36 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout style="@style/Widget.SampleMessageTile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView style="@style/Widget.SampleMessage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/horizontal_page_margin"
|
||||
android:layout_marginRight="@dimen/horizontal_page_margin"
|
||||
android:layout_marginTop="@dimen/vertical_page_margin"
|
||||
android:layout_marginBottom="@dimen/vertical_page_margin"
|
||||
android:text="@string/intro_message" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,86 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Widget.SampleMessage">
|
||||
<item name="android:textAppearance">?android:textAppearanceLarge</item>
|
||||
<item name="android:lineSpacingMultiplier">1.2</item>
|
||||
<item name="android:shadowDy">-6.5</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">DataLayer</string>
|
||||
<string name="intro_message">
|
||||
<![CDATA[
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
]]>
|
||||
</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?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="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>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
|
||||
|
||||
<dimen name="margin_tiny">4dp</dimen>
|
||||
<dimen name="margin_small">8dp</dimen>
|
||||
<dimen name="margin_medium">16dp</dimen>
|
||||
<dimen name="margin_large">32dp</dimen>
|
||||
<dimen name="margin_huge">64dp</dimen>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,42 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
|
||||
<style name="Theme.Base" parent="android:Theme.Light" />
|
||||
|
||||
<style name="Theme.Sample" parent="Theme.Base" />
|
||||
|
||||
<style name="AppTheme" parent="Theme.Sample" />
|
||||
<!-- Widget styling -->
|
||||
|
||||
<style name="Widget" />
|
||||
|
||||
<style name="Widget.SampleMessage">
|
||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
||||
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.SampleMessageTile">
|
||||
<item name="android:background">@drawable/tile</item>
|
||||
<item name="android:shadowColor">#7F000000</item>
|
||||
<item name="android:shadowDy">-3.5</item>
|
||||
<item name="android:shadowRadius">2</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.common.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import com.example.android.common.logger.Log;
|
||||
import com.example.android.common.logger.LogWrapper;
|
||||
|
||||
/**
|
||||
* Base launcher activity, to handle most of the common plumbing for samples.
|
||||
*/
|
||||
public class SampleActivityBase extends FragmentActivity {
|
||||
|
||||
public static final String TAG = "SampleActivityBase";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
initializeLogging();
|
||||
}
|
||||
|
||||
/** Set up targets to receive log data */
|
||||
public void initializeLogging() {
|
||||
// Using Log, front-end to the logging chain, emulates android.util.log method signatures.
|
||||
// Wraps Android's native log framework
|
||||
LogWrapper logWrapper = new LogWrapper();
|
||||
Log.setLogNode(logWrapper);
|
||||
|
||||
Log.i(TAG, "Ready");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.common.logger;
|
||||
|
||||
/**
|
||||
* Helper class for a list (or tree) of LoggerNodes.
|
||||
*
|
||||
* <p>When this is set as the head of the list,
|
||||
* an instance of it can function as a drop-in replacement for {@link android.util.Log}.
|
||||
* Most of the methods in this class server only to map a method call in Log to its equivalent
|
||||
* in LogNode.</p>
|
||||
*/
|
||||
public class Log {
|
||||
// Grabbing the native values from Android's native logging facilities,
|
||||
// to make for easy migration and interop.
|
||||
public static final int NONE = -1;
|
||||
public static final int VERBOSE = android.util.Log.VERBOSE;
|
||||
public static final int DEBUG = android.util.Log.DEBUG;
|
||||
public static final int INFO = android.util.Log.INFO;
|
||||
public static final int WARN = android.util.Log.WARN;
|
||||
public static final int ERROR = android.util.Log.ERROR;
|
||||
public static final int ASSERT = android.util.Log.ASSERT;
|
||||
|
||||
// Stores the beginning of the LogNode topology.
|
||||
private static LogNode mLogNode;
|
||||
|
||||
/**
|
||||
* Returns the next LogNode in the linked list.
|
||||
*/
|
||||
public static LogNode getLogNode() {
|
||||
return mLogNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LogNode data will be sent to.
|
||||
*/
|
||||
public static void setLogNode(LogNode node) {
|
||||
mLogNode = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the LogNode to print the log data provided. Other LogNodes can
|
||||
* be chained to the end of the LogNode as desired.
|
||||
*
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void println(int priority, String tag, String msg, Throwable tr) {
|
||||
if (mLogNode != null) {
|
||||
mLogNode.println(priority, tag, msg, tr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the LogNode to print the log data provided. Other LogNodes can
|
||||
* be chained to the end of the LogNode as desired.
|
||||
*
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
*/
|
||||
public static void println(int priority, String tag, String msg) {
|
||||
println(priority, tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at VERBOSE priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void v(String tag, String msg, Throwable tr) {
|
||||
println(VERBOSE, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at VERBOSE priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void v(String tag, String msg) {
|
||||
v(tag, msg, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints a message at DEBUG priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void d(String tag, String msg, Throwable tr) {
|
||||
println(DEBUG, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at DEBUG priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void d(String tag, String msg) {
|
||||
d(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at INFO priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void i(String tag, String msg, Throwable tr) {
|
||||
println(INFO, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at INFO priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void i(String tag, String msg) {
|
||||
i(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void w(String tag, String msg, Throwable tr) {
|
||||
println(WARN, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void w(String tag, String msg) {
|
||||
w(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void w(String tag, Throwable tr) {
|
||||
w(tag, null, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ERROR priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void e(String tag, String msg, Throwable tr) {
|
||||
println(ERROR, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ERROR priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void e(String tag, String msg) {
|
||||
e(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void wtf(String tag, String msg, Throwable tr) {
|
||||
println(ASSERT, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void wtf(String tag, String msg) {
|
||||
wtf(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void wtf(String tag, Throwable tr) {
|
||||
wtf(tag, null, tr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.common.logger;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
/**
|
||||
* Simple fraggment which contains a LogView and uses is to output log data it receives
|
||||
* through the LogNode interface.
|
||||
*/
|
||||
public class LogFragment extends Fragment {
|
||||
|
||||
private LogView mLogView;
|
||||
private ScrollView mScrollView;
|
||||
|
||||
public LogFragment() {}
|
||||
|
||||
public View inflateViews() {
|
||||
mScrollView = new ScrollView(getActivity());
|
||||
ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
mScrollView.setLayoutParams(scrollParams);
|
||||
|
||||
mLogView = new LogView(getActivity());
|
||||
ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
|
||||
logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
mLogView.setLayoutParams(logParams);
|
||||
mLogView.setClickable(true);
|
||||
mLogView.setFocusable(true);
|
||||
mLogView.setTypeface(Typeface.MONOSPACE);
|
||||
|
||||
// Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
|
||||
int paddingDips = 16;
|
||||
double scale = getResources().getDisplayMetrics().density;
|
||||
int paddingPixels = (int) ((paddingDips * (scale)) + .5);
|
||||
mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
|
||||
mLogView.setCompoundDrawablePadding(paddingPixels);
|
||||
|
||||
mLogView.setGravity(Gravity.BOTTOM);
|
||||
mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
|
||||
|
||||
mScrollView.addView(mLogView);
|
||||
return mScrollView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View result = inflateViews();
|
||||
|
||||
mLogView.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public LogView getLogView() {
|
||||
return mLogView;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.common.logger;
|
||||
|
||||
/**
|
||||
* Basic interface for a logging system that can output to one or more targets.
|
||||
* Note that in addition to classes that will output these logs in some format,
|
||||
* one can also implement this interface over a filter and insert that in the chain,
|
||||
* such that no targets further down see certain data, or see manipulated forms of the data.
|
||||
* You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
|
||||
* it received to HTML and sent it along to the next node in the chain, without printing it
|
||||
* anywhere.
|
||||
*/
|
||||
public interface LogNode {
|
||||
|
||||
/**
|
||||
* Instructs first LogNode in the list to print the log data provided.
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public void println(int priority, String tag, String msg, Throwable tr);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.common.logger;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.util.*;
|
||||
import android.widget.TextView;
|
||||
|
||||
/** Simple TextView which is used to output log data received through the LogNode interface.
|
||||
*/
|
||||
public class LogView extends TextView implements LogNode {
|
||||
|
||||
public LogView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LogView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LogView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the log data and prints it out to the LogView.
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
@Override
|
||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
||||
|
||||
|
||||
String priorityStr = null;
|
||||
|
||||
// For the purposes of this View, we want to print the priority as readable text.
|
||||
switch(priority) {
|
||||
case android.util.Log.VERBOSE:
|
||||
priorityStr = "VERBOSE";
|
||||
break;
|
||||
case android.util.Log.DEBUG:
|
||||
priorityStr = "DEBUG";
|
||||
break;
|
||||
case android.util.Log.INFO:
|
||||
priorityStr = "INFO";
|
||||
break;
|
||||
case android.util.Log.WARN:
|
||||
priorityStr = "WARN";
|
||||
break;
|
||||
case android.util.Log.ERROR:
|
||||
priorityStr = "ERROR";
|
||||
break;
|
||||
case android.util.Log.ASSERT:
|
||||
priorityStr = "ASSERT";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Handily, the Log class has a facility for converting a stack trace into a usable string.
|
||||
String exceptionStr = null;
|
||||
if (tr != null) {
|
||||
exceptionStr = android.util.Log.getStackTraceString(tr);
|
||||
}
|
||||
|
||||
// Take the priority, tag, message, and exception, and concatenate as necessary
|
||||
// into one usable line of text.
|
||||
final StringBuilder outputBuilder = new StringBuilder();
|
||||
|
||||
String delimiter = "\t";
|
||||
appendIfNotNull(outputBuilder, priorityStr, delimiter);
|
||||
appendIfNotNull(outputBuilder, tag, delimiter);
|
||||
appendIfNotNull(outputBuilder, msg, delimiter);
|
||||
appendIfNotNull(outputBuilder, exceptionStr, delimiter);
|
||||
|
||||
// In case this was originally called from an AsyncTask or some other off-UI thread,
|
||||
// make sure the update occurs within the UI thread.
|
||||
((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Display the text we just generated within the LogView.
|
||||
appendToLog(outputBuilder.toString());
|
||||
}
|
||||
})));
|
||||
|
||||
if (mNext != null) {
|
||||
mNext.println(priority, tag, msg, tr);
|
||||
}
|
||||
}
|
||||
|
||||
public LogNode getNext() {
|
||||
return mNext;
|
||||
}
|
||||
|
||||
public void setNext(LogNode node) {
|
||||
mNext = node;
|
||||
}
|
||||
|
||||
/** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
|
||||
* the logger takes so many arguments that might be null, this method helps cut out some of the
|
||||
* agonizing tedium of writing the same 3 lines over and over.
|
||||
* @param source StringBuilder containing the text to append to.
|
||||
* @param addStr The String to append
|
||||
* @param delimiter The String to separate the source and appended strings. A tab or comma,
|
||||
* for instance.
|
||||
* @return The fully concatenated String as a StringBuilder
|
||||
*/
|
||||
private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
|
||||
if (addStr != null) {
|
||||
if (addStr.length() == 0) {
|
||||
delimiter = "";
|
||||
}
|
||||
|
||||
return source.append(addStr).append(delimiter);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
// The next LogNode in the chain.
|
||||
LogNode mNext;
|
||||
|
||||
/** Outputs the string as a new line of log data in the LogView. */
|
||||
public void appendToLog(String s) {
|
||||
append("\n" + s);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.common.logger;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Helper class which wraps Android's native Log utility in the Logger interface. This way
|
||||
* normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
|
||||
*/
|
||||
public class LogWrapper implements LogNode {
|
||||
|
||||
// For piping: The next node to receive Log data after this one has done its work.
|
||||
private LogNode mNext;
|
||||
|
||||
/**
|
||||
* Returns the next LogNode in the linked list.
|
||||
*/
|
||||
public LogNode getNext() {
|
||||
return mNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LogNode data will be sent to..
|
||||
*/
|
||||
public void setNext(LogNode node) {
|
||||
mNext = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints data out to the console using Android's native log mechanism.
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
@Override
|
||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
||||
// There actually are log methods that don't take a msg parameter. For now,
|
||||
// if that's the case, just convert null to the empty string and move on.
|
||||
String useMsg = msg;
|
||||
if (useMsg == null) {
|
||||
useMsg = "";
|
||||
}
|
||||
|
||||
// If an exeption was provided, convert that exception to a usable string and attach
|
||||
// it to the end of the msg method.
|
||||
if (tr != null) {
|
||||
msg += "\n" + Log.getStackTraceString(tr);
|
||||
}
|
||||
|
||||
// This is functionally identical to Log.x(tag, useMsg);
|
||||
// For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
|
||||
Log.println(priority, tag, useMsg);
|
||||
|
||||
// If this isn't the last node in the chain, move things along.
|
||||
if (mNext != null) {
|
||||
mNext.println(priority, tag, msg, tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.common.logger;
|
||||
|
||||
/**
|
||||
* Simple {@link LogNode} filter, removes everything except the message.
|
||||
* Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
|
||||
* just easy-to-read message updates as they're happening.
|
||||
*/
|
||||
public class MessageOnlyLogFilter implements LogNode {
|
||||
|
||||
LogNode mNext;
|
||||
|
||||
/**
|
||||
* Takes the "next" LogNode as a parameter, to simplify chaining.
|
||||
*
|
||||
* @param next The next LogNode in the pipeline.
|
||||
*/
|
||||
public MessageOnlyLogFilter(LogNode next) {
|
||||
mNext = next;
|
||||
}
|
||||
|
||||
public MessageOnlyLogFilter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
||||
if (mNext != null) {
|
||||
getNext().println(Log.NONE, null, msg, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next LogNode in the chain.
|
||||
*/
|
||||
public LogNode getNext() {
|
||||
return mNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LogNode data will be sent to..
|
||||
*/
|
||||
public void setNext(LogNode node) {
|
||||
mNext = node;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* 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.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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
25
samples/browseable/DataLayer/Shared/AndroidManifest.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.android.datalayer.common">
|
||||
|
||||
<application android:allowBackup="true"
|
||||
android:label="@string/app_name">
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
18
samples/browseable/DataLayer/Shared/res/values/strings.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">Shared</string>
|
||||
</resources>
|
||||
55
samples/browseable/DataLayer/Wearable/AndroidManifest.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?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.datalayer" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="20"
|
||||
android:targetSdkVersion="20" />
|
||||
|
||||
<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.datalayer.EXAMPLE"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
BIN
samples/browseable/DataLayer/Wearable/res/drawable-hdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
samples/browseable/DataLayer/Wearable/res/drawable-mdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
samples/browseable/DataLayer/Wearable/res/drawable-xhdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
samples/browseable/DataLayer/Wearable/res/drawable-xxhdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,39 @@
|
||||
<?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>
|
||||
20
samples/browseable/DataLayer/Wearable/res/values/strings.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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.datalayer;
|
||||
|
||||
import static com.example.android.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
samples/browseable/DataLayer/_index.jd
Normal file
@@ -0,0 +1,11 @@
|
||||
page.tags="DataLayer"
|
||||
sample.group=Wearable
|
||||
@jd:body
|
||||
|
||||
<p>
|
||||
|
||||
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>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.android.delayedconfirmation" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="19"
|
||||
android:targetSdkVersion="19" />
|
||||
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 196 B |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,36 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout style="@style/Widget.SampleMessageTile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView style="@style/Widget.SampleMessage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/horizontal_page_margin"
|
||||
android:layout_marginRight="@dimen/horizontal_page_margin"
|
||||
android:layout_marginTop="@dimen/vertical_page_margin"
|
||||
android:layout_marginBottom="@dimen/vertical_page_margin"
|
||||
android:text="@string/intro_message" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Widget.SampleMessage">
|
||||
<item name="android:textAppearance">?android:textAppearanceLarge</item>
|
||||
<item name="android:lineSpacingMultiplier">1.2</item>
|
||||
<item name="android:shadowDy">-6.5</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">DelayedConfirmation</string>
|
||||
<string name="intro_message">
|
||||
<![CDATA[
|
||||
|
||||
|
||||
Demonstrates how to create a DelayedConfirmationView in your wearable app. In this
|
||||
sample, pressing a button on the phone app sends a message to the wearable to start a simple
|
||||
activity. This activity displays a DelayedConfirmationView that starts when the user presses "Start
|
||||
Timer." Then, callbacks are implemented on both the wearable and phone to show when the timer is
|
||||
selected or finishes. The activity on the wearable uses BoxInsetLayout to automatically apply
|
||||
appropriate margins based on whether the display is square or circular.
|
||||
|
||||
|
||||
]]>
|
||||
</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?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="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>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
|
||||
|
||||
<dimen name="margin_tiny">4dp</dimen>
|
||||
<dimen name="margin_small">8dp</dimen>
|
||||
<dimen name="margin_medium">16dp</dimen>
|
||||
<dimen name="margin_large">32dp</dimen>
|
||||
<dimen name="margin_huge">64dp</dimen>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,42 @@
|
||||
<!--
|
||||
Copyright 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Activity themes -->
|
||||
|
||||
<style name="Theme.Base" parent="android:Theme.Light" />
|
||||
|
||||
<style name="Theme.Sample" parent="Theme.Base" />
|
||||
|
||||
<style name="AppTheme" parent="Theme.Sample" />
|
||||
<!-- Widget styling -->
|
||||
|
||||
<style name="Widget" />
|
||||
|
||||
<style name="Widget.SampleMessage">
|
||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
||||
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.SampleMessageTile">
|
||||
<item name="android:background">@drawable/tile</item>
|
||||
<item name="android:shadowColor">#7F000000</item>
|
||||
<item name="android:shadowDy">-3.5</item>
|
||||
<item name="android:shadowRadius">2</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.common.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import com.example.android.common.logger.Log;
|
||||
import com.example.android.common.logger.LogWrapper;
|
||||
|
||||
/**
|
||||
* Base launcher activity, to handle most of the common plumbing for samples.
|
||||
*/
|
||||
public class SampleActivityBase extends FragmentActivity {
|
||||
|
||||
public static final String TAG = "SampleActivityBase";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
initializeLogging();
|
||||
}
|
||||
|
||||
/** Set up targets to receive log data */
|
||||
public void initializeLogging() {
|
||||
// Using Log, front-end to the logging chain, emulates android.util.log method signatures.
|
||||
// Wraps Android's native log framework
|
||||
LogWrapper logWrapper = new LogWrapper();
|
||||
Log.setLogNode(logWrapper);
|
||||
|
||||
Log.i(TAG, "Ready");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.common.logger;
|
||||
|
||||
/**
|
||||
* Helper class for a list (or tree) of LoggerNodes.
|
||||
*
|
||||
* <p>When this is set as the head of the list,
|
||||
* an instance of it can function as a drop-in replacement for {@link android.util.Log}.
|
||||
* Most of the methods in this class server only to map a method call in Log to its equivalent
|
||||
* in LogNode.</p>
|
||||
*/
|
||||
public class Log {
|
||||
// Grabbing the native values from Android's native logging facilities,
|
||||
// to make for easy migration and interop.
|
||||
public static final int NONE = -1;
|
||||
public static final int VERBOSE = android.util.Log.VERBOSE;
|
||||
public static final int DEBUG = android.util.Log.DEBUG;
|
||||
public static final int INFO = android.util.Log.INFO;
|
||||
public static final int WARN = android.util.Log.WARN;
|
||||
public static final int ERROR = android.util.Log.ERROR;
|
||||
public static final int ASSERT = android.util.Log.ASSERT;
|
||||
|
||||
// Stores the beginning of the LogNode topology.
|
||||
private static LogNode mLogNode;
|
||||
|
||||
/**
|
||||
* Returns the next LogNode in the linked list.
|
||||
*/
|
||||
public static LogNode getLogNode() {
|
||||
return mLogNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LogNode data will be sent to.
|
||||
*/
|
||||
public static void setLogNode(LogNode node) {
|
||||
mLogNode = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the LogNode to print the log data provided. Other LogNodes can
|
||||
* be chained to the end of the LogNode as desired.
|
||||
*
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void println(int priority, String tag, String msg, Throwable tr) {
|
||||
if (mLogNode != null) {
|
||||
mLogNode.println(priority, tag, msg, tr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the LogNode to print the log data provided. Other LogNodes can
|
||||
* be chained to the end of the LogNode as desired.
|
||||
*
|
||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged. The actual message to be logged.
|
||||
*/
|
||||
public static void println(int priority, String tag, String msg) {
|
||||
println(priority, tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at VERBOSE priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void v(String tag, String msg, Throwable tr) {
|
||||
println(VERBOSE, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at VERBOSE priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void v(String tag, String msg) {
|
||||
v(tag, msg, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints a message at DEBUG priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void d(String tag, String msg, Throwable tr) {
|
||||
println(DEBUG, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at DEBUG priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void d(String tag, String msg) {
|
||||
d(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at INFO priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void i(String tag, String msg, Throwable tr) {
|
||||
println(INFO, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at INFO priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void i(String tag, String msg) {
|
||||
i(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void w(String tag, String msg, Throwable tr) {
|
||||
println(WARN, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void w(String tag, String msg) {
|
||||
w(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at WARN priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void w(String tag, Throwable tr) {
|
||||
w(tag, null, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ERROR priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void e(String tag, String msg, Throwable tr) {
|
||||
println(ERROR, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ERROR priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void e(String tag, String msg) {
|
||||
e(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void wtf(String tag, String msg, Throwable tr) {
|
||||
println(ASSERT, tag, msg, tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param msg The actual message to be logged.
|
||||
*/
|
||||
public static void wtf(String tag, String msg) {
|
||||
wtf(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message at ASSERT priority.
|
||||
*
|
||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
||||
* to extract and print useful information.
|
||||
*/
|
||||
public static void wtf(String tag, Throwable tr) {
|
||||
wtf(tag, null, tr);
|
||||
}
|
||||
}
|
||||