简体   繁体   English

Android v23 PDFreader不断崩溃

[英]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. 这是我的应用程序的一部分,在该应用程序中,我想从资产中读取PDF文件并显示在片段中。 Android version used 23.4.0 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 error message 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)

There looks to be at least 2 different issues right now affecting PdfRenderer behaviour. 现在看来至少有2个不同的问题会影响PdfRenderer行为。

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 ). 第一个与gradle插件v2.2( https://code.google.com/p/android/issues/detail?id=224273 )中的错误有关,该错误会影响以下确保Gradle不需要的gradle配置的处理压缩(如https://github.com/googlesamples/android-PdfRendererBasic中所述 )。 This is required as PdfRenderer needs a ParcelFileDescriptor that is seekable (so file cannot be compressed). 这是必需的,因为PdfRenderer需要一个可ParcelFileDescriptor (因此无法压缩文件)。 You can reproduce this issue with google's PdfRendererBasic sample by using 2.2 version of gradle plugin. 您可以使用2.2版本的gradle插件,使用Google的PdfRendererBasic示例重现此问题。 A fix for this is to revert to v2.1.2 of plugin. 解决此问题的方法是还原到插件v2.1.2。

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). 另一个问题似乎不在PdfRendererBasic示例中发生,而是在其他应用程序中(包括我的!),并且似乎与apk的打包有关( Android Studio-PDFRendererBasic-无法替换sample.pdf?包含有关该问题的详细讨论)。

One suggestion in last linked SO article was to read from raw folder instead....however this didn't work for me for some reason. 上一篇链接的SO文章中的一个建议是改为从raw文件夹中读取...。但是由于某种原因,这对我不起作用。 What I had to do in the end was ready pdf from SD card using something like following 我最终要做的是使用以下类似的东西从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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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