因?yàn)楣綼pp的需求,需要加個(gè)自定義消息推送通知聲音痹栖,因?yàn)椴欢沧康脑灾氨豢撕芫貌t空,查了很多資料揪阿,終于搞定了,下面分享iOS和Android環(huán)境下的如何根據(jù)后臺傳過來的參數(shù)來指定播放app端的消息通知聲音咆畏。
開始之前南捂,需要先安裝三方庫jpush-react-native,這里我就不詳細(xì)說了旧找,按照文檔做就可以了溺健。
iOS端
由于自定義通知聲音還是由 iOS 系統(tǒng)來播放的,所以對音頻數(shù)據(jù)格式有限制钮蛛,可以是如下四種之一:
Linear PCM
MA4 (IMA/ADPCM)
μLaw
aLaw
對應(yīng)音頻文件格式是 aiff鞭缭,wav,caf 文件愿卒,文件也必須放到 app 的 mainBundle 目錄中缚去。
自定義通知聲音的播放時(shí)間必須在 30s 內(nèi),如果超過這個(gè)限制琼开,則將用系統(tǒng)默認(rèn)通知聲音替代易结。
可以使用 afconvert 工具來處理音頻文件格式,在終端中敲入如下命令就可以將一個(gè) mp3 文件轉(zhuǎn)換成 caf 文件:
$ afconvert test.mp3 test.caf -d ima4 -f caff -v
轉(zhuǎn)換完成后就可以將 test.caf 這個(gè)文件拖入 Xcode 工程中柜候,編譯運(yùn)行項(xiàng)目在真機(jī)上搞动。
發(fā)送推送通知時(shí),只需后臺配置 sound 字段的值為導(dǎo)入到工程中的音頻文件名渣刷,這里即就是 test.caf鹦肿。
如果要用系統(tǒng)自帶的聲音,必須傳'default',不然app端就沒有聲音了辅柴。
iOS的就搞定了箩溃,是不是很簡單瞭吃。這里其實(shí)用不著jpush-react-native庫,只要還是為了下面的安卓使用的涣旨。
Android端
安卓端的就稍微有點(diǎn)復(fù)雜了歪架,因?yàn)椴欢沧康脑颍宋也簧贂r(shí)間霹陡。
首先將聲音文件放在raw目錄下和蚪,沒有此目錄自己創(chuàng)建一個(gè)
注意,此時(shí)就用到了jpush-react-native庫了烹棉,文件要放在庫里攒霹,還有一點(diǎn)就是安卓自定義聲音只支持發(fā)送自定義消息,發(fā)送普通通知是不可以的浆洗。
然后到j(luò)push-react-native里的android/src/main/java/cn/jpush/reactnativejpush下找到JPushModule.java修改里面的代碼
找到接收自定義消息函數(shù)JPushReceiver催束,將里面的接收自定義函數(shù)代碼
public static class JPushReceiver extends BroadcastReceiver {
public JPushReceiver() {
}
@Override
public void onReceive(Context context, Intent data) {
mCachedBundle = data.getExtras();
if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(data.getAction())) {
try {
String message = data.getStringExtra(JPushInterface.EXTRA_MESSAGE);
Logger.i(TAG, "收到自定義消息: " + message);
if (mRAC != null) {
WritableMap map = Arguments.createMap();
map.putString("message", message);
map.putString("extras", data.getExtras().getString(JPushInterface.EXTRA_EXTRA));
mRAC.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(RECEIVE_CUSTOM_MESSAGE, map);
} else {
mEvent = RECEIVE_CUSTOM_MESSAGE;
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(data.getAction())) {
改成
public static class JPushReceiver extends BroadcastReceiver {
public JPushReceiver() {
}
@Override
public void onReceive(Context context, Intent data) {
mCachedBundle = data.getExtras();
if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(data.getAction())) {
processCustomMessage(context, mCachedBundle);
try {
String message = data.getStringExtra(JPushInterface.EXTRA_MESSAGE);
Logger.i(TAG, "收到自定義消息: " + message);
if (mRAC != null) {
WritableMap map = Arguments.createMap();
map.putString("message", message);
map.putString("extras", data.getExtras().getString(JPushInterface.EXTRA_EXTRA));
mRAC.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(RECEIVE_CUSTOM_MESSAGE, map);
} else {
mEvent = RECEIVE_CUSTOM_MESSAGE;
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(data.getAction())) {
其實(shí)就是多加了一行processCustomMessage(context, mCachedBundle);
然后在寫processCustomMessage函數(shù)
private void processCustomMessage(Context context, Bundle bundle) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notification = new NotificationCompat.Builder(context);
String message = bundle.getString(JPushInterface.EXTRA_MESSAGE);
String title = bundle.getString(JPushInterface.EXTRA_TITLE);
notification.setAutoCancel(true)
.setContentText(message)
.setContentTitle(title)
.setSmallIcon(R.mipmap.ic_launcher);
String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
if (!TextUtils.isEmpty(extras)) {
try {
JSONObject extraJson = new JSONObject(extras);
if (null != extraJson && extraJson.length() > 0) {
String sound = extraJson.getString("sound");
if("invite_price.mp3".equals(sound)){
notification.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" +R.raw.invite_price));
}else if("test.mp3".equals(sound)){
notification.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" +R.raw.test));
}else{
notification.setDefaults(1);
}
}
} catch (JSONException e) {
}
}
int timecurrentTimeMillis =(int)System.currentTimeMillis()/1000 ;
Intent intent = new Intent();
intent.setClass(context, JPushReceiver.class);
intent.setAction(JPushInterface.ACTION_NOTIFICATION_OPENED);
intent.putExtras(bundle);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, timecurrentTimeMillis, intent, PendingIntent.FLAG_ONE_SHOT);
notification.setContentIntent(pendingIntent);
notificationManager.notify(timecurrentTimeMillis, notification.build());
}
注意后臺傳給你的參數(shù)是在extras里的,里面的sound字段就對應(yīng)你本地的文件名辅髓,比如我這里的invite_price.mp3文件泣崩,sound即為'invite_price.mp3',如果想要使用系統(tǒng)默認(rèn)的,那就傳個(gè)不存在的文件名洛口,統(tǒng)一最好就用'default'吧矫付。timecurrentTimeMillis是通知唯一標(biāo)識符,如果不設(shè)置的話第焰,相當(dāng)于id一直沒變买优,這樣會(huì)導(dǎo)致新的通知會(huì)覆蓋舊的通知,通知列表永遠(yuǎn)只有1個(gè)挺举。最后如果提示有紅色的未定義的函數(shù)名杀赢,引入一下就好了。
int timecurrentTimeMillis =(int)System.currentTimeMillis()/1000 ;
Intent intent = new Intent();
intent.setClass(context, JPushReceiver.class);
intent.setAction(JPushInterface.ACTION_NOTIFICATION_OPENED);
intent.putExtras(bundle);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, timecurrentTimeMillis, intent, PendingIntent.FLAG_ONE_SHOT);
notification.setContentIntent(pendingIntent);
notificationManager.notify(timecurrentTimeMillis, notification.build());
這塊代碼的意思是點(diǎn)擊通知并且發(fā)送到廣播里湘纵,這樣在js里就可以通過JPushModule.addReceiveOpenNotificationListener()來監(jiān)聽到點(diǎn)擊通知的事件脂崔。
至此,iOS和Android的自定義通知聲音就OK啦梧喷。如果有哪里寫的不好的砌左,還望指正啊,不明白的也可以在下面留言铺敌,我看到就會(huì)回復(fù)的汇歹。或者加jpush-react-native官方群553406342