You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从服务器视频URL直接分享至第三方应用(无需下载视频)?Android代码求助

解决Android分享网络视频URL到第三方应用的问题

问题根源

你直接用Uri.parse(videoUrl)把网络URL传给EXTRA_STREAM的方式行不通,因为WhatsApp、Gmail这类第三方分享应用不支持直接读取远程网络URI——它们没有权限直接访问网络资源,也没法处理流式的远程视频内容。

可行解决方案:缓存视频到本地并通过FileProvider分享

既然没法直接分享网络URI,我们可以先把视频临时下载到应用的缓存目录,再通过FileProvider生成合法的content:// URI来分享,这样既满足应用的访问权限要求,也不会占用用户过多本地存储(缓存文件会在应用清理缓存时自动删除)。

步骤1:配置FileProvider

首先在AndroidManifest.xml中注册FileProvider:

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

然后在res/xml目录下创建file_paths.xml文件,指定缓存目录的访问路径:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 允许访问应用缓存下的videos子目录 -->
    <cache-path name="shared_videos" path="videos/" />
</paths>

步骤2:添加必要权限

在AndroidManifest.xml中添加网络权限(用于下载视频):

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

步骤3:编写下载并分享的代码

使用Kotlin协程处理异步下载(避免阻塞主线程),完成后切换到主线程发起分享:

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL

class ShareVideoActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val videoUrl = intent.extras?.getString("VIDEO") ?: run {
            Toast.makeText(this, "No video URL provided", Toast.LENGTH_SHORT).show()
            finish()
            return
        }
        // 调用分享函数
        shareRemoteVideo(videoUrl)
    }

    private fun shareRemoteVideo(videoUrl: String) {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                // 建立网络连接
                val url = URL(videoUrl)
                val connection = url.openConnection() as HttpURLConnection
                connection.connect()

                // 创建缓存目录
                val cacheVideoDir = File(cacheDir, "videos")
                if (!cacheVideoDir.exists()) cacheVideoDir.mkdirs()

                // 创建临时视频文件(扩展名根据实际视频类型调整)
                val tempVideoFile = File(cacheVideoDir, "temp_shared_video.mp4")

                // 下载视频到本地缓存
                val inputStream: InputStream = connection.inputStream
                val outputStream = FileOutputStream(tempVideoFile)
                val buffer = ByteArray(4096)
                var bytesRead: Int
                while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                    outputStream.write(buffer, 0, bytesRead)
                }
                inputStream.close()
                outputStream.close()

                // 切换到主线程发起分享
                withContext(Dispatchers.Main) {
                    // 生成Content URI
                    val contentUri = FileProvider.getUriForFile(
                        this@ShareVideoActivity,
                        "${packageName}.fileprovider",
                        tempVideoFile
                    )

                    val sharingIntent = Intent(Intent.ACTION_SEND).apply {
                        // 尝试获取准确的MIME类型, fallback到video/*
                        type = connection.contentType ?: "video/*"
                        putExtra(Intent.EXTRA_STREAM, contentUri)
                        // 授予接收应用临时读取权限
                        addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                    }

                    startActivity(Intent.createChooser(sharingIntent, "Share Video!"))
                }
            } catch (e: Exception) {
                e.printStackTrace()
                // 处理下载失败的情况
                withContext(Dispatchers.Main) {
                    Toast.makeText(this@ShareVideoActivity, "Failed to prepare video for sharing", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
}

备选方案:分享视频链接(无需下载)

如果你只是想让对方通过链接观看视频,而不是直接分享视频文件,可以简化代码,直接分享文本链接:

val videoUrl = extras!!.getString("VIDEO")
val sharingIntent = Intent(Intent.ACTION_SEND).apply {
    type = "text/plain"
    putExtra(Intent.EXTRA_TEXT, videoUrl)
}
startActivity(Intent.createChooser(sharingIntent, "Share Video Link!"))

这种方式无需下载,但对方需要点击链接跳转才能观看视频,适合不需要直接发送视频文件的场景。

内容的提问来源于stack exchange,提问作者Abhi Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 21:42:40