Android - открыть PDF во внешнем приложении - PullRequest
2 голосов
/ 26 февраля 2011

У меня есть pdf-файл в каталоге ресурсов моего приложения, который я хочу открыть с помощью внешнего приложения, поэтому написал мой поставщик контента, и я пытаюсь заставить его работать, но ничего ...

вот код:

Поставщик контента:

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

Не понимаю, в чем проблема, кажется, что внешнее приложение не может получить файл.

спасибо за любую помощь!

Ответы [ 3 ]

5 голосов
/ 06 ноября 2013

Моя реализация ниже. Обратите внимание, что если ваше имя файла 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;
  }
}
2 голосов
/ 26 марта 2011

Я новичок в разработке для Android и потратил целый день на поиски причины, по которой мой локально сохраненный PDF не может быть открыт внешними приложениями. Я рад, что нашел эту тему.

Тем временем Марко все заработал и описывает здесь. Осторожно: итальянский язык - сервис перевода Google может помочь; -)

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

Дополнительные примечания к его инструкции для начинающих:

Строка, которую Марко упоминает для вставки в Manifest.xml

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

должен быть вставлен в тег <application ...></application>.

И если вы планируете использовать пользовательские имена файлов, вам следует поменять

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

с

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

PDF-файлы должны быть помещены в уже существующую папку assets в вашем проекте (особенно не во вновь добавленной папке res / assets или sth.)! =) * * 1 029

2 голосов
/ 26 февраля 2011

setType() сбрасывает ваш Uri до null.Попробуйте пропустить Uri в конструкторе и использовать вместо него setDataAndType().

...