diff --git a/app/src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt b/app/src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt index d7bd7bd300a0..8f9c5144e04c 100644 --- a/app/src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt +++ b/app/src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt @@ -28,6 +28,8 @@ import android.os.BatteryManager import android.os.PowerManager import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.client.preferences.AppPreferencesImpl +import com.nextcloud.utils.extensions.registerBroadcastReceiver +import com.owncloud.android.datamodel.ReceiverFlag internal class PowerManagementServiceImpl( private val context: Context, @@ -67,7 +69,11 @@ internal class PowerManagementServiceImpl( @Suppress("MagicNumber") // 100% is 100, we're not doing Cobol override val battery: BatteryStatus get() { - val intent: Intent? = context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + val intent: Intent? = context.registerBroadcastReceiver( + null, + IntentFilter(Intent.ACTION_BATTERY_CHANGED), + ReceiverFlag.NotExported + ) val isCharging = intent?.let { when (it.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)) { BatteryManager.BATTERY_PLUGGED_USB -> true diff --git a/app/src/main/java/com/nextcloud/utils/extensions/ContextExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/ContextExtensions.kt new file mode 100644 index 000000000000..6dc7dde71e2f --- /dev/null +++ b/app/src/main/java/com/nextcloud/utils/extensions/ContextExtensions.kt @@ -0,0 +1,39 @@ +/* + * Nextcloud Android client application + * + * @author Alper Ozturk + * Copyright (C) 2023 Alper Ozturk + * Copyright (C) 2023 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.utils.extensions + +import android.annotation.SuppressLint +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.Build +import com.owncloud.android.datamodel.ReceiverFlag + +@SuppressLint("UnspecifiedRegisterReceiverFlag") +fun Context.registerBroadcastReceiver(receiver: BroadcastReceiver?, filter: IntentFilter, flag: ReceiverFlag): Intent? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver(receiver, filter, flag.getId()) + } else { + registerReceiver(receiver, filter) + } +} diff --git a/app/src/main/java/com/owncloud/android/datamodel/ReceiverFlag.kt b/app/src/main/java/com/owncloud/android/datamodel/ReceiverFlag.kt new file mode 100644 index 000000000000..4fdbd0245ee3 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/datamodel/ReceiverFlag.kt @@ -0,0 +1,35 @@ +/* + * Nextcloud Android client application + * + * @author Alper Ozturk + * Copyright (C) 2023 Alper Ozturk + * Copyright (C) 2023 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.datamodel + +import android.content.Context +import android.os.Build +import androidx.annotation.RequiresApi + +enum class ReceiverFlag { + NotExported; + + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + fun getId(): Int { + return Context.RECEIVER_NOT_EXPORTED + } +} diff --git a/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.java b/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.java index b5f00b9203aa..80df3b22deb8 100644 --- a/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.java @@ -32,7 +32,9 @@ import com.nextcloud.client.network.ConnectivityService; import com.nextcloud.client.network.WalledCheckCache; import com.nextcloud.common.DNSCache; +import com.nextcloud.utils.extensions.ContextExtensionsKt; import com.owncloud.android.MainApp; +import com.owncloud.android.datamodel.ReceiverFlag; import com.owncloud.android.datamodel.UploadsStorageManager; /** @@ -69,7 +71,7 @@ public void onReceive(Context context, Intent intent) { } }; - context.registerReceiver(broadcastReceiver, intentFilter); + ContextExtensionsKt.registerBroadcastReceiver(context, broadcastReceiver, intentFilter, ReceiverFlag.NotExported); } public static void registerPowerChangeReceiver( @@ -96,7 +98,7 @@ public void onReceive(Context context, Intent intent) { } }; - context.registerReceiver(broadcastReceiver, intentFilter); + ContextExtensionsKt.registerBroadcastReceiver(context, broadcastReceiver, intentFilter, ReceiverFlag.NotExported); } public static void registerPowerSaveReceiver( @@ -122,6 +124,6 @@ public void onReceive(Context context, Intent intent) { } }; - context.registerReceiver(broadcastReceiver, intentFilter); + ContextExtensionsKt.registerBroadcastReceiver(context, broadcastReceiver, intentFilter, ReceiverFlag.NotExported); } } diff --git a/app/src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt b/app/src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt index cb454dc47c3f..f219479bc4e5 100644 --- a/app/src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt +++ b/app/src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt @@ -27,6 +27,8 @@ import android.os.BatteryManager import android.os.Build import android.os.PowerManager import com.nextcloud.client.preferences.AppPreferences +import com.nextcloud.utils.extensions.registerBroadcastReceiver +import com.owncloud.android.datamodel.ReceiverFlag import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -137,7 +139,9 @@ class TestPowerManagementService { @Before fun setUp() { - whenever(context.registerReceiver(anyOrNull(), anyOrNull())).thenReturn(intent) + whenever(context.registerBroadcastReceiver(anyOrNull(), anyOrNull(), ReceiverFlag.NotExported)).thenReturn( + intent + ) } @Test @@ -193,12 +197,14 @@ class TestPowerManagementService { // device has API level P or below // battery status sticky intent is NOT available whenever(deviceInfo.apiLevel).thenReturn(Build.VERSION_CODES.P) - whenever(context.registerReceiver(anyOrNull(), anyOrNull())).thenReturn(null) + whenever(context.registerBroadcastReceiver(anyOrNull(), anyOrNull(), ReceiverFlag.NotExported)).thenReturn( + null + ) // THEN // charging flag is false assertFalse(powerManagementService.battery.isCharging) - verify(context).registerReceiver(anyOrNull(), any()) + verify(context).registerBroadcastReceiver(anyOrNull(), any(), ReceiverFlag.NotExported) } @Test diff --git a/scripts/analysis/lint-results.txt b/scripts/analysis/lint-results.txt index 71b1bcf45f86..e53927d3c705 100644 --- a/scripts/analysis/lint-results.txt +++ b/scripts/analysis/lint-results.txt @@ -1,2 +1,2 @@ DO NOT TOUCH; GENERATED BY DRONE - Lint Report: 3 errors and 73 warnings + Lint Report: 3 errors and 70 warnings