Kaynağa Gözat

Merge pull request #1728 from nextcloud/bugfix/756/notificationChannels

Adapt notification code to Android 8.0 (Oreo) and later
Marcel Hibbe 3 yıl önce
ebeveyn
işleme
1c1600c33a

+ 3 - 58
app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt

@@ -23,15 +23,12 @@ import android.annotation.SuppressLint
 import android.app.Notification
 import android.app.PendingIntent
 import android.content.Intent
-import android.media.AudioAttributes
 import android.net.Uri
 import android.os.Bundle
 import android.os.Handler
-import android.text.TextUtils
 import android.util.Base64
 import android.util.Log
 import androidx.core.app.NotificationCompat
-import androidx.core.app.NotificationManagerCompat
 import androidx.emoji.text.EmojiCompat
 import androidx.work.Data
 import androidx.work.OneTimeWorkRequest
@@ -48,7 +45,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA
 import com.nextcloud.talk.events.CallNotificationClick
 import com.nextcloud.talk.jobs.NotificationWorker
 import com.nextcloud.talk.jobs.PushRegistrationWorker
-import com.nextcloud.talk.models.RingtoneSettings
 import com.nextcloud.talk.models.SignatureVerification
 import com.nextcloud.talk.models.json.participants.Participant
 import com.nextcloud.talk.models.json.participants.ParticipantsOverall
@@ -57,7 +53,7 @@ import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.NotificationUtils
 import com.nextcloud.talk.utils.NotificationUtils.cancelAllNotificationsForAccount
 import com.nextcloud.talk.utils.NotificationUtils.cancelExistingNotificationWithId
-import com.nextcloud.talk.utils.NotificationUtils.createNotificationChannel
+import com.nextcloud.talk.utils.NotificationUtils.getCallRingtoneUri
 import com.nextcloud.talk.utils.PushUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FROM_NOTIFICATION_START_CALL
@@ -73,7 +69,6 @@ import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import retrofit2.Retrofit
-import java.io.IOException
 import java.net.CookieManager
 import java.security.InvalidKeyException
 import java.security.NoSuchAlgorithmException
@@ -202,58 +197,8 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
                                 PendingIntent.FLAG_UPDATE_CURRENT
                             )
 
-                            val audioAttributesBuilder =
-                                AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-                            audioAttributesBuilder.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST)
-
-                            val ringtonePreferencesString: String? = appPreferences!!.callRingtoneUri
-                            val soundUri = if (TextUtils.isEmpty(ringtonePreferencesString)) {
-                                Uri.parse(
-                                    "android.resource://" + applicationContext.packageName +
-                                        "/raw/librem_by_feandesign_call"
-                                )
-                            } else {
-                                try {
-                                    val ringtoneSettings =
-                                        LoganSquare.parse(ringtonePreferencesString, RingtoneSettings::class.java)
-                                    ringtoneSettings.ringtoneUri
-                                } catch (exception: IOException) {
-                                    Uri.parse(
-                                        "android.resource://" +
-                                            applicationContext.packageName +
-                                            "/raw/librem_by_feandesign_call"
-                                    )
-                                }
-                            }
-
-                            val notificationChannelId = NotificationUtils.getNotificationChannelId(
-                                applicationContext.resources
-                                    .getString(R.string.nc_notification_channel_calls),
-                                applicationContext.resources
-                                    .getString(R.string.nc_notification_channel_calls_description),
-                                true,
-                                NotificationManagerCompat.IMPORTANCE_HIGH,
-                                soundUri!!,
-                                audioAttributesBuilder.build(),
-                                null,
-                                false
-                            )
-
-                            createNotificationChannel(
-                                applicationContext!!,
-                                notificationChannelId,
-                                applicationContext.resources
-                                    .getString(R.string.nc_notification_channel_calls),
-                                applicationContext.resources
-                                    .getString(R.string.nc_notification_channel_calls_description),
-                                true,
-                                NotificationManagerCompat.IMPORTANCE_HIGH,
-                                soundUri,
-                                audioAttributesBuilder.build(),
-                                null,
-                                false
-                            )
-
+                            val soundUri = getCallRingtoneUri(applicationContext!!, appPreferences!!)
+                            val notificationChannelId = NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V4
                             val uri = Uri.parse(signatureVerification!!.userEntity.baseUrl)
                             val baseUrl = uri.host
 

+ 1 - 2
app/src/main/java/com/nextcloud/talk/activities/CallActivity.java

@@ -2295,8 +2295,7 @@ public class CallActivity extends CallBaseActivity {
         stopCallingSound();
         Uri ringtoneUri;
         if (isIncomingCallFromNotification) {
-            ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
-                                        "/raw/librem_by_feandesign_call");
+            ringtoneUri = NotificationUtils.INSTANCE.getCallRingtoneUri(getApplicationContext(), appPreferences);
         } else {
             ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/raw" +
                                         "/tr110_1_kap8_3_freiton1");

+ 2 - 22
app/src/main/java/com/nextcloud/talk/activities/CallNotificationActivity.java

@@ -32,11 +32,9 @@ import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
-import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 
-import com.bluelinelabs.logansquare.LoganSquare;
 import com.facebook.common.executors.UiThreadImmediateExecutorService;
 import com.facebook.common.references.CloseableReference;
 import com.facebook.datasource.DataSource;
@@ -50,7 +48,6 @@ import com.nextcloud.talk.api.NcApi;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.databinding.CallNotificationActivityBinding;
 import com.nextcloud.talk.events.CallNotificationClick;
-import com.nextcloud.talk.models.RingtoneSettings;
 import com.nextcloud.talk.models.database.CapabilitiesUtil;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.conversations.Conversation;
@@ -60,6 +57,7 @@ import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.DisplayUtils;
 import com.nextcloud.talk.utils.DoNotDisturbUtils;
+import com.nextcloud.talk.utils.NotificationUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.preferences.AppPreferences;
 
@@ -390,25 +388,7 @@ public class CallNotificationActivity extends CallBaseActivity {
     }
 
     private void playRingtoneSound() {
-        String callRingtonePreferenceString = appPreferences.getCallRingtoneUri();
-        Uri ringtoneUri;
-
-        if (TextUtils.isEmpty(callRingtonePreferenceString)) {
-            // play default sound
-            ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
-                                        "/raw/librem_by_feandesign_call");
-        } else {
-            try {
-                RingtoneSettings ringtoneSettings = LoganSquare.parse(
-                    callRingtonePreferenceString, RingtoneSettings.class);
-                ringtoneUri = ringtoneSettings.getRingtoneUri();
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to parse ringtone settings");
-                ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
-                                            "/raw/librem_by_feandesign_call");
-            }
-        }
-
+        Uri ringtoneUri = NotificationUtils.INSTANCE.getCallRingtoneUri(getApplicationContext(), appPreferences);
         if (ringtoneUri != null) {
             mediaPlayer = new MediaPlayer();
             try {

+ 3 - 0
app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt

@@ -58,6 +58,7 @@ import com.nextcloud.talk.jobs.SignalingSettingsWorker
 import com.nextcloud.talk.utils.ClosedInterfaceImpl
 import com.nextcloud.talk.utils.DeviceUtils
 import com.nextcloud.talk.utils.DisplayUtils
+import com.nextcloud.talk.utils.NotificationUtils
 import com.nextcloud.talk.utils.OkHttpNetworkFetcherWithCache
 import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule
 import com.nextcloud.talk.utils.database.user.UserModule
@@ -188,6 +189,8 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
         val emojiCompat = EmojiCompat.init(config)
 
         EmojiManager.install(GoogleCompatEmojiProvider(emojiCompat))
+
+        NotificationUtils.registerNotificationChannels(applicationContext, appPreferences)
     }
 
     override fun onTerminate() {

+ 3 - 5
app/src/main/java/com/nextcloud/talk/controllers/RingtoneSelectionController.java

@@ -45,6 +45,7 @@ import com.nextcloud.talk.adapters.items.NotificationSoundItem;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.models.RingtoneSettings;
+import com.nextcloud.talk.utils.NotificationUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.preferences.AppPreferences;
 import eu.davidea.flexibleadapter.FlexibleAdapter;
@@ -180,13 +181,10 @@ public class RingtoneSelectionController extends BaseController implements Flexi
 
     private String getRingtoneString() {
         if (callNotificationSounds) {
-            return ("android.resource://" + context.getPackageName() +
-                    "/raw/librem_by_feandesign_call");
+            return NotificationUtils.INSTANCE.getDEFAULT_CALL_RINGTONE_URI();
         } else {
-            return ("android.resource://" + context.getPackageName() + "/raw" +
-                    "/librem_by_feandesign_message");
+            return NotificationUtils.INSTANCE.getDEFAULT_MESSAGE_RINGTONE_URI();
         }
-
     }
 
     private void fetchNotificationSounds() {

+ 60 - 41
app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java

@@ -33,9 +33,12 @@ import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.security.KeyChain;
 import android.text.Editable;
 import android.text.InputType;
@@ -59,7 +62,6 @@ import com.bluelinelabs.conductor.Controller;
 import com.bluelinelabs.conductor.RouterTransaction;
 import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
 import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
-import com.bluelinelabs.logansquare.LoganSquare;
 import com.facebook.drawee.view.SimpleDraweeView;
 import com.google.android.material.card.MaterialCardView;
 import com.google.android.material.textfield.TextInputLayout;
@@ -70,7 +72,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.jobs.AccountRemovalWorker;
 import com.nextcloud.talk.jobs.ContactAddressBookWorker;
-import com.nextcloud.talk.models.RingtoneSettings;
 import com.nextcloud.talk.models.database.CapabilitiesUtil;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.generic.GenericOverall;
@@ -78,6 +79,7 @@ import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.DisplayUtils;
 import com.nextcloud.talk.utils.LoggingUtils;
+import com.nextcloud.talk.utils.NotificationUtils;
 import com.nextcloud.talk.utils.SecurityUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.database.user.UserUtils;
@@ -95,7 +97,6 @@ import com.yarolegovich.mp.MaterialSwitchPreference;
 
 import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener;
 
-import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
@@ -155,6 +156,8 @@ public class SettingsController extends BaseController {
     TextView serverAgeTextView;
     @BindView(R.id.server_age_warning_icon)
     ImageView serverAgeIcon;
+    @BindView(R.id.settings_notifications_category)
+    MaterialPreferenceCategory notificationsCategory;
     @BindView(R.id.settings_call_sound)
     MaterialStandardPreference settingsCallSound;
     @BindView(R.id.settings_message_sound)
@@ -293,21 +296,43 @@ public class SettingsController extends BaseController {
 
         versionInfo.setSummary("v" + BuildConfig.VERSION_NAME);
 
-        settingsCallSound.setOnClickListener(v -> {
-            Bundle bundle = new Bundle();
-            bundle.putBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), true);
-            getRouter().pushController(RouterTransaction.with(new RingtoneSelectionController(bundle))
-                    .pushChangeHandler(new HorizontalChangeHandler())
-                    .popChangeHandler(new HorizontalChangeHandler()));
-        });
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 
-        settingsMessageSound.setOnClickListener(v -> {
-            Bundle bundle = new Bundle();
-            bundle.putBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), false);
-            getRouter().pushController(RouterTransaction.with(new RingtoneSelectionController(bundle))
-                    .pushChangeHandler(new HorizontalChangeHandler())
-                    .popChangeHandler(new HorizontalChangeHandler()));
-        });
+            settingsCallSound.setOnClickListener(v -> {
+                Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
+                intent.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID);
+                intent.putExtra(Settings.EXTRA_CHANNEL_ID,
+                                NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_CALLS_V4());
+                startActivity(intent);
+            });
+
+            settingsMessageSound.setOnClickListener(v -> {
+                Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
+                intent.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID);
+                intent.putExtra(Settings.EXTRA_CHANNEL_ID,
+                                NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_MESSAGES_V3());
+                startActivity(intent);
+            });
+
+        } else {
+
+            settingsCallSound.setOnClickListener(v -> {
+                Bundle bundle = new Bundle();
+                bundle.putBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), true);
+                getRouter().pushController(RouterTransaction.with(new RingtoneSelectionController(bundle))
+                                               .pushChangeHandler(new HorizontalChangeHandler())
+                                               .popChangeHandler(new HorizontalChangeHandler()));
+            });
+
+            settingsMessageSound.setOnClickListener(v -> {
+                Bundle bundle = new Bundle();
+                bundle.putBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), false);
+                getRouter().pushController(RouterTransaction.with(new RingtoneSelectionController(bundle))
+                                               .pushChangeHandler(new HorizontalChangeHandler())
+                                               .popChangeHandler(new HorizontalChangeHandler()));
+            });
+
+        }
 
         if (CapabilitiesUtil.isPhoneBookIntegrationAvailable(userUtils.getCurrentUser())) {
             phoneBookIntegrationPreference.setVisibility(View.VISIBLE);
@@ -417,6 +442,18 @@ public class SettingsController extends BaseController {
         }
     }
 
+    private String getRingtoneName(Context context, Uri ringtoneUri) {
+        if (ringtoneUri == null) {
+            return getResources().getString(R.string.nc_settings_no_ringtone);
+        } else if (ringtoneUri.toString().equals(NotificationUtils.INSTANCE.getDEFAULT_CALL_RINGTONE_URI()) ||
+            ringtoneUri.toString().equals(NotificationUtils.INSTANCE.getDEFAULT_MESSAGE_RINGTONE_URI())) {
+            return getResources().getString(R.string.nc_settings_default_ringtone);
+        } else  {
+            Ringtone r = RingtoneManager.getRingtone(context, ringtoneUri);
+            return r.getTitle(context);
+        }
+    }
+
     @Override
     protected void onAttach(@NonNull View view) {
         super.onAttach(view);
@@ -479,33 +516,15 @@ public class SettingsController extends BaseController {
             }
         }
 
-        String ringtoneName = "";
-        RingtoneSettings ringtoneSettings;
-        if (!TextUtils.isEmpty(appPreferences.getCallRingtoneUri())) {
-            try {
-                ringtoneSettings = LoganSquare.parse(appPreferences.getCallRingtoneUri(), RingtoneSettings.class);
-                ringtoneName = ringtoneSettings.getRingtoneName();
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to parse ringtone name");
-            }
-            settingsCallSound.setSummary(ringtoneName);
-        } else {
-            settingsCallSound.setSummary(R.string.nc_settings_default_ringtone);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            notificationsCategory.setTitle(getResources().getString(R.string.nc_settings_notification_sounds_post_oreo));
         }
 
-        ringtoneName = "";
+        Uri callRingtoneUri = NotificationUtils.INSTANCE.getCallRingtoneUri(view.getContext(), appPreferences);
+        settingsCallSound.setSummary(getRingtoneName(view.getContext(), callRingtoneUri));
 
-        if (!TextUtils.isEmpty(appPreferences.getMessageRingtoneUri())) {
-            try {
-                ringtoneSettings = LoganSquare.parse(appPreferences.getMessageRingtoneUri(), RingtoneSettings.class);
-                ringtoneName = ringtoneSettings.getRingtoneName();
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to parse ringtone name");
-            }
-            settingsMessageSound.setSummary(ringtoneName);
-        } else {
-            settingsMessageSound.setSummary(R.string.nc_settings_default_ringtone);
-        }
+        Uri messageRingtoneUri = NotificationUtils.INSTANCE.getMessageRingtoneUri(view.getContext(), appPreferences);
+        settingsMessageSound.setSummary(getRingtoneName(view.getContext(), messageRingtoneUri));
 
         if ("No proxy".equals(appPreferences.getProxyType()) || appPreferences.getProxyType() == null) {
             hideProxySettings();

+ 7 - 62
app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java

@@ -21,7 +21,6 @@
 package com.nextcloud.talk.jobs;
 
 import android.app.Notification;
-import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -52,7 +51,6 @@ import com.nextcloud.talk.activities.CallActivity;
 import com.nextcloud.talk.activities.MainActivity;
 import com.nextcloud.talk.api.NcApi;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
-import com.nextcloud.talk.models.RingtoneSettings;
 import com.nextcloud.talk.models.SignatureVerification;
 import com.nextcloud.talk.models.database.ArbitraryStorageEntity;
 import com.nextcloud.talk.models.database.UserEntity;
@@ -333,51 +331,9 @@ public class NotificationWorker extends Worker {
         notificationBuilder.setExtras(notificationInfo);
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-
-            /*NotificationUtils.createNotificationChannelGroup(context,
-                    Long.toString(crc32.getValue()),
-                    groupName);*/
-
             if (CHAT.equals(decryptedPushMessage.getType()) || ROOM.equals(decryptedPushMessage.getType())) {
-                AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder().setContentType
-                        (AudioAttributes.CONTENT_TYPE_SONIFICATION);
-                audioAttributesBuilder.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT);
-
-                String ringtonePreferencesString;
-                Uri soundUri;
-
-                ringtonePreferencesString = appPreferences.getMessageRingtoneUri();
-                if (TextUtils.isEmpty(ringtonePreferencesString)) {
-                    soundUri = Uri.parse("android.resource://" + context.getPackageName() +
-                            "/raw/librem_by_feandesign_message");
-                } else {
-                    try {
-                        RingtoneSettings ringtoneSettings = LoganSquare.parse
-                                (ringtonePreferencesString, RingtoneSettings.class);
-                        soundUri = ringtoneSettings.getRingtoneUri();
-                    } catch (IOException exception) {
-                        soundUri = Uri.parse("android.resource://" + context.getPackageName() +
-                                "/raw/librem_by_feandesign_message");
-                    }
-                }
-
-                NotificationUtils.INSTANCE.createNotificationChannel(context,
-                        NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_MESSAGES_V3(), context.getResources()
-                                .getString(R.string.nc_notification_channel_messages), context.getResources()
-                                .getString(R.string.nc_notification_channel_messages), true,
-                        NotificationManager.IMPORTANCE_HIGH, soundUri, audioAttributesBuilder.build(), null, false);
-
                 notificationBuilder.setChannelId(NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_MESSAGES_V3());
-            } else {
-                /*NotificationUtils.INSTANCE.createNotificationChannel(context,
-                        NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_CALLS_V3(), context.getResources()
-                                .getString(R.string.nc_notification_channel_calls), context.getResources()
-                                .getString(R.string.nc_notification_channel_calls_description), true,
-                        NotificationManager.IMPORTANCE_HIGH);
-
-                notificationBuilder.setChannelId(NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_CALLS_V3());*/
             }
-
         } else {
             // red color for the lights
             notificationBuilder.setLights(0xFFFF0000, 200, 200);
@@ -491,26 +447,15 @@ public class NotificationWorker extends Worker {
         NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
         notificationManager.notify(notificationId, notification);
 
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            // On devices with Android 8.0 (Oreo) or later, notification sound will be handled by the system
+            // if notifications have not been disabled by the user.
+            return;
+        }
 
         if (!notification.category.equals(Notification.CATEGORY_CALL) || !muteCall) {
-            String ringtonePreferencesString;
-            Uri soundUri;
-
-            ringtonePreferencesString = appPreferences.getMessageRingtoneUri();
-            if (TextUtils.isEmpty(ringtonePreferencesString)) {
-                soundUri = Uri.parse("android.resource://" + context.getPackageName() +
-                        "/raw/librem_by_feandesign_message");
-            } else {
-                try {
-                    RingtoneSettings ringtoneSettings = LoganSquare.parse
-                            (ringtonePreferencesString, RingtoneSettings.class);
-                    soundUri = ringtoneSettings.getRingtoneUri();
-                } catch (IOException exception) {
-                    soundUri = Uri.parse("android.resource://" + context.getPackageName() +
-                            "/raw/librem_by_feandesign_message");
-                }
-            }
-
+            Uri soundUri = NotificationUtils.INSTANCE.getMessageRingtoneUri(getApplicationContext(),
+                                                                            appPreferences);
             if (soundUri != null && !ApplicationWideCurrentRoomHolder.getInstance().isInCall() &&
                     (DoNotDisturbUtils.INSTANCE.shouldPlaySound() || importantConversation)) {
                 AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder().setContentType

+ 120 - 54
app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.kt

@@ -23,64 +23,44 @@ package com.nextcloud.talk.utils
 import android.annotation.TargetApi
 import android.app.Notification
 import android.app.NotificationChannel
-import android.app.NotificationChannelGroup
 import android.app.NotificationManager
 import android.content.Context
 import android.media.AudioAttributes
 import android.net.Uri
 import android.os.Build
 import android.service.notification.StatusBarNotification
+import android.text.TextUtils
+import com.bluelinelabs.logansquare.LoganSquare
+import com.nextcloud.talk.BuildConfig
 import com.nextcloud.talk.R
+import com.nextcloud.talk.models.RingtoneSettings
 import com.nextcloud.talk.models.database.UserEntity
 import com.nextcloud.talk.utils.bundle.BundleKeys
-import java.util.Objects
+import com.nextcloud.talk.utils.preferences.AppPreferences
+import java.io.IOException
 
 object NotificationUtils {
-    val NOTIFICATION_CHANNEL_CALLS = "NOTIFICATION_CHANNEL_CALLS"
     val NOTIFICATION_CHANNEL_MESSAGES = "NOTIFICATION_CHANNEL_MESSAGES"
-    val NOTIFICATION_CHANNEL_CALLS_V2 = "NOTIFICATION_CHANNEL_CALLS_V2"
     val NOTIFICATION_CHANNEL_MESSAGES_V2 = "NOTIFICATION_CHANNEL_MESSAGES_V2"
     val NOTIFICATION_CHANNEL_MESSAGES_V3 = "NOTIFICATION_CHANNEL_MESSAGES_V3"
+    val NOTIFICATION_CHANNEL_CALLS = "NOTIFICATION_CHANNEL_CALLS"
+    val NOTIFICATION_CHANNEL_CALLS_V2 = "NOTIFICATION_CHANNEL_CALLS_V2"
     val NOTIFICATION_CHANNEL_CALLS_V3 = "NOTIFICATION_CHANNEL_CALLS_V3"
+    val NOTIFICATION_CHANNEL_CALLS_V4 = "NOTIFICATION_CHANNEL_CALLS_V4"
 
-    fun getVibrationEffectForCalls(): LongArray {
-        return longArrayOf(0L, 400L, 800L, 600L, 800L, 800L, 800L, 1000L)
-    }
-
-    fun getNotificationChannelId(
-        channelName: String,
-        channelDescription: String,
-        enableLights: Boolean,
-        importance: Int,
-        sound: Uri,
-        audioAttributes: AudioAttributes,
-        vibrationPattern: LongArray?,
-        bypassDnd: Boolean
-    ): String {
-        return Objects.hash(
-            channelName,
-            channelDescription,
-            enableLights,
-            importance,
-            sound,
-            audioAttributes,
-            vibrationPattern,
-            bypassDnd
-        ).toString()
-    }
+    val DEFAULT_CALL_RINGTONE_URI =
+        "android.resource://" + BuildConfig.APPLICATION_ID + "/raw/librem_by_feandesign_call"
+    val DEFAULT_MESSAGE_RINGTONE_URI =
+        "android.resource://" + BuildConfig.APPLICATION_ID + "/raw/librem_by_feandesign_message"
 
     @TargetApi(Build.VERSION_CODES.O)
-    fun createNotificationChannel(
+    private fun createNotificationChannel(
         context: Context,
         channelId: String,
         channelName: String,
         channelDescription: String,
-        enableLights: Boolean,
-        importance: Int,
         sound: Uri,
-        audioAttributes: AudioAttributes,
-        vibrationPattern: LongArray?,
-        bypassDnd: Boolean = false
+        audioAttributes: AudioAttributes
     ) {
 
         val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@@ -89,42 +69,81 @@ object NotificationUtils {
             Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
             notificationManager.getNotificationChannel(channelId) == null
         ) {
-
             val channel = NotificationChannel(
                 channelId, channelName,
-                importance
+                NotificationManager.IMPORTANCE_HIGH
             )
 
             channel.description = channelDescription
-            channel.enableLights(enableLights)
+            channel.enableLights(true)
             channel.lightColor = R.color.colorPrimary
             channel.setSound(sound, audioAttributes)
-            if (vibrationPattern != null) {
-                channel.enableVibration(true)
-                channel.vibrationPattern = vibrationPattern
-            } else {
-                channel.enableVibration(false)
-            }
-            channel.setBypassDnd(bypassDnd)
+            channel.setBypassDnd(false)
 
             notificationManager.createNotificationChannel(channel)
         }
     }
 
-    @TargetApi(Build.VERSION_CODES.O)
-    fun createNotificationChannelGroup(
+    private fun createCallsNotificationChannel(
+        context: Context,
+        appPreferences: AppPreferences
+    ) {
+        val audioAttributes =
+            AudioAttributes.Builder()
+                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST)
+                .build()
+        val soundUri = getCallRingtoneUri(context, appPreferences)
+
+        createNotificationChannel(
+            context,
+            NOTIFICATION_CHANNEL_CALLS_V4,
+            context.resources.getString(R.string.nc_notification_channel_calls),
+            context.resources.getString(R.string.nc_notification_channel_calls_description),
+            soundUri,
+            audioAttributes
+        )
+    }
+
+    private fun createMessagesNotificationChannel(
+        context: Context,
+        appPreferences: AppPreferences
+    ) {
+        val audioAttributes =
+            AudioAttributes.Builder()
+                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
+                .build()
+        val soundUri = getMessageRingtoneUri(context, appPreferences)
+
+        createNotificationChannel(
+            context,
+            NOTIFICATION_CHANNEL_MESSAGES_V3,
+            context.resources.getString(R.string.nc_notification_channel_messages),
+            context.resources.getString(R.string.nc_notification_channel_messages_description),
+            soundUri,
+            audioAttributes
+        )
+    }
+
+    fun registerNotificationChannels(
         context: Context,
-        groupId: String,
-        groupName: CharSequence
+        appPreferences: AppPreferences
     ) {
+        createCallsNotificationChannel(context, appPreferences)
+        createMessagesNotificationChannel(context, appPreferences)
+    }
+
+    @TargetApi(Build.VERSION_CODES.O)
+    private fun getNotificationChannel(
+        context: Context,
+        channelId: String
+    ): NotificationChannel? {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
-
-            val notificationChannelGroup = NotificationChannelGroup(groupId, groupName)
-            if (!notificationManager.notificationChannelGroups.contains(notificationChannelGroup)) {
-                notificationManager.createNotificationChannelGroup(notificationChannelGroup)
-            }
+            return notificationManager.getNotificationChannel(channelId)
         }
+        return null
     }
 
     fun cancelAllNotificationsForAccount(context: Context?, conversationUser: UserEntity) {
@@ -228,4 +247,51 @@ object NotificationUtils {
             }
         }
     }
+
+    private fun getRingtoneUri(
+        context: Context,
+        ringtonePreferencesString: String?,
+        defaultRingtoneUri: String,
+        channelId: String
+    ): Uri {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            val channel = getNotificationChannel(context, channelId)
+            if (channel != null) {
+                return channel.sound
+            }
+            // Notification channel will not be available when starting the application for the first time.
+            // Ringtone uris are required to register the notification channels -> get uri from preferences.
+        }
+        if (TextUtils.isEmpty(ringtonePreferencesString)) {
+            return Uri.parse(defaultRingtoneUri)
+        } else {
+            try {
+                val ringtoneSettings =
+                    LoganSquare.parse(ringtonePreferencesString, RingtoneSettings::class.java)
+                return ringtoneSettings.ringtoneUri!!
+            } catch (exception: IOException) {
+                return Uri.parse(defaultRingtoneUri)
+            }
+        }
+    }
+
+    fun getCallRingtoneUri(
+        context: Context,
+        appPreferences: AppPreferences
+    ): Uri {
+        return getRingtoneUri(
+            context,
+            appPreferences.callRingtoneUri, DEFAULT_CALL_RINGTONE_URI, NOTIFICATION_CHANNEL_CALLS_V4
+        )
+    }
+
+    fun getMessageRingtoneUri(
+        context: Context,
+        appPreferences: AppPreferences
+    ): Uri {
+        return getRingtoneUri(
+            context,
+            appPreferences.messageRingtoneUri, DEFAULT_MESSAGE_RINGTONE_URI, NOTIFICATION_CHANNEL_MESSAGES_V3
+        )
+    }
 }

+ 1 - 0
app/src/main/res/layout/controller_settings.xml

@@ -161,6 +161,7 @@
     </com.yarolegovich.mp.MaterialPreferenceCategory>
 
     <com.yarolegovich.mp.MaterialPreferenceCategory
+        android:id="@+id/settings_notifications_category"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:animateLayoutChanges="true"

+ 7 - 5
app/src/main/res/values/strings.xml

@@ -94,10 +94,11 @@
     <string name="nc_settings_no_talk_installed">Talk app is not installed on the server you tried to authenticate against</string>
     <string name="nc_settings_account_updated">Your already existing account was updated, instead of adding a new one</string>
     <string name="nc_account_scheduled_for_deletion">The account is scheduled for deletion, and cannot be changed</string>
-    <string name="nc_settings_notification_sounds">Sound</string>
+    <string name="nc_settings_notification_sounds">Notification sounds</string>
+    <string name="nc_settings_notification_sounds_post_oreo">Notifications</string>
     <string name="nc_settings_call_ringtone">Calls</string>
     <string name="nc_settings_call_ringtone_key" translatable="false">call_ringtone</string>
-    <string name="nc_settings_other_notifications_ringtone">Notifications</string>
+    <string name="nc_settings_other_notifications_ringtone">Messages</string>
     <string name="nc_settings_message_ringtone_key" translatable="false">message_ringtone</string>
     <string name="nc_settings_default_ringtone" translatable="false">Librem by feandesign</string>
     <string name="nc_settings_no_ringtone">No sound</string>
@@ -227,9 +228,10 @@
 
     <!-- Notification channels -->
     <string name="nc_notification_channel">%1$s on %2$s notification channel</string>
-    <string name="nc_notification_channel_calls">Calls notification channel</string>
-    <string name="nc_notification_channel_messages">Messages notification channel</string>
-    <string name="nc_notification_channel_calls_description">Shows incoming calls</string>
+    <string name="nc_notification_channel_calls">Calls</string>
+    <string name="nc_notification_channel_messages">Messages</string>
+    <string name="nc_notification_channel_calls_description">Notify about incoming calls</string>
+    <string name="nc_notification_channel_messages_description">Notify about incoming messages</string>
     <string name="nc_notification_settings">Notification settings</string>
     <string name="nc_plain_old_messages">Messages</string>
     <string name="nc_notify_me_always">Always notify</string>