Android 接收分享内容的完整实现指南
关于如何实现分享单个或多个文件,参考之前的Android 分享功能实现指南。本篇讲的则是从接收方,要接收来自其他应用的分享内容(文本、链接、图片或文件),需要正确配置 Intent Filter 和处理传入的数据。
1、基本配置
下面是完整的实现流程:
1.1. 修改 Manifest 文件
首先需要在 AndroidManifest.xml 中添加适当的 Intent Filter:android.intent.action.SEND
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" /> <!-- 接收任意类型 -->
</intent-filter>
支持多文件接收,添加android.intent.action.SEND_MULTIPLE:
<!-- 如果要同时支持多选 -->
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
1.2、处理不同类型的分享内容
在接收的Activity 中处理传入的 Intent:
public class ShareReceiverActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_receiver);
handleReceivedContent(getIntent());
}
private void handleReceivedContent(Intent intent) {
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
// 处理单个分享项
if ("text/plain".equals(type)) {
handleText(intent); // 处理文本
} else if (type.startsWith("image/")) {
handleImage(intent); // 处理图片
} else if (type.startsWith("*/*")){
handleFile(intent); // 处理通用文件
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
// 处理多个分享项
handleMultipleItems(intent);
} else {
// 不是有效的分享内容
finish();
}
}
}
2、具体数据处理方法
2.1. 接收纯文本或链接
private fun handleText(intent: Intent) {
val sharedText = intent.getStringExtra(Intent.EXTRA_TEXT)
Log.d(TAG, "handleText: $sharedText")
if (sharedText != null) {
// 更新UI显示文本
// 如果是URL链接
if (isValidUrl(sharedText)) {
//processLink(sharedText)
}
}
} 或者从clipData读取文本:
it.clipData?.getItemAt(0)?.text
判断是否是链接:
private boolean isValidUrl(String url) {
Pattern p = Patterns.WEB_URL;
Matcher m = p.matcher(url.toLowerCase(Locale.getDefault()));
return m.matches();
}
2.2. 接收单一图片/文件
private fun handleImage(intent: Intent) {
val imageUri: Uri? = intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
Log.i(TAG, "handleImage: $imageUri")
if (imageUri != null) {
try {
val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri)
// 显示图片
binding.image.setImageBitmap(bitmap)
// 如果需要保存文件
//saveToLocal(imageUri)
} catch (e: IOException) {
}
}
}
//保存接收到的图片
private void saveToLocal(Uri uri) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(uri);
File outputFile = new File(getExternalFilesDir(null), "received_" + System.currentTimeMillis() + ".jpg");
FileUtils.copy(inputStream, new FileOutputStream(outputFile));
} 或者从clipData读取
it.clipData?.getItemAt(0)?.uri
2.3. 接收多个文件
接收多文件:
private void handleMultipleItems(Intent intent) {
ArrayList<Uri> uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
if (uris != null) {
for (Uri uri : uris) {
String mimeType = getContentResolver().getType(uri);
if (mimeType != null) {
if (mimeType.startsWith("image/")) {
// 处理图片
} else if (mimeType.contains("video")) {
// 处理视频
} else {
// 处理普通文件
}
}
}
}
} 或者从clipData读取
for (i in 0 until clipData.itemCount) {
clipData.getItemAt(i).let { clipDataItem ->
clipDataItem.text
clipDataItem.uri
}
}
3、权限处理
确保在 manifest 中有必要的权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
对于 Android 10+,还需要使用 Scoped Storage API:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// 使用 ContentResolver 直接操作,不需要额外权限
} else {
// 检查并申请传统存储权限
}
4、优化用户体验
添加预览功能:对大图进行压缩后再显示
进度指示器:处理大文件时显示进度条
错误处理:捕获所有可能的IO异常并提供友好的提示
深色模式支持:适配不同的主题
5、注意要点
从不同应用发送不同类型的内容,以及兼容性考虑:
超大文件的处理能力
网络链接的正确识别
验证在多任务情况下的行为
以上实现了完整的分享接收功能,根据需要调整各部分细节来满足特定的业务需求。