Upload
constantine-mars
View
176
Download
0
Embed Size (px)
Citation preview
Android Wear 2.0Next Level of Freedom for Your Action
Constantine MarsOrganizer @ GDG DniproSenior Developer @ DataArt
A long time ago…
A long time ago… in the Lviv, not so far away :)
A long time ago… in the Lviv, not so far away :)We’ve been talking about...
#gdgceesummit
Freedom of tethering
BLE
WiFi
Cellular
#gdgceesummit
And chances to get direct access to Play Store
And today...
Developer Preview 3Play Store and MoreAvailable since September 28
#gdgceesummit
Play Store features
● multiple accounts, ● support of alpha and
beta testing● update or uninstall
apps in “My apps” view● install only the watch
app● phone apps are no
longer necessary
You can now build and publish watch-only apps for users to discover on Google Play
#gdgceesummit
android {
publishNonDefault true // Allows you to reference product flavors in your phone's build.gradle
defaultConfig
{ minSdkVersion 23 } // This is the minSdkVersion of the Wear 1.0 embedded app
productFlavors {
wear1 { /* Use the defaultConfig value */ }
wear2 { minSdkVersion 24 }
}
}
Flavors for supporting both 2.0 and 1.x
#gdgceesummit
dependencies {
...
wearApp project(path: ':wear', configuration: 'wear1Release')
}
Package only when build variant requires it
#gdgceesummit
If no need in 1.x - simply publish MultiAPK
HardwareKey platform features and supported watches
#gdgceesummit
Officially supported watches
LG Watch Urbane 2nd Edition Huawei Watch
#gdgceesummit
Officially supported watches
LG Watch Urbane 2nd Edition Huawei Watch
Display: 1.4 inches, 400 x 400 pixels (~286 ppi)
CPU:Quad-core 1.2 GHz Cortex-A7
GPU: Adreno 305, Chipset: Qualcomm Snapdragon 400
Memory: 4 GB, 512 MB RAM
Comm: Wi-Fi 802.11 b/g, Bluetooth v4.1 LE
Network: No cellular connectivity
Battery: 300 mAh (48h)
Display: 1.38 inches, 480 x 480 pixels (~348 ppi)
CPU: Quad-core 1.2 GHz Cortex-A7
GPU: Adreno 305, Chipset: Qualcomm Snapdragon 400
Memory: 4 GB, 768 MB RAM
Comm: Wi-Fi 802.11 b/g, Bluetooth v4.1 LE, GPS, NFC
Network: GSM, HSPA, LTE
Battery: 570 mAh (60h)
ComplicationsPersonal expression and utility
#gdgceesummit
Personal expression and utility
Modern by LG Ranger by Zuhanden GoogleFit Today
#gdgceesummit
Or simply an personal expression :)
HeyKittyKitty by WatchMaster
#gdgceesummit
Complications
“any feature in a timepiece beyond the simple display
of hours and minutes” (Wikipedia)
#gdgceesummit
Complication types
-Short text-Long text-Range of values-Icon (small picture)-Image (big picture)
Complications coding
#gdgceesummit
New in Preview 3
com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA
Request permission to access Complication Data
#gdgceesummit
Runtime permissions. Wearable version:)
Now required for accessing Complication Providers from WatchFace apps
#gdgceesummit
Each position need to be identified
private static final int LEFT_DIAL_COMPLICATION = 0;
private static final int RIGHT_DIAL_COMPLICATION = 1;
public static final int[] COMPLICATION_IDS = {LEFT_DIAL_COMPLICATION,
RIGHT_DIAL_COMPLICATION};
Complication ID
#gdgceesummit
Each position must be mapped with array of supported types
// Left and right dial supported types.
public static final int[][] COMPLICATION_SUPPORTED_TYPES = {
{ComplicationData.TYPE_SHORT_TEXT},
{ComplicationData.TYPE_SHORT_TEXT}
};
Complication supported types
#gdgceesummit
Data Providers and system trigger .onComplicationDataUpdate() sometimes
/* Called when there is updated data for a complication id. */
@Override
public void onComplicationDataUpdate(
int complicationId, ComplicationData complicationData) {
Log.d(TAG, "onComplicationDataUpdate() id: " + complicationId);
mActiveComplicationDataSparseArray.put(complicationId, complicationData);
invalidate();
}
ComplicationData receiving
#gdgceesummit
.onDraw() is the moment of drawing. ComplicationData where stored earlier
@Override
public void onDraw(Canvas canvas, Rect bounds) {
ComplicationData complicationData;
for (int i = 0; i < COMPLICATION_IDS.length; i++) {
complicationData = mActiveComplicationDataSparseArray
.get(COMPLICATION_IDS[i]);
// ...
Complications rendering
#gdgceesummit
Complication may be deactivated or contain wrong data type
if ((complicationData != null)
&& (complicationData.isActive(currentTimeMillis))
&& (complicationData.getType() ==
ComplicationData.TYPE_SHORT_TEXT)) {
ComplicationText mainText = complicationData.getShortText();
CharSequence complicationMessage =
mainText.getText(getApplicationContext(),
currentTimeMillis);
Complications rendering
#gdgceesummit
Actual drawing is trivial
canvas.drawText(
complicationMessage,
0,
complicationMessage.length(),
complicationsX,
mComplicationsY,
mComplicationPaint);
Complications rendering
Data Providers
#gdgceesummit
Android Wear role in data exchange
#gdgceesummit
Data Providers
Data Providers coding
#gdgceesummit
<service android:name=".RandomNumberProviderService"
android:label="@string/complications_provider_random_number"
android:icon="@drawable/ic_watch_white">
Data Provider Service attributesExtend ComplicationProviderService
#gdgceesummit
<intent-filter>
<action
android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDA
TE_REQUEST"/>
</intent-filter>
<meta-data
android:name="android.support.wearable.complications.SUPPORTED_TYPES"
android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT"/>
Data Provider declaration
#gdgceesummit
Update period
<meta-data
android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
android:value="120"/>
Data Provider declaration
#gdgceesummit
@Override
public void onComplicationActivated( int complicationId, int dataType,
ComplicationManager complicationManager) { … }
@Override
public void onComplicationUpdate( int complicationId, int dataType,
ComplicationManager complicationManager) { … }
@Override
public void onComplicationDeactivated(int complicationId) { … }
Data Provider methods
#gdgceesummit
@Override
public void onComplicationUpdate(int complicationId, int dataType,
ComplicationManager complicationManager) {
// Retrieve or generate your data
int randomNumber = (int) Math.floor(Math.random() * 10);
String randomNumberText =
String.format(Locale.getDefault(), "%d!", randomNumber);
Exposing data to complicationsCalled according to update period time
#gdgceesummit
ComplicationData complicationData = null;
switch (dataType) {
case ComplicationData.TYPE_SHORT_TEXT:
complicationData = new ComplicationData.Builder(
ComplicationData.TYPE_SHORT_TEXT)
.setShortText(ComplicationText.plainText(randomNumberText))
.build();
break;
Exposing data to complications
#gdgceesummit
@Override
public void onComplicationUpdate( int complicationId, int dataType,
ComplicationManager complicationManager) {
…
if (complicationData != null) {
complicationManager.updateComplicationData(
complicationId,
complicationData);
}
Exposing data to complications
#gdgceesummit
WatchFaceService.Engine.setDefaultComplicationProvider()
Default Providers
Notifications updated
#gdgceesummit
Notifications in Android Wear 1.X
#gdgceesummit
Android Wear 2.0 NotificationsMaterial Design for Wearables, Dark Theme
#gdgceesummit
Notifications preview
#gdgceesummit
Notifications messaging style
Notifications coding
#gdgceesummit
Notification noti = new NotificationCompat.Builder()
.setContentTitle(messages.length + " new messages with " + sender)
.setContentText("subject")
.setSmallIcon(R.drawable.new_message)
// 2) set the style to MessagingStyle
.setStyle(new NotificationCompat.MessagingStyle(
getResources().getString(R.string.reply_name))
.addMessage(messages[0])
.addMessage(messages[1]);
Notifications with modern MessagingStyle
set MessagingStyle
#gdgceesummit
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
getString(R.string.label), replyPendingIntent)
.addRemoteInput(remoteInput)
.setAllowGeneratedReplies(true)
.build();
Notifications with SmartReply
Allow SmartReply
Starting with Preview 3 SmartReply uses standalone machine, located on watch
#gdgceesummit
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
getString(R.string.label), replyPendingIntent)
.addRemoteInput(remoteInput)
.extend(new NotificationCompat.Action.WearableExtender()
.setHintDisplayActionInline(true))
.build();
Inline Action, available directly from stream
Set inline action
(Not new) Input Methods
#gdgceesummit
New input methods
#gdgceesummit
Voice input, Emoji
#gdgceesummit
Keyboard, Handwriting
#gdgceesummit
Wait, a Keyboard???LG Watch Urbane 2nd Edition
Display: 1.38 inches, 480 x 480 pixels (~348 ppi)
CPU: Quad-core 1.2 GHz Cortex-A7
GPU: Adreno 305, Chipset: Qualcomm Snapdragon 400
Memory: 4 GB, 768 MB RAM
Comm: Wi-Fi 802.11 b/g, Bluetooth v4.1, LE, GPS, NFC
Network: GSM, HSPA, LTE
Battery: 570 mAh (60h)
Size x2 bigger than first phones
Material Design for Wearables
#gdgceesummit
1D Layout
Do Don’t
#gdgceesummit
UI Anatomy
#gdgceesummit
Navigation Drawer
#gdgceesummit
Action Drawer
#gdgceesummit
Dark Theme
#gdgceesummit
Brightness values
1 App color - Default color
2 Dark background - 15%
3 Lighter background - 30%
4 UI element - 40%
5 Lighter UI element - 65%
6 Accent - 100%
#gdgceesummit
Applications list
#gdgceesummit
WearableRecyclerViewSince Preview 3 - .setCircularScrollingGestureEnabled(true) available
Some new Google Fit features for Android Wear
#gdgceesummit
Upcoming APIs
Beat to Beat API Goals API Profile API
#gdgceesummit
Real Time Gym Activity Recognition
#gdgceesummit
Recognized exercises
Q&A?
Thank you!
Constantine Mars
@ConstantineMars+ConstantineMars