Android 您所在的位置:网站首页 安卓推送消息怎么关闭声音提示 Android

Android

2024-07-08 10:58| 来源: 网络整理| 查看: 265

最近接到一个需求,如题,给友盟推送添加定制化声音。 在这里插入图片描述 描述很简洁,由上图可知,本次需求的重点工作是8.0以上版本的兼容问题。友盟给出的示例代码如下: 在这里插入图片描述 由以上代码可知,其实就是设置一个自定义Notification,但是以上代码用在8.0以上系统中并不可行。原因大家应该都清楚了,8.0以上通知栏新增了一个NotificationChannel的特性,如果没有设置channel通知渠道的话,就会导致通知无法展示。

设置本地声音

现在再来回到我们本次需求的重点:定制声音。通过以上分析我们已经知道了友盟自定义声音其实就是自定义通知,那么定制声音也就是自定义通知的一部分,该怎么做呢?通过查找NotificationChannel的API可以找到setSound(Uri sound, AudioAttributes audioAttributes)方法。那么赶快上代码吧,我们先来设置一个本地声音吧:

//Android 8.0 以上需包添加渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager manager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); NotificationChannel notificationChannel = new NotificationChannel(newChannel, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH); Uri sound = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.ding); //只能在create一个渠道之前修改铃声,在创建之后不支持修改 notificationChannel.setSound(sound, Notification.AUDIO_ATTRIBUTES_DEFAULT); manager.createNotificationChannel(notificationChannel); }

注意: 这里要特别注意上述代码中的注释,只能在create一个渠道之前修改铃声,在创建之后不支持修改。 具体原因setSound方法的注释中已经给出了描述: 在这里插入图片描述

声音可配置

看到这里有人可能有疑问了,那我如果要想更改声音,让定制声音可配置,这怎么办呢???

既然一个NotificationChannel只能绑定一个声音,那我们可不可以再新建一个Channel来绑定新的声音呢?答案是可以的。由于之前的声音不再使用,所以我们需要删掉(deleteNotificationChannel(String channelId))之前的NotificationChannel,这里有个坑,你什么时候去删除呢?第一次测试我是在修改铃声或者振动的时候创建一个新的渠道,把之前所有旧的渠道都删除,但是这样会有一个bug,之前渠道上还在状态栏显示的Notification都会删除掉,所有要做一个判断,如果当前渠道在状态栏没有notification显示则删除,否则继续保存,代码如下:

注: 这里补充下,deleteNotificationChannel方法并不是真的删除了该渠道,只是设置了一个删除标记。具体的分析过程可以看下源码PreferencesHelper.deleteNotificationChannel()。

private static void deleteNoNumberNotification(NotificationManager nm, String newChannelId) { List notificationChannels = nm.getNotificationChannels(); if (Utils.isEmpty(notificationChannels) || notificationChannels.size() < 5) { return; } for (NotificationChannel channel : notificationChannels) { if (channel.getId() == null || channel.getId().equals(newChannelId)) { continue; } int notificationNumbers = getNotificationNumbers(nm, channel.getId()); Logger.i(TAG, "notificationNumbers: " + notificationNumbers + " channelId:" + channel.getId()); if (notificationNumbers == 0) { Log.i(TAG, "deleteNoNumberNotification: " + channel.getId()); nm.deleteNotificationChannel(channel.getId()); } } } /** * 获取某个渠道下状态栏上通知显示个数 * * @param mNotificationManager NotificationManager * @param channelId String * @return int */ @RequiresApi(api = Build.VERSION_CODES.O) private static int getNotificationNumbers(NotificationManager mNotificationManager, String channelId) { if (mNotificationManager == null || TextUtils.isEmpty(channelId)) { return -1; } int numbers = 0; StatusBarNotification[] activeNotifications = mNotificationManager.getActiveNotifications(); for (StatusBarNotification item : activeNotifications) { Notification notification = item.getNotification(); if (notification != null) { if (channelId.equals(notification.getChannelId())) { numbers++; } } } return numbers; }

以上就是定制本地声音的所有问题了,那么有人又有问题了,我如果想要配置一个网络音频,该如何设置呢???

设置网络音频

参考友盟SDK里面UmengMessageHandler的getSound方法: 在这里插入图片描述在这里插入图片描述 如果是网络音频的话,友盟先将音频文件下载到本地缓存目录,在进行设置的。

这里我一开始有个偷懒的想法,既然友盟已经为我们考虑的如此周全了,那我可不可以直接用这个getSound方法呢?通过试验,很遗憾,直接用友盟的方法声音并没有播放出来,这里留个大大的问号给大家,如果有哪位伙伴知道原因可以评论分享出来一起探讨。

既然直接用友盟的消息不可靠那就只有直接动手了,按照友盟提供的思路,将文件下载到本地,再进行设置吧。这里我下载的目录是getExternalCacheDir(),奇怪竟然可以播放( •̀ ω •́ )y。

通知音频播放的一点点分析

这里还要插播一条:在找不到友盟下载的文件为什么不能播放的时候,我还有个偷懒的想法直接将http音频地址设置给Uri,测试发现在小米手机上Https的地址竟然可以播放,Http的地址不可以播放。这里稍微说下吧,其实这并不是一个解决方案,甚至本来就是一个错误的做法。为什么呢?

通知声音的播放是在NotificationPlayer类中实现,看代码: 在这里插入图片描述 最终声音的播放还是由MediaPlayer来执行的。之前我们给Notification设置的Sound就是MediaPlayer的DataSource,如果是网络音频,然后被Uri包裹,那么播放器就认为这是一个本地文件,在解析的时候就会报找不到文件错误,很神奇,这里明明报错了,有些手机上你还是可以听到声音的播放。所以并不建议大家直接将Http地址塞给Sound。

由于上面提到的源码部分只是某个点,需要了解更多的同学,请打开源码详细对照理解哈。

本文源码如下:

public static String UMENG_INTERNET_SOUND_DOWNPATH = MyApplication.getInstance().getExternalCacheDir() + "/sound_cache"; //8.0版本以上自定义通知兼容 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mPushAgent.setMessageHandler(messageHandler); } //自定义消息进行处理 private static UmengMessageHandler messageHandler = new UmengMessageHandler() { @Override public void dealWithNotificationMessage(Context context, UMessage uMessage) { if (uMessage.hasResourceFromInternet() && !MessageSharedPrefs.getInstance(context).hasMessageResourceDownloaded(uMessage.msg_id)) { downInternetSound(context, uMessage); return; } super.dealWithNotificationMessage(context, uMessage); } @Override public Uri getSound(Context context, UMessage uMessage) { return getCustomSound(context, uMessage); } @Override public Notification getNotification(Context context, UMessage uMessage) { if (uMessage.builder_id == 1) { long curTime = System.currentTimeMillis(); String CHANNEL_ID = AppUtils.getAppName();//应用频道Id唯一值, 长度若太长可能会被截断, String newChannel = CHANNEL_ID + curTime; String CHANNEL_NAME = AppUtils.getAppName();//最长40个字符,太长会被截断 Uri sound = getSound(context, uMessage); Intent hangIntent = new Intent(context, MainActivity.class); PendingIntent hangPendingIntent = PendingIntent.getActivity(context, 1001, hangIntent, PendingIntent.FLAG_UPDATE_CURRENT); Notification notification = new NotificationCompat.Builder(context, newChannel) .setContentTitle(uMessage.title) .setContentText(uMessage.text) .setSmallIcon(R.mipmap.app_logo) .setContentIntent(hangPendingIntent) //.setFullScreenIntent(hangPendingIntent,true) .setSound(sound) .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.app_logo)) .setAutoCancel(true) .build(); //Android 5.0 以上锁屏通知 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { notification.visibility = Notification.VISIBILITY_PUBLIC; } //Android 8.0 以上需包添加渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); //只能在create一个渠道之前修改铃声,在创建之后不支持修改 //只能去重新创建一个渠道设置铃声振动 //对于之前创建的渠道,通过deleteNotificationChannel(String channelId)去删除 List channelList = manager.getNotificationChannels(); if (channelList != null && channelList.size() > 0) { for (NotificationChannel channel : channelList) { if (!TextUtils.isEmpty(channel.getId()) && channel.getId().startsWith(CHANNEL_ID)) { manager.deleteNotificationChannel(channel.getId()); } } } NotificationChannel notificationChannel = new NotificationChannel(newChannel, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH); //只能在create一个渠道之前修改铃声,在创建之后不支持修改 notificationChannel.setSound(sound, Notification.AUDIO_ATTRIBUTES_DEFAULT); manager.createNotificationChannel(notificationChannel); } Log.d("umeng", "notificationDefault: " + getNotificationDefaults(context, uMessage)); return notification; } //默认为0,若填写的builder_id并不存在,也使用默认。 return super.getNotification(context, uMessage); } }; /** * 自定义通知声音 * * @param context * @param uMessage * @return */ private static Uri getCustomSound(Context context, UMessage uMessage) { String soundPath = uMessage.sound; try { if (soundPath == null) { int assetsSound = com.umeng.message.common.d.a(context).j("umeng_push_notification_default_sound"); if (assetsSound > 0) { soundPath = "android.resource://" + context.getPackageName() + "/" + assetsSound; } } else { if (uMessage.isSoundFromInternet()) { soundPath = UMENG_INTERNET_SOUND_DOWNPATH + "/" + uMessage.sound.hashCode(); } else { int assetsSound = com.umeng.message.common.d.a(context).j(uMessage.sound); if (assetsSound > 0) { soundPath = "android.resource://" + context.getPackageName() + "/" + assetsSound; } } } if (soundPath != null) { Uri soundUri = Uri.parse(soundPath); return soundUri; } } catch (Throwable throwable) { throwable.toString(); } return null; } private static void downInternetSound(Context context, UMessage uMessage) { String downPath = UMENG_INTERNET_SOUND_DOWNPATH; String downFileName = uMessage.sound.hashCode() + ""; OkGoRequest.downLoad(context, uMessage.sound, new FileCallback(downPath, downFileName) { @Override public void onSuccess(Response response) { MessageSharedPrefs.getInstance(context).setMessageResourceDownloaded(uMessage.msg_id); messageHandler.dealWithNotificationMessage(context, uMessage); } @Override public void onError(Response response) { super.onError(response); MessageSharedPrefs.getInstance(context).setMessageResourceDownloaded(uMessage.msg_id); messageHandler.dealWithNotificationMessage(context, uMessage); } }); }

代码仅提供思路,具体实现自己写完整代码哈。

补充:

最近又遇到说Android11上面有手机自定义声音不发声的,打开系统配置里面铃声配置,发现通知铃声为无,就挺诡异的。有同事提出仿QQ,微信的自定义铃声方案,自己去用MediaPlayer来播放音乐,这也是一种解决方案吧,遇到此问题的同学可以一试。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有