初始化 SDK
在應(yīng)用的 Application 的 onCreate()
方法中做初始化操作定页,同時(shí)我們可以傳入一些設(shè)置好的 options。
@Override
public void onCreate() {
EMOptions options = initChatOptions();
//初始化
if(options == null){
EMClient.getInstance().init(this, initChatOptions());
} else{
EMClient.getInstance().init(this, options);
}
//在做打包混淆時(shí)酗电,關(guān)閉debug模式魄藕,避免消耗不必要的資源
EMClient.getInstance().setDebugMode(true);
}
private EMOptions initChatOptions(){
EMOptions options = new EMOptions();
// 默認(rèn)添加好友時(shí),是不需要驗(yàn)證的撵术,改成需要驗(yàn)證
options.setAcceptInvitationAlways(false);
// set if you need read ack
options.setRequireAck(true);
// set if you need delivery ack
options.setRequireDeliveryAck(false);
// 建議初始化SDK的時(shí)候設(shè)置成每個(gè)會(huì)話默認(rèn)load一條消息背率,節(jié)省加載會(huì)話的時(shí)間
options.setNumberOfMessagesLoaded(1);
//you need apply & set your own id if you want to use google cloud messaging.
options.setGCMNumber("324169311137");
//you need apply & set your own id if you want to use Mi push notification
options.setMipushConfig("2882303761517426801", "5381742660801");
}
需要注意的是,如果應(yīng)用中有其它第三方的服務(wù)啟動(dòng)嫩与,那么在初始化環(huán)信 SDK 之前需要添加下面相關(guān)的代碼來防止環(huán)信 SDK 被初始化 2 次寝姿。
appContext = this;
int pid = android.os.Process.myPid();
String processAppName = getAppName(pid);
// 如果APP啟用了遠(yuǎn)程的service,此application:onCreate會(huì)被調(diào)用2次
// 為了防止環(huán)信SDK被初始化2次划滋,加此判斷會(huì)保證SDK被初始化1次
// 默認(rèn)的APP會(huì)在以包名為默認(rèn)的process name下運(yùn)行饵筑,如果查到的process name不是APP的process name就立即返回
if (processAppName == null ||!processAppName.equalsIgnoreCase(appContext.getPackageName())) {
Log.e(TAG, "enter the service process!");
// 則此application::onCreate 是被service 調(diào)用的,直接返回
return;
}
...
private String getAppName(int pID) {
String processName = null;
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List l = am.getRunningAppProcesses();
Iterator i = l.iterator();
PackageManager pm = this.getPackageManager();
while (i.hasNext()) {
ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());
try {
if (info.pid == pID) {
processName = info.processName;
return processName;
}
} catch (Exception e) {
// Log.d("Process", "Error>> :"+ e.toString());
}
}
return processName;
}
注冊(cè)
注冊(cè)模式分兩種古毛,開放注冊(cè)(客戶端可以直接注冊(cè))和授權(quán)注冊(cè)翻翩。
- 開放注冊(cè)是為了測(cè)試使用,正式環(huán)境中不推薦使用該方式注冊(cè)環(huán)信賬號(hào)稻薇;
- 授權(quán)注冊(cè)的流程是客戶端填寫好注冊(cè)信息后點(diǎn)擊注冊(cè)按鈕嫂冻,注冊(cè)信息提交到應(yīng)用服務(wù)器,應(yīng)用服務(wù)器提供環(huán)信提供的 REST API 進(jìn)行注冊(cè)塞椎,注冊(cè)完成后應(yīng)用服務(wù)器進(jìn)行處理在返回給客戶端注冊(cè)結(jié)果桨仿。
登錄
調(diào)用異步方法 login()
完成登錄。需要注意的是在登錄成功后需要調(diào)用 EMClient.getInstance().chatManager().loadAllConversations();
和 EMClient.getInstance().groupManager().loadAllGroups();
這兩個(gè)方法是為了保證進(jìn)入主頁后本地會(huì)話和群組都 load 完畢案狠。
EMClient.getInstance().login(userName,password,new EMCallBack() {//回調(diào)
@Override
public void onSuccess() {
EMClient.getInstance().groupManager().loadAllGroups();
EMClient.getInstance().chatManager().loadAllConversations();
Log.d("main", "登錄聊天服務(wù)器成功服傍!");
}
@Override
public void onProgress(int progress, String status) {
}
@Override
public void onError(int code, String message) {
Log.d("main", "登錄聊天服務(wù)器失敗骂铁!");
}
});
另外如果登錄過吹零,我們需要在應(yīng)用的歡迎界面中還要加入上面兩個(gè)方法來保證進(jìn)入主頁后本地會(huì)話和群組都 load 完畢。
在 SplashActivity 類中
if(isLoggedIn()) {
EMClient.getInstance().chatManager().loadAllConversations();
EMClient.getInstance().groupManager().loadAllGroups();
...
startActivity(new Intent(SplashActivity.this, MainActivity.class));
}
public boolean isLoggedIn() {
return EMClient.getInstance().isLoggedInBefore();
}
在我們首次登錄成功后拉庵,不需要再次調(diào)用登錄方法灿椅。在下次應(yīng)用啟動(dòng)時(shí),環(huán)信 SDK 會(huì)自動(dòng)完成登錄钞支。如果自動(dòng)登錄失敗茫蛹,也會(huì)讀取之前的會(huì)話信息。
自動(dòng)登錄在下面幾種情況下會(huì)被取消:
- 用戶調(diào)用了 SDK 的登出動(dòng)作烁挟;
- 用戶在別的設(shè)備上更改了密碼婴洼,導(dǎo)致此設(shè)備上自動(dòng)登錄失敗撼嗓;
- 用戶的賬號(hào)被從服務(wù)器端刪除柬采;
- 用戶從另一個(gè)設(shè)備登錄欢唾,把當(dāng)前設(shè)備上登錄的用戶踢出。
退出登錄
// 異步方法
EMClient.getInstance().logout(true, new EMCallBack() {
@Override
public void onSuccess() {
// TODO Auto-generated method stub
}
@Override
public void onProgress(int progress, String status) {
// TODO Auto-generated method stub
}
@Override
public void onError(int code, String message) {
// TODO Auto-generated method stub
}
});
有時(shí)候在執(zhí)行退出登錄時(shí)警没,由于網(wǎng)絡(luò)問題而導(dǎo)致賬號(hào)解綁失敗匈辱,即使界面退出,但還會(huì)收到消息的現(xiàn)象杀迹。為了避免這種情況的發(fā)生亡脸,我們可以在應(yīng)用選擇退出時(shí)彈出對(duì)話框顯示當(dāng)前網(wǎng)絡(luò)是否正常以及提示退出的風(fēng)險(xiǎn)(繼續(xù)退出可能還會(huì)收到消息)。
需要注意的是树酪,如果調(diào)用異步退出方法浅碾,在收到 onSuccess()
的回調(diào)后才去調(diào)用 IM 相關(guān)的方法,比如 login续语。
注冊(cè)連接監(jiān)聽
當(dāng)?shù)艟€時(shí)垂谢,Android SDK 會(huì)自動(dòng)重連,無需進(jìn)行任何操作疮茄,通過注冊(cè)連接監(jiān)聽來知道連接狀態(tài)滥朱。根據(jù) onDisconnected()
方法返回的 error 判斷賬號(hào)連接失敗的原因。
//注冊(cè)一個(gè)監(jiān)聽連接狀態(tài)的listener
EMClient.getInstance().addConnectionListener(new MyConnectionListener());
//實(shí)現(xiàn)ConnectionListener接口
private class MyConnectionListener implements EMConnectionListener {
@Override
public void onConnected() {
}
@Override
public void onDisconnected(final int error) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if(error == EMError.USER_REMOVED){
// 顯示帳號(hào)已經(jīng)被移除
}else if (error == EMError.USER_LOGIN_ANOTHER_DEVICE) {
// 顯示帳號(hào)在其他設(shè)備登錄
} else {
if (NetUtils.hasNetwork(MainActivity.this))
//連接不到環(huán)信聊天服務(wù)器
else
//當(dāng)前網(wǎng)絡(luò)不可用力试,請(qǐng)檢查網(wǎng)絡(luò)設(shè)置
}
}
});
}
}
文章只是作為自己記錄學(xué)習(xí)使用徙邻,如果有使用不當(dāng)?shù)牡胤娇梢訞我,謝謝畸裳。
參考文章:環(huán)信開發(fā)文檔