Android Intent/Context Flags 使用

文章目录

  • Android Intent/Context Flags 使用
    • 一、基本使用
    • 二、Flags介绍
      • 2.1. 系统定义的Flags
        • 2.1.1 Intent
        • 2.1.2 Context
      • 2.2 Actvity Flags
        • 测试工具
        • FLAG_ACTIVITY_NEW_TASK
        • FLAG_ACTIVITY_CLEAR_TOP
        • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
        • FLAG_ACTIVITY_FORWARD_RESULT
        • FLAG_ACTIVITY_NEW_DOCUMENT
        • FLAG_ACTIVITY_NO_ANIMATION
        • FLAG_ACTIVITY_NO_HISTORY
        • FLAG_ACTIVITY_NO_USER_ACTION
        • FLAG_ACTIVITY_LAUNCH_ADJACENT
        • FLAG_ACTIVITY_REORDER_TO_FRONT
        • FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
        • FLAG_ACTIVITY_RETAIN_IN_RECENTS
        • FLAG_ACTIVITY_SINGLE_TOP
        • FLAG_DEBUG_LOG_RESOLUTION
        • FLAG_EXCLUDE_STOPPED_PACKAGES / FLAG_INCLUDE_STOPPED_PACKAGES
        • FLAG_FROM_BACKGROUND
        • FLAG_ACTIVITY_TASK_ON_HOME
      • 2.3 Uri Flags
        • FLAG_GRANT_READ_URI_PERMISSION / FLAG_GRANT_WRITE_URI_PERMISSION
        • FLAG_GRANT_PERSISTABLE_URI_PERMISSION
        • FLAG_GRANT_PREFIX_URI_PERMISSION
        • 使用案例
      • 2.4 Receiver Flags
        • FLAG_RECEIVER_REGISTERED_ONLY
        • FLAG_RECEIVER_REPLACE_PENDING
        • FLAG_RECEIVER_FOREGROUND
        • FLAG_RECEIVER_NO_ABORT
        • FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
      • 2.5 Service Flags
        • BIND_AUTO_CREATE
        • BIND_DEBUG_UNBIND
        • BIND_NOT_FOREGROUND
        • BIND_ABOVE_CLIENT
        • BIND_ALLOW_OOM_MANAGEMENT
        • BIND_WAIVE_PRIORITY
        • BIND_IMPORTANT
        • BIND_ADJUST_WITH_ACTIVITY

一、基本使用

setFlags, 直接设置flags, 之前设置的flags会被覆盖

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

内部实现如下:

public @NonNull Intent setFlags(@Flags int flags) {    mFlags = flags;    return this;}

addFlags, 追加flags, 在之前设置的flags的基础上添加

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

内部实现如下:

public @NonNull Intent addFlags(@Flags int flags) {    mFlags |= flags;    return this;}

二、Flags介绍

2.1. 系统定义的Flags

2.1.1 Intent

  • FLAG_GRANT_READ_URI_PERMISSION
  • FLAG_GRANT_WRITE_URI_PERMISSION
  • FLAG_GRANT_PERSISTABLE_URI_PERMISSION
  • FLAG_GRANT_PREFIX_URI_PERMISSION
  • FLAG_FROM_BACKGROUND
  • FLAG_DEBUG_LOG_RESOLUTION
  • FLAG_EXCLUDE_STOPPED_PACKAGES
  • FLAG_INCLUDE_STOPPED_PACKAGES
  • FLAG_DEBUG_TRIAGED_MISSING
  • FLAG_IGNORE_EPHEMERAL
  • FLAG_ACTIVITY_MATCH_EXTERNAL
  • FLAG_ACTIVITY_NO_HISTORY
  • FLAG_ACTIVITY_SINGLE_TOP
  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_MULTIPLE_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_FORWARD_RESULT
  • FLAG_ACTIVITY_PREVIOUS_IS_TOP
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
  • FLAG_ACTIVITY_BROUGHT_TO_FRONT
  • FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
  • FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
  • FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
  • FLAG_ACTIVITY_NEW_DOCUMENT
  • FLAG_ACTIVITY_NO_USER_ACTION
  • FLAG_ACTIVITY_REORDER_TO_FRONT
  • FLAG_ACTIVITY_NO_ANIMATION
  • FLAG_ACTIVITY_CLEAR_TASK
  • FLAG_ACTIVITY_TASK_ON_HOME
  • FLAG_ACTIVITY_RETAIN_IN_RECENTS
  • FLAG_ACTIVITY_LAUNCH_ADJACENT
  • FLAG_RECEIVER_REGISTERED_ONLY
  • FLAG_RECEIVER_REPLACE_PENDING
  • FLAG_RECEIVER_FOREGROUND
  • FLAG_RECEIVER_NO_ABORT
  • FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
  • FLAG_RECEIVER_BOOT_UPGRADE
  • FLAG_RECEIVER_INCLUDE_BACKGROUND
  • FLAG_RECEIVER_EXCLUDE_BACKGROUND
  • FLAG_RECEIVER_FROM_SHELL
  • FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS

2.1.2 Context

  • BIND_AUTO_CREATE
  • BIND_DEBUG_UNBIND
  • BIND_NOT_FOREGROUND
  • BIND_ABOVE_CLIENT
  • BIND_ALLOW_OOM_MANAGEMENT
  • BIND_WAIVE_PRIORITY
  • BIND_IMPORTANT
  • BIND_ADJUST_WITH_ACTIVITY

2.2 Actvity Flags

测试工具

主要利用IntentTestApp进行测试验证

FLAG_ACTIVITY_NEW_TASK

要点

  • 很重要的一个标识
  • 启动Activity时, 如果符合Activity TaskAffinity的栈没有创建, 就会创建一个, 然后再启动Activity放置其中
  • 当App从Launcher启动时, Intent会添加这个标志位
  • 如果使用Application启动Activity, 必须添加这个标志位
  • 通常配合的其他标志位有:
    • Intent.FLAG_ACTIVITY_CLEAR_TASK
    • Intent.FLAG_ACTIVITY_CLEAR_TOP
    • Intent.FLAG_ACTIVITY_MULTIPLE_TASK
    • Intent.FLAG_ACTIVITY_NEW_DOCUMENT

FLAG_ACTIVITY_CLEAR_TOP

要点

  • 没有指定Activity TaskAffinity栈的情况下
    • 如果目标Activity还未启动, 直接在默认栈创建一个新的实例
    • 如果目标Activity已经启动, 并且已处于栈顶, 则会先启动一个新的实例, 再Destroy掉之前的实例
    • 如果目标Activity已经启动, 并且不处于栈顶, 则会先Destroy掉之前的实例, 再启动一个新的实例, 最后Destroy掉之前实例之上的其他Activity实例
  • 已经指定Activity TaskAffinity栈的情况下
    • 如果目标Activity还未启动, 不管是否有栈名称指定的Affinity匹配, 直接创建一个新栈和新的实例
    • 如果目标Activity已经启动, 直接将所在栈拉到前台
    • 如果只指定FLAG_ACTIVITY_CLEAR_TOP这一个标志位, 启动时系统自动添加FLAG_ACTIVITY_NEW_TASK标志位, 效果等同于SingleInstance

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

要点

  • 设置后Activity不会展示到最近任务页面中, 建议加上TaskAffinity配合使用
    • 例子: A启动B时, 添加FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS标志, 按Home回到桌面后再按最近任务页面, 显示的为A, 而不是B
  • 通过点击最近页面或者图标再次进入时, 会进入其他Activity页面
  • 尝试配合FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_MULTIPLE_TASK使用时, 效果很奇怪, 整个App都不在最近页面了

FLAG_ACTIVITY_FORWARD_RESULT

要点

  • 委托请求结果
    • 例子: A通过startActivityForResult启动B, B不知如何setResult, B就启动C, 由C设置setResult
    • 当C返回结果后, B设置setResult并没有任何效果, A收到的值是C的结果
    • 再由B启动C时需要调用startActivity, 使用startActivityForResult会抛出android.util.AndroidRuntimeException: FORWARD_RESULT_FLAG used while also requesting a result异常

FLAG_ACTIVITY_NEW_DOCUMENT

要点

  • 在最近任务页面里面添加同一个App的不同页面记录
  • 如果之前没有启动过Activity, 会创建一个新的任务栈, 并启动一个新的Activity放入, 否则直接将之前的任务栈拉到前台
  • 系统会自动添加FLAG_ACTIVITY_NEW_TASK标志位
  • 如果单独使用的话, 效果果同在Manifest设置documentLaunchMode="intoExisting"
  • 可以配合FLAG_ACTIVITY_MULTIPLE_TASK使用, 这样就总会创建新的任务栈和Activity实例, 效果同在Manifest设置documentLaunchMode="always"
  • 在手机上测试时发现, 不指定这个标志位, 只设置TaskAffinity, 也能达到这种效果, 但只有一个实例, 设置FLAG_ACTIVITY_MULTIPLE_TASK也没有效果

FLAG_ACTIVITY_NO_ANIMATION

要点

  • 去除动画效果
  • 仅这一次有效, 如果A启动B, B再启动C, 需要再次设置这个标志位

FLAG_ACTIVITY_NO_HISTORY

要点

  • 通过设置FLAG_ACTIVITY_NO_HISTORY启动的Activity在失去前台后会被销毁掉
  • 并不是立即销毁掉, 实际是这个Activity上面没有其他Activity时才会开始销毁
  • 感觉就是: 先失去前台, 再获取到前台, 发现设置了FLAG_ACTIVITY_NO_HISTORY标志位, 就直接销毁了

FLAG_ACTIVITY_NO_USER_ACTION

要点

  • Intent设置FLAG_ACTIVITY_NO_USER_ACTION后, 调用startActivity所在的Activity, 不会调用onUserLeaveHint, 不是被调用者
  • 不设置FLAG_ACTIVITY_NO_USER_ACTION情况下
    • onUserLeaveHint在失去前台时会被调用, 但在Activity销毁时不会被调用
    • 不知道是不是手机问题, 通过最近任务页面跳转到其他App时, onUserLeaveHint也不会被调用

FLAG_ACTIVITY_LAUNCH_ADJACENT

要点

  • 仅在分屏多窗口模式下起作用
  • 新Activity将显示在启动它的Activity的旁边
  • 需要与FLAG_ACTIVITY_NEW_TASK搭配使用, 如果需要创建现有Activity的新实例, 可以添加FLAG_ACTIVITY_MULTIPLE_TASK
  • 这个没有在手机上实际验证

FLAG_ACTIVITY_REORDER_TO_FRONT

要点

  • 效果为在不销毁Activity的前提下, 更改当前栈Activity的顺序
  • 例子:
    • 假设当前栈有Activity A、B、C、D, D在栈顶
    • D 启动Activity B, 并添加FLAG_ACTIVITY_REORDER_TO_FRONT标志位
    • 当前栈的顺序改为: A、C、D、B
    • B 会调用onNewIntent
  • 如果设置了FLAG_ACTIVITY_CLEAR_TOP, 忽略本标志位, 走FLAG_ACTIVITY_CLEAR_TOP这一套
  • FLAG_ACTIVITY_CLEAR_TOP的区别就在于, 是否会销毁上面的Activity

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

要点

  • 转移Activity到其他栈, 一般用于不同App之间
  • 需要在清单文件配置如下两个属性:
    • android:export="true"允许其他App启动
    • android:allowTaskReparenting=true允许Activity所在栈可以更换
  • 参考网络资源, 主要工作流程如下:
    • A 应用有主Activity A 和Activity A_2, A_2 设置android:export="true"android:allowTaskReparenting=true
    • B 应用有主Activity B
    • Activity B 启动 Activity A_2, 当前Activity A_2 在应用B的栈内
    • 回到桌面启动Activity A, 启动时, 系统会自动添加FLAG_ACTIVITY_RESET_TASK_IF_NEEDEDFLAG_ACTIVITY_NEW_TASK标志位
    • 此时系统会从所有App栈记录中查找和 Activity A taskAffinity相同的Activity, 并将找到的Activity放入这个A应用的新栈中

FLAG_ACTIVITY_RETAIN_IN_RECENTS

要点

  • 需要配合FLAG_ACTIVITY_NEW_DOCUMENT使用, 系统会自动添加FLAG_ACTIVITY_NEW_TASK标志位
  • 使用 FLAG_ACTIVITY_NEW_DOCUMENT时, 加不加FLAG_ACTIVITY_RETAIN_IN_RECENTS并没明显作用

FLAG_ACTIVITY_SINGLE_TOP

要点

  • 如果Activity已经在栈顶部, 则不会启动新实例, 仅调用onNewIntent
  • 可以搭配FLAG_ACTIVITY_CLEAR_TOP使用, 如果只使用FLAG_ACTIVITY_CLEAR_TOP, 会销毁本Activity和上面的其他Activity; 如果加上FLAG_ACTIVITY_SINGLE_TOP, 就只销毁本Activity上面的其他Activity, 本Activity会保留, 并调用onNewIntent

FLAG_DEBUG_LOG_RESOLUTION

要点

  • 启动Debug的标志, 在解析本Intent时打印日志消息
  • 可以在logcat中过滤IntentResolver关键字, 主要是queryIntent方法

FLAG_EXCLUDE_STOPPED_PACKAGES / FLAG_INCLUDE_STOPPED_PACKAGES

要点

  • FLAG_EXCLUDE_STOPPED_PACKAGES
    • 此Intent不去匹配没有运行的App, 防止唤醒
  • FLAG_INCLUDE_STOPPED_PACKAGES
    • 此Intent去匹配所有App, 包括没有运行的App
  • 这两个Flag都不设置或者都设置, 效果同FLAG_EXCLUDE_STOPPED_PACKAGES

FLAG_FROM_BACKGROUND

要点

  • 表示Intent来自后台操作, 而不是直接来自用户操作
  • 手机测试时, 并没有发现什么特殊效果

FLAG_ACTIVITY_TASK_ON_HOME

要点

  • 当Actvity返回时, 直接回到桌面, 需要搭配FLAG_ACTIVITY_NEW_TASK使用
  • 需要让Activity在栈底, 可选下列其一
    • 指定taskAffinity
    • 配合FLAG_ACTIVITY_NEW_DOCUMENT

2.3 Uri Flags

FLAG_GRANT_READ_URI_PERMISSION / FLAG_GRANT_WRITE_URI_PERMISSION

要点

  • 临时对目标授予Uri的读/写权限
  • 只使用这两个的话, 设备重启权限就消失了, 需要重新授予

FLAG_GRANT_PERSISTABLE_URI_PERMISSION

要点

  • 授予目标的权限一直保持, 重启设备后依然存在, 这个只是提供可能持久授权
  • 需要ContentResolver.takePersistableUriPermission(Uri, modeFlag)实现

FLAG_GRANT_PREFIX_URI_PERMISSION

要点

  • 添加FLAG_GRANT_PREFIX_URI_PERMISSION标志位后, 只要Uri的前缀相匹配就有相应的权限
  • 如果没有这个标志位, 需要Uri完全匹配才有相应的权限

使用案例

授予目标权限

Intent intent = new Intent();// 这里指定读和写权限intent.addFlags(    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);// 指定赋予权限的Uriintent.setData = Uri.parse("content://com.jeasoon.learnintent/hello/world");intent.setComponent = new ComponentName("com.jeasoon.learnintent_1", "com.jeasoon.learnintent.MainActivity");// 启动目标, 启动后的目标就有对指定Uri的读写权限了startActivity(intent);

回收权限

// 回收权限后, 目标就不能对Uri的读写做操作了Context.revokeUriPermission(    Uri.parse("content://com.jeasoon.learnintent/hello/world"),    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

2.4 Receiver Flags

FLAG_RECEIVER_REGISTERED_ONLY

要点

  • 只有动态注册的BroadcastReceiver可以收到消息
  • 在AndroidManifest.xml注册的BroadcastReceiver无法收到

FLAG_RECEIVER_REPLACE_PENDING

要点

  • 如果你的广播发送速度过快, 系统还没来得及处理之前的广播, 这些广播就会被最新的广播替换掉
  • 确保让程序处理的广播是最新的

FLAG_RECEIVER_FOREGROUND

要点

  • 以前台优先级运行广播接受者
  • 优先运行, 运行间隔会变小

FLAG_RECEIVER_NO_ABORT

要点

  • 发送有序广播时, 不允许中断广播
  • 后续广播接受者可以收到广播并继续修改传递结果

FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS

要点

  • 广播可被Instant App接收
  • 默认Instant App不接收任何广播

2.5 Service Flags

BIND_AUTO_CREATE

要点

  • 如果目标Service没有启动, 自动启动目标Service, 但不调用onStartCommand方法
  • 如果目标Service已经启动, 则只调用目标Service的onBind方法
  • 如果目标Service没有启动, 并且没有指定BIND_AUTO_CREATE, 则不会启动目标Service, 但返回值为true, 当其他地方使用startService启动Service时, 才会自动进行绑定
  • 在4.0之前, Service设置BIND_AUTO_CREATE标志位后, Service的优先级就会和调用Service的进程优先级一致, 不指定就是后台任务
  • 在4.0之后, Service设置BIND_ADJUST_WITH_ACTIVITY标志位后, Service才会与调用Service的进程优先级一致
  • 在4.0之后, 为了保持兼容, 在不指定BIND_AUTO_CREATE标志位时保持和4.0版本之前的行为一致, 系统会自动添加BIND_WAIVE_PRIORITYBIND_ADJUST_WITH_ACTIVITY标志位

BIND_DEBUG_UNBIND

要点

  • 因为使用时有内存泄漏问题, 建议仅用于debug模式
  • 记录解绑操作unbindService(), 当再次调用解绑操作unbindService()时app会崩溃, 会把上次解绑的位置打印出来
Caused by: java.lang.IllegalArgumentException: Originally unbound here:        at android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:1277)        at android.app.ContextImpl.unbindService(ContextImpl.java:1521)        at android.content.ContextWrapper.unbindService(ContextWrapper.java:658)        at com.jeasoon.flags.MainActivity$onCreate$2.run(MainActivity.kt:44)        at android.os.Handler.handleCallback(Handler.java:754)         at android.os.Handler.dispatchMessage(Handler.java:95)         at android.os.Looper.loop(Looper.java:163)         at android.app.ActivityThread.main(ActivityThread.java:6337) 

BIND_NOT_FOREGROUND

要点

  • 不允许绑定的Service优先级提升至前台
  • 只针对CPU调度, 不管客户端的CPU调度优先级在哪里, Service的CPU调度优先级都为后台
  • 内存优先级依然和客户端保持一致, 不受影响

BIND_ABOVE_CLIENT

要点

  • 提升Service的优先级比客户端进程更重要
  • 在内存不足时先杀客户端(理论是这样, 实际操作常常不是)

BIND_ALLOW_OOM_MANAGEMENT

要点

  • 在OOM时, 作为杀死的目标

BIND_WAIVE_PRIORITY

要点

  • 放弃优先级提升, 作为常规的后台标准程序, 允许系统利用LRU机制管理

BIND_IMPORTANT

要点

  • Service对客户端来说比较重要, 需要将Service提升到与客户端同一等级
  • 优先级最高也只能提升到可见进程, 即使客户端已经在前台了

BIND_ADJUST_WITH_ACTIVITY

要点

  • 只有绑定Service的是Actvitiy才会生效
  • Service的优先级会受到Actvity的优先级影响, 就是说Acticity优先级提升, Service优先级也提升, 但是提升到什么程度, 并没有给出说明
  • 会忽略其他降低优先级的标志位

更多相关文章

  1. Android(安卓)Wifi模块分析(三)
  2. Android(安卓)Activity的启动
  3. Android(安卓)任务和回退堆栈---启动任务
  4. Android——Activity四种启动模式
  5. 修复Android(安卓)App在开机后入口类被启动两次的bug
  6. 开机引导程序只执行一次的方法
  7. android 命令(adb shell)进入指定模拟器或设备
  8. Android(安卓)开机自启动程序
  9. Android(安卓)ASE 脚本环境

随机推荐

  1. 【Android(安卓)如何置底一个View(附 前置
  2. 我的Android开发之旅 —从.NET到PHP到And
  3. Android线程池的原理以及项目中实践
  4. Android艺术开发探索第三章————View
  5. 迷茫的时候,需要自己反思
  6. android ble 蓝牙4.0 cc2540 开发(一)
  7. android shouldOverrideUrlLoading 部分
  8. Android(安卓)如何从系统图库中选择图片
  9. Android图形---Graphics(概要)
  10. 2020上半年百度Android岗(初级到高级)面试