• 返回首页

    Android笔记——By Bug

    前言

    相关配置下载 下载 Android Studio 和应用工具 - Android 开发者 | Android Developers (google.cn)

    笔记的IDE版本信息如下 Android Studio Koala Feature Drop | 2024.1.2 Build #AI-241.18034.62.2412.12266719, built on August 23, 2024 Runtime version: 17.0.11+0--11852314 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 10.0 GC: G1 Young Generation, G1 Old Generation Memory: 2048M Cores: 20 Registry: ide.experimental.ui=true Non-Bundled Plugins: com.intellij.zh (241.271) com.github.tuchg.nonasciicodecompletionhelper (1.0.1)

    参考资料

    【2022 最新 Android 基础教程,从开发入门到项目实战,看它就够了,更新中】 https://www.bilibili.com/video/BV19U4y1R7zV/?p=2&share_source=copy_web&vd_source=ea0cf64e8dac6f0193a7e28187a0fccb

     

    介绍

    注意事项

    这个版本创建项目时,如需要使用Java语言编写,需要选择No Activity或Empty Viue Activity

    日志信息介绍

    运行调试APP应用

    App开发语言

    APP开发两大技术路线

    1. 原生开发

    2. 混合开发

    Android官方编程语言:Java,kotlin

    工程目录介绍

    创建新页面

     

    简单控件

    文本显示

    视图基础

     

     

    常用布局

    线性布局LinearLayout

    相对布局RelativeLayout

    相对布局的下级视图位置由其他试图决定,用于确定下级视图位置的参考物分为以下两种

    如果不设定下级视图的参照物,那么下级视图默认显示在RelativeLayout 内部的左上角

    网格布局GridLayout

    image-20240910185936287

     

    滚动视图ScrollView

    滚动视图有两种

     

     

    按钮触控

    Button

    Button新增两个属性如下

    在android开发中,把控件的初始化放到onCreate方法里面

     

    点击事件

    监听器:专门监听控件的动作行为,只有控件发生了指定的动作,监听器才会触发开关,去执行对应的代码逻辑

    点击监听器:setOnClickListener()方法设置,按钮被按住少于500ms,会触发点击事件

    案例:点击按钮,在文本框中显示内容

     

    长按事件

    长按监听器:setOnLongClickListener()方法设置,按钮被按住超过500ms,会触发长按事件

    案例:同上

     

    禁用和恢复按钮

    按钮是否允许点击使用enabled属性控制,属性为true代表允许点击,false代表禁止点击。

    案例:点击开始按钮,启用解锁按钮,点击解锁按钮,启用显示按钮,点击显示按钮,在文本框显示时间

     

    图像显示

    ImageView

    图像视图缩放类型 使用 android:scaleType=""属性设置图片的缩放类型

    XML缩放类型ScaleType类中的缩放类型说明
    fitXYFIT_XY拉伸图片填满视图(会导致图片变形)
    fitStartFIT_START保持宽高比,使其位于视图上方或左侧
    fitCenterFIT_CENTER保持宽高比,使其位于视图中间
    fitEndFIT_END保持宽高比,市区位于视图下方或右侧
    centerCENTER保持图片原尺寸,并使其位于视图中间
    centerCropCENTER_CROP拉伸图片充满视图,并位于视图中间
    CenterInsideCENTER_INSIDE保持宽高比,缩小图片使其位于视图中间(只缩小,不放大)

     

    ImageButton

    ImageButton是显示图片的图像按钮,但它继承自ImageView,而非继承Button

    ImageButton和Button的区别有:

    同时展示文本和图像

    展示文本图像途径

    1. 利用LinearLayout对ImgView和TextView组合

    2. 通过按钮控件Button和drawable属性设置文本周围的图标

      • drawableTop:指定文字上方的图片

      • drawableBottom:指定文字下方的图片

      • drawableLeft:指定文字左边的图片

      • drawableRight:指定文字右边的图片

      • drawablePadding:指定文字和图片的间距

     

    案例:计算器

    需求: image-20240919210157419

    需求描述:计算器的界面分为两大部分,第一部分是上方的计算表达式,既包括用户的按键输入,也包括计算结果数字;第二部分是下方的按键,例如:从0-9的数字按钮,加减乘除等号、正负号按钮,小数点按钮,求倒数按钮、平方按钮、开关按钮,以及退格、清空、取消等按钮。

     

    布局方式分析:

    页面设计

     

    逻辑处理

     

    activity生命周期

    activity启动与停止

    启动

    停止

     

    activity生命周期

    0_13112984810hZH

    生命周期方法

    各状态之间的切换

    onCreate
    onDestory
    onStart
    onStop
    onResume
    onPause
    不存在
    初始状态
    就绪状态
    活跃状态

     

    activity启动模式

    在代码中设置启动标志

     

    Intent(意图)

    Intent时各个组件之间信息沟通的桥梁,它是Android各组件之间的通信,主要完成下面的工作

    Intent的组成

    名称设置方法说明
    ComponentsetComponent()组件,指定意图的来源和目标
    ActionsetAction()动作,指定意图的动作行为
    DatasetData()Uri,指定动作要操作的数据路径
    CategoryaddCategory()类别,指定意图的操作类别
    TypesetType()数据类型,指定消息的数据类型
    ExtrasputExtras()扩展信息,指定装在的包裹信息
    FlagssetFlags()标志位,指定活动的启动标志

     

    显式Intent

    直接指定来源活动和目标活动,属于精准匹配,它有三种构建方式

     

    隐式Intent

    没有明确指定要跳转的目标活动,只给出一个动作字符串,让系统自动匹配,属于模糊匹配

    比如从应用中打开系统的拨号,短信等界面

    常见的系统动作

     

    向下一个Activity发送数据

    Intent使用Bundle对象存放待传递的数据信息

    Bundle对象操作各类数据的方法:

    数据类型读方法写方法
    整数型getIntputInt
    浮点型getFloatputFloat
    双精度数getDoubleputDouble
    布尔值getBooleanputBoolean
    字符串getStringputString
    字符串数组getStringArrayputStringArray
    字符串列表getStringArrayListputStringArrayList
    可序列化结构getSerializableputSerializable

     

    向上一个Activity返回数据

    处理下一个页面的应答数据如下:

    替代:

     

    利用资源文件配置字符串

    从string.xml文件中获取字符串

     

    利用元数据传递配置信息

    将数据写到清单文件中

    使用场景:使用第三方sdk,存储sdk提供服务的token

    在代码中获取元数据步骤:

     

    给页面注册快捷方式

    元数据不仅能传递简单的字符串,还能传递更加复杂的资源数据,比如:支付宝的快捷方式菜单(效果:支付宝桌面图标长按,会出现一个快捷方式菜单。)

    步骤:

    1. 创建一个xml文件

       

    2. 在清单文件中设置meta-data

     

     

    中级控件

    图形定制

    图形Drawable

    Android把所有能够显示的图形都抽象为Drawable类,这里的图形不只是图片,包括色块,画板,背景等。 包含图片在内的图形文件放在res目录下的drawable目录下。

     

    形状图形

    定义:这是一种在 XML 文件中定义的通用形状。

    文件位置:res / drawable / filename.xml

    形状类型说明
    rectangle圆环
    oval椭圆,此时corners失效
    line直线,必须设置stroke,否则报错
    ring圆环
    属性说明
    corners标签是用来字义圆角的,其中radius与其它四个可以共同使用,但其它四个优先级更高。
    gradient用以定义渐变色,可以定义两色渐变和三色渐变,及渐变样式,它的优先级高于solid,同时定义时显示gradient定义的效果。
    padding用来定义内部边距
    size是用来定义图形的大小
    solid用以指定内部填充色
    stroke描边属性,可以定义描边的宽度,颜色,虚实线等

    例子:有一个圆角矩形,一个椭圆形,点击按钮,切换图像的形状

     

    九宫格图片

    描述:将某张图片设置成视图的背景时,如果图片的尺寸太小,系统会自动拉伸填满背景,一旦图片拉伸过大,画面就容易变得模糊

    图片后缀名:xxx.9.png

    创建方法:

    1. 将图片引入项目

    2. 右键图片,在菜单中选择Create-9-Patch选项,可以将图片转换成九宫格图片(如果不是Png格式的图片,需要先将图片转换成Png格式)

     

    状态列表形状

    样例:按钮按下和抬起,分别是两种样式

    定义selector

    状态类型取值

    属性名称说明适用的控件
    state_pressed是否按下按钮Button
    state_checked是否勾选复选框CheckBox,单选按钮RadioButton
    state_focused是否获取焦点文本编辑框EditText
    state_selected是否选中各控件通用

     

    选择按钮

    CheckBox,Switch,RadioButton都继承自CompoundButton,CompoundButton类是抽象的复合按钮。因为它是抽象类,不能直接创建对象。

    复选框CheckBox

    一般使用原生的样式,不够美观,我们一般采用定制的样式,例如更换选择框的图标形状,选中和非选中为两种样式。 定制样式:

    在布局文件中,修改多选框的button属性,引用定制好的样式

     

    如果想要修改选中框为自己的图片样式,可以使用以下的方法

    为复选框添加事件监听

     

     

    开关按钮Switch

    按钮Switch在选中和取消时,可展现的界面元素比复选框更加丰富

    switch控件新添加的xml属性:

    开关按钮的使用方法

    自定义开关按钮的样式

     

    单选按钮RadioButton

    RadioGroup实质上是一个布局,可以设置按钮的排列方向,同一组RadioButton都要放在同一个RadioGroup下,除了RadioButton。也可以放其他控件

     

    文本输入

    编辑框EditText

    相关属性

     

    自定义边框样式

    定义一个形状,圆角矩形

    样式文件:

    引入

     

    文本变化监听器

    需求:用户输入手机号码,校验手机号码是否合法

    焦点变更监听器

     

    对话框

    提醒对话框AltertDialog

     

    日期对话框DatePickerDialog

    虽然文本编辑框有提供data格式的输入数据,但一般不使用其获取日期输入

    DatePicker日期组件

    DatePickerDialog日期弹窗

     

    时间对话框TimePickerDialog

    时间组件TimePicker

    时间对话框TimePickerDialog

     

    案例:登录和找回密码页面

    image-20241126225739028

    需求描述

    页面布局代码

    逻辑处理代码

     

    数据存储

    共享数据SharedPreferences

    共享参数用法

    介绍

    使用场景

     

    数据库SQLite

    SQLite是一种小巧的嵌入式数据库,使用方便,开发简单。属于轻型数据库。

    数据库详细笔记,请参阅主页的:《MySQL学习笔记》

    SQL基础语法

    数据定义语言
    1. 创建表格 创建表格使用create命令完成,格式:create table if not exists 表名; 比如创建一个用户信息表

      • SQL语句不区分大小写

      • SQLite支持整型integer,长整型LONG,字符串VARCHAR,浮点型FLOAT,但不支持布尔型!如果直接保存布尔类型,在存入数据库时,会自动将true转换成1,false转换成0,进行存储

      • 建表时需要加上唯一标识字段ID

    2. 删除表格 格式:drop table if exists 表名; 例如:删除用户表

    3. 修改表结构 修改表结构使用alter命令,但是在SQLite中,只支持增加字段,不支持删除和修改字段。

      语法:alter table 表名 add column 字段名 字段类型; 例如:在用户中添加体重字段

       

    数据操纵语言

    插入数据格式:insert into 表名 字段名 values 字段名

    删除数据格式:delete from 表名 where 字段名 ="值"

    修改数据格式:update name set 字段名 ="值" from 表名 where 字段名 ="值";

    查询数据格式:select 字段名列表 from 表名 where 查询条件;

     

    数据库管理SQLiteDatabase

    SQLiteDatabase是SQLite数据库管理类,它提供了若干操作数据表的API,常用的方法分为三类

    1. 管理类:用于数据库层面的操作

      • openDatabase:打开指定路径的数据库

      • isOpen:判断数据库是否打开。

      • close:关闭数据库

      • getVersion:获取数据库的版本号

      • setVersion:设置数据库的版本号

       

    2. 事务类,用于事务层面的操作

      • beginTransaction:开始事务

      • setTransaction:设置事务成功的标志

      • endTransaction:结束事务

      事务的四大特性|ACID(⭐)

      • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。

      • 一致性(Consistency):事务完成时,必须使所有数据都保持一致状态。

      • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。

      • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

       

    3. 数据处理类。用于数据层面的操作

      • execSQL:执行拼接好的SQL控制语句

      • delete:删除符合条件的记录

      • update:更新符合条件的记录

      • query:执行查询操作,返回结果集的游标

      • rewQuery:执行拼接好的SQL查询语句,返回结果集的游标

      • (相关操作代码见下SQLiteOpenHelper演示代码)

     

    数据库帮助器SQLiteOpenHelper

    SQLiteOpenHelper是Android提供的数据库辅助工具,用于指导开发者进行SQLite的合理使用

    SQLiteOpenHelper使用步骤如下

     

    使用演示(插入数据)相关代码:

     

    数据库升级

    当数据库版本发生变化时,会执行此该函数

    存储卡的文件操作

    私有空间和公共空间

    Android把外部存储分为两部分,一部分为所用应用都能访问的公共空间,另外一部分为只有应用自己才能访问的私有空间。

     

    在存储卡上读写文本文件

    读写文件的工具类

     

    注意!:保存至私有空间在软件卸载后将被删除,而保存在公共空间下的文件则不会被删除

     

    在存储卡上读写图片文件

    操作实例代码

    java代码

    布局代码

     

    应用组件Application

    Application生命周期

    Application是Android的一大组件,在app运行过程稿,有且只有一个Application对象贯穿整个生命周期。

    1. onConfigurationChanged( ) :在配置被改变时触发 。

    2. onCreate() :在程序创建时创建。

    3. onLowMemory() :内存不够时触发。

    4. onTerminate() :当终止程序时调用 但是不能保证一定调用

    5. onTrimMemory() :在内存清理时触发

    使用 首先创建一个Application对象

    重写对应的方法

     

    利用Application操作全局变量

    全局即其他代码都可以引用该变量,因此全局变量时共享数据和传递消息的好帮手

    在Application适合保存以下类型的数据

    1. 会频繁读取的信息,例如:用户名,手机号等信息

    2. 不方便通过意图进行传递的数据,例如:位图对象,非字符串类型的集合对象等

    3. 容易因频繁分配导致内存泄漏的对象,如Handler对象等

     

    自定义的Application

    ApplicationActivity

    扩展: 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

    这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

    单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。

     

    利用Room简化数据库操作

    以录入书籍信息为例,使用Room框架编码分为以下五部:

    1. 编写书籍信息表对应的实体类,该类添加"@Entity"注解

    2. 编写书籍信息表对应的持久化类,添加@“Dao”注解

    3. 编写书籍信息表对应的数据库类,该类从RoomDatabase派生而来,并添加”@Database“注解

    4. 在自定义的Application类中声明数据库的唯一实例

    5. 在操作书籍信息表的地方,获取数据表的持久化对象

     

    实例:对图书数据库进行增删改查操作 界面布局代码

    book实体类

    数据持久化类

    数据库类

    在自定义的Application类中声明数据库的唯一实例

    activity逻辑代码

     

    案例:购物车(待补)

    需求描述

     

    页面设计代码

     

    逻辑处理代码

     

     

    内容提供者

    在应用之间共享数据

    展示案例,一个服务端应用,一个客户端应用,客户端应用向服务端应用传递数据,服务端数据将数据存入到数据库等位置。

    ContentProvider封装数据

    ContentProvider为App存取内部数据提供统一的外部接口,让不同应用之间得以共享数据

    ContentResolver访问数据

    利用ContentProvider只实现服务端App的数据封装,如果客户端App想要访问对方内部的数据,就要通过内容解析器ContentResolver进行访问。

     

    使用内容组件获取通信信息

    在运行时动态申请权限

    Android系统为了防止一些App滥用权限,从6.0开始引入了运行时权限管理机制,允许App在运行过程中动态检查是否拥有某项权限,一旦发现缺少某项必须权限,则系统会自动弹出小窗提示用户开启权限。

    动态申请权限的步骤

    1. 检查App是否开启了指定权限 调用ContextCompat的checkSelfPermission方法

    2. 请求系统弹窗,以便用户选择是否开启权限 调用ActivityCompat的requestPermissions方法,即可命令系统自动弹出权限申请窗口

    3. 判断用户选择的结果 重写活动页面的权限请求回调方法onRequestPermissionsResult,在该方法内部处理权限选择的结果。

     

    ContentResolver读写联系人

     

    ContentObserver监听短信

    内容观察器ContentObserver给目标内容注册一个观察器,目标内容一旦发生改变,观察器规定好的逻辑动作将被触发,从而执行开发者预先设计的代码。

     

    ContentObserver还可以对自己的内容进行监听。

     

    应用之间共享文件

    从相册选择图片

     

    通过MediaStore查询图片

     

    FileProvider

    应用通常需要将自己的一个或多个文件提供给其他应用。例如,图库可能需要向图片编辑器提供文件,或者文件管理应用可能需要允许用户在外部存储设备中的区域之间复制和粘贴文件。发送方应用可以通过响应来自接收方应用的请求来共享文件。

    在所有情况下,将文件从您的应用提供给其他应用的唯一安全方式就是向接收方应用发送文件的内容 URI,并授予对该 URI 的临时访问权限。 具有临时 URI 访问权限的内容 URI 是安全的,因为它们仅适用于接收该 URI 的应用,并且会自动过期。Android FileProvider 组件提供了 getUriForFile() 方法,用于生成文件的内容 URI。

     

     

    高级控件

    下拉列表

    下拉框Spinner

    Spinner用于从一串列表中选择某项。功能类似于单选按钮的组合

     

    适配器Adapter

    适配器负责从数据集中取出对应的数据,显示到条目布局上。

    拓展知识:Adapter继承结构

    Adapter
    (interface)
    ListAdapter
    (interface)
    SpinnerAdapter
    (interface)
    BaseAdapter
    CursorAdapter
    ArrayAdapter
    SimpleAdapter
    WrapperListAdapter
    (interface)
    ResourceCursorAdapter
    SimpleCursorAdapter
    HeaderListAdapter

     

    数组适配器ArrayAdapter

     

    实例:使用ArrayAdapter渲染Spinner

     

    简单适配器SimpleAdapter

    SimpleAdapter允许在列表项中同时展示图片和文字

    // 条目样式

    布局文件

     

    列表类视图

    基本适配器BaseAdapter

    BaseAdapter是一种适应性更强的基本适配器。

    注意:BaseAdapter是一个抽象类,需要进行实现

    示例代码如下:

    条目布局

    convertView复用: 当列表的item从上方滚动出屏幕以外时,会将convertView传入getView,可以重新进行复用,可以节约性能

     

    列表视图ListView

    在Android开发中,ListView是一个比较常用的控件。它以列表的形式 展示具体数据内容,并且能够根据数据的长度自适应屏幕显示。

    ListView标签常用的属性

    属性名称属性功能
    android:cacheColorHint设置拖动的背景色
    android:divider设置分割线
    android:dividerHeight设置分割线的高度
    android:listSelector设置ListView item选中时的颜色
    android:scrollbars设置Listview的滚动条
    android:fadeScrollbars设置为true就可以实现滚动条的自动隐藏和显示

    示例代码:

     

    列表项的点击问题

    通常只要调用setOnItemClickListener方法设置点击监听器,点击列表项即可触发列表项的点击事件,但是如果列表项中存在编辑框或者按钮(如:Button,ImageButtom,Checkbox等),点击列表项时就无法出发点击事件了。因为这类控件会抢占焦点。

    为了避免焦点抢占问题,列表视图允许开发者自行设置内部视图的焦点抢占方式,该方式在XML文件中使用descendantFocusability属性设置,在代码中使用setDescendantFocusability方法设置。

    列表视图焦点抢占方式如下

    说明焦点抢占类型xml属性
    在子控件之前处理ViewGroup.FOCUS_BEFORE_DESCENDANTSbeforeDescendants
    在子控件之后处理ViewGroup.FOCUS_AFTER_DESCENDANTSafterDescendants
    不让子控件处理ViewGroup.FOCUS_BLOCK_DESCENDANTSblocksDescendants

    注意!:焦点抢占方式不是由ListView设置的,而是由列表项的根布局设置。

     

    网格视图GridView

    网格视图用于分行分裂显示网格信息。

    常用的属性

     

    示例代码

     

    翻页类视图

    使用下面两个控件,可以制作应用引导页。

    翻页视图ViewPage

    翻页视图允许页面在水平方向上左右滚动。可以做轮播图效果。

     

    翻页标签栏PagerTabStrip

    翻页标签栏能在翻页视图的上方显示页面标题,点击标题即可切换到对应页面。

     

     

     

    碎片Fragment

    传统的Activity并不能很好的处理大屏啥问题,需要使用碎片化的工具能够划分区域展示内容,且有自己独立的操作控件,于是就出现了Fragment

    Fragmentz注册方式分为静态注册(在布局文件中直接指定Fragment)和动态注册(在JAVA代码中动态添加Fragment)

     

    Fragment生命周期

    img

    碎片的静态注册

    Activity页面

    新建Fragment,会自动生成一个Fragment.java和Fragment.xml文件,将想要的Fragment布局写入到布局文件

     

    碎片的动态注册

    示例:两个FrameLayout切换

    创建一个Activity,再布局文件中设置FrameLayout

    创建两个fragment

    再Activity中进行切换fragment

     

    广播

    广播是一种数据传输方式。

    在Android中,发送一条广播,可以被不同的广播接收者所接收。广播接收者收到广播后,再进行逻辑处理。

     

    收发标准广播

    广播收发的过程分为以下三步:

     

    四大组件

    1.1 Activity组件,它一个单独的窗口,程序流程都必须在Activity中运行。

    1.2 service组件,用于在后台完成用户指定的操作。

    1.3 content provider组件,会为所有的应用准备一个内容窗口,并且保留数据库、文件。

    1.4 broadcast receiver组件,是程序之间传递信息时的一种机制,作用就是接收或者发送通知。

     

    broadcast receiver简介

    2.1 broadcast receiver做为四大组件之一,负责组件之间消息的传递和接收。

    2.2 采用观察者模式,基于消息的发布/订阅事件模型,通过Binder机制进行消息的注册和接收。

    2.3 广播中的角色:

    • 消息订阅者(广播接收者)

    • 消息发布者(广播发布者)

    • 消息中心(AMS,即Activity Manager Service)

    2.4 广播的工作流程:

    • 广播接收者通过 Binder机制在AMS注册

    • 广播发送者通过 Binder 机制向AMS发送广播

    • AMS根据广播发送者要求,在已注册列表中,寻找合适的广播接收者(寻找依据:IntentFilter / Permission)

    • AMS将广播发送到合适的广播接收者相应的消息循环队列中;

    • 广播接收者通过消息循环拿到此广播,并回调 onReceive()

    所有的广播接收者都要继承BroadcastReceiver

     

    广播的注册

    3.1 注册类型有两种:静态注册和动态注册

    3.2 静态注册,即在清单文件中注册

    第一步:创建一个广播接收器BroadcastReceiver ,广播也是通过Intent来传递数据。

    第二步,清单文件注册该广播

    第三步:在其它组件里面发送广播,比如Activity里面

    3.3 注意:

    android 8.0以后版本对静态注册的广播做了限制,自定义的接收器会接收不到发送方发送的广播。发送方需要在intent中设定接收方的package,接收方才会接收到。如下:

    3.4 动态注册:即通过 registerReceiver 注册

    第一步:一样先创建广播接收器

    第二步:在组件如Activity里面动态注册广播

    第三步:在任意组件里面发送广播

    第四步:取消注册,不然容易造成内存泄漏

     

    有序广播

    5.1 有序广播介绍:

    • 有序广播是一种同步执行的广播,广播发出之后,优先级高的广播接收器就可以先接收到广播消息。

    • 执行完该广播接收器的逻辑后,可以选择截断正在传递的广播或者继续传递,如果广播消息被截断,之后的广播接收器则无法收到广播消息。

    • 有序广播中的“有序”是针对广播接收者而言的。有序广播的定义过程与普通广播无异,只是其发送方式变为:sendOrderedBroadcast()。

    • 有序广播的接收者们将按照事先命的优先级依次接收,数越大优先级越高(取值范围:-1000~10000)

    • 优先级可以声明在

    • 也可以调用IntentFilter对象的 setPriority() 设置

    • 调用abortBroadcast()方法即可终止,一旦终止后面接收者就无法接受广播

    5.2 实战:

    第一步,创建有序广播接收器

    第二步:清单文件里面注册有序广播 ,并设置优先级

    或者动态注册并设置广播优先级

    第三步:发送广播

    第四步:拦截有序广播,在接收器里面拦截abortBroadcast();

     

    应用内广播

    6.1 Android中的广播可以跨进程甚至跨App直接通信,且注册是exported对于有intent-filter的情况下默认值是true,由此将可能出现安全隐患如下:

    • 其他App可能会针对性的发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收到广播并处理;

    • 其他App可以注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。

    6.2 解决款进程上面隐患方案如下:

    • 对于同一App内部发送和接收广播,将exported属性人为设置成false,使得非本App内部发出的此广播不被接收;

    • 在广播发送和接收时,都增加上相应的permission,用于权限验证;

    • 发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。

    6.3 LocalBroadcastManage处理App内广播

    Android v4兼容包中给出了封装好的LocalBroadcastManager类,用于统一处理App应用内的广播问题,使用方式上与通常的全局广播几乎相同,只是注册/取消注册广播接收器和发送广播时将主调context变成了LocalBroadcastManager的单一实例。使用方式如下:

     

    常用系统广播

    7.1 Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广播。

    7.2 当使用系统广播时,只需要在注册广播接收者时定义相关的action即可,并不需要手动发送广播,当系统有相关操作时会自动进行系统广播

    7.3 每个广播都有特定的Intent - Filter(包括具体的action),Android系统广播action如下:

    监听网络变化 android.net.conn.CONNECTIVITY_CHANGE

     

    关闭或打开飞行模式 Intent.ACTION_AIRPLANE_MODE_CHANGED

     

    充电时或电量发生变化 Intent.ACTION_BATTERY_CHANGED

     

    电池电量低 Intent.ACTION_BATTERY_LOW

     

    电池电量 Intent.ACTION_BATTERY_OKAY

     

    系统启动完成后(仅广播一次) Intent.ACTION_BOOT_COMPLETED

     

    按下照相时的拍照按键(硬件按键)时 Intent.ACTION_CAMERA_BUTTON

     

    屏幕锁屏 Intent.ACTION_CLOSE_SYSTEM_DIALOGS

     

    设备当前设置被改变时(界面语言、设备方向等) Intent.ACTION_CONFIGURATION_CHANGED

     

    插入耳机时 Intent.ACTION_HEADSET_PLUG

     

    未正确移除SD卡但已取出来时(正确移除方法:设置--SD卡和设备内存--卸载SD卡) Intent.ACTION_MEDIA_BAD_REMOVAL

     

    插入外部储存装置(如SD卡) Intent.ACTION_MEDIA_CHECKING

     

    成功安装APK Intent.ACTION_PACKAGE_ADDED

     

    成功删除APK Intent.ACTION_PACKAGE_REMOVED

     

    重启设备 Intent.ACTION_REBOOT

     

    屏幕被关闭 Intent.ACTION_SCREEN_OFF

     

    屏幕被打开 Intent.ACTION_SCREEN_ON

     

    关闭系统时 Intent.ACTION_SHUTDOWN

     

    重启设备 Intent.ACTION_REBOOT

    7.4 示例,比如监听事件分钟变化

    第一步:创建时间变化监听器

    第二步:注册系统监听

    第三步:取消系统时间监听

     

    广播的其它方式

    8.1 广播的作用就是会主动监听并接收数据变化,但广播是系统组件,需要传上下文,使用不规范可能会造成内存泄漏。而且系统的更新可能会限制广播的某些功能使用,于是也出现了基于发布/订阅模式的其它框架,比如使用非常广泛的EventBus。

    8.2 EventBus 优点:

    • 调度灵活,不依赖于 Context,使用时无需像广播一样关注 Context 的注入与传递。

    • 父类对于通知的监听和处理可以继承给子类,这对于简化代码至关重要。

    • 通知的优先级,能够保证 Subscriber 关注最重要的通知。

    • 粘滞事件 (sticky events) 能够保证通知不会因 Subscriber 的不在场而忽略

    8.3 当然使用广播和EventBus都能达到监听消息的机制,可以根据自己情况选择。还有其它类似的发送/接收机制的框架,比如配合网络请求使用的RxJava,LiveData等。

     


    笔记到此结束!完成!2025/1/1

    总词数:约25378词