简体   繁体   中英

Android v23 PDFreader keep crashing

I am new here however wondering if someone could point me in the right direction. This is part of my app in which I want to read PDF file from assets and display in the fragment. Android version used 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 error message

              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)

There looks to be at least 2 different issues right now affecting PdfRenderer behaviour.

First one is related to bug in v2.2 of gradle plugin ( https://code.google.com/p/android/issues/detail?id=224273 ) that affects treatment of following gradle config that's required to ensure pdf is not compressed (as mentioned in https://github.com/googlesamples/android-PdfRendererBasic ). This is required as PdfRenderer needs a ParcelFileDescriptor that is seekable (so file cannot be compressed). You can reproduce this issue with google's PdfRendererBasic sample by using 2.2 version of gradle plugin. A fix for this is to revert to v2.1.2 of plugin.

android {
    aaptOptions {
        noCompress "pdf"
    }
}

The other issue doesn't seem to be occurring in PdfRendererBasic sample but is in other apps (including mine!) and seems to be related to packaging of apk ( Android Studio - PDFRendererBasic - Unable to replace sample.pdf? contains detailed discussion on issue).

One suggestion in last linked SO article was to read from raw folder instead....however this didn't work for me for some reason. What I had to do in the end was ready pdf from SD card using something like following

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM