Skip to content

Commit 20326da

Browse files
committed
bugfix: notifications for API 33
1 parent 85b1c21 commit 20326da

File tree

11 files changed

+88
-64
lines changed

11 files changed

+88
-64
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
77
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
88
<uses-permission android:name="android.permission.INTERNET" />
9+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
910

1011
<application
1112
android:name=".SysctlGuiApp"
@@ -96,9 +97,6 @@
9697
<service
9798
android:name=".services.StartUpService"
9899
android:permission="android.permission.BIND_JOB_SERVICE" />
99-
<service
100-
android:name=".services.LegacyStartUpService"
101-
android:permission="android.permission.BIND_JOB_SERVICE" />
102100
<service
103101
android:name=".widgets.FavoritesWidgetService"
104102
android:permission="android.permission.BIND_REMOTEVIEWS" />

app/src/main/kotlin/com/androidvip/sysctlgui/receivers/BootReceiver.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import com.androidvip.sysctlgui.services.StartUpService
88
class BootReceiver : BroadcastReceiver() {
99
override fun onReceive(context: Context?, intent: Intent?) {
1010
if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
11-
1211
context?.let {
1312
StartUpService.start(context)
1413
}

app/src/main/kotlin/com/androidvip/sysctlgui/services/LegacyStartUpService.kt

Lines changed: 0 additions & 46 deletions
This file was deleted.

app/src/main/kotlin/com/androidvip/sysctlgui/services/StartUpService.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@ import android.app.job.JobService
66
import android.content.Context
77
import android.content.Intent
88
import android.os.Build
9-
import androidx.annotation.RequiresApi
109
import com.androidvip.sysctlgui.services.base.BaseStartUpService
1110
import java.lang.ref.WeakReference
1211

13-
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
1412
class StartUpService : JobService(), BaseStartUpService.ServiceHandler {
1513

1614
override fun onStartJob(params: JobParameters?): Boolean {

app/src/main/kotlin/com/androidvip/sysctlgui/services/base/BaseStartUpService.kt

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package com.androidvip.sysctlgui.services.base
22

3+
import android.Manifest
34
import android.app.Notification
45
import android.app.NotificationChannel
56
import android.app.NotificationManager
67
import android.content.Context
8+
import android.content.pm.PackageManager
79
import android.os.Build
10+
import androidx.core.app.ActivityCompat
811
import androidx.core.app.NotificationCompat
912
import androidx.core.app.NotificationManagerCompat
1013
import com.androidvip.sysctlgui.R
@@ -13,6 +16,8 @@ import com.androidvip.sysctlgui.domain.repository.AppPrefs
1316
import com.androidvip.sysctlgui.domain.usecase.ApplyParamsUseCase
1417
import com.androidvip.sysctlgui.domain.usecase.GetUserParamsUseCase
1518
import com.topjohnwu.superuser.Shell
19+
import java.lang.ref.WeakReference
20+
import kotlin.coroutines.CoroutineContext
1621
import kotlinx.coroutines.CoroutineDispatcher
1722
import kotlinx.coroutines.CoroutineScope
1823
import kotlinx.coroutines.Dispatchers
@@ -24,8 +29,6 @@ import kotlinx.coroutines.launch
2429
import kotlinx.coroutines.withContext
2530
import org.koin.core.component.KoinComponent
2631
import org.koin.core.component.inject
27-
import java.lang.ref.WeakReference
28-
import kotlin.coroutines.CoroutineContext
2932

3033
class BaseStartUpService(
3134
private var weakContext: WeakReference<Context?>,
@@ -67,7 +70,10 @@ class BaseStartUpService(
6770
private inline fun showNotificationAndThen(crossinline onShow: () -> Unit) {
6871
val context = weakContext.get() ?: return
6972
val resources = context.resources
70-
val builder: NotificationCompat.Builder = NotificationCompat.Builder(context, NOTIFICATION_ID)
73+
val builder: NotificationCompat.Builder = NotificationCompat.Builder(
74+
context,
75+
NOTIFICATION_ID
76+
)
7177
.setSmallIcon(R.drawable.app_icon_foreground)
7278
.setContentTitle(resources.getString(R.string.notification_start_up_title))
7379
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
@@ -82,7 +88,9 @@ class BaseStartUpService(
8288
resources.getString(R.string.notification_start_up_channel_name),
8389
NotificationManager.IMPORTANCE_DEFAULT
8490
).apply {
85-
description = resources.getString(R.string.notification_start_up_channel_description)
91+
description = resources.getString(
92+
R.string.notification_start_up_channel_description
93+
)
8694
notificationManager.createNotificationChannel(this)
8795
}
8896
}
@@ -104,14 +112,30 @@ class BaseStartUpService(
104112
for (i in startupDelay downTo 0) {
105113
if (i == 0) {
106114
builder.setProgress(0, 0, true)
107-
builder.setContentTitle(context.getString(R.string.notification_start_up_title))
108-
builder.setContentText(context.getString(R.string.notification_start_up_description))
109-
110-
notify(SERVICE_ID, builder.build())
115+
builder.setContentTitle(
116+
context.getString(R.string.notification_start_up_title)
117+
)
118+
builder.setContentText(
119+
context.getString(R.string.notification_start_up_description)
120+
)
121+
122+
if (ActivityCompat.checkSelfPermission(
123+
context,
124+
Manifest.permission.POST_NOTIFICATIONS
125+
) == PackageManager.PERMISSION_GRANTED ||
126+
Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU
127+
) {
128+
notify(SERVICE_ID, builder.build())
129+
}
111130
handler?.onStartForeground(SERVICE_ID, builder.build())
112131
onShow()
113132
} else {
114-
builder.setContentTitle(context.getString(R.string.notification_start_up_description_delay, i))
133+
builder.setContentTitle(
134+
context.getString(
135+
R.string.notification_start_up_description_delay,
136+
i
137+
)
138+
)
115139
builder.setProgress(startupDelay, delayCount, false)
116140
notify(SERVICE_ID, builder.build())
117141
delay(1100)

app/src/main/kotlin/com/androidvip/sysctlgui/ui/base/BaseAppCompatActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import org.koin.android.ext.android.inject
1212
* TODO: Temporary until 100% compose
1313
*/
1414
abstract class BaseAppCompatActivity : AppCompatActivity() {
15-
private val prefs by inject<AppPrefs>()
15+
protected val prefs by inject<AppPrefs>()
1616

1717
override fun onCreate(savedInstanceState: Bundle?) {
1818
super.onCreate(savedInstanceState)

app/src/main/kotlin/com/androidvip/sysctlgui/ui/main/MainActivity.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package com.androidvip.sysctlgui.ui.main
22

3+
import android.app.NotificationManager
4+
import android.content.Context
5+
import android.os.Build
36
import android.os.Bundle
7+
import android.os.Handler
48
import android.view.MenuItem
9+
import androidx.activity.result.contract.ActivityResultContracts
10+
import androidx.core.os.postDelayed
511
import androidx.core.view.WindowCompat
612
import androidx.navigation.fragment.NavHostFragment
713
import androidx.navigation.ui.AppBarConfiguration
@@ -14,6 +20,9 @@ import com.androidvip.sysctlgui.ui.base.BaseAppCompatActivity
1420
class MainActivity : BaseAppCompatActivity() {
1521
private lateinit var binding: ActivityMain2Binding
1622

23+
private val notificationPermissionLauncher =
24+
registerForActivityResult(ActivityResultContracts.RequestPermission()) { _ -> }
25+
1726
override fun onCreate(savedInstanceState: Bundle?) {
1827
super.onCreate(savedInstanceState)
1928
WindowCompat.setDecorFitsSystemWindows(window, false)
@@ -22,6 +31,10 @@ class MainActivity : BaseAppCompatActivity() {
2231
setContentView(binding.root)
2332
setSupportActionBar(binding.toolbar)
2433

34+
Handler(mainLooper).postDelayed(1000) {
35+
checkNotificationPermission()
36+
}
37+
2538
setUpNavigation()
2639
navigateFromIntent()
2740
}
@@ -71,6 +84,16 @@ class MainActivity : BaseAppCompatActivity() {
7184
}
7285
}
7386

87+
private fun checkNotificationPermission() {
88+
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
89+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
90+
if (prefs.askedForNotificationPermission || !prefs.runOnStartUp) return
91+
if (manager.areNotificationsEnabled()) return
92+
93+
notificationPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
94+
prefs.askedForNotificationPermission = true
95+
}
96+
7497
private val navHost: NavHostFragment
7598
get() = supportFragmentManager.findFragmentById(R.id.navHostFragment) as NavHostFragment
7699

app/src/main/kotlin/com/androidvip/sysctlgui/ui/settings/SettingsFragment.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package com.androidvip.sysctlgui.ui.settings
22

3+
import android.app.NotificationManager
4+
import android.content.Context
5+
import android.os.Build
36
import android.os.Bundle
7+
import androidx.activity.result.contract.ActivityResultContracts
48
import androidx.lifecycle.lifecycleScope
59
import androidx.preference.Preference
610
import androidx.preference.PreferenceFragmentCompat
@@ -18,6 +22,9 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
1822
private val prefs: AppPrefs by inject()
1923
private val rootUtils: RootUtils by inject()
2024

25+
private val notificationPermissionLauncher =
26+
registerForActivityResult(ActivityResultContracts.RequestPermission()) { _ -> }
27+
2128
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
2229
setPreferencesFromResource(R.xml.preferences, rootKey)
2330

@@ -62,6 +69,7 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
6269
when (preference.key) {
6370
Consts.Prefs.RUN_ON_START_UP -> {
6471
StartUpServiceToggle.toggleStartUpService(requireContext(), newValue == true)
72+
askForNotificationPermission()
6573
}
6674

6775
Consts.Prefs.COMMIT_MODE -> {
@@ -96,4 +104,17 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChan
96104

97105
return true
98106
}
107+
108+
private fun askForNotificationPermission() {
109+
val manager = requireContext().getSystemService(Context.NOTIFICATION_SERVICE)
110+
as NotificationManager
111+
112+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
113+
if (!manager.areNotificationsEnabled()) {
114+
notificationPermissionLauncher.launch(
115+
android.Manifest.permission.POST_NOTIFICATIONS
116+
)
117+
}
118+
}
119+
}
99120
}

common/utils/src/main/kotlin/com/androidvip/sysctlgui/utils/Consts.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ object Consts {
2121
const val MIGRATION_COMPLETED = "migration_completed"
2222
const val FORCE_DARK_THEME = "force_dark_theme"
2323
const val DYNAMIC_COLORS = "dynamic_colors"
24+
const val ASKED_NOTIFICATION_PERMISSION = "asked_notification_permission"
2425
}
2526
}

data/src/main/java/com/androidvip/sysctlgui/data/repository/AppPrefsImpl.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class AppPrefsImpl(private val prefs: SharedPreferences) : AppPrefs {
3232
prefs.edit { putBoolean(Consts.Prefs.USE_BUSYBOX, value) }
3333
}
3434
override var runOnStartUp: Boolean
35-
get() = prefs.getBoolean(Consts.Prefs.RUN_ON_START_UP, true)
35+
get() = prefs.getBoolean(Consts.Prefs.RUN_ON_START_UP, false)
3636
set(value) {
3737
prefs.edit { putBoolean(Consts.Prefs.RUN_ON_START_UP, value) }
3838
}
@@ -52,7 +52,7 @@ class AppPrefsImpl(private val prefs: SharedPreferences) : AppPrefs {
5252
prefs.edit { putBoolean(Consts.Prefs.MIGRATION_COMPLETED, value) }
5353
}
5454
override var forceDark: Boolean
55-
get() = prefs.getBoolean(Consts.Prefs.FORCE_DARK_THEME, true)
55+
get() = prefs.getBoolean(Consts.Prefs.FORCE_DARK_THEME, false)
5656
set(value) {
5757
prefs.edit { putBoolean(Consts.Prefs.FORCE_DARK_THEME, value) }
5858
}
@@ -61,4 +61,9 @@ class AppPrefsImpl(private val prefs: SharedPreferences) : AppPrefs {
6161
set(value) {
6262
prefs.edit { putBoolean(Consts.Prefs.DYNAMIC_COLORS, value) }
6363
}
64+
override var askedForNotificationPermission: Boolean
65+
get() = prefs.getBoolean(Consts.Prefs.ASKED_NOTIFICATION_PERMISSION, false)
66+
set(value) {
67+
prefs.edit { putBoolean(Consts.Prefs.ASKED_NOTIFICATION_PERMISSION, value) }
68+
}
6469
}

0 commit comments

Comments
 (0)