-2

I have some problem when trying to open a pdf (a.pdf) from my assets folder. Thi is the java code:

package com.tischer.alessandro.ecocardiochecklist;


import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Bibliografia extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bibliografia);
        AssetManager assetManager = getAssets();

        InputStream in = null;
        OutputStream out = null;
        File file = new File(getFilesDir(), "a.pdf");
        try
        {
            in = assetManager.open("a.pdf");
            out = openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);

            copyFile(in, out);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
        } catch (Exception e)
        {
            Log.e("tag", e.getMessage());
        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(
                Uri.parse("file://" + getFilesDir() + "/a.pdf"),
                "application/pdf");

        startActivity(intent);
    }

    private void copyFile(InputStream in, OutputStream out) throws IOException
    {
        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1)
        {
            out.write(buffer, 0, read);
        }
    }

}

This is the logcat:

11/10 11:52:42: Launching app
Cold swapped changes.
$ adb shell am start -n "com.tischer.alessandro.ecocardiochecklist/com.tischer.alessandro.ecocardiochecklist.SplashScreen" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Client not ready yet..Waiting for process to come online
Connected to process 3259 on device Nexus_5X_API_24 [emulator-5554]
I/InstantRun: Instant Run Runtime started. Android package is com.tischer.alessandro.ecocardiochecklist, real application class is null.

              [ 11-10 10:52:44.162  1489: 1510 D/         ]
              HostConnection::get() New Host Connection established 0x8d361440, tid 1510
W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
W/gralloc_ranchu: Gralloc pipe failed

                  [ 11-10 10:52:45.193  3259: 3259 D/         ]
                  HostConnection::get() New Host Connection established 0x9d027140, tid 3259


                  [ 11-10 10:52:45.239  3259: 3278 D/         ]
                  HostConnection::get() New Host Connection established 0x9d0d6d40, tid 3278
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
D/OpenGLRenderer: endAllActiveAnimators on 0x90937d80 (RippleDrawable) with handle 0x9d07eb80
E/tag: MODE_WORLD_READABLE no longer supported
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.tischer.alessandro.ecocardiochecklist, PID: 3259
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tischer.alessandro.ecocardiochecklist/com.tischer.alessandro.ecocardiochecklist.Bibliografia}: android.os.FileUriExposedException: file:///data/user/0/com.tischer.alessandro.ecocardiochecklist/files/a.pdf exposed beyond app through Intent.getData()
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
                      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:865)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                   Caused by: android.os.FileUriExposedException: file:///data/user/0/com.tischer.alessandro.ecocardiochecklist/files/a.pdf exposed beyond app through Intent.getData()
                      at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
                      at android.net.Uri.checkFileUriExposed(Uri.java:2346)
                      at android.content.Intent.prepareToLeaveProcess(Intent.java:8933)
                      at android.content.Intent.prepareToLeaveProcess(Intent.java:8894)
                      at android.app.Instrumentation.execStartActivity(Instrumentation.java:1517)
                      at android.app.Activity.startActivityForResult(Activity.java:4224)
                      at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
                      at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:75)
                      at android.app.Activity.startActivityForResult(Activity.java:4183)
                      at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:856)
                      at android.app.Activity.startActivity(Activity.java:4507)
                      at android.app.Activity.startActivity(Activity.java:4475)
                      at com.tischer.alessandro.ecocardiochecklist.Bibliografia.onCreate(Bibliografia.java:48)
                      at android.app.Activity.performCreate(Activity.java:6664)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
                      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:865) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 

I'm running Android 7.0, but the app crashes also with older versions... Where's the problem?

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • *Where's the problem?* FileUriExposedException - looks like self self-explanatory exception ... already asked many times ... obvious solution is to use the FileProvider – Selvin Nov 10 '16 at 11:08
  • Sorry, but I'm new in android development... I still can't understand what I have to change in the code... could you help me? – Alessandro Tischer Nov 10 '16 at 11:10
  • Do internet search on FileUriExposedException – Selvin Nov 10 '16 at 11:10
  • I modified file:// to content:// as explained here: [link](https://developer.android.com/reference/android/os/FileUriExposedException.html) But it still crashes – Alessandro Tischer Nov 10 '16 at 11:36
  • second link in internet search points to exact the same question here on SO with answers ... – Selvin Nov 10 '16 at 11:37
  • https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed Or, for this specific case, [use my `StreamProvider`](https://github.com/commonsguy/cwac-provider), and you can skip copying the file from assets. – CommonsWare Nov 10 '16 at 15:59

2 Answers2

0

You copy the file to your application's private directory, where no other apps can access. And then you try to open this file in another app (it is just unable to access that file from your application's private directory).

To solve this, you have few options:

  1. Copy the file to some public directory, like Environment.getExternalStorageDirectory()
  2. Implement a ContentProvider in your app

1st way is easier, and I would go this way if I was doing it.
2nd way is more correct, but obviously is an overheat here for me.

Vladyslav Matviienko
  • 10,610
  • 4
  • 33
  • 52
  • I'd like to implement the content provider, also because I'm creating this app because I want to learn, so I want to do things as better as possible. Could you help me in inserting the content provider? – Alessandro Tischer Nov 10 '16 at 11:46
  • I found this: [link](http://stackoverflow.com/a/21063373/7123499), which seems to be great, but it doesn't work for me... – Alessandro Tischer Nov 10 '16 at 11:48
  • @AlessandroTischer, I could, but it does not completely match your question topic. You should ask a new question for that I think. But firstly, you should google about that since there already is a tone of lessons about content providers on the internet, and there is no reason for me to copy-paste the code for you from one of the lessons – Vladyslav Matviienko Nov 10 '16 at 11:49
  • @AlessandroTischer, that library themes grait, but what actually `does not work` for you there? – Vladyslav Matviienko Nov 10 '16 at 11:52
  • I've set everything like it's said (assets/public_pdfs/filename.pdf.mp3). The app opens the pdf viewer, but it cannot see the pdf... (I can't attach log because I can't install pdf reader on the emulator) @Vlad – Alessandro Tischer Nov 10 '16 at 13:34
  • @AlessandroTischer, to get log, you can install an APK to the emulator directly, or debug on the real device. – Vladyslav Matviienko Nov 10 '16 at 13:37
  • I get no log about the error, probably because the error is gotten by the pdf viewer... @Vlad – Alessandro Tischer Nov 10 '16 at 13:47
  • "1st way is easier" -- except that it will not work on Android 7.0+, with a `targetSdkVersion` of 24 or higher, as it will lead to the very `FileUriExposedException` that the OP encountered. – CommonsWare Nov 10 '16 at 16:00
  • @CommonsWare, but why? – Vladyslav Matviienko Nov 10 '16 at 17:14
  • Because [the `file` `Uri` scheme is effectively banned in Android 7.0+](https://commonsware.com/blog/2016/03/14/psa-file-scheme-ban-n-developer-preview.html). – CommonsWare Nov 10 '16 at 17:15
0

i think you should get the context first,

Context context=getApplicationContext();

 AssetManager assetManager = context.getAssets();