mirror of
https://github.com/hmalik144/Weather-apps.git
synced 2025-12-10 02:05:20 +00:00
- Fixed android S issues
- Dialog box completed - Widget creation activity UI test added Took 1 hour 53 minutes
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user