Android LocalBroadcast本地广播

经过前面几章节的学习,我们对 BroadcastReceiver 应该有非常深的了解,知晓了如何接收广播和如何发送广播,这已经满足我们大部分的需求了

但前面说的广播都是 全局广播,意味着我们 APP 发出的广播,其它 APP 都会接收到, 或者其它 APP 发送的广播,我们的 APP 也会接收到,这样容易引起一些安全性的问题

Android 提供了 本地广播 的机制,使用该机制发出的广播只会在 APP 内部传播,而且 广播接收者也只能收到本应用发出的广播

本地广播

本地广播 发出的广播只会在 APP 内部传播,而且 广播接收者也只能收到本应用发出的广播

本地广播无法通过静态注册方式来接受,相比起系统全局广播更加高效

使用流程

使用 LocalBroadcastManager 来管理广播

  1. 调用 LocalBroadcastManager.getInstance() 获得实例 mLBM
  2. 调用 mLBM.registerReceiver() 注册广播
  3. 调用 mLBM.sendBroadcase() 发送广播
  4. 调用 mLBM.unregisterReceiver() 取消注册广播

注意事项

  1. 在广播中启动 Activity 的话需要为 intent 加入 FLAG_ACTIVITY_NEW_TASK 标记,不然会报错,因为需要一个栈来存放新打开的 Activity

  2. 广播中弹出 AlertDialog 的话,需要设置对话框的类型为 TYPE_SYSTEM_AERT 不然无法弹出

范例

我们写一个 demo 别处登录踢人下线 来演示下本地广播

像微信一样,正在运行的微信,如果我们用别的手机再次登陆自己的账号,前面这个是会提醒账户 在别的终端登录这样,然后把我们打开的所有 Activity 都关掉,然后回到登陆页面这样


  1. 创建一个 空的 Android 项目 cn.twle.android.LocalBroadcast

  2. MainActivity.java 目录下创建文件 ActivityManager.java 用来管理所有的 Activity

    package cn.twle.android.localbroadcast;
    
    import java.util.List;
    import java.util.ArrayList;
    
    import android.app.Activity;
    
    public class ActivityManager {
        private static List<Activity> activities = new ArrayList<Activity>();
        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();
                }
            }
        }
    }
    
  3. MainActivity.java 目录下创建文件 MsBaseActivity.java 作为所有 Activity 的基础类

    package cn.twle.android.localbroadcast;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    
    public class MsBaseActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivityManager.addActivity(this);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            ActivityManager.removeActivity(this);
        }
    }
    
  4. res/layout 目录下新建 activity_login.xml 添加一个登录页面

    <?xml version="1.0" encoding="utf-8" ?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal" 
        android:padding="8dp"
        android:orientation="vertical" >
    
        <TextView
            android:text="用户名"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
        <EditText android:id="@+id/login_username" 
            android:layout_width="match_parent"
            android:layout_height="wrap_content" 
            android:text="123" />
    
        <TextView
            android:text="密 码"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
        <EditText android:id="@+id/login_passwd" 
            android:layout_width="match_parent"
            android:layout_height="wrap_content" 
            android:text="123" />
    
        <Button 
            android:text="登录" 
            android:id="@+id/btn_login"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" />
    
    </LinearLayout>
    
  5. MainActivity.java 目录下创建文件 LoginActivity.java 作为登录页面的 Activity

    package cn.twle.android.localbroadcast;
    
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.os.Bundle;
    import android.preference.PreferenceManager;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class LoginActivity extends MsBaseActivity implements View.OnClickListener{
    
        private SharedPreferences pref;
        private SharedPreferences.Editor editor;
    
        private EditText login_username;
        private EditText login_passwd;
        private Button   btn_login;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            pref = PreferenceManager.getDefaultSharedPreferences(this);
    
            bindViews();
        }
    
        private void bindViews() {
            login_username = (EditText) findViewById(R.id.login_username);
            login_passwd = (EditText) findViewById(R.id.login_passwd);
            btn_login = (Button) findViewById(R.id.btn_login);
            btn_login.setOnClickListener(this);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            if(!pref.getString("user","").equals("")){
                login_username.setText(pref.getString("user",""));
                login_passwd.setText(pref.getString("pawd",""));
            }
        }
    
        @Override
        public void onClick(View v) {
            String user = login_username.getText().toString();
            String pawd = login_passwd.getText().toString();
            if(user.equals("123")&&pawd.equals("123")){
                editor = pref.edit();
                editor.putString("user", user);
                editor.putString("pawd", pawd);
                editor.commit();
                Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                startActivity(intent);
                Toast.makeText(LoginActivity.this,"哟,竟然蒙对了~",Toast.LENGTH_SHORT).show();
                finish();
            }else{
                Toast.makeText(LoginActivity.this,"这么简单都输出,脑子呢?",Toast.LENGTH_SHORT).show();
            }
    
        }
    }
    
  6. MainActivity.java 目录下创建文件 MsBroadcastReceiver.java

    重写 onReceive() 并实现弹出对话框操作,以及启动登陆页面

    package cn.twle.android.localbroadcast;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.app.AlertDialog;
    import android.view.WindowManager;
    
    public class MsBroadcastReceiver 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) {
                            ActivityManager.finishAll();
                            Intent intent = new Intent(context, LoginActivity.class);
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            context.startActivity(intent);
                        }
                    });
            AlertDialog alertDialog = dialogBuilder.create();
            alertDialog.getWindow().setType(
                    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            alertDialog.show();
        }
    }
    
  7. 修改 activity_main.xml 添加一个 登录按钮

    <?xml version="1.0" encoding="utf-8" ?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal" 
        android:orientation="vertical" >
    
        <Button 
            android:text="发送登录信息" 
            android:id="@+id/btn_send"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" />
    
    </LinearLayout>
    
  8. 修改 MainActivity.java

    package cn.twle.android.localbroadcast;
    
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.Bundle;
    import android.support.v4.content.LocalBroadcastManager;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends MsBaseActivity {
    
        private MsBroadcastReceiver localReceiver;
        private LocalBroadcastManager localBroadcastManager;
        private IntentFilter intentFilter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            localBroadcastManager = LocalBroadcastManager.getInstance(this);
    
            //初始化广播接收者,设置过滤器
            localReceiver = new MsBroadcastReceiver();
            intentFilter = new IntentFilter();
            intentFilter.addAction("cn.twle.android.localbroadcast.LOGIN_OTHER");
            localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    
            Button btn_send = (Button) findViewById(R.id.btn_send);
            btn_send.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent("com.jay.mybcreceiver.LOGIN_OTHER");
                    localBroadcastManager.sendBroadcast(intent);
                }
            });
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            localBroadcastManager.unregisterReceiver(localReceiver);
        }
    }
    
  9. 修改 AndroidManifest.xml 中加上系统对话框权限,注册 BroadcastActivity

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="cn.twle.android.localbroadcast">
    
        <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=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".LoginActivity" android:theme="@style/Theme.AppCompat.Dialog" />
            <receiver android:name=".MsBroadcastReceiver">
                <intent-filter>
                    <action android:name="cn.twle.android.localbroadcast.LOGIN_OTHER"/>
    
                </intent-filter>
            </receiver>
        </application>
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    </manifest>
    

尝试运行,用户名和密码都是 "123"

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.