ActivityNotFoundException is not triggered to open

2019-09-03 19:37发布

I want to download a PDF from a url and also want to trigger catch phrase if no PDF Viewer is detected.

Here's my code:

    try {
        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(materialPdfUrl)));
    } catch (ActivityNotFoundException e) {
        openDialog(getString(R.string.error),
                getString(R.string.no_pdf_reader));
    }

Now the problem is that ActivityNotFoundException is never triggered because it always download the PDF even if there is no PDF Viewer around. How do you suggest I do this?

EDIT: Here's my old code:

Intent pdfIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(materialPdfUrl));
pdfIntent.setType("application/pdf");
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(pdfIntent);

6条回答
forever°为你锁心
2楼-- · 2019-09-03 20:09
    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(materialPdfUrl)));

is starting an Implicit Intent and therefore will not throw ActivityNotFoundException.

If you read this http://developer.android.com/guide/components/intents-filters.html#ccases

Consider, for example, what the browser application does when the user follows a link on a web page. It first tries to display the data (as it could if the link was to an HTML page). If it can't display the data, it puts together an implicit intent with the scheme and data type and tries to start an activity that can do the job. If there are no takers, it asks the download manager to download the data. That puts it under the control of a content provider, so a potentially larger pool of activities (those with filters that just name a data type) can respond.

Therefore if no PDF viewers are found the Android Download Manager will attempt to download the file (rather than throw that exception).

If you want to view the pdf or be told you cannot view it (rather than download) then you will need to query the system manually using the PackageManager to find out if an application will respond to your intent rather than just firing and forgetting.


FYI ActivityNotFoundException will be thrown for Explicit Intent's something like:

Intent intent = new Intent();
intent.setComponent(new ComponentName("com.facebook","NewsFeedActivity.java"));
startActivity(intent);```
查看更多
走好不送
3楼-- · 2019-09-03 20:09

use startActivityForResult(..).

See the link here.

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
startActivityForResult(intent, REQUEST_CODE);

You will get the result in onActivityResult(..) of your activity.

查看更多
时光不老,我们不散
4楼-- · 2019-09-03 20:11

you may try this code. This may helpful to you.

Intent intent = new Intent();


                            intent.setClassName("com.adobe.reader", "com.adobe.reader.AdobeReader");

                            intent.setAction(android.content.Intent.ACTION_VIEW);
                            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                             Uri uri = Uri.fromFile(file);
                             intent.setDataAndType(uri, "application/pdf");

                                try {

                                    startActivity(intent);
                                } catch (Exception e) {

                                    AlertDialog.Builder builder = new AlertDialog.Builder(
                                            getApplicationContext());
                                    builder.setTitle("No Application Found");
                                    builder.setMessage("Download application from Android Market?");
                                    builder.setPositiveButton(
                                            "Yes, Please",
                                            new DialogInterface.OnClickListener() {
                                                @Override
                                                public void onClick(
                                                        DialogInterface dialog,
                                                        int which) {
                                                    Intent marketIntent = new Intent(
                                                            Intent.ACTION_VIEW);
                                                    marketIntent.setData(Uri
                                                            .parse("market://details?id=com.adobe.reader"));
                                                    mProgressDialog.dismiss();

                                                    startActivity(marketIntent);
                                                }
                                            });
                                    builder.setNegativeButton("No, Thanks",
                                            null);
                                    builder.create().show();
                                }
查看更多
Deceive 欺骗
5楼-- · 2019-09-03 20:20

That is because your device or emulator does not have an application capable of viewing a local PDF file.

Whenever you start an intent, you should have the native app installed on the emulator to handle that intent. Ex. If you invoke an intent with Maps as the action, you would have to use the Google API's based emulator. By default, android emulator does not have a PDF reader. You could test this on a device with a PDF reader and it should work fine.

查看更多
劳资没心,怎么记你
6楼-- · 2019-09-03 20:31

The function startActivity() you use is not on the condition that the PDF reader is not exist, it only download the PDF from the URL, and if there are PDF Readers then it will offer a selector, just as the function of clicking on a PDF file.

查看更多
我命由我不由天
7楼-- · 2019-09-03 20:33

I would recommend using the PackageManager to detect if the system will handle a PDF intent for you.

PackageManager packageManager = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_VIEW)
    .setType("application/pdf");
List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY;
if (list.size() > 0) {
    // Happy days a PDF reader exists
    startActivity(intent);
} else {
    // No PDF reader, ask the user to download one first 
    // or just open it in their browser like this
    intent = new Intent(Intent.ACTION_VIEW)
        .setData(Uri.parse("http://docs.google.com/gview?embedded=true&url=" + pdfUrl);
    startActivity(intent);
}

See this blog post for more info on checking intents. The added benefit of this approach is that you can grey out/remove menu options before the app even tries to execute the Intent. Then you can explain to the user in a slightly more friendly way that they need to grab a PDF viewer app, or indeed apply some logic to fallback to a web based PDF viewer.

Having trialled this approach with Foxit Reader and Adobe Reader they both seem to have different behaviours. Foxit will not download the PDF for you, it will redirect you to the browser and download the file. Adobe will download the file for you then display it.

So to get round this difference once you have detected that a PDF viewer is available then you will probably want to download the PDF to the SD card, for example the downloads folder. This is probably best achieved in an AsyncTask, or you might be able to use the DownloadManager. Then open the local file Uri in the preferred reader. This should get round the difference in behaviour. Maybe open a ticket with Foxit to bring it into line with Adobe? ;)

查看更多
登录 后发表回答