我是新来的,但是想知道是否有人可以指出我正确的方向。这是我的应用程序的一部分,我想从资源中读取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)
答案 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);