1.1.1引入
1.广播的生活案例
2.生活中广播特点
(1)广播发送者
(2)广播接收者
3.广播的好处
1.1.2Android中的广播
1.安卓中的广播
2.系统广播
3.广播的原理
4.广播机制
1.1.3广播接收器
1.BroadcastReceiver
2.BroadcastReceiver介绍
3.如何接收广播?
4.系统广播接收器创建步骤
关键是注册
总之,接收的事件处理逻辑放到onReceive方法中就可以。调用完onReceive方法之后就失效了。
5.发送本地广播的创建方式
1.1.4自定义广播接收器
//第一个广播 接收器
public class MyBroadcastReceiver1 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
}
}
1.1.5常见的系统权限
发短信要有发短信的权限
接收开机广播的权限
1.1.6常见的广播Action
1.1.7发送系统级广播
1.广播类型
2.创建方式
3.有序广播接收器
public final Bundle getResultExtras(boolean makeMap)
makeMap如果为true,如果当前的Bundle为null,将创建一个空的Bundle对象;否则需要准备好接收一个空Bundle对象。用的时候设置成true就行了
4.有序和无序的比较
标准 |
有序 |
异步 |
反之 |
不可以终止 |
反之 |
无法传递结果 |
反之 |
发送方式是sendBroadcast(intent) |
反之 |
1.1.8本地广播(重点)
1.优缺点
2.如何创建
3.LocalBroadcastManager
4.获取LocalBroadcastManager的实例对象
LocalBroadcastManager localBManager =
LocalBroadcastManager.getInstance( this ) ;
5.注册方式
6.创建步骤(重点)
注意:
7.取消注册的方法
两种注册方式:
1.2.1静态注册
1.注册方式
android:exported="true">
android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
扩展:在顺序广播中可以指定优先级
2.优缺点
优点:不用启动程序就可以
1.2.2动态注册
1.注册方式
2.IntentFilter的方法
No |
方法 |
类型 |
描述 |
1 |
public IntentFilter() |
构造 |
创建一个空的IntentFilter对象 |
2 |
public IntentFilter(String action) |
构造 |
创建一个IntentFilter对象,并指定Action |
3 |
public final void addAction(String action) |
普通 |
增加一个要过滤的Action |
4 |
public final void addCategory(String category) |
普通 |
增加一个要过滤的Category |
5 |
public final boolean hasAction(String action) |
普通 |
判断指定的Action是否存在 |
6 |
public final boolean hasCategory(String category) |
普通 |
判断指定的Category是否存在 |
3.取消注册
4.优缺点
优点:注册方式灵活,根据需要注册,常用于更新UI。
缺点:需要程序启动才可以接收广播,假如我们需要程序 没有启动,但是还是能接收广播的话,那么就需要注册静态广播了!
也就是广播接收器必须是启动着的。
1.2.3静态注册案例-接收开机广播
1.案例:接收开机的广播
//接收系统开机的广播事件
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "开机成功!", Toast.LENGTH_SHORT).show();
}
}
android:exported="true">
<!--接收开机广播的权限-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
1.2.4静/动态注册案例-发送广播
1.动态注册的方式发送标准广播
(1)布局文件
(2)Java代码
//点击按钮发送标准广播
public void sendBroadcast(View view) {
//设置发送的数据
Intent intent =new Intent();
intent.setAction("com.lxz.app8");
intent.putExtra("code","我是张三!");
//动态注册
IntentFilter filter=new IntentFilter();
filter.addAction("com.lxz.app8");
BroadcastReceiver1 receiver=new BroadcastReceiver1();
registerReceiver(receiver,filter);
//发送广播
sendBroadcast(intent);
}
(3)自定义广播接收器
//接收标准广播
public class BroadcastReceiver1 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收信息:"+intent.getStringExtra("code"), Toast.LENGTH_SHORT).show();
}
}
(4)效果图
2.在1的基础上设置权限
(1)manifest中定义和设置权限
(2)布局文件
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送标准广播(带权限)"
android:textSize="30dp"
android:onClick="sendBroadcast2" />
(3)发送广播的Java代码
//点击按钮发送标准广播(带权限)
public void sendBroadcast2(View view) {
//设置发送的数据
Intent intent =new Intent();
intent.setAction("com.lxz.app8");
intent.putExtra("code","我是张三!有权限!");
//动态注册
IntentFilter filter=new IntentFilter();
filter.addAction("com.lxz.app8");
BroadcastReceiver1 receiver=new BroadcastReceiver1();
registerReceiver(receiver,filter);
//设置权限
String str="com.lxz.app.permission";
//发送广播
sendBroadcast(intent,str);
}
(4)广播接收器
//接收标准广播
public class BroadcastReceiver1 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收信息:"+intent.getStringExtra("code"), Toast.LENGTH_SHORT).show();
}
}
(5)效果图
3.有序广播的测试
(1)布局文件
(2)发送有序广播的方法
//点击按钮发送有序广播
public void sendOrderBroadcast1(View view) {
//设置发送的数据
Intent intent =new Intent();
intent.setAction("com.lxz.app8");
intent.putExtra("code","请依次报号!");
//发送广播-参数2代表的是自定义的权限
sendOrderedBroadcast(intent,null);
}
(3)注册代码
android:exported="true"
>
android:exported="true"
>
android:exported="true"
>
android:exported="true"
>
(4)广播接收者
public class BroadcastOrderReceiver3 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收信息:"+intent.getStringExtra("code")+"我是3号", Toast.LENGTH_SHORT).show();
Bundle bundle=getResultExtras(true);
System.out.println("----第3个接收器---");
System.out.println("附加信息---"+bundle.getString("other"));
bundle.putString("other",bundle.getString("other")+",我是3号!");
setResultExtras(bundle);
}
}
public class BroadcastOrderReceiver2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收信息:"+intent.getStringExtra("code")+"我是2号", Toast.LENGTH_SHORT).show();
Bundle bundle=getResultExtras(true);
System.out.println("----第2个接收器---");
System.out.println("附加信息---"+bundle.getString("other"));
bundle.putString("other",bundle.getString("other")+",我是2号!");
setResultExtras(bundle);
}
}
public class BroadcastOrderReceiver1 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收信息:"+intent.getStringExtra("code")+"我是1号", Toast.LENGTH_SHORT).show();
Bundle bundle=getResultExtras(true);
System.out.println("----第1个接收器---");
System.out.println("附加信息---"+bundle.getString("other"));
bundle.putString("other",bundle.getString("other")+",我是1号!");
setResultExtras(bundle);
//停止广播的传递
abortBroadcast();
System.out.println("阻断传播");
}
}
public class BroadcastOrderReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收信息:"+intent.getStringExtra("code")+"我是0号", Toast.LENGTH_SHORT).show();
Bundle bundle=getResultExtras(true);
System.out.println("----第0个接收器---");
System.out.println("附加信息---"+bundle.getString("other"));
}
}
(5)效果图
1.2.5本地广播案例-简单的发送和接收
1.参考代码
(1)布局文件代码
(2)发送本地广播的Java代码
//发送本地广播
public void localBroadcast(View view) {
//设置数据
Intent intent=new Intent();
intent.setAction("com.lxz.localapp");
intent.putExtra("code","我是本地广播");
//动态注册
LocalBroadReceiver receiver=new LocalBroadReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("com.lxz.localapp");
LocalBroadcastManager manager=LocalBroadcastManager.getInstance(getApplicationContext());
manager.registerReceiver(receiver,filter);
//发送广播
manager.sendBroadcast(intent);
}
(3)本地广播接收者的代码
//接收本地广播
public class LocalBroadReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收信息:"+intent.getStringExtra("code"), Toast.LENGTH_SHORT).show();
}
}
(4)效果图
1.2.6本地广播案例-仿qq下线
待实现
1.案例要求
2.参考代码
(1)项目目录结构
(2)ActivityCtroller代码。
//Activity管理类
public class ActivityController {
//保存Activity
private static List<Activity> list=new ArrayList<>();
//添加Activity
public static void addActivity(Activity activity){
list.add(activity);
}
//删除Activity
public static void removeActivity(Activity activity){
list.remove(activity);
}
//结束所有的Activity
public static void finishAllActivity(){
for (Activity a:list){
if (!a.isFinishing()){
a.finish();
}
}
}
}
(3)BaseActivity,是登录成功界面的基类,可以注册BroadcastReceiver。
public class BaseActivity extends AppCompatActivity {
private LoginOutReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityController.addActivity(this);
}
@Override
protected void onResume() {
super.onResume();
//注册广播
IntentFilter filter = new IntentFilter();
filter.addAction("com.lxz.loginout");
filter.addCategory("android.intent.category.DEFAULT");
receiver = new LoginOutReceiver();
registerReceiver(receiver, filter);
}
@Override
protected void onPause() {
super.onPause();
if (receiver!=null){
unregisterReceiver(receiver);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
(4)登录界面的Activity。
//仿qq下线
public class LoginActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}
//方法:登录
public void login(View view) {
EditText account=findViewById(R.id.account);
EditText password=findViewById(R.id.password);
System.out.println(account+","+password);
if (account.getText().toString().equals("root")&&password.getText().toString().equals("123456")){
Toast.makeText(this, "登录成功!", Toast.LENGTH_SHORT).show();
Intent intent=new Intent();
intent.setClass(getApplicationContext(),LoginSuccessActivity.class);
startActivity(intent);
finish();
}
else{
Toast.makeText(this, "账号或密码错误!", Toast.LENGTH_SHORT).show();
}
}
}
(5)登录界面activity对应的布局文件。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".LoginActivity">
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:stretchColumns="1">
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:text="账号:"
android:textSize="30dp" />
<EditText
android:id="@+id/account"
android:text="root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="账号(root)"
android:inputType="text"
android:maxLines="1"
android:textSize="30dp" />
TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:text="密码:"
android:textSize="30dp" />
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码(123456)"
android:inputType="text"
android:maxLines="1"
android:text="123456"
android:textSize="30dp" />
TableRow>
TableLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="login"
android:text="登录"
android:textSize="30dp" />
LinearLayout>
(6)登录成功Activity,LoginSuccessActivity的代码。
//登录成功后的界面
public class LoginSuccessActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login_success);
//当登录后的Activity添加到管理类中去
ActivityController.addActivity(this);
}
//方法:强制下线(发布广播)
public void outlogin(View view) {
Intent intent=new Intent();
intent.setAction("com.lxz.loginout");
intent.addCategory("android.intent.category.DEFAULT");
sendBroadcast(intent);
}
}
(7)activity_login_success布局文件代码。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoginSuccessActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="outlogin"
android:text="强制下线"
android:textSize="30dp" />
LinearLayout>
(8)LoginOutReceiver广播接收器代码。
//强制下线的界面
public class LoginOutReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
AlertDialog.Builder builder=new AlertDialog.Builder(context);
builder.setTitle("Error")
.setMessage("您的账号在另外一台设备登录,程序即将回到登录界面!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityController.finishAllActivity();
Toast.makeText(context, "退出成功!", Toast.LENGTH_SHORT).show();
Intent intent1=new Intent();
intent1.setClass(context,LoginActivity.class);
context.startActivity(intent1);
}
})
;
builder.create().show(); }
}
(9)效果图
1.3.1生命周期图
1.3.2onReceive注意事项
onReceive方法中不能加入比较耗时的操作,否则系统会认为程序无响应,不要在广播里添加过多逻辑或者进行任何耗时操作,因为在广播中是不允许开辟线程的, 当onReceiver( )方法运行较长时间(超过10秒)还没有结束的话,那么程序会报错(ANR), 广播更多的时候扮演的是一个打开其他组件的角色,比如启动Service,Notification提示, Activity等。如果需要完成一项比较耗时的工作,可以通过发送Intent给Activity或Service,由Activity或Service来完成。