Christopher Rucinski Christopher Rucinski - 6 months ago 18
Android Question

Intent to open PDF instantly closes before showing the file

I am using the following code to open a specific file I have placed in my working app module...

private void openPDF(String filename) {

File file = new File(Environment.getExternalStorageDirectory(), filename);
Uri path = Uri.fromFile(file);

Intent pdfIntent = new Intent(Intent.ACTION_VIEW);

pdfIntent.setDataAndType(path, "application/pdf");

try {
startActivity(pdfIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(MainActivity.this, "There is no PDF file.",
Toast.LENGTH_SHORT).show();
}
}


I get within the
try-statement
and the
startActivity(...)
method is invoked. I get a dialog to choose which app I want to open the file in, but when I choose the app, Android will open the app, display the correct filename within the app, but then will automatically close the PDF app before the file is actually displayed.

How do I go about keeping the PDF file open until the user decides to actually "close" it?

By the way, I get no error messages and no warnings that I can see. The PDF app just closes. I also, tried to open the file with
Google Custom Tabs
since I already use that in my app, but it didn't open the PDF file (as I kind of expected)

Update



For implementing
StreamProvider
, I have decided to create a simple extension to
StreamProvider
that will read a unique tag
pdf-path
that will delegate the work to open an
asset
file

Here is the code...

public class PdfProvider extends StreamProvider {

// Special xml path tag that will work for PDFs (or any asset really)
private static final String PDF_TAG = "pdf-path";

@Override
protected String getUriPrefix() { return null; }

@Override
protected StreamStrategy buildStrategy(Context context, String tag, String name, String path, HashMap<String, String> attrs) throws IOException {
if (PDF_TAG.equals(tag)) {
super.buildStrategy(context, "asset", name, path, attrs);
}
return super.buildStrategy(context, tag, name, path, attrs);
}
}


Also, I have the
noCompress
addition to my
gradle
file and the path meta-data...

<paths>
<pdf-path name="resume" path="resume/resume.pdf"/>
</paths>


I am confused at how to actually use
PdfProvider
. The documentation seems to have
asset
logic as a second-thought and the demo code for
StreamProvider
is a little convoluted with additional logic that makes it harder to understand the provider aspect.

Answer

I just drag-and-dropped the file within the app module. Not within the src folder. Is that even right?

Alas, no. That is your project on your development machine. It is not external storage on ~1.5 billion devices.

If your long-term objective is to actually show a PDF from external storage, put it on external storage of your device or emulator. With the Android Studio 2.x emulator, you can drag and drop the PDF into the emulator window, though that will put it in the Downloads/ directory of external storage, not the root.

If your long-term objective is to show a PDF that you package with your app, put the PDF in assets/ of your module's main sourceset (e.g., app/src/main/assets/ in a typical Android Studio project). Then, either: