61

I am trying to load an image from the asset folder and then set it to an ImageView. I know it's much better if I use the R.id.* for this, but the premise is I don't know the id of the image. Basically, I'm trying to dynamically load the image via its filename.

For example, I randomly retrieve an element in the database representing let's say a 'cow', now what my application would do is to display an image of a 'cow' via the ImageView. This is also true for all element in the database. (The assumption is, for every element there is an equivalent image)

thanks in advance.

EDIT

forgot the question, how do I load the image from the asset folder?

biegleux
  • 12,934
  • 11
  • 42
  • 52
kishidp
  • 1,746
  • 5
  • 22
  • 27

8 Answers8

123

Checkout this code . IN this tutorial you can find how to load image from asset folder.

// load image

try 
{
    // get input stream
    InputStream ims = getAssets().open("avatar.jpg");
    // load image as Drawable
    Drawable d = Drawable.createFromStream(ims, null);
    // set image to ImageView
    mImage.setImageDrawable(d);
  ims .close();
}
catch(IOException ex) 
{
    return;
}
Ameer
  • 2,625
  • 1
  • 25
  • 42
Chirag
  • 55,270
  • 29
  • 150
  • 194
  • 10
    Shouldn't you be closing the stream after using it? – Nicolas Tyler Jun 12 '15 at 09:56
  • I think the best approach would be a [try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html). That would ensure the stream always is closed without the need to write it all out – chris2112 Aug 14 '19 at 14:55
  • @NicolasTyler the InputStream object is destroyed automatically when execution leaves the current scope and when there are no more references to the object. – gregn3 Apr 11 '20 at 18:48
  • @gregn3 as far as I know the garbage collector will not close the stream when the stream goes out of scope. As stated in Elliotte Rusty Harold's Java I/O https://books.google.co.za/books?id=wqR2eOdZOqcC&pg=PA40&dq=%22streams+associated+with+files+and+network+connections+should+always+be+closed%22&hl=en&sa=X&ved=0ahUKEwir-Y_n4o3pAhXUi1wKHZTAAR0Q6AEIKDAA#v=onepage&q=%22streams%20associated%20with%20files%20and%20network%20connections%20should%20always%20be%20closed%22&f=false – Nicolas Tyler Apr 29 '20 at 13:49
  • @NicolasTyler I couldn't access the paywalled link, but I found this other [SO discussion](https://stackoverflow.com/questions/45456509/is-inline-created-inputstream-closed-automatically-by-gc): `So yes, you should close it yourself if you want to write clean code. The GC will close it eventually, if it gets around to calling the finalize() method (shown below) on the stream, but you shouldn't rely on that. Always close your resources, that's the only way to be sure.` – gregn3 Apr 29 '20 at 15:39
52

Here you are,

  public Bitmap getBitmapFromAssets(String fileName) {
    AssetManager assetManager = getAssets();

    InputStream istr = assetManager.open(fileName);
    Bitmap bitmap = BitmapFactory.decodeStream(istr);
    istr.close();

    return bitmap;
}
Ricky Dev
  • 21
  • 1
  • 5
osayilgan
  • 5,770
  • 7
  • 45
  • 68
32

If you know the filename in the code, calling this won't be a problem:

ImageView iw= (ImageView)findViewById(R.id.imageView1);  
int resID = getResources().getIdentifier(drawableName, "drawable",  getPackageName());
iw.setImageResource(resID);

Your filename will be the same name as drawableName so you won't have to deal with assets.

Erol
  • 6,302
  • 4
  • 39
  • 54
  • does the drawableName include the file extension? say "cow.png" or should I leave it as just "cow"? – kishidp Jul 31 '12 at 07:08
  • 5
    No, you don't have to include the extension as long as it is a valid image extension and the image is a drawable. – Erol Jul 31 '12 at 07:08
  • ah ok, got it.. thank you :) btw, is using the resource id much better than trying to load the image in assets, in terms of performance? – kishidp Jul 31 '12 at 07:16
  • 2
    Not a big difference. I would say using resources makes it a little faster and more practical due to indexing and also avoiding misnaming issues at compile time. Also, most api uses resource ids. Drawables give you, beside indexing, option to fight with screen density fragmentation and Assets shouldn't depend on density. Having big pictures on smaller screens and/or lower specification phones (RAM, CPU) can cause real trouble and influence usability and app responsivity. Assets are more occasional for me. – Erol Jul 31 '12 at 07:25
  • 3
    Does it really work for *assets* folder?? It works for *res* folder for sure, but this is the only reference I've seen that says it can work on assets too. It didn't work for me - did anyone verify that? – Amir Uval Jul 03 '13 at 14:56
  • Awesome! it's exactly what I need. – Ye Lin Aung Dec 10 '13 at 11:01
  • 2
    It works only without the extension in drawableName. – faizal Jan 31 '14 at 14:49
  • 12
    @uval Right, why is this the selected answer? The question was about loading from the "assets" folder. I guess the OP didn't really care where the file was actually located. See answers from osayilgan and Chirag Raval for examples using the "assets" folder. – Alan Mar 03 '14 at 22:04
  • worked when used drawableName without extension, "cow" instead of "cow.jpg" – ir2pid Mar 16 '15 at 21:56
  • my asset image is inside an image folder "assets/image/cow.jpg" and I'm unable to load it using drawableName "image/cow", has anyone faced a similar sitiation – ir2pid Mar 30 '15 at 19:47
  • 1
    This answer does not apply to the question: the question is display it from the asset folder and though the questioner is satisfied with an alternative approach, other people searching on this question get the wrong answer. – Safa Alai Jun 07 '15 at 02:40
  • I doesn't work from assets, you may have copies in some res/drawable folder as I did. – becker Sep 16 '16 at 21:22
7

Some of these answers may answer the question but I never liked any of them so I ended up writing this, it my help the community.

Get Bitmap from assets:

public Bitmap loadBitmapFromAssets(Context context, String path)
{
    InputStream stream = null;
    try
    {
        stream = context.getAssets().open(path);
        return BitmapFactory.decodeStream(stream);
    }
    catch (Exception ignored) {} finally
    {
        try
        {
            if(stream != null)
            {
                stream.close();
            }
        } catch (Exception ignored) {}
    }
    return null;
}

Get Drawable from assets:

public Drawable loadDrawableFromAssets(Context context, String path)
{
    InputStream stream = null;
    try
    {
        stream = context.getAssets().open(path);
        return Drawable.createFromStream(stream, null);
    }
    catch (Exception ignored) {} finally
    {
        try
        {
            if(stream != null)
            {
                stream.close();
            }
        } catch (Exception ignored) {}
    }
    return null;
}
Nicolas Tyler
  • 9,372
  • 4
  • 38
  • 62
3

According to Android Developer Documentation loading with bitmap can degrade app performane.Here's a link! So doc suggest to use Glide library.

If you want to load image from assets folder then using Glide library help you alots easier.

just add dependencies to build.gradle (Module:app) from https://github.com/bumptech/glide

 dependencies {
  implementation 'com.github.bumptech.glide:glide:4.9.0'
  annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
}

sample example :

// For a simple view:
@Override public void onCreate(Bundle savedInstanceState) {
  ...
  ImageView imageView = (ImageView) findViewById(R.id.my_image_view);

  Glide.with(this).load("file:///android_asset/img/fruit/cherries.jpg").into(imageView);
}

In case not worked by above method : Replace this object with view object from below code (only if you have Inflate method applied as below in your code).

 LayoutInflater mInflater =  LayoutInflater.from(mContext);
        view  = mInflater.inflate(R.layout.book,parent,false);
2
public static Bitmap getImageFromAssetsFile(Context mContext, String fileName) {
        Bitmap image = null;
        AssetManager am = mContext.getResources().getAssets();
        try {
            InputStream is = am.open(fileName);
            image = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;
    }
Anil Singhania
  • 615
  • 10
  • 8
2

This worked in my use case:

AssetManager assetManager = getAssets();
ImageView imageView = (ImageView) findViewById(R.id.imageView);
try (
        //declaration of inputStream in try-with-resources statement will automatically close inputStream
        // ==> no explicit inputStream.close() in additional block finally {...} necessary
        InputStream inputStream = assetManager.open("products/product001.jpg")
) {
    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
    imageView.setImageBitmap(bitmap);
} catch (IOException ex) {
    //ignored
}

(see also https://javarevisited.blogspot.com/2014/10/right-way-to-close-inputstream-file-resource-in-java.html)

Yves
  • 121
  • 1
  • 3
0
WebView web = (WebView) findViewById(R.id.webView);
web.loadUrl("file:///android_asset/pract_recommend_section1_pic2.png");
web.getSettings().setBuiltInZoomControls(true);
Evgeny
  • 163
  • 9
  • 8
    TS asks about ImageView, not WebView container. Embedding web browser for image displaying is very **huge** overhead. – ruX Feb 20 '14 at 18:40
  • @ruX using WebView should not be overhead. You don't need to embed a web browser to use WebView. Also, WebView is a nice option if you want to add zoom/pan functionality to your images or text. – Nj Subedi Dec 01 '15 at 05:40
  • @njs proof? WebView is embedded web browser btw. – ruX Dec 01 '15 at 16:04