Android BroadcastReceiver 详解(上)

171 阅读4分钟

这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

文章目录

广播的特征

1、有一个广播的发送方,若干个接收方
2、通过“频道”匹配发送方与接收方

在 Android 系统中,把具有广播的通信方式的特征的数据传输方式称之为“广播”

BroadcastReceiver 是 Android 系统的核心组件,因此我们需要新建一个类继承 BroadcastReceiver 并注册

开发步骤

  1. 自定义类,继承自 BroadcastReveiver
  2. 在 AndroidManifest.xml 中注册该自定义的广播接收者
  3. 当需要发送广播时,调用sendBroadcast(intent)方法实现发送,该方法是 Context 定义的方法,所以在 Activity 或 Service 中能直接调用该方法。在发送广播前,应该为 intent 对象配置 Action 属性,用于确定广播的“频道”
  4. 在 AndroidManifest.xml 中找到广播接收者的注册节点,添加子级<intent-filter>节点,配置<action/>节点属性,使之匹配广播的发送方的“频道”

栗子

目的:实现简单的发送和接受

新建 CustomReceiver 继承 BroadcastReceiver

public class CustomReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String date = intent.getStringExtra("date");
        Log.d("BROADCAST","CustomReceiver->onReceive();时间:"+date);
    }
}

布局文件 activity_main

<Button
	android:id="@+id/btn_send"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="发送广播"/>

MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button btnSend;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnSend = findViewById(R.id.btn_send);
        btnSend.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        long date = System.currentTimeMillis();
        Intent intent = new Intent();
        intent.setAction("CCTV5");
        intent.putExtra("date",""+date);
        Log.d("BROADCAST","Mainctivity->onClick();时间:"+date);
        sendBroadcast(intent);
    }
}

AndroidManifest

<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">

        <receiver android:name=".CustomReceiver">
            <intent-filter>
                <action android:name="CCTV5"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </receiver>

        <activity android:name=".MainActivity">
			......
        </activity>
    </application>

点击按钮,查看日志

D/BROADCAST: Mainctivity->onClick();时间:1523503113567
D/BROADCAST: CustomReceiver->onReceive();时间:1523503113567

由于广播可以有多个接收方,所以我们新建 CustomReceiver2

public class CustomReceiver2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String date = intent.getStringExtra("date");
        Log.d("BROADCAST","CustomReceiver2->onReceive();时间:"+date);
    }
}

AndroidManifest中注册

<receiver android:name=".CustomReceiver2">
	<intent-filter>
		<action android:name="CCTV5"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</receiver>

点击按钮查看日志

D/BROADCAST: Mainctivity->onClick();时间:1523503682968
D/BROADCAST: CustomReceiver->onReceive();时间:1523503682968
D/BROADCAST: CustomReceiver2->onReceive();时间:1523503682968

报错处理:Background execution not allowed

Android 8以上并不会正常接收到广播,而是会输出警告:Background execution not allowed

解决办法1:因为这是静态广播注册才会有的问题,所以可以考虑将静态广播修改为动态广播。

解决办法2:增加 packageName

Intent intent = new Intent();
intent.setPackage("com.example.testapplication");
intent.setAction("CCTV5");
intent.putExtra("date", "" + date);
Log.d("BROADCAST", "Mainctivity->onClick();时间:" + date);
sendBroadcast(intent);

广播的注册类型

  1. 静态注册:在项目清单中注册,这种方式注册的广播接收者是常驻型的,即只要 APP 安装到手机上就会接收广播,直至 APP 被卸载,而无视该 APP 有没有在手机上运行
  2. 动态注册:在程序运行过程中注册,registerReceiver(receiver,filter)方法注册,这种方式注册的广播接收者,仅当注册后才开始接收广播,需要停止接受时,应该调用unregisterReceiver(receiver);注销

栗子

在页面增加两个按钮
这里写图片描述

MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btnSend;
    private Button btnResiger;
    private Button btnUnregister;
    private InnerReceiver receiver;

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

        btnSend = findViewById(R.id.btn_send);
        btnResiger = findViewById(R.id.btn_register_receiver);
        btnUnregister = findViewById(R.id.btn_unregister_receiver);
        btnSend.setOnClickListener(this);
        btnResiger.setOnClickListener(this);
        btnUnregister.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_send:
                long date = System.currentTimeMillis();
                Intent intent = new Intent();
                intent.setPackage("com.example.testapplication");
                intent.setAction("CCTV5");
                intent.putExtra("date", "" + date);
                Log.d("BROADCAST", "Mainctivity->onClick();时间:" + date);
                sendBroadcast(intent);
                break;
            case R.id.btn_register_receiver:
                if (receiver == null) {
                    receiver = new InnerReceiver();
                    IntentFilter filter = new IntentFilter();
                    filter.addAction("CCTV5");
                    registerReceiver(receiver, filter);
                }
                break;
            case R.id.btn_unregister_receiver:
                if (receiver != null) {
                    unregisterReceiver(receiver);
                    receiver = null;
                }
                break;
        }
    }

    private class InnerReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String date = intent.getStringExtra("date");
            Log.d("BROADCAST", "InnerReceiver->onReceive();时间:" + date);
        }
    }
}

先点击发送广播

D/BROADCAST: Mainctivity->onClick();时间:1523505690920
D/BROADCAST: CustomReceiver->onReceive();时间:1523505690920
D/BROADCAST: CustomReceiver2->onReceive();时间:1523505690920

点击注册内部接收者,再点击发送广播

D/BROADCAST: Mainctivity->onClick();时间:1523505725969
D/BROADCAST: InnerReceiver->onReceive();时间:1523505725969
D/BROADCAST: CustomReceiver->onReceive();时间:1523505725969
D/BROADCAST: CustomReceiver2->onReceive();时间:1523505725969

点击注销内部接收者,再点击发送广播

D/BROADCAST: Mainctivity->onClick();时间:1523505817228
D/BROADCAST: CustomReceiver->onReceive();时间:1523505817228
D/BROADCAST: CustomReceiver2->onReceive();时间:1523505817228