Search code examples
androidimageandroid-intentmime-typesandroid-intent-chooser

Pixel3 ACTION_VIEW won't start for other files than images


This is my code for trying to open a file I create from a base64 string:

var decodedBytes = Base64.decode(filtered.first().contentsB64String, Base64.NO_WRAP)
var ext = FilenameUtils.getExtension(commonName)
fileTemporary = File(Environment.getExternalStorageDirectory().toString() + "/xelion/xelion_temp." + ext)
if (fileTemporary != null) {
    if (!fileTemporary!!.exists()) {
        fileTemporary?.createNewFile()
    }
    FileUtils.writeByteArrayToFile(fileTemporary, decodedBytes)
    var intent = Intent(Intent.ACTION_VIEW)
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    var uri = Uri.fromFile(fileTemporary)
    if (Build.VERSION.SDK_INT >= 24) {
        uri = Uri.parse(fileTemporary!!.getPath())
    }
    intent.setDataAndType(uri, filtered.first().mimeType)
    activity!!.startActivity(intent)
}

I have also tried with this , but I still get the same error:

    fun openFile(url: Uri) {
        var intent = Intent(Intent.ACTION_VIEW)
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        if (url.toString().contains(".doc") || url.toString().contains(".docx")) {
            // Word document
            intent.setDataAndType(url, "application/msword")
        } else if (url.toString().contains(".pdf")) {
            // PDF file
            intent.setDataAndType(url, "application/pdf")
        } else if (url.toString().contains(".ppt") || url.toString().contains(".pptx")) {
            // Powerpoint file
            intent.setDataAndType(url, "application/vnd.ms-powerpoint")
        } else if (url.toString().contains(".xls") || url.toString().contains(".xlsx")) {
            // Excel file
            intent.setDataAndType(url, "application/vnd.ms-excel")
        } else if (url.toString().contains(".zip") || url.toString().contains(".rar")) {
            // WAV audio file
            intent.setDataAndType(url, "application/x-wav")
        } else if (url.toString().contains(".rtf")) {
            // RTF file
            intent.setDataAndType(url, "application/rtf")
        } else if (url.toString().contains(".wav") || url.toString().contains(".mp3")) {
            // WAV audio file
            intent.setDataAndType(url, "audio/x-wav")
        } else if (url.toString().contains(".gif")) {
            // GIF file
            intent.setDataAndType(url, "image/gif")
        } else if (url.toString().contains(".jpg") || url.toString().contains(".jpeg") || url.toString().contains(".png")) {
            // JPG file
            intent.setDataAndType(url, "image/jpeg")
        } else if (url.toString().contains(".txt")) {
            // Text file
            intent.setDataAndType(url, "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(url, "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(url, "*/*")
        }

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        activity!!.startActivity(intent)

    }

Error:

No Activity found to handle Intent { act=android.intent.action.VIEW dat=/storage/emulated/0/xelion/xelion_temp.txt typ=text/plain flg=0x10000001 }

Solution

  • First, /storage/emulated/0/xelion/xelion_temp.txt is not a valid Uri. Use FileProvider to make your content available to other apps.

    Second, Environment.getExternalStorageDirectory() is inaccessible to you on Android 10 (by default) and Android R+ (for all apps). When you switch to using FileProvider, you will be able to switch to storing this data in getCacheDir() or similar locations supplied by Context.

    Also, your second code snippet has bugs:

    • It will think that this.is.not.a.ppt.txt is a PowerPoint presentation
    • It uses wildcard MIME types, which are not meant for use by suppliers of content

    And, bear in mind that there is no requirement for every Android device to have apps that support every possible content type.