package com.tutosandroidfrance.wearsample;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
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.DataMap;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.io.ByteArrayOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Response;
public class WearService extends WearableListenerService {
private final static String TAG = WearService.class.getCanonicalName();
protected GoogleApiClient mApiClient;
@Override
public void onCreate() {
super.onCreate();
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.build();
mApiClient.connect();
}
@Override
public void onDestroy() {
super.onDestroy();
mApiClient.disconnect();
}
/**
* Appellé à la réception d'un message envoyé depuis la montre
*
* @param messageEvent message reçu
*/
@Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
//Ouvre une connexion vers la montre
ConnectionResult connectionResult = mApiClient.blockingConnect(30, TimeUnit.SECONDS);
if (!connectionResult.isSuccess()) {
Log.e(TAG, "Failed to connect to GoogleApiClient.");
return;
}
//traite le message reçu
final String path = messageEvent.getPath();
if (path.equals("bonjour")) {
//Utilise Retrofit pour réaliser un appel REST
AndroidService androidService = new RestAdapter.Builder()
.setEndpoint(AndroidService.ENDPOINT)
.build().create(AndroidService.class);
//Récupère et deserialise le contenu de mon fichier JSON en objet Element
androidService.getElements(new Callback<List<Element>>() {
@Override
public void success(List<Element> elements, Response response) {
envoyerListElements(elements);
}
@Override
public void failure(RetrofitError error) {
}
});
}
}
/**
* Envoie la liste d'éléments à la montre
* Envoie de même les images
* @param elements
*/
private void envoyerListElements(final List<Element> elements) {
new Thread(new Runnable() {
@Override
public void run() {
int nombreElements = elements.size();
//Envoie des elements et leurs images
sendElements(elements);
}
}).start();
}
/**
* Envoie un message à la montre
*
* @param path identifiant du message
* @param message message à transmettre
*/
protected void sendMessage(final String path, final String message) {
//effectué dans un trhead afin de ne pas être bloquant
new Thread(new Runnable() {
@Override
public void run() {
//envoie le message à tous les noeuds/montres connectées
final NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(mApiClient, node.getId(), path, message.getBytes()).await();
}
}
}).start();
}
/**
* Récupère une bitmap à partir d'une URL
*/
public static Bitmap getBitmapFromURL(String src) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(src).openConnection();
connection.setDoInput(true);
connection.connect();
return BitmapFactory.decodeStream(connection.getInputStream());
} catch (Exception e) {
// Log exception
return null;
}
}
/**
* Les bitmap transferés depuis les DataApi doivent être empaquetées en Asset
*/
public static Asset createAssetFromBitmap(Bitmap bitmap) {
final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
return Asset.createFromBytes(byteStream.toByteArray());
}
/**
* Permet d'envoyer une liste d'elements
*/
protected void sendElements(final List<Element> elements) {
final PutDataMapRequest putDataMapRequest = PutDataMapRequest.create("/elements/");
ArrayList<DataMap> elementsDataMap = new ArrayList<>();
//envoie chaque élémént 1 par 1
for (int position = 0; position < elements.size(); ++position) {
DataMap elementDataMap = new DataMap();
Element element = elements.get(position);
//créé un emplacement mémoire "element/[position]"
//ajoute la date de mi[jase à jour
elementDataMap.putString("timestamp", new Date().toString());
//ajoute l'element champ par champ
elementDataMap.putString("titre", element.getTitre());
elementDataMap.putString("description", element.getDescription());
elementDataMap.putString("url", element.getUrl());
//ajoute cette datamap à notre arrayList
elementsDataMap.add(elementDataMap);
}
//place la liste dans la datamap envoyée à la wear
putDataMapRequest.getDataMap().putDataMapArrayList("/list/",elementsDataMap);
//envoie la liste à la montre
if (mApiClient.isConnected())
Wearable.DataApi.putDataItem(mApiClient, putDataMapRequest.asPutDataRequest());
//puis envoie les images dans un second temps
for(int position = 0; position < elements.size(); ++position){
//charge l'image associée pour l'envoyer en bluetooth
sendImage(elements.get(position).getUrl(), position);
}
}
/**
* Permet d'envoyer une image à la montre
*/
protected void sendImage(String url, int position) {
//télécharge l'image
Bitmap bitmap = getBitmapFromURL(url);
if (bitmap != null) {
Asset asset = createAssetFromBitmap(bitmap);
//créé un emplacement mémoire "image/[url_image]"
final PutDataMapRequest putDataMapRequest = PutDataMapRequest.create("/image/" + position);
//ajoute la date de mise à jour, important pour que les données soient mises à jour
putDataMapRequest.getDataMap().putString("timestamp", new Date().toString());
//ajoute l'image à la requête
putDataMapRequest.getDataMap().putAsset("image", asset);
//envoie la donnée à la montre
if (mApiClient.isConnected())
Wearable.DataApi.putDataItem(mApiClient, putDataMapRequest.asPutDataRequest());
}
}
}