Android四大组件——BroadcastReceiver——自定义广播

1.发送标准广播

步骤一:新建MyBroadcastActivity,布局如下:

 

 

 现在我们要实现的是:输入要发送的广播内容,点击发送按钮后,该条广播被接收,并在日志处打印出来。

MyBroadcastActivity的代码如下:

//采用静态注册的方式
public class MyBroadcastActivity extends AppCompatActivity {
    private EditText message ;
    private Button send_message;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_broadcast_receiver);
        message = findViewById(R.id.message);
        send_message = findViewById(R.id.send_message);
        send_message.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String content = message.getText().toString();//获取输入的广播内容
                Intent intent = new Intent(); //靠intent进行数据传递
                //添加广播的action,自定义为com.java.androidtest.SEND_MESSAGE,表示发送信息的广播
                intent.setAction("com.java.androidtest.SEND_MESSAGE");
                intent.putExtra("content",content);//将输入内容也传递过去
                //Android8.0以后,静态注册的BroadcastReceiver是无法接收隐式广播的,而默认情况下我们发出的自定义广播恰恰都是隐式广播。
                //因此这里一定要调用setPackage()方法,指定这条广播是发送给那个应用程序的,从而让它变成一条显示广播。否则,静态注册的BroadcastReceiver将无法接收这条广播。
                intent.setPackage(getPackageName()); 
                sendBroadcast(intent);
            }
        });
    }
}

步骤二:创建MyBroadcastReceiver,用于接收广播。代码如下:

public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG,"action ==>"+action);
        String content = intent.getStringExtra("content");
        Log.d(TAG,"content is = >"+content);//将广播内容在日志中打印出来
    }
}

步骤三:静态注册该广播。在AndroidManifest.xml文件application标签中,对MyBroadcastReceiver进行静态注册。如下:

        <receiver android:name="com.kotlin.androidtest.MyBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.java.androidtest.SEND_MESSAGE"/>
            </intent-filter>
        </receiver>

现在,发送一条广播,看看运行结果吧。

 

 

点击发送按钮后,查看日志的打印情况:

 

 可以看到,该条广播的action正是我们自定义的com.java.androidtest.SEND_MESSAGE,也成功将输入的信息通过广播的方式传输并接收。

 2.发送有序广播

和标准广播不同,有序广播是一种同步执行的广播,并且可以被截断。

新建LowBroadcastReceiver,代码如下:

public class LowBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG ="LowBroadcastReceiver" ;
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG,"action ==>"+action);
        String content = intent.getStringExtra("content");
        Log.d(TAG,"content is = >"+content);
    }
}

和MyBroadcastReceiver内容一致,现在我们对LowBroadcastReceiver进行静态注册。

代码如下:(这里将MyBroadcastReceiver也展示了出来。)

        <receiver android:name=".LowBroadcastReceiver">
            <intent-filter>
                <action android:name="com.java.androidtest.SEND_MESSAGE"/>
            </intent-filter>
        </receiver>
        <receiver android:name=".MyBroadcastReceiver">
            <intent-filter>
                <action android:name="com.java.androidtest.SEND_MESSAGE"/>
            </intent-filter>
        </receiver>

到目前为止,程序发出的都是标准广播。现在需要发送有序广播,需要两步:

第一步:修改MyBroadcastActivity中发送广播的源代码:

将sendBroadcast(intent,null) 改为:sendOrderedBroadcast(intent,null);

该完后的源代码如下所示:

//采用静态注册的方式
public class MyBroadcastActivity extends AppCompatActivity {
    private EditText message ;
    private Button send_message;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_broadcast_receiver);
        message = findViewById(R.id.message);
        send_message = findViewById(R.id.send_message);
        send_message.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String content = message.getText().toString();//获取输入的广播内容
                Intent intent = new Intent(); //靠intent进行数据传递
                //添加广播的action,自定义为com.kotlin.androidtest.SEND_MESSAGE,表示发送信息的广播
                intent.setAction("com.java.androidtest.SEND_MESSAGE");
                intent.putExtra("content",content);//将输入内容也传递过去
                //Android8.0以后,静态注册的BroadcastReceiver是无法接收隐式广播的,而默认情况下我们发出的自定义广播恰恰都是隐式广播。
                //因此这里一定要调用setPackage()方法,指定这条广播是发送给那个应用程序的,从而让它变成一条显示广播。否则,静态注册的BroadcastReceiver将无法接收这条广播。
                intent.setPackage(getPackageName());
                sendOrderedBroadcast(intent,null); //发送有序广播
            }
        });
    }
}

第二步:有序广播是有顺序的,并且前面的BroadcastReceiver还可以将广播截断。现在我们给广播接收者设定优先级,优先级高的先接收到广播。

修改静态注册中的代码,增加priority优先级的设定,修改后的代码如下:

        <receiver android:name=".LowBroadcastReceiver">
            <intent-filter android:priority="10"> <!--优先级设定为10-->
                <action android:name="com.java.androidtest.SEND_MESSAGE"/>
            </intent-filter>
        </receiver>
        <receiver android:name=".MyBroadcastReceiver">
            <intent-filter android:priority="100"> <!--优先级设定为100-->
                <action android:name="com.java.androidtest.SEND_MESSAGE"/>
            </intent-filter>
        </receiver>

priority的取值范围为:-1000~1000

可以看到,现在MyBroadcastReceiver的优先级高于LowBroadcastReceiver的优先级,所以广播会先发送给前者,再发送给后者。

运行后,如下所示:

 

 现在,转换二者的优先级,使MyBroadcastReceiver的优先级低于LowBroadcastReceiver的优先级。运行后,如下所示:

 

 

已经成功获取到了广播的优先级,那么终止广播需要怎么做呢?

只需要在优先级高的BroadcastReceiver中加上:abortBroadcast(),便能截断广播了。现在我们对优先级高的LowBroadcastReceiver进行修改,修改后的代码如下:

public class LowBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG ="LowBroadcastReceiver" ;
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG,"action ==>"+action);
        String content = intent.getStringExtra("content");
        Log.d(TAG,"content is = >"+content);
        abortBroadcast(); //截断广播
    }
}

运行后,日志如下:

 

 已经成功截断广播。

 

既然可以截断广播,那么可以修改广播内容再继续传递吗?

当然可以。

我们再捋一下前面逻辑:在MyBroadcastActivity中获取界面输入的内容,并通过intent来传递给下一个广播。优先级高(LowBroadcastReceiver)的优先接收到广播,优先级低(MyBroadcastReceiver)的后接收到广播。

知识点:

在发送广播时 使用 sendOrderedBroadcast的重载方法来修改广播内容。

sendOrderedBroadcast(Intent intent, receiverPermission,BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras);

对应参数的解释:
    第一个参数,意图对象,用于封装数据和设置过滤。
    第二个参数,权限
    第三个参数是广播接收者,这个广播接收者是最终接收的广播接收者,用于检查数据是否有传达或者数据被修改
    第四个参数是一个自定义的Hanlder,用于处理结果接收者,也就是上面那个接收者的回调。
    第五个参数是初始码,这个会作为结果码,通常是Activity.RESULT_OK,也就是-1。
    第六个参数是用于传递数据的,这个数据在各个Receiver里获取到,通过getResultData方法获取。
    第七个参数也是用于封装数据的,不同的是,这个用于封装数据集合,通过getResultExtras方法获取

OK,现在开始实战。

第一步:修改MyBroadcastActivity中的代码。

send_message.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String content = message.getText().toString();//获取输入的广播内容
                Intent intent = new Intent(); //靠intent进行数据传递
                Bundle bundle = new Bundle();
                //添加广播的action,自定义为com.kotlin.androidtest.SEND_MESSAGE,表示发送信息的广播
                intent.setAction("com.java.androidtest.SEND_MESSAGE");
                bundle.putCharSequence("content",content);//将输入内容也传递过去
                //Android8.0以后,静态注册的BroadcastReceiver是无法接收隐式广播的,而默认情况下我们发出的自定义广播恰恰都是隐式广播。
                //因此这里一定要调用setPackage()方法,指定这条广播是发送给那个应用程序的,从而让它变成一条显示广播。否则,静态注册的BroadcastReceiver将无法接收这条广播。
                intent.setPackage(getPackageName());
                sendOrderedBroadcast(intent,null,null,null, Activity.RESULT_OK,null,bundle);
            }
        });

可以看到,这里用bundle传递广播内容。

第二步:修改BroadcastReceiver中接收广播的内容。

public class LowBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG ="LowBroadcastReceiver" ;
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG,"action ==>"+action);
        //abortBroadcast();
        Bundle resultExtras = getResultExtras(true);
        String content = resultExtras.getCharSequence("content").toString();
        Log.d(TAG,"content is = >"+content);
        resultExtras.putCharSequence("content","我是一条被修改过的广播。");
        setResultExtras(resultExtras);
    }
}

这里我们将接收到的广播进行了修改,再往下传递。

public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG,"action ==>"+action);
        Bundle resultExtra = getResultExtras(true);
        String content = resultExtra.getCharSequence("content").toString();
        Log.d(TAG,"content is = >"+content);
    }
}

此处就是修改了一下接收广播内容的方式。

运行后,日志如下:

 

 可以看到,已经成功修改了广播内容。

posted @ 2022-08-08 16:16  虞美人体重90  阅读(608)  评论(0编辑  收藏  举报