diff options
author | Robin Watts <robin.watts@artifex.com> | 2013-01-24 19:26:26 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-01-26 17:26:54 +0000 |
commit | 0cbf73e579846395c7b9f7ebd3f3f229d99104ac (patch) | |
tree | ad21e1587baabc1316989fa2bcbcd4b7f7851378 /android/src/com/artifex/mupdfdemo | |
parent | e6f5e24b5d145cb571f82b2e01178be4c3eff662 (diff) | |
download | mupdf-0cbf73e579846395c7b9f7ebd3f3f229d99104ac.tar.xz |
Android: Fix NullPointerException seen on Google Play
According to Google Plays automated crash detection, we get a
NullPointerException when trying to parse a null string as a
Uri.
This turns out to be caused by us trying to open a PDF attachment
from gmail. This is because MuPDF is invoked with a content:// URL
that does not have a file associated with it. Instead we can open
that URL as an InputStream.
Here we amend MuPDF to spot that case, and to open the InputStream,
suck the data into a byteArray, and then to use that to open the
file from.
Diffstat (limited to 'android/src/com/artifex/mupdfdemo')
-rw-r--r-- | android/src/com/artifex/mupdfdemo/MuPDFActivity.java | 74 | ||||
-rw-r--r-- | android/src/com/artifex/mupdfdemo/MuPDFCore.java | 12 |
2 files changed, 82 insertions, 4 deletions
diff --git a/android/src/com/artifex/mupdfdemo/MuPDFActivity.java b/android/src/com/artifex/mupdfdemo/MuPDFActivity.java index f41b6178..f095a041 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFActivity.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFActivity.java @@ -1,6 +1,8 @@ package com.artifex.mupdfdemo; import java.util.concurrent.Executor; +import java.io.InputStream; +import java.io.FileInputStream; import android.animation.Animator; import android.animation.AnimatorInflater; @@ -12,6 +14,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources; import android.database.Cursor; import android.graphics.Color; import android.graphics.RectF; @@ -260,6 +263,23 @@ public class MuPDFActivity extends Activity return core; } + private MuPDFCore openBuffer(byte buffer[]) + { + System.out.println("Trying to open byte buffer"); + try + { + core = new MuPDFCore(buffer); + // New file: drop the old outline data + OutlineActivityData.set(null); + } + catch (Exception e) + { + System.out.println(e); + return null; + } + return core; + } + /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) @@ -292,6 +312,7 @@ public class MuPDFActivity extends Activity } if (core == null) { Intent intent = getIntent(); + byte buffer[] = null; if (Intent.ACTION_VIEW.equals(intent.getAction())) { Uri uri = intent.getData(); if (uri.toString().startsWith("content://")) { @@ -300,10 +321,51 @@ public class MuPDFActivity extends Activity // using explicit paths. Cursor cursor = getContentResolver().query(uri, new String[]{"_data"}, null, null, null); if (cursor.moveToFirst()) { - uri = Uri.parse(cursor.getString(0)); + String str = cursor.getString(0); + String failString = null; + if (str == null) { + try { + InputStream is = getContentResolver().openInputStream(uri); + int len = is.available(); + buffer = new byte[len]; + is.read(buffer, 0, len); + is.close(); + } + catch (java.lang.OutOfMemoryError e) + { + System.out.println("Out of memory during buffer reading"); + failString = e.toString(); + } + catch (Exception e) { + failString = e.toString(); + } + if (failString != null) + { + buffer = null; + Resources res = getResources(); + AlertDialog alert = mAlertBuilder.create(); + String contentFailure = res.getString(R.string.content_failure); + String openFailed = res.getString(R.string.open_failed); + setTitle(String.format(contentFailure, openFailed, failString)); + alert.setButton(AlertDialog.BUTTON_POSITIVE, "Dismiss", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + alert.show(); + return; + } + } else { + uri = Uri.parse(str); + } } } - core = openFile(Uri.decode(uri.getEncodedPath())); + if (buffer != null) { + core = openBuffer(buffer); + } else { + core = openFile(Uri.decode(uri.getEncodedPath())); + } SearchTaskResult.set(null); } if (core != null && core.needsPassword()) { @@ -1023,17 +1085,21 @@ public class MuPDFActivity extends Activity @Override protected void onStart() { if (core != null) + { core.startAlerts(); + createAlertWaiter(); + } - createAlertWaiter(); super.onStart(); } @Override protected void onStop() { - destroyAlertWaiter(); if (core != null) + { + destroyAlertWaiter(); core.stopAlerts(); + } super.onStop(); } diff --git a/android/src/com/artifex/mupdfdemo/MuPDFCore.java b/android/src/com/artifex/mupdfdemo/MuPDFCore.java index cf35be8d..ed9ded92 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFCore.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFCore.java @@ -18,9 +18,11 @@ public class MuPDFCore private float pageWidth; private float pageHeight; private long globals; + private byte fileBuffer[]; /* The native functions */ private native long openFile(String filename); + private native long openBuffer(); private native int countPagesInternal(); private native void gotoPageInternal(int localActionPageNum); private native float getPageWidth(); @@ -68,6 +70,16 @@ public class MuPDFCore } } + public MuPDFCore(byte buffer[]) throws Exception + { + fileBuffer = buffer; + globals = openBuffer(); + if (globals == 0) + { + throw new Exception("Failed to open buffer"); + } + } + public int countPages() { if (numPages < 0) |