- 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.Rule
open class BaseTest() {
open class BaseTest {
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
val idArray = intArrayOf(appWidgetId)
intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray)
return PendingIntent.getBroadcast(
context, seconds, intentUpdate,
PendingIntent.FLAG_UPDATE_CURRENT)

View File

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

View File

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

View File

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

View File

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

View File

@@ -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>()

View File

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

View File

@@ -6,6 +6,7 @@ import android.appwidget.AppWidgetManager.*
import android.content.Intent
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat.checkSelfPermission
@@ -17,11 +18,16 @@ import kotlinx.android.synthetic.monoWeather.permissions_declaration_dialog.*
const val PERMISSION_CODE = 401
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
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
message = readFromResources(R.string.widget_declaration)
// 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)
@@ -38,7 +44,10 @@ class WidgetLocationPermissionActivity : AppCompatActivity(), DeclarationBuilder
}
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 {
if (checkSelfPermission(this, ACCESS_COARSE_LOCATION) != PERMISSION_GRANTED) {
@@ -88,7 +97,4 @@ class WidgetLocationPermissionActivity : AppCompatActivity(), DeclarationBuilder
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,31 +2,28 @@ package com.appttude.h_mal.atlas_weather.monoWeather.widget
import android.app.Activity
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.app.TaskStackBuilder
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import android.widget.RemoteViews
import androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.core.app.JobIntentService
import com.appttude.h_mal.atlas_weather.helper.ServicesHelper
import com.squareup.picasso.Picasso
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
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() {
lateinit var appWidgetManager: AppWidgetManager
lateinit var appWidgetIds: IntArray
fun initBaseWidget(componentName: ComponentName){
fun initBaseWidget(componentName: ComponentName) {
appWidgetManager = AppWidgetManager.getInstance(baseContext)
appWidgetIds = appWidgetManager.getAppWidgetIds(componentName)
}
@@ -45,21 +42,24 @@ abstract class BaseWidgetServiceIntentClass<T: AppWidgetProvider> : JobIntentSer
intentUpdate.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
val idArray = intArrayOf(appWidgetId)
intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray)
return PendingIntent.getBroadcast(
this, seconds, intentUpdate,
PendingIntent.FLAG_UPDATE_CURRENT)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(this, seconds, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
} else {
PendingIntent.getBroadcast(this, seconds, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT)
}
}
/**
* create a pending intent used to navigate to activity:
* @param activityClass
*/
fun <T: Activity> createClickingPendingIntent(activityClass: Class<T>): PendingIntent {
fun <T : Activity> createClickingPendingIntent(activityClass: Class<T>): PendingIntent {
val clickIntentTemplate = Intent(this, activityClass)
return TaskStackBuilder.create(this)
.addNextIntentWithParentStack(clickIntentTemplate)
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
}
fun setImageView(
@@ -67,7 +67,7 @@ abstract class BaseWidgetServiceIntentClass<T: AppWidgetProvider> : JobIntentSer
views: RemoteViews,
@IdRes viewId: Int,
appWidgetId: Int
){
) {
CoroutineScope(Dispatchers.Main).launch {
Picasso.get().load(path).into(views, viewId, intArrayOf(appWidgetId))
}