Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving images in external storage works on emulator, but not on physical phone with the same source code

I am trying to save some photos from a server. I have used some parts that i've found, and it was working on emulator(i was using the directory for the photos as Envinronment.getExternalStorageDirectory). Now, I tried to add the app to my phone, and it won't work. When I try to get the images from memory, I get the error: E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/PictogrameProbleme/20.png: open failed: ENOENT (No such file or directory) which means the photos are not saved there in the first place. This is the code I am running to save and retrieve the photos:

LATEST EDIT: After serious testing and debugging and so on, I came past another issue: Failed to create image decoder with message 'unimplemented'

EDIT: I have also added the required permissions in manifest, plus asking for them at runtime.

EDIT: I have edited the code to save on External memory, but the same error occurs. I have used the logcat to get the LOCATIE, from where the the file should be retrieved, and the logcat give me the location of the file as: storage/emulated/0/...

public static String saveToSdCard(Bitmap bitmap, String filename) {

        String stored = null;

        File sdcard = Environment.getExternalStorageDirectory() ;

        File folder = new File(sdcard.getAbsoluteFile(), "/PictogrameProbleme");//the dot makes this directory hidden to the user
        folder.mkdir();
        File file = new File(folder.getAbsoluteFile(), filename + ".png") ;
        if (file.exists())
            return stored ;

        try {
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
            stored = "success";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stored;
    }

    public static File getImage(String imagename) {

        File mediaImage = null;
        try {
            String root = Environment.getExternalStorageDirectory().toString();
            File myDir = new File(root);
            if (!myDir.exists())
                return null;

            mediaImage = new File(myDir.getPath() + "/PictogrameProbleme/"+imagename);
            Log.d("LOCATIE",myDir.getPath() + "/PictogrameProbleme/"+imagename );
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return mediaImage;
    }
    public static boolean checkifImageExists(String imagename)
    {
        Bitmap b = null ;
        File file = ImageStorage.getImage(imagename+".png");
        assert file != null;
        String path = file.getAbsolutePath();

        if (path != null)
            b = BitmapFactory.decodeFile(path);

        if(b == null ||  b.equals(""))
        {
            return false ;
        }
        return true ;
    }
}

EDIT: I have added the code that works on emulator, but not on phone.

EDIT: Added permissions. in onCreate I call the function requestWritePermission().

 @Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    if(requestCode == WRITE_PERMISSION){
        if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
            Log.d(TAG, "Write Permission Failed");
            Toast.makeText(this, "You must allow permission write external storage to your mobile device.", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

private void requestWritePermission(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},WRITE_PERMISSION);
        }
    }
}

Also in manifest:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

EDIT: Added the way I get the photos from URL, maybe there's the problem.

private void SalveazaPictograme(final String url, final String imagename) {
     class GetImage extends AsyncTask<Object, Object, Object> {
        String requestUrl = url;
        String imagename_ = imagename;


        @Override
        protected Object doInBackground(Object... objects) {
            try {
                URL url = new URL(requestUrl);
                URLConnection conn = url.openConnection();
                bitmap = BitmapFactory.decodeStream(conn.getInputStream());

            } catch (Exception ex) {
            }
           return null;
        }

        @Override
        protected void onPostExecute(Object o) {
            if (!ImageStorage.checkifImageExists(imagename_)) {
                ImageStorage.saveToSdCard(bitmap, imagename_);
                Log.d("LALA","lalalallalaa");
            }

        }
    }
     GetImage au = new GetImage();
     au.execute();
}

I declare bitmap at the start of the program.

like image 386
Costin Avatar asked Dec 08 '25 08:12

Costin


1 Answers

I have a hunch your problem might be related to your phone running Android Q. look at my answer to this question. external files directory should not be storage/emulated/0/ but rather storage/emulated/0/Android/data/your.package.name/ try using Context.getExternalFilesDir(null) in order to get your external files directory instead.

as you can see from the documentation of Environment.getExternalStorageDirectory() it is deprecated since API 29 and wont return a valid file path if you are targeting Android Q.

let me know if this helps solve your problem.

like image 165
quealegriamasalegre Avatar answered Dec 10 '25 21:12

quealegriamasalegre



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!