Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
Ask Question
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.
–
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";
–
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
–
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();
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";
mPath= Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpeg";
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>
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/
you need to grant permission on the Android emulator:
touch your app in Android Emulator 2 seconds,
go to app info.
go to permissions.
select Files and media
Allow management files.
You can save photos in DCIM or create a directory in it in Android 11, which is a good pattern. I'm having the same problem, however after I do this, everything works fine.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) {
Yourpath= getActivity().getExternalFilesDir
(Environment.DIRECTORY_DCIM) + "/" + nameoffile + ".jpeg";
Yourpath=Environment.getExternalStorageDirectory()
.toString() + "/" + nameoffile + ".jpeg";
Happy Coding!
Starting with SDK version 30, you can NOT extend android:requestLegacyExternalStorage="true"
. Instead modify you ImageLoader library a little. I see you have to modify you file path: File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Caramel");
into something like File dir = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "Caramel");
. This should do a trick.
This worked for me: MANAGE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE
in file pubspec.yaml
dependencies:
flutter:
sdk: flutter
http: ^0.13.4
permission_handler: ^9.0.2
flutter_downloader: ^1.5.2
path_provider: ^2.0.9
external_path: ^1.0.1
in file AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:label="ejemplo_test"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">
<provider
android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
android:authorities="${applicationId}.flutter_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
in file main.dart
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await FlutterDownloader.initialize(
debug: true
runApp(const MyApp());
class _MyHomePageState extends State<MyHomePage> {
String localPath = "";
int progress = 0;
ReceivePort _port = ReceivePort();
@override
void initState(){
super.initState();
initPlatformState();
IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
_port.listen((dynamic data) {
String id = data[0];
DownloadTaskStatus status = data[1];
int progress = data[2];
setState((){ });
FlutterDownloader.registerCallback(downloadCallback);
_requestPermissions();
@override
void dispose() {
IsolateNameServer.removePortNameMapping('downloader_send_port');
super.dispose();
static void downloadCallback(String id, DownloadTaskStatus status, int progress) {
final SendPort? send = IsolateNameServer.lookupPortByName('downloader_send_port');
send?.send([id, status, progress]);
Future<void> initPlatformState() async {
final path = await ExternalPath.getExternalStorageDirectories();
setState(() {
localPath = path[0].toString()+"/Android/media/NameAPP";
log("path: ${localPath}");
final savedDir = Directory(localPath);
bool hasExisted = await savedDir.exists();
if (!hasExisted) {
savedDir.create(recursive: true);
SaveImages(String url,String name) async{
log("url: ${url}");
log("name: ${name}");
final id = await FlutterDownloader.enqueue(
url:"${url}",
savedDir: localPath,
fileName: name.toString(),
showNotification: true,
openFileFromNotification: true,
Future<void> _requestPermissions() async {
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
Permission.manageExternalStorage
].request();
log("statuses: ${statuses}");
if (statuses == PermissionStatus.granted) {
//createFolder("TiendaOnline");
MensajeToast("Permission granted.",Colors.green);
} else if (statuses == PermissionStatus.denied) {
MensajeToast("Denied. Show a dialog with a reason and again ask for the permission.",Colors.red);
} else if (statuses == PermissionStatus.permanentlyDenied) {
MensajeToast("Take the user to the settings page.",Colors.red);
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.