Android入门笔记08
广播
- 广播的概念
- 现实:电台通过发送广播发布消息,买个收音机,就能收听
- Android:系统在产生某个事件时发送广播,应用程序使用广播接收者接收这个广播,就知道系统产生了什么事件。
Android系统在运行的过程中,会产生很多事件,比如开机、电量改变、收发短信、拨打电话、屏幕解锁
IP拨号器
原理:接收拨打电话的广播,修改广播内携带的电话号码
定义广播接收者接收打电话广播
public class CallReceiver extends BroadcastReceiver {
//当广播接收者接收到广播时,此方法会调用@Overridepublic void onReceive(Context context, Intent intent) {//拿到用户拨打的号码String number = getResultData();//修改广播内的号码setResultData("17951" + number);}
}
在清单文件中定义该广播接收者接收的广播类型
<receiver android:name="com.itheima.ipdialer.CallReceiver"><intent-filter ><action android:name="android.intent.action.NEW_OUTGOING_CALL"/></intent-filter></receiver>
接收打电话广播需要权限
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
即使广播接收者的进程没有启动,当系统发送的广播可以被该接收者接收时,系统会自动启动该接收者所在的进程
短信拦截器
系统收到短信时会产生一条广播,广播中包含了短信的号码和内容
定义广播接收者接收短信广播
public void onReceive(Context context, Intent intent) {//拿到广播里携带的短信内容Bundle bundle = intent.getExtras();Object[] objects = (Object[]) bundle.get("pdus");for(Object ob : objects ){//通过object对象创建一个短信对象SmsMessage sms = SmsMessage.createFromPdu((byte[])ob);System.out.println(sms.getMessageBody());System.out.println(sms.getOriginatingAddress());}
}
系统创建广播时,把短信存放到一个数组,然后把数据以pdus为key存入bundle,再把bundle存入intent
清单文件中配置广播接收者接收的广播类型,注意要设置优先级属性,要保证优先级高于短信应用,才可以实现拦截
<receiver android:name="com.itheima.smslistener.SmsReceiver"><intent-filter android:priority="1000"><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>
添加权限
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
4.0以后广播接收者安装以后必须手动启动一次,否则不生效
4.0以后广播接收者如果被手动关闭,就不会再启动了
监听SD卡状态
清单文件中定义广播接收者接收的类型,监听SD卡常见的三种状态,所以广播接收者需要接收三种广播
<receiver android:name="com.itheima.sdcradlistener.SDCardReceiver"><intent-filter ><action android:name="android.intent.action.MEDIA_MOUNTED"/><action android:name="android.intent.action.MEDIA_UNMOUNTED"/><action android:name="android.intent.action.MEDIA_REMOVED"/><data android:scheme="file"/></intent-filter></receiver>
广播接收者的定义
public class SDCardReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// 区分接收到的是哪个广播String action = intent.getAction();if(action.equals("android.intent.action.MEDIA_MOUNTED")){System.out.println("sd卡就绪");}else if(action.equals("android.intent.action.MEDIA_UNMOUNTED")){System.out.println("sd卡被移除");}else if(action.equals("android.intent.action.MEDIA_REMOVED")){System.out.println("sd卡被拔出");}}}
勒索软件
接收开机广播,在广播接收者中启动勒索的Activity
清单文件中配置接收开机广播
<receiver android:name="com.itheima.lesuo.BootReceiver"><intent-filter ><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver>
权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
定义广播接收者
@Overridepublic void onReceive(Context context, Intent intent) {//开机的时候就启动勒索软件Intent it = new Intent(context, MainActivity.class); context.startActivity(it);}
以上代码还不能启动MainActivity,因为广播接收者的启动,并不会创建任务栈,那么没有任务栈,就无法启动activity
手动设置创建新任务栈的flag
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
监听应用的安装、卸载、更新
原理:应用在安装卸载更新时,系统会发送广播,广播里会携带应用的包名
清单文件定义广播接收者接收的类型,因为要监听应用的三个动作,所以需要接收三种广播
<receiver android:name="com.itheima.app.AppReceiver"><intent-filter ><action android:name="android.intent.action.PACKAGE_ADDED"/><action android:name="android.intent.action.PACKAGE_REPLACED"/><action android:name="android.intent.action.PACKAGE_REMOVED"/><data android:scheme="package"/></intent-filter></receiver>
广播接收者的定义
public void onReceive(Context context, Intent intent) {//区分接收到的是哪种广播String action = intent.getAction();//获取广播中包含的应用包名Uri uri = intent.getData();if(action.equals("android.intent.action.PACKAGE_ADDED")){System.out.println(uri + "被安装了");}else if(action.equals("android.intent.action.PACKAGE_REPLACED")){System.out.println(uri + "被更新了");}else if(action.equals("android.intent.action.PACKAGE_REMOVED")){System.out.println(uri + "被卸载了");}}
广播的两种类型
- 无序广播:所有跟广播的intent匹配的广播接收者都可以收到该广播,并且是没有先后顺序(同时收到)
- 有序广播:所有跟广播的intent匹配的广播接收者都可以收到该广播,但是会按照广播接收者的优先级来决定接收的先后顺序
- 优先级的定义:-1000~1000
- 最终接收者:所有广播接收者都接收到广播之后,它才接收,并且一定会接收
- abortBroadCast:阻止其他接收者接收这条广播,类似拦截,只有有序广播可以被拦截
#Service
- 就是默默运行在后台的组件,可以理解为是没有前台的activity,适合用来运行不需要前台界面的代码
- 服务可以被手动关闭,不会重启,但是如果被自动关闭,内存充足就会重启
- startService启动服务的生命周期
- onCreate-onStartCommand-onDestroy
- 重复的调用startService会导致onStartCommand被重复调用
进程优先级
- 前台进程:拥有前台activity(onResume方法被调用)
- 可见进程:拥有可见activity(onPause方法被调用)
- 服务进程:不到万不得已不会被回收,而且即便被回收,内存充足时也会被重启
- 后台进程:拥有后台activity(activity的onStop方法被调用了),很容易被回收
- 空进程:没有运行任何activity,很容易被回收
电话窃听器
电话状态:空闲、响铃、接听
获取电话管理器,设置侦听
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);tm.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
侦听对象的实现
class MyPhoneStateListener extends PhoneStateListener{//当电话状态改变时,此方法调用@Overridepublic void onCallStateChanged(int state, String incomingNumber) {// TODO Auto-generated method stubsuper.onCallStateChanged(state, incomingNumber);switch (state) {case TelephonyManager.CALL_STATE_IDLE://空闲if(recorder != null){recorder.stop();recorder.release();}break;case TelephonyManager.CALL_STATE_OFFHOOK://摘机if(recorder != null){recorder.start();}break;case TelephonyManager.CALL_STATE_RINGING://响铃recorder = new MediaRecorder();//设置声音来源recorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置音频文件格式recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);recorder.setOutputFile("sdcard/haha.3gp");//设置音频文件编码recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);try {recorder.prepare();} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}break;}}}
服务两种启动方式
- startService:服务被启动之后,跟启动它的组件没有一毛钱关系
- bindService:跟启动它的组件同生共死
- 绑定服务和解绑服务的生命周期方法:onCreate->onBind->onUnbind->onDestroy
找领导办证
把服务看成一个领导,服务中有一个banZheng方法,如何才能访问?
绑定服务时,会触发服务的onBind方法,此方法会返回一个Ibinder的对象给MainActivity,通过这个对象访问服务中的方法
绑定服务
Intent intent = new Intent(this, BanZhengService.class);bindService(intent, conn, BIND_AUTO_CREATE);
绑定服务时要求传入一个ServiceConnection实现类的对象
定义这个实现类
class MyServiceconn implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {zjr = (PublicBusiness) service;}@Overridepublic void onServiceDisconnected(ComponentName name) { }
}
创建实现类对象
conn = new MyServiceconn();
在服务中定义一个类实现Ibinder接口,以在onBind方法中返回
class ZhongJianRen extends Binder implements PublicBusiness{public void QianXian(){//访问服务中的banZheng方法BanZheng();} public void daMaJiang(){}
}
把QianXian方法抽取到接口PublicBusiness中定义
两种启动方法混合使用
- 用服务实现音乐播放时,因为音乐播放必须运行在服务进程中,可是音乐服务中的方法,需要被前台Activity所调用,所以需要混合启动音乐服务
- 先start,再bind,销毁时先unbind,在stop
使用服务注册广播接收者
Android四大组件都要在清单文件中注册
广播接收者比较特殊,既可以在清单文件中注册,也可以直接使用代码注册
有的广播接收者,必须代码注册
- 电量改变
- 屏幕锁屏和解锁
注册广播接收者
//创建广播接收者对象receiver = new ScreenOnOffReceiver();//通过IntentFilter对象指定广播接收者接收什么类型的广播IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_SCREEN_ON);//注册广播接收者registerReceiver(receiver, filter);
解除注册广播接收者
unregisterReceiver(receiver);
解除注册之后,广播接收者将失去作用
本地服务:服务和启动它的组件在同一个进程
远程服务:服务和启动它的组件不在同一个进程
- 远程服务只能隐式启动,类似隐式启动Activity,在清单文件中配置Service标签时,必须配置intent-filter子节点,并指定action子节点
AIDL
- Android interface definition language
- 安卓接口定义语言
- 作用:跨进程通信
- 应用场景:远程服务中的中间人对象,其他应用是拿不到的,那么在通过绑定服务获取中间人对象时,就无法强制转换,使用aidl,就可以在其他应用中拿到中间人类所实现的接口
支付宝远程服务
- 定义支付宝的服务,在服务中定义pay方法
- 定义中间人对象,把pay方法抽取成接口
- 把抽取出来的接口后缀名改成aidl
- 中间人对象直接继承Stub对象
- 注册这个支付宝服务,定义它的intent-Filter
需要支付的应用
- 把刚才定义好的aidl文件拷贝过来,注意aidl文件所在的包名必须跟原包名一致
- 远程绑定支付宝的服务,通过onServiceConnected方法我们可以拿到中间人对象
- 把中间人对象通过Stub.asInterface方法强转成定义了pay方法的接口
- 调用中间人的pay方法
五种前台进程
- activity执行了onresume方法,获得焦点
- 拥有一个跟正在与用户交互的activity绑定的服务
- 拥有一个服务执行了startForeground()方法
- 拥有一个正在执行onCreate()、onStart()或者onDestroy()方法中的任意一个的服务
- 拥有一个正在执行onReceive方法的广播接收者
两种可见进程
- activity执行了onPause方法,失去焦点,但是可见
- 拥有一个跟可见或前台activity绑定的服务
Android入门笔记08相关推荐
- Android入门笔记之更改手机屏幕方向
Android入门笔记之更改手机屏幕方向 <1>简介 通过一个按钮组来改变横屏竖屏显示. <2>关键步骤 主要通过android.app.activity.getRequest ...
- ESP32 入门笔记08:1.54寸(240*240)彩色TFT 显示高清IPS LCD 屏幕 SPI接口
目录 1.屏幕规格 2.原理图 3.程序实现 3.1引脚定义 3.2Adafruit_GFX / Arduino_ST7789版 3.3TFT_eSPI库版 3.3.1配置TFT_eSPI a.选择屏 ...
- Android Studio 基础入门笔记
Android Studio 基础入门笔记 Android Studio 基础入门笔记 为什么选择使用 Android Studio 而不是EclipseADT 安卓配置JDK AS如何更新 常规的 ...
- Android 插件化原理入门笔记
Android开发笔记 onGithub 笔记,参考7.2中所列参考文章所写,DEMO地址在PluginTestDemoApplication 1.综述 2015年是Android插件化技术突飞猛进的 ...
- Android入门自学笔记
Android入门 前几个月要去作物联网项目,花了一个月入门android本文写于物联网大赛后 Android入门所需书籍 <android第一行代码>-----入门必看书.这本书实例和理 ...
- MyBatis-学习笔记08【08.动态SQL】
Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...
- ROS入门笔记(七):详解ROS文件系统
ROS入门笔记(七):详解ROS文件系统 文章目录 01 Catkin编译系统 1.1 Catkin特点 1.2 Catkin工作原理 1.3 使用`catkin_make`进行编译 02 Catki ...
- go web框架_golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web
micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go- ...
- Android开发笔记(序)写在前面的目录
知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...
- Android开发笔记(一百一十六)网络学习资源
知名网站 本系列的开发笔记,对Android开发来说只是沧海一瓢,还有更多的技术等待我们去汲取.下面列出几个常用的开发网站,供初学者上路: 首先当然是国内首屈一指的技术网站csdn啦,csdn提供了众 ...
最新文章
- ​kdevelop用法_weixin_44594953的博客-CSDN博客_kdevelop​
- 科大星云诗社动态20210217
- 记录下UIButton的图文妙用和子控件的优先显示
- [COGS58] 延绵的山峰
- 20140625 程序 进程 线程 物理存储器
- c++ 每半个小时打印一次_有了3D打印机,后期该如何维护呢
- Promise机制(持续更新中)
- 温故而知新:查看端口占用情况以及DOS中的管道操作/重定向操作
- XP照片缩略图和照片本身显示不一致,如何解决防范?
- 15.3 实时时钟芯片DS1302介绍
- java 追加文件换行_java 追加换行txt
- typora主题配置:公众号一键排版
- meanshift算法通俗讲解
- D. Lizard Era: Beginning
- 海康威视监控下载下来的mp4格式的视频,小类别MPEG-PS格式,这种格式在浏览器中没法播放,跪求播放方法。
- mysql子查询返回多于1行_mysql – 子查询返回超过1行
- 3.识别AP版本与胖转瘦
- Python:python镜像源汇总及使用
- 我的一加5刷机基本步骤
- vs code 不能正确补全结构体成员变量的解决方法
热门文章
- 数据bag中的激光雷达数据和相机数据分割出来
- Advances in adversarial attacks and defenses in computer vision: A survey论文解读
- FM、LFM、AFM、NFM、DeepFM、 Deep Cross Network
- Storm目录树、任务提交、消息容错、通信机制
- C#的GC机制(来自网摘复制,未整理)
- 字符串输入控制:与空格、回车的输入相关的几种函数
- 了解:shell脚本+脚本优化+脚本注入+正则表达式
- 开源大数据周刊-第74期
- 资金流学习 - 关注点
- 编程十年 (3):初识计算机