I faced this problem when I tried to save the image to internal storage on android.
public static String setImage(Bitmap image) {
if (image != null) {
FileOutputStream outputStream = null;
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Caramel");
dir.mkdir();
String fileName = System.currentTimeMillis() + ".jpg";
File file = new File(dir, fileName);
try {
outputStream = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.close();
return fileName;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
All goes nice and well, and I can see my Bitmap image in debug mode, but all the same, i get the next error:
W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Caramel/1587724428205.jpg: open failed: EPERM (Operation not permitted)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:495)
W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
W/System.err: at com.example.caramel.Position.setImage(Position.java:176)
W/System.err: at com.example.caramel.PositionActivity.onActivityResult(PositionActivity.java:129)
W/System.err: at android.app.Activity.dispatchActivityResult(Activity.java:8300)
W/System.err: at android.app.ActivityThread.deliverResults(ActivityThread.java:4905)
W/System.err: at android.app.ActivityThread.handleSendResult(ActivityThread.java:4953)
W/System.err: at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
W/System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
W/System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:106)
W/System.err: at android.os.Looper.loop(Looper.java:216)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7464)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
W/System.err: Caused by: android.system.ErrnoException: open failed: EPERM (Operation not permitted)
W/System.err: at libcore.io.Linux.open(Native Method)
W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
W/System.err: at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7360)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:481)
W/System.err: ... 17 more
It seems, that reason could be in my Manifest.xml file, but i've already set these permissions:
<uses-permission android:name="android.permission.CAMERA" />
<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.c2dm.permission.RECEIVE" />
Thanks for your support, guys.
As a temporary fix you could do: In your android/app/src/main/AndroidManifest.xml
file, at
<application android:label="APPNAME" android:icon="ICONNAME" ...>
add android:requestLegacyExternalStorage="true"
, like so:
<application android:label="APPNAME" android:icon="ICONNAME" android:requestLegacyExternalStorage="true">
It will then use the pre-Android 10 way of requesting access to storage, so you can still save your file as you could earlier.
But caution: After you update your app to target Android 11 (API level 30), the system ignores the requestLegacyExternalStorage attribute when your app is running on Android 11 devices, so your app must be ready to support scoped storage and to migrate app data for users on those devices. See https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage for more info
I got the issue In android 11 ":" is not allowed in file name. And when you append date at the end of file name its add ":" at the end. so just replace all ":" with "." and its working fine.
String fileName =
System.currentTimeMillis().toString().replaceAll(":", ".") + ".jpg";
The permission system in android is very strict, you must take this into account when writing to internal memory Try something like this:
public class MainActivity extends AppCompatActivity {
Button save;
Bitmap bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Drawable drawable = getResources().getDrawable(R.drawable.mario);
bitmap = ((BitmapDrawable) drawable).getBitmap();
save = findViewById(R.id.save);
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ContextWrapper cw = new ContextWrapper(getApplicationContext());
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
File file = new File(directory, "UniqueFileName" + ".jpg");
if (!file.exists()) {
Log.d("path", file.toString());
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
}
});
}
}
Add the following attribute in your app's Manifest.xml file inside the application tag:
android:requestLegacyExternalStorage="true"
Finally, it will look like this:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:requestLegacyExternalStorage="true">
...
</application>
In android 11 you can use this pattern
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) {
mPath= getActivity().getExternalFilesDir(Environment.DIRECTORY_DCIM) + "/" + now + ".jpeg";
}
else
{
mPath= Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpeg";
}
I would suggest to change it to
ContextWrapper cw = new ContextWrapper(mContext);
String fullPath =cw.getExternalFilesDir(Environment.DIRECTORY_MUSIC).toString();
File directory = cw.getExternalFilesDir(Environment.DIRECTORY_MUSIC);
check it here https://www.programmersought.com/article/50766505696/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With