I am stuck trying to open files from assets in my app .apk file. I get a variety of errors each time I do it but currently I have the following error.
2019-01-18 15:51:34.248 8120-8120/com.example.geoff.crosshouse_icu E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.geoff.crosshouse_icu, PID: 8120 android.os.FileUriExposedException: file:///storage/emulated/0/MyFiles/paediatric_drugs.xlsx exposed beyond app through Intent.getData() at android.os.StrictMode.onFileUriExposed(StrictMode.java:1978) at android.net.Uri.checkFileUriExposed(Uri.java:2371) at android.content.Intent.prepareToLeaveProcess(Intent.java:10247) at android.content.Intent.prepareToLeaveProcess(Intent.java:10201) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1667) at android.app.Activity.startActivityForResult(Activity.java:4586)
My current method involves click a navigation menu item to load a spreadsheet from assets called "paediatrics_drugs.xlsx". When that is clicked, the following code is run.
// Copy file from assets
String filename = "paediatric_drugs.xlsx";
copyAsset(filename);
try {
openFile(filename);
} catch (IOException e){
e.printStackTrace();
Toast.makeText(this, "Intent failed!", Toast.LENGTH_SHORT).show();
}
The copyAsset(String) method creates a folder in external storage called "MyFiles" and attempts to create a new file there by reading from an InputStream as seen in code below:
private void copyAsset(String filename) {
String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyFiles";
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
}
AssetManager assets = getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assets.open(filename);
File outFile = new File(dirPath, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
Toast.makeText(this, "saved!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "failed!", Toast.LENGTH_LONG).show();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
It calls copyFile which takes an input and output stream:
private void copyFile(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
}
And lastly it calls openFile(String filename) which creates an intent to open the spreadsheet:
private void openFile(String filename) throws IOException {
String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyFiles";
File toOpen = new File(dirPath, filename);
if (toOpen.exists()) {
Uri uri = Uri.fromFile(toOpen);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "application/vnd.ms-excel");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
}
I am not sure what I am doing wrong, I have looked into several ways of doing it online and have also tried to read from res/raw instead and don't seem to be having any joy. I have the correct permissions established in my manifest, and I am testing in using a minimum Sdk of 15, but running it on a Google Pixel with sdk 28.
Any advice would be much appreciated. If you need me to provide any further information just let me know.