Внешнее хранилище: невозможно запросить файл, к которому у меня есть доступ для чтения - PullRequest
0 голосов
/ 02 февраля 2020

Я использую намерение "ACTION_OPEN_DOCUMENT", чтобы выбрать файл и открыть его.

Это прекрасно работает, когда я go для чтения файла.

Однако, когда файл находится на ВНЕШНЕМ хранилище, и я запускаю запрос, чтобы получить имя файла, моя программа падает. Если файл находится во ВНУТРЕННЕМ хранилище, у меня нет проблем.

У меня есть (и я проверяю) разрешения на доступ к внешнему хранилищу.

У меня есть запрос, заключенный в попытку {}, но исключение не пойман. Я занимаюсь разработкой книги Chrome, поэтому я не могу запустить отладчик на ней. Но я изолировал проблему с result = cursor.getString (cursor.getColumnIndex (OpenableColumns.DISPLAY_NAME)); оператор.

Я знаю, что доступ к файлам на внешнем хранилище был ограничен , но я бы подумал, что если я смогу прочитать файл, я тоже смогу его запросить.

Вот мой код:

package com.muddco.demo3;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;


public class MainActivity extends AppCompatActivity {

    Activity mAct;
    TextView rvalue, fnamevalue;
    Button btn1, btn2;
    Uri fileUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn1 = findViewById(R.id.btn1);
        btn2 = findViewById(R.id.btn2);
        rvalue = findViewById(R.id.readResult);
        fnamevalue = findViewById(R.id.textView2);
        mAct = this;

        ActivityCompat.requestPermissions(MainActivity.this,
                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                /*
                 * Launch a file picker
                 */
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("*/*");

                startActivityForResult(Intent.createChooser(intent, "Select a GPX file"), 1);
            }
        });

        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                /*
                 * Get and display file name
                 */
                String fname = getFileName(fileUri);
                fnamevalue.setText(fname);
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {

        switch (requestCode) {
            case 1: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission granted and now can proceed
                    Toast.makeText(MainActivity.this, "Permission granted", Toast.LENGTH_SHORT).show();

                } else {

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
                }
                return;
            }
            // add other cases for more permissions
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        InputStream inputStream = null;
        Uri uri = null;

        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == 1) {
                // Process GPX file
                uri = data.getData();
                try {
                     inputStream = getBaseContext().getContentResolver().openInputStream(uri);

                    rvalue.setText(readFile(inputStream));

                } catch (FileNotFoundException e) {
                    Toast.makeText(this, "File not found: " + uri.toString(), Toast.LENGTH_SHORT).show();
                }
                //String fName = getFileName(uri);
                //Toast.makeText(mAct, "Filename: "+fName, Toast.LENGTH_LONG).show();
                fileUri = uri;
                btn2.setVisibility(View.VISIBLE);
            }
        }
    }

    /*
     * Read a FileStream
     *
     */
    String readFile(InputStream is) {
        String ret = "";
        String line = null;

        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            while ((line = br.readLine()) != null) {
                ret += line + "\n";
            }
            br.close();
        } catch (Exception e) {
            // if any I/O error occurs
            e.printStackTrace();
            ret = "Exception!";
        }
        return ret;
    }

    /*
    * Obtain the filename from a URI
     */
public String getFileName(Uri uri) {
        String result = "<empty>";
        Cursor cursor;

        if (uri.getScheme().equals("content")) {
            ContentResolver cr = getContentResolver();
            try {
                cursor = cr.query(uri, null, null, null, null);
            } catch (Exception e) {
                Toast.makeText(this, "Cursor exception: " + e.toString(), Toast.LENGTH_LONG).show();
                return null;
            }
            try {
                if (cursor != null && cursor.moveToFirst()) {
                    //
                    // THE NEXT STATEMENT CRASHES WHEN FILE RESIDES ON EXTERNAL STORAGE
                    //
                    result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
                else {
                    Toast.makeText(mAct, "Bad cursor", Toast.LENGTH_SHORT).show();
                    return "Bad Cursor";
                }
            } catch (Exception e) {
                Toast.makeText(this, "Cursor exception: " + e.toString(), Toast.LENGTH_LONG).show();
                return "Cursoe Exception";
            } finally {
                cursor.close();
            }
        }
        else
            result="Non content URI";

        return result;
    }
}

Когда я нажимаю первую кнопку , запросчик файла появляется, и я выбираю свой тестовый текстовый файл. Содержимое файла отображается в текстовом поле, затем отображается вторая кнопка. Когда эта вторая кнопка нажата, я запрашиваю файл и помещаю имя файла во второе текстовое поле.

Весь проект вместе с файлом test.txt, который я использую для тестирования, можно найти здесь

...