/*
* Copyright (C) Winson Chiu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cw.kop.autobackground;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ThumbnailUtils;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataItem;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
import cw.kop.autobackground.shared.WearConstants;
public class EventListenerService extends WearableListenerService {
public static final String LOAD_IMAGE = "cw.kop.autobackground.EventListenerService.LOAD_IMAGE";
public static final String LOAD_SETTINGS = "cw.kop.autobackground.EventListenerService.LOAD_SETTINGS";
private static final String TAG = EventListenerService.class.getCanonicalName();
private static final int TIMEOUT_MS = 2000;
private static Bitmap currentBitmap = null;
private static Bitmap lastBitmap = null;
private GoogleApiClient googleApiClient;
public EventListenerService() {
}
public static Bitmap getBitmap() {
return currentBitmap;
}
@Override
public void onCreate() {
super.onCreate();
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle connectionHint) {
Log.d(TAG, "onConnected: " + connectionHint);
// Now you can use the Data Layer API
}
@Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "onConnectionSuspended: " + cause);
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.d(TAG, "onConnectionFailed: " + result);
}
})
// Request access only to the Wearable API
.addApi(Wearable.API)
.build();
googleApiClient.connect();
Log.i(TAG, "EventListenerService created");
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
Log.i(TAG, "Message received");
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
for (DataEvent event : dataEvents) {
DataItem dataItem = event.getDataItem();
DataMap dataMap = DataMapItem.fromDataItem(dataItem).getDataMap();
if (event.getType() == DataEvent.TYPE_CHANGED) {
switch (dataItem.getUri().getPath()) {
case WearConstants.IMAGE:
Asset profileAsset = dataMap.getAsset("faceImage");
lastBitmap = currentBitmap;
currentBitmap = loadBitmapFromAsset(profileAsset);
if (currentBitmap != null) {
Intent intent = new Intent(LOAD_IMAGE);
LocalBroadcastManager.getInstance(this).sendBroadcast(
intent);
Log.i(TAG, "Bitmap received");
}
break;
case WearConstants.SETTINGS:
WearSettings.setTimeType(dataMap.getString(WearConstants.TIME_TYPE,
WearSettings.DIGITAL));
WearSettings.setTimeOffset(dataMap.getLong(WearConstants.TIME_OFFSET, 0));
WearSettings.setUseTimePalette(dataMap.getBoolean(WearConstants.USE_TIME_PALETTE,
false));
WearSettings.setSeparatorText(dataMap.getString(WearConstants.SEPARATOR_TEXT,
":"));
WearSettings.setSeparatorColor(dataMap.getInt(WearConstants.SEPARATOR_COLOR,
0xFFFFFFFF));
WearSettings.setSeparatorShadowColor(dataMap.getInt(WearConstants.
SEPARATOR_SHADOW_COLOR,
0xFF000000));
WearSettings.setHourColor(dataMap.getInt(WearConstants.HOUR_COLOR,
0xFFFFFFFF));
WearSettings.setHourShadowColor(dataMap.getInt(WearConstants.HOUR_SHADOW_COLOR,
0xFF000000));
WearSettings.setMinuteColor(dataMap.getInt(WearConstants.MINUTE_COLOR,
0xFFFFFFFF));
WearSettings.setMinuteShadowColor(dataMap.getInt(WearConstants.MINUTE_SHADOW_COLOR,
0xFF000000));
WearSettings.setSecondColor(dataMap.getInt(WearConstants.SECOND_COLOR,
0xFFFFFFFF));
WearSettings.setSecondShadowColor(dataMap.getInt(WearConstants.SECOND_SHADOW_COLOR,
0xFF000000));
WearSettings.setTickLengthRatio(dataMap.getFloat(WearConstants.TICK_LENGTH_RATIO,
10f));
WearSettings.setHourLengthRatio(dataMap.getFloat(WearConstants.HOUR_LENGTH_RATIO,
50f));
WearSettings.setMinuteLengthRatio(dataMap.getFloat(WearConstants.
MINUTE_LENGTH_RATIO,
66f));
WearSettings.setSecondLengthRatio(dataMap.getFloat(WearConstants.
SECOND_LENGTH_RATIO,
100f));
WearSettings.setTickWidth(dataMap.getFloat(WearConstants.TICK_WIDTH, 1.0f));
WearSettings.setHourWidth(dataMap.getFloat(WearConstants.HOUR_WIDTH, 5.0f));
WearSettings.setMinuteWidth(dataMap.getFloat(WearConstants.MINUTE_WIDTH, 3.0f));
WearSettings.setSecondWidth(dataMap.getFloat(WearConstants.SECOND_WIDTH, 2.0f));
Intent intent = new Intent(LOAD_SETTINGS);
LocalBroadcastManager.getInstance(this).sendBroadcast(
intent);
Log.i(TAG, "Settings received");
break;
}
}
}
Log.i(TAG, "Data changed");
super.onDataChanged(dataEvents);
}
public static void recycleLast() {
if (lastBitmap != null) {
lastBitmap.recycle();
lastBitmap = null;
}
}
public Bitmap loadBitmapFromAsset(Asset asset) {
if (asset == null) {
throw new IllegalArgumentException("Asset must be non-null");
}
ConnectionResult result =
googleApiClient.blockingConnect(TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (!result.isSuccess()) {
return null;
}
// convert asset into a file descriptor and block until it's ready
InputStream assetInputStream = Wearable.DataApi.getFdForAsset(
googleApiClient, asset).await().getInputStream();
googleApiClient.disconnect();
if (assetInputStream == null) {
Log.w(TAG, "Requested an unknown Asset.");
return null;
}
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int screenHeight = getResources().getDisplayMetrics().heightPixels;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inPreferQualityOverSpeed = true;
options.inScaled = true;
options.inDither = true;
Bitmap bitmap = ThumbnailUtils.extractThumbnail(
BitmapFactory.decodeStream(assetInputStream, null, options),
screenWidth, screenHeight, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
try {
assetInputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
}