Android tip #1 ContentProvider , Accessing local file system from WebView / showing image in webview using content://

January 10, 2009 - android / General / java / software / Tech Tips

ok, this was a tough one.
First be informed that this is something Google (Android people) are trying to prevent i.e. letting browser (WebView) have access to the local file system. In earlier releases of SDK you could access local files using ‘file://’ but it is stopped now. Then there was an option where you can provide a WebViewClient and implement shouldOverrideUrlLoading to make it work. This was also removed.
The way to make it work now is by implementing your own ContentProvider, there is lot of discussion and documentation on implementing ContentProvider but all that is completely redundant (not needed). The solution is very simple, create your own ContentProvider and only override

<br />
public android.os.ParcelFileDescriptor openFile(android.net.Uri uri, java.lang.String mode) throws java.io.FileNotFoundException<br />

Rest of the code in ContentProvder is not needed for this problem.

Step 1:
Declare your Content Provider in AndroidManifest.xml

</p>
<provider android:name="MyDataContentProvider"  android:authorities="com.techjini" />

Step 2:
Create your ContentProvider and implement openFile
All you have to do is get real path from uri, open it and return the descriptor

<br />
URI uri = URI.create(&#8220;file:///data/data/com.techjini/files/myImage.jpeg&#8221;);<br />
File file = new File(uri);<br />
ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);<br />
return parcel;<br />

Step 3:
(You need this step only if file is not already present on the device/sdcard)
Save your content to the file. Following is an example to store a Bitmap

<br />
FileOutputStream fos = openFileOutput(&#8220;myImage.jpeg&#8221;, Activity.MODE_WORLD_WRITEABLE);<br />
imageView.getBitmap().compress(Bitmap.CompressFormat.JPEG, 100, fos);</p>
<p>fos.flush();<br />
fos.close();<br />

You can find out where your image is stored using

<br />
System.out.println(getFilesDir().getAbsolutePath());<br />

Step 4:
Access the file in WebView

<br />
myWebView.loadUrl(&#8220;content://com.techjini/myImage.jpeg&#8221;);<br />
//com.techjini is what you mentioned in &#8216;android:authorities&#8217; in your AndroidManifest.xml<br />

Looks simple :)

Comments

  1. vinay says:

    hi,
    I am not familiar to Java stuff and got into making webview display /sdcard/index.html file. This index.html has got some website links (www.amazon.com) as my board does not have keypad.
    Can you provide me the above mentioned complete code and compile procedue.
    -vinay

  2. Tyler says:

    Thanks for this, it was a BIG help! You may want to clarify that step #3 isn’t necessary if a file already exists; it’s just to provide a sample. Also, here’s an override of openFile that points to any Uri you pass it (i.e. passing “file://sdcard/foo/bar/anything.jpeg” will be reachable via “content://com.yourauthority/sdcard/foo/bar/anything.jpeg”):

    // SDK v. 1.0_r2
    @Override
    public ParcelFileDescriptor openFile( Uri uri, String mode ){
    URI fileURI = URI.create( “file://” + uri.getPath() );
    File file = new File( fileURI );

    ParcelFileDescriptor parcel = null;
    try {
    parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
    } catch (FileNotFoundException e) {
    Log.e( TAG, “Error finding: ” + fileURI + “\n” + e.toString() );
    }

    return parcel;
    }

  3. Amit says:

    Hello Tyler,
    Thanks for pointing that out and giving your code, I have added a note in point 3.

  4. ATrubka says:

    Hi, guys. I thought it might be helpful to have a complete working example.

    It’s on my blog with some explanations around it:
    http://blog.tourizo.com/2009/02/how-to-display-local-file-in-android.html

  5. [...] found a few posts about WebView being unable to open local files, and the need to use a ContentProvider to get around [...]

  6. Santori says:

    Nice post. Thanks for sharing these tips.

  7. Schorsch says:

    Hi Amit,

    as i am not a coder, but only a project manager (for a small startup) i have a general question. Does your workaround also work with a simple web/xhtml page or is it neccessary to create a piece of software that needs to be installed on each individual handset that wants to access the local file system? I am asking because we want to give the users of our not yet released community the possibility to upload pictures stored on their devices from within the browser. We dont have any app and also dont want our users to install any apps (unless theres sth like firefox plugins, that would actually be great!)

    Do you have any idea on how to make that happen from a pure browsers environment? Or does your idea already work from a pure xhtml site?

    Thanks alot in advance!
    Schorsch

  8. Amit says:

    Hello Schorsch,

    Couple of things, the solution above was for android 1.0/1.1 earlier, with the new 2.1 api this is supported out of the box. Now if I am embedding webkit in my app I can load local files easily.

    Now coming to your situation, if you do not want an app and just have a web page which android users will open in their app it would not be a problem to access pictures from device.

    You can easily try it by making a simple html, putting it on your server and trying to access it from android browser.

  9. Yaya says:

    Hi,
    can you explain how do access the file in the html code ?

    i’ve tryed and i having “Failed to find provider info for com.myCompany.myPackageName”.
    For more explanation see:
    http://groups.google.com/group/android-developers/browse_thread/thread/d105f5194d843861#

    Thanks a lot in advance !

    Yaya

  10. Android Apps says:

    I think your blog need a new wordpress template. Downalod it from http://www.wpxthemes.com, The site has nice and unique wordpress templates.

  11. Aris Boch says:

    Can any1 send me an app which can open html files from the g1 resp. android local storage?

  12. Jason says:

    Thanks for sharing! I had similar problem, not with WebView but AppWidget instead. My AppWidget has a ImageView and needs to load a local (sdcard) image file using setImageUri method. I was struggling to access a local file through URI for days, and finally found the answer from you post. Thanks!

  13. Leonardo Rocha says:

    Thanks a lot! It solve my problem!!

  14. gokul says:

    Hi friends,
    from past two days i am stucking this problem i dont know how to use the code in my project .I want to display the sdcard imgage on webview . please and one send me the sample code . alagudream@gmail.com >

  15. Hugo Garcia-Cotte says:

    If you just want to read a file you have embbed in you .apk, there is a much simpler way to do it.

    Just add your file in a folder named “assets” in your project
    and you can get your file at the url:
    file:///android_asset/your_file
    sample code here:
    http://developer.android.com/resources/articles/using-webviews.html

  16. Saqib says:

    Hey everyone!

    I want access application data ! coz i have application running which takes some URL like (www.yahoo.com) i want to make change in URl text which i beleive in application data i have created diffrent application if user open my application and type URl i want to pass this URl to other application data so user dont have to write again!!!
    can anyone help?

    Thanx in Advance

  17. Thanks for the post!

    I am using your file provider method to attach images to content sent via various “share” (Action.SEND) methods.

    I notice that when sent via email that the query method is called.
    If I use your code that throws an exception (surprisingly!) it seems that the GMail client doesn’t catch it and crashes :-)

    It seems to want to know the mime type and display name and size of the attached image/file.

    That would be a nice enhancement of your provider, filling out some of those other methods so that it could be more widely used than just with WebView.

    Thanks all the same.

  18. If instead, in query() you return null, then this provider will work for more uses (e.g. when sharing something via Email, Twitter or other applications installed) (e.g. attach an image via EXTRA_STREAM to an intent to share, using a Uri from this provider).

    I am looking into fuller implementations of getType() that return a valid MIME-type, and query() using MatrixCursor().

  19. idazfelkuwgo says:

    Richard watched her willingness. He lay on him.

  20. An fascinating dialogue is worth comment. I believe that it’s best to write extra on this topic, it may not be a taboo subject however usually persons are not enough to speak on such topics. To the next. Cheers

  21. steff says:

    If you want to use this content provider for sharing, and get a bug with native email client for Android, then there are two methods you must implement as well :

    // http://source-android.frandroid.com/packages/apps/Email/src/com/android/email/activity/MessageCompose.java
    // for native email client
    @Override
    public Cursor query( Uri uri, String[] arg1, String arg2, String[] arg3, String arg4 ) {
    String filePath = getFilePathFromUri( uri );
    // share file content.
    File file = new File( filePath );
    if ( file.exists() ) {
    final long size = file.length();

    Ln.d( “Inside query” );
    MatrixCursor matrixCursor = new MatrixCursor( new String[] { OpenableColumns.SIZE } );
    matrixCursor.addRow( new Object[] { size } );

    return matrixCursor;
    } else {
    return null;
    }
    }

    And

    // http://source-android.frandroid.com/packages/apps/Email/src/com/android/email/activity/MessageCompose.java
    // for native email client
    @Override
    public String getType( Uri uri ) {
    Ln.d( “Inside query type” );
    String filePath = getFilePathFromUri( uri );
    // share file content.
    File file = new File( filePath );
    if ( file.exists() ) {
    String extension = ;
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension( extension );
    }
    return null;
    }

    Thanks for the whole idea !

  22. dresses says:

    I guess, it comes down to 109575 simple choice!

  23. Having read this I thought it was rather enlightening.

    I appreciate you finding the time and effort to put
    this short article together. I once again
    find myself personally spending a significant amount of time
    both reading and commenting. But so what, it was still worthwhile!

  24. I’ve been surfing online more than 3 hours these days, yet I by no means discovered any fascinating article like yours. It is lovely value sufficient for me. In my opinion, if all web owners and bloggers made excellent content as you probably did, the net shall be much more helpful than ever before.

  25. Hi to every one, the contents present at this site are in fact remarkable for people experience, well, keep up the
    nice work fellows.

  26. Hi! I know this is kinda off topic but I was
    wondering which blog platform are you using for this site? I’m getting fed up of WordPress because I’ve had issues with
    hackers and I’m looking at alternatives for another platform. I would be great if you could point me in the direction of a good platform.

  27. Great blog post. A few things i would like to bring up is that personal computer memory must be purchased if the computer is unable to cope with everything you do along with it. One can deploy two RAM boards of 1GB each, by way of example, but not one of 1GB and one having 2GB. One should always check the maker’s documentation for own PC to be certain what type of ram is needed.

  28. Nice, but have an error. Second code dosn’t work

  29. Elinore Jett says:

    There are some interesting cut-off dates on this article but I don’t know if I see all of them middle to heart. There’s some validity but I’ll take maintain opinion till I look into it further. Good article , thanks and we wish more! Added to FeedBurner as properly

  30. Avada theme says:

    You made some decent points there. I looked on the internet for the issue and located most individuals will go together with along with your website.

  31. snort this says:

    I believe this web site has some rattling wonderful info for everyone :D.

  32. android says:

    Its that you understand my head! You seem to know lots relating to this, such as you published the publication there something like that. I do think that you may use a number of pix to drive the content residence slightly, but rather than in which, this is certainly fantastic site. An excellent study. Let me definitely be returning.

  33. Good to see this tip.To be honest i am good on reading code but i know a little bit about it.This tip is really useful and i like it.

Leave a Reply