Flutter Android开发:限制分享文件时应用选择器仅显示指定应用
你添加的<queries>标签只是满足Android 11+的包可见性要求,让你的应用能检测到WhatsApp和Telegram的存在,但不会改变系统分享选择器的显示逻辑——系统默认会列出所有支持ACTION_SEND/ACTION_SEND_MULTIPLE的应用,所以无关应用还是会出现。
要实现只显示指定应用,或者过滤支持多文件分享的应用,需要自定义分享逻辑,以下是具体方案:
方案1:强制仅显示WhatsApp和Telegram
通过手动构建这两个应用的分享Intent,再生成只包含这些Intent的系统选择器。需要结合Flutter MethodChannel调用原生Android代码实现:
1. Flutter端代码
import 'package:flutter/services.dart'; class CustomShare { static const _channel = MethodChannel('custom_share'); // 调用原生分享方法,传入文件路径列表 static Future<void> shareFiles(List<String> filePaths) async { try { await _channel.invokeMethod('shareToSpecificApps', {'filePaths': filePaths}); } on PlatformException catch (e) { print('分享失败:${e.message}'); } } }
2. Android端代码(MainActivity)
import android.content.Intent import android.net.Uri import android.os.Build import androidx.core.content.FileProvider import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import java.io.File class MainActivity : FlutterActivity() { private val CHANNEL = "custom_share" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "shareToSpecificApps") { val filePaths = call.argument<List<String>>("filePaths") ?: emptyList() shareToTargetApps(filePaths) result.success(null) } else { result.notImplemented() } } } private fun shareToTargetApps(filePaths: List<String>) { // 转换文件路径为Uri(适配Android 7+的文件权限) val uris = mutableListOf<Uri>() filePaths.forEach { path -> val file = File(path) val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { FileProvider.getUriForFile(this, "${packageName}.fileprovider", file) } else { Uri.fromFile(file) } uris.add(uri) } val targetIntents = mutableListOf<Intent>() // 添加WhatsApp分享Intent(先检查是否安装) packageManager.getLaunchIntentForPackage("com.whatsapp")?.let { val waIntent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { type = "*/*" // 根据你的文件类型修改,比如"image/*" putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(uris)) setPackage("com.whatsapp") addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } targetIntents.add(waIntent) } // 添加Telegram分享Intent(先检查是否安装) packageManager.getLaunchIntentForPackage("org.telegram.messenger")?.let { val tgIntent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { type = "*/*" putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(uris)) setPackage("org.telegram.messenger") addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } targetIntents.add(tgIntent) } if (targetIntents.isEmpty()) { // 没有安装目标应用,跳转到应用商店 val storeIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("market://search?q=WhatsApp+or+Telegram") } startActivity(storeIntent) return } // 生成仅包含目标应用的选择器 val chooser = Intent.createChooser(targetIntents.removeAt(0), "选择分享应用") chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toTypedArray()) startActivity(chooser) } }
3. 配置FileProvider(AndroidManifest.xml)
在<application>标签内添加:
<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"> <external-files-path name="app_files" path="." /> <external-cache-path name="app_cache" path="." /> <!-- 根据你的文件存储路径添加对应配置 --> </paths>
方案2:仅显示支持多文件分享的应用
如果接受过滤出所有支持多文件分享的应用,可以修改原生代码,查询系统中所有支持ACTION_SEND_MULTIPLE的应用,再生成选择器:
// 查询所有支持多文件分享的应用包名 private fun getMultiFileShareApps(): List<String> { val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { type = "*/*" } val resolveInfos = packageManager.queryIntentActivities(intent, 0) return resolveInfos.map { it.activityInfo.packageName }.distinct() }
然后在构建targetIntents时,遍历上述包名列表,为每个包创建对应的分享Intent即可。
内容的提问来源于stack exchange,提问作者Slava709
相关产品推荐
相关产品推荐

