2011-02-26 38 views
2

我,我想使用外部應用程序打開我的應用程序的資源目錄已經PDF文件打開PDF,所以我寫了內容提供商,我tryng,使其工作,但沒有...Android的 - 在外部應用程序

這裏是代碼:

內容提供商:

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"); 
     } 

    } 

,並在這裏,我如何調用打開文件:

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); 

我已在Android清單下面一行,在標籤內:

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

這是logcat的輸出:

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 

不明白問題出在哪裏,似乎是外部應用程序無法獲取文件。

感謝您的任何幫助!

回答

2

我是新android開發,花了一整天找我的本地存儲的PDF不能由外部應用程序打開的原因。我很高興找到這個線程。

與此同時,馬可得到它的工作,並在這裏描述。 當心:意大利語言 - 谷歌翻譯服務,可以幫助;-)

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

附加說明他的HOWTO初學者:

線馬可提到在清單中插入.xml

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

應該插入wi薄<application ...></application>標記。

如果您計劃自定義的文件名,你應該

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

PDF文件交換

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

已在項目中投入已經存在的文件夾資產(尤其不要在任何新添加的文件夾res/assets或者某物)! =)

2

setType()將您的Uri重置爲null。嘗試跳過構造函數中的Uri,並使用setDataAndType()代替。

+0

我做過嘗試,但它做wsn't工作,logcat不會拋出異議,但外部程序說「文件路徑無效」 –

5

我的實現如下。請注意,如果您的文件名是MyPdf.pdf,則該文件應該是assets/public_pdfs/MyPdf.pdf.mp3。路徑public_pdfs僅用於導出您真正想要導出的pdf,並且.mp3擴展名用於防止壓縮。

AndroidManifest.xml中

<provider android:authorities="my.app.PdfContentProvider" android:enabled="true" android:exported="true" android:name="my.app.PdfContentProvider"> 
</provider> 

打開PDF

Intent intent = new Intent(); 
intent.setAction(Intent.ACTION_VIEW); 

Uri uri = Uri.parse("content://my.app.PdfContentProvider/" + filename); 
intent.setDataAndType(uri, "application/pdf"); 

startActivity(intent); 

PdfContentProvider.java

public class PdfContentProvider extends ContentProvider 
{ 
    private static final String PDFPATH = "public_pdfs/"; 

    @Override 
    public String getType(Uri uri) 
    { 
    return "application/pdf"; 
    } 

    @Override 
    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException 
    { 
    AssetManager am = getContext().getAssets(); 
    String file_name = uri.getLastPathSegment(); 

    if (file_name == null) throw new FileNotFoundException(); 
    AssetFileDescriptor afd = null; 
    try 
    { 
     afd = am.openFd(PDFPATH + file_name + ".mp3"); 
    } 
    catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
    return afd; 
    } 

    private final static String[] COLUMNS = {OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}; 

    @Override 
    /** 
    * This function is required for it to work on the Quickoffice at Android 4.4 (KitKat) 
    */ 
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 
    { 
    if (projection == null) 
    { 
     projection = COLUMNS; 
    } 

    String[] cols = new String[projection.length]; 
    Object[] values = new Object[projection.length]; 
    int i = 0; 
    for (String col : projection) 
    { 
     if (OpenableColumns.DISPLAY_NAME.equals(col)) 
     { 
     cols[i] = OpenableColumns.DISPLAY_NAME; 
     values[i++] = uri.getLastPathSegment(); 
     } 
     else if (OpenableColumns.SIZE.equals(col)) 
     { 
     cols[i] = OpenableColumns.SIZE; 
     values[i++] = AssetFileDescriptor.UNKNOWN_LENGTH; 
     } 
    } 

    cols = copyOf(cols, i); 
    values = copyOf(values, i); 

    final MatrixCursor cursor = new MatrixCursor(cols, 1); 
    cursor.addRow(values); 
    return cursor; 
    } 

    private static String[] copyOf(String[] original, int newLength) 
    { 
    final String[] result = new String[newLength]; 
    System.arraycopy(original, 0, result, 0, newLength); 
    return result; 
    } 

    private static Object[] copyOf(Object[] original, int newLength) 
    { 
    final Object[] result = new Object[newLength]; 
    System.arraycopy(original, 0, result, 0, newLength); 
    return result; 
    } 

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

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

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

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

非常非常非常聰明的工作,以找到從資產文件夾打開文件的方式。這應該是正確的答案。爲此+1。 – Smeet

+0

似乎有點破碎。唯一發生的事情是Toast的消息「This document can not be opened」... – glace

相關問題