1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.wearable.watchface; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.content.ComponentName; 22 import android.content.DialogInterface; 23 import android.graphics.Color; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.support.wearable.companion.WatchFaceCompanion; 27 import android.util.Log; 28 import android.view.View; 29 import android.widget.AdapterView; 30 import android.widget.Spinner; 31 import android.widget.TextView; 32 33 import com.google.android.gms.common.ConnectionResult; 34 import com.google.android.gms.common.api.GoogleApiClient; 35 import com.google.android.gms.common.api.ResultCallback; 36 import com.google.android.gms.wearable.DataApi; 37 import com.google.android.gms.wearable.DataItem; 38 import com.google.android.gms.wearable.DataMap; 39 import com.google.android.gms.wearable.DataMapItem; 40 import com.google.android.gms.wearable.Wearable; 41 42 /** 43 * The phone-side config activity for {@code DigitalWatchFaceService}. Like the watch-side config 44 * activity ({@code DigitalWatchFaceWearableConfigActivity}), allows for setting the background 45 * color. Additionally, enables setting the color for hour, minute and second digits. 46 */ 47 public class DigitalWatchFaceCompanionConfigActivity extends Activity 48 implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, 49 ResultCallback<DataApi.DataItemResult> { 50 private static final String TAG = "DigitalWatchFaceConfig"; 51 52 // TODO: use the shared constants (needs covering all the samples with Gradle build model) 53 private static final String KEY_BACKGROUND_COLOR = "BACKGROUND_COLOR"; 54 private static final String KEY_HOURS_COLOR = "HOURS_COLOR"; 55 private static final String KEY_MINUTES_COLOR = "MINUTES_COLOR"; 56 private static final String KEY_SECONDS_COLOR = "SECONDS_COLOR"; 57 private static final String PATH_WITH_FEATURE = "/watch_face_config/Digital"; 58 59 private GoogleApiClient mGoogleApiClient; 60 private String mPeerId; 61 62 @Override onCreate(Bundle savedInstanceState)63 protected void onCreate(Bundle savedInstanceState) { 64 super.onCreate(savedInstanceState); 65 setContentView(R.layout.activity_digital_watch_face_config); 66 67 mPeerId = getIntent().getStringExtra(WatchFaceCompanion.EXTRA_PEER_ID); 68 mGoogleApiClient = new GoogleApiClient.Builder(this) 69 .addConnectionCallbacks(this) 70 .addOnConnectionFailedListener(this) 71 .addApi(Wearable.API) 72 .build(); 73 74 ComponentName name = getIntent().getParcelableExtra( 75 WatchFaceCompanion.EXTRA_WATCH_FACE_COMPONENT); 76 TextView label = (TextView)findViewById(R.id.label); 77 label.setText(label.getText() + " (" + name.getClassName() + ")"); 78 } 79 80 @Override onStart()81 protected void onStart() { 82 super.onStart(); 83 mGoogleApiClient.connect(); 84 } 85 86 @Override onStop()87 protected void onStop() { 88 if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) { 89 mGoogleApiClient.disconnect(); 90 } 91 super.onStop(); 92 } 93 94 @Override // GoogleApiClient.ConnectionCallbacks onConnected(Bundle connectionHint)95 public void onConnected(Bundle connectionHint) { 96 if (Log.isLoggable(TAG, Log.DEBUG)) { 97 Log.d(TAG, "onConnected: " + connectionHint); 98 } 99 100 if (mPeerId != null) { 101 Uri.Builder builder = new Uri.Builder(); 102 Uri uri = builder.scheme("wear").path(PATH_WITH_FEATURE).authority(mPeerId).build(); 103 Wearable.DataApi.getDataItem(mGoogleApiClient, uri).setResultCallback(this); 104 } else { 105 displayNoConnectedDeviceDialog(); 106 } 107 } 108 109 @Override // ResultCallback<DataApi.DataItemResult> onResult(DataApi.DataItemResult dataItemResult)110 public void onResult(DataApi.DataItemResult dataItemResult) { 111 if (dataItemResult.getStatus().isSuccess() && dataItemResult.getDataItem() != null) { 112 DataItem configDataItem = dataItemResult.getDataItem(); 113 DataMapItem dataMapItem = DataMapItem.fromDataItem(configDataItem); 114 DataMap config = dataMapItem.getDataMap(); 115 setUpAllPickers(config); 116 } else { 117 // If DataItem with the current config can't be retrieved, select the default items on 118 // each picker. 119 setUpAllPickers(null); 120 } 121 } 122 123 @Override // GoogleApiClient.ConnectionCallbacks onConnectionSuspended(int cause)124 public void onConnectionSuspended(int cause) { 125 if (Log.isLoggable(TAG, Log.DEBUG)) { 126 Log.d(TAG, "onConnectionSuspended: " + cause); 127 } 128 } 129 130 @Override // GoogleApiClient.OnConnectionFailedListener onConnectionFailed(ConnectionResult result)131 public void onConnectionFailed(ConnectionResult result) { 132 if (Log.isLoggable(TAG, Log.DEBUG)) { 133 Log.d(TAG, "onConnectionFailed: " + result); 134 } 135 } 136 displayNoConnectedDeviceDialog()137 private void displayNoConnectedDeviceDialog() { 138 AlertDialog.Builder builder = new AlertDialog.Builder(this); 139 String messageText = getResources().getString(R.string.title_no_device_connected); 140 String okText = getResources().getString(R.string.ok_no_device_connected); 141 builder.setMessage(messageText) 142 .setCancelable(false) 143 .setPositiveButton(okText, new DialogInterface.OnClickListener() { 144 public void onClick(DialogInterface dialog, int id) { } 145 }); 146 AlertDialog alert = builder.create(); 147 alert.show(); 148 } 149 150 /** 151 * Sets up selected items for all pickers according to given {@code config} and sets up their 152 * item selection listeners. 153 * 154 * @param config the {@code DigitalWatchFaceService} config {@link DataMap}. If null, the 155 * default items are selected. 156 */ setUpAllPickers(DataMap config)157 private void setUpAllPickers(DataMap config) { 158 setUpColorPickerSelection(R.id.background, KEY_BACKGROUND_COLOR, config, 159 R.string.color_black); 160 setUpColorPickerSelection(R.id.hours, KEY_HOURS_COLOR, config, R.string.color_white); 161 setUpColorPickerSelection(R.id.minutes, KEY_MINUTES_COLOR, config, R.string.color_white); 162 setUpColorPickerSelection(R.id.seconds, KEY_SECONDS_COLOR, config, R.string.color_gray); 163 164 setUpColorPickerListener(R.id.background, KEY_BACKGROUND_COLOR); 165 setUpColorPickerListener(R.id.hours, KEY_HOURS_COLOR); 166 setUpColorPickerListener(R.id.minutes, KEY_MINUTES_COLOR); 167 setUpColorPickerListener(R.id.seconds, KEY_SECONDS_COLOR); 168 } 169 setUpColorPickerSelection(int spinnerId, final String configKey, DataMap config, int defaultColorNameResId)170 private void setUpColorPickerSelection(int spinnerId, final String configKey, DataMap config, 171 int defaultColorNameResId) { 172 String defaultColorName = getString(defaultColorNameResId); 173 int defaultColor = Color.parseColor(defaultColorName); 174 int color; 175 if (config != null) { 176 color = config.getInt(configKey, defaultColor); 177 } else { 178 color = defaultColor; 179 } 180 Spinner spinner = (Spinner) findViewById(spinnerId); 181 String[] colorNames = getResources().getStringArray(R.array.color_array); 182 for (int i = 0; i < colorNames.length; i++) { 183 if (Color.parseColor(colorNames[i]) == color) { 184 spinner.setSelection(i); 185 break; 186 } 187 } 188 } 189 setUpColorPickerListener(int spinnerId, final String configKey)190 private void setUpColorPickerListener(int spinnerId, final String configKey) { 191 Spinner spinner = (Spinner) findViewById(spinnerId); 192 spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 193 @Override 194 public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long id) { 195 final String colorName = (String) adapterView.getItemAtPosition(pos); 196 sendConfigUpdateMessage(configKey, Color.parseColor(colorName)); 197 } 198 199 @Override 200 public void onNothingSelected(AdapterView<?> adapterView) { } 201 }); 202 } 203 sendConfigUpdateMessage(String configKey, int color)204 private void sendConfigUpdateMessage(String configKey, int color) { 205 if (mPeerId != null) { 206 DataMap config = new DataMap(); 207 config.putInt(configKey, color); 208 byte[] rawData = config.toByteArray(); 209 Wearable.MessageApi.sendMessage(mGoogleApiClient, mPeerId, PATH_WITH_FEATURE, rawData); 210 211 if (Log.isLoggable(TAG, Log.DEBUG)) { 212 Log.d(TAG, "Sent watch face config message: " + configKey + " -> " 213 + Integer.toHexString(color)); 214 } 215 } 216 } 217 } 218