广播的最佳实践——实现强制下现功能

新建项目BroadcastBestProctice

1.创建一个类ActivityCollector用于管理所有活动

package com.example.broadcastbestpractice;

import android.app.Activity;

import java.util.ArrayList;
import java.util.List;


public class ActivityCollector extends Activity{
    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(){
        for(Activity activity : activities){
            if(!activity.isFinishing()){
                activity.finish();
            }
        }
    }
}

2.创建BaseActivity类作为所有活动的父类

public class ActivityBase extends AppCompatActivity {

    private ForceOffline forceOffline;
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.finishAll();
    }
 }

创建登录界面的活动LoginActivity和布局activity_login.xml。

3.编辑登录界面的布局activity_login.xml

最外层是一个纵向的LinearLayout,里面包含三个元素
1.横向的LinearLayout,用于输入账号
2.横向的LinearLayout,用于输入密码
3.一个登录按钮

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60sp"
        android:orientation="horizontal">
        <TextView
            android:layout_width="90sp"
            android:layout_height="wrap_content"
            android:text="Account:"
            android:layout_gravity="center_vertical"
            android:textSize="18sp"
            android:textAllCaps="false"/>
        <EditText
            android:id="@+id/account"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60sp"
        android:orientation="horizontal">
        <TextView
            android:layout_width="90sp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="Password:"
            android:textAllCaps="false"
            android:textSize="18sp"/>
        <EditText
            android:id="@+id/password"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>

    <Button
        android:id="@+id/button"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Login"
        android:textAllCaps="false"/>
</LinearLayout> 

4.编写登录界面的活动LoginActivity

package com.example.broadcastbestpractice;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class LoginActivity extends ActivityBase {

    private EditText accountEdit;
    private EditText passworkEdit;
    private Button login;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        accountEdit = (EditText)findViewById(R.id.account);
        passworkEdit = (EditText)findViewById(R.id.password);
        login = (Button) findViewById(R.id.button);

        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //获取输入的账号和密码
                String account = accountEdit.getText().toString();
                String passwork = passworkEdit.getText().toString();

                //如果账号和密码正确,跳转到MainActivity
                if(account.equals("admin")&&passwork.equals("12345")){
                    Intent intent = new Intent(LoginActivity.this,MainActivity.class);
                    startActivity(intent);
                    finish();
                }else{//如果账号或密码错误,则提示该错误
                    Toast.makeText(LoginActivity.this,"the account or passwork is wrong",Toast.LENGTH_LONG).show();
                }
            }
        });
    }
}

5.修改activity_main.xml,添加发送广播按钮

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical|center_horizontal">

    <Button
        android:id="@+id/force_offline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send force offline broadcast"
        android:textAllCaps="false"/>


</LinearLayout> 

6.修改MainActivity,触发下线功能

点击按钮,发送一条值为com.example.broadcastbestpractice.FORCE_OFFLINE的广播,通知程序强制用户下线。

package com.example.broadcastbestpractice;

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 ActivityBase {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button force_offline  = (Button)findViewById(R.id.force_offline);
        force_offline.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("com.example.broadcastbestpractice.FORCE_OFFLINE");
                sendBroadcast(intent);
            }
        });
    }
}

7.在BaseActivity中动态注册一个广播接收器

强制用户下线的逻辑写在接收这条广播接收器里,这样强制下线功能不会依附于任何界面,不管是在程序的任何地方,只要发出这样一条广播,就可以完成强制下线功能。
因为始终需要保证只有处于栈顶的活动才能接收到这条强制下线广播,费站定的活动不应该去接收这条广播,故在onResum()方法和onPause()方法中注册和取消注册广播接收器。

public class ActivityBase extends AppCompatActivity {

    private ForceOffline forceOffline;
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.finishAll();
    }

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE");
        forceOffline = new ForceOffline();
        registerReceiver(forceOffline,intentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if(forceOffline != null){
            unregisterReceiver(forceOffline);
            forceOffline = null;
        }
    }

    //广播接收器
    class ForceOffline extends BroadcastReceiver{
        @Override
        public void onReceive(final Context context, final Intent intent) {
            //显示对话框
            AlertDialog.Builder dialog = new AlertDialog.Builder(context);
            dialog.setTitle("Warning");
            dialog.setMessage("You are forced to be offline. Please try to lagin again ");
            dialog.setCancelable(false);
            dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    ActivityCollector.finishAll();//销毁所有活动
                    Intent intent1 = new Intent(context,LoginActivity.class);
                   startActivity(intent1);//重启LoginActivity
                }
            });
            dialog.show();
        }
    }
}

8.在AndroidMainfest.xml中将LoginActivity设为主活动

 <activity android:name=".LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

9.运行程序

在这里插入图片描述
输入错误的密码
在这里插入图片描述
输入正确的密码,进入MainActivity
在这里插入图片描述
点击按钮,发送强制用户下线的广播
在这里插入图片描述
选择OK,注销所有活动并回到登录页面。

猜你喜欢

转载自blog.csdn.net/weixin_42937036/article/details/90759992