On Github justinribeiro / android-wear-introduction-gdg-devfest-2014
Justin Ribeiro justin@stickmanventures.com
@justinribeiro +Justin Ribeiro justinribeiro
Slides: https://goo.gl/dsbkIQ
Source: Engadget - "Microsoft's Android Wear keyboard has you drawing every letter"
Think about those seconds
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationManagerCompat; import android.support.v4.app.NotificationCompat.WearableExtender;
// Let's build a notification
NotificationCompat.Builder myNotification =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_event)
.setContentTitle("I'm a title!")
.setContentText("DevFest 2014 Whooo Hooo")
.setContentIntent(myIntent);
// Get an instance of the NotificationManager service
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);
// Build and send
notificationManager.notify(myNotificationId, myNotification.build());
NotificationCompat.Builder myNotification =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_event)
.setContentTitle("I'm a title!")
.setContentText("DevFest 2014 Whooo Hooo")
.setContentIntent(myIntent)
.addAction(R.drawable.ic_something,
"More",
myOtherIntent);
NotificationCompat.Action myAction = new NotificationCompat.Action.Builder(...)
NotificationCompat.Builder myNotification =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_event)
.setContentTitle("I'm a title!")
.setContentText("DevFest 2014 Whooo Hooo")
.extend(new WearableExtender().addAction(myAction));
BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
bigStyle.bigText("I'm supposed to be long but that might not fit into this slide, yada yada yada");
NotificationCompat.Builder myNotification =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_event)
.setContentTitle("I'm a title!")
.setContentText("DevFest 2014 Whooo Hooo")
.addAction(R.drawable.ic_something, "More", myOtherIntent)
.setStyle(bigStyle);
The big view...but tiny on this slide.
Yes, we should be using NotificationCompat.WearableExtender()
NotificationCompat.WearableExtender extendMyWearable =
new NotificationCompat.WearableExtender()
.setHintHideIcon(true)
.setBackground(myMoreAwesomeImage);
Notification myNotification = new NotificationCompat.Builder(someContext)
.setContentTitle("Justin Says....")
.setContentText("Speeling is hard")
.setSmallIcon(R.drawable.ic_blahblah);
.extend(extendMyWearable)
.build();
Maybe you just need to send a little more without forcing the user to their handheld
// Create builder for the main notification
NotificationCompat.Builder theMainNotification = new NotificationCompat.Builder(...);
// Create the second page
Notification theSecondPageNotification = new NotificationCompat.Builder(...);
// The pages become friends
Notification thePagesAll = new WearableExtender()
.addPage(theSecondPageNotification)
.extend(theMainNotification)
.build();
// send them!
notificationManager.notify(notificationId, thePagesAll);
Pages!
We should probably stack our notifications
// Our group for the stack
final static String MY_GROUP_KEY = "group_things_such";
// Let's add this notification to this group
Notification myNotification = new NotificationCompat.Builder(someContext)
.setContentTitle("Get it together")
.setContentText("I'm important news")
.setSmallIcon(R.drawable.ic_blahblah);
.setGroup(MY_GROUP_KEY)
.build();
notificationManager.notify(notificationId1, myNotification);
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_large_icon);
Notification summary = new NotificationCompat.Builder(mContext)
.setContentTitle("2 new messages")
.setSmallIcon(R.drawable.ic_small_icon)
.setLargeIcon(largeIcon)
.setStyle(new NotificationCompat.InboxStyle()
.addLine("Alex Faaborg Check this out")
.addLine("Jeff Chang Launch Party")
.setBigContentTitle("2 new messages")
.setSummaryText("johndoe@gmail.com"))
.setGroup(MY_GROUP_KEY)
.setGroupSummary(true)
.build();
notificationManager.notify(notificationId3, summaryNotification);
Stacks!
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(myGoogleApiClient);
We can also listen and be notified if this connection changes
public interface NodeListener {
void onPeerConnected(Node peer);
void onPeerDisconnected(Node peer);
}
See: NodeApi.NodeListener
// Method
PendingResult
sendMessage(GoogleApiClient client, String nodeId, String action, byte[] data);
// Listener
public interface MessageListener {
void onMessageReceived(MessageEvent messageEvent);
}
// Method PendingResult putDataItem(GoogleApiClient client, PutDataRequest request); PendingResult getDataItem(GoogleApiClient client, Uri uri);
// ... snip ...
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_DELETED) {
Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
} else if (event.getType() == DataEvent.TYPE_CHANGED) {
Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
}
}
}
// ... snip ...
Whoooa there partner: let's have a talk.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.android.support:wearable:+'
compile 'com.google.android.gms:play-services-wearable:+'
}
Helps when you need seperate layouts for form factors
<android.support.wearable.view.WatchViewStub
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="@layout/rect_activity_wear"
app:roundLayout="@layout/round_activity_wear">
</android.support.wearable.view.WatchViewStub>
Have to wait for inflations of view
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wear);
WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override public void onLayoutInflated(WatchViewStub stub) {
// Now you can access your views
TextView tv = (TextView) stub.findViewById(R.id.text);
}
});
}
Allows single layout define for both form factors
<android.support.wearable.view.BoxInsetLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/robot_background"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:padding="15dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
app:layout_box="all">
<TextView
android:gravity="center"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="@string/sometext"
android:textColor="@color/black" />
...
<activity android:name="MyNoteActivity"> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="com.google.android.voicesearch.SELF_NOTE" /> </intent-filter> </activity>
<activity android:name="StartRunActivity" android:label="MyRunningApp"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>E;
// Key for the string that's delivered in the action's intent
private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
.setLabel(replyLabel)
.build();
// Create the reply action and add the remote input
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
getString(R.string.label, replyPendingIntent))
.addRemoteInput(remoteInput)
.build();
/**
* Obtain the intent that started this activity by calling
* Activity.getIntent() and pass it into this method to
* get the associated voice input string.
*/
private CharSequence getMessageText(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(EXTRA_VOICE_REPLY);
}
}
return null;
}
private static final int SPEECH_REQUEST_CODE = 0;
// Create an intent that can start the Speech Recognizer activity
private void displaySpeechRecognizer() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
// Start the activity, the intent will be populated with the speech text
startActivityForResult(intent, SPEECH_REQUEST_CODE);
}
// This callback is invoked when the Speech Recognizer returns.
// This is where you process the intent and extract the speech text from the intent.
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == SPEECH_REQUEST_CODE && resultCode == RESULT_OK) {
List results = data.getStringArrayListExtra(
RecognizerIntent.EXTRA_RESULTS);
String spokenText = results.get(0);
// Do something with spokenText
}
super.onActivityResult(requestCode, resultCode, data);
}
We've only touched the surface, so much more!