(八)Android广播接收器BroadcastReceiver

时间:2023-03-08 18:03:24

一、使用Broadcast Reciver

1.右击java文件夹,new->other->Broadcast Receiver后会在AndroidManifest.xml文件中生成一个receiver项

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.shiyanshi.learnbroadcast" > <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true" >
</receiver>

    </application>

</manifest>

2.同时生成了一个MyReceiver 的类,该类中onReceive用于响应sendBroadcast函数发送的消息

package com.example.shiyanshi.learnbroadcast;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
} @Override

public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
// throw new UnsupportedOperationException("Not yet implemented");
System.out.println("Recv Data:"+intent.getStringExtra("data"));
}

}

3.调用sendBroadcast函数进行发送消息,该函数需要一个Intent

package com.example.shiyanshi.learnbroadcast;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View; public class MainActivity extends Activity implements View.OnClickListener { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); findViewById(R.id.btnSendMsg).setOnClickListener(this);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
} @Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btnSendMsg:

Intent intent =new Intent(this,MyReceiver.class);
intent.putExtra("data","henry");
sendBroadcast(intent);

                break;
}
}
}

二、动态注册和注销

1.删去AndroidManifest.xml文件中的receiver时,需要动态注册和注销,才能发送和接收消息

<receiver
android:name=".MyReceiver"

android:enabled="true"

android:exported="true" >

</receiver>

2.MainActivity更改如下:发送消息消息时,Intent要使用隐式Intent(MyReceiver.ACTION为定义的一个常量字符串

public static final String ACTION="com.example.shiyanshi.learnbroadcast.intent.action.MyReceiver";//前半部分时包名,后半部分时intent的格式,MyReceiver是上述中用于

响应sendBroadcast的类),注册时使用registerReceiver函数,注销时使用unregisterReceiver函数

函数原型为:

public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

public void unregisterReceiver(BroadcastReceiver receiver)

receiver是我们新建Broadcast时声称的用于响应sendBroadcast的MyReceiver类,filter是过滤器,需想起传递隐式Intent类似的参数。

public class MainActivity extends Activity implements View.OnClickListener {

private MyReceiver receiver=null;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); findViewById(R.id.btnSendMsg).setOnClickListener(this);
findViewById(R.id.btnRegister).setOnClickListener(this);
findViewById(R.id.btnUnregister).setOnClickListener(this);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
} @Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btnSendMsg:
// Intent intent =new Intent(this,MyReceiver.class);

//动态注册和注销时要使用隐式Intent,而不能使用显示Intent了
Intent intent=new Intent(MyReceiver.ACTION);

                intent.putExtra("data","henry");
sendBroadcast(intent);
break;

case R.id.btnRegister:
if (receiver==null){
receiver=new MyReceiver();
registerReceiver(receiver,new IntentFilter(MyReceiver.ACTION));
}
break;
case R.id.btnUnregister:
if(receiver!=null){
unregisterReceiver(receiver);
receiver=null;
}
break;

        }
}
}

三、Broadcast的优先级

当发送数据时,采用隐式Intent的形式(如上),两个receiver中的action name相同时,二者可以同时接收到数据。

默认情况下最后写的那个receiver所对应的优先级高,此外可以显示的在receiver下的Intent-filter中指明优先级priority,其数值越大,优先级越高,越先响应数据

 <receiver
android:name=".MyReceiver1"
android:enabled="true"
android:exported="true" >
<intent-filter android:priority="2">
<action android:name="com.example.shiyanshi.learnbroadcast.intent.action.MyReceiver"/>
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1">
<action android:name="com.example.shiyanshi.learnbroadcast.intent.action.MyReceiver"/>
</intent-filter>
</receiver>
</application>

此外,当优先级高的那个onReceive执行后,可以在其中调用abortBroadcast来终止数据的传递,优先级别低的onReceive便不会执行了.

注意:若想使用abortBroadcast函数,发送时需使用sendOrderedBroadcast而非sendBroadcast,否则会弹出错误java.lang.RuntimeException: BroadcastReceiver trying to return result during a non-ordered broadcast。

Intent intent=new Intent(MyReceiver.ACTION);
intent.putExtra("data","henry");
// sendBroadcast(intent);
sendOrderedBroadcast(intent,null);

其中sendOrderedBroadcast的第二个参数用来指明权限,可以为空