Android v23 PDFreader不断崩溃

时间:2016-12-13 01:16:12

标签: android pdf-rendering

我是新来的,但是想知道是否有人可以指出我正确的方向。这是我的应用程序的一部分,我想从资源中读取PDF文件并显示在片段中。 Android版本使用23.4.0

public class PDFFragment extends Fragment {

private ParcelFileDescriptor fileDescriptor;
private PdfRenderer pdfRenderer;
private PdfRenderer.Page currentPage;
private ImageView image;
private Button buttonPrevious;
private Button buttonNext;

public PDFFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_research_paper, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    // Retain view references.
    image = (ImageView) view.findViewById(R.id.image);
    buttonPrevious = (Button) view.findViewById(R.id.button_previous_research);
    buttonNext = (Button) view.findViewById(R.id.button_next_research);

    //set buttons event
    buttonPrevious.setOnClickListener(onActionListener(-1)); //previous button clicked
    buttonNext.setOnClickListener(onActionListener(1)); //next button clicked

    int index = 0;
    // If there is a savedInstanceState (screen orientations, etc.), we restore the page index.
    if (null != savedInstanceState) {
        index = savedInstanceState.getInt("current_page", 0);
    }
    showPage(index);
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        openRenderer(activity);
    } catch (IOException e) {
        e.printStackTrace();
        Log.i("Fragment", "Error occurred!");
        Log.e("Fragment", e.getMessage());
        activity.finish();
    }
}

@Override
public void onDestroy() {
    try {
        closeRenderer();
    } catch (IOException e) {
        e.printStackTrace();
    }
    super.onDestroy();
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (null != currentPage) {
        outState.putInt("current_page", currentPage.getIndex());
    }
}

 //Create a PDF renderer
private void openRenderer(Activity activity) throws IOException {
    // Reading a PDF file from the assets directory.
    fileDescriptor = activity.getAssets().openFd("research_paper.pdf").getParcelFileDescriptor();

    // This is the PdfRenderer we use to render the PDF.
    pdfRenderer = new PdfRenderer(fileDescriptor);
}

 //Closes PdfRenderer and related resources.
private void closeRenderer() throws IOException {
    if (null != currentPage) {
        currentPage.close();
    }
    pdfRenderer.close();
    fileDescriptor.close();
}

 //Shows the specified page of PDF file to screen
private void showPage(int index) {
    if (pdfRenderer.getPageCount() <= index) {
        return;
    }
    // Make sure to close the current page before opening another one.
    if (null != currentPage) {
        currentPage.close();
    }
    //open a specific page in PDF file
    currentPage = pdfRenderer.openPage(index);
    // Important: the destination bitmap must be ARGB (not RGB).
    Bitmap bitmap = Bitmap.createBitmap(currentPage.getWidth(), currentPage.getHeight(),
            Bitmap.Config.ARGB_8888);
    // Here, we render the page onto the Bitmap.
    currentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
    // showing bitmap to an imageview
    image.setImageBitmap(bitmap);
    updateUIData();
}

 //Updates the state of 2 control buttons in response to the current page index.
private void updateUIData() {
    int index = currentPage.getIndex();
    int pageCount = pdfRenderer.getPageCount();
    buttonPrevious.setEnabled(0 != index);
    buttonNext.setEnabled(index + 1 < pageCount);
    getActivity().setTitle(getString(index + 1, pageCount));
}

private View.OnClickListener onActionListener(final int i) {
    return new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (i < 0) {//go to previous page
                showPage(currentPage.getIndex() - 1);
            } else {
                showPage(currentPage.getIndex() + 1);
            }
        }
    };
}

}

Logcat错误消息

              java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.pdf.PdfRenderer.getPageCount()' on a null object reference
                  at com.example.PDFFragment.showPage(PDFFragment.java:115)
                  at com.example.PDFFragment.onViewCreated(PDFFragment.java:61)
                  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
                  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
                  at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
                  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
                  at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:5417)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

1 个答案:

答案 0 :(得分:1)

现在看来至少有两个不同的问题正在影响PdfRenderer行为。

第一个与gradle插件v2.2(https://code.google.com/p/android/issues/detail?id=224273)中的错误相关,该错误会影响以下gradle配置的处理,这是确保pdf未被压缩所必需的(如https://github.com/googlesamples/android-PdfRendererBasic中所述)。这是必需的,因为PdfRenderer需要可查找的ParcelFileDescriptor(因此无法压缩文件)。您可以使用2.2版本的gradle插件通过google的PdfRendererBasic示例重现此问题。解决此问题的方法是恢复到插件的v2.1.2。

android {
    aaptOptions {
        noCompress "pdf"
    }
}

另一个问题似乎没有发生在PdfRendererBasic示例中,但是在其他应用程序中(包括我的!)并且似乎与apk的包装有关(Android Studio - PDFRendererBasic - Unable to replace sample.pdf?包含有关问题的详细讨论)。

上一篇链接的SO文章中的一个建议是从raw文件夹中读取....但是由于某种原因,这对我不起作用。最后我要做的就是从SD卡上准备pdf,使用类似下面的内容

    String pdfPath = Environment.getExternalStorageDirectory() + "/sample.pdf";
    mFileDescriptor = ParcelFileDescriptor.open(new File(pdfPath), ParcelFileDescriptor.MODE_READ_ONLY);

    // This is the PdfRenderer we use to render the PDF.
    mPdfRenderer = new PdfRenderer(mFileDescriptor);