无法在外部应用程序中打开 PDF 文件

Cannot open PDF file in external app

我想在用户单击按钮时打开 PDF 文件。 目前,我正在使用此代码来实现此目的:

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);

但是没用。

当我 select 使用 Adob​​e Acrobat 时,我收到一条消息,显示为 Toast,上面写着

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

当我尝试使用 Drive PDF 查看器时,我得到

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

PDF 文件存储在

app > build > intermediates > assets

问题出在哪里?

编辑

现在我使用以下代码:

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();
            }

但是当我尝试通过单击按钮打开 PDF 时,应用程序崩溃了。

这是我得到的日志:

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)

这是我的 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;
        }


    }

}

}

有人可以帮助我吗?

编辑 2

我找到了解决方案,请查看下面我的答案以获取代码。

谢谢大家的回答。

第三方应用无法通过 file:///android_asset 个 URL 访问您的资产。

您可以:

  • 尝试使用 my StreamProvider,让您的应用程序中有一个 ContentProvider 可以直接从资产提供 PDF,或者

  • 使用 Android 支持包中的 FileProvider,将文件从资产复制到内部存储后,如 this sample app 中所示,或

  • 将文件复制到外部存储并使用从 Uri.fromFile() 创建的 Uri 指向该副本

添加此权限并再次检查:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

似乎访问文件有问题。

尝试打开另一个 pdf 文件,让我们知道日志是什么。

而且我认为你不能使用这个:file:///android_asset

看看这个:

选择带ExternalStorageDirectory的文件:

File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+ filename);
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.fromFile(file),"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

Intent intent = Intent.createChooser(target, "Open File");

发件人:

有资产文件夹:

这是代码,如果您将其与 Assets 文件夹一起使用!

File file = new File("file:///android_asset/example.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);

然后加上上面的权限再用Assets code检查一遍。 另外,检查一下:

好的,问题解决了!

这是我用来打开存储在外部存储器中的 PDF 文件的代码:

File pdfFile = new File(Environment.getExternalStorageDirectory(),"namePdfFile.pdf");//File path
            if (pdfFile.exists()) //Checking if the file exists or not
            {
                Uri path = Uri.fromFile(pdfFile);
                Intent objIntent = new Intent(Intent.ACTION_VIEW);
                objIntent.setDataAndType(path, "application/pdf");
                objIntent.setFlags(Intent. FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(objIntent);//Starting the pdf viewer
            } else {

                Toast.makeText(getActivity(), "The file not exists! ", Toast.LENGTH_SHORT).show();

            }

将数据设置为 "file:///" + filePath 对我有用。

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

我遇到了同样的问题,经过几个小时的处理后我意识到我错过了在文件路径和文件名之间添加“/”。

所以找不到文件,我收到 "This file could not be accessed Check the location or the network and try again." 消息。

希望这对某人有所帮助 ;)

添加此权限后我的问题得到解决:)

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

该错误是因为每次pdf重新开始下载,但由于在限定的时间内无法下载完成,所以显示无效格式错误,文件id仍在下载中state.Use代码喜欢..

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

if (file.exists()) {
    showPdf();
}
else {
    download();
    showPdf();
}

对于较新的 API,您可以在 WebView 中打开 PDF,请参阅 Load PDF file in webview。我测试过,在 API 21 设备上它提供了几个应用程序可以打开,在 API 27 它在 WebView.

中打开

对于通常在外部打开 reader 复制此代码。我用过:intent.resolveActivity != null but launching the intent throws an ActivityNotFound exception, 。你应该先定义FileProvider。

// 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
            }
        }
    }

在API29模拟器(没有PDF应用程序)中我发现它在内置库中打开PDF。

向 runTime Persion 询问 WRITE STORAGE 否则文件本身不会存储到外部存储 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

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.

如果您使用的是 Android 9+,那么您至少需要在较低版本中测试一次。