mirror of
https://github.com/hmalik144/Weather-apps.git
synced 2026-03-18 15:36:04 +00:00
- Commit latest to main
Took 14 minutes
This commit is contained in:
@@ -24,7 +24,7 @@ import org.kodein.di.android.x.kodein
|
||||
import org.kodein.di.generic.instance
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
abstract class BaseFragment : Fragment(), KodeinAware {
|
||||
abstract class BaseFragment() : Fragment(), KodeinAware {
|
||||
|
||||
override val kodein by kodein()
|
||||
val factory by instance<ApplicationViewModelFactory>()
|
||||
|
||||
@@ -7,11 +7,9 @@ import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.forecast.Forecast
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.details.FurtherInfoFragmentArgs
|
||||
import kotlinx.android.synthetic.main.activity_further_info.*
|
||||
|
||||
|
||||
private const val WEATHER = "param1"
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* Use the [FurtherInfoFragment.newInstance] factory method to
|
||||
|
||||
@@ -24,7 +24,7 @@ import kotlinx.android.synthetic.main.fragment_home.*
|
||||
* A simple [Fragment] subclass.
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class HomeFragment : BaseFragment(){
|
||||
class HomeFragment : BaseFragment() {
|
||||
|
||||
private val viewModel by getFragmentViewModel<MainViewModel>()
|
||||
|
||||
@@ -49,6 +49,7 @@ class HomeFragment : BaseFragment(){
|
||||
adapter = recyclerAdapter
|
||||
}
|
||||
|
||||
|
||||
getPermissionResult(Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST){
|
||||
viewModel.fetchData()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.ui.widget
|
||||
|
||||
import android.Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
import android.app.Activity
|
||||
import android.appwidget.AppWidgetManager.*
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat.checkSelfPermission
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.utils.displayToast
|
||||
import kotlinx.android.synthetic.monoWeather.permissions_declaration_dialog.*
|
||||
|
||||
const val PERMISSION_CODE = 401
|
||||
|
||||
class WidgetLocationPermissionActivity : AppCompatActivity() {
|
||||
private var mAppWidgetId = INVALID_APPWIDGET_ID
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Set the result to CANCELED. This will cause the widget host to cancel
|
||||
// out of the widget placement if the user presses the back button.
|
||||
setResult(RESULT_CANCELED)
|
||||
|
||||
// Find the widget id from the intent.
|
||||
intent.extras?.let {
|
||||
mAppWidgetId = it.getInt(EXTRA_APPWIDGET_ID, INVALID_APPWIDGET_ID)
|
||||
}
|
||||
|
||||
// If this activity was started with an intent without an app widget ID, finish with an error.
|
||||
if (mAppWidgetId == INVALID_APPWIDGET_ID) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
setContentView(R.layout.permissions_declaration_dialog)
|
||||
|
||||
submit.setOnClickListener {
|
||||
if (checkSelfPermission(this, ACCESS_COARSE_LOCATION) != PERMISSION_GRANTED) {
|
||||
requestPermissions(arrayOf(ACCESS_COARSE_LOCATION), PERMISSION_CODE)
|
||||
} else {
|
||||
submitWidget()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
if (requestCode == PERMISSION_CODE) {
|
||||
if (grantResults.isNotEmpty() && grantResults[0] == PERMISSION_GRANTED) {
|
||||
submitWidget()
|
||||
} else {
|
||||
displayToast("Location Permission denied")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun submitWidget() {
|
||||
sendUpdateIntent()
|
||||
finishCurrencyWidgetActivity()
|
||||
}
|
||||
|
||||
private fun finishCurrencyWidgetActivity() {
|
||||
// Make sure we pass back the original appWidgetId
|
||||
val resultValue = intent
|
||||
resultValue.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId)
|
||||
setResult(Activity.RESULT_OK, resultValue)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun sendUpdateIntent() {
|
||||
// It is the responsibility of the configuration activity to update the app widget
|
||||
// Send update broadcast to widget app class
|
||||
Intent(this@WidgetLocationPermissionActivity,
|
||||
WidgetLocationPermissionActivity::class.java
|
||||
).apply {
|
||||
action = ACTION_APPWIDGET_UPDATE
|
||||
|
||||
// Put current app widget ID into extras and send broadcast
|
||||
putExtra(EXTRA_APPWIDGET_IDS, intArrayOf(mAppWidgetId))
|
||||
sendBroadcast(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import androidx.lifecycle.observe
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.BaseFragment
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.WorldItemFragmentDirections
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.ui.world.WorldFragmentDirections.actionWorldFragmentToWorldItemFragment
|
||||
import com.appttude.h_mal.atlas_weather.utils.navigateTo
|
||||
import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel
|
||||
|
||||
@@ -35,7 +35,6 @@ class MyWidgetRemoteViewsFactory(
|
||||
|
||||
override fun getViewAt(i: Int): RemoteViews {
|
||||
val rv = RemoteViews(context.packageName, R.layout.widget_item)
|
||||
|
||||
if (list.isNullOrEmpty()) return rv
|
||||
|
||||
list?.get(i)?.let {
|
||||
@@ -57,4 +56,5 @@ class MyWidgetRemoteViewsFactory(
|
||||
override fun getItemId(i: Int): Long = i.toLong()
|
||||
|
||||
override fun hasStableIds(): Boolean = true
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetJobServiceIntent.Companion.enqueueWork
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
package com.appttude.h_mal.atlas_weather.monoWeather.widget
|
||||
|
||||
import android.Manifest
|
||||
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
|
||||
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||
import android.net.Uri
|
||||
import android.os.PowerManager
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.ActivityCompat.checkSelfPermission
|
||||
import com.appttude.h_mal.atlas_weather.R
|
||||
import com.appttude.h_mal.atlas_weather.model.widget.WidgetData
|
||||
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.utils.isInternetAvailable
|
||||
import com.appttude.h_mal.atlas_weather.utils.tryOrNullSuspended
|
||||
@@ -34,11 +35,7 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() {
|
||||
// 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.
|
||||
|
||||
val pm = getSystemService(POWER_SERVICE) as PowerManager
|
||||
val isScreenOn = pm.isInteractive
|
||||
|
||||
// If screen is on then update widget or do nothing
|
||||
if (isScreenOn) executeWidgetUpdate()
|
||||
executeWidgetUpdate()
|
||||
}
|
||||
|
||||
private fun executeWidgetUpdate(){
|
||||
@@ -48,23 +45,45 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() {
|
||||
val thisAppWidget = ComponentName(packageName, NewAppWidget::class.java.name)
|
||||
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
|
||||
|
||||
// Check if we have an active connection and permissions granted
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||
!= PackageManager.PERMISSION_GRANTED || !isInternetAvailable(this.applicationContext)) {
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
setEmptyView(this, appWidgetManager, appWidgetId)
|
||||
}
|
||||
}else{
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val result = getWidgetWeather()
|
||||
validateOperation()?.let {
|
||||
if (it) updateWidget(appWidgetIds, appWidgetManager)
|
||||
else updateErrorWidget(appWidgetIds, appWidgetManager)
|
||||
}
|
||||
}
|
||||
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
bindView(this@WidgetJobServiceIntent, appWidgetManager, appWidgetId, result)
|
||||
}
|
||||
private fun updateWidget(appWidgetIds: IntArray, appWidgetManager: AppWidgetManager){
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val result = getWidgetWeather()
|
||||
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
bindView(this@WidgetJobServiceIntent, appWidgetManager, appWidgetId, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateErrorWidget(appWidgetIds: IntArray, appWidgetManager: AppWidgetManager){
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
setEmptyView(this, appWidgetManager, appWidgetId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateOperation(): Boolean? {
|
||||
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
|
||||
@@ -76,18 +95,17 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() {
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
suspend fun getWidgetWeather(): WidgetData? {
|
||||
suspend fun getWidgetWeather(): WidgetWeatherCollection? {
|
||||
return tryOrNullSuspended {
|
||||
helper.fetchData()
|
||||
helper.getWidgetWeather()
|
||||
helper.getWidgetWeatherCollection()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setEmptyView(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
|
||||
try {
|
||||
val error = if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
val error = if (checkSelfPermission(context, ACCESS_COARSE_LOCATION)
|
||||
!= PERMISSION_GRANTED) {
|
||||
"No Permission"
|
||||
} else if (!isInternetAvailable(context.applicationContext)) {
|
||||
"No Connection"
|
||||
@@ -100,7 +118,6 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() {
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun bindEmptyView(
|
||||
@@ -128,18 +145,19 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() {
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetId: Int,
|
||||
weather: WidgetData?) {
|
||||
collection: WidgetWeatherCollection?) {
|
||||
val views = createRemoteView(context, R.layout.weather_app_widget)
|
||||
setLastUpdated(views)
|
||||
views.setInt(R.id.whole_widget_view, "setBackgroundColor", helper.getWidgetBackground())
|
||||
val clickingUpdatePendingIntent = createUpdatePendingIntent(NewAppWidget::class.java, context, appWidgetId)
|
||||
val forecastListIntent = createForecastListIntent(context, appWidgetId)
|
||||
|
||||
if (weather != null) {
|
||||
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)
|
||||
@@ -151,7 +169,8 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() {
|
||||
setOnClickPendingIntent(R.id.widget_current_icon, clickingUpdatePendingIntent)
|
||||
setOnClickPendingIntent(R.id.widget_current_location, clickingUpdatePendingIntent)
|
||||
|
||||
setRemoteAdapter(R.id.widget_listview, forecastListIntent)
|
||||
loadCells(appWidgetId, views, collection.forecast)
|
||||
// setRemoteAdapter(R.id.widget_listview, forecastListIntent)
|
||||
}
|
||||
|
||||
// Instruct the widget manager to update the widget
|
||||
@@ -163,6 +182,22 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass() {
|
||||
|
||||
}
|
||||
|
||||
private fun loadCells(appWidgetId: Int, remoteViews: RemoteViews, weather: List<InnerWidgetCellData>){
|
||||
(0..4).forEach { i ->
|
||||
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)
|
||||
|
||||
val it = weather[i]
|
||||
|
||||
remoteViews.setTextViewText(dayId, it.date)
|
||||
remoteViews.setTextViewText(tempId, it.highTemp)
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
Picasso.get().load(it.icon).into(remoteViews, imageId, intArrayOf(appWidgetId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setLastUpdated(views: RemoteViews){
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
val current = LocalDateTime.now()
|
||||
|
||||
Reference in New Issue
Block a user