我正在尝试通过从照片中选择图像来获取文件并获取意图数据,将文件保存在内部存储器中并使用该文件加载到图像视图中。
但我收到如下错误:
java.io.FileNotFoundException:/storage/emulated/0/Android/data/com.dailyfaithapp.dailyfaith/Files/MI_10052020_1711.png:打开失败:ENOENT(没有这样的文件或目录)
我在 24 上检查了较低版本的 api,它工作了一两次,但又失败了。
在 api 29 上它根本不起作用。为此,我关注了这个网址: https ://medium.com/@sriramaripirala/android-10-open-failed-eacces-permission-denied-da8b630a89df
我检查了java中的代码并尝试了相同的方法,但仍然给出了错误。
我还在检查运行时权限并在清单文件中指定了权限。
以下是我的代码:
<uses-permission android:name = "android.permission.INTERNET" />
<uses-permission android:name = "android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name = "android.permission.WAKE_LOCK" />
<uses-permission android:name = "android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name = "com.google.android.apps.photos.permission.GOOGLE_PHOTOS" />
检查运行时权限:
private boolean checkPermission() {
return ContextCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
;
}
private void requestPermissionAndContinue() {
if (ContextCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, WRITE_EXTERNAL_STORAGE)
&& ActivityCompat.shouldShowRequestPermissionRationale(this, READ_EXTERNAL_STORAGE)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
alertBuilder.setCancelable(true);
alertBuilder.setTitle("Allow Daily Faith to access photos," +
"media, and files on your device?");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(ThemesActivity.this,
new String[]{WRITE_EXTERNAL_STORAGE
, READ_EXTERNAL_STORAGE}, 200);
}
});
AlertDialog alert = alertBuilder.create();
alert.show();
Log.e("", "permission denied, show dialog");
} else {
ActivityCompat.requestPermissions(ThemesActivity.this,
new String[]{WRITE_EXTERNAL_STORAGE,
READ_EXTERNAL_STORAGE}, 200);
}
} else {
selectImageFromGallery();
}
}
检查是否授予权限:
if (!checkPermission()) {
selectImageFromGallery();
} else {
if (checkPermission()) {
requestPermissionAndContinue();
} else {
selectImageFromGallery();
}
}
开业意向:
public void selectImageFromGallery()
{
Intent pickPhoto = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , 2);
}
获取有关结果的意图数据:
@RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 2) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a image.
// The Intent's data Uri identifies which item was selected.
if (data != null) {
customTheme = true;
// This is the key line item, URI specifies the name of the data
mImageUri = data.getData();
// Saves image URI as string to Default Shared Preferences
SharedPreferencesData sharedPreferencesData =
new SharedPreferencesData(this);
sharedPreferencesData.setStr("customThemeSet","true");
try {
Bitmap bitmap =
MediaStore.Images.Media.getBitmap(getContentResolver(), mImageUri);
/* Utils.storeImage(bitmap,
ThemesActivity.this);
File file = Utils.getOutputMediaFile(ThemesActivity.this);
*/
try {
final ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(
mImageUri, "r");
final FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
Utils.storeImage(bitmap,
ThemesActivity.this);
File file = Utils.getOutputMediaFile(ThemesActivity.this);
int color = Utils.getDominantColor(bitmap);
Log.d("Bitmap", bitmap.toString());
Boolean isDark = Utils.isColorDark(color);
if(customTheme) {
for (Themes themes : themesArrayList) {
themes.setCustomTheme(file.getPath());
themes.setDark(isDark);
}
if(isDark)
sharedPreferencesData.setStr("ThemeColor","dark");
else
sharedPreferencesData.setStr("ThemeColor","light");
themesAdapter = new ThemesAdapter(themesArrayList, this,customTheme);
recyclerView.setAdapter(themesAdapter);
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
Log.e("Failed", "Failed to Parse Image Uri", e);
try {
throw new Exception("failed to parse image uri");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
}
保存和获取文件
public static File getOutputMediaFile(Context context){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/"
+ context.getApplicationContext().getPackageName()
+ "/Files");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
mediaStorageDir.mkdirs();
}
else {
return null;
}
// Create a media file name
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
File mediaFile;
String mImageName="MI_"+ timeStamp +".png";
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
return mediaFile;
}
public static void storeImage(Bitmap image,Context context) {
File pictureFile = getOutputMediaFile(context);
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: ");// e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
image.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
在我只使用以上两个函数保存文件时出现 EACCESS 错误之前。
后来我尝试了 Parcel 文件描述符但不工作 为什么我收到这个错误?是否也仅在 api 级别 29 或以下?在所有设备上运行的解决方案是什么?