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.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

View File

@ -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");

View File

@ -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 {

View File

@ -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() {

View File

@ -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() {

View File

@ -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,6 +296,26 @@ public class SettingsController extends BaseController {
versionInfo.setSummary("v" + BuildConfig.VERSION_NAME);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
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);
@ -309,6 +332,8 @@ public class SettingsController extends BaseController {
.popChangeHandler(new HorizontalChangeHandler()));
});
}
if (CapabilitiesUtil.isPhoneBookIntegrationAvailable(userUtils.getCurrentUser())) {
phoneBookIntegrationPreference.setVisibility(View.VISIBLE);
} else {
@ -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();

View File

@ -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

View File

@ -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,
groupId: String,
groupName: CharSequence
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,
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
)
}
}

View File

@ -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"

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_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>