From a1a32e4ceb09f52d6861e6a4367f2fb896b956bd Mon Sep 17 00:00:00 2001 From: hmalik144 Date: Tue, 15 Feb 2022 00:57:52 +0000 Subject: [PATCH] Wake screen widget (#8) * - Update widget validation * - Cleaned widget folder and code --- .gitignore | 1 + .idea/caches/build_file_checksums.ser | Bin 537 -> 537 bytes .../atlas_weather/helper/ServicesHelper.kt | 37 +-- .../atlas_weather/model/widget/WidgetData.kt | 3 +- .../main/res/layout/weather_app_widget.xml | 5 + .../widget/BaseWidgetServiceIntentClass.kt | 49 +++- .../widget/MyWidgetRemoteViewsFactory.kt | 60 ----- .../widget/WidgetJobServiceIntent.kt | 249 +++++++++--------- .../widget/WidgetRemoteViewsService.kt | 10 - .../monoWeather/widget/WidgetState.kt | 28 ++ .../monoWeather/widget/WidgetUtils.kt | 15 -- 11 files changed, 213 insertions(+), 244 deletions(-) delete mode 100644 app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/MyWidgetRemoteViewsFactory.kt delete mode 100644 app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetRemoteViewsService.kt create mode 100644 app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetState.kt delete mode 100644 app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetUtils.kt diff --git a/.gitignore b/.gitignore index f93a34c..fd18cac 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /local.properties /.idea/workspace.xml /.idea/libraries +/.idea/caches .DS_Store /build /captures diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index e72d7c1f2eae089c89dc064500b86d45f387cb1a..ba14306ce59ae18014673799b45788aa20e3506b 100644 GIT binary patch delta 36 ucmV+<0NekW1epYomj!;>w9^@poOck<0)!<-zU{*O6lV>c0pVDaBLVg+MG#2< delta 36 ucmV+<0NekW1epYomj!t6pq2BHoOciq0k@UyQo*DK7KtUed=D*?BLVg+HV=~k diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/helper/ServicesHelper.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/helper/ServicesHelper.kt index f7b2196..361842f 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/helper/ServicesHelper.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/helper/ServicesHelper.kt @@ -29,7 +29,7 @@ class ServicesHelper( private val repository: Repository, private val settingsRepository: SettingsRepository, private val locationProvider: LocationProvider -){ +) { @RequiresPermission(Manifest.permission.ACCESS_COARSE_LOCATION) suspend fun fetchData(): Boolean { @@ -60,13 +60,14 @@ class ServicesHelper( suspend fun getWidgetWeather(): WidgetData? { return try { val result = repository.loadSingleCurrentWeatherFromRoom(CURRENT_LOCATION) - + val epoc = System.currentTimeMillis() + result.weather.let { val bitmap = it.current?.icon val location = locationProvider.getLocationNameFromLatLong(it.lat, it.lon) val temp = it.current?.temp?.toInt().toString() - WidgetData(location, bitmap, temp) + WidgetData(location, bitmap, temp, epoc) } } catch (e: Exception) { null @@ -80,7 +81,7 @@ class ServicesHelper( result.weather.daily?.drop(1)?.dropLast(2)?.forEach { dailyWeather -> val day = dailyWeather.dt?.toSmallDayName() - val bitmap = withContext(Dispatchers.Main) { + val bitmap = withContext(Dispatchers.Main) { getBitmapFromUrl(dailyWeather.icon) } val temp = dailyWeather.max?.toInt().toString() @@ -102,15 +103,16 @@ class ServicesHelper( val bitmap = it.current?.icon val location = locationProvider.getLocationNameFromLatLong(it.lat, it.lon) val temp = it.current?.temp?.toInt().toString() + val epoc = System.currentTimeMillis() - WidgetData(location, bitmap, temp) + WidgetData(location, bitmap, temp, epoc) } val list = mutableListOf() result.weather.daily?.drop(1)?.dropLast(2)?.forEach { dailyWeather -> val day = dailyWeather.dt?.toSmallDayName() - val icon = dailyWeather.icon + val icon = dailyWeather.icon val temp = dailyWeather.max?.toInt().toString() val item = InnerWidgetCellData(day, icon, temp) @@ -126,25 +128,24 @@ class ServicesHelper( private suspend fun getBitmapFromUrl(imageAddress: String?): Bitmap? { return suspendCoroutine { cont -> - Picasso.get().load(imageAddress).into(object : Target { - override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) { - cont.resume(bitmap) - } + Picasso.get().load(imageAddress).into(object : Target { + override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) { + cont.resume(bitmap) + } - override fun onBitmapFailed(e: Exception?, d: Drawable?) { - cont.resume(null) - } + override fun onBitmapFailed(e: Exception?, d: Drawable?) { + cont.resume(null) + } - override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} - }) + override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} + }) } } fun getWidgetBackground(): Int { - return if (settingsRepository.isBlackBackground()) { + return if (settingsRepository.isBlackBackground()) Color.BLACK - } else { + else Color.TRANSPARENT - } } } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/model/widget/WidgetData.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/model/widget/WidgetData.kt index ba20936..c33b42c 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/model/widget/WidgetData.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/model/widget/WidgetData.kt @@ -5,7 +5,8 @@ import android.graphics.Bitmap data class WidgetData( val location: String?, val icon: String?, - val currentTemp: String? + val currentTemp: String?, + val timeStamp: Long ) data class InnerWidgetData( diff --git a/app/src/main/res/layout/weather_app_widget.xml b/app/src/main/res/layout/weather_app_widget.xml index 677fc44..f58459a 100644 --- a/app/src/main/res/layout/weather_app_widget.xml +++ b/app/src/main/res/layout/weather_app_widget.xml @@ -133,6 +133,7 @@ android:rowCount="1"> : JobIntentService(){ - private val kodein = LateInitKodein() - val helper: ServicesHelper by kodein.instance() + lateinit var appWidgetManager: AppWidgetManager + lateinit var appWidgetIds: IntArray - fun setKodein(context: Context){ - kodein.baseKodein = (context.applicationContext as KodeinAware).kodein + fun initBaseWidget(componentName: ComponentName){ + appWidgetManager = AppWidgetManager.getInstance(baseContext) + appWidgetIds = appWidgetManager.getAppWidgetIds(componentName) } - fun createRemoteView(context: Context, @LayoutRes id: Int): RemoteViews { - return RemoteViews(context.packageName, id) + fun createRemoteView(@LayoutRes id: Int): RemoteViews { + return RemoteViews(packageName, id) } // Create pending intent commonly used for 'click to update' features - fun createUpdatePendingIntent( + fun createUpdatePendingIntent( appWidgetProvider: Class, - context: Context, appWidgetId: Int ): PendingIntent? { val seconds = (System.currentTimeMillis() / 1000L).toInt() - val intentUpdate = Intent(context.applicationContext, appWidgetProvider) + val intentUpdate = Intent(applicationContext, appWidgetProvider) intentUpdate.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE val idArray = intArrayOf(appWidgetId) intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray) return PendingIntent.getBroadcast( - context, seconds, intentUpdate, + this, seconds, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT) } @@ -48,11 +54,26 @@ abstract class BaseWidgetServiceIntentClass : JobIntentService(){ * create a pending intent used to navigate to activity: * @param activityClass */ - fun createClickingPendingIntent(context: Context, activityClass: Class): PendingIntent { - val clickIntentTemplate = Intent(context, activityClass) + fun createClickingPendingIntent(activityClass: Class): PendingIntent { + val clickIntentTemplate = Intent(this, activityClass) - return TaskStackBuilder.create(context) + return TaskStackBuilder.create(this) .addNextIntentWithParentStack(clickIntentTemplate) .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT) } + + fun setImageView( + path: String?, + views: RemoteViews, + @IdRes viewId: Int, + appWidgetId: Int + ){ + CoroutineScope(Dispatchers.Main).launch { + Picasso.get().load(path).into(views, viewId, intArrayOf(appWidgetId)) + } + } + + open fun bindView(widgetId: Int, views: RemoteViews, data: Any?) {} + open fun bindEmptyView(widgetId: Int, views: RemoteViews, data: Any?) {} + open fun bindErrorView(widgetId: Int, views: RemoteViews, data: Any?) {} } \ No newline at end of file diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/MyWidgetRemoteViewsFactory.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/MyWidgetRemoteViewsFactory.kt deleted file mode 100644 index e90dc29..0000000 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/MyWidgetRemoteViewsFactory.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.appttude.h_mal.atlas_weather.monoWeather.widget - -import android.content.Context -import android.content.Intent -import android.widget.RemoteViews -import android.widget.RemoteViewsService.RemoteViewsFactory -import com.appttude.h_mal.atlas_weather.R -import com.appttude.h_mal.atlas_weather.helper.ServicesHelper -import com.appttude.h_mal.atlas_weather.model.widget.InnerWidgetData -import kotlinx.coroutines.runBlocking -import org.kodein.di.KodeinAware -import org.kodein.di.android.kodein -import org.kodein.di.generic.instance - - -class MyWidgetRemoteViewsFactory( - private val context: Context, - val intent: Intent -) : RemoteViewsFactory, KodeinAware{ - - override val kodein by kodein(context) - private val helper : ServicesHelper by kodein.instance() - - private var list: List? = null - - override fun onCreate() {} - override fun onDataSetChanged() { - runBlocking { - list = helper.getWidgetInnerWeather() - } - } - override fun onDestroy() {} - - override fun getCount(): Int = list?.size ?: 5 - - override fun getViewAt(i: Int): RemoteViews { - val rv = RemoteViews(context.packageName, R.layout.widget_item) - if (list.isNullOrEmpty()) return rv - - list?.get(i)?.let { - rv.setTextViewText(R.id.widget_item_day, it.date) - rv.setImageViewBitmap(R.id.widget_item_image, it.icon) - rv.setTextViewText(R.id.widget_item_temp_high, it.highTemp) - rv.setOnClickFillInIntent(R.id.widget_item_layout, intent) - } - - return rv - } - - override fun getLoadingView(): RemoteViews { - return RemoteViews(context.packageName, R.layout.widget_item_loading) - } - - override fun getViewTypeCount(): Int = 2 - - override fun getItemId(i: Int): Long = i.toLong() - - override fun hasStableIds(): Boolean = true - -} \ No newline at end of file diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetJobServiceIntent.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetJobServiceIntent.kt index a5b6185..fa25aeb 100644 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetJobServiceIntent.kt +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetJobServiceIntent.kt @@ -3,187 +3,178 @@ package com.appttude.h_mal.atlas_weather.monoWeather.widget import android.Manifest.permission.ACCESS_COARSE_LOCATION import android.annotation.SuppressLint import android.app.PendingIntent -import android.appwidget.AppWidgetManager import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageManager.PERMISSION_GRANTED -import android.net.Uri +import android.icu.text.SimpleDateFormat import android.os.PowerManager import android.widget.RemoteViews +import android.os.Build import androidx.core.app.ActivityCompat.checkSelfPermission import com.appttude.h_mal.atlas_weather.R +import com.appttude.h_mal.atlas_weather.helper.ServicesHelper import com.appttude.h_mal.atlas_weather.model.widget.InnerWidgetCellData import com.appttude.h_mal.atlas_weather.model.widget.WidgetWeatherCollection import com.appttude.h_mal.atlas_weather.monoWeather.ui.MainActivity +import com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetState.* +import com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetState.Companion.getWidgetState import com.appttude.h_mal.atlas_weather.utils.isInternetAvailable import com.appttude.h_mal.atlas_weather.utils.tryOrNullSuspended -import com.squareup.picasso.Picasso import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter +import org.kodein.di.KodeinAware +import org.kodein.di.LateInitKodein +import org.kodein.di.generic.instance +import java.util.* /** - * Example implementation of a JobIntentService. + * Implementation of a JobIntentService used for home screen widget */ -class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() { +const val HALF_DAY = 43200000L +class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() { + + private val kodein = LateInitKodein() + private val helper: ServicesHelper by kodein.instance() override fun onHandleWork(intent: Intent) { // We have received work to do. The system or framework is already // holding a wake lock for us at this point, so we can just go. - - executeWidgetUpdate() + kodein.baseKodein = (applicationContext as KodeinAware).kodein + executeWidgetUpdate() } - private fun executeWidgetUpdate(){ - setKodein(this) + private fun executeWidgetUpdate() { + val componentName = ComponentName(this, NewAppWidget::class.java) + initBaseWidget(componentName) - val appWidgetManager = AppWidgetManager.getInstance(this) - val thisAppWidget = ComponentName(packageName, NewAppWidget::class.java.name) - val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget) + initiateWidgetUpdate(getCurrentWidgetState()) + } - validateOperation()?.let { - if (it) updateWidget(appWidgetIds, appWidgetManager) - else updateErrorWidget(appWidgetIds, appWidgetManager) + private fun initiateWidgetUpdate(state: WidgetState) { + when (state) { + NO_LOCATION, SCREEN_ON_CONNECTION_UNAVAILABLE -> updateErrorWidget(state) + SCREEN_ON_CONNECTION_AVAILABLE -> updateWidget(false) + SCREEN_OFF_CONNECTION_AVAILABLE -> updateWidget(true) + SCREEN_OFF_CONNECTION_UNAVAILABLE -> return } } - private fun updateWidget(appWidgetIds: IntArray, appWidgetManager: AppWidgetManager){ + private fun updateWidget(fromStorage: Boolean) { CoroutineScope(Dispatchers.IO).launch { - val result = getWidgetWeather() - - for (appWidgetId in appWidgetIds) { - bindView(this@WidgetJobServiceIntent, appWidgetManager, appWidgetId, result) - } + val result = getWidgetWeather(fromStorage) + appWidgetIds.forEach { id -> setupView(id, result) } } } - private fun updateErrorWidget(appWidgetIds: IntArray, appWidgetManager: AppWidgetManager){ - for (appWidgetId in appWidgetIds) { - setEmptyView(this, appWidgetManager, appWidgetId) - } + private fun updateErrorWidget(state: WidgetState) { + appWidgetIds.forEach { id -> setEmptyView(id, state) } } - private fun validateOperation(): Boolean? { + private fun getCurrentWidgetState(): WidgetState { val pm = getSystemService(POWER_SERVICE) as PowerManager val isScreenOn = pm.isInteractive val locationGranted = checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED val internetAvailable = isInternetAvailable(this.applicationContext) - // no location return false - if (!locationGranted) return false - // internet is available lets go - if (internetAvailable) return true - // screen is off and no connection, do nothing - if (!isScreenOn && !internetAvailable) return null - - return if (isScreenOn && !internetAvailable) false else null - } - - private fun createForecastListIntent( - context: Context, - appWidgetId: Int - ): Intent { - return Intent(context, WidgetRemoteViewsService::class.java).apply { - putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) - data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME)) - } + return getWidgetState(locationGranted, isScreenOn, internetAvailable) } @SuppressLint("MissingPermission") - suspend fun getWidgetWeather(): WidgetWeatherCollection? { + suspend fun getWidgetWeather(storageOnly: Boolean): WidgetWeatherCollection? { return tryOrNullSuspended { - helper.fetchData() + if (!storageOnly) helper.fetchData() helper.getWidgetWeatherCollection() } } - private fun setEmptyView(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) { - try { - val error = if (checkSelfPermission(context, ACCESS_COARSE_LOCATION) - != PERMISSION_GRANTED) { - "No Permission" - } else if (!isInternetAvailable(context.applicationContext)) { - "No Connection" - } else { - "No Data" - } - val updatePendingIntent = createUpdatePendingIntent(NewAppWidget::class.java, context, appWidgetId) - val views = createRemoteView(context, R.layout.weather_app_widget) - bindEmptyView(appWidgetManager, appWidgetId, views, updatePendingIntent, error) - } catch (e: Exception) { - e.printStackTrace() + private fun setEmptyView(appWidgetId: Int, state: WidgetState) { + val error = when (state) { + NO_LOCATION -> "No Location Permission" + SCREEN_ON_CONNECTION_UNAVAILABLE -> "No network available" + else -> "No data" } + + val views = createRemoteView(R.layout.weather_app_widget) + bindErrorView(appWidgetId, views, error) } - private fun bindEmptyView( - appWidgetManager: AppWidgetManager, + private fun setupView( appWidgetId: Int, - views: RemoteViews, - clickingUpdateIntent: PendingIntent?, - warning: String + collection: WidgetWeatherCollection? ) { - setLastUpdated(views) - views.setTextViewText(R.id.widget_current_location, warning) - views.setImageViewResource(R.id.widget_current_icon, R.drawable.ic_baseline_cloud_off_24) - views.setImageViewResource(R.id.location_icon, 0) - - views.setTextViewText(R.id.widget_main_temp, "") - views.setTextViewText(R.id.widget_feel_temp, "") - - views.setOnClickPendingIntent(R.id.widget_current_icon, clickingUpdateIntent) - views.setOnClickPendingIntent(R.id.widget_current_location, clickingUpdateIntent) - appWidgetManager.updateAppWidget(appWidgetId, views) - appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview) - } - - private fun bindView( - context: Context, - appWidgetManager: AppWidgetManager, - appWidgetId: Int, - collection: WidgetWeatherCollection?) { - val views = createRemoteView(context, R.layout.weather_app_widget) - setLastUpdated(views) + val views = createRemoteView(R.layout.weather_app_widget) + setLastUpdated(views, collection?.widgetData?.timeStamp) views.setInt(R.id.whole_widget_view, "setBackgroundColor", helper.getWidgetBackground()) - val clickingUpdatePendingIntent = createUpdatePendingIntent(NewAppWidget::class.java, context, appWidgetId) if (collection != null) { - val clickPendingIntentTemplate = - createClickingPendingIntent(context, MainActivity::class.java) - - views.apply { - val weather = collection.widgetData - - setTextViewText(R.id.widget_main_temp, weather.currentTemp) - setTextViewText(R.id.widget_feel_temp, "°C") - setTextViewText(R.id.widget_current_location, weather.location) - setImageViewResource(R.id.location_icon, R.drawable.location_flag) - CoroutineScope(Dispatchers.Main).launch { - Picasso.get().load(weather.icon).into(views, R.id.widget_current_icon, intArrayOf(appWidgetId)) - } - setPendingIntentTemplate(R.id.widget_listview, clickPendingIntentTemplate) - setOnClickPendingIntent(R.id.widget_current_icon, clickingUpdatePendingIntent) - setOnClickPendingIntent(R.id.widget_current_location, clickingUpdatePendingIntent) - - loadCells(appWidgetId, views, collection.forecast) -// setRemoteAdapter(R.id.widget_listview, forecastListIntent) - } - - // Instruct the widget manager to update the widget - appWidgetManager.updateAppWidget(appWidgetId, views) - appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview) + bindView(appWidgetId, views, collection) } else { - bindEmptyView(appWidgetManager, appWidgetId, views, clickingUpdatePendingIntent, "No Connection") + bindEmptyView(appWidgetId, views, "No weather available") } - } - private fun loadCells(appWidgetId: Int, remoteViews: RemoteViews, weather: List){ + override fun bindErrorView( + widgetId: Int, + views: RemoteViews, + data: Any? + ) { + bindEmptyView(widgetId, views, data) + } + + override fun bindEmptyView( + widgetId: Int, + views: RemoteViews, + data: Any? + ) { + val clickUpdate = createUpdatePendingIntent(NewAppWidget::class.java, widgetId) + + views.apply { + setTextViewText(R.id.widget_current_location, data as String) + setImageViewResource(R.id.widget_current_icon, R.drawable.ic_baseline_cloud_off_24) + setImageViewResource(R.id.location_icon, 0) + + setTextViewText(R.id.widget_main_temp, "") + setTextViewText(R.id.widget_feel_temp, "") + + setOnClickPendingIntent(R.id.widget_current_icon, clickUpdate) + setOnClickPendingIntent(R.id.widget_current_location, clickUpdate) + appWidgetManager.updateAppWidget(widgetId, this) + } + } + + override fun bindView(widgetId: Int, views: RemoteViews, data: Any?) { + val clickUpdate = createUpdatePendingIntent(NewAppWidget::class.java, widgetId) + val clickToMain = createClickingPendingIntent(MainActivity::class.java) + + val collection = data as WidgetWeatherCollection + val weather = collection.widgetData + views.apply { + setTextViewText(R.id.widget_main_temp, weather.currentTemp) + setTextViewText(R.id.widget_feel_temp, "°C") + setTextViewText(R.id.widget_current_location, weather.location) + setImageViewResource(R.id.location_icon, R.drawable.location_flag) + setImageView(weather.icon, this, R.id.widget_current_icon, widgetId) + setOnClickPendingIntent(R.id.widget_current_icon, clickUpdate) + setOnClickPendingIntent(R.id.widget_current_location, clickUpdate) + + loadCells(widgetId, this, collection.forecast, clickToMain) + // Instruct the widget manager to update the widget + appWidgetManager.updateAppWidget(widgetId, views) + } + } + + private fun loadCells( + appWidgetId: Int, + remoteViews: RemoteViews, + weather: List, + clickIntent: PendingIntent + ) { (0..4).forEach { i -> + val containerId: Int = resources.getIdentifier("widget_item_$i", "id", packageName) val dayId: Int = resources.getIdentifier("widget_item_day_$i", "id", packageName) val imageId: Int = resources.getIdentifier("widget_item_image_$i", "id", packageName) val tempId: Int = resources.getIdentifier("widget_item_temp_high_$i", "id", packageName) @@ -192,18 +183,24 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() { remoteViews.setTextViewText(dayId, it.date) remoteViews.setTextViewText(tempId, it.highTemp) - CoroutineScope(Dispatchers.Main).launch { - Picasso.get().load(it.icon).into(remoteViews, imageId, intArrayOf(appWidgetId)) - } + setImageView(it.icon, remoteViews, imageId, appWidgetId) + remoteViews.setOnClickPendingIntent(containerId, clickIntent) } } - private fun setLastUpdated(views: RemoteViews){ - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - val current = LocalDateTime.now() - val formatter = DateTimeFormatter.ofPattern("HH:mm") - val formatted = current.format(formatter) - views.setTextViewText(R.id.widget_current_status, "last updated: $formatted") + private fun setLastUpdated(views: RemoteViews, timeStamp: Long?) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && timeStamp != null) { + val difference = System.currentTimeMillis().minus(timeStamp) + + val status = if (difference > HALF_DAY) { + "12hrs ago" + } else { + val date = Date(timeStamp) + val sdf = SimpleDateFormat("HH:mm", Locale.getDefault()) + sdf.format(date) + } + + views.setTextViewText(R.id.widget_current_status, "last updated: $status") } } diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetRemoteViewsService.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetRemoteViewsService.kt deleted file mode 100644 index 254a232..0000000 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetRemoteViewsService.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.appttude.h_mal.atlas_weather.monoWeather.widget - -import android.content.Intent -import android.widget.RemoteViewsService - -class WidgetRemoteViewsService : RemoteViewsService() { - override fun onGetViewFactory(intent: Intent): RemoteViewsFactory { - return MyWidgetRemoteViewsFactory(applicationContext, intent) - } -} \ No newline at end of file diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetState.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetState.kt new file mode 100644 index 0000000..f95e06c --- /dev/null +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetState.kt @@ -0,0 +1,28 @@ +package com.appttude.h_mal.atlas_weather.monoWeather.widget + +enum class WidgetState { + NO_LOCATION, + SCREEN_ON_CONNECTION_AVAILABLE, + SCREEN_ON_CONNECTION_UNAVAILABLE, + SCREEN_OFF_CONNECTION_AVAILABLE, + SCREEN_OFF_CONNECTION_UNAVAILABLE; + + companion object { + fun getWidgetState( + locationAvailable: Boolean, + screenOn: Boolean, + connectionAvailable: Boolean + ): WidgetState { + return if (!locationAvailable) + NO_LOCATION + else if (screenOn && connectionAvailable) + SCREEN_ON_CONNECTION_AVAILABLE + else if (screenOn && !connectionAvailable) + SCREEN_ON_CONNECTION_UNAVAILABLE + else if (!screenOn && connectionAvailable) + SCREEN_OFF_CONNECTION_AVAILABLE + else + SCREEN_OFF_CONNECTION_UNAVAILABLE + } + } +} \ No newline at end of file diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetUtils.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetUtils.kt deleted file mode 100644 index e7f5ffc..0000000 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/widget/WidgetUtils.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.appttude.h_mal.atlas_weather.monoWeather.widget - -import android.app.Activity -import android.app.PendingIntent -import android.app.TaskStackBuilder -import android.content.Context -import android.content.Intent - -fun createClickingPendingIntent(context: Context, activityClass: Class): PendingIntent { - val clickIntentTemplate = Intent(context, activityClass) - - return TaskStackBuilder.create(context) - .addNextIntentWithParentStack(clickIntentTemplate) - .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT) -} \ No newline at end of file