Android requestCode的限制
一、 why ?
由于才疏学浅,在开发中requestCode的让我很困惑。困惑是因为什么呢,是因为弄混了。要想弄明白,不困惑,来想一想用到requestCode的地方:
① startActivityForResult开启另一个Activity的时候:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
② 请求权限的时候:
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHasCurrentPermissionsRequest) {
Log.w(TAG, "Can reqeust only one set of permissions at a time");
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, new String[0], new int[0]);
return;
}
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}
(1)首先来看startActivityForResult()的requestCode:
通过查看源码发现:在Activity中startActivityForResult() 和Activity的子类FragmentActivity中的startActivityForResult()是不一样的,代码展示区别:
/** |
/** /** |
通过以上代码的比较我们知道,会造成下面的错误,是FragmentActivity添加的限制,而Activity中没有该限制,这里解决了一点点疑惑:
java.lang.IllegalArgumentException: Can only use lower bits for requestCode
所以这里总结一下:在startActivityForResult()中的resquestCode的限制是 0 <= requestCode <= 216 ,小于零会造成什么问题,你可以试试,我没有尝试。
(2)再来看ActivityCompat请求权限中的requestCode:
public static void requestPermissions(final @NonNull Activity activity,
final @NonNull String[] permissions, final int requestCode) {
if (Build.VERSION.SDK_INT >= 23) {
ActivityCompatApi23.requestPermissions(activity, permissions, requestCode);
} else if (activity instanceof OnRequestPermissionsResultCallback) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
final int[] grantResults = new int[permissions.length]; PackageManager packageManager = activity.getPackageManager();
String packageName = activity.getPackageName(); final int permissionCount = permissions.length;
for (int i = 0; i < permissionCount; i++) {
grantResults[i] = packageManager.checkPermission(
permissions[i], packageName);
} ((OnRequestPermissionsResultCallback) activity).onRequestPermissionsResult(
requestCode, permissions, grantResults);
}
});
}
}
由源码可以知道:当sdk >=23的时候,会走 ActivityCompatApi23.requestPermissions(activity, permissions, requestCode),来看看它干了什么:
public static void requestPermissions(Activity activity, String[] permissions,
int requestCode) {
if (activity instanceof RequestPermissionsRequestCodeValidator) {
((RequestPermissionsRequestCodeValidator) activity)
.validateRequestPermissionsRequestCode(requestCode);
}
activity.requestPermissions(permissions, requestCode);
}
如果Activity实现了接口RequestPermissionsRequestCodeValidator 就会对requestCode进行判断,天啊,终于说到它了。validateRequestPermissionsRequestCode 见名之意,它对requestCode作了限制,看看FragmentActivity实现的该接口是怎么限制的:checkForValidRequestCode() 这个方法是不是很熟悉:上面就有看看吧,看来限制是一样的: 请求权限 requestCode <= 216
@Override
public final void validateRequestPermissionsRequestCode(int requestCode) {
// We use 16 bits of the request code to encode the fragment id when
// requesting permissions from a fragment. Hence, requestPermissions()
// should validate the code against that but we cannot override it as
// we can not then call super and also the ActivityCompat would call
// back to this override. To handle this we use dependency inversion
// where we are the validator of request codes when requesting
// permissions in ActivityCompat.
if (!mRequestedPermissionsFromFragment
&& requestCode != -1) {
checkForValidRequestCode(requestCode);
}
}
你会不会以为这个限制只有在sdk >=23以上才有,那就错了。我们来看看小于23时的分支会直接走到onRequestPermissionsResult(),来看看它:哇,同样的限制。
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
int index = (requestCode >> 16) & 0xffff;
if (index != 0) {
index--; String who = mPendingFragmentActivityResults.get(index);
mPendingFragmentActivityResults.remove(index);
if (who == null) {
Log.w(TAG, "Activity result delivered for unknown Fragment.");
return;
}
Fragment frag = mFragments.findFragmentByWho(who);
if (frag == null) {
Log.w(TAG, "Activity result no fragment exists for who: " + who);
} else {
frag.onRequestPermissionsResult(requestCode & 0xffff, permissions, grantResults);
}
}
}
二、总结:
FragmentActivity是对Activtiy的一层包装,requestCode的限制是在它里面添加的,而Activity本身对requestCode是没有限制的。所以如果发现有的requestCode大于216仍然能通过,不要疑惑,你懂得!
Android requestCode的限制的更多相关文章
- Android requestcode resultcode的作用
requestcode 一个页面的不同事件,激发不同的函数,startActivityForResult中传入不同的请求码的值以调用下一个界面,在被调用界面结束返回第一个界面时,请求码会自动返回(自动 ...
- android startActivityForResult(Intent intent, int requestCode) 整理与总结! .
假设有两个Activity,主界面A,功能界面B,由A启动B,并传数据给B,B在经过处理后把数据传回给A. 先是A传B: Bundle bundle = new Bundle();bundle.put ...
- Android FragmentActivity 嵌套 Fragment 调用startActivityForResult返回的requestCode错误
Android FragmentActivity 嵌套 Fragment 调用startActivityForResult返回的requestCode错误 此时,要在调用startActivityFo ...
- android小知识之fragment中调用startActivityForResult(Intent intent,int requestcode)所遇到的问题
大家都知道对于Activity和Fragment都可以注册OnActivityResult()方法,但是要注意几点: a.当activity和fragment都注册了OnActivityResult( ...
- Android开发 Fragment中调用startActivityForResult返回错误的requestCode
返回错误的requestCode返回值为65537,在Fragment里调用startActivityForResult,就必须在Fragment里处理onActivityResult.
- Android onActivityResult 设置requestCode 返回的code不对
今天在项目里用到 Intent intent=new Intent(getActivity(), Test.class);startActivityForResult(intent, 1); onAc ...
- Android 6.0 权限知识学习笔记
最近在项目上因为6.0运行时权限吃了亏,发现之前对运行时权限的理解不足,决定回炉重造,重新学习一下Android Permission. 进入正题: Android权限 在Android系统中,权限分 ...
- Android权限管理之Android 6.0运行时权限及解决办法
前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
随机推荐
- Zynq ZC706 传统方式移植Linux -- 编译u-boot
我用的是zc706不是zed 基本思路是: 1.安装交叉编译工具(见 https://www.cnblogs.com/idyllcheung/p/10532654.html ) 2.下载xilinx ...
- Shell生成数字序列
转自http://kodango.com/generate-number-sequence-in-shell Shell里怎么输出指定的数字序列: for i in {1..5}; do echo $ ...
- 数据库的增、删、改、查 (CURD)
增改查删可以用CURD来表示 增加:create 修改:update 查找:read 删除:delete 增加create : insert +表名+values+(信息): in ...
- Docker学习笔记之在开发环境中使用服务发现
0x00 概述 服务发现应用是很多服务化系统的组成部分,所以在开发.测试环境中也就有必要配备一套服务发现体系来配合我们的开发.测试工作.在这一小节里,我们就来谈谈如何在 Docker 环境下部署服务发 ...
- Linux 搭建安装Maven环境
1.前提条件: 1)下载并安装好JDK .在终端输入命令“java -version”,如果出现类似如下信息说明JDK安装成功. $ java -version java version " ...
- Linux FreeTDS的安装与配置
Linux FreeTDS的安装与配置 一.简介 官方网站:http://www.freetds.org 版本:0.64 下载地址:http://ibiblio.org/pub/Linux/ALPHA ...
- 尚硅谷面试第一季-12Linux常用服务类相关命令
课堂重点: 实操命令及运行结果: (centos 6) service network status chkconfig --list chkconfig --level 5 network off ...
- python --- 17. 面向对象成员
面向对象的成员 能写的所有成员 一.变量 1.实例变量 访问时 对象.变量 2.类变量 访问时 类名.变量 注意: 二.方法 1.实例方法 必须有一个参数(self) 调用时 ...
- 转载:Systemd 命令
目录 一.由来 二.Systemd 概述 三.系统管理 3.1 systemctl 3.2 systemd-analyze 3.3 hostnamectl 3.4 localectl 3.5 time ...
- 算法总结(转自CS-Notes)
转载地址: 注意要点: 1.希尔排序:实际是将元素按步距h分为几组,每组元素没有关系,是组里每个元素跨步距h得到的一组元素是有序的,那么剩下的问题就是组内有序,再处理好组间边界即可.实际解决的方式是不 ...