使用Android intent从服务器打开pdf文件

8

我正在搜索如何在Android上使用默认的PDF查看器从服务器打开PDF文件。我发现的方法是先下载文件,然后在意图中启动它或使用Google文档加载它。我不想这样做。我只想直接从手机上的默认PDF查看器中直接加载它。我尝试使用意图打开视频URL,并且它起作用了。但是使用意图打开PDF URL却不起作用。以下是我的代码;

private void openFilePDF(){
        try{
            Toast.makeText(getBaseContext(), "Opening PDF... ", Toast.LENGTH_SHORT).show();
            Intent inte = new Intent(Intent.ACTION_VIEW);
            inte.setDataAndType(
                    Uri.parse("http://122.248.233.68/pvfiles/Guide-2.pdf"),
                    "application/pdf");

            startActivity(inte);
            }catch(ActivityNotFoundException e){
                Log.e("Viewer not installed on your device.", e.getMessage());
            }
    }

有没有一种方法可以在意图中加载pdf url?

1
https://dev59.com/L3E85IYBdhLWcg3wNw14 - Raghunandan
1
我不想下载,只想从服务器加载它。 - ksh
请参考以下链接以下载文件:https://dev59.com/Q2Af5IYBdhLWcg3wXhoJ - Husain Ahamed
4个回答

17

首先创建一个下载器类

public class Downloader {

    public static void DownloadFile(String fileURL, File directory) {
        try {

            FileOutputStream f = new FileOutputStream(directory);
            URL u = new URL(fileURL);
            HttpURLConnection c = (HttpURLConnection) u.openConnection();
            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();

            InputStream in = c.getInputStream();

            byte[] buffer = new byte[1024];
            int len1 = 0;
            while ((len1 = in.read(buffer)) > 0) {
                f.write(buffer, 0, len1);
            }
            f.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

之后创建一个活动,从互联网下载PDF文件。

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        String extStorageDirectory = Environment.getExternalStorageDirectory()
        .toString();
        File folder = new File(extStorageDirectory, "pdf");
        folder.mkdir();
        File file = new File(folder, "Read.pdf");
        try {
            file.createNewFile();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        Downloader.DownloadFile("http://122.248.233.68/pvfiles/Guide-2.pdf", file);

        showPdf();
    }
    public void showPdf()
        {
            File file = new File(Environment.getExternalStorageDirectory()+"/Mypdf/Read.pdf");
            PackageManager packageManager = getPackageManager();
            Intent testIntent = new Intent(Intent.ACTION_VIEW);
            testIntent.setType("application/pdf");
            List list = packageManager.queryIntentActivities(testIntent, PackageManager.MATCH_DEFAULT_ONLY);
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_VIEW);
            Uri uri = Uri.fromFile(file);
            intent.setDataAndType(uri, "application/pdf");
            startActivity(intent);
        }
}

最后,在AndroidManifest.xml中声明权限。

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

感谢你的信息。我会尝试一下。 - ksh
@ksh 你的问题解决了吗?有没有任何答案对你有帮助? - GrIsHu
试一试,然后看看。@AnandPrakash - GrIsHu
1
如果没有PDF应用程序,它将无法工作。因为“Intent”找不到与PDF文件相关的任何应用程序。另一种方法是您也可以直接在浏览器中显示PDF。如果不想在浏览器中加载,则必须使用第三方API进行PDF查看器。 - GrIsHu
这个程序出现了错误:No Activity found to handle Intent { act=android.intent.action.VIEW dat=file:///mnt/sdcard/Mypdf/Read.pdf typ=application/pdf } - CIRCLE
显示剩余3条评论

8
您可以使用WebView尝试此操作:
public class MyPdfViewActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    WebView mWebView=new WebView(MyPdfViewActivity.this);
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.getSettings().setPluginsEnabled(true);
    mWebView.loadUrl("https://docs.google.com/gview?embedded=true&url="+LinkTo);
    setContentView(mWebView);
  }
}

我知道这已经很老了,但为了完整性,setPluginsEnabled()在API级别9中被弃用,并在API级别18中被移除。新版本setPluginState(WebSettings.PluginState.ON)在API级别8中添加,但在API级别18中被弃用。插件在API级别18之后不再受支持。 - Lee Richardson
@LeeRichardson 感谢您的评论,您能更新答案吗? - Shailendra Madda
这是非常重要的,将您可下载的PDF文件的URL与"https://docs.google.com/gview?embedded=true&url="绑定在一起。 - CrazyMind

0
根据我个人的观点,没有直接在设备上打开PDF文件的方法。由于Android设备浏览器的属性,当我们尝试打开PDF文件时,它会下载到设备上。只有两种方法可以打开PDF文件。
1. 您可以使用PDF应用程序意图来选择打开文件的应用程序。 2. 您可以将服务器URL与Google文档URL附加在一起,并在浏览器中打开它,这样您的PDF文件将在浏览器中打开。

谢谢您的回复。但是PDF应用程序意图只能打开本地文件,无法从服务器加载文件。 - ksh
是的,您需要将文件下载到设备上,然后才能使用意图打开该特定文件。 - Vaibhav Agarwal

0

从服务器下载PDF文件,下载完成后可以使用待处理意图打开此PDF文件。

在编写代码之前,请查看下面显示我的附加代码功能的图像。

enter image description here enter image description here enter image description here enter image description here

步骤 - 1:您需要创建一个异步任务来从服务器 URL 下载文件。请参见以下代码:

public class DownloadFileFromURL extends AsyncTask<String, Integer, String> {

private NotificationManager mNotifyManager;
private NotificationCompat.Builder build;
private File fileurl;
int id = 123;
OutputStream output;
private Context context;
private String selectedDate;
private String ts = "";

public DownloadFileFromURL(Context context, String selectedDate) {
    this.context = context;
    this.selectedDate = selectedDate;

}

protected void onPreExecute() {
    super.onPreExecute();

    mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    build = new NotificationCompat.Builder(context);
    build.setContentTitle("Download")
            .setContentText("Download in progress")
            .setChannelId(id + "")
            .setAutoCancel(false)
            .setDefaults(0)
            .setSmallIcon(R.drawable.ic_menu_download);

    // Since android Oreo notification channel is needed.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(id + "",
                "Social Media Downloader",
                NotificationManager.IMPORTANCE_HIGH);
        channel.setDescription("no sound");
        channel.setSound(null, null);
        channel.enableLights(false);
        channel.setLightColor(Color.BLUE);
        channel.enableVibration(false);
        mNotifyManager.createNotificationChannel(channel);

    }
    build.setProgress(100, 0, false);
    mNotifyManager.notify(id, build.build());
    String msg = "Download started";
    //CustomToast.showToast(context,msg);
}

@Override
protected String doInBackground(String... f_url) {
    int count;
    ts = selectedDate.split("T")[0];
    try {
        URL url = new URL(f_url[0]);
        URLConnection conection = url.openConnection();
        conection.connect();
        int lenghtOfFile = conection.getContentLength();

        InputStream input = new BufferedInputStream(url.openStream(),
                8192);
        // Output stream
        output = new FileOutputStream(Environment
                .getExternalStorageDirectory().toString()
                + Const.DownloadPath + ts + ".pdf");
        fileurl = new File(Environment.getExternalStorageDirectory()
                + Const.DownloadPath + ts + ".pdf");
        byte[] data = new byte[1024];

        long total = 0;

        while ((count = input.read(data)) != -1) {
            total += count;
            int cur = (int) ((total * 100) / lenghtOfFile);

            publishProgress(Math.min(cur, 100));
            if (Math.min(cur, 100) > 98) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    Log.d("Failure", "sleeping failure");
                }
            }
            Log.i("currentProgress", "currentProgress: " + Math.min(cur, 100) + "\n " + cur);

            output.write(data, 0, count);
        }

        output.flush();

        output.close();
        input.close();

    } catch (Exception e) {
        Log.e("Error: ", e.getMessage());
    }

    return null;
}

protected void onProgressUpdate(Integer... progress) {
    build.setProgress(100, progress[0], false);
    mNotifyManager.notify(id, build.build());
    super.onProgressUpdate(progress);
}

@Override
protected void onPostExecute(String file_url) {
    build.setContentText("Download complete");
    Intent intent = new Intent(context, DownloadBroadcastReceiver.class);
    Uri finalurl = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", fileurl);
    intent.putExtra("currenturl", finalurl.toString());
    intent.putExtra("selectedfilename", ts);
    context.sendBroadcast(intent);
    build.setProgress(0, 0, false);
    mNotifyManager.notify(id, build.build());
} }

在上面的代码中,我使用 DownloadFileFromURL.java 类文件创建了异步任务。在这个类文件中编写了一段代码,在 Android O 和旧版本中显示通知。

步骤2:下载完成后,我将其发送到广播接收器。借助广播接收器,您可以轻松地在待定意图中打开 PDF 文件。您可以在异步任务的 onPostExecute 方法中查看广播接收器代码。

请参见下面的代码以处理广播接收器中的待定意图。

public class DownloadBroadcastReceiver extends BroadcastReceiver {
private NotificationManager mNotifyManager;
private NotificationCompat.Builder build;
private int rId=123;
private String localuri="";
private String selectedfilename="";

@Override
public void onReceive(Context context, Intent intent) {
    localuri=intent.getStringExtra("currenturl");
    selectedfilename=intent.getStringExtra("selectedfilename");
    startNotification(context,intent);
}

private void startNotification(Context context, Intent intent) {
    Log.e("fat", "startNotification: "+localuri );

    File fileurl = new File(Environment.getExternalStorageDirectory()
            + Const.DownloadPath + selectedfilename+".pdf");
    Uri finalurl = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID+".provider", fileurl);
    Intent downloadintent = new Intent(Intent.ACTION_VIEW);
    downloadintent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    downloadintent.setDataAndType(finalurl, "application/pdf");
    grantAllUriPermissions(context, downloadintent, finalurl);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, downloadintent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    build = new NotificationCompat.Builder(context);
    build.setContentTitle("Download Completed")
            .setContentText("Open Downloaded FIle")
            .setChannelId(rId+"")
            .setAutoCancel(true)
            .setContentIntent(pendingIntent)
            .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
            .setSmallIcon(R.drawable.ic_menu_download);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(rId+"" ,
                "Call Reminder",
                NotificationManager.IMPORTANCE_HIGH);
        channel.setDescription("With sound");
        channel.setSound(null,null);
        channel.enableLights(false);
        channel.setLightColor(Color.BLUE);
        channel.enableVibration(true);
        mNotifyManager.createNotificationChannel(channel);

    }


    mNotifyManager.notify(rId, build.build());

}

private void grantAllUriPermissions(Context context, Intent downloadintent, Uri finalurl) {
    List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(downloadintent, PackageManager.MATCH_DEFAULT_ONLY);
    for (ResolveInfo resolveInfo : resInfoList) {
        String packageName = resolveInfo.activityInfo.packageName;
        context.grantUriPermission(packageName, finalurl, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
} }

在上面的代码中,您可以看到我在通知紧凑建造者中添加了挂起意图。
注意:当您添加待定意图时,您必须使用以下代码分配访问权限,我已经添加了。
 downloadintent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP);
 grantAllUriPermissions(context, downloadintent, finalurl);

这里创建了GrantAllpermission方法,支持所有设备。

 private void grantAllUriPermissions(Context context, Intent downloadintent, Uri finalurl) {
    List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(downloadintent, PackageManager.MATCH_DEFAULT_ONLY);
    for (ResolveInfo resolveInfo : resInfoList) {
        String packageName = resolveInfo.activityInfo.packageName;
        context.grantUriPermission(packageName, finalurl, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
}

步骤 -3 : 使用以下代码将您的广播接收器添加到Android清单文件中。

 <receiver android:name=".services.DownloadBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

步骤 - 4:在Android清单文件中添加文件提供程序。通过文件提供程序,您可以打开设备存储中的文件。

  <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_provider_path" />
    </provider>

注意:如果您遇到在Android 10(O)设备上的问题,则需要将以下代码添加到您的Android清单文件中的应用程序中。

android:requestLegacyExternalStorage="true"

通过使用requestLegacyExternalStorage,您可以轻松获取已下载文件的列表。

步骤-5:现在最后一步是在单击事件中调用异步类文件。这里我编写了PDF图像单击代码。要调用异步任务,请使用以下代码。

 new DownloadFileFromURL(fContext,selectedDate).execute(currentResponse.getData());

您可以从以下链接下载完整的代码文件:

DownloadFileFromURL.java类文件

DownloadBroadcastReceiver.java类文件


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