如何通过Android Intent打开在线PDF文件?

43

目前我有一个pdf的url,我希望可以使用intent来打开它,但是如果我将url放在intent中,它就无法工作。

我的代码是这样的,它总是抛出ActivityNotFoundException错误。

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(law.url), "application/pdf");

try {
    startActivity(intent);
} catch (ActivityNotFoundException e){
    Utility.showErrorDialog(
        ctx,ctx.getResources().getString(R.string.sys_in, 
        ctx.getResources().getString(R.string.err_no_pdf_reader), 
        ctx.getResources().getString(R.string.close));
}

我也尝试了使用谷歌文档的方法,但我的客户拒绝了,所以我没有使用这种方法。

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setDataAndType(Uri.parse("http://docs.google.com/viewer?url=" 
+ publish.get(Integer.parseInt((String) view.getTag())).pdfURL), "text/html");  
ctx.startActivity(intent);

谢谢您的帮助

日志记录错误更新

04-23 18:18:50.487: E/AndroidRuntime(17161): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=http://oshc.zizsoft.com/oshc_testing.pdf typ=application/pdf }
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1568)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1439)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.app.Activity.startActivityForResult(Activity.java:3356)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.app.Activity.startActivityForResult(Activity.java:3317)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.support.v4.app.FragmentActivity.startActivityFromFragment(FragmentActivity.java:848)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.support.v4.app.Fragment.startActivity(Fragment.java:878)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at com.example.oshpedia.Fragment.Shelf$4.onItemClick(Shelf.java:142)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at it.sephiroth.android.library.widget.AdapterView.performItemClick(AdapterView.java:299)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at it.sephiroth.android.library.widget.AbsHListView.performItemClick(AbsHListView.java:972)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at it.sephiroth.android.library.widget.AbsHListView$PerformClick.run(AbsHListView.java:2511)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at it.sephiroth.android.library.widget.AbsHListView$1.run(AbsHListView.java:3200)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.os.Handler.handleCallback(Handler.java:615)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.os.Handler.dispatchMessage(Handler.java:92)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.os.Looper.loop(Looper.java:137)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at android.app.ActivityThread.main(ActivityThread.java:4882)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at java.lang.reflect.Method.invokeNative(Native Method)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at java.lang.reflect.Method.invoke(Method.java:511)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
04-23 18:18:50.487: E/AndroidRuntime(17161):    at dalvik.system.NativeStart.main(Native Method)

第一个例子应该可以工作。请发布完整的“ActivityNotFoundException”堆栈跟踪。 - shkschneider
你好,你有什么建议吗?通过Android Intent打开在线PDF文件,哪种方法最好? - Bolt UIX
14个回答

88

您可以通过以下两种方式之一查看或下载pdf文件,即在设备内置浏览器中打开它,或通过将其嵌入您的应用程序中的Web视图中。

要在浏览器中打开pdf文件,请

Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(pdf_url));
startActivity(browserIntent);

不要打开网页视图,

 WebView webView = (WebView) findViewById(R.id.webView1);
 webView.getSettings().setJavaScriptEnabled(true);
 webView.loadUrl(pdf_url);

@Tuhin Subhra,你是如何解决网页无法访问的问题的? - Ameer
不建议使用Google文档中的webView.loadUrl(),如此处所述:https://dev59.com/MHE95IYBdhLWcg3wGqEH#10861538 - hjchin
1
注意:它是 WebView 而不是 Webview。(从 android.webkit.WebView 导入) - lcsvcn

41

在开始之前,最好将您的Intent包装到Chooser中。这提供了内置的应用程序选择对话框,避免了ActivityNotFoundException

以下是一个简单的示例:

Intent browserIntent = new Intent(Intent.ACTION_VIEW);
browserIntent.setDataAndType(Uri.parse(msg.getData()), Constants.MIME_PDF);

Intent chooser = Intent.createChooser(browserIntent, getString(R.string.chooser_title));
chooser.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // optional

startActivity(chooser);

Constants.MIME_PDF 被定义为字符串值 "application/pdf"。


可以向 PackageManager 询问此 Intent 是否具有适当的处理 Activity

public static boolean isActivityForIntentAvailable(Context context, Intent intent) {
    final PackageManager packageManager = context.getPackageManager();
    List list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}

1
这是一个很好的解决方案,因为它利用现有的应用程序打开PDF文档,并且还给用户选择他喜欢的选项。如果不添加选择器,那么如果没有安装任何“PDF阅读器”应用程序,该应用程序将会出现故障。 - mgm
简单而惊人。谢谢! - Alex Belets
这对我很有帮助。我有一个没有PDF名称的链接,当我们点击该URL时会生成PDF。在Webview中,它最近停止显示。使用chooser方法,我能够显示PDF。谢谢。 - ashishdhiman2007
这是一个不错的解决方案,但当我使用谷歌云盘的链接时,它无法工作。您能否请看一下这个问题 - ganjaam

11

你可以像这样在网页视图中查看PDF

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setDataAndType(Uri.parse( "http://docs.google.com/viewer?url=" + pdfLink), "text/html");

startActivity(intent);

2
当您的浏览器中没有Google帐户时,它将无法工作。 - Hoàng Vũ Anh

10
我看到您正在尝试使用此方法定义数据类型: ```

我看到您正在尝试使用此方法定义数据类型:

```
Intent intent = new Intent();
intent.setDataAndType(Uri.parse(url), "application/pdf");
startActivity(intent);

但是这会导致以下问题:

ActivityNotFoundException: 找不到Activity处理Intent

使用没有类型定义的方法,它将完美地工作:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);

6
您可以像这样在Webview中查看PDF文件。
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginsEnabled(true);
webView.loadUrl("https://docs.google.com/viewer?"+pdf_url);

4
谢谢您的回答,对我帮助很大。不过请注意,您的代码缺少url参数名称,即应该是:webView.loadUrl("https://docs.google.com/viewer?url="+pdf_url); - gts101
3
我无法预览。 - Juturu Yugandhar
嗨,在这里我需要传递输入参数和URL,然后我会得到PDF链接。 - Kumar
@JuturuYugandhar,这个解决方案有一个限制。它无法显示大型PDF文件。此线程包含有关此问题的答案:https://dev59.com/8Jvga4cB1Zd3GeqP0lgo - ganjaam

5

从这里下载源代码 (以编程方式在安卓中打开URL中的PDF)

MainActivity.java

package com.deepshikha.openpdf;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {
    WebView webview;
    ProgressBar progressbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webview = (WebView)findViewById(R.id.webview);
        progressbar = (ProgressBar) findViewById(R.id.progressbar);
        webview.getSettings().setJavaScriptEnabled(true);
        String filename ="http://www3.nd.edu/~cpoellab/teaching/cse40816/android_tutorial.pdf";
        webview.loadUrl("http://docs.google.com/gview?embedded=true&url=" + filename);

        webview.setWebViewClient(new WebViewClient() {

            public void onPageFinished(WebView view, String url){
                // do your stuff here
                progressbar.setVisibility(View.GONE);
            }
        });

    }
}

2

如果您使用Intent,您将一直被引导到浏览器,因此,请使用PDFView Android Widget在Android应用程序中查看Pdf。假设您已经拥有PDF Url您可以使用Intent将URL传递到此活动

步骤1:添加依赖项

implementation 'com.github.barteksc:android-pdf-viewer:3.1.0-beta.1'
implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'

同步 Gradle

步骤 2:创建布局[TextView 可选]

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout     xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ViewPdf">




    <com.github.barteksc.pdfviewer.PDFView
        android:id="@+id/ViewPdf"
        android:layout_height="match_parent"
        android:layout_width="match_parent"

        />

    <TextView
        android:id="@+id/txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="invisible"
        />
</RelativeLayout>

第三步:这是Activity.java文件的代码,请在代码中间将URL添加到pdfUrl变量中。

package com.example.firebase;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.media.Image;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.TextView;
import android.widget.Toast;

import com.github.barteksc.pdfviewer.PDFView;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class ViewPdf extends AppCompatActivity {

    private TextView txt; // You can remove if you don't want this
    private PDFView pdf;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pdf);
        pdf = findViewById(R.id.ViewPdf);
        txt = findViewById(R.id.txt);

        //Intent inten = getIntent();
        String pdfUrl = "Add PDF url"
        //Toast.makeText(this, pdfUrl, Toast.LENGTH_SHORT).show();


        try{
            new RetrievePdfStream().execute(pdfUrl);
        }
        catch (Exception e){
            Toast.makeText(this, "Failed to load Url :" + e.toString(), Toast.LENGTH_SHORT).show();
        }
    }


class RetrievePdfStream extends AsyncTask<String, Void, InputStream>{
    @Override
    protected InputStream doInBackground(String... strings) {
        InputStream inputStream = null;

        try {
            URL url = new URL(strings[0]);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            if (urlConnection.getResponseCode() == 200) {
                inputStream = new BufferedInputStream(urlConnection.getInputStream());

            }
        } catch (IOException e) {
            return null;

        }
        return inputStream;
    }
        @Override
        protected void onPostExecute(InputStream inputStream) {
            pdf.fromStream(inputStream).load();
        }
    }
}

步骤四: 不要忘记更改/提供上述代码中的PDF网址以使其正常工作。

谢谢@Be Champzz,你解决了我最大的问题。代码运行非常顺畅,只需要添加进度条来知道加载了多少%的PDF。 - abhilash kaveriappa

2

实际错误

android.content.ActivityNotFoundException: No Activity found to 
handle Intent 
{
 act=android.intent.action.VIEW 
 dat=http://oshc.zizsoft.com/oshc_testing.pdf typ=application/pdf 
}

这意味着:
  1. 你“广播”一个Intent,让系统尝试打开一个PDF文件
  2. 系统没有找到任何已注册的应用程序能够处理这种类型的文件(PDF)
你只需要一个PDF查看器即可。
解决方案:
获取一个PDF阅读器应用或使用@Mahendra的解决方案。

我已经安装了ezPDF阅读器,仍然返回相同的错误。 - user3538235

1
您可以跟随这个。
 Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setData(Uri.parse(URL_HERE));
            startActivity(intent);

1
你可以尝试这个。 它适用于.pdf.docx
 String pdfUrl = "abc.pdf"; //
 String url = "http://docs.google.com/gview?embedded=true&url=" + pdfUrl;

 WebView webView = findViewById(R.id.webview_cv_viewer);
 webView.getSettings().setSupportZoom(true);
 webView.getSettings().setJavaScriptEnabled(true);
 webView.loadUrl(url);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接