一、 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()是不一样的,代码展示区别:

/**
* Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
* with no options.
*
* @param intent The intent to start.
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits.
*
* @throws android.content.ActivityNotFoundException
*
* @see #startActivity
*/
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
/**
* Modifies the standard behavior to allow results to be delivered to fragments.
* This imposes a restriction that requestCode be <= 0xffff.
*/
@Override
public void startActivityForResult(Intent intent, int requestCode) {
// If this was started from a Fragment we've already checked
     // the upper 16 bits were not in
// use, and then repurposed them for the Fragment's index.
if (!mStartedActivityFromFragment) {
if (requestCode != -1) {
checkForValidRequestCode(requestCode);
}
}
super.startActivityForResult(intent, requestCode);
}
/**
* Checks whether the given request code is a valid code by masking it with 0xffff0000. Throws
* an {@link IllegalArgumentException} if the code is not valid.
*/
static void checkForValidRequestCode(int requestCode) {
if ((requestCode & 0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
}
}
 

通过以上代码的比较我们知道,会造成下面的错误,是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的限制的更多相关文章

  1. Android requestcode resultcode的作用

    requestcode 一个页面的不同事件,激发不同的函数,startActivityForResult中传入不同的请求码的值以调用下一个界面,在被调用界面结束返回第一个界面时,请求码会自动返回(自动 ...

  2. android startActivityForResult(Intent intent, int requestCode) 整理与总结! .

    假设有两个Activity,主界面A,功能界面B,由A启动B,并传数据给B,B在经过处理后把数据传回给A. 先是A传B: Bundle bundle = new Bundle();bundle.put ...

  3. Android FragmentActivity 嵌套 Fragment 调用startActivityForResult返回的requestCode错误

    Android FragmentActivity 嵌套 Fragment 调用startActivityForResult返回的requestCode错误 此时,要在调用startActivityFo ...

  4. android小知识之fragment中调用startActivityForResult(Intent intent,int requestcode)所遇到的问题

    大家都知道对于Activity和Fragment都可以注册OnActivityResult()方法,但是要注意几点: a.当activity和fragment都注册了OnActivityResult( ...

  5. Android开发 Fragment中调用startActivityForResult返回错误的requestCode

    返回错误的requestCode返回值为65537,在Fragment里调用startActivityForResult,就必须在Fragment里处理onActivityResult.

  6. Android onActivityResult 设置requestCode 返回的code不对

    今天在项目里用到 Intent intent=new Intent(getActivity(), Test.class);startActivityForResult(intent, 1); onAc ...

  7. Android 6.0 权限知识学习笔记

    最近在项目上因为6.0运行时权限吃了亏,发现之前对运行时权限的理解不足,决定回炉重造,重新学习一下Android Permission. 进入正题: Android权限 在Android系统中,权限分 ...

  8. Android权限管理之Android 6.0运行时权限及解决办法

    前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...

  9. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

随机推荐

  1. Prometheus监控学习笔记之Prometheus不完全避坑指南

    0x00 概述 Prometheus 是一个开源监控系统,它本身已经成为了云原生中指标监控的事实标准,几乎所有 k8s 的核心组件以及其它云原生系统都以 Prometheus 的指标格式输出自己的运行 ...

  2. Docker学习笔记之使用 Docker Compose 管理容器

    0x00 概述 通过之前的介绍,我们已经基本掌握了构建.运行容器的方法,但这还远远不够,由于 Docker 采用轻量级容器的设计,每个容器一般只运行一个软件,而目前绝大多数应用系统都绝不是一个软件所能 ...

  3. ora-12705解决方法

    最近使用instant sqlplus测试时,遇到ora-12705,一开始以为是少了配置,经查是,NLS_LANG设置问题,设置为"SIMPLIFIED CHINESE_CHINA.ZHS ...

  4. 在见证了1000多家公司的兴衰灭亡之后,YC创始合伙人总结了创业公司的6个不死法则(转)

    今天,我想先说一下个人消息.在 YC 工作了 11 年之后,我明年想去休假.我希望把精力放在一些项目上,说实话,我有点累了. YC 是这世界上我最喜欢的事情之一,但它也很费精力. 11 年不间断的耗费 ...

  5. 【题解】Luogu P1533 可怜的狗狗

    原题传送门 莫队介绍,Splay介绍 离线的题目,莫队是不错的解决方法 先把询问排一下序 剩下就套一个莫队的板子 每来一只狗就把漂亮值插入平衡树 每去掉一只狗就把漂亮值从平衡树中删掉 每次查询查平衡树 ...

  6. python 爬取历史天气

    python 爬取历史天气 官网:http://lishi.tianqi.com/luozhuangqu/201802.html # encoding:utf-8 import requests fr ...

  7. python base64加解密

    加密字符串 encodestr = base64.b64encode("chenglee1234".encode(encoding='utf-8')) 解密字符串 decodest ...

  8. QT---实现舒尔特方格(零基础入门)

    按照之前说的,加上舒尔特方格,读者还可以自行将此游戏做成APP放到手机上,后面还有贪吃蛇,Java版的飞机大战,五子棋,各类游戏会不断加上来的,当然,会免费附加源代码! 读者可以去4399去玩一下,可 ...

  9. bzoj 4445 小凸想跑步 - 半平面交

    题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...

  10. loj#2305. 「NOI2017」游戏 2-sat

    链接 https://loj.ac/problem/2305 https://www.luogu.org/problemnew/show/P3825 思路 3-sat神马的就不要想了,NP问题 除去x ...