- Fixed android S issues

- Dialog box completed
 - Widget creation activity UI test added

Took 1 hour 53 minutes
This commit is contained in:
2022-04-11 01:31:02 +01:00
parent 1c415b4f9a
commit 742875c295
11 changed files with 75 additions and 43 deletions

View File

@@ -8,7 +8,7 @@ import com.appttude.h_mal.atlas_weather.utils.Stubs
import org.junit.After import org.junit.After
import org.junit.Rule import org.junit.Rule
open class BaseTest() { open class BaseTest {
lateinit var testApp: TestAppClass lateinit var testApp: TestAppClass

View File

@@ -0,0 +1,29 @@
package com.appttude.h_mal.atlas_weather.monoWeather.ui.widget
import android.appwidget.AppWidgetManager
import android.content.Intent
import androidx.test.espresso.Espresso
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.rule.ActivityTestRule
import com.appttude.h_mal.atlas_weather.R
import org.junit.Rule
import org.junit.Test
class WidgetLocationPermissionActivityTest {
@Rule
@JvmField
var mActivityTestRule : ActivityTestRule<WidgetLocationPermissionActivity> =
ActivityTestRule<WidgetLocationPermissionActivity>(WidgetLocationPermissionActivity::class.java, false, false)
@Test
fun demo_test() {
val i = Intent()
i.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 112)
mActivityTestRule.launchActivity(i)
Espresso.onView((ViewMatchers.withId(R.id.declaration_text))).check(matches(isDisplayed()));
}
}

View File

@@ -22,6 +22,7 @@ abstract class BaseWidgetClass : AppWidgetProvider(){
intentUpdate.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE intentUpdate.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
val idArray = intArrayOf(appWidgetId) val idArray = intArrayOf(appWidgetId)
intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray) intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray)
return PendingIntent.getBroadcast( return PendingIntent.getBroadcast(
context, seconds, intentUpdate, context, seconds, intentUpdate,
PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.FLAG_UPDATE_CURRENT)

View File

@@ -2,7 +2,8 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -13,6 +14,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/forecast_listview" android:id="@+id/forecast_listview"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/db_list_item"> tools:listitem="@layout/db_list_item">
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>

View File

@@ -18,7 +18,8 @@
android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.MainActivity" android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
@@ -30,13 +31,15 @@
android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.settings.UnitSettingsActivity" android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.settings.UnitSettingsActivity"
android:label="Settings" /> android:label="Settings" />
<activity android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.widget.WidgetLocationPermissionActivity"> <activity android:name="com.appttude.h_mal.atlas_weather.monoWeather.ui.widget.WidgetLocationPermissionActivity"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter> </intent-filter>
</activity> </activity>
<receiver android:name="com.appttude.h_mal.atlas_weather.monoWeather.widget.NewAppWidget"> <receiver android:name="com.appttude.h_mal.atlas_weather.monoWeather.widget.NewAppWidget"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_ENABLED" /> <action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
@@ -48,9 +51,6 @@
android:resource="@xml/new_app_widget_info" /> android:resource="@xml/new_app_widget_info" />
</receiver> </receiver>
<service
android:name="com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetRemoteViewsService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<service <service
android:name="com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetJobServiceIntent" android:name="com.appttude.h_mal.atlas_weather.monoWeather.widget.WidgetJobServiceIntent"
android:exported="true" android:exported="true"

View File

@@ -1,10 +1,12 @@
package com.appttude.h_mal.atlas_weather.monoWeather.dialog package com.appttude.h_mal.atlas_weather.monoWeather.dialog
import android.content.Context import android.content.Context
import android.content.res.Resources
import android.os.Build import android.os.Build
import android.text.Html import android.text.Html
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
interface DeclarationBuilder{ interface DeclarationBuilder{
val link: String val link: String

View File

@@ -20,7 +20,6 @@ abstract class BaseDeclarationDialog(val context: Context): DeclarationBuilder {
abstract override val link: String abstract override val link: String
abstract override val message: String abstract override val message: String
@RequiresApi(Build.VERSION_CODES.N)
fun showDialog(agreeCallback: () -> Unit = { Unit }, disagreeCallback: () -> Unit = { Unit }) { fun showDialog(agreeCallback: () -> Unit = { Unit }, disagreeCallback: () -> Unit = { Unit }) {
val myMessage = buildMessage() val myMessage = buildMessage()
@@ -38,8 +37,8 @@ abstract class BaseDeclarationDialog(val context: Context): DeclarationBuilder {
alertDialog.show() alertDialog.show()
// Make the textview clickable. Must be called after show() // Make the textview clickable. Must be called after show()
val msgTxt = alertDialog.findViewById<View>(R.id.message) as TextView? val msgTxt = alertDialog.findViewById<View>(android.R.id.message) as TextView?
msgTxt!!.movementMethod = LinkMovementMethod.getInstance() msgTxt?.movementMethod = LinkMovementMethod.getInstance()
} }
} }

View File

@@ -24,7 +24,7 @@ import org.kodein.di.android.x.kodein
import org.kodein.di.generic.instance import org.kodein.di.generic.instance
import kotlin.properties.Delegates import kotlin.properties.Delegates
abstract class BaseFragment() : Fragment(), KodeinAware { abstract class BaseFragment : Fragment(), KodeinAware {
override val kodein by kodein() override val kodein by kodein()
val factory by instance<ApplicationViewModelFactory>() val factory by instance<ApplicationViewModelFactory>()

View File

@@ -9,7 +9,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.observe import androidx.lifecycle.observe
import androidx.recyclerview.widget.LinearLayoutManager
import com.appttude.h_mal.atlas_weather.R import com.appttude.h_mal.atlas_weather.R
import com.appttude.h_mal.atlas_weather.application.LOCATION_PERMISSION_REQUEST import com.appttude.h_mal.atlas_weather.application.LOCATION_PERMISSION_REQUEST
import com.appttude.h_mal.atlas_weather.monoWeather.dialog.PermissionsDeclarationDialog import com.appttude.h_mal.atlas_weather.monoWeather.dialog.PermissionsDeclarationDialog
@@ -34,7 +33,6 @@ class HomeFragment : BaseFragment() {
return inflater.inflate(R.layout.fragment_home, container, false) return inflater.inflate(R.layout.fragment_home, container, false)
} }
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@@ -45,18 +43,13 @@ class HomeFragment : BaseFragment() {
navigateTo(directions) navigateTo(directions)
} }
forecast_listview.apply { forecast_listview.adapter = recyclerAdapter
layoutManager = LinearLayoutManager(context)
adapter = recyclerAdapter
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
PermissionsDeclarationDialog(requireContext()).showDialog(agreeCallback = { PermissionsDeclarationDialog(requireContext()).showDialog(agreeCallback = {
getPermissionResult(Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST) { getPermissionResult(Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST) {
viewModel.fetchData() viewModel.fetchData()
} }
}) })
}
swipe_refresh.apply { swipe_refresh.apply {
setOnRefreshListener { setOnRefreshListener {

View File

@@ -6,6 +6,7 @@ import android.appwidget.AppWidgetManager.*
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager.PERMISSION_GRANTED import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Bundle import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat.checkSelfPermission import androidx.core.app.ActivityCompat.checkSelfPermission
@@ -17,11 +18,16 @@ import kotlinx.android.synthetic.monoWeather.permissions_declaration_dialog.*
const val PERMISSION_CODE = 401 const val PERMISSION_CODE = 401
class WidgetLocationPermissionActivity : AppCompatActivity(), DeclarationBuilder { class WidgetLocationPermissionActivity : AppCompatActivity(), DeclarationBuilder {
override val link: String = "https://sites.google.com/view/hmaldev/home/monochrome"
override var message: String = ""
private var mAppWidgetId = INVALID_APPWIDGET_ID private var mAppWidgetId = INVALID_APPWIDGET_ID
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
message = readFromResources(R.string.widget_declaration)
// Set the result to CANCELED. This will cause the widget host to cancel // 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. // out of the widget placement if the user presses the back button.
setResult(RESULT_CANCELED) setResult(RESULT_CANCELED)
@@ -38,7 +44,10 @@ class WidgetLocationPermissionActivity : AppCompatActivity(), DeclarationBuilder
} }
setContentView(R.layout.permissions_declaration_dialog) setContentView(R.layout.permissions_declaration_dialog)
findViewById<TextView>(R.id.declaration_text).setText(buildMessage()) findViewById<TextView>(R.id.declaration_text).apply {
text = buildMessage()
movementMethod = LinkMovementMethod.getInstance()
}
submit.setOnClickListener { submit.setOnClickListener {
if (checkSelfPermission(this, ACCESS_COARSE_LOCATION) != PERMISSION_GRANTED) { if (checkSelfPermission(this, ACCESS_COARSE_LOCATION) != PERMISSION_GRANTED) {
@@ -88,7 +97,4 @@ class WidgetLocationPermissionActivity : AppCompatActivity(), DeclarationBuilder
sendBroadcast(this) sendBroadcast(this)
} }
} }
override val link: String = "https://sites.google.com/view/hmaldev/home/monochrome"
override val message: String = readFromResources(R.string.widget_declaration)
} }

View File

@@ -2,24 +2,21 @@ package com.appttude.h_mal.atlas_weather.monoWeather.widget
import android.app.Activity import android.app.Activity
import android.app.PendingIntent import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.app.TaskStackBuilder import android.app.TaskStackBuilder
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider import android.appwidget.AppWidgetProvider
import android.content.ComponentName import android.content.ComponentName
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build
import android.widget.RemoteViews import android.widget.RemoteViews
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.core.app.JobIntentService import androidx.core.app.JobIntentService
import com.appttude.h_mal.atlas_weather.helper.ServicesHelper
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.kodein.di.KodeinAware
import org.kodein.di.LateInitKodein
import org.kodein.di.generic.instance
abstract class BaseWidgetServiceIntentClass<T : AppWidgetProvider> : JobIntentService() { abstract class BaseWidgetServiceIntentClass<T : AppWidgetProvider> : JobIntentService() {
@@ -45,9 +42,12 @@ abstract class BaseWidgetServiceIntentClass<T: AppWidgetProvider> : JobIntentSer
intentUpdate.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE intentUpdate.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
val idArray = intArrayOf(appWidgetId) val idArray = intArrayOf(appWidgetId)
intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray) intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray)
return PendingIntent.getBroadcast(
this, seconds, intentUpdate, return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.getBroadcast(this, seconds, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
} else {
PendingIntent.getBroadcast(this, seconds, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT)
}
} }
/** /**
@@ -59,7 +59,7 @@ abstract class BaseWidgetServiceIntentClass<T: AppWidgetProvider> : JobIntentSer
return TaskStackBuilder.create(this) return TaskStackBuilder.create(this)
.addNextIntentWithParentStack(clickIntentTemplate) .addNextIntentWithParentStack(clickIntentTemplate)
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT) .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
} }
fun setImageView( fun setImageView(