Search code examples
androidpdfandroid-contentprovider

Android - open pdf in external application


i've a pdf file in my app assets directory that i want open using an external app, so wrote my content provider and i'm tryng to make it work but nothing...

here is the code:

Content Provider:

package package.name;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URI;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;

public class FileContentProvider extends ContentProvider {
       private static final String URI_PREFIX = "content://package.name.filecontentprovider";

       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 {
           URI uri1 = URI.create("file:///data/data/package.name/"+uri.getPath()); 
           File file = new File(uri1.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");
       }

    }

and here how i call the opening of the file:

    File pdf = new File("assets/prova.pdf");
    Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("content://package.name/" + pdf));
    i.setType("application/pdf");
    startActivity(i);

i've added the following line in the android manifest, inside the tag:

    <provider android:name=".FileContentProvider" android:authorities="package.name" />

this is the logcat output:

02-26 19:47:44.938: ERROR/AndroidRuntime(6494): Uncaught handler: thread main exiting due to uncaught exception
02-26 19:47:44.953: ERROR/AndroidRuntime(6494): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tf.thinkdroid.samsung/com.tf.thinkdroid.pdf.app.PdfRenderScreen}: java.lang.NullPointerException
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.app.ActivityThread.access$2200(ActivityThread.java:119)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.os.Looper.loop(Looper.java:123)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.app.ActivityThread.main(ActivityThread.java:4363)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at java.lang.reflect.Method.invokeNative(Native Method)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at java.lang.reflect.Method.invoke(Method.java:521)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at dalvik.system.NativeStart.main(Native Method)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494): Caused by: java.lang.NullPointerException
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at com.tf.thinkdroid.pdf.app.RenderScreen.onNewIntent(Unknown Source)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at com.tf.thinkdroid.pdf.app.RenderScreen.onCreate(Unknown Source)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at com.tf.thinkdroid.pdf.app.PdfRenderScreen.onCreate(Unknown Source)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
02-26 19:47:44.953: ERROR/AndroidRuntime(6494):     ... 11 more

don't understand where the problem is, seem that the external application can't get the file.

thanks for any help!


Solution

  • I am new to android development and spent the whole day looking for the reason that my locally stored PDF could not be opened by external apps. I am glad having found this thread.

    In the meantime Marco got it working and describes it here. Beware: Italian language- Google translation service might help ;-)

    http://www.marcofaion.it/?p=7
    http://web.archive.org/web/20111020204554/http://www.marcofaion.it/?p=7

    Additional notes to his howto for beginners:

    The line Marco mentions to be inserted in the Manifest.xml

    <provider android:name=".FileContentProvider" android:authorities="package.name" />
    

    should be inserted within the <application ...></application> tag.

    And if you plan to have custom filenames you should exchange

    InputStream is = am.open("file.pdf");
    

    with

    InputStream is = am.open(uri.getLastPathSegment());
    

    PDF files have to be put into already existing folder assets in your project (especially not in any newly added folder res/assets or sth.)! =)