diff --git a/build.gradle b/build.gradle index 5409afedc..9e1366ce3 100644 --- a/build.gradle +++ b/build.gradle @@ -86,11 +86,11 @@ ext { android { namespace 'eu.siacs.conversations' - compileSdkVersion 31 + compileSdkVersion 32 defaultConfig { minSdkVersion 21 - targetSdkVersion 30 + targetSdkVersion 32 versionCode 42034 versionName "2.10.8" archivesBaseName += "-$versionName" diff --git a/src/conversations/AndroidManifest.xml b/src/conversations/AndroidManifest.xml index bf2297949..d573b32d3 100644 --- a/src/conversations/AndroidManifest.xml +++ b/src/conversations/AndroidManifest.xml @@ -26,7 +26,8 @@ + android:launchMode="singleTask" + android:exported="true"> diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 458c8a7f4..2a48da7a0 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -83,7 +83,9 @@ - + @@ -107,6 +109,7 @@ android:label="@string/title_activity_show_location" /> @@ -127,6 +130,7 @@ android:windowSoftInputMode="stateAlwaysHidden" /> @@ -166,6 +170,7 @@ @@ -174,6 +179,7 @@ @@ -192,6 +198,7 @@ @@ -225,6 +232,7 @@ android:label="@string/group_chat_avatar" /> @@ -261,10 +269,6 @@ - - - - @@ -302,6 +307,7 @@ diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index abe6e9e11..acac26cc0 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.services; +import static eu.siacs.conversations.utils.Compatibility.s; + import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; @@ -625,7 +627,9 @@ public class NotificationService { mXmppConnectionService, requestCode, fullScreenIntent, - PendingIntent.FLAG_UPDATE_CURRENT); + s() + ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } public void cancelIncomingCallNotification() { @@ -759,7 +763,7 @@ public class NotificationService { && conversations != null && conversations.size() == 1; // if this check is changed to > 0 catchup messages will - // create one notification per conversation + // create one notification per conversation if (notifications.size() == 0) { cancel(NOTIFICATION_ID); @@ -835,9 +839,7 @@ public class NotificationService { } else { mBuilder.setLocalOnly(true); } - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mBuilder.setCategory(Notification.CATEGORY_MESSAGE); - } + mBuilder.setCategory(Notification.CATEGORY_MESSAGE); mBuilder.setPriority( notify ? (headsup @@ -1280,7 +1282,9 @@ public class NotificationService { mXmppConnectionService, generateRequestCode(message.getConversation(), 18), intent, - PendingIntent.FLAG_UPDATE_CURRENT); + s() + ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } } return null; @@ -1299,13 +1303,17 @@ public class NotificationService { mXmppConnectionService, generateRequestCode(conversationUuid, 8), viewConversationIntent, - PendingIntent.FLAG_UPDATE_CURRENT); + s() + ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } else { return PendingIntent.getActivity( mXmppConnectionService, generateRequestCode(conversationUuid, 10), viewConversationIntent, - PendingIntent.FLAG_UPDATE_CURRENT); + s() + ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } } @@ -1332,9 +1340,20 @@ public class NotificationService { if (conversation != null) { intent.putExtra("uuid", conversation.getUuid()); return PendingIntent.getService( - mXmppConnectionService, generateRequestCode(conversation, 20), intent, 0); + mXmppConnectionService, + generateRequestCode(conversation, 20), + intent, + s() + ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } - return PendingIntent.getService(mXmppConnectionService, 0, intent, 0); + return PendingIntent.getService( + mXmppConnectionService, + 0, + intent, + s() + ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } private PendingIntent createReplyIntent( @@ -1348,7 +1367,12 @@ public class NotificationService { intent.putExtra("last_message_uuid", lastMessageUuid); final int id = generateRequestCode(conversation, dismissAfterReply ? 12 : 14); return PendingIntent.getService( - mXmppConnectionService, id, intent, PendingIntent.FLAG_UPDATE_CURRENT); + mXmppConnectionService, + id, + intent, + s() + ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } private PendingIntent createReadPendingIntent(Conversation conversation) { @@ -1360,7 +1384,9 @@ public class NotificationService { mXmppConnectionService, generateRequestCode(conversation, 16), intent, - PendingIntent.FLAG_UPDATE_CURRENT); + s() + ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } private PendingIntent createCallAction(String sessionId, final String action, int requestCode) { @@ -1369,7 +1395,12 @@ public class NotificationService { intent.setPackage(mXmppConnectionService.getPackageName()); intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, sessionId); return PendingIntent.getService( - mXmppConnectionService, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); + mXmppConnectionService, + requestCode, + intent, + s() + ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } private PendingIntent createSnoozeIntent(Conversation conversation) { @@ -1381,19 +1412,33 @@ public class NotificationService { mXmppConnectionService, generateRequestCode(conversation, 22), intent, - PendingIntent.FLAG_UPDATE_CURRENT); + s() + ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } private PendingIntent createTryAgainIntent() { final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class); intent.setAction(XmppConnectionService.ACTION_TRY_AGAIN); - return PendingIntent.getService(mXmppConnectionService, 45, intent, 0); + return PendingIntent.getService( + mXmppConnectionService, + 45, + intent, + s() + ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } private PendingIntent createDismissErrorIntent() { final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class); intent.setAction(XmppConnectionService.ACTION_DISMISS_ERROR_NOTIFICATIONS); - return PendingIntent.getService(mXmppConnectionService, 69, intent, 0); + return PendingIntent.getService( + mXmppConnectionService, + 69, + intent, + s() + ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } private boolean wasHighlightedOrPrivate(final Message message) { @@ -1538,15 +1583,9 @@ public class NotificationService { } } mBuilder.setDeleteIntent(createDismissErrorIntent()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mBuilder.setVisibility(Notification.VISIBILITY_PRIVATE); - mBuilder.setSmallIcon(R.drawable.ic_warning_white_24dp); - } else { - mBuilder.setSmallIcon(R.drawable.ic_stat_alert_warning); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { - mBuilder.setLocalOnly(true); - } + mBuilder.setVisibility(Notification.VISIBILITY_PRIVATE); + mBuilder.setSmallIcon(R.drawable.ic_warning_white_24dp); + mBuilder.setLocalOnly(true); mBuilder.setPriority(Notification.PRIORITY_LOW); final Intent intent; if (AccountUtils.MANAGE_ACCOUNT_ACTIVITY != null) { @@ -1558,7 +1597,12 @@ public class NotificationService { } mBuilder.setContentIntent( PendingIntent.getActivity( - mXmppConnectionService, 145, intent, PendingIntent.FLAG_UPDATE_CURRENT)); + mXmppConnectionService, + 145, + intent, + s() + ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT)); if (Compatibility.runsTwentySix()) { mBuilder.setChannelId("error"); } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 7965a4e31..a6823e670 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -36,6 +36,7 @@ import android.preference.PreferenceManager; import android.provider.ContactsContract; import android.security.KeyChain; import android.telephony.PhoneStateListener; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.DisplayMetrics; @@ -1203,9 +1204,10 @@ public class XmppConnectionService extends Service { private void setupPhoneStateListener() { final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); - if (telephonyManager != null) { - telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + if (telephonyManager == null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + return; } + telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); } public boolean isPhoneInCall() { @@ -1402,7 +1404,16 @@ public class XmppConnectionService extends Service { final Intent intent = new Intent(this, EventReceiver.class); intent.setAction("ping"); try { - PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode, intent, 0); + final PendingIntent pendingIntent; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + pendingIntent = + PendingIntent.getBroadcast( + this, requestCode, intent, PendingIntent.FLAG_IMMUTABLE); + } else { + pendingIntent = + PendingIntent.getBroadcast( + this, requestCode, intent, 0); + } alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToWake, pendingIntent); } catch (RuntimeException e) { Log.e(Config.LOGTAG, "unable to schedule alarm for ping", e); diff --git a/src/main/java/eu/siacs/conversations/utils/Compatibility.java b/src/main/java/eu/siacs/conversations/utils/Compatibility.java index aadeaabf5..21004e26a 100644 --- a/src/main/java/eu/siacs/conversations/utils/Compatibility.java +++ b/src/main/java/eu/siacs/conversations/utils/Compatibility.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.utils; +import static eu.siacs.conversations.services.EventReceiver.EXTRA_NEEDS_FOREGROUND_SERVICE; + import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; @@ -24,23 +26,26 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.ui.SettingsActivity; import eu.siacs.conversations.ui.SettingsFragment; -import static eu.siacs.conversations.services.EventReceiver.EXTRA_NEEDS_FOREGROUND_SERVICE; - public class Compatibility { - private static final List UNUSED_SETTINGS_POST_TWENTYSIX = Arrays.asList( - "led", - "notification_ringtone", - "notification_headsup", - "vibrate_on_notification" - ); - private static final List UNUESD_SETTINGS_PRE_TWENTYSIX = Collections.singletonList( - "message_notification_settings" - ); - + private static final List UNUSED_SETTINGS_POST_TWENTYSIX = + Arrays.asList( + "led", + "notification_ringtone", + "notification_headsup", + "vibrate_on_notification"); + private static final List UNUESD_SETTINGS_PRE_TWENTYSIX = + Collections.singletonList("message_notification_settings"); public static boolean hasStoragePermission(Context context) { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + return Build.VERSION.SDK_INT < Build.VERSION_CODES.M + || ContextCompat.checkSelfPermission( + context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED; + } + + public static boolean s() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; } private static boolean runsTwentyFour() { @@ -66,20 +71,22 @@ public class Compatibility { private static boolean targetsTwentySix(Context context) { try { final PackageManager packageManager = context.getPackageManager(); - final ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0); + final ApplicationInfo applicationInfo = + packageManager.getApplicationInfo(context.getPackageName(), 0); return applicationInfo == null || applicationInfo.targetSdkVersion >= 26; } catch (PackageManager.NameNotFoundException | RuntimeException e) { - return true; //when in doubt… + return true; // when in doubt… } } private static boolean targetsTwentyFour(Context context) { try { final PackageManager packageManager = context.getPackageManager(); - final ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0); + final ApplicationInfo applicationInfo = + packageManager.getApplicationInfo(context.getPackageName(), 0); return applicationInfo == null || applicationInfo.targetSdkVersion >= 24; } catch (PackageManager.NameNotFoundException | RuntimeException e) { - return true; //when in doubt… + return true; // when in doubt… } } @@ -92,14 +99,23 @@ public class Compatibility { } public static boolean keepForegroundService(Context context) { - return runsAndTargetsTwentySix(context) || getBooleanPreference(context, SettingsActivity.KEEP_FOREGROUND_SERVICE, R.bool.enable_foreground_service); + return runsAndTargetsTwentySix(context) + || getBooleanPreference( + context, + SettingsActivity.KEEP_FOREGROUND_SERVICE, + R.bool.enable_foreground_service); } public static void removeUnusedPreferences(SettingsFragment settingsFragment) { - List categories = Arrays.asList( - (PreferenceCategory) settingsFragment.findPreference("notification_category"), - (PreferenceCategory) settingsFragment.findPreference("advanced")); - for (String key : (runsTwentySix() ? UNUSED_SETTINGS_POST_TWENTYSIX : UNUESD_SETTINGS_PRE_TWENTYSIX)) { + List categories = + Arrays.asList( + (PreferenceCategory) + settingsFragment.findPreference("notification_category"), + (PreferenceCategory) settingsFragment.findPreference("advanced")); + for (String key : + (runsTwentySix() + ? UNUSED_SETTINGS_POST_TWENTYSIX + : UNUESD_SETTINGS_PRE_TWENTYSIX)) { Preference preference = settingsFragment.findPreference(key); if (preference != null) { for (PreferenceCategory category : categories) { @@ -111,7 +127,8 @@ public class Compatibility { } if (Compatibility.runsTwentySix()) { if (targetsTwentySix(settingsFragment.getContext())) { - Preference preference = settingsFragment.findPreference(SettingsActivity.KEEP_FOREGROUND_SERVICE); + Preference preference = + settingsFragment.findPreference(SettingsActivity.KEEP_FOREGROUND_SERVICE); if (preference != null) { for (PreferenceCategory category : categories) { if (category != null) { @@ -132,11 +149,12 @@ public class Compatibility { context.startService(intent); } } catch (RuntimeException e) { - Log.d(Config.LOGTAG, context.getClass().getSimpleName() + " was unable to start service"); + Log.d( + Config.LOGTAG, + context.getClass().getSimpleName() + " was unable to start service"); } } - @SuppressLint("UnsupportedChromeOsCameraSystemFeature") public static boolean hasFeatureCamera(final Context context) { final PackageManager packageManager = context.getPackageManager();