0

When downloading finished, either an app chooser open that show some app according to file extension of the downloaded file or it opens an app that is selected as default for that file extension when a user clicks on open in snackbar.

I try to achieve something like this:

For pdf files, it shows something like this For pdf files, it shows something like this

For images, it shows something like this For images, it shows something like this

My Code

webView.setDownloadListener(new DownloadListener() {
        public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
            int last_index = url.lastIndexOf("/");
            subPath[0] = url.substring(last_index, url.length());       //downloads file name

            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
            request.allowScanningByMediaScanner();
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, subPath[0]);
            DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            if (dm != null) {
                dm.enqueue(request);
            }
            showSnackBar(MainTab.this,"Downloading file", false);
        }
    });
    BroadcastReceiver onComplete=new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            showSnackBar(MainTab.this,"Downloading finished", true);
        }
    };
    registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

public void showSnackBar(Activity activity, String message, boolean bool){
        View rootView = activity.getWindow().getDecorView().findViewById(android.R.id.content);
        Snackbar snackbar = Snackbar.make(rootView, message, Snackbar.LENGTH_LONG);
        if(bool){
            snackbar.setAction(R.string.open, new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(getApplicationContext(), "Downloaded File open", Toast.LENGTH_LONG).show();
                    Intent baseIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(subPath[0]));
                    Intent chooserIntent = Intent.createChooser(baseIntent, "Open with");
                    if (baseIntent.resolveActivity(getPackageManager()) != null) {
                        startActivity(chooserIntent);
                    }

                }
            });
        }
        snackbar.show();
    }

Manifest file:

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

<application
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:configChanges="keyboardHidden|orientation|screenSize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:mimeType="text/html"/>
            <data android:mimeType="text/pdf"/>
            <data android:mimeType="audio/*"/>
            <data android:mimeType="video/*"/>
            <data android:mimeType="image/*"/>
            <data android:scheme="http" />
            <data android:scheme="https" />
        </intent-filter>
    </activity>
</application>

Please help me to sort it out. Thanks, in advance.

Edit:

Modified code according to @Reaz Murshed

            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "Downloaded File open", Toast.LENGTH_LONG).show();

                String extension = MimeTypeMap.getFileExtensionFromUrl(new File(subPath[0]).getPath());
                String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                intent.setDataAndType(Uri.fromFile(new File(subPath[0])), type);
                getApplicationContext().startActivity( intent );

            }

logcat:

02-10 16:47:38.966 16467-16467/? I/art: Not late-enabling -Xcheck:jni (already on)
02-10 16:47:39.023 16467-16473/? I/art: Debugger is no longer active
02-10 16:47:39.034 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_dependencies_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_dependencies_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.208 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_0_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_0_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.240 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_1_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_1_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.260 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_2_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_2_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.279 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_3_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_3_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.300 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_4_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_4_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.338 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_5_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_5_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.362 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_6_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_6_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.392 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_7_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_7_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.413 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_8_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_8_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.432 16467-16467/? W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/app/biz.coolpage.aashish.browser-1/split_lib_slice_9_apk.apk --oat-file=/data/dalvik-cache/x86/data@app@biz.coolpage.aashish.browser-1@split_lib_slice_9_apk.apk@classes.dex) because non-0 exit status
02-10 16:47:39.434 16467-16467/? W/System: ClassLoader referenced unknown path: /data/app/biz.coolpage.aashish.browser-1/lib/x86
02-10 16:47:39.439 16467-16467/? I/InstantRun: starting instant run server: is main process
02-10 16:47:39.524 16467-16467/? W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
02-10 16:47:39.700 16467-16505/? D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true

                                                   [ 02-10 16:47:39.702 16467:16467 D/         ]
                                                   HostConnection::get() New Host Connection established 0xaa95e200, tid 16467


                                                   [ 02-10 16:47:39.734 16467:16505 D/         ]
                                                   HostConnection::get() New Host Connection established 0xaa95e800, tid 16505
02-10 16:47:39.737 16467-16505/? I/OpenGLRenderer: Initialized EGL, version 1.4
02-10 16:47:39.737 16467-16505/? W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
02-10 16:47:39.747 16467-16505/? D/EGL_emulation: eglCreateContext: 0xaa960360: maj 3 min 1 rcv 4
02-10 16:47:39.753 16467-16505/? D/EGL_emulation: eglMakeCurrent: 0xaa960360: ver 3 1 (tinfo 0xaa94ee60)
Aashish Kumar
  • 2,771
  • 3
  • 28
  • 43
  • 1
    Why are you specifying `intent-filter` in your Manifest? Do you want your app to be listed in the **Open With** list? – anemo Feb 11 '18 at 17:35
  • 1
    If you want to use external apps for opening files, you should not specify `intent-filter`. Check the docs here : https://developer.android.com/guide/topics/manifest/intent-filter-element.html – anemo Feb 11 '18 at 17:39
  • 1
    Actually, I required both features. i.e, my app to be listed in the Open With list and also want to use external apps for opening files. But I am currently focus on the problem with opening files in external apps. – Aashish Kumar Feb 11 '18 at 17:45

3 Answers3

1

Before you call startActivity(Intent) you should check if the Intent can be handled.

PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
    Log.d(TAG, "No Intent available to handle action");
}
0

As far as I have understood, you have no problem in detecting when the file is downloaded completely and you get the name of the File immediately. Now based on above assumption, as long as you get the fully specified file name in your hand, you can easily pick the applications which are recommended to open these types of files.

Get the file type from the file extension of the downloaded file. I have a sample code to demonstrate the idea of filtering the application chooser.

String extension = MimeTypeMap.getFileExtensionFromUrl(yourDownloadedFile.getPath());
String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(yourDownloadedFile), type);    
context.startActivity( intent );

Please let me know if I have misunderstood in some part.

Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
  • I try this solution but now the app crashes when clicking on open. – Aashish Kumar Feb 10 '18 at 07:40
  • Can you please share logcat? – Reaz Murshed Feb 10 '18 at 07:55
  • at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 02-10 15:07:29.011 15104-15146/biz.coolpage.aashish.browser E/eglCodecCommon: glUtilsParamSize: unknow param 0x000085b5 – Aashish Kumar Feb 10 '18 at 09:42
  • This is hard to see the logcat error here. Can you please update your question along with the full logcat? – Reaz Murshed Feb 10 '18 at 10:34
  • I think the error is nothing related to this code-segment. Anyway, let me check the error in details. I will notify you back if I can come up with the reason. – Reaz Murshed Feb 10 '18 at 12:13
  • Please check the answer here as well if you are running the application in emulator. https://stackoverflow.com/a/27882308/3145960 – Reaz Murshed Feb 10 '18 at 12:15
  • As you say this problem may arise because I run the app in the emulator. So, I run it on an actual android phone but the problem persists (i.e, app crashed). – Aashish Kumar Feb 10 '18 at 13:31
  • What's the error shown in Logcat when the application crashed. The logcat you shared before is not the one when application crashed I think. – Reaz Murshed Feb 10 '18 at 14:02
  • No, logcat I share is the same one when the app crashed. but in the emulator. will you want to see logcat when the app crashed in an actual android phone?? – Aashish Kumar Feb 10 '18 at 14:07
  • Please share the logcat. – Reaz Murshed Feb 10 '18 at 14:22
  • I also posted the logcat of an actual android phone. – Aashish Kumar Feb 10 '18 at 15:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/164893/discussion-between-reaz-murshed-and-aashish). – Reaz Murshed Feb 10 '18 at 16:56
0

I try this and it works.

public void onClick(View v) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(subPath[0]);
    String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);

    Intent baseIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(subPath[0]));
    baseIntent.setType(type);

    if (baseIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(baseIntent);
    }
    else {
        Toast.makeText(getApplicationContext(), "File unable to open", Toast.LENGTH_LONG).show();
    }
}
Aashish Kumar
  • 2,771
  • 3
  • 28
  • 43