2017-12-29 32 views
1

제 애플리케이션에서, PDF 파일을 비트 맵으로 렌더링하고 싶습니다. StackOverflow에서 많은 솔루션을 발견했지만 지금까지 아무 것도 작동하지 않았습니다. 나는 android:largeHeap="true"하고 여기에OutOfMemoryError 예외를 던집니다.

android:hardwareAccelerated="false" 스택 트레이스를 다음 변경 한

다음
FATAL EXCEPTION: main 
Process: com.myclasscampus.aspire, PID: 6214 
java.lang.OutOfMemoryError: Failed to allocate a 434035012 byte allocation with 4194304 free bytes and 328MB until OOM 
at dalvik.system.VMRuntime.newNonMovableArray(Native Method) 
at android.graphics.Bitmap.nativeCreate(Native Method) 
at android.graphics.Bitmap.createBitmap(Bitmap.java:879) 
at android.graphics.Bitmap.createBitmap(Bitmap.java:856) 
at android.graphics.Bitmap.createBitmap(Bitmap.java:823) 
at com.aspire.pdfViewer.PDFViewFragment.showPage(PDFViewFragment.java:176) 
at com.aspire.pdfViewer.PDFViewFragment.openRenderer(PDFViewFragment.java:154) 
at com.aspire.pdfViewer.PDFViewFragment.onCreateView(PDFViewFragment.java:86) 
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2192) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1299) 
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595) 
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:758) 
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2363) 
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2149) 
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2103) 
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2013) 
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388) 
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:607) 
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178) 
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1248) 
at android.app.Activity.performStart(Activity.java:6679) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2609) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6077) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) 

내 AndroidManifest를 선언

다음
<application 
     android:name="com.aspire.webserviceConstant.AppController" 
     android:allowBackup="true" 
     android:hardwareAccelerated="false" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:largeHeap="true" 
     android:supportsRtl="true" 
     android:theme="@style/AppTheme.calender" 
     tools:replace="android:name"> 

입니다 이 코드 행은 메모리 434,035,012 바이트를 할당하려고 비트 맵을

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 
    private void showPage(int index) { 
     try { 

      if (pdfRenderer.getPageCount() <= index) { 
       return; 
      } 

      if (null != currentPage) { 
       currentPage.close(); 
      } 

      currentPage = pdfRenderer.openPage(index); 
      releaseBitmap(); 

      bitmapPDF = Bitmap.createBitmap(
        getResources().getDisplayMetrics().densityDpi * currentPage.getWidth()/72, 
        getResources().getDisplayMetrics().densityDpi * currentPage.getHeight()/72, 
        Bitmap.Config.ARGB_8888); 

      currentPage.render(bitmapPDF, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY); 
      imgPdfView.setImageBitmap(bitmapPDF); 
      updateUIData(); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

private void releaseBitmap() { 
    if (bitmapPDF != null) { 
     bitmapPDF.recycle(); 
     bitmapPDF = null; 
    } 
} 
+4

질문을 편집하고 두 줄만 입력하는 대신 전체 Java 스택 추적을 게시하십시오. – CommonsWare

+0

@CommonsWare 물론 확인해보세요. – Kuls

+0

당신은 또한'android : hardwareAccelerated = "true"'시도해 보았습니다. –

답변

4
 bitmapPDF = Bitmap.createBitmap(
       getResources().getDisplayMetrics().densityDpi * currentPage.getWidth()/72, 
       getResources().getDisplayMetrics().densityDpi * currentPage.getHeight()/72, 
       Bitmap.Config.ARGB_8888); 

을 만들어 내 코드입니다. ARGB_8888의 경우 픽셀 당 4 바이트로 10,416 x 10,416 픽셀 이미지와 같습니다.

크기와 비슷한 화면 해상도를 가진 일반적인 Android 기기가 없습니다. 당신이 더 당신이 메모리 문제로 실행할 수 있습니다 — 1000 X 1000 픽셀 등으로 인해 안드로이드의 가비지 컬렉터의 한계와 결합 할 때 Bitmap을 해제하는 정책으로, — 말을 꽤하여이를 감소하더라도

.

이 Android API를 통해 PDF를 만든 경우가 아니면 PdfRenderer이 제대로 렌더링하지 못할 가능성이 있습니다. 이 클래스는 인쇄 미리보기를 위해 존재하며 임의의 PDF 내용을 렌더링하기위한 것이 아닙니다.

임의의 PDF를 렌더링하려는 경우 other PDF rendering options을 사용하십시오. Android 드로잉 코드를 통해 만든 PDF의 인쇄 미리보기를 수행하려는 경우 PdfRenderer을 계속 사용하려면 해상도를 줄이고 가능한 한 적은 수의 Bitmap 개체를 사용하십시오. 이전에 할당 한 개체를 다시 할당하지 말고 다시 사용하십시오. 모든 페이지.

+0

자세한 답변을 주셔서 대단히 감사드립니다. 주요 관심사는 응용 프로그램 내에 PDF를 표시하는 것입니다. 어떤 종류의 발췌 문장이나 PDF 또는 어쨌든 이런 종류의 비트 맵을 처리하는 다른 방법을 제안 할 수 있습니까? – Kuls

+0

@KulsDroid : "일부 스 니펫이나 PDF를 보여줄 다른 방법을 제안 할 수 있습니까?"- 내가 당신을 [주제에 관한 블로그 게시물]에 링크 시켰습니다 (https://commonsware.com/blog/2017/01/04). /options-viewing-pdfs.html). "어쨌든 이런 종류의 비트 맵을 처리 할 수 ​​있습니까?" - 나는 이것을 내 대답에서 다루었 다. 해상도를 줄이고 가능한 한 적은 Bitmap 오브젝트를 사용하십시오. 모든 페이지에 새로운 오브젝트를 할당하는 것이 아니라 이전에 할당 된 오브젝트를 재사용함으로써 가능합니다. – CommonsWare