tags:

views:

2867

answers:

4

I'm trying to launch an image which is written to my application directory with the builtin Android image viewer. This image has been written in a different part of the app to the app directory. When getting the following file:

super.getFilesDir() + "/current.png"

File.exists() returns true.

How can i launch the builtin Android image viewer to view this file? Currently i'm doing:

File f = new File(super.getFilesDir()+"/current.png");
uri = Uri.parse("file://"+super.getFilesDir()+"/current.png");
startActivity(new Intent(Intent.ACTION_VIEW, uri));

And it keeps churning out:

10-11 13:09:24.367: INFO/ActivityManager(564): Starting activity: Intent { act=android.intent.action.VIEW dat=file:///data/data/com.davidgoemans.myapp/files/current.png } 10-11 13:09:24.367: ERROR/myapp(2166): Exception occuredandroid.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=file:///data/data/com.davidgoemans.myapp/files/current.png }

irrespective of what i change the uri schema to ( eg, content://, file://, media://, image:// ).

+1  A: 

Option #1: Create a ContentProvider to serve up the file out of your app's private file area, then use an ACTION_VIEW Intent on that content:// Uri.

Option #2: Move the file to the SD card, and use an ACTION_VIEW Intent on the Uri and also with the appropriate MIME type. Android does not automatically associate file extensions with MIME types, so you need to tell the Intent what sort of MIME type the Uri points to. This is handled for you "automatically" with the ContentProvider.

CommonsWare
Part of the problem is that i'm stuggling to find firm examples of how to server up my app's private file area with a Content Provider or how to use a custom dir on the SD Card to server my files. The Android documentation very vaguely describes the Content Provider procedure, and copy/pasting their XML doesn't build.
DavidG
+1  A: 

Your image is within your application sandbox, so you should use ContentProvider to give other apps external access to your image data. Keep in mind that in Android, pre-installed apps don't have higher priority than third-party apps - you still have to give permission to your data, even if you want to use the default apps.

Otherwise, take a look at the Gallery activity's IntentFilter tags in the Camera application, for a reference what Intent you can use to open an image with the default viewer.

Dimitar Dimitrov
+3  A: 

One way is to implement a context provider to give other applications access to your data.

Create a new class containing:

public class FileContentProvider extends ContentProvider {
   private static final String URI_PREFIX = "content://uk.co.ashtonbrsc.examplefilecontentprovider";

   public static String constructUri(String url) {
       Uri uri = Uri.parse(url);
       return uri.isAbsolute() ? url : URI_PREFIX + url;
   }

   @Override
   public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
       File file = new File(uri.getPath());
       ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
       return parcel;
   }

   @Override
   public boolean onCreate() {
       return true;
   }

   @Override
   public int delete(Uri uri, String s, String[] as) {
       throw new UnsupportedOperationException("Not supported by this provider");
   }

   @Override
   public String getType(Uri uri) {
   throw new UnsupportedOperationException("Not supported by this provider");
   }

   @Override
   public Uri insert(Uri uri, ContentValues contentvalues) {
       throw new UnsupportedOperationException("Not supported by this provider");
   }

   @Override
   public Cursor query(Uri uri, String[] as, String s, String[] as1, String s1) {
       throw new UnsupportedOperationException("Not supported by this provider");
   }

   @Override
   public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
       throw new UnsupportedOperationException("Not supported by this provider");
   }

}

Add the content provider to your AndroidManifest.xml:

<provider android:name=".FileContentProvider" android:authorities="uk.co.ashtonbrsc.examplefilecontentprovider" />

You should then be able to use "content://uk.co.ashtonbrsc.examplefilecontentprovider/" + the full path to the image in your ACTION_VIEW intent.

AshtonBRSC
Thanks, will try this out tonight. I pretty much had that implemented, it just seems like such overkill to execute an application. Great design/architecture, but over complex for basic usage.
DavidG
Note: Overriding getType() required me to set the mime type, eg: @Override public String getType(Uri uri) { return "image/png"; }
DavidG
A: 

Would I do something simular to have a new file type launch my app? For example if I have a new file type 'file.mjl' and I receive this file as an email, I want Android to associate this file type with my app and allow me to open / save it.

Mike
that's even easier, you just need to set your intent to handle the given file extension
DavidG