权限拒绝:重新启动应用程序时打开提供程序com.android.providers.media.MediaDocumentsProvider - java

我有一个Android应用程序,允许用户如下选择个人资料照片:

public void pickImage(View view) {
    Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
    getIntent.setType("image/*");

    Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    pickIntent.setType("image/*");

    Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});

    startActivityForResult(chooserIntent, 1);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Context context = getApplicationContext();
    if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
        if (data == null) {
            //Display an error
            return;
        }
        try {
            ImageView im = findViewById(R.id.circularImageView);
            uri = data.getData();
            im.setImageURI(uri);
            String image = uri.toString();


            Log.d("ImageS", image);

            SqlHelper db = new SqlHelper(this);
            Intent i = getIntent();
            String userid = i.getStringExtra("Name");
            db.updateImage(userid, image);

        }catch (Exception e){

        }
        //Now you can do whatever you want with your inpustream, save it as file, upload to a server, decode a bitmap...
    }
}

在重新启动应用程序之前,一切正常。在这里,我想从数据库中检索图像,一切正常:

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    ActionBar actionBar = getActionBar();
    actionBar.hide();
    setContentView(R.layout.activity_main);

    String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MANAGE_DOCUMENTS};
    for(String permission: permissions){
        if (ContextCompat.checkSelfPermission(this, permission)
                != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    permission)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed; request the permission
                ActivityCompat.requestPermissions(this,
                        permissions, 0);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }
    }



    mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
    ImageView logo = findViewById(R.id.imageView4);
    logo.setImageResource(R.drawable.logo);
    SqlHelper db = new SqlHelper(this);

    //Add some locations for the users
    a.setLatitude(Latitude[0]);
    a.setLongitude(Longitude[0]);
    b.setLatitude(Latitude[1]);
    b.setLongitude(Longitude[1]);

    Intent intentR = getIntent();
    String name = intentR.getStringExtra("Name");


    // Check for the freshest data.

    ImageView im1 = findViewById(R.id.circularImageView2);
    im1.setImageURI(null);
    String iS = db.getImage(name);
    Log.d("ImageR", iS);
    //
    // Uri uri = Uri.parse(image);
    //Log.d("Equals", String.valueOf(iS.equals(String.valueOf(R.drawable.imageuser))));
    if(iS.equals(String.valueOf(R.drawable.imageuser))){
        im1.setImageResource(Integer.parseInt(iS));
    }else{
        Uri uri = Uri.parse(iS);
        ContentResolver contentResolver= getContentResolver();
        ParcelFileDescriptor parcelFileDescriptor = null;
        try {
//HERE COMES THE PROBLEM//
            parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r"); /
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        try {
            parcelFileDescriptor.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        im1.setImageBitmap(image);
    }


    ArrayList<String> notifications = db.getNotifications(name);
    if(notifications.size()>0) {
        ImageView im = findViewById(R.id.bell);
        ImageView c = findViewById(R.id.circleN);
        TextView tx = findViewById(R.id.nNot);
        im.setVisibility(View.VISIBLE);
        c.setVisibility(View.VISIBLE);
        tx.setVisibility(View.VISIBLE);
        tx.setText(String.valueOf(notifications.size()));
    }

   // db.addUser(new User("Babouche", "Babouche", location[1]), this);
   // db.addUser(new User("Arturo", "Arturo", location[0]), this);


}`

问题是,当我重新启动应用程序时,进入用户更改图像的活动时,出现以下错误:

FATAL EXCEPTION: main
Process: com.example.arturopavon.finalproject, PID: 1445
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.arturopavon.finalproject/com.example.arturopavon.finalproject.MainActivity} : java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{47cb71a 1445:com.example.arturopavon.finalproject/u0a294} (pid=1445, uid=10294) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

我已经为我的应用设置了读取内部存储的权限,但是重启后好像无法使用。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.arturopavon.finalproject">

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission
    android:name="android.permission.MANAGE_DOCUMENTS"/>
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="BiteME"
    android:roundIcon="@drawable/logo"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".LoginActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".MainActivity" />
    <activity android:name=".UserActivity" />
    <activity android:name=".UserPreferences" />
    <activity android:name=".SignUp" />
    <activity android:name=".Notifications" />

</application>
    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.login);
    String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MANAGE_DOCUMENTS};
    for(String permission: permissions){
        if (ContextCompat.checkSelfPermission(this, permission)
                != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    permission)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed; request the permission
                ActivityCompat.requestPermissions(this,
                        permissions, 0);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }
    }

}

关于如何解决这个问题的任何想法?

参考方案

如SAF Storage Access Framework (SAF)中所述:

如果您希望您的应用仅读取/导入数据,请使用ACTION_GET_CONTENT。通过这种方法,应用程序可以导入数据的副本,例如图像文件。
如果您希望您的应用对文件提供者拥有的文件具有长期,持久的访问权限,请使用ACTION_OPEN_DOCUMENT。

看来您有第二个用例。
所以代替:
Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
尝试
Intent getIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
该文档提供了一个sample来使用它。

单击后退按钮时,滑行加载的图像会重置 - java

我正在滑行加载图像。但是问题是,当我们按下后退按钮时,从视图中清除加载的图像。无论我在活动图像视图中还是在recyclerview中加载图像,我都面临着这个问题。我正在加载图像GlideApp.with(this) .load(url) .into(mToolbarAvatar); 参考方案 在代码中添加两行.skipMemoryCache(true) .d…

有没有一种方法可以在一个mediaplayer对象中播放mp3文件? - java

我可以使用Java android中的Mediaplayer类播放声音。我这样制作一个Mediaplayer对象。Mediaplayer mp=Mediaplayer.create(this,R.raw.mysong); 然后开始播放,但是如果我有一首以上的歌曲必须播放。我需要为每个人都做对象吗?我要说的是Mediaplayer类是否具有可以清除旧歌曲并放上…

Android Firebase:将数据保存到数据库 - java

我正在尝试从Firebase保存和检索数据,但是在获取正确的语法时遇到了一些麻烦。用户通过电子邮件和密码的身份验证方法进行注册,并使用相同的详细信息登录。我有两个编辑文本字段,要求输入名称和语句。在两个编辑文本框下面有一个按钮,用于将数据保存到数据库。private void saveQuote(){ String name = author.getText…

Android-通过ArrayList时应用崩溃 - java

我通过单击按钮将类型为ArrayList的主题传递给另一个活动。但是此后该应用程序崩溃了。这是我的第一个活动的摘录。 ComputeGrades是按下按钮时要调用的方法。我没有为显示主题的动态表添加代码。public class ACMActivity2A extends Activity { ArrayList<Subject> subject…

如何自定义Xamarin形式的滑块? - java

我要自定义滑块,使其看起来如下图所示:我在.xaml文件中的代码:<Slider MaximumTrackColor="Black" MinimumTrackColor="Black" HeightRequest="50" ThumbColor="Black" ThumbI…