diff --git a/app/build.gradle b/app/build.gradle index 23edbc7..80c4f79 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ android { } } buildTypes.each { - it.buildConfigField 'String', 'OPEN_WEATHER_MAP_API_KEY', '""' + it.buildConfigField 'String', 'OPEN_WEATHER_MAP_API_KEY', '"f230a5958a6234052143e3983e295d58"' } } @@ -33,4 +33,5 @@ dependencies { compile 'com.android.support:recyclerview-v7:23.1.1' compile 'com.google.android.gms:play-services-gcm:7.8.0' compile 'com.google.android.apps.muzei:muzei-api:2.0' + compile 'com.google.android.gms:play-services-wearable:7.8.0' } diff --git a/app/src/main/java/com/example/android/sunshine/app/MainActivity.java b/app/src/main/java/com/example/android/sunshine/app/MainActivity.java index d90301c..2058138 100644 --- a/app/src/main/java/com/example/android/sunshine/app/MainActivity.java +++ b/app/src/main/java/com/example/android/sunshine/app/MainActivity.java @@ -36,11 +36,13 @@ import android.view.View; import com.example.android.sunshine.app.data.WeatherContract; import com.example.android.sunshine.app.sync.SunshineSyncAdapter; +import com.example.android.sunshine.app.sync.SunshineWearSyncHelper; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.gcm.GoogleCloudMessaging; import java.io.IOException; +import java.util.Random; public class MainActivity extends AppCompatActivity implements ForecastFragment.Callback { @@ -145,6 +147,11 @@ public class MainActivity extends AppCompatActivity implements ForecastFragment. if (id == R.id.action_settings) { startActivity(new Intent(this, SettingsActivity.class)); return true; + } else if(id == R.id.syncWear) { + // TODO remove + SunshineWearSyncHelper helper = new SunshineWearSyncHelper(); + Random rnd = new Random(); + helper.updateWear(this, rnd.nextInt(100), rnd.nextInt(100), R.drawable.art_fog); } return super.onOptionsItemSelected(item); } 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 7a4be1c..5651fb9 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 @@ -59,12 +59,12 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { // Interval at which to sync with the weather, in seconds. // 60 seconds (1 minute) * 180 = 3 hours public static final int SYNC_INTERVAL = 60 * 180; - public static final int SYNC_FLEXTIME = SYNC_INTERVAL/3; + public static final int SYNC_FLEXTIME = SYNC_INTERVAL / 3; private static final long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; private static final int WEATHER_NOTIFICATION_ID = 3004; - private static final String[] NOTIFY_WEATHER_PROJECTION = new String[] { + private static final String[] NOTIFY_WEATHER_PROJECTION = new String[]{ WeatherContract.WeatherEntry.COLUMN_WEATHER_ID, WeatherContract.WeatherEntry.COLUMN_MAX_TEMP, WeatherContract.WeatherEntry.COLUMN_MIN_TEMP, @@ -78,8 +78,9 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { private static final int INDEX_SHORT_DESC = 3; @Retention(RetentionPolicy.SOURCE) - @IntDef({LOCATION_STATUS_OK, LOCATION_STATUS_SERVER_DOWN, LOCATION_STATUS_SERVER_INVALID, LOCATION_STATUS_UNKNOWN, LOCATION_STATUS_INVALID}) - public @interface LocationStatus {} + @IntDef({LOCATION_STATUS_OK, LOCATION_STATUS_SERVER_DOWN, LOCATION_STATUS_SERVER_INVALID, LOCATION_STATUS_UNKNOWN, LOCATION_STATUS_INVALID}) + public @interface LocationStatus { + } public static final int LOCATION_STATUS_OK = 0; public static final int LOCATION_STATUS_SERVER_DOWN = 1; @@ -186,7 +187,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { /** * Take the String representing the complete forecast in JSON Format and * pull out the data we need to construct the Strings needed for the wireframes. - * + *

* Fortunately parsing is easy: constructor takes the JSON string and converts it * into an Object hierarchy for us. */ @@ -232,7 +233,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { JSONObject forecastJson = new JSONObject(forecastJsonStr); // do we have an error? - if ( forecastJson.has(OWM_MESSAGE_CODE) ) { + if (forecastJson.has(OWM_MESSAGE_CODE)) { int errorCode = forecastJson.getInt(OWM_MESSAGE_CODE); switch (errorCode) { @@ -278,7 +279,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { // now we work exclusively in UTC dayTime = new Time(); - for(int i = 0; i < weatherArray.length(); i++) { + for (int i = 0; i < weatherArray.length(); i++) { // These are the values that will be collected. long dateTime; double pressure; @@ -296,7 +297,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { JSONObject dayForecast = weatherArray.getJSONObject(i); // Cheating to convert this to UTC time, which is what we want anyhow - dateTime = dayTime.setJulianDay(julianStartDay+i); + dateTime = dayTime.setJulianDay(julianStartDay + i); pressure = dayForecast.getDouble(OWM_PRESSURE); humidity = dayForecast.getInt(OWM_HUMIDITY); @@ -334,7 +335,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { int inserted = 0; // add to database - if ( cVVector.size() > 0 ) { + if (cVVector.size() > 0) { ContentValues[] cvArray = new ContentValues[cVVector.size()]; cVVector.toArray(cvArray); getContext().getContentResolver().bulkInsert(WeatherContract.WeatherEntry.CONTENT_URI, cvArray); @@ -342,11 +343,12 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { // delete old data so we don't build up an endless history getContext().getContentResolver().delete(WeatherContract.WeatherEntry.CONTENT_URI, WeatherContract.WeatherEntry.COLUMN_DATE + " <= ?", - new String[] {Long.toString(dayTime.setJulianDay(julianStartDay-1))}); + new String[]{Long.toString(dayTime.setJulianDay(julianStartDay - 1))}); updateWidgets(); updateMuzei(); notifyWeather(); + syncWearable(); } Log.d(LOG_TAG, "Sync Complete. " + cVVector.size() + " Inserted"); setLocationStatus(getContext(), LOCATION_STATUS_OK); @@ -376,6 +378,24 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { } } + private void syncWearable() { + String locationQuery = Utility.getPreferredLocation(getContext()); + Uri weatherUri = WeatherContract.WeatherEntry.buildWeatherLocationWithDate(locationQuery, System.currentTimeMillis()); + Cursor cursor = getContext().getContentResolver().query(weatherUri, NOTIFY_WEATHER_PROJECTION, null, null, null); + + try { + if (cursor.moveToFirst()) { + // we only show ints on the wear + int highestTemp = (int) cursor.getDouble(INDEX_MAX_TEMP); + int lowestTemp = (int) cursor.getDouble(INDEX_MIN_TEMP); + int weatherIconId = Utility.getArtResourceForWeatherCondition(cursor.getInt(INDEX_WEATHER_ID)); + new SunshineWearSyncHelper().updateWear(getContext(), highestTemp, lowestTemp, weatherIconId); + } + } finally { + cursor.close(); + } + } + private void notifyWeather() { Context context = getContext(); //checking the last update and notify if it' the first of the day @@ -384,7 +404,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { boolean displayNotifications = prefs.getBoolean(displayNotificationsKey, Boolean.parseBoolean(context.getString(R.string.pref_enable_notifications_default))); - if ( displayNotifications ) { + if (displayNotifications) { String lastNotificationKey = context.getString(R.string.pref_last_notification); long lastSync = prefs.getLong(lastNotificationKey, 0); @@ -487,9 +507,9 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { * Helper method to handle insertion of a new location in the weather database. * * @param locationSetting The location string used to request updates from the server. - * @param cityName A human-readable city name, e.g "Mountain View" - * @param lat the latitude of the city - * @param lon the longitude of the city + * @param cityName A human-readable city name, e.g "Mountain View" + * @param lat the latitude of the city + * @param lon the longitude of the city * @return the row ID of the added location. */ long addLocation(String locationSetting, String cityName, double lat, double lon) { @@ -554,6 +574,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { /** * Helper method to have the sync adapter sync immediately + * * @param context The context used to access the account service */ public static void syncImmediately(Context context) { @@ -582,7 +603,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { context.getString(R.string.app_name), context.getString(R.string.sync_account_type)); // If the password doesn't exist, the account doesn't exist - if ( null == accountManager.getPassword(newAccount) ) { + if (null == accountManager.getPassword(newAccount)) { /* * Add the account and account type, no password or user data @@ -627,10 +648,11 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter { /** * Sets the location status into shared preference. This function should not be called from * the UI thread because it uses commit to write to the shared preferences. - * @param c Context to get the PreferenceManager from. + * + * @param c Context to get the PreferenceManager from. * @param locationStatus The IntDef value to set */ - static private void setLocationStatus(Context c, @LocationStatus int locationStatus){ + static private void setLocationStatus(Context c, @LocationStatus int locationStatus) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c); SharedPreferences.Editor spe = sp.edit(); spe.putInt(c.getString(R.string.pref_location_status_key), locationStatus); diff --git a/app/src/main/java/com/example/android/sunshine/app/sync/SunshineWearSyncHelper.java b/app/src/main/java/com/example/android/sunshine/app/sync/SunshineWearSyncHelper.java new file mode 100644 index 0000000..a077185 --- /dev/null +++ b/app/src/main/java/com/example/android/sunshine/app/sync/SunshineWearSyncHelper.java @@ -0,0 +1,89 @@ +package com.example.android.sunshine.app.sync; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.util.Log; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.ResultCallback; +import com.google.android.gms.wearable.Asset; +import com.google.android.gms.wearable.DataApi; +import com.google.android.gms.wearable.DataMap; +import com.google.android.gms.wearable.PutDataMapRequest; +import com.google.android.gms.wearable.PutDataRequest; +import com.google.android.gms.wearable.Wearable; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class SunshineWearSyncHelper implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { + + public static final String KEY_HIGHEST_TEMP = "highestTemp"; + public static final String KEY_LOWEST_TEMP = "lowestTemp"; + public static final String KEY_WEATHER_ICON = "weatherIcon"; + + private GoogleApiClient mApiClient; + private PutDataRequest mDataRequest; + + public void updateWear(Context context, int highestTemp, int lowestTemp, int weatherIconResId) { + mDataRequest = buildRequest(context, highestTemp, lowestTemp, weatherIconResId); + mApiClient = new GoogleApiClient.Builder(context.getApplicationContext()) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .addApi(Wearable.API) + .build(); + mApiClient.connect(); + } + + /** + * Build the DataRequest + * @param highestTemp daily highest temperature + * @param lowestTemp daily lowest Temperature + * @return PutDataRequest with the given values in it + */ + private PutDataRequest buildRequest(Context context, int highestTemp, int lowestTemp, int weatherIconResId) { + PutDataMapRequest mapRequest = PutDataMapRequest.create("/dailyTemp"); + DataMap dMap = mapRequest.getDataMap(); + dMap.putInt(KEY_HIGHEST_TEMP, highestTemp); + dMap.putInt(KEY_LOWEST_TEMP, lowestTemp); + + try { + Bitmap weatherIcon = BitmapFactory.decodeResource(context.getResources(), weatherIconResId); + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + weatherIcon.compress(Bitmap.CompressFormat.PNG, 100, stream); + stream.flush(); + byte[] byteArray = stream.toByteArray(); + Asset asset = Asset.createFromBytes(byteArray); + dMap.putAsset(KEY_WEATHER_ICON, asset); + } catch (IOException e) { + // should now happen + } + + return mapRequest.asPutDataRequest(); + } + + + @Override + public void onConnected(Bundle bundle) { + Log.d("SunshineWearSyncHelper", "Api connected."); + Wearable.DataApi.putDataItem(mApiClient, mDataRequest).setResultCallback(new ResultCallback() { + @Override + public void onResult(DataApi.DataItemResult dataItemResult) { + Log.d("SunshineWearSyncHelper", "Data item synced: " + dataItemResult.getDataItem().getUri()); + } + }); + } + + @Override + public void onConnectionSuspended(int i) { + Log.d("SunshineWearSyncHelper", "Api connection suspended. " + i ); + } + + @Override + public void onConnectionFailed(ConnectionResult connectionResult) { + Log.d("SunshineWearSyncHelper", "Api connection failed. " + connectionResult); + } +} diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml index db060a2..3e4b30a 100644 --- a/app/src/main/res/menu/main.xml +++ b/app/src/main/res/menu/main.xml @@ -21,4 +21,9 @@ android:title="@string/action_settings" android:orderInCategory="100" app:showAsAction="never" /> + \ No newline at end of file diff --git a/build.gradle b/build.gradle index a6fcfe1..cda0ee6 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,14 @@ buildscript { repositories { jcenter() + maven { + url 'https://repos.zeroturnaround.com/nexus/content/repositories/zt-public-releases' + } } dependencies { classpath 'com.android.tools.build:gradle:1.5.0' + // This does not break the build when Android Studio is missing the JRebel for Android plugin. + classpath 'com.zeroturnaround.jrebel.android:jr-android-gradle:1.0.+' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/wear/build.gradle b/wear/build.gradle index 7c1e717..8cad6b0 100644 --- a/wear/build.gradle +++ b/wear/build.gradle @@ -1,4 +1,6 @@ apply plugin: 'com.android.application' +// This does not break the build when Android Studio is missing the JRebel for Android plugin. +apply plugin: 'com.zeroturnaround.jrebel.android' android { @@ -6,7 +8,7 @@ android { buildToolsVersion "23.0.2" defaultConfig { - applicationId "com.example.android.sunshine.wear" + applicationId "com.example.android.sunshine.app" minSdkVersion 21 targetSdkVersion 23 versionCode 1 diff --git a/wear/src/main/java/com/example/android/sunshine/wear/SunshineWatchFaceService.java b/wear/src/main/java/com/example/android/sunshine/wear/SunshineWatchFaceService.java index e4d1f91..01eb22d 100644 --- a/wear/src/main/java/com/example/android/sunshine/wear/SunshineWatchFaceService.java +++ b/wear/src/main/java/com/example/android/sunshine/wear/SunshineWatchFaceService.java @@ -21,17 +21,35 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Rect; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.wearable.watchface.CanvasWatchFaceService; import android.support.wearable.watchface.WatchFaceStyle; import android.text.format.Time; +import android.util.Log; import android.view.SurfaceHolder; import android.view.WindowInsets; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.PendingResult; +import com.google.android.gms.common.api.ResultCallback; +import com.google.android.gms.wearable.Asset; +import com.google.android.gms.wearable.DataApi; +import com.google.android.gms.wearable.DataEvent; +import com.google.android.gms.wearable.DataEventBuffer; +import com.google.android.gms.wearable.DataItem; +import com.google.android.gms.wearable.DataMap; +import com.google.android.gms.wearable.DataMapItem; +import com.google.android.gms.wearable.Wearable; + +import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @@ -78,13 +96,16 @@ public class SunshineWatchFaceService extends CanvasWatchFaceService { } } - private class SunshineWatchFaceEngine extends CanvasWatchFaceService.Engine { + private class SunshineWatchFaceEngine extends CanvasWatchFaceService.Engine implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, DataApi.DataListener { final Handler mUpdateTimeHandler = new EngineHandler(this); WatchFaceDrawHelper mDrawerHelper; boolean mRegisteredTimeZoneReceiver = false; boolean mAmbient; Time mTime; + int tempHigh, tempLow; + Bitmap weatherIcon; + final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -99,6 +120,8 @@ public class SunshineWatchFaceService extends CanvasWatchFaceService { */ boolean mLowBitAmbient; + GoogleApiClient mApiClient; + @Override public void onCreate(SurfaceHolder holder) { super.onCreate(holder); @@ -111,6 +134,13 @@ public class SunshineWatchFaceService extends CanvasWatchFaceService { .build()); mTime = new Time(); + + mApiClient = new GoogleApiClient.Builder(getApplicationContext()) + .addApi(Wearable.API) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .build(); + mApiClient.connect(); } @Override @@ -192,11 +222,10 @@ public class SunshineWatchFaceService extends CanvasWatchFaceService { } - @Override public void onDraw(Canvas canvas, Rect bounds) { mTime.setToNow(); - mDrawerHelper.draw(canvas, bounds, mTime, 25, 16); + mDrawerHelper.draw(canvas, bounds, mTime, tempHigh, tempLow, weatherIcon); } /** @@ -230,5 +259,62 @@ public class SunshineWatchFaceService extends CanvasWatchFaceService { mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs); } } + + @Override + public void onConnected(Bundle bundle) { + Log.d("SunshineWatchFaceSync", "connected"); + Wearable.DataApi.addListener(mApiClient, this); + } + + @Override + public void onConnectionSuspended(int i) { + Log.d("SunshineWatchFaceSync", "connection suspended: " + i); + } + + @Override + public void onConnectionFailed(ConnectionResult connectionResult) { + Log.d("SunshineWatchFaceSync", + "connection failed: " + connectionResult.toString()); + } + + public static final String KEY_HIGHEST_TEMP = "highestTemp"; + public static final String KEY_LOWEST_TEMP = "lowestTemp"; + public static final String KEY_WEATHER_ICON = "weatherIcon"; + + @Override + public void onDataChanged(DataEventBuffer dataEvents) { + Log.d("SunshineWatchFaceSync", "data changed"); + for (DataEvent event : dataEvents) { + if (event.getType() == DataEvent.TYPE_CHANGED) { + // DataItem changed + DataItem item = event.getDataItem(); + if (item.getUri().getPath().compareTo("/dailyTemp") == 0) { + DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap(); + tempHigh = dataMap.getInt(KEY_HIGHEST_TEMP); + tempLow = dataMap.getInt(KEY_LOWEST_TEMP); + + + GoogleApiClient client = mApiClient; + Asset asset = dataMap.getAsset(KEY_WEATHER_ICON); + + PendingResult pendingResult = Wearable.DataApi.getFdForAsset(client, asset); + pendingResult.setResultCallback(new ResultCallback() { + @Override + public void onResult(DataApi.GetFdForAssetResult assetResult) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = 6; // TODO calculate this + InputStream assetInputStream = assetResult.getInputStream(); + weatherIcon = BitmapFactory.decodeStream(assetInputStream, null, options); + } + }); + + + Log.d("SunshineWatchFaceSync", "new dataitem: highest: " + tempHigh + " lowest: " + tempLow); + } + } else if (event.getType() == DataEvent.TYPE_DELETED) { + Log.d("SunshineWatchFaceSync", "dailyTemp deleted"); + } + } + } } } diff --git a/wear/src/main/java/com/example/android/sunshine/wear/WatchFaceDrawHelper.java b/wear/src/main/java/com/example/android/sunshine/wear/WatchFaceDrawHelper.java index fc690f4..14a4116 100644 --- a/wear/src/main/java/com/example/android/sunshine/wear/WatchFaceDrawHelper.java +++ b/wear/src/main/java/com/example/android/sunshine/wear/WatchFaceDrawHelper.java @@ -1,6 +1,7 @@ package com.example.android.sunshine.wear; import android.content.res.Resources; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -23,23 +24,30 @@ public class WatchFaceDrawHelper { private Paint mDateTextPaint; private Paint mHighestTempPaint; private Paint mLowestTempPaint; + private Paint mIconPaint; - float timeXOffset; - float timeYOffset; + float mTimeXOffset; + float mTimeYOffset; float mDateXOffset; float mDateYOffset; - float mWeatherYOffset; - float mWeatherXOffset; - float mWeatherXOffset2; + float mTempYOffset; + float mWeatherIconXOffset; + float mWeatherIconYOffset; + float mTempHighXOffset; + float mTempLowXOffset; public WatchFaceDrawHelper(Resources resources, boolean isRound) { - timeYOffset = resources.getDimension(R.dimen.time_y_offset); + mTimeYOffset = resources.getDimension(R.dimen.time_y_offset); mDateYOffset = resources.getDimension(R.dimen.date_y_offset); - mWeatherYOffset = resources.getDimension(R.dimen.weather_y_offset); + mTempYOffset = resources.getDimension(R.dimen.temp_y_offset); + mWeatherIconYOffset = resources.getDimension(R.dimen.weather_icon_y_offset); mBackgroundPaint = new Paint(); mBackgroundPaint.setColor(resources.getColor(R.color.background)); + mIconPaint = new Paint(); +// mIconPaint.setColor(resources.getColor(android.R.color.transparent)); + timeTextPaint = createTextPaint(resources.getColor(R.color.textcolor_primary)); mDateTextPaint = createTextPaint(resources.getColor(R.color.textcolor_secondary)); @@ -47,14 +55,16 @@ public class WatchFaceDrawHelper { mHighestTempPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); mLowestTempPaint = createTextPaint(resources.getColor(R.color.textcolor_primary)); - timeXOffset = resources.getDimension(isRound + mTimeXOffset = resources.getDimension(isRound ? R.dimen.time_x_offset_round : R.dimen.time_x_offset); mDateXOffset = resources.getDimension(isRound ? R.dimen.date_x_offset_round : R.dimen.date_x_offset); - mWeatherXOffset = resources.getDimension(isRound - ? R.dimen.weather_x_offset_round : R.dimen.weather_x_offset); - mWeatherXOffset2 = resources.getDimension(isRound - ? R.dimen.weather_x_offset_round_2 : R.dimen.weather_x_offset_2); + mWeatherIconXOffset = resources.getDimension(isRound + ? R.dimen.weather_icon_x_offset_round : R.dimen.weather_icon_x_offset); + mTempHighXOffset = resources.getDimension(isRound + ? R.dimen.temp_high_x_offset_round : R.dimen.temp_high_x_offset); + mTempLowXOffset = resources.getDimension(isRound + ? R.dimen.temp_low_x_offset_round : R.dimen.temp_low_x_offset); float timeTextSize = resources.getDimension(isRound ? R.dimen.time_text_size_round : R.dimen.time_text_size); @@ -91,7 +101,7 @@ public class WatchFaceDrawHelper { this.isLowBitAmbient = isLowBitAmbient; } - public void draw(Canvas canvas, Rect bounds, Time time, int highestTemp, int lowestTemp) { + public void draw(Canvas canvas, Rect bounds, Time time, int highestTemp, int lowestTemp, Bitmap weatherIcon) { // Draw the background. if (isInAmbientMode) { canvas.drawColor(Color.BLACK); @@ -104,17 +114,21 @@ public class WatchFaceDrawHelper { String timeText = isInAmbientMode ? String.format(TIME_FORMAT, time.hour, time.minute) : String.format(TIME_FORMAT_AMBIENT, time.hour, time.minute, time.second); - canvas.drawText(timeText, timeXOffset, timeYOffset, timeTextPaint); + canvas.drawText(timeText, mTimeXOffset, mTimeYOffset, timeTextPaint); // Draw current date String dateText = time.format(DATE_FORMAT); canvas.drawText(dateText, mDateXOffset, mDateYOffset, mDateTextPaint); // Draw weather - String currentHigh = String.format(TEMP_FORMAT, highestTemp); - canvas.drawText(currentHigh, mWeatherXOffset, mWeatherYOffset, mHighestTempPaint); - String currentLow = String.format(TEMP_FORMAT, lowestTemp); - canvas.drawText(currentLow, mWeatherXOffset + mWeatherXOffset2, mWeatherYOffset, mLowestTempPaint); + if(!(highestTemp == 0 && lowestTemp == 0)) { + String currentHigh = String.format(TEMP_FORMAT, highestTemp); + canvas.drawText(currentHigh, mTempHighXOffset, mTempYOffset, mHighestTempPaint); + String currentLow = String.format(TEMP_FORMAT, lowestTemp); + canvas.drawText(currentLow, mTempLowXOffset, mTempYOffset, mLowestTempPaint); + } + if(weatherIcon != null) + canvas.drawBitmap(weatherIcon, mWeatherIconXOffset, mWeatherIconYOffset, mIconPaint); } } diff --git a/wear/src/main/res/values/dimens.xml b/wear/src/main/res/values/dimens.xml index 2d4469a..9dfb06f 100644 --- a/wear/src/main/res/values/dimens.xml +++ b/wear/src/main/res/values/dimens.xml @@ -16,12 +16,17 @@ 25dp 15dp 20dp - 45dp - 55dp - 70dp - 100dp - 140dp - 40dp + 15dp + 55dp + 120dp + + 70dp + 100dp + 125dp + 140dp + 140dp + +