blob: f1abd3cbc2dea0f3097d112f027a5a11861bbceb [file] [log] [blame]
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* 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 com.google.samples.apps.iosched.nearby;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import android.util.Patterns;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import static com.google.samples.apps.iosched.Config.METADATA_URL;
import static com.google.samples.apps.iosched.util.LogUtils.makeLogTag;
/**
* Class for resolving BLE device metadata via proxy.
*/
public class MetadataResolver {
static String TAG = makeLogTag("MetadataResolver");
static Map<String, String> mDeviceUrlMap;
static RequestQueue mRequestQueue;
static boolean mIsInitialized = false;
public static void initialize(Context context) {
mDeviceUrlMap = new HashMap<String, String>();
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(context);
}
mIsInitialized = true;
}
public static String getURLForDevice(NearbyDevice device) {
if (!mIsInitialized) {
Log.e(TAG, "Not initialized.");
return null;
}
// If the device name is already a URL, use it.
String deviceName = device.getName();
String url = deviceName;
if (Patterns.WEB_URL.matcher(deviceName).matches()) {
// TODO: Improve this.
// For now, if there's no scheme present, add a default http:// scheme.
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = "http://" + url;
}
} else {
// Otherwise, try doing the lookup.
url = mDeviceUrlMap.get(deviceName);
}
return url;
}
public static void getBatchMetadata(List<NearbyDevice> batchList) {
if (!mIsInitialized) {
Log.e(TAG, "Not initialized.");
return;
}
JSONObject jsonObj = createRequestObject(batchList);
Map<String, NearbyDevice> deviceMap = new HashMap<String, NearbyDevice>();
for (int i = 0; i < batchList.size(); i++) {
NearbyDevice nearbyDevice = batchList.get(i);
deviceMap.put(nearbyDevice.getUrl(), nearbyDevice);
}
JsonObjectRequest jsObjRequest = createMetadataRequest(jsonObj, deviceMap);
// Queue the request
mRequestQueue.add(jsObjRequest);
}
private static JsonObjectRequest createMetadataRequest(JSONObject jsonObj, final Map<String, NearbyDevice> deviceMap) {
return new JsonObjectRequest(
METADATA_URL,
jsonObj,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonResponse) {
try {
JSONArray foundMetaData = jsonResponse.getJSONArray("metadata");
int deviceCount = foundMetaData.length();
for (int i = 0; i < deviceCount; i++) {
JSONObject deviceData = foundMetaData.getJSONObject(i);
String title = "Unknown name";
String url = "Unknown url";
String description = "Unknown description";
String iconUrl = "/favicon.ico";
String id = deviceData.getString("id");
if (deviceData.has("title")) {
title = deviceData.getString("title");
}
if (deviceData.has("url")) {
url = deviceData.getString("url");
}
if (deviceData.has("description")) {
description = deviceData.getString("description");
}
if (deviceData.has("icon")) {
// We might need to do some magic here.
iconUrl = deviceData.getString("icon");
}
// Provisions for a favicon specified as a relative URL.
if (!iconUrl.startsWith("http")) {
// Lets just assume we are dealing with a relative path.
Uri fullUri = Uri.parse(url);
Uri.Builder builder = fullUri.buildUpon();
// Append the default favicon path to the URL.
builder.path(iconUrl);
iconUrl = builder.toString();
}
DeviceMetadata deviceMetadata = new DeviceMetadata();
deviceMetadata.title = title;
deviceMetadata.description = description;
deviceMetadata.siteUrl = url;
deviceMetadata.iconUrl = iconUrl;
downloadIcon(deviceMetadata, deviceMap.get(id));
// Look up the device from the input and update the data
deviceMap.get(id).onDeviceInfo(deviceMetadata);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Log.i(TAG, "VolleyError: " + volleyError.toString());
}
}
);
}
private static JSONObject createRequestObject(List<NearbyDevice> devices) {
JSONObject jsonObj = new JSONObject();
try {
JSONArray urlArray = new JSONArray();
for(int dIdx = 0; dIdx < devices.size(); dIdx++) {
NearbyDevice device = devices.get(dIdx);
JSONObject urlObject = new JSONObject();
urlObject.put("url", device.getUrl());
urlObject.put("rssi", device.getLastRSSI());
urlArray.put(urlObject);
}
JSONObject location = new JSONObject();
location.put("lat", 49.129837);
location.put("lon", 120.38142);
jsonObj.put("location", location);
jsonObj.put("objects", urlArray);
} catch(JSONException ex) {
}
return jsonObj;
}
/**
* Asynchronously download the image for the nearby device.
* @param metadata
* @param listener
*/
private static void downloadIcon(final DeviceMetadata metadata, final OnMetadataListener listener) {
ImageRequest imageRequest = new ImageRequest(metadata.iconUrl, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
Log.i(TAG, "Got an image: " + response.toString());
metadata.icon = response;
listener.onDeviceInfo(metadata);
}
}, 0, 0, null, null);
mRequestQueue.add(imageRequest);
}
public interface OnMetadataListener {
public void onDeviceInfo(DeviceMetadata deviceMetadata);
}
}