Kotlin中如何使用Intent实现图片分享到其他应用的功能
你当前代码报错的核心原因是:调用系统相机拍照未指定输出路径时,返回的Intent中data?.data为null,仅在extra中携带低分辨率缩略图Bitmap,你传入空Uri到分享Intent自然触发错误。
前置配置(必须)
1. 清单文件配置
在AndroidManifest.xml中添加如下配置:
<!-- 存储权限,Android 13及以上无需WRITE_EXTERNAL_STORAGE --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <application ...> <!-- FileProvider配置,7.0及以上共享文件必须 --> <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> </application>
2. FileProvider路径配置
在res目录下新建xml文件夹,创建file_paths.xml文件:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="my_images" path="Pictures" /> <external-path name="external_files" path="."/> </paths>
完整功能代码
import android.content.Intent import android.graphics.Bitmap import android.net.Uri import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.provider.MediaStore import android.widget.Button import android.widget.ImageView import android.widget.Toast import androidx.core.content.FileProvider import java.io.File import java.io.FileOutputStream import java.io.OutputStream class MainActivity : AppCompatActivity() { private lateinit var iv: ImageView private lateinit var shareBtn: Button private var currentImageBitmap: Bitmap? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val takePhotoBtn = findViewById<Button>(R.id.btn) iv = findViewById(R.id.iV) shareBtn = findViewById(R.id.Share) // 拍照按钮逻辑 takePhotoBtn.setOnClickListener{ val takePhotoIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) startActivityForResult(takePhotoIntent, 1) } // 分享按钮逻辑 shareBtn.setOnClickListener { currentImageBitmap?.let { bitmap -> shareImage(bitmap) } ?: run { Toast.makeText(this, "请先拍摄图片", Toast.LENGTH_SHORT).show() } } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if(resultCode == RESULT_OK && requestCode == 1 && data != null){ // 获取缩略图Bitmap val imageBitmap = data.extras?.get("data") as Bitmap currentImageBitmap = imageBitmap iv.setImageBitmap(imageBitmap) } } // 核心分享方法 private fun shareImage(bitmap: Bitmap) { // 先将Bitmap保存到本地获取Uri val imageUri = saveBitmapToFile(bitmap) ?: return val shareIntent = Intent(Intent.ACTION_SEND) shareIntent.type = "image/*" // 给第三方应用授予Uri读取权限 shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri) // 避免没有可处理应用崩溃 if (shareIntent.resolveActivity(packageManager) != null) { startActivity(Intent.createChooser(shareIntent, "分享图片到")) } else { Toast.makeText(this, "没有可处理分享的应用", Toast.LENGTH_SHORT).show() } } // 将Bitmap保存为文件并返回可共享的Uri private fun saveBitmapToFile(bitmap: Bitmap): Uri? { return try { val imagesFolder = File(getExternalFilesDir(null), "Pictures") if (!imagesFolder.exists()) imagesFolder.mkdirs() val imageFile = File(imagesFolder, "share_image_${System.currentTimeMillis()}.jpg") val outputStream: OutputStream = FileOutputStream(imageFile) bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream) outputStream.flush() outputStream.close() // 生成可共享的FileProvider Uri FileProvider.getUriForFile(this, "${packageName}.fileprovider", imageFile) } catch (e: Exception) { e.printStackTrace() Toast.makeText(this, "图片保存失败", Toast.LENGTH_SHORT).show() null } } }
关键改动说明
- 提前保存ImageView展示的Bitmap,不依赖拍照返回的空Uri
- 采用官方推荐的FileProvider生成可跨应用访问的Uri,替换不安全的StrictMode绕过方案
- 给分享Intent添加读取权限标记,避免第三方应用无法访问图片
- 增加异常兜底逻辑,避免无处理应用时崩溃
内容的提问来源于stack exchange,提问作者Divyanshu Dobriyal
相关产品推荐
相关产品推荐

