如何在Android O上用Intent.ACTION_ATTACH_DATA设置壁纸等(不使用WallpaperManager)
使用Intent.ACTION_ATTACH_DATA在Android中设置壁纸、联系人照片等(适配Android O)
我之前也折腾过这个需求——不用WallpaperManager,而是借助系统自带的选择器完成壁纸、联系人照片甚至第三方应用(比如WhatsApp)的资料图设置,结合FileProvider完全能适配Android O及以上系统,下面一步步给你拆解实现步骤,顺便说几个我踩过的坑:
1. 先搞定FileProvider的配置(必须步骤)
首先得在AndroidManifest.xml里注册FileProvider,注意authorities要和你代码里用的完全一致,别写错:
<provider android:name="androidx.core.content.FileProvider" android:authorities="com.mydomain.provider" 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文件,指定你要共享的图片存储路径(对应你代码里getExternalFilesDir(null)下的images目录):
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="my_images" path="images/" /> </paths>
2. 准备图片文件并获取合法Uri
你代码里已经有部分逻辑,这里补全细节,确保文件存在且Uri生成正确:
// 创建图片存储目录,不存在就新建 File imageDir = new File(getExternalFilesDir(null), "images"); if (!imageDir.exists()) { imageDir.mkdirs(); } // 生成唯一的图片文件名 String fileName = "share_image_" + System.currentTimeMillis() + ".jpg"; File imageFile = new File(imageDir, fileName); // 这里需要把你的Bitmap保存到上面创建的文件里,示例代码如下: // Bitmap yourBitmap = ...; // 你的目标Bitmap对象 // try (FileOutputStream fos = new FileOutputStream(imageFile)) { // yourBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos); // } catch (IOException e) { // e.printStackTrace(); // } // 通过FileProvider获取可共享的Uri Uri bmpUri = FileProvider.getUriForFile(this, "com.mydomain.provider", imageFile);
3. 构造Intent.ACTION_ATTACH_DATA并启动
核心就在这一步,不同用途的设置只需要保证MIME类型正确,同时适配权限要求:
3.1 设置为壁纸
Intent attachIntent = new Intent(Intent.ACTION_ATTACH_DATA); attachIntent.setDataAndType(bmpUri, "image/jpeg"); attachIntent.putExtra("mimeType", "image/jpeg"); // 必须添加这个flag,否则目标应用无法读取你的图片 attachIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 启动系统选择器,让用户选怎么设置壁纸 startActivity(Intent.createChooser(attachIntent, "设置壁纸"));
3.2 设置为联系人照片
逻辑和壁纸类似,系统会自动识别联系人应用并响应:
Intent attachIntent = new Intent(Intent.ACTION_ATTACH_DATA); attachIntent.setDataAndType(bmpUri, "image/jpeg"); attachIntent.putExtra("mimeType", "image/jpeg"); attachIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 启动选择器,用户选择联系人应用后就能设置对应联系人的照片 startActivity(Intent.createChooser(attachIntent, "设置联系人照片"));
3.3 设置为WhatsApp个人资料
不用额外改Intent,直接用上面的代码启动选择器,用户选择WhatsApp后,系统会自动跳转到个人资料设置界面,前提是你的Uri是合法可访问的。
Android O及以上的关键注意事项
- 别用file:// Uri:Android O开始严格限制文件暴露,必须用
FileProvider生成content://开头的Uri,否则会抛出FileUriExposedException。 - 权限必须给足:一定要加
Intent.FLAG_GRANT_READ_URI_PERMISSION,不然第三方应用(比如WhatsApp、联系人应用)读不到你的图片。 - authority要一致:Manifest里的
authorities参数必须和getUriForFile里的第二个参数完全匹配,差一个字符都不行。 - 路径配置要对应:
file_paths.xml里的路径要和你实际存储图片的目录对应,不然FileProvider找不到文件,生成的Uri也是无效的。
内容的提问来源于stack exchange,提问作者Tonui Nicholus
相关产品推荐
相关产品推荐

