Skip to content

Commit 2729861

Browse files
authored
Disable alerts with missing notification permission (#341)
* disable warnings when notifications are not available * clean up and fix tests * update version * cleanup
1 parent 1471fbc commit 2729861

File tree

12 files changed

+118
-70
lines changed

12 files changed

+118
-70
lines changed

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ android {
1212
applicationId "org.blitzortung.android.app"
1313
minSdkVersion 21
1414
targetSdk 35
15-
versionCode 342
16-
versionName '2.4.1'
15+
versionCode 343
16+
versionName '2.4.2'
1717
multiDexEnabled false
1818
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1919
}

app/src/main/java/org/blitzortung/android/app/Main.kt

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,9 @@ class Main : FragmentActivity(), OnSharedPreferenceChangeListener {
449449
Log.v(LOG_TAG, "Main.onResume()")
450450

451451
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
452-
PermissionsSupport.ensurePermissions(this,
452+
PermissionsSupport.ensure(this,
453453
LocationPermissionRequester(preferences),
454-
NotificationPermissionRequester(),
454+
NotificationPermissionRequester(preferences),
455455
BackgroundLocationPermissionRequester(this, preferences),
456456
WakeupPermissionRequester(this, preferences)
457457
)
@@ -581,18 +581,14 @@ class Main : FragmentActivity(), OnSharedPreferenceChangeListener {
581581
}
582582

583583
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
584-
Log.v(
585-
LOG_TAG,
586-
"Main.onRequestPermissionsResult() $requestCode - ${permissions.joinToString()} - ${grantResults.joinToString { it.toString() }}"
587-
)
588-
val providerRelation = LocationProviderRelation.byOrdinal[requestCode]
589-
if (providerRelation != null) {
590-
val providerName = providerRelation.providerName
584+
val locationProviderRelation = LocationProviderRelation.byOrdinal[requestCode]
585+
if (locationProviderRelation != null) {
586+
val providerName = locationProviderRelation.providerName
591587
if (grantResults.size == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
592588
val previousValue = preferences.get(PreferenceKey.LOCATION_MODE, "n/a")
593589
Log.i(
594590
LOG_TAG,
595-
"Main..onRequestPermissionResult() $providerName permission has now been granted. (code $requestCode, previous: $previousValue)"
591+
"Main.onRequestPermissionResult() $providerName permission has now been granted. (code $requestCode, previous: $previousValue)"
596592
)
597593
preferences.edit {
598594
put(PreferenceKey.LOCATION_MODE, providerName)
@@ -601,11 +597,24 @@ class Main : FragmentActivity(), OnSharedPreferenceChangeListener {
601597
} else {
602598
Log.i(
603599
LOG_TAG,
604-
"Main..onRequestPermissionResult() $providerName permission was NOT granted. (code $requestCode)"
600+
"Main.onRequestPermissionResult() $providerName permission was NOT granted. (code $requestCode)"
605601
)
606602
locationHandler.shutdown()
607603
}
608-
} else {
604+
} else if (requestCode == REQUEST_CODE_POST_NOTIFICATIONS && grantResults.isNotEmpty()) {
605+
val alertEnabled = preferences.get(PreferenceKey.ALERT_ENABLED, false)
606+
if (grantResults.size == 1 && grantResults[0] == PackageManager.PERMISSION_DENIED && (alertEnabled || backgroundAlertEnabled)) {
607+
Log.i(
608+
LOG_TAG,
609+
"Main.onRequestPermissionResult() POST_NOTIFICATIONS permission was NOT granted but is required for alerts. Disabling alerts and background queries"
610+
)
611+
Toast.makeText(baseContext, R.string.post_notifications_required_for_alerts, Toast.LENGTH_LONG).show()
612+
preferences.edit {
613+
put(PreferenceKey.ALERT_ENABLED, false)
614+
put(PreferenceKey.BACKGROUND_QUERY_PERIOD, "0")
615+
}
616+
}
617+
}else {
609618
Log.i(LOG_TAG, "Main.onRequestPermissionResult() permissions: $permissions, requestCode: $requestCode")
610619
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
611620
}

app/src/main/java/org/blitzortung/android/app/permission/PermissionsManager.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ class PermissionsSupport(
1313
) {
1414

1515
@RequiresApi(Build.VERSION_CODES.M)
16-
fun requestPermission(permission: String, requestCode: Int, permissionRequiredStringId: Int): Boolean {
17-
val shouldShowPermissionRationale = activity.shouldShowRequestPermissionRationale(permission)
18-
val permissionIsGranted = activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
16+
fun request(permission: String, requestCode: Int, permissionRequiredStringId: Int): Boolean {
17+
val showRationale = activity.shouldShowRequestPermissionRationale(permission)
18+
val isGranted = activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
1919
Log.v(
2020
LOG_TAG,
21-
"Main.requestPermission() permission: $permission, requestCode: $requestCode, isGranted: $permissionIsGranted, shouldShowRationale: ${!shouldShowPermissionRationale}"
21+
"PermissionsSupport.request() permission: $permission, requestCode: $requestCode, isGranted: $isGranted, showRationale: $showRationale"
2222
)
2323

24-
return if (!permissionIsGranted) {
25-
if (shouldShowPermissionRationale) {
26-
requestPermissionsAfterDialog(permissionRequiredStringId, permission, requestCode)
24+
return if (!isGranted) {
25+
if (showRationale) {
26+
requestAfterDialog(permissionRequiredStringId, permission, requestCode)
2727
} else {
2828
activity.requestPermissions(arrayOf(permission), requestCode)
2929
}
@@ -34,14 +34,14 @@ class PermissionsSupport(
3434
}
3535

3636
@RequiresApi(Build.VERSION_CODES.M)
37-
private fun requestPermissionsAfterDialog(
37+
private fun requestAfterDialog(
3838
dialogTextResource: Int,
3939
permission: String,
4040
requestCode: Int,
4141
) {
4242
Log.v(
4343
LOG_TAG,
44-
"Main.requestPermissionsAfterDialog() permission: $permission, dialogResource: $dialogTextResource, requestCode: $requestCode"
44+
"PermissionsSupport.requestPermissionsAfterDialog() permission: $permission, dialogResource: $dialogTextResource, requestCode: $requestCode"
4545
)
4646

4747
val message = activity.resources.getString(dialogTextResource)
@@ -53,13 +53,13 @@ class PermissionsSupport(
5353

5454
companion object {
5555
@RequiresApi(Build.VERSION_CODES.M)
56-
fun ensurePermissions(activity: Activity, vararg permissionRequesters : PermissionRequester) {
56+
fun ensure(activity: Activity, vararg permissionRequesters : PermissionRequester) {
5757

5858
val permissionsSupport = PermissionsSupport(activity)
5959

6060
for (permissionRequester in permissionRequesters) {
6161
val result = permissionRequester.request(permissionsSupport)
62-
Log.v(LOG_TAG, "Main.onResume() permission ${permissionRequester.name}: result: $result")
62+
Log.v(LOG_TAG, "PermissionsSupport.ensure() permission ${permissionRequester.name}: result: $result")
6363
if (result) {
6464
break
6565
}

app/src/main/java/org/blitzortung/android/app/permission/requester/BackgroundLocationPermissionRequester.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class BackgroundLocationPermissionRequester(
3838
val message = activity.resources.getString(R.string.location_permission_background_disclosure)
3939
AlertDialog.Builder(activity).setMessage(message).setCancelable(false)
4040
.setPositiveButton(android.R.string.ok) { _, _ ->
41-
permissionsSupport.requestPermission(
41+
permissionsSupport.request(
4242
ACCESS_BACKGROUND_LOCATION,
4343
REQUEST_CODE_BACKGROUND_LOCATION,
4444
R.string.location_permission_background_required

app/src/main/java/org/blitzortung/android/app/permission/requester/LocationPermissionRequester.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@ import org.blitzortung.android.app.view.PreferenceKey
1616
import org.blitzortung.android.app.view.get
1717

1818
class LocationPermissionRequester(
19-
private val sharedPreferences: SharedPreferences
19+
private val preferences: SharedPreferences
2020
) : PermissionRequester {
2121
override val name: String = "location"
2222

2323
@RequiresApi(Build.VERSION_CODES.M)
2424
override fun request(permissionsSupport: PermissionsSupport): Boolean {
25-
val (permission, requestCode) = getLocationPermission(sharedPreferences)
25+
val (permission, requestCode) = getLocationPermission(preferences)
2626

2727
return if (permission != null) {
28-
permissionsSupport.requestPermission(
28+
permissionsSupport.request(
2929
permission, requestCode, R.string.location_permission_required
3030
)
3131
} else {
@@ -34,8 +34,8 @@ class LocationPermissionRequester(
3434
}
3535

3636
companion object {
37-
internal fun getLocationPermission(sharedPreferences: SharedPreferences): Pair<String?, Int> {
38-
val locationProviderName = sharedPreferences.get(PreferenceKey.LOCATION_MODE, PASSIVE_PROVIDER)
37+
internal fun getLocationPermission(preferences: SharedPreferences): Pair<String?, Int> {
38+
val locationProviderName = preferences.get(PreferenceKey.LOCATION_MODE, PASSIVE_PROVIDER)
3939
val permission = when (locationProviderName) {
4040
PASSIVE_PROVIDER, GPS_PROVIDER -> ACCESS_FINE_LOCATION
4141
NETWORK_PROVIDER -> ACCESS_COARSE_LOCATION
Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,36 @@
11
package org.blitzortung.android.app.permission.requester
22

33
import android.Manifest.permission.POST_NOTIFICATIONS
4+
import android.content.SharedPreferences
45
import android.os.Build
6+
import android.util.Log
7+
import org.blitzortung.android.app.Main.Companion.LOG_TAG
58
import org.blitzortung.android.app.Main.Companion.REQUEST_CODE_POST_NOTIFICATIONS
69
import org.blitzortung.android.app.R
710
import org.blitzortung.android.app.permission.PermissionRequester
811
import org.blitzortung.android.app.permission.PermissionsSupport
12+
import org.blitzortung.android.app.permission.requester.BackgroundLocationPermissionRequester.Companion.isBackgroundAlertEnabled
13+
import org.blitzortung.android.app.view.PreferenceKey
14+
import org.blitzortung.android.app.view.get
915

10-
class NotificationPermissionRequester() : PermissionRequester {
16+
class NotificationPermissionRequester(
17+
val preferences: SharedPreferences
18+
) : PermissionRequester {
1119
override val name: String = "notification"
1220

1321
override fun request(permissionsSupport: PermissionsSupport): Boolean {
14-
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
15-
permissionsSupport.requestPermission(POST_NOTIFICATIONS, REQUEST_CODE_POST_NOTIFICATIONS, R.string.post_notifications_request)
22+
val requiresNotifications = isAlertEnabled(preferences) || isBackgroundAlertEnabled(preferences)
23+
Log.v(LOG_TAG, "NotificationPermissionRequester.request() requiresNotifications: $requiresNotifications")
24+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && requiresNotifications) {
25+
permissionsSupport.request(POST_NOTIFICATIONS, REQUEST_CODE_POST_NOTIFICATIONS, R.string.post_notifications_request)
1626
} else {
1727
false
1828
}
1929
}
30+
31+
companion object {
32+
internal fun isAlertEnabled(preferences: SharedPreferences) : Boolean =
33+
preferences.get(PreferenceKey.ALERT_ENABLED, false)
34+
}
35+
2036
}

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,4 +385,5 @@ Russian by Ivan Karev (karev.ivan@gmail.com)\n
385385
<string name="post_notifications_request">Enable post notification permission if notification alerts are desired.</string>
386386
<string name="background_alerts" translatable="false">Background alert symbol</string>
387387
<string name="default_alarm_signal">Default alarm sound</string>
388+
<string name="post_notifications_required_for_alerts">Notification permission is required for alerts, disabling alerts and background queries.</string>
388389
</resources>

app/src/test/java/org/blitzortung/android/app/permission/PermissionsManagerTest.kt

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,17 @@ import android.app.Activity
55
import android.content.pm.PackageManager
66
import android.os.Build
77
import android.widget.Button
8-
import androidx.appcompat.app.AlertDialog
98
import io.mockk.MockKAnnotations
109
import io.mockk.every
1110
import io.mockk.impl.annotations.MockK
1211
import io.mockk.verify
1312
import org.junit.Before
1413
import org.junit.Test
1514
import org.junit.runner.RunWith
16-
import org.robolectric.Robolectric
1715
import org.robolectric.RobolectricTestRunner
1816
import org.robolectric.Shadows.shadowOf
1917
import org.robolectric.annotation.Config
20-
import org.robolectric.shadows.ShadowAlertDialog
21-
import org.robolectric.shadows.ShadowActivity
22-
import org.robolectric.shadows.ShadowResources
2318
import org.assertj.core.api.Assertions.assertThat
24-
import org.blitzortung.android.app.Main
2519
import org.junit.Ignore
2620
import org.robolectric.shadows.ShadowDialog
2721
import org.robolectric.shadows.ShadowLooper
@@ -52,7 +46,7 @@ class PermissionsManagerTest {
5246
every {activity.checkSelfPermission(PERMISSION_STRING)} answers { PackageManager.PERMISSION_GRANTED }
5347

5448
// Act
55-
val result = permissionsSupport.requestPermission(
49+
val result = permissionsSupport.request(
5650
PERMISSION_STRING,
5751
REQUEST_CODE,
5852
PERMISSION_RATIONALE_STRING_ID
@@ -67,7 +61,7 @@ class PermissionsManagerTest {
6761
every {activity.checkSelfPermission(PERMISSION_STRING)} answers { PackageManager.PERMISSION_DENIED }
6862
every {activity.shouldShowRequestPermissionRationale(PERMISSION_STRING)} answers { false }
6963

70-
val result = permissionsSupport.requestPermission(
64+
val result = permissionsSupport.request(
7165
PERMISSION_STRING,
7266
REQUEST_CODE,
7367
PERMISSION_RATIONALE_STRING_ID
@@ -88,7 +82,7 @@ class PermissionsManagerTest {
8882
shadowPackageManager.setShouldShowRequestPermissionRationale(PERMISSION_STRING, true)
8983

9084
// Act
91-
val result = permissionsSupport.requestPermission(
85+
val result = permissionsSupport.request(
9286
PERMISSION_STRING,
9387
REQUEST_CODE,
9488
android.R.string.copy
@@ -134,7 +128,7 @@ class PermissionsManagerTest {
134128
val requester = MockPermissionRequester("TestRequester", true)
135129

136130
// Act
137-
PermissionsSupport.ensurePermissions(activity, requester)
131+
PermissionsSupport.ensure(activity, requester)
138132

139133
// Assert
140134
assertThat(requester.requestCalled).isTrue()
@@ -147,7 +141,7 @@ class PermissionsManagerTest {
147141
val requester2 = MockPermissionRequester("Requester2", true)
148142

149143
// Act
150-
PermissionsSupport.ensurePermissions(activity, requester1, requester2)
144+
PermissionsSupport.ensure(activity, requester1, requester2)
151145

152146
// Assert
153147
assertThat(requester1.requestCalled).isTrue()
@@ -161,7 +155,7 @@ class PermissionsManagerTest {
161155
val requester2 = MockPermissionRequester("Requester2", false)
162156

163157
// Act
164-
PermissionsSupport.ensurePermissions(activity, requester1, requester2)
158+
PermissionsSupport.ensure(activity, requester1, requester2)
165159

166160
// Assert
167161
assertThat(requester1.requestCalled).isTrue()

app/src/test/java/org/blitzortung/android/app/permission/requester/BackgroundLocationPermissionRequesterTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class BackgroundLocationPermissionRequesterTest {
7373

7474
assertThat(result).isFalse()
7575
verify(exactly = 0) {
76-
permissionsSupport.requestPermission(any(), any(), any())
76+
permissionsSupport.request(any(), any(), any())
7777
}
7878
}
7979

@@ -86,14 +86,14 @@ class BackgroundLocationPermissionRequesterTest {
8686
assertThat(result).isFalse()
8787

8888
verify(exactly = 0) {
89-
permissionsSupport.requestPermission(any(), any(), any())
89+
permissionsSupport.request(any(), any(), any())
9090
}
9191
}
9292

9393
@Test
9494
@Config(sdk = [Build.VERSION_CODES.Q])
9595
fun `request should open the dialog if all conditions are valid and request permission on clicking OK`() {
96-
every { permissionsSupport.requestPermission(any(), any(), any()) } answers { true }
96+
every { permissionsSupport.request(any(), any(), any()) } answers { true }
9797

9898
val result = backgroundLocationPermissionRequester.request(permissionsSupport)
9999
assertThat(result).isTrue()
@@ -106,7 +106,7 @@ class BackgroundLocationPermissionRequesterTest {
106106
assertThat(dialog.isShowing).isFalse()
107107

108108
verify(exactly = 1) {
109-
permissionsSupport.requestPermission(
109+
permissionsSupport.request(
110110
ACCESS_BACKGROUND_LOCATION,
111111
102,
112112
R.string.location_permission_background_required
@@ -118,7 +118,7 @@ class BackgroundLocationPermissionRequesterTest {
118118
@Test
119119
@Config(sdk = [Build.VERSION_CODES.Q])
120120
fun `request should open the dialog if all conditions are valid and request permission on clicking Cancel`() {
121-
every { permissionsSupport.requestPermission(any(), any(), any()) } answers { true }
121+
every { permissionsSupport.request(any(), any(), any()) } answers { true }
122122

123123
val result = backgroundLocationPermissionRequester.request(permissionsSupport)
124124
assertThat(result).isTrue()
@@ -131,7 +131,7 @@ class BackgroundLocationPermissionRequesterTest {
131131
assertThat(dialog.isShowing).isFalse()
132132

133133
verify(exactly = 0) {
134-
permissionsSupport.requestPermission(any(), any(), any())
134+
permissionsSupport.request(any(), any(), any())
135135
}
136136
assertThat(preferences.getString(PreferenceKey.BACKGROUND_QUERY_PERIOD, "")).isEqualTo("0")
137137
}

app/src/test/java/org/blitzortung/android/app/permission/requester/LocationPermissionRequesterTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ class LocationPermissionRequesterTest {
4949

5050
@Test
5151
fun `request should use PASSIVE provider by default`() {
52-
every { permissionsSupport.requestPermission(any(), any(), any()) } answers { true }
52+
every { permissionsSupport.request(any(), any(), any()) } answers { true }
5353

5454
val result = locationPermissionRequester.request(permissionsSupport)
5555
assertThat(result).isTrue()
5656

5757
verify(exactly = 1) {
58-
permissionsSupport.requestPermission(
58+
permissionsSupport.request(
5959
ACCESS_FINE_LOCATION, 1, R.string.location_permission_required
6060
)
6161
}
@@ -66,26 +66,26 @@ class LocationPermissionRequesterTest {
6666
preferences.edit {
6767
putString(PreferenceKey.LOCATION_MODE.toString(), MANUAL_PROVIDER)
6868
}
69-
every { permissionsSupport.requestPermission(any(), any(), any()) } answers { false }
69+
every { permissionsSupport.request(any(), any(), any()) } answers { false }
7070

7171
val result = locationPermissionRequester.request(permissionsSupport)
7272
assertThat(result).isFalse()
7373

74-
verify(exactly = 0) { permissionsSupport.requestPermission(any(), any(), any()) }
74+
verify(exactly = 0) { permissionsSupport.request(any(), any(), any()) }
7575
}
7676

7777
@Test
7878
fun `request shold be configured correctly for Network location provider`() {
7979
preferences.edit {
8080
putString(PreferenceKey.LOCATION_MODE.toString(), NETWORK_PROVIDER)
8181
}
82-
every { permissionsSupport.requestPermission(any(), any(), any()) } answers { true }
82+
every { permissionsSupport.request(any(), any(), any()) } answers { true }
8383

8484
val result = locationPermissionRequester.request(permissionsSupport)
8585
assertThat(result).isTrue()
8686

8787
verify(exactly = 1) {
88-
permissionsSupport.requestPermission(
88+
permissionsSupport.request(
8989
ACCESS_COARSE_LOCATION, 2, R.string.location_permission_required
9090
)
9191
}

0 commit comments

Comments
 (0)