Manage new Android 13 notification permission.
This commit is contained in:
parent
3952f732dd
commit
652069d520
|
@ -635,6 +635,8 @@
|
||||||
<string name="permissions_rationale_msg_record_audio">${app_name} needs permission to access your microphone to perform audio calls.</string>
|
<string name="permissions_rationale_msg_record_audio">${app_name} needs permission to access your microphone to perform audio calls.</string>
|
||||||
<!-- Note to translators: the translation MUST contain the string "${app_name}", which will be replaced by the application name -->
|
<!-- Note to translators: the translation MUST contain the string "${app_name}", which will be replaced by the application name -->
|
||||||
<string name="permissions_rationale_msg_camera_and_audio">${app_name} needs permission to access your camera and your microphone to perform video calls.\n\nPlease allow access on the next pop-ups to be able to make the call.</string>
|
<string name="permissions_rationale_msg_camera_and_audio">${app_name} needs permission to access your camera and your microphone to perform video calls.\n\nPlease allow access on the next pop-ups to be able to make the call.</string>
|
||||||
|
<!-- Note to translators: the translation MUST contain the string "${app_name}", which will be replaced by the application name -->
|
||||||
|
<string name="permissions_rationale_msg_notification">${app_name} needs permission to display notifications. Notifications can display your messages, your invitations, etc.\n\nPlease allow access on the next pop-ups to be able to view notification.</string>
|
||||||
|
|
||||||
<string name="permissions_denied_qr_code">To scan a QR code, you need to allow camera access.</string>
|
<string name="permissions_denied_qr_code">To scan a QR code, you need to allow camera access.</string>
|
||||||
<string name="permissions_denied_add_contact">Allow permission to access your contacts.</string>
|
<string name="permissions_denied_add_contact">Allow permission to access your contacts.</string>
|
||||||
|
@ -854,7 +856,9 @@
|
||||||
<string name="settings_troubleshoot_test_system_settings_title">System Settings.</string>
|
<string name="settings_troubleshoot_test_system_settings_title">System Settings.</string>
|
||||||
<string name="settings_troubleshoot_test_system_settings_success">Notifications are enabled in the system settings.</string>
|
<string name="settings_troubleshoot_test_system_settings_success">Notifications are enabled in the system settings.</string>
|
||||||
<string name="settings_troubleshoot_test_system_settings_failed">Notifications are disabled in the system settings.\nPlease check system settings.</string>
|
<string name="settings_troubleshoot_test_system_settings_failed">Notifications are disabled in the system settings.\nPlease check system settings.</string>
|
||||||
|
<string name="settings_troubleshoot_test_system_settings_permission_failed">${app_name} needs the permission to show notifications.\nPlease grant the permission.</string>
|
||||||
<string name="open_settings">Open Settings</string>
|
<string name="open_settings">Open Settings</string>
|
||||||
|
<string name="grant_permission">Grant Permission</string>
|
||||||
|
|
||||||
<string name="settings_troubleshoot_test_account_settings_title">Account Settings.</string>
|
<string name="settings_troubleshoot_test_account_settings_title">Account Settings.</string>
|
||||||
<string name="settings_troubleshoot_test_account_settings_success">Notifications are enabled for your account.</string>
|
<string name="settings_troubleshoot_test_account_settings_success">Notifications are enabled for your account.</string>
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
## From https://developer.android.com/develop/ui/views/notifications/notification-permission#test
|
||||||
|
|
||||||
|
PACKAGE_NAME=im.vector.app.debug
|
||||||
|
|
||||||
|
# App is newly installed on a device that runs Android 13 or higher:
|
||||||
|
|
||||||
|
adb shell pm revoke ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS
|
||||||
|
adb shell pm clear-permission-flags ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS user-set
|
||||||
|
adb shell pm clear-permission-flags ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS user-fixed
|
||||||
|
|
||||||
|
# The user keeps notifications enabled when the app is installed on a device that runs 12L or lower,
|
||||||
|
# then the device upgrades to Android 13 or higher:
|
||||||
|
|
||||||
|
# adb shell pm grant ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS
|
||||||
|
# adb shell pm set-permission-flags ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS user-set
|
||||||
|
# adb shell pm clear-permission-flags ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS user-fixed
|
||||||
|
|
||||||
|
# The user manually disables notifications when the app is installed on a device that runs 12L or lower,
|
||||||
|
# then the device upgrades to Android 13 or higher:
|
||||||
|
|
||||||
|
# adb shell pm revoke ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS
|
||||||
|
# adb shell pm set-permission-flags ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS user-set
|
||||||
|
# adb shell pm clear-permission-flags ${PACKAGE_NAME} android.permission.POST_NOTIFICATIONS user-fixed
|
|
@ -22,6 +22,7 @@ import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.core.utils.checkPermissions
|
import im.vector.app.core.utils.checkPermissions
|
||||||
|
@ -46,7 +47,15 @@ class DebugPermissionActivity : VectorBaseActivity<ActivityDebugPermissionBindin
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||||
Manifest.permission.READ_CONTACTS
|
Manifest.permission.READ_CONTACTS
|
||||||
)
|
) + getAndroid13Permissions()
|
||||||
|
|
||||||
|
private fun getAndroid13Permissions(): List<String> {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
listOf(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var lastPermissions = emptyList<String>()
|
private var lastPermissions = emptyList<String>()
|
||||||
|
|
||||||
|
@ -77,6 +86,14 @@ class DebugPermissionActivity : VectorBaseActivity<ActivityDebugPermissionBindin
|
||||||
lastPermissions = listOf(Manifest.permission.READ_CONTACTS)
|
lastPermissions = listOf(Manifest.permission.READ_CONTACTS)
|
||||||
checkPerm()
|
checkPerm()
|
||||||
}
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
views.notification.setOnClickListener {
|
||||||
|
lastPermissions = listOf(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
checkPerm()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
views.notification.isVisible = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPerm() {
|
private fun checkPerm() {
|
||||||
|
|
|
@ -30,43 +30,43 @@
|
||||||
android:id="@+id/camera"
|
android:id="@+id/camera"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="CAMERA"
|
android:text="CAMERA" />
|
||||||
android:textAllCaps="false" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/audio"
|
android:id="@+id/audio"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="RECORD_AUDIO"
|
android:text="RECORD_AUDIO" />
|
||||||
android:textAllCaps="false" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/camera_audio"
|
android:id="@+id/camera_audio"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="CAMERA + RECORD_AUDIO"
|
android:text="CAMERA + RECORD_AUDIO" />
|
||||||
android:textAllCaps="false" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/write"
|
android:id="@+id/write"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="WRITE_EXTERNAL_STORAGE"
|
android:text="WRITE_EXTERNAL_STORAGE" />
|
||||||
android:textAllCaps="false" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/read"
|
android:id="@+id/read"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="READ_EXTERNAL_STORAGE"
|
android:text="READ_EXTERNAL_STORAGE" />
|
||||||
android:textAllCaps="false" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/contact"
|
android:id="@+id/contact"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="READ_CONTACTS"
|
android:text="READ_CONTACTS" />
|
||||||
android:textAllCaps="false" />
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/notification"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.fdroid.features.settings.troubleshoot
|
package im.vector.app.fdroid.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
|
@ -32,7 +30,7 @@ class TestAutoStartBoot @Inject constructor(
|
||||||
) :
|
) :
|
||||||
TroubleshootTest(R.string.settings_troubleshoot_test_service_boot_title) {
|
TroubleshootTest(R.string.settings_troubleshoot_test_service_boot_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
if (vectorPreferences.autoStartOnBoot()) {
|
if (vectorPreferences.autoStartOnBoot()) {
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_success)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_success)
|
||||||
status = TestStatus.SUCCESS
|
status = TestStatus.SUCCESS
|
||||||
|
@ -42,7 +40,7 @@ class TestAutoStartBoot @Inject constructor(
|
||||||
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_service_boot_quickfix) {
|
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_service_boot_quickfix) {
|
||||||
override fun doFix() {
|
override fun doFix() {
|
||||||
vectorPreferences.setAutoStartOnBoot(true)
|
vectorPreferences.setAutoStartOnBoot(true)
|
||||||
manager?.retry(activityResultLauncher)
|
manager?.retry(testParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = TestStatus.FAILED
|
status = TestStatus.FAILED
|
||||||
|
|
|
@ -15,9 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.fdroid.features.settings.troubleshoot
|
package im.vector.app.fdroid.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.core.net.ConnectivityManagerCompat
|
import androidx.core.net.ConnectivityManagerCompat
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
@ -32,7 +30,7 @@ class TestBackgroundRestrictions @Inject constructor(
|
||||||
) :
|
) :
|
||||||
TroubleshootTest(R.string.settings_troubleshoot_test_bg_restricted_title) {
|
TroubleshootTest(R.string.settings_troubleshoot_test_bg_restricted_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
context.getSystemService<ConnectivityManager>()!!.apply {
|
context.getSystemService<ConnectivityManager>()!!.apply {
|
||||||
// Checks if the device is on a metered network
|
// Checks if the device is on a metered network
|
||||||
if (isActiveNetworkMetered) {
|
if (isActiveNetworkMetered) {
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.fdroid.features.settings.troubleshoot
|
package im.vector.app.fdroid.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
@ -30,7 +28,7 @@ class TestBatteryOptimization @Inject constructor(
|
||||||
private val stringProvider: StringProvider
|
private val stringProvider: StringProvider
|
||||||
) : TroubleshootTest(R.string.settings_troubleshoot_test_battery_title) {
|
) : TroubleshootTest(R.string.settings_troubleshoot_test_battery_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
if (context.isIgnoringBatteryOptimizations()) {
|
if (context.isIgnoringBatteryOptimizations()) {
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_battery_success)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_battery_success)
|
||||||
status = TestStatus.SUCCESS
|
status = TestStatus.SUCCESS
|
||||||
|
@ -39,7 +37,7 @@ class TestBatteryOptimization @Inject constructor(
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_battery_failed)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_battery_failed)
|
||||||
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_battery_quickfix) {
|
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_battery_quickfix) {
|
||||||
override fun doFix() {
|
override fun doFix() {
|
||||||
requestDisablingBatteryOptimization(context, activityResultLauncher)
|
requestDisablingBatteryOptimization(context, testParameters.activityResultLauncher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = TestStatus.FAILED
|
status = TestStatus.FAILED
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.gplay.features.settings.troubleshoot
|
package im.vector.app.gplay.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import com.google.firebase.messaging.FirebaseMessaging
|
import com.google.firebase.messaging.FirebaseMessaging
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
@ -36,7 +34,7 @@ class TestFirebaseToken @Inject constructor(
|
||||||
private val fcmHelper: FcmHelper,
|
private val fcmHelper: FcmHelper,
|
||||||
) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) {
|
) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
status = TestStatus.RUNNING
|
status = TestStatus.RUNNING
|
||||||
try {
|
try {
|
||||||
FirebaseMessaging.getInstance().token
|
FirebaseMessaging.getInstance().token
|
||||||
|
@ -53,7 +51,7 @@ class TestFirebaseToken @Inject constructor(
|
||||||
"ACCOUNT_MISSING" -> {
|
"ACCOUNT_MISSING" -> {
|
||||||
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) {
|
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) {
|
||||||
override fun doFix() {
|
override fun doFix() {
|
||||||
startAddGoogleAccountIntent(context, activityResultLauncher)
|
startAddGoogleAccountIntent(context, testParameters.activityResultLauncher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg)
|
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg)
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.gplay.features.settings.troubleshoot
|
package im.vector.app.gplay.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import com.google.android.gms.common.ConnectionResult
|
import com.google.android.gms.common.ConnectionResult
|
||||||
import com.google.android.gms.common.GoogleApiAvailability
|
import com.google.android.gms.common.GoogleApiAvailability
|
||||||
|
@ -35,7 +33,7 @@ class TestPlayServices @Inject constructor(
|
||||||
) :
|
) :
|
||||||
TroubleshootTest(R.string.settings_troubleshoot_test_play_services_title) {
|
TroubleshootTest(R.string.settings_troubleshoot_test_play_services_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
val apiAvailability = GoogleApiAvailability.getInstance()
|
val apiAvailability = GoogleApiAvailability.getInstance()
|
||||||
val resultCode = apiAvailability.isGooglePlayServicesAvailable(context)
|
val resultCode = apiAvailability.isGooglePlayServicesAvailable(context)
|
||||||
if (resultCode == ConnectionResult.SUCCESS) {
|
if (resultCode == ConnectionResult.SUCCESS) {
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.gplay.features.settings.troubleshoot
|
package im.vector.app.gplay.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.work.WorkInfo
|
import androidx.work.WorkInfo
|
||||||
|
@ -42,7 +40,7 @@ class TestTokenRegistration @Inject constructor(
|
||||||
) :
|
) :
|
||||||
TroubleshootTest(R.string.settings_troubleshoot_test_token_registration_title) {
|
TroubleshootTest(R.string.settings_troubleshoot_test_token_registration_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
// Check if we have a registered pusher for this token
|
// Check if we have a registered pusher for this token
|
||||||
val fcmToken = fcmHelper.getFcmToken() ?: run {
|
val fcmToken = fcmHelper.getFcmToken() ?: run {
|
||||||
status = TestStatus.FAILED
|
status = TestStatus.FAILED
|
||||||
|
@ -66,9 +64,9 @@ class TestTokenRegistration @Inject constructor(
|
||||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
|
||||||
if (workInfo != null) {
|
if (workInfo != null) {
|
||||||
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
|
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
|
||||||
manager?.retry(activityResultLauncher)
|
manager?.retry(testParameters)
|
||||||
} else if (workInfo.state == WorkInfo.State.FAILED) {
|
} else if (workInfo.state == WorkInfo.State.FAILED) {
|
||||||
manager?.retry(activityResultLauncher)
|
manager?.retry(testParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
|
||||||
|
<!-- https://developer.android.com/develop/ui/views/notifications/notification-permission#exemptions -->
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<!-- Call feature -->
|
<!-- Call feature -->
|
||||||
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
|
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
|
||||||
<!-- Commented because Google PlayStore does not like we add permission if we are not requiring it. And it was added for future use -->
|
<!-- Commented because Google PlayStore does not like we add permission if we are not requiring it. And it was added for future use -->
|
||||||
|
|
|
@ -48,6 +48,7 @@ import im.vector.app.core.platform.VectorMenuProvider
|
||||||
import im.vector.app.core.pushers.FcmHelper
|
import im.vector.app.core.pushers.FcmHelper
|
||||||
import im.vector.app.core.pushers.PushersManager
|
import im.vector.app.core.pushers.PushersManager
|
||||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
|
import im.vector.app.core.utils.registerForPermissionsResult
|
||||||
import im.vector.app.core.utils.startSharePlainTextIntent
|
import im.vector.app.core.utils.startSharePlainTextIntent
|
||||||
import im.vector.app.databinding.ActivityHomeBinding
|
import im.vector.app.databinding.ActivityHomeBinding
|
||||||
import im.vector.app.features.MainActivity
|
import im.vector.app.features.MainActivity
|
||||||
|
@ -143,6 +144,7 @@ class HomeActivity :
|
||||||
@Inject lateinit var fcmHelper: FcmHelper
|
@Inject lateinit var fcmHelper: FcmHelper
|
||||||
@Inject lateinit var nightlyProxy: NightlyProxy
|
@Inject lateinit var nightlyProxy: NightlyProxy
|
||||||
@Inject lateinit var disclaimerDialog: DisclaimerDialog
|
@Inject lateinit var disclaimerDialog: DisclaimerDialog
|
||||||
|
@Inject lateinit var notificationPermissionManager: NotificationPermissionManager
|
||||||
|
|
||||||
private var isNewAppLayoutEnabled: Boolean = false // delete once old app layout is removed
|
private var isNewAppLayoutEnabled: Boolean = false // delete once old app layout is removed
|
||||||
|
|
||||||
|
@ -172,6 +174,10 @@ class HomeActivity :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val postPermissionLauncher = registerForPermissionsResult { _, _ ->
|
||||||
|
// Nothing to do with the result.
|
||||||
|
}
|
||||||
|
|
||||||
private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {
|
private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {
|
||||||
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
|
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
|
||||||
if (f is MatrixToBottomSheet) {
|
if (f is MatrixToBottomSheet) {
|
||||||
|
@ -273,6 +279,7 @@ class HomeActivity :
|
||||||
}
|
}
|
||||||
is HomeActivityViewEvents.OnCrossSignedInvalidated -> handleCrossSigningInvalidated(it)
|
is HomeActivityViewEvents.OnCrossSignedInvalidated -> handleCrossSigningInvalidated(it)
|
||||||
HomeActivityViewEvents.ShowAnalyticsOptIn -> handleShowAnalyticsOptIn()
|
HomeActivityViewEvents.ShowAnalyticsOptIn -> handleShowAnalyticsOptIn()
|
||||||
|
HomeActivityViewEvents.ShowNotificationDialog -> handleShowNotificationDialog()
|
||||||
HomeActivityViewEvents.ShowReleaseNotes -> handleShowReleaseNotes()
|
HomeActivityViewEvents.ShowReleaseNotes -> handleShowReleaseNotes()
|
||||||
HomeActivityViewEvents.NotifyUserForThreadsMigration -> handleNotifyUserForThreadsMigration()
|
HomeActivityViewEvents.NotifyUserForThreadsMigration -> handleNotifyUserForThreadsMigration()
|
||||||
is HomeActivityViewEvents.MigrateThreads -> migrateThreadsIfNeeded(it.checkSession)
|
is HomeActivityViewEvents.MigrateThreads -> migrateThreadsIfNeeded(it.checkSession)
|
||||||
|
@ -288,6 +295,10 @@ class HomeActivity :
|
||||||
homeActivityViewModel.handle(HomeActivityViewActions.ViewStarted)
|
homeActivityViewModel.handle(HomeActivityViewActions.ViewStarted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleShowNotificationDialog() {
|
||||||
|
notificationPermissionManager.eventuallyRequestPermission(this, postPermissionLauncher)
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleShowReleaseNotes() {
|
private fun handleShowReleaseNotes() {
|
||||||
startActivity(Intent(this, ReleaseNotesActivity::class.java))
|
startActivity(Intent(this, ReleaseNotesActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ sealed interface HomeActivityViewEvents : VectorViewEvents {
|
||||||
data class OnCrossSignedInvalidated(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents
|
data class OnCrossSignedInvalidated(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents
|
||||||
object PromptToEnableSessionPush : HomeActivityViewEvents
|
object PromptToEnableSessionPush : HomeActivityViewEvents
|
||||||
object ShowAnalyticsOptIn : HomeActivityViewEvents
|
object ShowAnalyticsOptIn : HomeActivityViewEvents
|
||||||
|
object ShowNotificationDialog : HomeActivityViewEvents
|
||||||
object ShowReleaseNotes : HomeActivityViewEvents
|
object ShowReleaseNotes : HomeActivityViewEvents
|
||||||
object NotifyUserForThreadsMigration : HomeActivityViewEvents
|
object NotifyUserForThreadsMigration : HomeActivityViewEvents
|
||||||
data class MigrateThreads(val checkSession: Boolean) : HomeActivityViewEvents
|
data class MigrateThreads(val checkSession: Boolean) : HomeActivityViewEvents
|
||||||
|
|
|
@ -143,6 +143,8 @@ class HomeActivityViewModel @AssistedInject constructor(
|
||||||
.onEach { didAskUser ->
|
.onEach { didAskUser ->
|
||||||
if (!didAskUser) {
|
if (!didAskUser) {
|
||||||
_viewEvents.post(HomeActivityViewEvents.ShowAnalyticsOptIn)
|
_viewEvents.post(HomeActivityViewEvents.ShowAnalyticsOptIn)
|
||||||
|
} else {
|
||||||
|
_viewEvents.post(HomeActivityViewEvents.ShowNotificationDialog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.launchIn(viewModelScope)
|
.launchIn(viewModelScope)
|
||||||
|
@ -162,6 +164,8 @@ class HomeActivityViewModel @AssistedInject constructor(
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
_viewEvents.post(HomeActivityViewEvents.ShowNotificationDialog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.home
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.utils.checkPermissions
|
||||||
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
|
import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class NotificationPermissionManager @Inject constructor(
|
||||||
|
private val sdkIntProvider: BuildVersionSdkIntProvider,
|
||||||
|
private val vectorPreferences: VectorPreferences,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun isPermissionGranted(activity: Activity): Boolean {
|
||||||
|
return if (sdkIntProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
|
||||||
|
ContextCompat.checkSelfPermission(
|
||||||
|
activity,
|
||||||
|
Manifest.permission.POST_NOTIFICATIONS
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
} else {
|
||||||
|
// No notification permission management before API 33.
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun eventuallyRequestPermission(
|
||||||
|
activity: Activity,
|
||||||
|
requestPermissionLauncher: ActivityResultLauncher<Array<String>>,
|
||||||
|
showRationale: Boolean = true,
|
||||||
|
ignorePreference: Boolean = false,
|
||||||
|
) {
|
||||||
|
if (!sdkIntProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU)) return
|
||||||
|
if (!vectorPreferences.areNotificationEnabledForDevice() && !ignorePreference) return
|
||||||
|
checkPermissions(
|
||||||
|
listOf(Manifest.permission.POST_NOTIFICATIONS),
|
||||||
|
activity,
|
||||||
|
activityResultLauncher = requestPermissionLauncher,
|
||||||
|
if (showRationale) R.string.permissions_rationale_msg_notification else 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(33)
|
||||||
|
fun askPermission(requestPermissionLauncher: ActivityResultLauncher<Array<String>>) {
|
||||||
|
requestPermissionLauncher.launch(
|
||||||
|
arrayOf(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,9 +43,12 @@ import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.core.services.GuardServiceStarter
|
import im.vector.app.core.services.GuardServiceStarter
|
||||||
import im.vector.app.core.utils.combineLatest
|
import im.vector.app.core.utils.combineLatest
|
||||||
import im.vector.app.core.utils.isIgnoringBatteryOptimizations
|
import im.vector.app.core.utils.isIgnoringBatteryOptimizations
|
||||||
|
import im.vector.app.core.utils.registerForPermissionsResult
|
||||||
import im.vector.app.core.utils.requestDisablingBatteryOptimization
|
import im.vector.app.core.utils.requestDisablingBatteryOptimization
|
||||||
|
import im.vector.app.core.utils.startNotificationSettingsIntent
|
||||||
import im.vector.app.features.VectorFeatures
|
import im.vector.app.features.VectorFeatures
|
||||||
import im.vector.app.features.analytics.plan.MobileScreen
|
import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
|
import im.vector.app.features.home.NotificationPermissionManager
|
||||||
import im.vector.app.features.notifications.NotificationUtils
|
import im.vector.app.features.notifications.NotificationUtils
|
||||||
import im.vector.app.features.settings.BackgroundSyncMode
|
import im.vector.app.features.settings.BackgroundSyncMode
|
||||||
import im.vector.app.features.settings.BackgroundSyncModeChooserDialog
|
import im.vector.app.features.settings.BackgroundSyncModeChooserDialog
|
||||||
|
@ -76,12 +79,24 @@ class VectorSettingsNotificationPreferenceFragment :
|
||||||
@Inject lateinit var vectorPreferences: VectorPreferences
|
@Inject lateinit var vectorPreferences: VectorPreferences
|
||||||
@Inject lateinit var guardServiceStarter: GuardServiceStarter
|
@Inject lateinit var guardServiceStarter: GuardServiceStarter
|
||||||
@Inject lateinit var vectorFeatures: VectorFeatures
|
@Inject lateinit var vectorFeatures: VectorFeatures
|
||||||
|
@Inject lateinit var notificationPermissionManager: NotificationPermissionManager
|
||||||
|
|
||||||
override var titleRes: Int = R.string.settings_notifications
|
override var titleRes: Int = R.string.settings_notifications
|
||||||
override val preferenceXmlRes = R.xml.vector_settings_notifications
|
override val preferenceXmlRes = R.xml.vector_settings_notifications
|
||||||
|
|
||||||
private var interactionListener: VectorSettingsFragmentInteractionListener? = null
|
private var interactionListener: VectorSettingsFragmentInteractionListener? = null
|
||||||
|
|
||||||
|
private val notificationStartForActivityResult = registerStartForActivityResult { _ ->
|
||||||
|
// No op
|
||||||
|
}
|
||||||
|
|
||||||
|
private val postPermissionLauncher = registerForPermissionsResult { _, deniedPermanently ->
|
||||||
|
if (deniedPermanently) {
|
||||||
|
// Open System setting, to give a chance to the user to enable notification. Sometimes the permission dialog is not displayed
|
||||||
|
startNotificationSettingsIntent(requireContext(), notificationStartForActivityResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
analyticsScreenName = MobileScreen.ScreenName.SettingsNotifications
|
analyticsScreenName = MobileScreen.ScreenName.SettingsNotifications
|
||||||
|
@ -118,6 +133,12 @@ class VectorSettingsNotificationPreferenceFragment :
|
||||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_NOTIFICATION_METHOD_KEY)
|
findPreference<VectorPreference>(VectorPreferences.SETTINGS_NOTIFICATION_METHOD_KEY)
|
||||||
?.summary = unifiedPushHelper.getCurrentDistributorName()
|
?.summary = unifiedPushHelper.getCurrentDistributorName()
|
||||||
}
|
}
|
||||||
|
notificationPermissionManager.eventuallyRequestPermission(
|
||||||
|
requireActivity(),
|
||||||
|
postPermissionLauncher,
|
||||||
|
showRationale = false,
|
||||||
|
ignorePreference = true
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
unifiedPushHelper.unregister(pushersManager)
|
unifiedPushHelper.unregister(pushersManager)
|
||||||
session.pushersService().refreshPushers()
|
session.pushersService().refreshPushers()
|
||||||
|
|
|
@ -34,6 +34,8 @@ import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.cleanup
|
import im.vector.app.core.extensions.cleanup
|
||||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
|
import im.vector.app.core.utils.registerForPermissionsResult
|
||||||
|
import im.vector.app.core.utils.startNotificationSettingsIntent
|
||||||
import im.vector.app.databinding.FragmentSettingsNotificationsTroubleshootBinding
|
import im.vector.app.databinding.FragmentSettingsNotificationsTroubleshootBinding
|
||||||
import im.vector.app.features.notifications.NotificationActionIds
|
import im.vector.app.features.notifications.NotificationActionIds
|
||||||
import im.vector.app.features.push.NotificationTroubleshootTestManagerFactory
|
import im.vector.app.features.push.NotificationTroubleshootTestManagerFactory
|
||||||
|
@ -76,7 +78,7 @@ class VectorSettingsNotificationsTroubleshootFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
views.troubleshootRunButton.debouncedClicks {
|
views.troubleshootRunButton.debouncedClicks {
|
||||||
testManager?.retry(testStartForActivityResult)
|
testManager?.retry(TroubleshootTest.TestParameters(testStartForActivityResult, testStartForPermissionResult))
|
||||||
}
|
}
|
||||||
startUI()
|
startUI()
|
||||||
}
|
}
|
||||||
|
@ -125,7 +127,7 @@ class VectorSettingsNotificationsTroubleshootFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
views.troubleshootTestRecyclerView.adapter = testManager?.adapter
|
views.troubleshootTestRecyclerView.adapter = testManager?.adapter
|
||||||
testManager?.runDiagnostic(testStartForActivityResult)
|
testManager?.runDiagnostic(TroubleshootTest.TestParameters(testStartForActivityResult, testStartForPermissionResult))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -139,8 +141,17 @@ class VectorSettingsNotificationsTroubleshootFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val testStartForPermissionResult = registerForPermissionsResult { allGranted, deniedPermanently ->
|
||||||
|
if (allGranted) {
|
||||||
|
retry()
|
||||||
|
} else if (deniedPermanently) {
|
||||||
|
// Open System setting
|
||||||
|
startNotificationSettingsIntent(requireContext(), testStartForActivityResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun retry() {
|
private fun retry() {
|
||||||
testManager?.retry(testStartForActivityResult)
|
testManager?.retry(TroubleshootTest.TestParameters(testStartForActivityResult, testStartForPermissionResult))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDetach() {
|
override fun onDetach() {
|
||||||
|
|
|
@ -15,10 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
@ -50,7 +48,7 @@ class NotificationTroubleshootTestManager(val fragment: Fragment) {
|
||||||
test.manager = this
|
test.manager = this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runDiagnostic(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
fun runDiagnostic(testParameters: TroubleshootTest.TestParameters) {
|
||||||
if (isCancelled) return
|
if (isCancelled) return
|
||||||
currentTestIndex = 0
|
currentTestIndex = 0
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
@ -69,7 +67,7 @@ class NotificationTroubleshootTestManager(val fragment: Fragment) {
|
||||||
// Cosmetic: Start with a small delay for UI/UX reason (better animation effect) for non async tests
|
// Cosmetic: Start with a small delay for UI/UX reason (better animation effect) for non async tests
|
||||||
handler.postDelayed({
|
handler.postDelayed({
|
||||||
if (fragment.isAdded) {
|
if (fragment.isAdded) {
|
||||||
troubleshootTest.perform(activityResultLauncher)
|
troubleshootTest.perform(testParameters)
|
||||||
}
|
}
|
||||||
}, 600)
|
}, 600)
|
||||||
} else {
|
} else {
|
||||||
|
@ -81,18 +79,18 @@ class NotificationTroubleshootTestManager(val fragment: Fragment) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fragment.isAdded) {
|
if (fragment.isAdded) {
|
||||||
testList.firstOrNull()?.perform(activityResultLauncher)
|
testList.firstOrNull()?.perform(testParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun retry(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
fun retry(testParameters: TroubleshootTest.TestParameters) {
|
||||||
testList.forEach {
|
testList.forEach {
|
||||||
it.cancel()
|
it.cancel()
|
||||||
it.description = null
|
it.description = null
|
||||||
it.quickFix = null
|
it.quickFix = null
|
||||||
it.status = TroubleshootTest.TestStatus.NOT_STARTED
|
it.status = TroubleshootTest.TestStatus.NOT_STARTED
|
||||||
}
|
}
|
||||||
runDiagnostic(activityResultLauncher)
|
runDiagnostic(testParameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasQuickFix(): Boolean {
|
fun hasQuickFix(): Boolean {
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
@ -38,7 +36,7 @@ class TestAccountSettings @Inject constructor(
|
||||||
) :
|
) :
|
||||||
TroubleshootTest(R.string.settings_troubleshoot_test_account_settings_title) {
|
TroubleshootTest(R.string.settings_troubleshoot_test_account_settings_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||||
val defaultRule = session.pushRuleService().getPushRules().getAllRules()
|
val defaultRule = session.pushRuleService().getPushRules().getAllRules()
|
||||||
.find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL }
|
.find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL }
|
||||||
|
@ -59,7 +57,7 @@ class TestAccountSettings @Inject constructor(
|
||||||
session.pushRuleService().updatePushRuleEnableStatus(RuleKind.OVERRIDE, defaultRule, !defaultRule.enabled)
|
session.pushRuleService().updatePushRuleEnableStatus(RuleKind.OVERRIDE, defaultRule, !defaultRule.enabled)
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
manager?.retry(activityResultLauncher)
|
manager?.retry(testParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.pushers.FcmHelper
|
import im.vector.app.core.pushers.FcmHelper
|
||||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
|
@ -30,7 +28,7 @@ class TestAvailableUnifiedPushDistributors @Inject constructor(
|
||||||
private val fcmHelper: FcmHelper,
|
private val fcmHelper: FcmHelper,
|
||||||
) : TroubleshootTest(R.string.settings_troubleshoot_test_distributors_title) {
|
) : TroubleshootTest(R.string.settings_troubleshoot_test_distributors_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
val distributors = unifiedPushHelper.getExternalDistributors()
|
val distributors = unifiedPushHelper.getExternalDistributors()
|
||||||
description = if (distributors.isEmpty()) {
|
description = if (distributors.isEmpty()) {
|
||||||
stringProvider.getString(
|
stringProvider.getString(
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
@ -28,7 +26,7 @@ class TestCurrentUnifiedPushDistributor @Inject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
) : TroubleshootTest(R.string.settings_troubleshoot_test_current_distributor_title) {
|
) : TroubleshootTest(R.string.settings_troubleshoot_test_current_distributor_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
description = stringProvider.getString(
|
description = stringProvider.getString(
|
||||||
R.string.settings_troubleshoot_test_current_distributor,
|
R.string.settings_troubleshoot_test_current_distributor,
|
||||||
unifiedPushHelper.getCurrentDistributorName()
|
unifiedPushHelper.getCurrentDistributorName()
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
|
@ -31,7 +29,7 @@ class TestDeviceSettings @Inject constructor(
|
||||||
) :
|
) :
|
||||||
TroubleshootTest(R.string.settings_troubleshoot_test_device_settings_title) {
|
TroubleshootTest(R.string.settings_troubleshoot_test_device_settings_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
if (vectorPreferences.areNotificationEnabledForDevice()) {
|
if (vectorPreferences.areNotificationEnabledForDevice()) {
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_device_settings_success)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_device_settings_success)
|
||||||
quickFix = null
|
quickFix = null
|
||||||
|
@ -40,7 +38,7 @@ class TestDeviceSettings @Inject constructor(
|
||||||
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_device_settings_quickfix) {
|
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_device_settings_quickfix) {
|
||||||
override fun doFix() {
|
override fun doFix() {
|
||||||
vectorPreferences.setNotificationEnabledForDevice(true)
|
vectorPreferences.setNotificationEnabledForDevice(true)
|
||||||
manager?.retry(activityResultLauncher)
|
manager?.retry(testParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_device_settings_failed)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_device_settings_failed)
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.work.WorkInfo
|
import androidx.work.WorkInfo
|
||||||
|
@ -38,7 +36,7 @@ class TestEndpointAsTokenRegistration @Inject constructor(
|
||||||
private val unifiedPushHelper: UnifiedPushHelper,
|
private val unifiedPushHelper: UnifiedPushHelper,
|
||||||
) : TroubleshootTest(R.string.settings_troubleshoot_test_endpoint_registration_title) {
|
) : TroubleshootTest(R.string.settings_troubleshoot_test_endpoint_registration_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
// Check if we have a registered pusher for this token
|
// Check if we have a registered pusher for this token
|
||||||
val endpoint = unifiedPushHelper.getEndpointOrToken() ?: run {
|
val endpoint = unifiedPushHelper.getEndpointOrToken() ?: run {
|
||||||
status = TestStatus.FAILED
|
status = TestStatus.FAILED
|
||||||
|
@ -66,9 +64,9 @@ class TestEndpointAsTokenRegistration @Inject constructor(
|
||||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
|
||||||
if (workInfo != null) {
|
if (workInfo != null) {
|
||||||
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
|
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
|
||||||
manager?.retry(activityResultLauncher)
|
manager?.retry(testParameters)
|
||||||
} else if (workInfo.state == WorkInfo.State.FAILED) {
|
} else if (workInfo.state == WorkInfo.State.FAILED) {
|
||||||
manager?.retry(activityResultLauncher)
|
manager?.retry(testParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.utils.startNotificationSettingsIntent
|
import im.vector.app.core.utils.startNotificationSettingsIntent
|
||||||
|
@ -34,14 +32,14 @@ class TestNotification @Inject constructor(
|
||||||
) :
|
) :
|
||||||
TroubleshootTest(R.string.settings_troubleshoot_test_notification_title) {
|
TroubleshootTest(R.string.settings_troubleshoot_test_notification_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
// Display the notification right now
|
// Display the notification right now
|
||||||
notificationUtils.displayDiagnosticNotification()
|
notificationUtils.displayDiagnosticNotification()
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_notification_notice)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_notification_notice)
|
||||||
|
|
||||||
quickFix = object : TroubleshootQuickFix(R.string.open_settings) {
|
quickFix = object : TroubleshootQuickFix(R.string.open_settings) {
|
||||||
override fun doFix() {
|
override fun doFix() {
|
||||||
startNotificationSettingsIntent(context, activityResultLauncher)
|
startNotificationSettingsIntent(context, testParameters.activityResultLauncher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.error.ErrorFormatter
|
import im.vector.app.core.error.ErrorFormatter
|
||||||
|
@ -43,7 +41,7 @@ class TestPushFromPushGateway @Inject constructor(
|
||||||
private var action: Job? = null
|
private var action: Job? = null
|
||||||
private var pushReceived: Boolean = false
|
private var pushReceived: Boolean = false
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
pushReceived = false
|
pushReceived = false
|
||||||
action = activeSessionHolder.getActiveSession().coroutineScope.launch {
|
action = activeSessionHolder.getActiveSession().coroutineScope.launch {
|
||||||
val result = runCatching { pushersManager.testPush() }
|
val result = runCatching { pushersManager.testPush() }
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
@ -39,7 +37,7 @@ class TestPushRulesSettings @Inject constructor(
|
||||||
RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS
|
RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||||
val pushRules = session.pushRuleService().getPushRules().getAllRules()
|
val pushRules = session.pushRuleService().getPushRules().getAllRules()
|
||||||
var oneOrMoreRuleIsOff = false
|
var oneOrMoreRuleIsOff = false
|
||||||
|
|
|
@ -15,34 +15,44 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.utils.startNotificationSettingsIntent
|
import im.vector.app.core.utils.startNotificationSettingsIntent
|
||||||
|
import im.vector.app.features.home.NotificationPermissionManager
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if notifications are enable in the system settings for this app.
|
* Checks if notifications are enable in the system settings for this app.
|
||||||
|
* On Android 13, it will check for the notification permission.
|
||||||
*/
|
*/
|
||||||
class TestSystemSettings @Inject constructor(
|
class TestSystemSettings @Inject constructor(
|
||||||
private val context: FragmentActivity,
|
private val context: FragmentActivity,
|
||||||
private val stringProvider: StringProvider
|
private val stringProvider: StringProvider,
|
||||||
) :
|
private val notificationPermissionManager: NotificationPermissionManager,
|
||||||
TroubleshootTest(R.string.settings_troubleshoot_test_system_settings_title) {
|
) : TroubleshootTest(R.string.settings_troubleshoot_test_system_settings_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {
|
if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_system_settings_success)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_system_settings_success)
|
||||||
quickFix = null
|
quickFix = null
|
||||||
status = TestStatus.SUCCESS
|
status = TestStatus.SUCCESS
|
||||||
} else {
|
} else {
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_system_settings_failed)
|
if (notificationPermissionManager.isPermissionGranted(context)) {
|
||||||
quickFix = object : TroubleshootQuickFix(R.string.open_settings) {
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_system_settings_failed)
|
||||||
override fun doFix() {
|
quickFix = object : TroubleshootQuickFix(R.string.open_settings) {
|
||||||
startNotificationSettingsIntent(context, activityResultLauncher)
|
override fun doFix() {
|
||||||
|
startNotificationSettingsIntent(context, testParameters.activityResultLauncher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// In this case, we can ask for user permission
|
||||||
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_system_settings_permission_failed)
|
||||||
|
quickFix = object : TroubleshootQuickFix(R.string.grant_permission) {
|
||||||
|
override fun doFix() {
|
||||||
|
notificationPermissionManager.askPermission(testParameters.permissionResultLauncher)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = TestStatus.FAILED
|
status = TestStatus.FAILED
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
@ -28,7 +26,7 @@ class TestUnifiedPushEndpoint @Inject constructor(
|
||||||
private val unifiedPushHelper: UnifiedPushHelper,
|
private val unifiedPushHelper: UnifiedPushHelper,
|
||||||
) : TroubleshootTest(R.string.settings_troubleshoot_test_current_endpoint_title) {
|
) : TroubleshootTest(R.string.settings_troubleshoot_test_current_endpoint_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
val endpoint = unifiedPushHelper.getPrivacyFriendlyUpEndpoint()
|
val endpoint = unifiedPushHelper.getPrivacyFriendlyUpEndpoint()
|
||||||
if (endpoint != null) {
|
if (endpoint != null) {
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_current_endpoint_success, endpoint)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_current_endpoint_success, endpoint)
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package im.vector.app.features.settings.troubleshoot
|
package im.vector.app.features.settings.troubleshoot
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
@ -28,7 +26,7 @@ class TestUnifiedPushGateway @Inject constructor(
|
||||||
private val stringProvider: StringProvider
|
private val stringProvider: StringProvider
|
||||||
) : TroubleshootTest(R.string.settings_troubleshoot_test_current_gateway_title) {
|
) : TroubleshootTest(R.string.settings_troubleshoot_test_current_gateway_title) {
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(testParameters: TestParameters) {
|
||||||
description = stringProvider.getString(
|
description = stringProvider.getString(
|
||||||
R.string.settings_troubleshoot_test_current_gateway,
|
R.string.settings_troubleshoot_test_current_gateway,
|
||||||
unifiedPushHelper.getPushGateway()
|
unifiedPushHelper.getPushGateway()
|
||||||
|
|
|
@ -22,6 +22,11 @@ import kotlin.properties.Delegates
|
||||||
|
|
||||||
abstract class TroubleshootTest(@StringRes val titleResId: Int) {
|
abstract class TroubleshootTest(@StringRes val titleResId: Int) {
|
||||||
|
|
||||||
|
data class TestParameters(
|
||||||
|
val activityResultLauncher: ActivityResultLauncher<Intent>,
|
||||||
|
val permissionResultLauncher: ActivityResultLauncher<Array<String>>
|
||||||
|
)
|
||||||
|
|
||||||
enum class TestStatus {
|
enum class TestStatus {
|
||||||
NOT_STARTED,
|
NOT_STARTED,
|
||||||
RUNNING,
|
RUNNING,
|
||||||
|
@ -40,7 +45,7 @@ abstract class TroubleshootTest(@StringRes val titleResId: Int) {
|
||||||
|
|
||||||
var manager: NotificationTroubleshootTestManager? = null
|
var manager: NotificationTroubleshootTestManager? = null
|
||||||
|
|
||||||
abstract fun perform(activityResultLauncher: ActivityResultLauncher<Intent>)
|
abstract fun perform(testParameters: TestParameters)
|
||||||
|
|
||||||
fun isFinished(): Boolean = (status == TestStatus.FAILED || status == TestStatus.SUCCESS)
|
fun isFinished(): Boolean = (status == TestStatus.FAILED || status == TestStatus.SUCCESS)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue