在Android 10及以上版本中,直接访问外部存储器中的文件需要使用新的文件访问权限模型。以下是一个解决方法的示例:
import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_CODE = 100;
private static final int OPEN_DOCUMENT_REQUEST_CODE = 200;
private Button openButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
openButton = findViewById(R.id.open_button);
openButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkPermissionsAndOpenDocument();
}
});
}
private void checkPermissionsAndOpenDocument() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
PERMISSION_REQUEST_CODE);
} else {
openDocument();
}
}
private void openDocument() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// 在Android 10及以上版本中使用新的文件访问方法
openDocumentUsingStorageAccessFramework();
} else {
// 在Android 9及以下版本中使用传统的文件访问方法
openDocumentUsingTraditionalMethod();
}
}
private void openDocumentUsingStorageAccessFramework() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, OPEN_DOCUMENT_REQUEST_CODE);
}
private void openDocumentUsingTraditionalMethod() {
// 获取数据库文件路径
String dbPath = "/sdcard/database.db";
// 打开数据库连接
SQLiteDatabase db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY);
// 查询数据库
Cursor cursor = db.rawQuery("SELECT * FROM table", null);
// 处理查询结果
if (cursor != null && cursor.moveToFirst()) {
do {
// 处理每一行数据
String data = cursor.getString(cursor.getColumnIndex("data"));
// ...
} while (cursor.moveToNext());
}
// 关闭游标和数据库连接
if (cursor != null) {
cursor.close();
}
db.close();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openDocument();
} else {
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == OPEN_DOCUMENT_REQUEST_CODE && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
if (uri != null) {
// 获取文件路径
String filePath = getFilePathFromUri(uri);
// 使用文件路径进行访问
// ...
}
}
}
private String getFilePathFromUri(Uri uri) {
String filePath = null;
if (DocumentsContract.isDocumentUri(this, uri)) {
// 使用Storage Access Framework获取文件路径
try (Cursor cursor = getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
filePath = cursor.getString(cursor.getColumnIndex(DocumentsContract.Document.COLUMN_DOCUMENT_ID));
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
// 直接获取文件路径
filePath = uri.getPath();
}
return filePath;
}
}
在上面的示例中,首先检查是否授予了文件访问权限,如果没有授予,则请求权限。然后,根据设