【问题标题】:Android: Send intent with playable video to telegram appAndroid:将带有可播放视频的意图发送到电报应用程序
【发布时间】:2021-07-04 04:50:53
【问题描述】:

我想通过 Intent 将视频发送到电报应用程序,但是当我发送它时,它作为文件发送(图像也是如此)。有什么技巧可以指定您要如何发送它吗? (因为从画廊它发送相同的视频可播放)

Intent 发送函数

private fun shareItem(fileName: String) {
    Log.i(TAG, "shareItem: ")
    val videoContentUri = FileProvider.getUriForFile(requireContext(),
        "${activity?.applicationContext?.packageName}.provider",
        File(LocalFilesRepository.getFullVideoPath(fileName, requireContext()))
    )
    Log.i("TAG", "shareItem: $videoContentUri")


    val shareIntent: Intent = Intent().apply {
        action = Intent.ACTION_SEND
        flags =  Intent.FLAG_GRANT_READ_URI_PERMISSION
        putExtra(Intent.EXTRA_STREAM, videoContentUri)
        type = "video/mp4"
    }
    startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to)))
}

...
fun getFullVideoPath(fileName: String, context: Context) =
            context.getExternalFilesDir(Environment.DIRECTORY_MOVIES).toString() + File.separatorChar + fileName

videoContentUri 看起来像这样的内容://com.dmytroa.appname.provider/external_files/emulated/0/Android/data/com.dmytroa.appname/files/Movies/1625360538459.mp4

【问题讨论】:

    标签: android android-intent


    【解决方案1】:

    如果有人感兴趣,我只需将文件临时保存在公共存储中,然后从 Mediastore 返回 Uri。

    fun createTemporaryCopyInPublicStorage(file: File, context: Context): Uri? {
                val fileName = "tmp"
                return if(Build.VERSION.SDK_INT >= 29) {
                    val uri = findCreatedTemporaryUri(context, fileName, TEMPORARY_DIR_Q)
                    copyVideoQAndAbove(context, file, uri, fileName, TEMPORARY_DIR_Q)
                } else {
                    val uri = findCreatedTemporaryUri(context, fileName, TEMPORARY_DIR_BELOWQ)
                    copyVideoBelowQ(context, file, uri, fileName, TEMPORARY_DIR_BELOWQ)
                }
            }
    
    
            private fun findCreatedTemporaryUri(context: Context, fileName: String, path: String): Uri? {
                val collection = if(Build.VERSION.SDK_INT >= 29) {
                    MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
                } else {
                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                }
    
                val selection = if (Build.VERSION.SDK_INT >= 29) {
                    "${MediaStore.Video.Media.TITLE} = ? " +
                            "AND " +
                            "${MediaStore.Video.Media.RELATIVE_PATH} = ? "
                } else {
                    "${MediaStore.Video.Media.TITLE} = ? " +
                            "AND " +
                            "${MediaStore.Video.Media.DATA} = ? "
                }
    
                val args = if (Build.VERSION.SDK_INT >= 29) {
                    arrayOf(fileName, path)
                } else {
                    arrayOf(fileName, File(path, fileName).absolutePath)
                }
    
                context.contentResolver.query(
                    collection,
                    arrayOf(MediaStore.Video.Media._ID
                    ),
                    selection,
                    args,
                    null
                ).use { cursor ->
                    return if (cursor != null && cursor.moveToFirst()) {
                        val columnIndexID = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
                        val id = cursor.getLong(columnIndexID)
    
                        Log.i(TAG, "findCreatedTemporaryUri: " +
                                "contentUri was already added $id $path $fileName")
                        Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "$id")
                    } else {
                        null
                    }
                }
            }
    
            @RequiresApi(Build.VERSION_CODES.Q)
            private fun copyVideoQAndAbove(context: Context,
                                           fileToCopy: File,
                                           uri: Uri?,
                                           fileName: String,
                                           relPath: String): Uri? {
    
                val contentDetails = ContentValues().apply {
                    put(MediaStore.Video.Media.IS_PENDING, 1)
                }
    
                val contentUri = if (uri != null) {
                    context.contentResolver.update(uri, contentDetails, null, null)
                    uri
                } else {
                    Log.i(TAG, "saveVideoQAndAbove: contentUri insert")
                    contentDetails.apply {
                        put(MediaStore.Video.Media.DISPLAY_NAME, fileName)
                        put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
                        put(MediaStore.Video.Media.RELATIVE_PATH, relPath)
                    }
                    val collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
                    context.contentResolver.insert(collection, contentDetails)
                }
    
                return contentUri?.let { createdUri ->
                    try {
                        context.contentResolver.openFileDescriptor(createdUri, "w").use { pfd ->
                            ParcelFileDescriptor.AutoCloseOutputStream(pfd).write(fileToCopy.readBytes())
                        }
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
    
                    contentDetails.clear()
                    contentDetails.put(MediaStore.Video.Media.IS_PENDING, 0)
                    context.contentResolver.update(createdUri, contentDetails, null, null)
                    createdUri
                }
            }
    
            private fun copyVideoBelowQ(context: Context,
                                        fileToCopy: File,
                                        uri: Uri?,
                                        fileName: String,
                                        dstParentPath: String): Uri? {
                val dstDir = File(dstParentPath)
                if (!dstDir.exists())
                    dstDir.mkdirs()
    
                val fileToCreate = File(dstDir, fileName)
    
                fileToCreate.delete()
                fileToCreate.createNewFile()
                Log.i(TAG, "saveVideo: created ${fileToCreate.name}")
                try {
                    fileToCopy.inputStream().use { input ->
                        fileToCreate.outputStream().use { output ->
                            input.copyTo(output, 2 * 1024)
                            Log.i(TAG, "saveVideo: finished ${fileToCreate.path}")
                        }
                    }
                    return uri ?: let {
                        val values = ContentValues().apply {
                            put(MediaStore.Video.Media.TITLE, fileToCreate.name)
                            put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
                            put(MediaStore.Video.Media.DATA, fileToCreate.path)
                        }
                        context.contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values)
                    }
                } catch (e: IOException) {
                    e.printStackTrace()
                }
    
                return null
            }
    
            private val TEMPORARY_DIR_Q = Environment.DIRECTORY_MOVIES + File.separator +
                    "APPNAME" + File.separator +
                    "temporary" + File.separator
    
            private val TEMPORARY_DIR_BELOWQ = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_MOVIES).absolutePath + File.separator +
                    "APPNAME" + File.separator +
                    "temporary" + File.separator
    

    【讨论】:

      猜你喜欢
      • 2021-04-19
      • 2015-05-03
      • 2010-10-09
      • 2010-12-07
      • 1970-01-01
      • 1970-01-01
      • 2017-01-11
      • 1970-01-01
      相关资源
      最近更新 更多