利用廣播BroadcastReceiver實現登錄強制下線功能
在這裏面登錄界面裏面的用戶名和密碼爲默認的“admin””123456” 可以在LoginActivity裏面進行修改,該例子只是簡單的說明怎麼樣BroadcastReceiver進行強制性的下線。
原理
在應用程序中經常會遇到強制下線的情況,比如qq在別處登錄,本機的你就被強制下線了。其實強制下線的原理很簡單,就是彈出一個對話框讓你沒辦法進行去他的操作,只能點擊對話框的“確定”按鈕進行重新登錄驗證身份,但是我們被通知需要強制下線的時候可能處於任何一個界面,肯定不能在沒一個界面都寫一個對話框。此時就用到了廣播。在本例中點擊button後觸發廣播,然後提交給ForceOfflineReceiver類進行接受廣播,進行銷燬所有的活動,完成用戶強制性下線
1、首先創建一個Activity管理類“ActivityCollector”
在這裏面進行Activity的添加 刪除 和銷燬所有,能夠在後面強制下線時,銷燬所有的Activity,只顯示一個對話框
package com.example.chencong.broadcastbestpractive;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
/**
* Created by chencong on 2017/3/16.
*/
public class ActivityCollector {
/**
* 創建一個Activity類來管理所有的活動
*/
public static List<Activity> activities = new ArrayList<Activity>();
/**
* 定義泛型數組activities 添加activity活動的方法addActivity
* @param activity
*/
public static void addActivity(Activity activity){
activities.add(activity);
}
/**
* 移除activity活動的方法removeActivity
* @param activity
*/
public static void removeActivity(Activity activity){
activities.remove(activity);
}
/**
* 遍歷所有活動將其停止完成
*/
public static void findAll(){
for (Activity activity: activities) {
if (!activity.isFinishing()){
activity.finish();
}
}
}
}
2、然後創建一個基類BaseActivity
之所以創建這個基類,是爲了方便對所有的Activity進行管理(添加 刪除 銷燬所有),因爲在後面創建的Activity是繼承此Activity的,能夠保證在創建的時候就已添加到ActivityCollector中。
package com.example.chencong.broadcastbestpractive;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
/**
* 定義父類BaseActivity
*/
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//創建活動時,將其加入管理器中
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//銷燬活動時,將其從管理器中移除
ActivityCollector.removeActivity(this);
}
}
3、一個簡單的登錄界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="輸入賬戶"/>
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="輸入密碼"/>
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登錄"/>
</LinearLayout>
4、爲login.xml
編寫活動
創建一個Activity繼承BaseActivity,命名爲LoginActivity.java,在這裏使用的賬號和密碼爲默認的“admin”“123456”
package com.example.chencong.broadcastbestpractive;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class LoginActivity extends BaseActivity implements View.OnClickListener {
private EditText accountEdit;
private EditText passwordEdit;
private Button loginButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
//初始化 註冊控件
accountEdit = (EditText)findViewById(R.id.account);
passwordEdit = (EditText)findViewById(R.id.password);
loginButton = (Button)findViewById(R.id.login);
//登錄按鈕的點擊事件
loginButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
//在這裏進行默認賬戶爲 admin 密碼爲123456
if (account.equals("admin") && password.equals("123456")){
//登錄成功後 進入MainActivity 並且在這裏面提供強制下線的功能
Intent intent = new Intent(LoginActivity.this,MainActivity.class);
startActivity(intent);
finish();
}else {
Toast.makeText(LoginActivity.this,"賬戶和密碼不匹配",Toast.LENGTH_SHORT).show();
}
}
}
當從LoginActivity.java中登錄進去後會進入到MainActivity中,在這裏頁面中只有一個Button,當然登錄進去之後,想實現怎樣的功能由你自己去實現了。
5、在MainActivity中進行強制下線
package com.example.chencong.broadcastbestpractive;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button forceOffline = (Button)findViewById(R.id.force_offline);
/**點擊按鈕 發送一個"com.example.chencong.broadcastbestpractive.FORCE_OFFLINE"
*強制下線的廣播 然後在接受這條廣播的類(接收器)中進行強制下線的功能
* 在這裏新建一個廣播接收器 ForceOfflineReceiver 類 來繼承 BroadcastReceiver
*/
forceOffline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.chencong.broadcastbestpractive.FORCE_OFFLINE");
sendBroadcast(intent);
}
});
}
}
佈局很簡單啦,就一個Button就行了
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.chencong.broadcastbestpractive.MainActivity">
<!--<TextView-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:text="Hello World!" />-->
<!--提供強制下線的功能-->
<Button
android:id="@+id/force_offline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="強制下線賬戶"/>
</RelativeLayout>
不過這裏有個重點,在Button的點擊事件中,發送了一條廣播,廣播值爲com.example.chencong.broadcastbestpractive.FORCE_OFFLINE
,這條廣播就是用於通知程序,將用戶強制下線的。
也就是說強制用戶下線的功能並不是寫在MainActivity中的,而是寫在這條廣播的廣播接收器中,這樣強制下線就不會依賴任何界面,不管是在程序的任何地方,只要一發出這樣的一條廣播,就可以完成強制下線了。
對,現在就來創建一個廣播的接收器,新建一個ForceOfflineReceiver類繼承BroadcastReceiver
6、新建一個ForceOfflineReceiver類繼承BroadcastReceiver
package com.example.chencong.broadcastbestpractive;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.WindowManager;
/**
* Created by chencong on 2017/3/16.
*/
public class ForceOfflineReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
//構建一個對話框
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle("警告");
dialogBuilder.setMessage("你的賬號被強制下線,請重新登錄");
dialogBuilder.setCancelable(false); //並且對話框不可被取消
//給對話框註冊確定按鈕
dialogBuilder.setPositiveButton("重新登錄", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCollector.findAll(); //銷燬所有活動
Intent i = new Intent(context,LoginActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //在廣播接收器中啓動活動 因此需要加上這個標誌
context.startActivity(i); //重新啓動登錄界面
}
});
AlertDialog alertDialog = dialogBuilder.create();
//設置AlertDialog 的類型 保證廣播接收器中可以正常的彈出
//系統級別的對話框 因此需要在AndroidManifest中進行聲明
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
}
}
在onReceiver()方法中,首先使用AlertDialog.Builder構建一個對話框,並且調用setCancelable()方法將對話框設置爲不可取消,否則用戶按一下返回鍵就能夠關閉對話框就能夠繼續使用程序了,然後用setPositiveButton()方法爲對話框註冊確定按鈕,並且當用戶點擊確定按鈕時候就調用之前我們創建的ActivityCollector這個類的finishAll()方法類銷燬所有的Activity,並且重新啓動LoginActivity進行登錄。
並且在廣播接收器中啓動活動時候,一定要給Intent的對象加入FLAG_ACTIVITY_NEW_TASK這個標誌,最後將對話框的類型設置爲系統級別,否在無法在廣播接收器中進行彈出。
7、最後的配置
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.chencong.broadcastbestpractive">
<!--進行權限配置-->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".LoginActivity"
android:label="@string/app_login">
<intent-filter
android:label="@string/app_name">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BaseActivity" />
<activity android:name=".MainActivity"
android:label="@string/app_mian"/>
<receiver android:name=".ForceOfflineReceiver">
<intent-filter>
<action android:name="com.example.chencong.broadcastbestpractive.FORCE_OFFLINE"/>
</intent-filter>
</receiver>
</application>
</manifest>
前面將對話框設置爲系統級別的,因此在這裏需要進行聲明。然後對廣播進行註冊,並且指定爲哪一個廣播。
8、運行看看效果啦
登錄界面,輸入賬戶 密碼
登錄進去後 進行點擊下線
9、最後附上源碼
項目地址:github傳送門
apk下載:github傳送門
喜歡就去做,想到就去做!做自己喜歡的事情
----by chencong