preface

The idea of forcibly logging out is also relatively simple. You only need to pop up a dialog box so that the user cannot perform any other operations. You must click ok in the dialog box and return to the login page.

The complete project is attached at the end

Note: The account is admin and the password is 123456

The project has begun

Create a new project called BroadcastBestPractice

The forced logout function requires you to close all activities and return to the login screen. So start by creating an ActivityCollector class to manage all activities as follows:

public class ActivityCollector {

    public static List<Activity> activities = new ArrayList<>();

    public static void addActivity(Activity activity){
        activities.add(activity);
    }

    public static void removeActivity(Activity activity){
        activities.remove(activity);
    }

    public static void finishAll(a){
        for (Activity activity : activities){
            if (!activity.isFinishing()){
                activity.finish();
            }
        }
        activities.clear();
    }

}
Copy the code

Then create the BaseActivity class as a parent class for all activities, as shown below:

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy(a) {
        super.onDestroy();
        ActivityCollector.removeActivity(this); }}Copy the code

Create a new LoginActivity for the login screen and edit the layout file activity_login. XML as follows:

<? The XML version = "1.0" encoding = "utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".LoginActivity" android:orientation="vertical"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="60dp"> <TextView android:layout_width="90dp" android:layout_height="wrap_content" Android: layout_gravity = "center_vertical" android: textSize = "18 sp" android: text = "Account: "/> <EditText android:id="@+id/account" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="60dp"> <TextView android:layout_width="90dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textSize="18sp" android:text="Password:"/> <EditText android:id="@+id/password" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" android:inputType="textPassword"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <CheckBox android:id="@+id/remember_pass" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:layout_width="wrap_content"  android:layout_height="wrap_content" android:textSize="18sp" android:text="Remember password"/> </LinearLayout> <Button  android:id="@+id/login" android:layout_width="match_parent" android:layout_height="60dp" android:text="Login"/> </LinearLayout>Copy the code

Modify the code in the LoginActivity as follows:

Note: Remember the account password function is also perfect, click CheckBox can remember the account password

public class LoginActivity extends BaseActivity {

    private SharedPreferences pref;
    private SharedPreferences.Editor editor;
    private EditText accountEdit;
    private EditText passwordEdit;
    private Button login;
    private CheckBox rememberPass;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        pref = PreferenceManager.getDefaultSharedPreferences(this);
        initView();
        boolean isRemember = pref.getBoolean("remember_password".false);
        if (isRemember) {
            // Set the account and password to the text box
            String account = pref.getString("account"."");
            String password = pref.getString("password"."");
            accountEdit.setText(account);
            passwordEdit.setText(password);
            rememberPass.setChecked(true);
        }
        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String account = accountEdit.getText().toString();
                String password = passwordEdit.getText().toString();
                // If the user name is admin and the password is 123456, the login is successful
                if (account.equals("admin") && password.equals("123456")) {
                    editor = pref.edit();
                    // Check whether the check box is selected
                    if (rememberPass.isChecked()) {
                        editor.putBoolean("remember_password".true);
                        editor.putString("account", account);
                        editor.putString("password", password);
                    } else {
                        editor.clear();
                    }
                    editor.apply();
                    Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    Toast.makeText(LoginActivity.this."account or password is invalid", Toast.LENGTH_SHORT).show(); }}}); }private void initView(a) { accountEdit = (EditText) findViewById(R.id.account); passwordEdit = (EditText) findViewById(R.id.password); login = (Button) findViewById(R.id.login); rememberPass = (CheckBox) findViewById(R.id.remember_pass); }}Copy the code

To think of MainActivity as the main screen of the program after a successful login, simply add the forced logout function. Modify the code in activity_main.xml as follows:

<? The XML version = "1.0" encoding = "utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:orientation="vertical"> <Button android:id="@+id/force_offline" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send force offline broadcast"/> </LinearLayout>Copy the code

Modify the code in MainActivity as follows:

public class MainActivity extends BaseActivity {

    private Button forceOffline;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        forceOffline.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("com.example.broadcastbestpractice.FORCE_OFFLINE");
                // Send a broadcastsendBroadcast(intent); }}); }private void initView(a) { forceOffline = (Button) findViewById(R.id.force_offline); }}Copy the code

Note: MainActivity inside the button click event sent a radio, broadcast the value for the com. Example. Broadcastbestpractice. FORCE_OFFLINE, the radio is used for mandatory user logoff notification program.

The logic for forcing users to log out is not written in MainActivity, but should be written in the broadcast receiver that receives this broadcast, so that the function of forcing users to log out is not attached to any interface, no matter where in the program, just need to send such a broadcast, can complete the operation of forcing users to log out.

Since the broadcast receiver needs to pop up a dialog box to block the user’s normal operation, if you create a statically registered broadcast receiver, there is no way to pop up a UI control such as a dialog box in the onReceive() method, and there is no way to register a dynamic broadcast receiver for every activity.

Modify the code in BaseActivity as follows:

public class BaseActivity extends AppCompatActivity {

    private ForceOfflineReceiver receiver;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }

    // Register a broadcast receiver
    protected void onResume(a) {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE");
        receiver = new ForceOfflineReceiver();
        registerReceiver(receiver, intentFilter);
    }

    // Unregister the broadcast receiver
    @Override
    protected void onPause(a) {
        super.onPause();
        if(receiver ! =null) {
            unregisterReceiver(receiver);
            receiver = null; }}@Override
    protected void onDestroy(a) {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }

    class ForceOfflineReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(final Context context, Intent intent) {
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("Warning");
            builder.setMessage("You are forced to be offline.Please try to login again");
            builder.setCancelable(false);
            builder.setPositiveButton("Ok".new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int which) {
                    // Destroy all activities
                    ActivityCollector.finishAll();
                    Intent i = new Intent(context, LoginActivity.class);
                    // Restart LoginActivitycontext.startActivity(i); }}); builder.show(); }}}Copy the code

Build a dialog box using alertdialog.builder. Note that the setCancelable() method must be called to make the dialog box uncancelable, otherwise the user can press the Back key to close the dialog box and continue using the program.

Q: Previously, onCreate() and onDestroy() were used to register and unregister broadcast receivers.

A: This is because we always need to ensure that only activities at the top of the stack can receive the forced logout broadcast. Activities that are not at the top of the stack should not and need not receive the forced logout broadcast, so the onResume() and onPause() methods can solve this problem. The broadcast receiver is automatically unregistered when an activity loses its position at the top of the stack.

Finally modify androidmanifest.xml as follows:

<? The XML version = "1.0" encoding = "utf-8"? > <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lwm.broadcastbestpractice"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".LoginActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MainActivity"> </activity> </application> </manifest>Copy the code

Project link: pan.baidu.com/s/1Si5z_a5E…

Extraction code: OUIP