From 868593cfd3790517f6b30e01807be726907e8eac Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Wed, 26 Jul 2017 18:12:12 +0200 Subject: [PATCH] Pebble: further improvements to the background webview - the webview is not static anymore (but its holder is) - the openweathermap calls of type weather and forecast are now supported (as properly as possible) - assemble the main JSON messages in the weather receiver, as info are lost afterwards - switch to Uri parsing instead of String (also unify handling of legacy and new requests) - attempt to address most of the lints/warnings of AS - remove printStackTrace in favor of LOG.warn --- .../gadgetbridge/util/WebViewSingleton.java | 233 ++++++++++-------- .../notification/ParcelableWeather2.java | 113 ++++++++- 2 files changed, 235 insertions(+), 111 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/WebViewSingleton.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/WebViewSingleton.java index 7042dd34e..42fe21a35 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/WebViewSingleton.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/WebViewSingleton.java @@ -1,6 +1,7 @@ package nodomain.freeyourgadget.gadgetbridge.util; import android.Manifest; +import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -15,6 +16,7 @@ import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; +import android.util.SparseArray; import android.webkit.ConsoleMessage; import android.webkit.JavascriptInterface; import android.webkit.ValueCallback; @@ -47,6 +49,7 @@ import java.security.NoSuchAlgorithmException; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; import java.util.Scanner; import java.util.UUID; @@ -54,13 +57,12 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppMessage; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.Weather; -import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; public class WebViewSingleton { private static final Logger LOG = LoggerFactory.getLogger(WebViewSingleton.class); - private static WebView instance = null; + private WebView instance = null; private MutableContextWrapper contextWrapper; private Looper mainLooper; private static WebViewSingleton webViewSingleton = new WebViewSingleton(); @@ -70,23 +72,23 @@ public class WebViewSingleton { } public static synchronized WebView getInstance(Activity context) { - if (instance == null) { + if (webViewSingleton.instance == null) { webViewSingleton.contextWrapper = new MutableContextWrapper(context); webViewSingleton.mainLooper = context.getMainLooper(); - instance = new WebView(webViewSingleton.contextWrapper); - instance.setWillNotDraw(true); - instance.clearCache(true); - instance.setWebViewClient(new GBWebClient()); - instance.setWebChromeClient(new GBChromeClient()); - instance.setWebContentsDebuggingEnabled(true); - WebSettings webSettings = instance.getSettings(); + webViewSingleton.instance = new WebView(webViewSingleton.contextWrapper); + WebView.setWebContentsDebuggingEnabled(true); + webViewSingleton.instance.setWillNotDraw(true); + webViewSingleton.instance.clearCache(true); + webViewSingleton.instance.setWebViewClient(new GBWebClient()); + webViewSingleton.instance.setWebChromeClient(new GBChromeClient()); + WebSettings webSettings = webViewSingleton.instance.getSettings(); webSettings.setJavaScriptEnabled(true); //needed to access the DOM webSettings.setDomStorageEnabled(true); //needed for localstorage webSettings.setDatabaseEnabled(true); } - return instance; + return webViewSingleton.instance; } public static void updateActivityContext(Activity context) { @@ -97,7 +99,7 @@ public class WebViewSingleton { @NonNull public static WebView getWebView() { - return instance; + return webViewSingleton.instance; } public static void runJavascriptInterface(GBDevice device, UUID uuid) { @@ -110,9 +112,9 @@ public class WebViewSingleton { new Handler(webViewSingleton.mainLooper).post(new Runnable() { @Override public void run() { - instance.removeJavascriptInterface("GBjs"); - instance.addJavascriptInterface(jsInterface, "GBjs"); - instance.loadUrl("file:///android_asset/app_config/configure.html?rand=" + Math.random() * 500); + webViewSingleton.instance.removeJavascriptInterface("GBjs"); + webViewSingleton.instance.addJavascriptInterface(jsInterface, "GBjs"); + webViewSingleton.instance.loadUrl("file:///android_asset/app_config/configure.html?rand=" + Math.random() * 500); } }); } @@ -121,7 +123,7 @@ public class WebViewSingleton { public static void appMessage(GBDeviceEventAppMessage message) { - if (instance == null) { + if (webViewSingleton.instance == null) { LOG.warn("WEBVIEW is not initialized, cannot send appMessages to it"); return; } @@ -131,7 +133,7 @@ public class WebViewSingleton { new Handler(webViewSingleton.mainLooper).post(new Runnable() { @Override public void run() { - instance.evaluateJavascript("Pebble.evaluate('appmessage',[" + appMessage + "]);", new ValueCallback() { + webViewSingleton.instance.evaluateJavascript("Pebble.evaluate('appmessage',[" + appMessage + "]);", new ValueCallback() { @Override public void onReceiveValue(String s) { //TODO: the message should be acked here instead of in PebbleIoThread @@ -146,14 +148,14 @@ public class WebViewSingleton { new Handler(webViewSingleton.mainLooper).post(new Runnable() { @Override public void run() { - if (instance != null) { - instance.setWebChromeClient(null); - instance.setWebViewClient(null); - instance.clearHistory(); - instance.clearCache(true); - instance.loadUrl("about:blank"); - instance.freeMemory(); - instance.pauseTimers(); + if (webViewSingleton.instance != null) { + webViewSingleton.instance.setWebChromeClient(null); + webViewSingleton.instance.setWebViewClient(null); + webViewSingleton.instance.clearHistory(); + webViewSingleton.instance.clearCache(true); + webViewSingleton.instance.loadUrl("about:blank"); +// webViewSingleton.instance.freeMemory(); + webViewSingleton.instance.pauseTimers(); // instance.destroy(); // instance = null; // contextWrapper = null; @@ -168,7 +170,7 @@ public class WebViewSingleton { double altitude; float latitude, longitude, accuracy, speed; - public CurrentPosition() { + private CurrentPosition() { Prefs prefs = GBApplication.getPrefs(); this.latitude = prefs.getFloat("location_latitude", 0); this.longitude = prefs.getFloat("location_longitude", 0); @@ -188,15 +190,12 @@ public class WebViewSingleton { this.latitude = (float) lastKnownLocation.getLatitude(); this.longitude = (float) lastKnownLocation.getLongitude(); - this.accuracy = (float) lastKnownLocation.getAccuracy(); + this.accuracy = lastKnownLocation.getAccuracy(); this.altitude = (float) lastKnownLocation.getAltitude(); - this.speed = (float) lastKnownLocation.getSpeed(); - + this.speed = lastKnownLocation.getSpeed(); } } } - - } } @@ -204,60 +203,79 @@ public class WebViewSingleton { return null; } + private static JSONObject coordObject(CurrentPosition currentPosition) throws JSONException { + JSONObject coord = new JSONObject(); + coord.put("lat", currentPosition.latitude); + coord.put("lon", currentPosition.longitude); + return coord; + } - private static WebResourceResponse mimicOpenWeatherMapResponse(String origialRequestURL) { - WeatherSpec weatherSpec = Weather.getInstance().getWeatherSpec(); + private static JSONObject sysObject(CurrentPosition currentPosition) throws JSONException { + GregorianCalendar[] sunrise = SPA.calculateSunriseTransitSet(new GregorianCalendar(), currentPosition.latitude, currentPosition.longitude, DeltaT.estimate(new GregorianCalendar())); - if (weatherSpec == null) { + JSONObject sys = new JSONObject(); + sys.put("country", "World"); + sys.put("sunrise", (sunrise[0].getTimeInMillis() / 1000)); + sys.put("sunset", (sunrise[2].getTimeInMillis() / 1000)); + + return sys; + } + + private static void convertTemps(JSONObject main, String units) throws JSONException { + if ("metric".equals(units)) { + main.put("temp", (int) main.get("temp") - 273); + main.put("temp_min", (int) main.get("temp_min") - 273); + main.put("temp_max", (int) main.get("temp_max") - 273); + } else if ("imperial".equals(units)) { //it's 2017... this is so sad + main.put("temp", ((int) (main.get("temp")) - 273.15f) * 1.8f + 32); + main.put("temp_min", ((int) (main.get("temp_min")) - 273.15f) * 1.8f + 32); + main.put("temp_max", ((int) (main.get("temp_max")) - 273.15f) * 1.8f + 32); + } + } + + private static WebResourceResponse mimicOpenWeatherMapResponse(String type, String units) { + + if (Weather.getInstance() == null || Weather.getInstance().getWeather2() == null) { LOG.warn("WEBVIEW - Weather instance is null, cannot update weather"); return null; } - //location block CurrentPosition currentPosition = new CurrentPosition(); - GregorianCalendar[] sunrise = SPA.calculateSunriseTransitSet(new GregorianCalendar(), currentPosition.latitude, currentPosition.longitude, DeltaT.estimate(new GregorianCalendar())); - JSONObject resp = new JSONObject(); - JSONObject coord = new JSONObject(); - JSONObject sys = new JSONObject(); - JSONArray weather = new JSONArray(); - JSONObject currCond = new JSONObject(); - JSONObject main = new JSONObject(); try { - coord.put("lat", currentPosition.latitude); - coord.put("lon", currentPosition.longitude); + JSONObject resp; - sys.put("country", "World"); - sys.put("sunrise", (sunrise[0].getTimeInMillis() / 1000)); - sys.put("sunset", (sunrise[2].getTimeInMillis() / 1000)); + if ("weather".equals(type) && Weather.getInstance().getWeather2().reconstructedWeather != null) { + resp = new JSONObject(Weather.getInstance().getWeather2().reconstructedWeather.toString()); - currCond.put("id", weatherSpec.currentConditionCode); - currCond.put("main", weatherSpec.currentCondition); - currCond.put("icon", Weather.mapToOpenWeatherMapIcon(weatherSpec.currentConditionCode)); - weather.put(currCond); + JSONObject main = resp.getJSONObject("main"); - int currentTemp = weatherSpec.currentTemp; - int todayMinTemp = weatherSpec.todayMinTemp; - int todayMaxTemp = weatherSpec.todayMaxTemp; + convertTemps(main, units); //caller might want different units - if (origialRequestURL.contains("units=metric")) { // not nice but WebResourceRequest is not in KitKat - currentTemp -= 273; - todayMinTemp -= 273; - todayMaxTemp -= 273; + resp.put("cod", 200); + resp.put("coord", coordObject(currentPosition)); + resp.put("sys", sysObject(currentPosition)); + } else if ("forecast".equals(type) && Weather.getInstance().getWeather2().reconstructedForecast != null) { + resp = new JSONObject(Weather.getInstance().getWeather2().reconstructedForecast.toString()); + + JSONObject city = resp.getJSONObject("city"); + city.put("coord", coordObject(currentPosition)); + + JSONArray list = resp.getJSONArray("list"); + for (int i = 0, size = list.length(); i < size; i++) { + JSONObject item = list.getJSONObject(i); + JSONObject main = item.getJSONObject("main"); + convertTemps(main, units); //caller might want different units + } + + resp.put("cod", 200); + } else { + LOG.warn("WEBVIEW - cannot mimick request of type " + type + " (unsupported or lack of data)"); + return null; } - main.put("temp", currentTemp); - main.put("temp_min", todayMinTemp); - main.put("temp_max", todayMaxTemp); - main.put("name", weatherSpec.location); - - resp.put("cod", 200); - resp.put("coord", coord); - resp.put("sys", sys); - resp.put("weather", weather); - resp.put("main", main); LOG.info("WEBVIEW - mimic openweather response" + resp.toString()); - HashMap headers = new HashMap<>(); + Map headers = new HashMap<>(); headers.put("Access-Control-Allow-Origin", "*"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -269,7 +287,7 @@ public class WebViewSingleton { return new WebResourceResponse("application/json", "utf-8", new ByteArrayInputStream(resp.toString().getBytes())); } } catch (JSONException e) { - e.printStackTrace(); + LOG.warn(e.getMessage()); } return null; @@ -297,39 +315,50 @@ public class WebViewSingleton { } private static class GBWebClient extends WebViewClient { + @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - LOG.debug("WEBVIEW shouldInterceptRequest URL" + request.getUrl()); - if (request.getUrl().toString().startsWith("http://api.openweathermap.org") || request.getUrl().toString().startsWith("https://api.openweathermap.org")) { - return mimicOpenWeatherMapResponse(request.getUrl().toString()); - } else { - LOG.debug("WEBVIEW request:" + request.getUrl().toString() + " not intercepted"); - } - } + Uri parsedUri = request.getUrl(); + LOG.debug("WEBVIEW shouldInterceptRequest URL: " + parsedUri.toString()); + WebResourceResponse mimickedReply = mimicReply(parsedUri); + if (mimickedReply != null) + return mimickedReply; return super.shouldInterceptRequest(view, request); } @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { - LOG.debug("WEBVIEW shouldInterceptRequest URL (legacy)" + url); - if (url.startsWith("http://api.openweathermap.org") || url.startsWith("https://api.openweathermap.org")) { - return mimicOpenWeatherMapResponse(url); - } else { - LOG.debug("WEBVIEW request:" + url + " not intercepted"); - } + LOG.debug("WEBVIEW shouldInterceptRequest URL (legacy): " + url); + Uri parsedUri = Uri.parse(url); + WebResourceResponse mimickedReply = mimicReply(parsedUri); + if (mimickedReply != null) + return mimickedReply; return super.shouldInterceptRequest(view, url); } + private WebResourceResponse mimicReply(Uri requestedUri) { + if (requestedUri.getHost().contains("openweathermap.org")) { + LOG.debug("WEBVIEW request to openweathermap.org detected of type: " + requestedUri.getLastPathSegment() + " params: " + requestedUri.getQuery()); + return mimicOpenWeatherMapResponse(requestedUri.getLastPathSegment(), requestedUri.getQueryParameter("units")); + } else { + LOG.debug("WEBVIEW request:" + requestedUri.toString() + " not intercepted"); + } + return null; + } + @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - if (url.startsWith("http://") || url.startsWith("https://")) { + Uri parsedUri = Uri.parse(url); + + if (parsedUri.getScheme().startsWith("http")) { Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); GBApplication.getContext().startActivity(i); - } else { + } else if (parsedUri.getScheme().startsWith("pebblejs")) { url = url.replaceFirst("^pebblejs://close#", "file:///android_asset/app_config/configure.html?config=true&json="); view.loadUrl(url); + } else { + LOG.debug("WEBVIEW Ignoring unhandled scheme: " + parsedUri.getScheme()); } return true; @@ -341,21 +370,21 @@ public class WebViewSingleton { File destDir = new File(FileUtils.getExternalFilesDir() + "/pbw-cache"); File configurationFile = new File(destDir, uuid.toString() + ".json"); if (configurationFile.exists()) { - String jsonstring = FileUtils.getStringFromFile(configurationFile); - JSONObject json = new JSONObject(jsonstring); + String jsonString = FileUtils.getStringFromFile(configurationFile); + JSONObject json = new JSONObject(jsonString); return json.getJSONObject("appKeys"); } } catch (IOException | JSONException e) { - e.printStackTrace(); + LOG.warn(e.getMessage()); } return null; } - public static String parseIncomingAppMessage(String msg, UUID uuid) { + private static String parseIncomingAppMessage(String msg, UUID uuid) { JSONObject jsAppMessage = new JSONObject(); JSONObject knownKeys = getAppConfigurationKeys(uuid); - HashMap appKeysMap = new HashMap(); + SparseArray appKeysMap = new SparseArray<>(); String inKey, outKey; //knownKeys contains "name"->"index", we need to reverse that @@ -388,7 +417,7 @@ public class WebViewSingleton { jsAppMessage.put("payload", outgoing); } catch (JSONException e) { - e.printStackTrace(); + LOG.warn(e.getMessage()); } return jsAppMessage.toString(); } @@ -398,7 +427,7 @@ public class WebViewSingleton { UUID mUuid; GBDevice device; - public JSInterface(GBDevice device, UUID mUuid) { + private JSInterface(GBDevice device, UUID mUuid) { LOG.debug("Creating JS interface for UUID: " + mUuid.toString()); this.device = device; this.mUuid = mUuid; @@ -456,7 +485,7 @@ public class WebViewSingleton { GBApplication.deviceService().onAppConfiguration(this.mUuid, out.toString()); } catch (JSONException e) { - e.printStackTrace(); + LOG.warn(e.getMessage()); } } @@ -470,7 +499,7 @@ public class WebViewSingleton { //TODO: use real info wi.put("language", "en"); } catch (JSONException e) { - e.printStackTrace(); + LOG.warn(e.getMessage()); } //Json not supported apparently, we need to cast back and forth return wi.toString(); @@ -486,7 +515,7 @@ public class WebViewSingleton { return "file:///" + configurationFile.getAbsolutePath(); } } catch (IOException e) { - e.printStackTrace(); + LOG.warn(e.getMessage()); } return null; } @@ -501,7 +530,7 @@ public class WebViewSingleton { } } catch (IOException e) { GB.toast("Error reading presets", Toast.LENGTH_LONG, GB.ERROR); - e.printStackTrace(); + LOG.warn(e.getMessage()); } return null; } @@ -519,7 +548,7 @@ public class WebViewSingleton { GB.toast("Presets stored", Toast.LENGTH_SHORT, GB.INFO); } catch (IOException e) { GB.toast("Error storing presets", Toast.LENGTH_LONG, GB.ERROR); - e.printStackTrace(); + LOG.warn(e.getMessage()); } } @@ -537,12 +566,12 @@ public class WebViewSingleton { digest.update(bytes, 0, bytes.length); bytes = digest.digest(); final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < bytes.length; i++) { - sb.append(String.format("%02X", bytes[i])); + for (byte aByte : bytes) { + sb.append(String.format("%02X", aByte)); } return sb.toString().toLowerCase(); } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { - e.printStackTrace(); + LOG.warn(e.getMessage()); return prefix; } } @@ -577,7 +606,7 @@ public class WebViewSingleton { geoPosition.put("coords", coords); } catch (JSONException e) { - e.printStackTrace(); + LOG.warn(e.getMessage()); } LOG.info("WEBVIEW - geo position" + geoPosition.toString()); return geoPosition.toString(); diff --git a/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java b/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java index 2911885c1..70870a08d 100644 --- a/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java +++ b/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java @@ -20,9 +20,14 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import nodomain.freeyourgadget.gadgetbridge.model.Weather; + public class ParcelableWeather2 implements Parcelable { private static final Logger LOG = LoggerFactory.getLogger(ParcelableWeather2.class); @@ -35,15 +40,17 @@ public class ParcelableWeather2 implements Parcelable { public int currentTemp = 0; public String currentCondition = ""; - String[] currentConditionType = null; + private String[] currentConditionType = null; public int currentConditionCode = 3200; - String[] forecastConditionType = null; + private String[] forecastConditionType = null; public int forecastConditionCode = 3200; public int todayLowTemp = 0; public int todayHighTemp = 0; public int forecastLowTemp = 0; public int forecastHighTemp = 0; + public JSONObject reconstructedWeather = null; + public JSONObject reconstructedForecast = null; private ParcelableWeather2(Parcel in) { int version = in.readInt(); @@ -59,6 +66,11 @@ public class ParcelableWeather2 implements Parcelable { int conditions = bundle.getInt("weather_conditions"); if (conditions > 0) { Bundle conditionBundle = in.readBundle(); + reconstructedWeather = new JSONObject(); + JSONArray weather = new JSONArray(); + JSONObject condition = new JSONObject(); + JSONObject main = new JSONObject(); + currentCondition = conditionBundle.getString("weather_condition_text"); conditionBundle.getStringArray("weather_condition_types"); currentTemp = conditionBundle.getInt("weather_current_temp"); @@ -67,22 +79,105 @@ public class ParcelableWeather2 implements Parcelable { currentConditionCode = weatherConditionTypesToOpenWeatherMapIds(currentConditionType[0]); todayLowTemp = conditionBundle.getInt("weather_low_temp"); todayHighTemp = conditionBundle.getInt("weather_high_temp"); + try { + condition.put("id", currentConditionCode); + condition.put("main", currentCondition); + condition.put("icon", Weather.mapToOpenWeatherMapIcon(currentConditionCode)); + weather.put(condition); + + main.put("temp", currentTemp); + main.put("humidity", conditionBundle.getInt("weather_humidity_value")); + main.put("temp_min", todayLowTemp); + main.put("temp_max", todayHighTemp); + main.put("name", location); + + reconstructedWeather.put("weather", weather); + reconstructedWeather.put("main", main); + + } catch (JSONException e) { + e.printStackTrace(); + } + LOG.debug("Weather JSON for WEBVIEW: " + reconstructedWeather.toString()); //fetch immediate next forecast if (--conditions > 0) { + int timeOffset = 86400000; //manually determined + reconstructedForecast = new JSONObject(); + JSONArray list = new JSONArray(); + JSONObject city = new JSONObject(); + JSONObject item = new JSONObject(); + condition = new JSONObject(); + main = new JSONObject(); + weather = new JSONArray(); Bundle forecastBundle = in.readBundle(); forecastConditionType = forecastBundle.getStringArray("weather_condition_types"); forecastConditionCode = weatherConditionTypesToOpenWeatherMapIds(forecastConditionType[0]); forecastLowTemp = forecastBundle.getInt("weather_low_temp"); forecastHighTemp = forecastBundle.getInt("weather_high_temp"); + try { + condition.put("id", forecastConditionCode); + condition.put("main", forecastBundle.getString("weather_condition_text")); + condition.put("icon", Weather.mapToOpenWeatherMapIcon(forecastConditionCode)); + weather.put(condition); + + main.put("temp", forecastBundle.getInt("weather_current_temp")); + main.put("humidity", forecastBundle.getInt("weather_humidity_value")); + main.put("temp_min", forecastLowTemp); + main.put("temp_max", forecastHighTemp); + + //forecast + //"city":{"id":3181913,"name":"Bolzano","coord":{"lat":46.4927,"lon":11.3336},"country":"IT"} + city.put("name", location); + city.put("country", "World"); + reconstructedForecast.put("city", city); + + item.put("dt", (time / 1000) + timeOffset); + item.put("main", main); + item.put("weather", weather); + list.put(item); + } catch (JSONException e) { + e.printStackTrace(); + } + + // get the rest + while (--conditions > 0) { + conditionBundle = in.readBundle(); + conditionBundle.getString("weather_condition_text"); + weatherConditionTypesToOpenWeatherMapIds(conditionBundle.getStringArray("weather_condition_types")[0]); + conditionBundle.getInt("weather_current_temp"); + item = new JSONObject(); + condition = new JSONObject(); + main = new JSONObject(); + weather = new JSONArray(); + timeOffset += 86400000; + try { + condition.put("id", weatherConditionTypesToOpenWeatherMapIds(conditionBundle.getStringArray("weather_condition_types")[0])); + condition.put("main", conditionBundle.getString("weather_condition_text")); + condition.put("icon", Weather.mapToOpenWeatherMapIcon(weatherConditionTypesToOpenWeatherMapIds(conditionBundle.getStringArray("weather_condition_types")[0]))); + weather.put(condition); + + main.put("temp", conditionBundle.getInt("weather_current_temp")); + main.put("humidity", conditionBundle.getInt("weather_humidity_value")); + main.put("temp_min", conditionBundle.getInt("weather_low_temp")); + main.put("temp_max", conditionBundle.getInt("weather_high_temp")); + + item.put("dt", (time / 1000) + timeOffset); + item.put("main", main); + item.put("weather", weather); + list.put(item); + } catch (JSONException e) { + e.printStackTrace(); + } + } + try { + reconstructedForecast.put("cnt", list.length()); + reconstructedForecast.put("list", list); + + } catch (JSONException e) { + e.printStackTrace(); + } + LOG.debug("Forecast JSON for WEBVIEW: " + reconstructedForecast.toString()); } } - // get the rest - while (--conditions > 0) { - Bundle conditionBundle = in.readBundle(); - conditionBundle.getString("weather_condition_text"); - conditionBundle.getStringArray("weather_condition_types"); - conditionBundle.getInt("weather_current_temp"); - } } public static final Creator CREATOR = new Creator() {