Home | History | Annotate | Download | only in watchface
      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
     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
     81     protected void onStart() {
     82         super.onStart();
     83         mGoogleApiClient.connect();
     84     }
     85 
     86     @Override
     87     protected void onStop() {
     88         if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
     89             mGoogleApiClient.disconnect();
     90         }
     91         super.onStop();
     92     }
     93 
     94     @Override // GoogleApiClient.ConnectionCallbacks
     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>
    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
    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
    131     public void onConnectionFailed(ConnectionResult result) {
    132         if (Log.isLoggable(TAG, Log.DEBUG)) {
    133             Log.d(TAG, "onConnectionFailed: " + result);
    134         }
    135     }
    136 
    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      */
    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 
    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 
    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 
    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