2

I'm using GridView to load json data holding images. When I built project it happened some exceptions

AndroidManifest.xml:

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

FileCache class:

public class FileCache {

private File cacheDir;

public FileCache(Context context) {
    // Find the dir to save cached images
    if (android.os.Environment.getExternalStorageState().equals(
            android.os.Environment.MEDIA_MOUNTED))
        cacheDir = new File(
                android.os.Environment.getExternalStorageDirectory(),
                "JsonParseTutorialCache");
    else
        cacheDir = context.getCacheDir();
    if (!cacheDir.exists())
        cacheDir.mkdirs();
}

public File getFile(String url) throws IOException {
    String filename = String.valueOf(url.hashCode());
    // String filename = URLEncoder.encode(url);
    File f = new File(cacheDir, filename);
    f.createNewFile();
    return f;
}

public void clear() {
    File[] files = cacheDir.listFiles();
    if (files == null)
        return;
    for (File f : files)
        f.delete();
 }

}

Logcat:

W/System.err: java.io.IOException: open failed: ENOENT (No such file or directory)
W/System.err:     at java.io.File.createNewFile(File.java:939)
W/System.err:     at    com.totoroads.android.app.FileCache.getFile(FileCache.java:33) 
W/System.err:     at com.totoroads.android.app.ImageLoader.getBitmap(ImageLoader.java:64)
W/System.err:     at com.totoroads.android.app.ImageLoader.access$000(ImageLoader.java:29)
W/System.err:     at com.totoroads.android.app.ImageLoader$PhotosLoader.run(ImageLoader.java:155)
W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
W/System.err:     at java.lang.Thread.run(Thread.java:818)
W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
W/System.err:     at libcore.io.Posix.open(Native Method)
W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
W/System.err:     at java.io.File.createNewFile(File.java:932)
W/System.err:   ... 9 more

I want to download, read and display images on GridView, How to fix those exceptions?

luongkhanh
  • 1,753
  • 2
  • 16
  • 30

4 Answers4

11

In my case, it was:

If targeting Android 10 (API level 29) or higher, set the value of requestLegacyExternalStorage to true in your app's AndroidManifest file.

<manifest ... >
<application android:requestLegacyExternalStorage="true" ... >
sɐunıɔןɐqɐp
  • 3,332
  • 15
  • 36
  • 40
Duong.Nguyen
  • 373
  • 3
  • 13
  • Awesome.. this was indeed the issue in my case, where despite WRITE_EXTERNAL_STORAGE permission at runtime, i was not able to create the directory. – Yogesh Kumar Gupta Aug 23 '20 at 16:06
  • This was the case for me as well. Thanks a lot for help. – Jim Jan 29 '21 at 08:35
  • FYI, the answer above is a short way to resolve the problem. But as far as you should migrate your data from local to the scope store before upgrade to android 11. you can check here to know how can migrate: https://developer.android.com/training/data-storage/use-cases#migrate-legacy-storage – Duong.Nguyen May 17 '21 at 08:01
3

The code in FileCache.java is

public File getFile(String url) {
    String filename = String.valueOf(url.hashCode());
    // String filename = URLEncoder.encode(url);
    File f = new File(cacheDir, filename);
    return f;
}

A new file object has been created, but the file may not exist. So, replace the above code with

public File getFile(String url) {
    String filename = String.valueOf(url.hashCode());
    // String filename = URLEncoder.encode(url);
    File f = new File(cacheDir, filename);
    f.createNewFile();
    return f;
}

Hope, it helps.

Edit : As you're running your code on >= Android 6.0, you gotta request for permission to access External Storage at runtime. Adding those in AndroidManifest.xml isn't enough. You can use this link on how to do it.

Community
  • 1
  • 1
Srikanth R
  • 410
  • 5
  • 17
1

You can use Picasso library for showing images in grid view. it is provide one line code for load image. Use Library function for load images--

Picasso.with(context).load("YOURIMAGE").into(imageView);

You can also resize images according to your requirement. and it is also manage internally cache mechanism

Refer Link for more info - http://square.github.io/picasso/

Nishchal Sharma
  • 1,070
  • 9
  • 16
1

You can also save yourself the f.createNewFile and use File.createTempFile(imageFileName, ".jpg", storageDir)

So your method now becomes

public File getFile(String url) {
    String filename = String.valueOf(url.hashCode());
    // String filename = URLEncoder.encode(url);

    return File.createTempFile(filename, ".jpg", cacheDir);
}
Enoobong
  • 1,594
  • 2
  • 15
  • 25