API 26运行时权限和android.os.FileUriExposedException

时间:2018-11-10 11:28:27

标签: android android-layout android-fragments android-fragmentactivity rxpermissions

我的应用需要以下权限。已合并到AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.autofocus"/>

升级到API 26后

  

(targetSdkVersion 26)

某些功能不起作用。因为我需要合并运行时权限。我正在使用RxPermission。 问题是我的大多数实现都放在helper类中(而不是在main活动中)。 当我尝试使用帮助程序库时出现错误-。Can not resolve constructor 我也尝试了以下选项-

  

RxPermissions rxPermissions =新的RxPermissions(((FragmentActivity)mContext);

由于RxPermission要求以Fragment为目标。我们可以在主要活动中向用户询问所有权限吗?示例代码将对我有所帮助。 reference

的项目代码

[已修复] 现在,我正在从活动中致电。 Reference代码已更改-

RxPermissions rxPermissions=new RxPermissions(this);
rxPermissions.request(Manifest.permission.CAMERA)
        .subscribe(granted -> {
            if (granted) {

                //LogUtil.e(LOG_TAG, "Granted external permission");
                setContentView(R.layout.activity_local_album);
                ViewGroup backGround = (ViewGroup) findViewById(R.id.background);
                MyUtil.setBackgroundBlur(backGround, this);

                initAdapter();
                assignViews();

            } else {
                // Oups permission denied
            }
        });

[新错误] 我收到android.os.FileUriExposedException:错误。代码:

public void onClick(View v) {
    switch (v.getId()) {
        // 返回
        case R.id.action_back:
            myFinish();
            break;
        // 拍照
        case R.id.action_capture:
            PackageManager pm = getPackageManager();
            // FEATURE_CAMERA - 后置相机
            // FEATURE_CAMERA_FRONT - 前置相机
            if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
                // 访问相机类型
                int requestType;
                // 截取主题壁纸
                if (mRequestType != 2) {
                    requestType = REQUEST_IMAGE_CAPTURE_THEME;
                } else { // 截取二维码logo
                    requestType = REQUEST_IMAGE_CAPTURE_QRCODE_LOGO;
                }

                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                mImageUri = Uri.fromFile(MyUtil.getFileDirectory(this, "/Android/data/" +
                        getPackageName() + "/capture/temporary.jpg"));
                intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
                startActivityForResult(intent, requestType);
                overridePendingTransition(0, R.anim.zoomin);
            }
  

错误

 Process: com.bisw.weac, PID: 20997
android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.bisw.weac/capture/temporary.jpg exposed beyond app through ClipData.Item.getUri()
    at android.os.StrictMode.onFileUriExposed(StrictMode.java:1958)
    at android.net.Uri.checkFileUriExposed(Uri.java:2356)
    at android.content.ClipData.prepareToLeaveProcess(ClipData.java:944)
    at android.content.Intent.prepareToLeaveProcess(Intent.java:10480)
    at android.content.Intent.prepareToLeaveProcess(Intent.java:10465)
    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1616)
    at android.app.Activity.startActivityForResult(Activity.java:4564)
    at android.support.v4.app.BaseFragmentActivityApi16.startActivityForResult(BaseFragmentActivityApi16.java:54)
    at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:68)
    at android.app.Activity.startActivityForResult(Activity.java:4522)
    at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:751)
    at com.bisw.weac.activities.LocalAlbumActivity.onClick(LocalAlbumActivity.java:222)
    at android.view.View.performClick(View.java:6877)
    at android.widget.TextView.performClick(TextView.java:12651)
    at android.view.View$PerformClick.run(View.java:26069)
    at android.os.Handler.handleCallback(Handler.java:789)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6938)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

2 个答案:

答案 0 :(得分:1)

  

我的应用需要以下权限

请注意,除非您的应用程序已通过固件签名密钥签名或安装在特权应用程序分区(主要是针对root用户的设备)上,否则无法持有return [ word for word in allWords if sum( [ LETTER_SCORES[letter] for letter in word ] ) == targetScore ]

  

我们可以要求用户在主要活动中获得所有许可吗?

根据the documentation,您别无选择。根据这些指示,仅当您从MOUNT_UNMOUNT_FILESYTEMS的{​​{1}}(或onCreate()的{​​{1}})请求权限时,RxPermissions才有效。 / p>

  

示例代码对我有帮助

除文档外,the RxPermissions GitHub repository还有一个示例应用程序。 Here is the v0.9.3 edition of that sample app

答案 1 :(得分:0)

最后,我能够解决从主类调用的问题。

 RxPermissions rxPermissions=new RxPermissions(this);
    rxPermissions.request(Manifest.permission.READ_EXTERNAL_STORAGE)
            .subscribe(granted -> {
                if (granted) {
                    customDefineBtn.setOnClickListener(this);
                    LogUtil.e(LOG_TAG, "Granted external permission");

                } else {
                    // Oups permission denied
                }
            });