Я использую намерение "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, который я использую для тестирования, можно найти здесь