Reputation: 15155
I am attempting to read a feed from a URL in the form of a JSON Object, and pass that feed to a Wearable device to display as a list using the Data API. This JSON Object contains an array of objects, each object containing a few elements. Something like this:
{ "items":[
{ "title":"item 1", "element_1":"element 1", "element_2":"element 2" }
{ "title":"item 2", "element_1":"element 1", "element_2":"element 2" }
{ "title":"item 3", "element_1":"element 1", "element_2":"element 2" }
]}
I can get these items into an ArrayList
of objects using GSON, or Jackson (though I think I prefer GSON), but I do not know how I would be able to that ArrayList
of objects to the wearable. From what I can tell, I cannot. I would like to know if there is a way to do this, or if not, some sort of best practices on how I should go about this? Should I just get the JSON as a string, pass the string to the wearable, and parse it afterwards? I do not know if this would be inefficient if the string were very large though, considering I do not know how large the list of JSON objects could get. Also I know it is possible to parse a string with GSON, but I do not know if this is inefficient as well.
Upvotes: 0
Views: 1869
Reputation: 15155
I found the Android Wear Sample XYZTouristAttractions, and this is my current code based on that example. Firstly, I created a shared library to reduce duplicate code. This shared library contains the Item
class that holds the JSON data. I use this class in my DownloadArrayListTask
on the handheld, which takes the JSON Object from the input stream and puts the data in an ArrayList
of Item
objects.
@Override
protected ArrayList<Item> doInBackground(URL... params) {
URL url = params[0];
ArrayList<Item> items = new ArrayList<>();
try {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
InputStreamReader input = new InputStreamReader(connection.getInputStream());
Type listType = new TypeToken<Map<String, ArrayList<Item>>>(){}.getType();
Gson gson = new GsonBuilder().create();
Map<String, ArrayList<Item>> treeMap = gson.fromJson(input, listType);
items = treeeMap.get("items");
input.close();
} finally {
connection.disconnect();
}
} catch (IOException exception) {
exception.printStackTrace();
}
return items
}
This ArrayList
is broken apart into strings in the DataLayerListenerService
and placed in an ArrayList
of DataMap
objects for the wearable to receive.
@Override
public void onMessageReceived(MessageEvent messageEvent) {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API).build();
ConnectionResult connectionResult = googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
if(!connectionResult.isSuccess()) {
Log.e(TAG, "Failed to connect to Google API Client");
return;
}
if(messageEvent.getPath().equals("/update_path") {
ArrayList<Item> items = new ArrayList<>()
try {
items = new DownloadArrayListTask().execute(new URL("http://my_url")).get();
} catch (MalformedURLException | InterruptedException | ExecutionException exception) {
exception.printStackTrace();
}
ArrayList<DataMap> itemMaps = new ArrayList<>(items.size());
for(Item item : items) {
DataMap dataMap = new DataMap();
dataMap.putString("title", item.getTitle());
dataMap.putString("element1", item.getElement1());
dataMap.putString("element2", item.getElement2());
itemMaps.add(dataMap);
}
new Thread(new Runnable() {
@Override
public void run() {
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for(Node node : nodes.getNodes()) {
PutDataMapRequest dataMapRequest = PutDataMapRequest.create("/item_path");
dataMapRequest.getDataMap().putDataMapArrayList("item_key", itemMaps);
PutDataRequest request = dataMapRequest.asPutDataRequest();
DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleApiClient, request).await();
if(!result.getStatus().isSuccess()) {
Log.d(TAG, "Failed to send data");
}
}
}
}).start();
}
}
Then the wearable device receives this ArrayList
of DataMap
objects, and uses its own AsyncTask
to put them back into an ArrayList
of Item
objects.
@Override
protected ArrayList<Item> doInBackground(Uri... params) {
Uri uri = params[0];
ArrayList<Item> items = new ArrayList<>();
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API).build();
ConnectionResult connectionResult = googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
if(!connectionResult.isSuccess()) {
Log.e(TAG, "Failed to connect to Google API Client");
return;
}
DataItemBuffer results = Wearable.DataApi.getDataItems(googleApiClient).await();
if(results.getStatus().isSuccess() && results.getCount() != 0) {
DataMapItem dataMapItem = DataMapItem.fromDataItem(results.get(0);
List<DataMap> data = dataMapItem.getDataMap().getDataMapArrayList("item_key");
for(DataMap dataItem : data) {
Item item = new Item(dataItem.getString("title"),
dataItem.getString("element1"),
dataItem.getString("element2"));
items.add(item);
}
} else {
Log.d(TAG, "Failed to obtain data");
} return items;
}
Upvotes: 1
Reputation: 3525
The general recommendations are to send to the wearable the minimum data it needs, and to make the maximum processing on the handheld device, as it has much more processing power (and battery).
According to the documentation:
https://developers.google.com/android/reference/com/google/android/gms/wearable/DataItem.html#setData(byte[])
The current maximum data item size limit is approximtely 100k. Data items should generally be much smaller than this limit.
You should make the decision if this suits your needs - if it is possible to receive very big JSON, maybe you can split it on the handheld device side, or you can filter some of the data inside.
If you think that this would not be possible for your case, then maybe you should revise the requirements you have!
I am processing JSON using GSON directly on the wearable, and for my use-cases it is working good enough.
Upvotes: 1