Cannot open PDF file in external app

2020-03-11 08:37发布

I would like to open a PDF file when the user clicks on a button. Currently, i am using this code to achieve this:

Uri path = Uri.fromFile(new File("file:///android_asset/regola11_1.pdf"));
            Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
            pdfIntent.setDataAndType(path, "application/pdf");
            pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(pdfIntent);

but it doesn't work.

When i select to use Adobe Acrobat, i get a message, displayed as a Toast, that says

"This file could not be accessed Check the location or the network and try again."

When i try with Drive PDF Viewer, i get

"Cannot display PDF ( regola11_1.pdf cannot be opened)"

The PDF file is stored in

app > build > intermediates > assets

Where is the problem?

EDIT

Now i'm using the following code:

File file = new File("\"file:///android_asset/regola11_1.pdf");
            Uri path = Uri.fromFile(file);
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(path, "application/pdf");
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

            try {
                context.startActivity(intent);
            }
            catch (ActivityNotFoundException e) {
                Toast.makeText(context, "No application available to view PDF", Toast.LENGTH_LONG).show();
            }

But when i try to open the PDF by clicking on the button, the app crashes.

This is the log i get:

05-31 10:05:25.132  24474-24474/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.andrey.andreyvedis.iamaref, PID: 24474
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.content.Context.startActivity(android.content.Intent)' on a null object reference
        at com.andrey.andreyvedis.iamaref.FragmentR11.onClick(FragmentR11.java:147)
        at android.view.View.performClick(View.java:4781)
        at android.view.View$PerformClick.run(View.java:19873)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5293)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)

This is my class:

public class FragmentR11 extends Fragment implements  View.OnClickListener{
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
Context context;



// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;


/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1.
 * @param param2 Parameter 2.
 * @return A new instance of fragment FragmentR11.
 */
// TODO: Rename and change types and number of parameters
public static FragmentR11 newInstance(String param1, String param2) {
    FragmentR11 fragment = new FragmentR11();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

public FragmentR11() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }



}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_r11, container, false);


}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    getActivity().findViewById(R.id.bD1).setOnClickListener(this);
    getActivity().findViewById(R.id.bD2).setOnClickListener(this);
    getActivity().findViewById(R.id.bD3).setOnClickListener(this);
    getActivity().findViewById(R.id.bD4).setOnClickListener(this);
    getActivity().findViewById(R.id.bD5).setOnClickListener(this);
    getActivity().findViewById(R.id.bD6).setOnClickListener(this);
    getActivity().findViewById(R.id.bD7).setOnClickListener(this);
    getActivity().findViewById(R.id.bD8).setOnClickListener(this);
    getActivity().findViewById(R.id.bD9).setOnClickListener(this);
    getActivity().findViewById(R.id.bD10).setOnClickListener(this);
    getActivity().findViewById(R.id.bD11).setOnClickListener(this);
    getActivity().findViewById(R.id.bD12).setOnClickListener(this);
    getActivity().findViewById(R.id.bD13).setOnClickListener(this);
    getActivity().findViewById(R.id.bD14).setOnClickListener(this);
    getActivity().findViewById(R.id.bD15).setOnClickListener(this);
    getActivity().findViewById(R.id.bD16).setOnClickListener(this);
    getActivity().findViewById(R.id.bD17).setOnClickListener(this);


}

/**private void openPDF(final String pathToPDF) {
    File file = new File(pathToPDF);
    Uri path = Uri.fromFile(file);
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.setDataAndType(path, "application/pdf");
    try {
        startActivity(intent);
    } catch (ActivityNotFoundException e) {
        Toast.makeText(getActivity(), "Devi installare un'app per aprire PDF, come Adobe Acrobat Reader ", Toast.LENGTH_SHORT).show();
    }
}*/


@Override
public void onClick(View v) {



    switch(v.getId()){

        case R.id.bD1: {

            /**Uri path = Uri.fromFile(new File("regola11_1.pdf"));
            Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
            pdfIntent.setDataAndType(path, "application/pdf");
            pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(pdfIntent);
            Toast.makeText(getActivity(), "Hai cliccato Regola 1 in Reg11 ", Toast.LENGTH_SHORT).show();*/

            File file = new File("\"file:///android_asset/regola11_1.pdf");
            Uri path = Uri.fromFile(file);
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(path, "application/pdf");
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

            try {
                context.startActivity(intent);
            }
            catch (ActivityNotFoundException e) {
                Toast.makeText(context, "No application available to view PDF", Toast.LENGTH_LONG).show();
            }
            break;
        }

        case R.id.bD2:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 2 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }


        case R.id.bD3:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 3 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD4:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 4 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD5:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 5 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD6:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 6 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD7:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 7 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD8:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 8 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD9:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 9 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD10:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 10 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD11:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 11 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD12:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 12 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD13:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 13 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD14:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 14 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD15:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 15 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD16:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 16 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }

        case R.id.bD17:

        {
            Toast.makeText(getActivity(), "Hai cliccato Regola 17 in Reg11 ", Toast.LENGTH_SHORT).show();

            break;
        }


    }

}

}

Can someone help me?

EDIT 2

I have found the solution, check my answer below for the code.

Thank you all for your answers.

10条回答
Rolldiameter
2楼-- · 2020-03-11 08:54

Ask runTime Persion for WRITE STORAGE other wise file itself will not store to external storage <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

查看更多
啃猪蹄的小仙女
3楼-- · 2020-03-11 09:03

Setting data as "file:///" + filePath worked out for me.

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(filePath));
intent.setDataAndType(Uri.parse("file:///" + filePath), "application/pdf");
context.startActivity(intent);
查看更多
We Are One
4楼-- · 2020-03-11 09:07

For newer API you can open PDF in WebView, see Load PDF file in webview. I tested, on API 21 device it offered several applications to open, in API 27 it opened inside WebView.

For usual opening in external reader copy this code. I used: intent.resolveActivity != null but launching the intent throws an ActivityNotFound exception, https://stackoverflow.com/a/57141679/2914140. You should define FileProvider first.

// Try to open PDF and return false if it is not possible.
fun openPdf(file: File, context: Context): Boolean {
    val uri = getUriFromFile(file, context)
    if (uri == null) {
        return false
    } else {
        val intent = Intent(Intent.ACTION_VIEW).apply {
            setDataAndType(uri, "application/pdf")
            flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
        // Validate that the device can open your File.
        val activityInfo = intent.resolveActivityInfo(context.packageManager, intent.flags)
        return if (activityInfo?.exported == true) {
            context.startActivity(Intent.createChooser(intent, "Open PDF")))
            true
        } else {
            false
        }
    }
}

// Get URI from file.
fun getUriFromFile(file: File, context: Context): Uri? =
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        Uri.fromFile(file)
    } else {
        try {
            FileProvider.getUriForFile(context, context.packageName + ".provider", file)
        } catch (e: Exception) {
            if (e.message?.contains("ProviderInfo.loadXmlMetaData") == true) {
                throw Error("FileProvider doesn't exist or has no permissions")
            } else {
                throw e
            }
        }
    }

In API 29 emulator (without PDF applications) I found that it opened PDF in built-in library.

查看更多
姐就是有狂的资本
5楼-- · 2020-03-11 09:07

Had the same problem. This sounds silly, maybe outrageously stupid but guys let me tell you, I've tried everything, from correct permissions to FileProvider,ContentProvider custom classes but nothing worked (cost almost 7 hours). And guess what worked, uninstalling the app and running after re-installation, worked like a charm without anything extra. If nothing works give it a shot.

If you are using Android 9+ then you need to at least test once in lower versions.

查看更多
再贱就再见
6楼-- · 2020-03-11 09:13

I had the same problem, after hours dealing with the problem I realized that I missed to add "/" between file path and file name.

So the file was not found and I've got "This file could not be accessed Check the location or the network and try again." message.

Hope this help someone ;)

查看更多
▲ chillily
7楼-- · 2020-03-11 09:13

The error is because every time the pdf starts downloading again, but since downloading cann't be completed in that limited time period, it shows invalid format error and the file id is still in downloading state.Use code like..

Searchedtext = text.getText().toString();
File file = new File(Environment.getExternalStorageDirectory() + "/pdf", Searchedtext + ".pdf");

if (file.exists()) {
    showPdf();
}
else {
    download();
    showPdf();
}
查看更多
登录 后发表回答