3

I am trying to download a pdf file from server. I write some code for that. It works fine for api level 21 and >=23 but not working on api 22. Here is the problem:

OutputStream output = new FileOutputStream(fileName);
byte data[] = new byte[1024];

while ((count = input.read(data)) != -1) {
   output.write(data, 0, count);
}

But when it tries to execute

 OutputStream output = new FileOutputStream(fileName); 

it shows

java.io.FileNotFoundException: /storage/emulated/0/data    /data/com.example.test/files/training/training.pdf: open failed: ENOENT (No such file or directory)

This works fine for api level 21 and 23. What went wrong? How can I solve this?

coder
  • 51
  • 1
  • 5
  • have you given the `` permission in AndroidManifest.xml file? – Farmer Dec 09 '16 at 11:00
  • Sure. Also it is working on api 21 and 23 – coder Dec 09 '16 at 11:01
  • please check before get file that it is exist or not then after try to read. you can check http://stackoverflow.com/questions/16237950/android-check-if-file-exists-without-creating-a-new-one – Farmer Dec 09 '16 at 11:04
  • From Android developer Console FileNotFoundException occurs when "if the file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason". That means if file does not exist it will create new file – coder Dec 09 '16 at 11:07
  • What filename are you passing to the FileOutputStream() constructor? – Jonas Köritz Dec 09 '16 at 11:08
  • please check this http://stackoverflow.com/questions/14376807/how-to-read-write-string-from-a-file-in-android or as @JonasKöritz told that what type of file you passed in FileOutputStream() constructor? – Farmer Dec 09 '16 at 11:12
  • String root = Environment.getExternalStorageDirectory().toString(); String path = path = "/training/training.pdf"; String fileName = fileName=root+"/"+getFilesDir()+path; – coder Dec 09 '16 at 11:14
  • @Shailesh am I wrong about that: if there is no file then it will create a new one? – coder Dec 09 '16 at 11:17
  • yes, because if file not exists and try to read then how it's possible? you need to check first that file is exists or not and if file not exists then create then after try to read. – Farmer Dec 09 '16 at 11:21
  • That is a very strange place to write files. If nothing else, you need to call `mkdirs()` to ensure that your invented `Environment.getExternalStorageDirectory().toString()+"/'+getFilesDir()` exists, as the system certainly will not create it for you. If you want an app-specific location on external storage, get rid of all of that and just use `getExternalFilesDir()`, called on a `Context`. As a bonus, you do not need any permissions to write to that directory on Android 4.4+. – CommonsWare Dec 09 '16 at 11:25
  • @CommonsWare before calling FileOutputStream() i am calling this public void createDirectory() { File directory = new File(getFilesDir() + "/training"); if (!directory.exists()) { directory.mkdir(); } } – coder Dec 09 '16 at 11:33
  • `if (!directory.exists()) { directory.mkdir(); }`. You should check the return value of mkdir as it might fail. If it fails you should inform the user about this and not continue with your code but return. – greenapps Dec 09 '16 at 12:09

1 Answers1

3

before calling FileOutputStream() i am calling this public void createDirectory() { File directory = new File(getFilesDir() + "/training"); if (!directory.exists()) { directory.mkdir(); } }

That is not where you are trying to write the file:

String root = Environment.getExternalStorageDirectory().toString(); String path = path = "/training/training.pdf"; String fileName = fileName=root+"/"+getFilesDir()+path;

As you can see, these do not match.


If you want the file on external storage, the best solution is to get rid of all of that and use getExternalFilesDir(), called on Context (akin to getFilesDir()). This gives you:

  • A unique directory
  • On external storage
  • Where the files will be deleted when your app is uninstalled
  • That does not require permission on Android 4.4+

The next-best solution for external storage is to get rid of all of that and use Environment.getExternalStoragePublicDirectory() as your base, to put the files in a standard location based on their type (e.g., photos, videos, music). These files will survive an uninstall, and this location will require WRITE_EXTERNAL_STORAGE. Plus, you will have to create a unique subdirectory under this root yourself, though typically this is done via a user-friendly display name (e.g., OpenCamera) rather than the package name.

Your directory that you are creating in createDirectory() is perfectly fine, but it is internal storage, so the user cannot access it. If you want to use that, then use the same algorithm to create the File for your FileOutputStream as you are using in createDirectory().

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks a lot. I was reading the file from root folder. It is not necessary. Now I am using the getFilesDir() method and the problem banished! – coder Dec 09 '16 at 12:23