com.google.samples.apps.iosched.nearby.MetadataResolver.java Source code

Java tutorial

Introduction

Here is the source code for com.google.samples.apps.iosched.nearby.MetadataResolver.java

Source

/*
 * 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);
    }
}