diff --git a/app/build.gradle b/app/build.gradle
index 4d476dfe..9618e3f7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -29,5 +29,7 @@ dependencies {
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.support:design:22.2.0'
compile 'com.android.support:recyclerview-v7:22.2.0'
+ compile 'com.google.android.apps.muzei:muzei-api:2.0'
compile 'com.google.android.gms:play-services-gcm:7.5.0'
+ compile 'com.google.android.gms:play-services-location:7.5.0'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1ae3cdd4..a8893d32 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -39,6 +39,9 @@
android:protectionLevel="signature" />
+
+
+
+
+
+
+
+
+
+
+
= 300 && weatherId <= 321) {
stringId = R.string.condition_3xx;
- } else switch(weatherId) {
+ } else switch (weatherId) {
case 500:
stringId = R.string.condition_500;
break;
@@ -502,6 +502,42 @@ public static String getStringForWeatherCondition(Context context, int weatherId
return context.getString(stringId);
}
+ /*
+ * Helper method to provide the correct image according to the weather condition id returned
+ * by the OpenWeatherMap call.
+ *
+ * @param weatherId from OpenWeatherMap API response
+ * @return A string URL to an appropriate image or null if no mapping is found
+ */
+ public static String getImageUrlForWeatherCondition(int weatherId) {
+ // Based on weather code data found at:
+ // http://bugs.openweathermap.org/projects/api/wiki/Weather_Condition_Codes
+ if (weatherId >= 200 && weatherId <= 232) {
+ return "http://upload.wikimedia.org/wikipedia/commons/2/28/Thunderstorm_in_Annemasse,_France.jpg";
+ } else if (weatherId >= 300 && weatherId <= 321) {
+ return "http://upload.wikimedia.org/wikipedia/commons/a/a0/Rain_on_leaf_504605006.jpg";
+ } else if (weatherId >= 500 && weatherId <= 504) {
+ return "http://upload.wikimedia.org/wikipedia/commons/6/6c/Rain-on-Thassos.jpg";
+ } else if (weatherId == 511) {
+ return "http://upload.wikimedia.org/wikipedia/commons/b/b8/Fresh_snow.JPG";
+ } else if (weatherId >= 520 && weatherId <= 531) {
+ return "http://upload.wikimedia.org/wikipedia/commons/6/6c/Rain-on-Thassos.jpg";
+ } else if (weatherId >= 600 && weatherId <= 622) {
+ return "http://upload.wikimedia.org/wikipedia/commons/b/b8/Fresh_snow.JPG";
+ } else if (weatherId >= 701 && weatherId <= 761) {
+ return "http://upload.wikimedia.org/wikipedia/commons/e/e6/Westminster_fog_-_London_-_UK.jpg";
+ } else if (weatherId == 761 || weatherId == 781) {
+ return "http://upload.wikimedia.org/wikipedia/commons/d/dc/Raised_dust_ahead_of_a_severe_thunderstorm_1.jpg";
+ } else if (weatherId == 800) {
+ return "http://upload.wikimedia.org/wikipedia/commons/7/7e/A_few_trees_and_the_sun_(6009964513).jpg";
+ } else if (weatherId == 801) {
+ return "http://upload.wikimedia.org/wikipedia/commons/e/e7/Cloudy_Blue_Sky_(5031259890).jpg";
+ } else if (weatherId >= 802 && weatherId <= 804) {
+ return "http://upload.wikimedia.org/wikipedia/commons/5/54/Cloudy_hills_in_Elis,_Greece_2.jpg";
+ }
+ return null;
+ }
+
/**
* Returns true if the network is available or about to become available.
*
diff --git a/app/src/main/java/com/example/android/sunshine/app/muzei/WeatherMuzeiSource.java b/app/src/main/java/com/example/android/sunshine/app/muzei/WeatherMuzeiSource.java
new file mode 100644
index 00000000..dcfc24cb
--- /dev/null
+++ b/app/src/main/java/com/example/android/sunshine/app/muzei/WeatherMuzeiSource.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.example.android.sunshine.app.muzei;
+
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+
+import com.example.android.sunshine.app.MainActivity;
+import com.example.android.sunshine.app.Utility;
+import com.example.android.sunshine.app.data.WeatherContract;
+import com.example.android.sunshine.app.sync.SunshineSyncAdapter;
+import com.google.android.apps.muzei.api.Artwork;
+import com.google.android.apps.muzei.api.MuzeiArtSource;
+
+/**
+ * Muzei source that changes your background based on the current weather conditions
+ */
+public class WeatherMuzeiSource extends MuzeiArtSource {
+ private static final String[] FORECAST_COLUMNS = new String[]{
+ WeatherContract.WeatherEntry.COLUMN_WEATHER_ID,
+ WeatherContract.WeatherEntry.COLUMN_SHORT_DESC
+ };
+ // these indices must match the projection
+ private static final int INDEX_WEATHER_ID = 0;
+ private static final int INDEX_SHORT_DESC = 1;
+
+ public WeatherMuzeiSource() {
+ super("WeatherMuzeiSource");
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ super.onHandleIntent(intent);
+ boolean dataUpdated = intent != null &&
+ SunshineSyncAdapter.ACTION_DATA_UPDATED.equals(intent.getAction());
+ if (dataUpdated && isEnabled()) {
+ onUpdate(UPDATE_REASON_OTHER);
+ }
+ }
+
+ @Override
+ protected void onUpdate(int reason) {
+ String location = Utility.getPreferredLocation(this);
+ Uri weatherForLocationUri = WeatherContract.WeatherEntry.buildWeatherLocationWithStartDate(
+ location, System.currentTimeMillis());
+ Cursor cursor = getContentResolver().query(weatherForLocationUri, FORECAST_COLUMNS, null,
+ null, WeatherContract.WeatherEntry.COLUMN_DATE + " ASC");
+ if (cursor.moveToFirst()) {
+ int weatherId = cursor.getInt(INDEX_WEATHER_ID);
+ String desc = cursor.getString(INDEX_SHORT_DESC);
+
+ String imageUrl = Utility.getImageUrlForWeatherCondition(weatherId);
+ // Only publish a new wallpaper if we have a valid image
+ if (imageUrl != null) {
+ publishArtwork(new Artwork.Builder()
+ .imageUri(Uri.parse(imageUrl))
+ .title(desc)
+ .byline(location)
+ .viewIntent(new Intent(this, MainActivity.class))
+ .build());
+ }
+ }
+ cursor.close();
+ }
+}
diff --git a/app/src/main/java/com/example/android/sunshine/app/sync/SunshineSyncAdapter.java b/app/src/main/java/com/example/android/sunshine/app/sync/SunshineSyncAdapter.java
index c9275d0e..5968effe 100644
--- a/app/src/main/java/com/example/android/sunshine/app/sync/SunshineSyncAdapter.java
+++ b/app/src/main/java/com/example/android/sunshine/app/sync/SunshineSyncAdapter.java
@@ -34,6 +34,7 @@
import com.example.android.sunshine.app.R;
import com.example.android.sunshine.app.Utility;
import com.example.android.sunshine.app.data.WeatherContract;
+import com.example.android.sunshine.app.muzei.WeatherMuzeiSource;
import org.json.JSONArray;
import org.json.JSONException;
@@ -341,6 +342,7 @@ private void getWeatherDataFromJson(String forecastJsonStr,
new String[] {Long.toString(dayTime.setJulianDay(julianStartDay-1))});
updateWidgets();
+ updateMuzei();
notifyWeather();
}
Log.d(LOG_TAG, "Sync Complete. " + cVVector.size() + " Inserted");
@@ -361,6 +363,16 @@ private void updateWidgets() {
context.sendBroadcast(dataUpdatedIntent);
}
+ private void updateMuzei() {
+ // Muzei is only compatible with Jelly Bean MR1+ devices, so there's no need to update the
+ // Muzei background on lower API level devices
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ Context context = getContext();
+ context.startService(new Intent(ACTION_DATA_UPDATED)
+ .setClass(context, WeatherMuzeiSource.class));
+ }
+ }
+
private void notifyWeather() {
Context context = getContext();
//checking the last update and notify if it' the first of the day
diff --git a/app/src/main/res/drawable-hdpi/ic_current_location.png b/app/src/main/res/drawable-hdpi/ic_current_location.png
new file mode 100644
index 00000000..85e38726
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_current_location.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_current_location.png b/app/src/main/res/drawable-mdpi/ic_current_location.png
new file mode 100644
index 00000000..5684aa7d
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_current_location.png differ
diff --git a/app/src/main/res/drawable-nodpi/ic_muzei.png b/app/src/main/res/drawable-nodpi/ic_muzei.png
new file mode 100755
index 00000000..b0fe3c49
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/ic_muzei.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_current_location.png b/app/src/main/res/drawable-xhdpi/ic_current_location.png
new file mode 100644
index 00000000..7faa3455
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_current_location.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_current_location.png b/app/src/main/res/drawable-xxhdpi/ic_current_location.png
new file mode 100644
index 00000000..d3a1ab08
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_current_location.png differ
diff --git a/app/src/main/res/layout/pref_current_location.xml b/app/src/main/res/layout/pref_current_location.xml
new file mode 100644
index 00000000..a5d79382
--- /dev/null
+++ b/app/src/main/res/layout/pref_current_location.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 74e7690a..cd9580a9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -48,6 +48,9 @@
94043
+
+ Use my location
+
Invalid Location (%1$s)"
Validating Location... (%1$s)"
@@ -140,6 +143,9 @@
Sunshine Today
Sunshine Details
+
+ Today\'s weather
+
No Weather Information Available
No weather information available. The network is not available to fetch weather data.