I am trying to make an app which downloads the pdf file from the internet and saves it to Downloads folder. After downloading the pdf,instead of opening a 3rd party pdf app , I want it to render in the app itself.( I have done downloading and saving in Downloads folder part). For this, I have to use PDFRendered. But the problem I am facing is that I am a newbie and after looking at some tutorials , I am able to render a pdf properly but only when it is present in the assets folder. Downloaded pdf is present in the Downloads folder. Is there any way in which I can use the pdf from Downloads folder and render it in the app itself instead of pre-defining the pdf file in the assets folder?
I have tried downloading and saving file in Downloading folder and I have successfully done it but I'm unable to use the file to render as it is not inside assets folder.
//Code which is successfully rendering pdf from assets folder. How to
//use it to render pdf from Download folder?
public class PdfRender extends AppCompatActivity {
@BindView(R.id.pdf_image) ImageView imageViewPdf;
@BindView(R.id.button_pre_doc) FloatingActionButton prePageButton;
@BindView(R.id.button_next_doc) FloatingActionButton nextPageButton;
private static final String FILENAME = Environment.DIRECTORY_DOWNLOADS+"/a.pdf";
private int pageIndex;
private PdfRenderer pdfRenderer;
private PdfRenderer.Page currentPage;
private ParcelFileDescriptor parcelFileDescriptor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pdf_render);
ButterKnife.bind(this);
pageIndex = 0;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onStart() {
super.onStart();
try {
openRenderer(getApplicationContext());
showPage(pageIndex);
} catch (IOException e) {
e.printStackTrace();
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onStop() {
try {
closeRenderer();
} catch (IOException e) {
e.printStackTrace();
}
super.onStop();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@OnClick(R.id.button_pre_doc)
public void onPreviousDocClick(){
showPage(currentPage.getIndex() - 1);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@OnClick(R.id.button_next_doc)
public void onNextDocClick(){
showPage(currentPage.getIndex() + 1);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void openRenderer(Context context) throws IOException {
// In this sample, we read a PDF from the assets directory.
File file = new File(context.getCacheDir(), FILENAME);
if (!file.exists()) {
// Since PdfRenderer cannot handle the compressed asset file directly, we copy it into
// the cache directory.
InputStream asset = context.getAssets().open(FILENAME);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
// This is the PdfRenderer we use to render the PDF.
if (parcelFileDescriptor != null) {
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void closeRenderer() throws IOException {
if (null != currentPage) {
currentPage.close();
}
pdfRenderer.close();
parcelFileDescriptor.close();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
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();
}
// Use `openPage` to open a specific page in PDF.
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.
// To render a portion of the page, use the second and third parameter. Pass nulls to get
// the default result.
// Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
currentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// We are ready to show the Bitmap to user.
imageViewPdf.setImageBitmap(bitmap);
updateUi();
}
/**
* Updates the state of 2 control buttons in response to the current page index.
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void updateUi() {
int index = currentPage.getIndex();
int pageCount = pdfRenderer.getPageCount();
prePageButton.setEnabled(0 != index);
nextPageButton.setEnabled(index + 1 < pageCount);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public int getPageCount() {
return pdfRenderer.getPageCount();
}
}
Update-: I tried to make changes to a working code of Rendering app and edit openRenderer() to make changes and give my file name and location as below but still the pdf file dosen't open even thugh it is detected (checked in logs using file.exists()) . Any way to find solution to this problem?
`private void openRenderer(Context context) throws IOException {
File file = new File("storage/emulated/0/Download/" + FILENAME);
if (!file.exists()) {
Log.e("testit", "Not exists");
FileInputStream asset = new FileInputStream(file);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
parcelFileDescriptor = ParcelFileDescriptor.open(file,ParcelFileDescriptor.MODE_READ_ONLY);
// This is the PdfRenderer we use to render the PDF.
if (parcelFileDescriptor != null) {
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
}
}`
I get the following error in logs
`java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.pdf.PdfRenderer.close()' on a null object reference`
Expected results are fetch and download the pdf from the internet. Click on a button which downloads and immediately after downloading renders the pdf in the app itself and users can view the pdf in the app itself without the use of any 3rd party pdf app or a webview(for users after or on 5.0).