Android移动应用开发之广播接收者
一、广播接收者简介
在Android中内置了很多广播,例如手机开机后会发送一条广播,电量不足时会发送一条广播,Android提供了一个BroadcastReceiver组件,该组件可以监听来自系统或者应用程序的广播,只需要创建一个类继承自BroadcastReceiver类,重写onReceive方法并在方法中处理广播事件即可。
二、广播接收者入门
1、广播接收者的创建
点击包,右键
创建完成后,AndroidManifest.xml如下:
package edu.hzuapps.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.content.IntentFilter;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
MyReceiver myReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//实例化广播接收者
myReceiver = new MyReceiver();
//实例化过滤器并设置要过滤的广播
String action = "android.provider.Telephony.SMS_RECEIVED";
IntentFilter intentFilter = new IntentFilter(action);
//注册广播
registerReceiver(myReceiver, intentFilter);
}
protected void OnDestroy() {
super.onDestroy();
//当Activit销毁时取消注册BroadcastReceiver
unregisterReceiver(myReceiver);
}
}
2、实战演练:电话拦截
用户界面activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="@drawable/bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/et_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="200dp"
android:textSize="20sp"
android:hint="请输入拦截号码" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/et_phone"
android:layout_centerHorizontal="true"
android:background="#ACD6FF"
android:onClick="click"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="保存拦截号码"
android:textSize="16sp" />
</RelativeLayout>
交互界面MainActivity.java:
package edu.hzuapps.interceptcall;
import androidx.appcompat.app.AppCompatActivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText editText;
private SharedPreferences sharedPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.et_phone);
//创建SharedPreferences对象来将要拦截的号码保存
sharedPreferences = getSharedPreferences("config", MODE_PRIVATE);
}
public void click(View view) {
//获取用户输入的拦截号码
String phone = editText.getText().toString().trim();
//创建Editor对象保存号码
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("phone", phone);
editor.commit();
Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
}
}
监听广播界面OutCallReceiver.java:
package edu.hzuapps.interceptcall;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
public class OutCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取当前电话号码
String outcalphone = getResultData();
//创建SharedPreferences对象获取拦截号码
SharedPreferences sharedPreferences = context.getSharedPreferences("config", Context.MODE_PRIVATE);
String phone = sharedPreferences.getString("phone", "");
if (outcalphone.equals(phone)) {
//拦截电话
setResultData(null);
}
}
}
由于外拨电话涉及权限问题,因此AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="edu.hzuapps.interceptcall">
<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=".OutCallReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<!--设置权限-->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
</manifest>
三、自定义广播
1、自定义广播的发送与接收
当自定义广播发送消息时,会存储到公共消息区中,而公共消息区中如果存在对应的广播接收者就会及时接收到这条信息。
2、实战演练:自定义广播
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:onClick="send"
android:layout_marginTop="50dp"
android:text="发送求救广播"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:background="#FFD2D2"
android:textSize="20sp" />
</RelativeLayout>
MainActivity.java:
package edu.hzuapps.forhelp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void send(View view) {
Intent intent = new Intent();
//定义广播类型
intent.setAction("Custom_broadcast");
//发送广播
sendBroadcast(intent);
}
}
MyBroadcastReceiver.java:
package edu.hzuapps.forhelp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("MyBroadcastReceiver", "自定义的广播接收者,接收到了广播事件");
Log.i("MyBroadcastReceiver", intent.getAction());
}
}
AndroidMainfest.xml:
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="Custom_broadcast" />
</intent-filter>
</receiver>
点击按钮可以看到:
四、广播的类型
1、有序广播和无序广播
(1)有序广播
无序广播是完全异步执行的,所有监听该广播的广播接收者都会受到该消息,但顺序不确定,效率较高,但无法拦截。
(2)无序广播
有序广播按照优先级被依次接受,且每次只有一个接收者几首,可被拦截。
2、实战演练:拦截有序广播
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="80dp"
android:onClick="send"
android:text="发送有序广播"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:background="#FBFBFF"
android:textSize="20sp" />
</RelativeLayout>
MainActivity.java:
package edu.hzuapps.orderedbroadcast;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void send(View view) {
Intent intent = new Intent();
//定义广播事件类型
intent.setAction("Intercept_broadcast");
//发送广播,null表示不指明权限
sendOrderedBroadcast(intent, null);
}
}
MyBroadcastReceiverOne.java:
package edu.hzuapps.orderedbroadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyBroadcastReceiverOne extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("MyBroadcastReceiverOne", "有序广播接收者One,接收到了广播事件");
}
}
MyBroadcastReceiverTwo.java:
package edu.hzuapps.orderedbroadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyBroadcastReceiverTwo extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("MyBroadcastReceiverTwo", "有序广播接收者Two,接收到了广播事件");
}
}
MyBroadcastReceiverThree.java:
package edu.hzuapps.orderedbroadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyBroadcastReceiverThree extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("MyBroadcastReceiverThr", "有序广播接收者Three,接收到了广播事件");
}
}
AndroidMainfest.xml:
<receiver android:name=".MyBroadcastReceiverOne">
<intent-filter android:priority="1000">
<action android:name="Intercept_broadcast" />
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiverTwo">
<intent-filter android:priority="200">
<action android:name="Intercept_broadcast" />
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiverThree">
<intent-filter android:priority="600">
<action android:name="Intercept_broadcast" />
</intent-filter>
</receiver>
假设要保证有一个接收者必须接收到广播(无论优先级高低),可使用sendOrderedBroadcast
在MyBroadcastReceiverOne中添加拦截者:
abortBroadcast();
Log.i("MyBroadcastReceiverOne", "广播已在此处被拦截");
在MainActivity.java中要求Two必须收到广播:
MyBroadcastReceiverTwo receiverTwo = new MyBroadcastReceiverTwo();
sendOrderedBroadcast(intent, null, receiverTwo, null, 0 ,null, null);