項目源碼:lzan13 / VMChatDemoCall
前言
集成聊天靠胜,目的無非就是為了讓兩個人能夠方便的溝通脖祈,但是有時我們會退到后臺由境,kill 程序颠锉,這時候別人再發(fā)送消息就收不到了,以及有些用戶還想在呼叫通話時也能通知對方额衙,打開 app 接聽通話饮焦,這些都因為 app 被殺死而實現(xiàn)不了;還好有推送服務(wù)可用窍侧,蘋果有apns
县踢,雖然Android
有gcm
, 但是在國內(nèi)也用不了疏之,因此就催生了各種各樣的第三方推送殿雪,環(huán)信這邊根據(jù)市場設(shè)備情況,選擇了兩家推送集成锋爪,在國內(nèi)可以集成小米和華為推送,這樣可以保證在他們自家的設(shè)備上實現(xiàn)離線消息通知爸业;
PS:為什么不用極光其骄,因為極光并不是國內(nèi)那些 rom 廠商自家的推送服務(wù),他們不允許第三方的服務(wù)器在自家設(shè)備的后臺撒歡
PS:經(jīng)測試小米的多報名在推送上不好使扯旷,不知道現(xiàn)在怎么樣拯爽,如果有使用多包名測試不行的情況,可以重新創(chuàng)建應(yīng)用試下
廢話不多說钧忽,今天就通過集成最新的小米推送來實現(xiàn)下消息的離線推送通知毯炮,以及被呼叫方離線時方推送提醒對方啟動 app 接聽通話;其實都是通過集成推送完成耸黑!
準(zhǔn)備工作
首先你的項目需要集成環(huán)信 sdk桃煎,并且已經(jīng)實現(xiàn)了發(fā)送消息以及音視頻通話功能(這個可以直接用我上邊 github 上的項目);
然后你需要有小米的開發(fā)者賬戶大刊,需要創(chuàng)建一個應(yīng)用为迈,包名要和你自己的項目一樣,然后需要用到的就是應(yīng)用的appId
、appKey
葫辐、appSecret
搜锰,這些在環(huán)信開發(fā)者后臺上傳小米證書,以及在項目中初始化小米推送需要用到耿战;
開始集成
首先這邊先把證書弄好了蛋叼,證書的名字和秘鑰以及包名一定要對應(yīng):
然后需要做的就是在代碼中集成小米推送,需要做的有兩個地方:
- 在初始化 sdk 的時候調(diào)用 options 設(shè)置小米的 appId 和 appKey
- 在 AndroidManifest配置文件配置相應(yīng)的權(quán)限和廣播接收器以及服務(wù)
/**
* 初始化環(huán)信sdk剂陡,并做一些注冊監(jiān)聽的操作鸦列,這里把其他的處理都去掉了只寫了小米推送
*/
private void initHyphenate() {
// 初始化sdk的一些配置
EMOptions options = new EMOptions();
// 設(shè)置小米推送 appID 和 appKey
options.setMipushConfig("2882303761517573806", "5981757315806");
// 初始化環(huán)信SDK,一定要先調(diào)用init()
EMClient.getInstance().init(context, options);
// 開啟 debug 模式
EMClient.getInstance().setDebugMode(true);
}
然后就是AndroidManifest
配置
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.vmloft.develop.app.demo.call">
<!-- 項目權(quán)限配置 -->
<!--小米推送相關(guān)權(quán)限-->
<permission
android:name="com.vmloft.develop.app.demo.call.permission.MIPUSH_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.vmloft.develop.app.demo.call.permission.MIPUSH_RECEIVE"/>
<!--小米推送權(quán)限 end-->
<!--程序入口-->
<application
android:name="com.vmloft.develop.app.demo.call.AppApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<!--小米推送相關(guān)配置-->
<service
android:name="com.xiaomi.push.service.XMJobService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"
android:process=":pushservice"/>
<service
android:name="com.xiaomi.push.service.XMPushService"
android:enabled="true"
android:process=":pushservice"/>
<service
android:name="com.xiaomi.mipush.sdk.PushMessageHandler"
android:enabled="true"
android:exported="true"/>
<service
android:name="com.xiaomi.mipush.sdk.MessageHandleService"
android:enabled="true"/>
<!--推送消息廣播接收器,這個廣播接收器必須繼承自環(huán)信實現(xiàn)的接收器-->
<receiver
android:name=".push.MIPushReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE"/>
</intent-filter>
<intent-filter>
<action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED"/>
</intent-filter>
<intent-filter>
<action android:name="com.xiaomi.mipush.ERROR"/>
</intent-filter>
</receiver>
<receiver
android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver
android:name="com.xiaomi.push.service.receivers.PingReceiver"
android:exported="false"
android:process=":pushservice">
<intent-filter>
<action android:name="com.xiaomi.push.PING_TIMER"/>
</intent-filter>
</receiver>
<!--小米推送配置 end-->
</application>
</manifest>
其中MIPushReceiver
這個廣播接收器可以不用自己實現(xiàn)鹏倘,如果自己實現(xiàn)薯嗤,必須繼承自環(huán)信 sdk 實現(xiàn)的廣播接收器EMMipushReceiver
實現(xiàn),也可以直接用(這里如果需要自己與自己的業(yè)務(wù)處理可以繼承環(huán)信實現(xiàn)的的這個廣播接收器纤泵,不然收不到離線推送骆姐,然后去處理自己的邏輯;詳細可以根據(jù)小米推送官方 sdk 文檔進行了解下)捏题;
當(dāng)我們做完這些之后在收到離線消息后就可以收到推送通知了玻褪,只不過這個推送通知我們不能自定義,因為這些都是服務(wù)器推什么我們接受什么公荧,這點比較坑带射!
通話的離線通知
上邊已經(jīng)實現(xiàn)了消息的離線通知,我們下邊就要做當(dāng)呼叫對方時循狰,對方卻不在線窟社,我們怎么通知對方打開 app 進行接聽呢?
曾經(jīng)集成過環(huán)信用戶應(yīng)該知道绪钥,在呼叫對方不在線后會馬上結(jié)束通話灿里,回調(diào)對方不在線,在新版3.2.2的 sdk 中新增設(shè)置音視頻參數(shù)及呼叫時對方離線是否發(fā)推送的接口程腹,在初始化的時候進行以下設(shè)置:
// 設(shè)置通話過程中對方如果離線是否發(fā)送離線推送通知匣吊,默認(rèn) false
EMClient.getInstance().callManager().getCallOptions().setIsSendPushIfOffline(true);
// 設(shè)置了這個之后就不會在通話狀態(tài)監(jiān)聽中回調(diào)對方不在線,需要實現(xiàn)另外一個回調(diào)
...
// 設(shè)置音頻通話推送提供者寸潦,在 onRemoteOffline()回調(diào)中給對方發(fā)送消息就行了
EMClient.getInstance().callManager().setPushProvider(EMCallManager.EMCallPushProvider {
@Override public void onRemoteOffline(String username) {
EMMessage message = EMMessage.createTxtSendMessage("有人呼叫你色鸳,開啟 APP 接聽吧", username);
// 設(shè)置強制推送
message.setAttribute("em_force_notification", "true");
// 設(shè)置自定義推送提示
JSONObject extObj = new JSONObject();
try {
extObj.put("em_push_title", "有人呼叫你,開啟 APP 接聽吧");
extObj.put("extern", "定義推送擴展內(nèi)容");
} catch (JSONException e) {
e.printStackTrace();
}
message.setAttribute("em_apns_ext", extObj);
message.setMessageStatusCallback(new EMCallBack() {
@Override public void onSuccess() {
// 在這里可以刪除消息
}
@Override public void onError(int i, String s) {
// 在這里可以刪除消息
}
@Override public void onProgress(int i, String s) {}
});
EMClient.getInstance().chatManager().sendMessage(message);
}
});
實現(xiàn)了上邊的這個推送提供者之后见转,當(dāng)對方不在線就會回調(diào) onRemoteOffline()方法命雀,就可以發(fā)送一條消息給對方,然后上邊我們已經(jīng)集成了小米推送池户,就可以通過離線推送的方式通知對方有新消息咏雌,對方看到后點擊通知欄就可以打開 app了凡怎,這個時候我們的語音或視頻呼叫還在一直呼叫,然后就可以連通了赊抖!
結(jié)語
OK 到這里基本就已經(jīng)完成了统倒,大家可以運行自己的項目,或者我上邊的 demo 測試下氛雪,我這邊通過小米5測試 OK房匆;其實集成推送部分并不難,只是有幾點需要注意:
- 環(huán)信開發(fā)者后臺的推送證書設(shè)置時一定要注意應(yīng)用包名和小米推送后臺的應(yīng)用包名以及自己項目的包名报亩,三個地方一定要一致
- 初始化設(shè)置一定要通過環(huán)信的 options 去設(shè)置小米推送的 appId 和 appKey浴鸿,不需要用小米的注冊方法自己注冊;
- Androidmanifest 一定要加上環(huán)信的廣播接收器弦追,或者繼承自環(huán)信封裝的廣播接收器
注意以上幾點基本推送就沒有問題了岳链,如果不行可以先通過小米開發(fā)者后臺的推送工具測試推送是否通了,然后檢查以上幾點劲件;
PS:華為推送相關(guān)其實一樣掸哑,不過因為華為不允許個人開發(fā)者注冊賬戶,所以這里暫時不贅述