Java tutorial
/* * Copyright 2015 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 org.physical_web.physicalweb; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.util.Base64; import android.webkit.URLUtil; import org.uribeacon.scan.util.RangingUtils; import org.uribeacon.scan.util.RegionResolver; import org.json.JSONException; import org.json.JSONObject; import java.io.ByteArrayOutputStream; /** * This class holds data about a Physical Web Object and its url. * * A physical web object is any source of a broadcasted url. */ class PwoMetadata implements Comparable<PwoMetadata> { private static final String URL_KEY = "deviceAddress"; private static final String IS_PUBLIC_KEY = "isPublic"; private static final String SCAN_MILLIS_KEY = "scanMillis"; private static final String PWS_TRIP_MILLIS_KEY = "pwsTripMillis"; private static final String BLE_METADATA_KEY = "bleMetadata"; private static final String URL_METADATA_KEY = "urlMetadata"; String url; boolean isPublic; long scanMillis; long pwsTripMillis; BleMetadata bleMetadata; UrlMetadata urlMetadata; /** * A container class for ble-specific metadata. */ public static class BleMetadata { private static final String DEVICE_ADDRESS_KEY = "deviceAddress"; private static final String RSSI_KEY = "rssi"; private static final String TX_POWER_KEY = "txPower"; String deviceAddress; int rssi; int txPower; private static RegionResolver sRegionResolver; public BleMetadata(String deviceAddress, int rssi, int txPower) { this.deviceAddress = deviceAddress; this.rssi = rssi; this.txPower = txPower; } public JSONObject toJsonObj() throws JSONException { JSONObject jsonObj = new JSONObject(); jsonObj.put(DEVICE_ADDRESS_KEY, deviceAddress); jsonObj.put(RSSI_KEY, rssi); jsonObj.put(TX_POWER_KEY, txPower); return jsonObj; } public String toJsonStr() throws JSONException { return toJsonObj().toString(); } public static BleMetadata fromJsonObj(JSONObject jsonObj) throws JSONException { BleMetadata bleMetadata = new BleMetadata(jsonObj.getString(DEVICE_ADDRESS_KEY), jsonObj.getInt(RSSI_KEY), jsonObj.getInt(TX_POWER_KEY)); return bleMetadata; } public static BleMetadata fromJsonStr(String jsonStr) throws JSONException { return fromJsonObj(new JSONObject(jsonStr)); } private static RegionResolver getRegionResolver() { if (sRegionResolver == null) { sRegionResolver = new RegionResolver(); } return sRegionResolver; } public void updateRegionInfo() { getRegionResolver().onUpdate(this.deviceAddress, this.rssi, this.txPower); } public int getSmoothedRssi() { return getRegionResolver().getSmoothedRssi(deviceAddress); } public double getDistance() { return getRegionResolver().getDistance(deviceAddress); } public int getRegion() { return getRegionResolver().getRegion(deviceAddress); } public String getRegionString() { return RangingUtils.toString(getRegion()); } } /** * A container class for a url's fetched metadata. * The metadata consists of the title, site url, description, * iconUrl and the icon (or favicon). * This data is scraped via a server that receives a url * and returns a json blob. */ public static class UrlMetadata implements Comparable<UrlMetadata> { private static final String ID_KEY = "id"; private static final String SITE_URL_KEY = "siteUrl"; private static final String DISPLAY_URL_KEY = "displayUrl"; private static final String TITLE_KEY = "title"; private static final String DESCRIPTION_KEY = "description"; private static final String ICON_URL_KEY = "iconUrl"; private static final String ICON_KEY = "icon"; private static final String RANK_KEY = "rank"; public String id; public String siteUrl; public String displayUrl; public String title; public String description; public String iconUrl; public Bitmap icon; public double rank; public UrlMetadata() { } public int compareTo(UrlMetadata other) { int rankCompare = ((Double) rank).compareTo(other.rank); if (rankCompare != 0) { return rankCompare; } // If ranks are equal, compare based on title return title.compareTo(other.title); } public JSONObject toJsonObj() throws JSONException { JSONObject jsonObj = new JSONObject(); jsonObj.put(ID_KEY, id); jsonObj.put(SITE_URL_KEY, siteUrl); jsonObj.put(DISPLAY_URL_KEY, displayUrl); jsonObj.put(TITLE_KEY, title); jsonObj.put(DESCRIPTION_KEY, description); jsonObj.put(ICON_URL_KEY, iconUrl); if (icon != null) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); icon.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] bitmapData = stream.toByteArray(); jsonObj.put(ICON_KEY, Base64.encodeToString(bitmapData, Base64.DEFAULT)); } jsonObj.put(RANK_KEY, rank); return jsonObj; } public String toJsonStr() throws JSONException { return toJsonObj().toString(); } public static UrlMetadata fromJsonObj(JSONObject jsonObj) throws JSONException { UrlMetadata urlMetadata = new UrlMetadata(); urlMetadata.id = jsonObj.getString(ID_KEY); urlMetadata.siteUrl = jsonObj.getString(SITE_URL_KEY); urlMetadata.displayUrl = jsonObj.getString(DISPLAY_URL_KEY); urlMetadata.title = jsonObj.getString(TITLE_KEY); urlMetadata.description = jsonObj.getString(DESCRIPTION_KEY); urlMetadata.iconUrl = jsonObj.getString(ICON_URL_KEY); if (jsonObj.has(ICON_KEY)) { byte[] bitmapData = Base64.decode(jsonObj.getString(ICON_KEY), Base64.DEFAULT); urlMetadata.icon = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length); } urlMetadata.rank = jsonObj.getDouble(RANK_KEY); return urlMetadata; } public static UrlMetadata fromJsonStr(String jsonStr) throws JSONException { return fromJsonObj(new JSONObject(jsonStr)); } } public PwoMetadata(String url, long scanMillis) { this.url = url; this.scanMillis = scanMillis; // Default isPublic to true isPublic = true; } public void setUrlMetadata(UrlMetadata urlMetadata, long pwsTripMillis) { this.urlMetadata = urlMetadata; this.pwsTripMillis = pwsTripMillis; } public void setBleMetadata(String deviceAddress, int rssi, int txPower) { this.bleMetadata = new BleMetadata(deviceAddress, rssi, txPower); } public boolean hasBleMetadata() { return bleMetadata != null; } public boolean hasUrlMetadata() { return urlMetadata != null; } public String getNavigableUrl(Context context) { String urlToNavigateTo = url; if (hasUrlMetadata()) { String siteUrl = urlMetadata.siteUrl; if (siteUrl != null) { urlToNavigateTo = siteUrl; } } if (!URLUtil.isNetworkUrl(urlToNavigateTo)) { urlToNavigateTo = "http://" + urlToNavigateTo; } return urlToNavigateTo; } public Intent createNavigateToUrlIntent(Context context) { String urlToNavigateTo = getNavigableUrl(context); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(urlToNavigateTo)); return intent; } public PendingIntent createNavigateToUrlPendingIntent(Context context) { Intent intent = createNavigateToUrlIntent(context); int requestID = (int) System.currentTimeMillis(); PendingIntent pendingIntent = PendingIntent.getActivity(context, requestID, intent, 0); return pendingIntent; } public int compareTo(PwoMetadata other) { // Give preference to the PWO that has url metatada if (!hasUrlMetadata()) { return 1; } if (!other.hasUrlMetadata()) { return -1; } return urlMetadata.compareTo(other.urlMetadata); } public JSONObject toJsonObj() throws JSONException { JSONObject jsonObj = new JSONObject(); jsonObj.put(URL_KEY, url); jsonObj.put(SCAN_MILLIS_KEY, scanMillis); jsonObj.put(PWS_TRIP_MILLIS_KEY, pwsTripMillis); if (hasBleMetadata()) { jsonObj.put(BLE_METADATA_KEY, bleMetadata.toJsonObj()); } if (hasUrlMetadata()) { jsonObj.put(URL_METADATA_KEY, urlMetadata.toJsonObj()); } return jsonObj; } public String toJsonStr() throws JSONException { return toJsonObj().toString(); } public static PwoMetadata fromJsonObj(JSONObject jsonObj) throws JSONException { PwoMetadata pwoMetadata = new PwoMetadata(jsonObj.getString(URL_KEY), jsonObj.getLong(SCAN_MILLIS_KEY)); pwoMetadata.pwsTripMillis = jsonObj.getLong(PWS_TRIP_MILLIS_KEY); if (jsonObj.has(BLE_METADATA_KEY)) { pwoMetadata.bleMetadata = BleMetadata.fromJsonObj(jsonObj.getJSONObject(BLE_METADATA_KEY)); } if (jsonObj.has(URL_METADATA_KEY)) { pwoMetadata.urlMetadata = UrlMetadata.fromJsonObj(jsonObj.getJSONObject(URL_METADATA_KEY)); } return pwoMetadata; } public static PwoMetadata fromJsonStr(String jsonStr) throws JSONException { return fromJsonObj(new JSONObject(jsonStr)); } }