写在前面的话
1、主要参考自:https://b23.tv/Flmxaa
2、内容如果有不对的,希望可以指出或补充。
3、新知识。
一、广播
(一)广播接收者
① 概述
广播接收者(BroadcastReceiver):Android系统中内置了很多广播,列如手机的开机完成、电池电量不足时都会发送一条广播。为了监听来自系统或者应用程序的广播事件,Android系统提供了广播接收者组件(四大组件之一)。当Android系统产生一个广播事件时,可以有多个对应的广播接收者接收并进行处理
。相当于是接收电台消息的收音机。
特点:一对多(如一个电台的发出的频率,可以被多个收音机接收到),消息是单向的(如收音机只能接收消息)。
② 测试
1 创建广播接收者。
2 动态注册广播接收者-创建
静态的注册:系统一般会自动创建,在项目清单文件里。
动态注册的特点:只有当注册广播接收者的组件活着的时候(存在),对应的广播接收者才会接收到广播,这也是和静态注册的区别所在。
3 测试-拦截电话
① 布局
② 代码部分
③ 运行效果
项目清单文件
如下:
(二)自定义广播的发送与接收
① 概述
当系统提供的广播不能满足需求时,可以自定义广播(发送消息),同时需要编写对应的广播接收者(监听消息)。
当自定义广播发送消息时,会存储到公共消息区中,而公共消息区中如果存在对应的广播接收者,就会及时的接收这条消息
。
② 测试
1 布局以及MainActivity.java内容
2 测试效果
和上面的测试一样的道理,处理项目清单文件(声明自定义的广播事件的意图)
运行结果:
(三)有序广播和无序广播
① 概述
Android系统提供了两种广播类型,有序广播和无序广播,开发者可根据需求为程序设置不同的广播类型。
有序广播:按照接收者的优先级接收,只有一个广播接收者能接收到消息,在此广播接收者中逻辑执行完毕后,才会继续传递
。
无序广播:是完全异步执行
,发送广播时所有监听这个广播的广播接收者都会接收到此消息,但接收的顺序不确定。
有序广播可以被拦截;无序广播所有的广播接收者都可以接收到消息
。
② 测试-有序广播
需要新建三个广播接收者,以便更好的测试。这三个广播接收者的设置都差不多,如:
1 布局略
2 运行效果
项目清单文件
效果如下:
注:如果priority的数值相同(优先级一样),那么就是在项目清单文件中最先声明(位置在前面的)先收到消息。如果把高优先级的广播中断了(在广播接收者里编写 拦截有序广播:abortBroadcast();
),优先级较低的就不会再收到消息了,但有方法(如下图-在发送方法里编写)可以强制广播接收者接收到消息。
二、服务
Day12内容。
服务(Service)也是四大组件之一,可将它看作是一个没界面的activity(一般用于后台操作,如手机息屏后音乐的播放)。
最大的特点:可在后台长时间运行。
(一)基础知识
创建:同广播接收者的创建类似(在程序包名上右击选择【New】→【Service】→【Service】→在弹出的窗口中输入服务名称或默认即可);若采用自行创建Java类继承Service类的方式创建服务,则需要手动在项目清单文件中进行注册。
生命周期:也就是它从启动到关闭所经历的一个过程。转↓
启动方式:
① 通过startService()方法:服务会长期运行在后台,且服务的状态与开启者的状态无关,也就是即使启动服务的组件已被销毁,服务会依旧运行。需要自身调用stopSelf()方法或其他组件调用stopService()方法时服务才能停止
。
② 通过bindService()方法:服务会与组件绑定。需要调用onUnbind()方法解除绑定之后才会被销毁
。注:如果要长期存在,就需要在绑定之前用startService启动服务(结合使用)。
(二)测试
① startService启动Service
1 布局
2 服务类
3 展示结果
总结:onCreate()表示的是当服务创建的时候执行(创建成功了就不会再有作用了),只调用一次;多次执行开启服务(只要服务还是启动着的)会多次调用onStartCommand()且只是复用前面产生的service对象,不会新建新service对象;onDestroy()表示的是关闭服务,同onCreate()一样的道理,只调用一次。
② bindService启动Service
1 布局略(与①的布局设置同理)
2 代码
① MyService.java
在OnBind()方法中需要返回一个IBinder的实例,否则监听连接状态的方法就不会调用。
package com.example.testservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
public MyService() { }
//定义onBinder方法所返回的对象实例
//创建服务代理 调用服务中的方法
class MyBinder extends Binder{
//可以间接调用到service里面的相关方法
public void callTestInService(){
testInService();
}
}
public void testInService(){
Log.i("MyService","自定义方法,testInService()");
}
@Override
//IBinder是一个接口 可进行跨进程访问(远程调用)
public IBinder onBind(Intent intent) {
Log.i("MyService","绑定服务,调用onBind()");
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
Log.i("MyService","创建服务,调用onCreate()");
}
@Override
//解绑
public boolean onUnbind(Intent intent) {
Log.i("MyService","解绑服务,调用onUnbind()");
return super.onUnbind(intent);
}
}
② MainActivity.java
package com.example.testservice;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private MyService.MyBinder myBinder;
private MyTest mytest;
@Override
//自带
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//绑定(开启)服务
public void btnBind(View view){
if(mytest == null){
mytest = new MyTest();
}
Intent intent = new Intent(this,MyService.class);
//参数1:用于指定要启动的service,参数2:监听调用者与service间的连接状态,
// 参数3:指定绑定时是否自动创建service
bindService(intent,mytest,BIND_AUTO_CREATE);
}
//服务连接时执行
private class MyTest implements ServiceConnection{
@Override
//当成功绑定服务时调用,返回MyService里面的Ibinder对象
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;
Log.i("MainActivity","服务成功绑定,内存地址为:"+myBinder.toString());
}
//当服务失去连接时,调用的方法
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("MainActivity","服务失去连接");
}
}
//调用服务中的方法
public void btnCall(View view){
//访问到MyService里的callTestInService()方法
myBinder.callTestInService();
}
//解绑服务
public void btnUnbind(View view){
//需要判断是因为:解除绑定时就需要接收ServiceConnection
if(mytest != null){
unbindService(mytest);
mytest = null;
}
}
}
3 展示结果
总结:多次启动服务,onBind()只被调用一次。
三、补充
1、Android的四大组件,只要被定义了,就必须在AndroidManifest.xml(清单文件)中注册。一般,系统都会自动注册。