草庐IT

android - 从 Fragment 请求权限时,在 Activity 的 onRequestPermissionsResult 中收到不正确的 resultCode

coder 2023-11-29 原文

我有一个 targetSdkVersion = 23, compileSdkVersion = 23 的应用程序,主要 Activity 设置如下

- HomeActivity (AppCompatActivity)
  - FragmentA (V4 Fragment)
    - ViewPager
      - NestedFragmentA (V4 Fragment)
      - NestedFragmentB (v4 Fragment)
      - NestedFragmentC (v4 Fragment)
      - NestedFragmentD (v4 Fragment)
  - Fragment B (V4 Fragment)
  - Fragment C (V4 Fragment)

在 HomeActivity 中
public static final String PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    Log.i("Logger", "Request Code: " + String.valueOf(requestCode));

    // Handle permission request result
}

我从@CommonsWare 阅读了这个答案,

https://stackoverflow.com/a/33170531/760363

嵌套 fragment 中的 onRequestPermissionsResult 永远不会被调用(在我的情况下,它的结果将返回到 HomeActivity)但我很好,我会手动通知 fragment 结果。

但问题是,当我在 HomeActivity 中请求许可时,一切正常。

首页 Activity
// Request permission from HomeActivity
// Supply 101 as request code, get 101 back

@Override
public void clickSomething(View v) {
    requestPermissions(new String[]{PERMISSION}, 101);
}

// Logcat
Logger: Request Code: 101 <<< CORRECT

但在 fragment nA 嵌套 fragment A ,当我从嵌套 fragment 请求时,返回 HomeActivity 的 requestCode 发生了变化

fragment A
// Request permission from FragmentA
// Supply 102 as request code, get 358 back

@Override
public void clickAnotherThing(View v) {
    requestPermissions(new String[]{HomeActivity.PERMISSION}, 102);
}

// Logcat
Logger: Request Code: 358 <<< INCORRECT

嵌套 fragment A
// Request permission from NestedFragmentA
// Supply 103 as request code, get 615 back

@Override
public void clickDifferentThing(View v) {
    requestPermissions(new String[]{HomeActivity.PERMISSION}, 103);
}

// Logcat
Logger: Request Code: 615 <<< INCORRECT

你知道什么会导致这个问题吗?

最佳答案

我不会否定 "Nested Fragments do not receive request permissions (onRequestPermissionsResult()) callback" 的事实。 .

但我在这里要做的是解释您观察到的关于 requestPermissions() 的容器 Activity 中收到的不同“奇怪”请求代码的行为。由 fragment 和嵌套 fragment 组成。

为了解释这一点,让我们考虑你的例子 -

- HomeActivity (AppCompatActivity)
  - FragmentA (V4 Fragment)
    - ViewPager
      - NestedFragmentA (V4 Fragment)
      - NestedFragmentB (v4 Fragment)
      - NestedFragmentC (v4 Fragment)
      - NestedFragmentD (v4 Fragment)
  - Fragment B (V4 Fragment)
  - Fragment C (V4 Fragment)

实现onRequestPermissionsResult()仅在 HomeActivity, FragmentA and NestedFragmentA为了更好地理解打印收到的请求代码的日志
    @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            Log.d("debug", "req code :: " + requestCode);     
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

还向 FragmentA 请求某些许可和 NestedFragmentA .让我们以位置权限为例
 requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 102); 

现在每当我们requestPermissions()从 fragment 或嵌套 fragment ,它调用Fragment class's requestPermissions()进而调用 FragmentHostCallback's onRequestPermissionsFromFragment()进而调用 FragmentActivity's requestPermissionsFromFragment() .现在这里是您的请求代码的转换。
验证您的请求代码后,它会调用
ActivityCompat's requestPermissions()

但是

使用转换后的请求代码 -
ActivityCompat.requestPermissions(this, permissions,((fragment.mIndex + 1) << 8) + (requestCode & 0xff));

所以更改后的请求代码是 -
((fragment.mIndex + 1) << 8) + (requestCode & 0xff)

在哪里 fragment.mIndex是 fragment 级别。所以对于直接 fragment (直接表示容器 Activity 的子项),它将是“0”
对于直接嵌套的 fragment (意味着 fragment 中的 fragment ),它将为“1”,并且它会根据 fragment 嵌套的深度而增加。

在我们的例子中,对于 FragmentA , 请求代码更改为
 (((0 + 1) << 8) + (102 & 0xff)) which computes to 358

对于 NestedFragmentA , 请求代码更改为
(((1 + 1) << 8) + (102 & 0xff)) which computes to 614

现在我们知道请求代码在哪里改变了。让我们从 ActivityCompat.requestPermissions() 继续.所以我们知道ActivityCompat.requestPermissions()因为我们使用这种方法来请求 Activity 的权限。
此外,我们知道这将执行一些操作,并且将向用户显示权限弹出窗口以接受/拒绝请求的权限。

现在我们来onRequestPermissionsResult() .当用户接受/拒绝时,onRequestPermissionsResult()的容器 Activity 将被调用,因为最终 ActivityCompat.requestPermissions()被称为。
假设您接受/拒绝来自 FragmentA 的许可所以你会得到日志-
 req code ::358

在那之后
super.onRequestPermissionsResult(requestCode, permissions, grantResults);

将调用 FragmentActivity's onRequestPermissionsResult()依次执行一些验证和调用
frag.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);

低头可以看到frag.onRequestPermissionsResult()中传入的请求码是不同的。 requestCode358及之后 &0xff它变成 102再次。
瞧!
这意味着尽管我们在 358 中获得了不同的请求代码 ( HomeActivity's onRequestPermissionsResult() ) ,但我们正在调用 FragmentA's onRequestPermissionsResult()使用原始请求代码 (102)
所以我们将从 FragmentA 获取这些日志-
 req code ::358

现在来到 NestedFragmentA .假设您接受/拒绝来自 NestedFragmentA 的许可所以你会得到HomeActivity的登录-
 req code ::614

但我们知道onRequestPermissionsResult()不会为嵌套 fragment 调用,因此我们不会在 NestedFragmentA's onRequestPermissionsResult() 中获得任何日志

我想我已经解释了我们在 requestPermissions() 的容器 Activity 中获得不同请求代码的原因。由 fragment 和嵌套 fragment 组成。

所以我会说对于没有嵌套的 fragment requestPermissions()仅从 fragment 中执行 onRequestPermissionsResult()仅存在于容器 Activity 中,而不存在于容器 Activity 中。
对于嵌套 fragment ,应该 requestPermissions()仅适用于来自父 fragment 的嵌套 fragment 所需的权限。看来这是唯一的解决方法。

关于android - 从 Fragment 请求权限时,在 Activity 的 onRequestPermissionsResult 中收到不正确的 resultCode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36170324/

有关android - 从 Fragment 请求权限时,在 Activity 的 onRequestPermissionsResult 中收到不正确的 resultCode的更多相关文章

  1. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  2. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  3. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  4. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

  5. ruby-on-rails - 获取并发布相同匹配项的请求 - 2

    在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g

  6. ruby-on-rails - 如何在 ActionController::TestCase 请求中设置内容类型 - 2

    我试图像这样在我的测试用例中执行获取:request.env['CONTENT_TYPE']='application/json'get:index,:application_name=>"Heka"虽然,它失败了:ActionView::MissingTemplate:Missingtemplatealarm_events/indexwith{:handlers=>[:builder,:haml,:erb,:rjs,:rhtml,:rxml],:locale=>[:en,:en],:formats=>[:html]尽管在我的Controller中我有:respond_to:html,

  7. ruby - 如何测试 (rspec) 花费太长时间的 http 请求? - 2

    如果使用rspec请求花费的时间太长,我该如何测试行为?我正在考虑使用线程来模拟这个:describe"Test"doit"shouldtimeoutiftherequesttakestoolong"dolambda{thread1=Thread.new{#net::httprequesttogoogle.com}thread2=Thread.new{sleep(xxseconds)}thread1.jointhread2.join}.shouldraise_errorendend我想确保在第一次发出请求后,另一个线程“启动”,在这种情况下只是休眠xx秒。然后我应该期望请求超时,因为执

  8. ruby - Sinatra 路由中定义的全局变量是否在请求之间共享? - 2

    假设我有:get'/'do$random=Random.rand()response.body=$randomend如果我每秒有数千个请求到达/,$random是否会被共享并“泄漏”到上下文之外,或者它会像getblock的“本地”变量一样?我想如果它是在get'/'do的上下文之外定义的,它确实会被共享,但我想知道在ruby​​中是否有我不知道的$机制。 最佳答案 ThispartoftheSinatraREADMEaboutscopeisalwayshelpfultoread但是,如果您只需要为请求保留变量,那么我认为我建议使用

  9. ruby - 无法安装 ruby​​ 1.9.3 获取请求的 URL 不存在 - 2

    运行以下命令时:rvminstall1.9.3我得到以下输出:Error:therequestedURLdoesnotexist:ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-.tar.bz2我已将rvm更新到最新版本并输入rvmreload有什么想法吗? 最佳答案 URL应该是这样的:ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.bz2尝试更新您的rvmrvmgethead然后安装1.9.3rvminstall1.9.3

  10. ruby-on-rails - Ruby On Rails,周数不正确 (-1) - 2

    我需要当前周数,如果我没有完全弄错的话现在是第51周?然而,当在控制台中测试它时,我得到了这个。Time.now=>2013-12-1911:08:25+0100Time.now.strftime('%U')=>"50"Date.today=>Thu,19Dec2013Date.today.strftime("%U").to_i=>50这是为什么? 最佳答案 Time.now.strftime('%V')将根据ISO8601为您提供周数。 关于ruby-on-rails-RubyOnRa

随机推荐