ACTION_VIEW intent for a file with unknown MimeType
Asked Answered
T

13

69

My app has a feature that browse files on your phone and SD card and open them using other apps. I want a solution where I don't have to specify the MimeType and can work with any type of file.

Here is my code:

Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setData(Uri.fromFile(item));
startActivity(myIntent);

However, I'm getting the following error:

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.PICK dat=file:///sdcard/dropbox/test.pdf }
Trumpetweed answered 7/6, 2011 at 12:42 Comment(0)
M
125

This should detect the mimetype and open with default:

MimeTypeMap myMime = MimeTypeMap.getSingleton();
Intent newIntent = new Intent(Intent.ACTION_VIEW);
String mimeType = myMime.getMimeTypeFromExtension(fileExt(getFile()).substring(1));
newIntent.setDataAndType(Uri.fromFile(getFile()),mimeType);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
    context.startActivity(newIntent);
} catch (ActivityNotFoundException e) {
    Toast.makeText(context, "No handler for this type of file.", Toast.LENGTH_LONG).show();
}

Using this function:

private String fileExt(String url) {
    if (url.indexOf("?") > -1) {
        url = url.substring(0, url.indexOf("?"));
    }
    if (url.lastIndexOf(".") == -1) {
        return null;
    } else {
        String ext = url.substring(url.lastIndexOf(".") + 1);
        if (ext.indexOf("%") > -1) {
            ext = ext.substring(0, ext.indexOf("%"));
        }
        if (ext.indexOf("/") > -1) {
            ext = ext.substring(0, ext.indexOf("/"));
        }
        return ext.toLowerCase();

    }
}
Menstruum answered 17/6, 2011 at 4:53 Comment(3)
How about URLConnection.guessContentTypeFromName(url)?Novelette
There is a problem with this code: in third line of code you shouldn't use substring(1). use this line: String mimeType = myMime.getMimeTypeFromExtension(fileExt(getFile()));. (fileExt will only return the extension without dot.)Melodimelodia
User FileProvider instead of URI.fromFile() on target >= 24 androidsHocker
B
18

createChooser should do the trick:

Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setData(Uri.fromFile(item));
Intent j = Intent.createChooser(myIntent, "Choose an application to open with:");
startActivity(j);
Bootery answered 7/6, 2011 at 13:17 Comment(0)
F
16

try this one almost covers all file extensions

  public void openFile(File url) {

    Uri uri = Uri.fromFile(url);

    Intent intent = new Intent(Intent.ACTION_VIEW);
    if (url.toString().contains(".doc") || url.toString().contains(".docx")) {
        // Word document
        intent.setDataAndType(uri, "application/msword");
    } else if (url.toString().contains(".pdf")) {
        // PDF file
        intent.setDataAndType(uri, "application/pdf");
    } else if (url.toString().contains(".ppt") || url.toString().contains(".pptx")) {
        // Powerpoint file
        intent.setDataAndType(uri, "application/vnd.ms-powerpoint");
    } else if (url.toString().contains(".xls") || url.toString().contains(".xlsx")) {
        // Excel file
        intent.setDataAndType(uri, "application/vnd.ms-excel");
    } else if (url.toString().contains(".zip") || url.toString().contains(".rar")) {
        // WAV audio file
        intent.setDataAndType(uri, "application/x-wav");
    } else if (url.toString().contains(".rtf")) {
        // RTF file
        intent.setDataAndType(uri, "application/rtf");
    } else if (url.toString().contains(".wav") || url.toString().contains(".mp3")) {
        // WAV audio file
        intent.setDataAndType(uri, "audio/x-wav");
    } else if (url.toString().contains(".gif")) {
        // GIF file
        intent.setDataAndType(uri, "image/gif");
    } else if (url.toString().contains(".jpg") || url.toString().contains(".jpeg") || url.toString().contains(".png")) {
        // JPG file
        intent.setDataAndType(uri, "image/jpeg");
    } else if (url.toString().contains(".txt")) {
        // Text file
        intent.setDataAndType(uri, "text/plain");
    } else if (url.toString().contains(".3gp") || url.toString().contains(".mpg") || url.toString().contains(".mpeg") || url.toString().contains(".mpe") || url.toString().contains(".mp4") || url.toString().contains(".avi")) {
        // Video files
        intent.setDataAndType(uri, "video/*");
    } else {
        //if you want you can also define the intent type for any other file
        //additionally use else clause below, to manage other unknown extensions
        //in this case, Android will show all applications installed on the device
        //so you can choose which application to use
        intent.setDataAndType(uri, "*/*");
    }

    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent);

}
Fino answered 29/7, 2016 at 4:23 Comment(7)
Cool! Nice job!Handfast
But How about endsWith instead of contains method?Handfast
@V.Kalyuzhnyu of course whatever works for you is fineFino
what will happen if extension is in capital letter, e.g. sample.DOCX?Lava
i used url.toString().contains(".zip") || url.toString().contains(".rar") and application/x-wav but i am gettting error android.content.ActivityNotFoundException: No Activity found to handle Intent any solutionLobation
if you are getting ActivityNotFoundException for (.zip) (.rar) then use : application/zipPlast
help me to open CSV file pleaseMarivelmariya
S
8
Intent myIntent = new Intent(Intent.ACTION_VIEW);
String mime=URLConnection.guessContentTypeFromStream(new FileInputStream(item));
if(mime==null) mime=URLConnection.guessContentTypeFromName(item.getName());
myIntent.setDataAndType(Uri.fromFile(item), mime);
startActivity(myIntent);

At first I try to guess with the file content, but as i see it always returns null.

Sheets answered 3/9, 2013 at 14:39 Comment(2)
Doesn't work when targeting Android NStump
Thomas Vos's point is crucial. This code is useful but if you're going to use it then you need to set your targetSdkVersion to 23 or under. If an Android 7.0 device runs this code it will crash.Cowell
T
5

Android does not start activities based on file extensions, unless there's an app that specifies a particular intent filter for it. You will need the mime type to the Intent to tell android enough information to start the right Activity.

You have the option to automate this task by using the MimeTypeMap class. Check the method String getMimeTypeFromExtension(String extension).

BTW, do you have a pdf reader installed in your device?

You should also handle this exception, probably by showing a nice popup saying that there is no app for that particular type of file.

Thorr answered 7/6, 2011 at 13:10 Comment(0)
S
5

You can find out the mime type of a file and make your own intent to open the file.

Use the following code to open any file...

File temp_file=new File("YOUR FILE PATH");
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(temp_file),getMimeType(temp_file.getAbsolutePath()));
startActivity(intent); 

Where getMimeType() is....(this method will return desired mime type or null if the file does not have any proper mime type)...

private String getMimeType(String url)
    {
        String parts[]=url.split("\\.");
        String extension=parts[parts.length-1];
        String type = null;
        if (extension != null) {
            MimeTypeMap mime = MimeTypeMap.getSingleton();
            type = mime.getMimeTypeFromExtension(extension);
        }
        return type;
    }
Salver answered 13/5, 2013 at 12:20 Comment(0)
P
2

Simple share file ("multipart/")

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
intent.setType("multipart/");
startActivity(intent);
Pyrene answered 13/3, 2014 at 0:57 Comment(1)
FileUriExposedExceptionFalito
S
2

This will work surely..

 private void showFile(File file, String filetype) 
{
                MimeTypeMap myMime = MimeTypeMap.getSingleton();
                Intent intent = new Intent(Intent.ACTION_VIEW);
                String mimeType = 
                myMime.getMimeTypeFromExtension(filetype);
                if(android.os.Build.VERSION.SDK_INT >=24) {
                 Uri fileURI = FileProvider.getUriForFile(getContext(),
                            BuildConfig.APPLICATION_ID + ".provider",
                            file);
                    intent.setDataAndType(fileURI, mimeType);

                }else {
                    intent.setDataAndType(Uri.fromFile(file), mimeType);
                }
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_GRANT_READ_URI_PERMISSION);
                try {
                    context.startActivity(intent);
                }catch (ActivityNotFoundException e){
                    Toast.makeText(context, "No Application found to open this type of file.", Toast.LENGTH_LONG).show();

                }
            }
Slew answered 29/3, 2018 at 11:49 Comment(0)
V
1

I wrote these few lines in kotlin and and it works like a charm.Enjoy it.

val file = File(path)              
val mimeType = URLConnection.guessContentTypeFromName(file.absolutePath)
                Intent().apply {
                    setDataAndType(Uri.fromFile(file), mimeType)
                    flags = Intent.FLAG_ACTIVITY_NEW_TASK
                }.let {
                    try {
                        itemView.context.startActivity(it)
                    } catch (e: ActivityNotFoundException) {
                        Toast.makeText(itemView.context, "There's no program to open this file", Toast.LENGTH_LONG).show()
                    }
                }
Vassily answered 8/6, 2019 at 14:42 Comment(3)
I think you forgot to add action to the intentNorth
@North feel free to edit, it's been years I don't even work with Kotlin or Java anymore.Vassily
Thanks, I just added it so that whoever is referring to this answer can add that piece of code too.North
S
0

There is a problem with NoBugs's answer. This is directly out of the eclipse function information window:

String android.webkit.MimeTypeMap.getMimeTypeFromExtension(String extension)

public String getMimeTypeFromExtension (String extension)

Since: API Level 1

Return the MIME type for the given extension.

Parameters

extension A file extension without the leading '.'

Returns The MIME type for the given extension or null iff there is none.

Striper answered 23/10, 2012 at 12:17 Comment(6)
Can you give an example? What should be done if it's null type?Menstruum
I was looking for a solution for it returning null, still have not found one.Striper
Can you give an example of a filetype that returns null?Menstruum
I had a custom one. I don't even remember what it was. I long abandoned that project.Striper
Oh, ok. In the case of a custom file extension I guess you'd check before, and open your activity directly, if you can't make an intent-filter work.Menstruum
Huh. I was unaware of that abbreviation. You learn something new everyday, so thanks for contributing to my day ;-)Striper
E
0

Use this method to get the MIME type from the uri of the file :

public static String getMimeType(String url) {

    String type = null;
    String extension = url.substring(url.lastIndexOf(".") + 1);
    if (extension != null) {
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return type;
}
Eructate answered 19/2, 2016 at 22:54 Comment(0)
A
0

You should always check the same with

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

}

and to get MimeTpye of file you can use :-

 public String getMimeType(Uri uri, Context context) {
        String mimeType = null;
        if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
            ContentResolver cr = context.getContentResolver();
            mimeType = cr.getType(uri);
        } else {
            String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
                    .toString());
            mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                    fileExtension.toLowerCase());
        }
        return mimeType;
    }
Aldwon answered 16/1, 2018 at 10:42 Comment(0)
S
0

You have to use the MimeTypeMap and get the type using the file extension. Then pass it to intent to open any type of file.

Kotlin

fun getIntentForFile(filePath: String, context: Context): Intent {
    val intent = Intent()

    val uri = FileProvider.getUriForFile(
        context,
        context.applicationContext.packageName + ".fileprovider",
        File(filePath)
    )
    intent.action = Intent.ACTION_VIEW
    intent.putExtra(Intent.EXTRA_STREAM, uri)
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    intent.setDataAndType(uri, getFileContentType(filePath))
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    return intent
}

fun getFileContentType(filePath: String): String? {
    val file = File(filePath)
    val map = MimeTypeMap.getSingleton()
    val ext = MimeTypeMap.getFileExtensionFromUrl(file.name)
    var type = map.getMimeTypeFromExtension(ext)
    if (type == null) type = "*/*"
    return type
}
Skelton answered 27/5, 2020 at 14:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.