159

I have been trying to get the URI path for an asset file.

uri = Uri.fromFile(new File("//assets/mydemo.txt"));

When I check if the file exists I see that file doesn't exist

File f = new File(filepath);
if (f.exists() == true) {
    Log.e(TAG, "Valid :" + filepath);
} else {
    Log.e(TAG, "InValid :" + filepath);
}

Can some one tell me how I can mention the absolute path for a file existing in the asset folder

klefevre
  • 8,595
  • 7
  • 42
  • 71
Titus
  • 1,613
  • 2
  • 11
  • 8

13 Answers13

187

There is no "absolute path for a file existing in the asset folder". The content of your project's assets/ folder are packaged in the APK file. Use an AssetManager object to get an InputStream on an asset.

For WebView, you can use the file Uri scheme in much the same way you would use a URL. The syntax for assets is file:///android_asset/... (note: three slashes) where the ellipsis is the path of the file from within the assets/ folder.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • The reason why I wanted an absolute path was that I wanted a URI for the file. – Titus Jan 27 '11 at 19:39
  • 35
    `file://android_asset/...`, where `...` is the relative path within your project's `assets/` directory. – CommonsWare Jan 27 '11 at 19:40
  • I tried that and i get it still as an invalid path. I have verified the apk is containing the txt file within its asset folder – Titus Jan 27 '11 at 19:53
  • 5
    Here is a sample project using `file://android_asset/`, though not for a `Uri`: https://github.com/commonsguy/cw-advandroid/tree/master/WebView/GeoWeb1 – CommonsWare Jan 27 '11 at 19:56
  • I can confirm that Commons' tip works at least for the purpose of showing resources in a WebView. – thom_nic Jul 12 '11 at 11:43
  • 22
    @CommonsWare it looks like you missed a '/' in your URI. It should be `file:///`. – ThomasW Nov 04 '11 at 07:20
  • 11
    I tried this as `new File("file:///android_asset/sounds/beep.mid");`, but result file doesn't exists. Any ideas? P.S. file is in `assets/sounds/` folder. – uncle Lem May 14 '14 at 00:15
  • 6
    Is it right that ´file:///android_asset/...´ works only in WebView and is not possible to get InputStream using URI/URL/Uri outside WebView? – Lubbo Apr 26 '17 at 14:27
  • @Lubbo: AFAIK, the only thing that pays attention to `file:///android_asset/` is `WebView`. It's possible that `ContentResolver` and `openInputStream()` works with it, but I do not recall that it does. The syntax in that earlier comment definitely will not work. – CommonsWare Apr 26 '17 at 16:52
  • 1
    for a quick note `android_asset` is a not your asset directory's name, its same no mater what is your asset directory's name,`file:///android_asset/` this part will be same no mater what is your asset directory's name – Pranoy Sarkar Aug 02 '17 at 16:54
78

The correct url is:

file:///android_asset/RELATIVEPATH

where RELATIVEPATH is the path to your resource relative to the assets folder.

Note the 3 /'s in the scheme. Web view would not load any of my assets without the 3. I tried 2 as (previously) commented by CommonsWare and it wouldn't work. Then I looked at CommonsWare's source on github and noticed the extra forward slash.

This testing though was only done on the 1.6 Android emulator but I doubt its different on a real device or higher version.

EDIT: CommonsWare updated his answer to reflect this tiny change. So I've edited this so it still makes sense with his current answer.

Russ
  • 1,786
  • 13
  • 17
  • 3
    Doesn't work anymore `String fileName = "file:///android_asset/file.csv";` `System.out.println(new File(fileName).exists()); // prints false` – Elgirhath Jun 19 '20 at 20:15
  • @Elgirhath the constructor for `File` that accepts a string is expecting a _path_ not a _URI_. I haven't coded for Android for a few years and things may have changed. I'm unsure if you can access the embedded assets folder using a normal java File class. I seem to remember that you have to use an [AssetManager](https://developer.android.com/reference/android/content/Context#getAssets()). Files in the assets folder are placed on the device in the read-only bundled APK and compressed (APKs are actually zip files), thus more work to read it back. Try something like `new File(new URI(filename))` – Russ Jun 20 '20 at 21:42
29

Finally, I found a way to get the path of a file which is present in assets from this answer in Kotlin. Here we are copying the assets file to cache and getting the file path from that cache file.

@Throws(IOException::class)
    fun getFileFromAssets(context: Context, fileName: String): File = File(context.cacheDir, fileName)
            .also {
               if (!it.exists()) {
                it.outputStream().use { cache ->
                    context.assets.open(fileName).use { inputStream ->
                            inputStream.copyTo(cache)
                    }
                  }
                }
            }

Get the path to the file like:

val filePath =  getFileFromAssets(context, "fileName.extension").absolutePath
Elementary
  • 2,153
  • 2
  • 24
  • 35
Shailendra Madda
  • 20,649
  • 15
  • 100
  • 138
  • 1
    Notice that if the `fileName` have directory `dir/file`. It will crash with path the `cache/dir/file` not exist. Also I think better have a checking `if(!it.exist)` inside the `also` block, then it will not copy the file every time even the file is already on the cache – Yeung Sep 27 '19 at 09:55
  • @ShylendraMadda, @Yeung, `if(!it.exist)` thows an error unresolved reference. any solution ? – binrebin May 29 '20 at 10:03
  • Check that file exists in your cache with that file name? @binrebin – Shailendra Madda May 29 '20 at 12:58
  • @ShylendraMadda, I know filename only. Can we load it with script without knowing actual uri – binrebin May 29 '20 at 17:32
  • I think `if(!it.exist)` should put before `it.outputStream()`... – Yeung Jun 03 '20 at 05:37
  • @Yeung Updated, Thanks – Shailendra Madda Jun 03 '20 at 06:15
  • @SamChen Glad that it helped you – Shailendra Madda Feb 28 '22 at 04:48
  • @Shailendra Madda Can you help me with this: https://stackoverflow.com/q/71301543/3466808, would be very appreciated! – Sam Chen Feb 28 '22 at 22:27
  • 1
    for someone if have some dir before the file name, like -> ("raw/filename.ext" ), inside if (!it.exists()) block befor the it.outputStream().use { cache -> ... add this code to create directory if is not exist --> val fileDir = File( context.cacheDir, File.separator.toString() + "raw" ) fileDir.mkdir() – A S A D I Jul 19 '22 at 06:01
15

Please try this code working fine

 Uri imageUri = Uri.fromFile(new File("//android_asset/luc.jpeg"));

    /* 2) Create a new Intent */
    Intent imageEditorIntent = new AdobeImageIntent.Builder(this)
            .setData(imageUri)
            .build();
Raaz Thakur
  • 175
  • 1
  • 2
7

enter image description here

Be sure ,your assets folder put in correct position.

Chuanhang.gu
  • 870
  • 9
  • 13
6

Works for WebView but seems to fail on URL.openStream(). So you need to distinguish file:// protocols and handle them via AssetManager as suggested.

Andro Selva
  • 53,910
  • 52
  • 193
  • 240
Gaylord Zach
  • 121
  • 1
  • 3
3

Try this out, it works:

InputStream in_s = 
    getClass().getClassLoader().getResourceAsStream("TopBrands.xml");

If you get a Null Value Exception, try this (with class TopBrandData):

InputStream in_s1 =
    TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml");
tanius
  • 14,003
  • 3
  • 51
  • 63
  • If not working , please Try this one : InputStream in_s1 = TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml"); – Jaspreet Singh Jul 02 '14 at 08:25
3
InputStream is = getResources().getAssets().open("terms.txt");
String textfile = convertStreamToString(is);
    
public static String convertStreamToString(InputStream is)
        throws IOException {

    Writer writer = new StringWriter();
    char[] buffer = new char[2048];

    try {
        Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        int n;
        while ((n = reader.read(buffer)) != -1) {
            writer.write(buffer, 0, n);
        }
    } finally {
        is.close();
    }

    String text = writer.toString();
    return text;
}
tanius
  • 14,003
  • 3
  • 51
  • 63
jayesh kavathiya
  • 3,531
  • 2
  • 22
  • 25
1

try this :

Uri uri = Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.cat); 

I had did it and it worked

Nyle
  • 79
  • 2
  • 2
    Actually it works. Check [ContentResolver.openAssetFileDescriptor](https://developer.android.com/reference/android/content/ContentResolver.html#openAssetFileDescriptor(android.net.Uri%2C%20java.lang.String)) – Hippo Seven Nov 14 '16 at 17:20
  • 1
    Worked. Thanks a lot. Lol, I just looking for get URI internal file // CREATE RAW FOLDER INSIDE RES, THEN NAME FILE CONTAIN ONLY a..z0..9 character, NO UPPERCASE !!! – phnghue Apr 30 '18 at 01:30
1

Since it's actually data in the APK file and not on the emulator, you won't be able to find an "absolute path". I've eventually implemented in this pretty straightforward way :

private fun getUriFromAsset(context: Context, assetFileName: String): Uri? {
    val assetManager = context.assets
    var inputStream: InputStream? = null
    var outputStream: FileOutputStream? = null
    var tempFile: File? = null

    return try {
        inputStream = assetManager.open(assetFileName)
        tempFile = File.createTempFile("temp_asset", null, context.cacheDir)
        outputStream = FileOutputStream(tempFile)

        inputStream.copyTo(outputStream)

        Uri.fromFile(tempFile)
    } catch (e: IOException) {
        e.printStackTrace()
        null
    } finally {
        inputStream?.close()
        outputStream?.close()
        tempFile?.deleteOnExit()
    }
}
Lestode
  • 11
  • 3
0

Yeah you can't access your drive folder from you android phone or emulator because your computer and android are two different OS.I would go for res folder of android because it has good resources management methods. Until and unless you have very good reason to put you file in assets folder. Instead You can do this

try {
      Resources res = getResources();
      InputStream in_s = res.openRawResource(R.raw.yourfile);

      byte[] b = new byte[in_s.available()];
      in_s.read(b);
      String str = new String(b);
    } catch (Exception e) {
      Log.e(LOG_TAG, "File Reading Error", e);
 }
Valery Viktorovsky
  • 6,487
  • 3
  • 39
  • 47
willnotquit
  • 49
  • 1
  • 8
0

If you are okay with not using assets folder and want to get a URI without storing it in another directory, you can use res/raw directory and create a helper function to get the URI from resID:

internal fun Context.getResourceUri(@AnyRes resourceId: Int): Uri =
    Uri.Builder()
        .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
        .authority(packageName)
        .path(resourceId.toString())
        .build()

Now if you have a mydemo.txt file under res/raw directory you can simply get the URI by calling the above helper method

context.getResourceUri(R.raw.mydemo)

Reference: https://stackoverflow.com/a/57719958

mohit
  • 154
  • 2
  • 9
-9

Worked for me Try this code

   uri = Uri.fromFile(new File("//assets/testdemo.txt"));
   String testfilepath = uri.getPath();
    File f = new File(testfilepath);
    if (f.exists() == true) {
    Toast.makeText(getApplicationContext(),"valid :" + testfilepath, 2000).show();
    } else {
   Toast.makeText(getApplicationContext(),"invalid :" + testfilepath, 2000).show();
 }
Ranjeet Chouhan
  • 686
  • 5
  • 13
Irfan Ali
  • 189
  • 1
  • 9