限制單設(shè)備登錄指的是同一個(gè)賬戶(id)不能在一個(gè)以上的設(shè)備上登錄對(duì)應(yīng)的用戶系統(tǒng)(排除web端和移動(dòng)端可以同時(shí)登錄的情況),例如:用戶m在A設(shè)備登錄并保持登錄狀態(tài),然后又在B設(shè)備登錄,此時(shí)A應(yīng)該要強(qiáng)制下線,m無法在A設(shè)備上繼續(xù)執(zhí)行用戶相關(guān)的操作
服務(wù)端
服務(wù)端需要集成Token,每次在app登錄時(shí)為app分配新的token,如果在某次http請(qǐng)求中app傳遞token不是最新的,則視為需要重新登錄(或者根據(jù)自己需要后臺(tái)設(shè)定token有效時(shí)間,過期視為Token失效,需要重新登錄).在token失效的情況下,返回約定好的code
Android端監(jiān)聽
App如何知道已經(jīng)在其他設(shè)備登錄了呢,一般可以有三種方式
1.api請(qǐng)求中后臺(tái)返回特定code
這種是最常見的方式,缺點(diǎn)是需要下次api請(qǐng)求才知道被踢下線,可以在網(wǎng)絡(luò)層實(shí)體模型的基類BaseModel中處理,對(duì)code進(jìn)行判斷
switch (code) {
case 1:
break;
case 3://被踢下線
//Do Something
break;
}
2.推送
后臺(tái)推送給app,從而app得知該賬戶在其他設(shè)備登錄了,進(jìn)而執(zhí)行下線操作,優(yōu)點(diǎn)是可以及時(shí)響應(yīng)
3.使用第三方的監(jiān)聽器
很多時(shí)候app會(huì)集成一些第三方的賬戶系統(tǒng),例如在集成了環(huán)信的app中,每個(gè)用戶對(duì)應(yīng)一個(gè)環(huán)信的imUserName,環(huán)信自身有提供連接狀態(tài)的接聽,通過監(jiān)聽環(huán)信的用戶狀態(tài),從而達(dá)到監(jiān)聽app自身用戶系統(tǒng)的效果
EMClient.getInstance().addConnectionListener(this);
Android被踢下線后的操作
不管是哪種監(jiān)聽方式,最后的操作都是一樣的,可以根據(jù)自己的需求進(jìn)行對(duì)應(yīng)的操作.這里提供一種常規(guī)化的下線流程.
- 從棧頂取到當(dāng)前的前臺(tái)Activity,Dialog提示用戶,點(diǎn)擊后跳轉(zhuǎn)登錄頁
首先,任意地方獲取到前臺(tái)Activity
public Activity getTaskTop() {
return mActivities.get(mActivities.size() - 1);
}
然后在主線程彈出dialog
private void onConnectionConflict() {//被踢下線處理
SPUtils.logout();
final Activity taskTop = ActivityManager.getInstance().getTaskTop();
if (taskTop == null) return;
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
MDdialogFactory.CreateMustOkDia(taskTop, "您的賬號(hào)已在其他終端登錄,請(qǐng)重新登錄", new MDCallBack() {
@Override
public void onMdCall(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
Intent intent = new Intent(taskTop, LoginActivity.class);
intent.putExtra(ConstantKey.MUST_LOGIN_KEY, true);
taskTop.startActivity(intent);
}
}).show();
}
});
}
這里做一些說明
-
由于監(jiān)聽到被踢下線的環(huán)境不一定在主線程,所以需要切換到主線程進(jìn)行彈出Dilaog
new Handler(Looper.getMainLooper()).post(Runnable r)
-
這里的dialog是強(qiáng)制的,取消不了(這里dialog是自定義的,用系統(tǒng)的也是可以的,這不是重點(diǎn))
builder.cancelable(false); builder.canceledOnTouchOutside(false);
關(guān)于作者
- 簡(jiǎn) 書:uncochen
- github:ChenZhen
- 新浪微博:@Chen丶振
- Email:18620156376@163.com