0

I am using the following code to set an image from the assets folder.

Uri numBgUri = Uri.parse("file:///android_asset/background_numbers.png");
numBgImage.setImageURI(numBgUri);

The background_numbers.png file definitely exists in the assets root directory. I am getting a FileNotFoundException in the log: -

09-23 17:05:23.803: WARN/ImageView(23713): Unable to open content: file:///android_asset/background_numbers.png

Any ideas what I could be doing wrong?

Thanks!

Ash McConnell
  • 1,340
  • 1
  • 17
  • 28

3 Answers3

6

I managed to get a viable workaround for this using my own custom ContentProvider (It's easier than you think!). Thanks to skink on Google Groups for the tip

This code should work, you just need to set a provider URL and register it as a provider in the manifest file

package sirocco.widgets;

import java.io.FileNotFoundException;
import java.io.IOException;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.Uri;

public class AssetContentProvider extends ContentProvider {

    private AssetManager mAssetManager;
    public static final Uri CONTENT_URI = 
            Uri.parse("content://your.provider.name");

    @Override
    public int delete(Uri arg0, String arg1, String[] arg2) {
        return 0;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public boolean onCreate() {
        mAssetManager = getContext().getAssets();
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return null;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
        String path = uri.getPath().substring(1);
        try {
            AssetFileDescriptor afd = mAssetManager.openFd(path);
            return afd;
        } catch (IOException e) {
            throw new FileNotFoundException("No asset found: " + uri);
        }
    }

}

I hope this helps any googlers out there with the same problem!

Ash McConnell
  • 1,340
  • 1
  • 17
  • 28
  • Yes, thanks so much for this! I didn't realize until the second time I took a good look at it that I could simply use a Uri like "content:///" in conjunction with your solution. Straightforward solution to a problem that shouldn't exist IMO. :-| – mharper Jan 31 '13 at 22:58
0

You need to place all images in you resources directory. For example :

/root/res/drawable/background_numbers.png

And you can access it via:

numBgImage.setImageResource(R.drawable.background_numbers);
HandlerExploit
  • 8,131
  • 4
  • 31
  • 50
  • 1
    Yep, I know that's a possibility, but it should also be possible to place them in the assets directory. When releasing a new version then the resource ids don't change. – Ash McConnell Sep 23 '11 at 16:45
  • All resource ids are changed when you recompile the application, this is a normality. You can reference the specific ids using the R class so that even though the values change it will not impact anything. – HandlerExploit Sep 23 '11 at 17:37
  • Yep, I am aware of how it works. It only changes value if you add or delete resources. I am data driving a number of skins for my widgets. I am using URIs, so uris to resources aren't "permanent", but assets should be. I store the uris in the sharedprefs for each widget – Ash McConnell Sep 23 '11 at 18:21
0

I advice you to double check that:

  • ImageView activity that appears in your logcat belongs to the same apk that your code. asset files are only readable from within your application.

  • The assets folder is in the project directory root.

EDIT

It seems that it is not possible to feed an ImageView directly from an asset ressource. See this question for illustration. As a workaround you should try to create a drawable from your asset file, then associate it with your Image view using ImageView.setImageDrawable:

Drawable d = Drawable.createFromStream(getAssets().open("background_numbers.png"), null);
if (null != d) numBgImage.setImageDrawable(d);

The first line of this code is an adaptation of this answer from @IgorKhomenko .

Community
  • 1
  • 1
Laurent'
  • 2,611
  • 1
  • 14
  • 22
  • Thanks. I checked the log and it's definitely an error from my application. I unzipped my APK to double check it was in the correct place, but /assets/background_numbers.png is there. I am successfully loading a font and some properties files from assets, it's just the URI thing that isn't working for some reason. – Ash McConnell Sep 23 '11 at 20:26
  • @Ash McConnell, could you please detail numBgImage type and provide additional code? – Laurent' Sep 23 '11 at 20:50
  • numBgImage is an ImageView. Here is how I get it: - ImageView numBgImage = (ImageView) layout.findViewById(R.id.numBackground); – Ash McConnell Sep 24 '11 at 09:25
  • Hehe, you referenced this question ;). Unfortunately I can't do this as it's a Widget, There are problems using Drawables / Bitmaps (if there are quite a few) – Ash McConnell Sep 24 '11 at 13:19
  • @AshMcConnell Oh, it's a widget now? I surrender :) I think you should edit your question for completness in order to help future helpers helping you. – Laurent' Sep 24 '11 at 14:35
  • Hehe, well it's the configuration for a widget, but the widget uses URIs to set ImageViews (as I'm skinning). I don't see why setImageUri shouldn't work, but that's Android for you ;) – Ash McConnell Sep 24 '11 at 17:09