Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2017 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.util;
     18 
     19 import android.graphics.Color;
     20 import android.net.Uri;
     21 import android.util.Log;
     22 
     23 import com.google.android.gms.common.api.GoogleApiClient;
     24 import com.google.android.gms.common.api.ResultCallback;
     25 import com.google.android.gms.wearable.DataApi;
     26 import com.google.android.gms.wearable.DataItem;
     27 import com.google.android.gms.wearable.DataMap;
     28 import com.google.android.gms.wearable.DataMapItem;
     29 import com.google.android.gms.wearable.NodeApi;
     30 import com.google.android.gms.wearable.PutDataMapRequest;
     31 import com.google.android.gms.wearable.Wearable;
     32 
     33 import com.example.android.wearable.watchface.watchface.DigitalWatchFaceService;
     34 
     35 public final class DigitalWatchFaceUtil {
     36     private static final String TAG = "DigitalWatchFaceUtil";
     37 
     38     /**
     39      * The {@link DataMap} key for {@link DigitalWatchFaceService} background color name.
     40      * The color name must be a {@link String} recognized by {@link Color#parseColor}.
     41      */
     42     public static final String KEY_BACKGROUND_COLOR = "BACKGROUND_COLOR";
     43 
     44     /**
     45      * The {@link DataMap} key for {@link DigitalWatchFaceService} hour digits color name.
     46      * The color name must be a {@link String} recognized by {@link Color#parseColor}.
     47      */
     48     public static final String KEY_HOURS_COLOR = "HOURS_COLOR";
     49 
     50     /**
     51      * The {@link DataMap} key for {@link DigitalWatchFaceService} minute digits color name.
     52      * The color name must be a {@link String} recognized by {@link Color#parseColor}.
     53      */
     54     public static final String KEY_MINUTES_COLOR = "MINUTES_COLOR";
     55 
     56     /**
     57      * The {@link DataMap} key for {@link DigitalWatchFaceService} second digits color name.
     58      * The color name must be a {@link String} recognized by {@link Color#parseColor}.
     59      */
     60     public static final String KEY_SECONDS_COLOR = "SECONDS_COLOR";
     61 
     62     /**
     63      * The path for the {@link DataItem} containing {@link DigitalWatchFaceService} configuration.
     64      */
     65     public static final String PATH_WITH_FEATURE = "/watch_face_config/Digital";
     66 
     67     /**
     68      * Name of the default interactive mode background color and the ambient mode background color.
     69      */
     70     public static final String COLOR_NAME_DEFAULT_AND_AMBIENT_BACKGROUND = "Black";
     71     public static final int COLOR_VALUE_DEFAULT_AND_AMBIENT_BACKGROUND =
     72             parseColor(COLOR_NAME_DEFAULT_AND_AMBIENT_BACKGROUND);
     73 
     74     /**
     75      * Name of the default interactive mode hour digits color and the ambient mode hour digits
     76      * color.
     77      */
     78     public static final String COLOR_NAME_DEFAULT_AND_AMBIENT_HOUR_DIGITS = "White";
     79     public static final int COLOR_VALUE_DEFAULT_AND_AMBIENT_HOUR_DIGITS =
     80             parseColor(COLOR_NAME_DEFAULT_AND_AMBIENT_HOUR_DIGITS);
     81 
     82     /**
     83      * Name of the default interactive mode minute digits color and the ambient mode minute digits
     84      * color.
     85      */
     86     public static final String COLOR_NAME_DEFAULT_AND_AMBIENT_MINUTE_DIGITS = "White";
     87     public static final int COLOR_VALUE_DEFAULT_AND_AMBIENT_MINUTE_DIGITS =
     88             parseColor(COLOR_NAME_DEFAULT_AND_AMBIENT_MINUTE_DIGITS);
     89 
     90     /**
     91      * Name of the default interactive mode second digits color and the ambient mode second digits
     92      * color.
     93      */
     94     public static final String COLOR_NAME_DEFAULT_AND_AMBIENT_SECOND_DIGITS = "Gray";
     95     public static final int COLOR_VALUE_DEFAULT_AND_AMBIENT_SECOND_DIGITS =
     96             parseColor(COLOR_NAME_DEFAULT_AND_AMBIENT_SECOND_DIGITS);
     97 
     98     /**
     99      * Callback interface to perform an action with the current config {@link DataMap} for
    100      * {@link DigitalWatchFaceService}.
    101      */
    102     public interface FetchConfigDataMapCallback {
    103         /**
    104          * Callback invoked with the current config {@link DataMap} for
    105          * {@link DigitalWatchFaceService}.
    106          */
    107         void onConfigDataMapFetched(DataMap config);
    108     }
    109 
    110     private static int parseColor(String colorName) {
    111         return Color.parseColor(colorName.toLowerCase());
    112     }
    113 
    114     /**
    115      * Asynchronously fetches the current config {@link DataMap} for {@link DigitalWatchFaceService}
    116      * and passes it to the given callback.
    117      * <p>
    118      * If the current config {@link DataItem} doesn't exist, it isn't created and the callback
    119      * receives an empty DataMap.
    120      */
    121     public static void fetchConfigDataMap(final GoogleApiClient client,
    122             final FetchConfigDataMapCallback callback) {
    123         Wearable.NodeApi.getLocalNode(client).setResultCallback(
    124                 new ResultCallback<NodeApi.GetLocalNodeResult>() {
    125                     @Override
    126                     public void onResult(NodeApi.GetLocalNodeResult getLocalNodeResult) {
    127                         String localNode = getLocalNodeResult.getNode().getId();
    128                         Uri uri = new Uri.Builder()
    129                                 .scheme("wear")
    130                                 .path(DigitalWatchFaceUtil.PATH_WITH_FEATURE)
    131                                 .authority(localNode)
    132                                 .build();
    133                         Wearable.DataApi.getDataItem(client, uri)
    134                                 .setResultCallback(new DataItemResultCallback(callback));
    135                     }
    136                 }
    137         );
    138     }
    139 
    140     /**
    141      * Overwrites (or sets, if not present) the keys in the current config {@link DataItem} with
    142      * the ones appearing in the given {@link DataMap}. If the config DataItem doesn't exist,
    143      * it's created.
    144      * <p>
    145      * It is allowed that only some of the keys used in the config DataItem appear in
    146      * {@code configKeysToOverwrite}. The rest of the keys remains unmodified in this case.
    147      */
    148     public static void overwriteKeysInConfigDataMap(final GoogleApiClient googleApiClient,
    149             final DataMap configKeysToOverwrite) {
    150 
    151         DigitalWatchFaceUtil.fetchConfigDataMap(googleApiClient,
    152                 new FetchConfigDataMapCallback() {
    153                     @Override
    154                     public void onConfigDataMapFetched(DataMap currentConfig) {
    155                         DataMap overwrittenConfig = new DataMap();
    156                         overwrittenConfig.putAll(currentConfig);
    157                         overwrittenConfig.putAll(configKeysToOverwrite);
    158                         DigitalWatchFaceUtil.putConfigDataItem(googleApiClient, overwrittenConfig);
    159                     }
    160                 }
    161         );
    162     }
    163 
    164     /**
    165      * Overwrites the current config {@link DataItem}'s {@link DataMap} with {@code newConfig}.
    166      * If the config DataItem doesn't exist, it's created.
    167      */
    168     public static void putConfigDataItem(GoogleApiClient googleApiClient, DataMap newConfig) {
    169         PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(PATH_WITH_FEATURE);
    170         putDataMapRequest.setUrgent();
    171         DataMap configToPut = putDataMapRequest.getDataMap();
    172         configToPut.putAll(newConfig);
    173         Wearable.DataApi.putDataItem(googleApiClient, putDataMapRequest.asPutDataRequest())
    174                 .setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
    175                     @Override
    176                     public void onResult(DataApi.DataItemResult dataItemResult) {
    177                         if (Log.isLoggable(TAG, Log.DEBUG)) {
    178                             Log.d(TAG, "putDataItem result status: " + dataItemResult.getStatus());
    179                         }
    180                     }
    181                 });
    182     }
    183 
    184     private static class DataItemResultCallback implements ResultCallback<DataApi.DataItemResult> {
    185 
    186         private final FetchConfigDataMapCallback mCallback;
    187 
    188         public DataItemResultCallback(FetchConfigDataMapCallback callback) {
    189             mCallback = callback;
    190         }
    191 
    192         @Override
    193         public void onResult(DataApi.DataItemResult dataItemResult) {
    194             if (dataItemResult.getStatus().isSuccess()) {
    195                 if (dataItemResult.getDataItem() != null) {
    196                     DataItem configDataItem = dataItemResult.getDataItem();
    197                     DataMapItem dataMapItem = DataMapItem.fromDataItem(configDataItem);
    198                     DataMap config = dataMapItem.getDataMap();
    199                     mCallback.onConfigDataMapFetched(config);
    200                 } else {
    201                     mCallback.onConfigDataMapFetched(new DataMap());
    202                 }
    203             }
    204         }
    205     }
    206 
    207     private DigitalWatchFaceUtil() { }
    208 }
    209