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

Adapt notification code to Android 8.0 (Oreo) and later
This commit is contained in:
Marcel Hibbe 2021-12-15 16:24:24 +01:00 committed by GitHub
commit 1c1600c33a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 207 additions and 249 deletions

View File

@ -23,15 +23,12 @@ import android.annotation.SuppressLint
import android.app.Notification import android.app.Notification
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Intent import android.content.Intent
import android.media.AudioAttributes
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.text.TextUtils
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.emoji.text.EmojiCompat import androidx.emoji.text.EmojiCompat
import androidx.work.Data import androidx.work.Data
import androidx.work.OneTimeWorkRequest 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.events.CallNotificationClick
import com.nextcloud.talk.jobs.NotificationWorker import com.nextcloud.talk.jobs.NotificationWorker
import com.nextcloud.talk.jobs.PushRegistrationWorker import com.nextcloud.talk.jobs.PushRegistrationWorker
import com.nextcloud.talk.models.RingtoneSettings
import com.nextcloud.talk.models.SignatureVerification import com.nextcloud.talk.models.SignatureVerification
import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.models.json.participants.ParticipantsOverall 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
import com.nextcloud.talk.utils.NotificationUtils.cancelAllNotificationsForAccount import com.nextcloud.talk.utils.NotificationUtils.cancelAllNotificationsForAccount
import com.nextcloud.talk.utils.NotificationUtils.cancelExistingNotificationWithId 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.PushUtils
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FROM_NOTIFICATION_START_CALL 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.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import retrofit2.Retrofit import retrofit2.Retrofit
import java.io.IOException
import java.net.CookieManager import java.net.CookieManager
import java.security.InvalidKeyException import java.security.InvalidKeyException
import java.security.NoSuchAlgorithmException import java.security.NoSuchAlgorithmException
@ -202,58 +197,8 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
PendingIntent.FLAG_UPDATE_CURRENT PendingIntent.FLAG_UPDATE_CURRENT
) )
val audioAttributesBuilder = val soundUri = getCallRingtoneUri(applicationContext!!, appPreferences!!)
AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) val notificationChannelId = NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V4
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 uri = Uri.parse(signatureVerification!!.userEntity.baseUrl) val uri = Uri.parse(signatureVerification!!.userEntity.baseUrl)
val baseUrl = uri.host val baseUrl = uri.host

View File

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

View File

@ -32,11 +32,9 @@ import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import com.bluelinelabs.logansquare.LoganSquare;
import com.facebook.common.executors.UiThreadImmediateExecutorService; import com.facebook.common.executors.UiThreadImmediateExecutorService;
import com.facebook.common.references.CloseableReference; import com.facebook.common.references.CloseableReference;
import com.facebook.datasource.DataSource; 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.application.NextcloudTalkApplication;
import com.nextcloud.talk.databinding.CallNotificationActivityBinding; import com.nextcloud.talk.databinding.CallNotificationActivityBinding;
import com.nextcloud.talk.events.CallNotificationClick; 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.CapabilitiesUtil;
import com.nextcloud.talk.models.database.UserEntity; import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.conversations.Conversation; 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.ApiUtils;
import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.DisplayUtils;
import com.nextcloud.talk.utils.DoNotDisturbUtils; import com.nextcloud.talk.utils.DoNotDisturbUtils;
import com.nextcloud.talk.utils.NotificationUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys; import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.preferences.AppPreferences; import com.nextcloud.talk.utils.preferences.AppPreferences;
@ -390,25 +388,7 @@ public class CallNotificationActivity extends CallBaseActivity {
} }
private void playRingtoneSound() { private void playRingtoneSound() {
String callRingtonePreferenceString = appPreferences.getCallRingtoneUri(); Uri ringtoneUri = NotificationUtils.INSTANCE.getCallRingtoneUri(getApplicationContext(), appPreferences);
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");
}
}
if (ringtoneUri != null) { if (ringtoneUri != null) {
mediaPlayer = new MediaPlayer(); mediaPlayer = new MediaPlayer();
try { try {

View File

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

View File

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

View File

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

View File

@ -21,7 +21,6 @@
package com.nextcloud.talk.jobs; package com.nextcloud.talk.jobs;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -52,7 +51,6 @@ import com.nextcloud.talk.activities.CallActivity;
import com.nextcloud.talk.activities.MainActivity; import com.nextcloud.talk.activities.MainActivity;
import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.models.RingtoneSettings;
import com.nextcloud.talk.models.SignatureVerification; import com.nextcloud.talk.models.SignatureVerification;
import com.nextcloud.talk.models.database.ArbitraryStorageEntity; import com.nextcloud.talk.models.database.ArbitraryStorageEntity;
import com.nextcloud.talk.models.database.UserEntity; import com.nextcloud.talk.models.database.UserEntity;
@ -333,51 +331,9 @@ public class NotificationWorker extends Worker {
notificationBuilder.setExtras(notificationInfo); notificationBuilder.setExtras(notificationInfo);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 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())) { 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()); 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 { } else {
// red color for the lights // red color for the lights
notificationBuilder.setLights(0xFFFF0000, 200, 200); notificationBuilder.setLights(0xFFFF0000, 200, 200);
@ -491,26 +447,15 @@ public class NotificationWorker extends Worker {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(notificationId, notification); 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) { if (!notification.category.equals(Notification.CATEGORY_CALL) || !muteCall) {
String ringtonePreferencesString; Uri soundUri = NotificationUtils.INSTANCE.getMessageRingtoneUri(getApplicationContext(),
Uri soundUri; appPreferences);
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");
}
}
if (soundUri != null && !ApplicationWideCurrentRoomHolder.getInstance().isInCall() && if (soundUri != null && !ApplicationWideCurrentRoomHolder.getInstance().isInCall() &&
(DoNotDisturbUtils.INSTANCE.shouldPlaySound() || importantConversation)) { (DoNotDisturbUtils.INSTANCE.shouldPlaySound() || importantConversation)) {
AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder().setContentType AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder().setContentType

View File

@ -23,64 +23,44 @@ package com.nextcloud.talk.utils
import android.annotation.TargetApi import android.annotation.TargetApi
import android.app.Notification import android.app.Notification
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationChannelGroup
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.media.AudioAttributes import android.media.AudioAttributes
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.service.notification.StatusBarNotification 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.R
import com.nextcloud.talk.models.RingtoneSettings
import com.nextcloud.talk.models.database.UserEntity import com.nextcloud.talk.models.database.UserEntity
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import java.util.Objects import com.nextcloud.talk.utils.preferences.AppPreferences
import java.io.IOException
object NotificationUtils { object NotificationUtils {
val NOTIFICATION_CHANNEL_CALLS = "NOTIFICATION_CHANNEL_CALLS"
val NOTIFICATION_CHANNEL_MESSAGES = "NOTIFICATION_CHANNEL_MESSAGES" 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_V2 = "NOTIFICATION_CHANNEL_MESSAGES_V2"
val NOTIFICATION_CHANNEL_MESSAGES_V3 = "NOTIFICATION_CHANNEL_MESSAGES_V3" 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_V3 = "NOTIFICATION_CHANNEL_CALLS_V3"
val NOTIFICATION_CHANNEL_CALLS_V4 = "NOTIFICATION_CHANNEL_CALLS_V4"
fun getVibrationEffectForCalls(): LongArray { val DEFAULT_CALL_RINGTONE_URI =
return longArrayOf(0L, 400L, 800L, 600L, 800L, 800L, 800L, 1000L) "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"
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()
}
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
fun createNotificationChannel( private fun createNotificationChannel(
context: Context, context: Context,
channelId: String, channelId: String,
channelName: String, channelName: String,
channelDescription: String, channelDescription: String,
enableLights: Boolean,
importance: Int,
sound: Uri, sound: Uri,
audioAttributes: AudioAttributes, audioAttributes: AudioAttributes
vibrationPattern: LongArray?,
bypassDnd: Boolean = false
) { ) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@ -89,42 +69,81 @@ object NotificationUtils {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
notificationManager.getNotificationChannel(channelId) == null notificationManager.getNotificationChannel(channelId) == null
) { ) {
val channel = NotificationChannel( val channel = NotificationChannel(
channelId, channelName, channelId, channelName,
importance NotificationManager.IMPORTANCE_HIGH
) )
channel.description = channelDescription channel.description = channelDescription
channel.enableLights(enableLights) channel.enableLights(true)
channel.lightColor = R.color.colorPrimary channel.lightColor = R.color.colorPrimary
channel.setSound(sound, audioAttributes) channel.setSound(sound, audioAttributes)
if (vibrationPattern != null) { channel.setBypassDnd(false)
channel.enableVibration(true)
channel.vibrationPattern = vibrationPattern
} else {
channel.enableVibration(false)
}
channel.setBypassDnd(bypassDnd)
notificationManager.createNotificationChannel(channel) notificationManager.createNotificationChannel(channel)
} }
} }
@TargetApi(Build.VERSION_CODES.O) private fun createCallsNotificationChannel(
fun createNotificationChannelGroup(
context: Context, context: Context,
groupId: String, appPreferences: AppPreferences
groupName: CharSequence
) { ) {
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,
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) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
return notificationManager.getNotificationChannel(channelId)
val notificationChannelGroup = NotificationChannelGroup(groupId, groupName)
if (!notificationManager.notificationChannelGroups.contains(notificationChannelGroup)) {
notificationManager.createNotificationChannelGroup(notificationChannelGroup)
}
} }
return null
} }
fun cancelAllNotificationsForAccount(context: Context?, conversationUser: UserEntity) { 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
)
}
} }

View File

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

View File

@ -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_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_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_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">Calls</string>
<string name="nc_settings_call_ringtone_key" translatable="false">call_ringtone</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_message_ringtone_key" translatable="false">message_ringtone</string>
<string name="nc_settings_default_ringtone" translatable="false">Librem by feandesign</string> <string name="nc_settings_default_ringtone" translatable="false">Librem by feandesign</string>
<string name="nc_settings_no_ringtone">No sound</string> <string name="nc_settings_no_ringtone">No sound</string>
@ -227,9 +228,10 @@
<!-- Notification channels --> <!-- Notification channels -->
<string name="nc_notification_channel">%1$s on %2$s notification channel</string> <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_calls">Calls</string>
<string name="nc_notification_channel_messages">Messages notification channel</string> <string name="nc_notification_channel_messages">Messages</string>
<string name="nc_notification_channel_calls_description">Shows incoming calls</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_notification_settings">Notification settings</string>
<string name="nc_plain_old_messages">Messages</string> <string name="nc_plain_old_messages">Messages</string>
<string name="nc_notify_me_always">Always notify</string> <string name="nc_notify_me_always">Always notify</string>