我正在使用“ ACTION_OPEN_DOCUMENT”意图选择一个文件并打开它。
当我去阅读文件时,这很好。
但是,当文件驻留在EXTERNAL存储器上时,我运行查询以获取文件名,则程序崩溃。如果文件位于内部存储中,则没有问题。
我确实具有(并检查)外部存储访问权限。
我将查询括在try {}中,但未捕获到异常。我正在开发一本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文件here