结论:
使用 content Uri 而不是 File Uri 去让图库打开图片即可。
分析过程:
首先看一下点击“将照片设置为”按钮需要经过哪些activity跳转,过滤“start u0”(我不确定这个log是不是公版代码就带了)
在图库中打开图片,并点击“将照片设置为”时:
09-11 03:18:21.051 429-3924/system_process I/ActivityManager: START u0 {act=android.intent.action.CHOOSER flg=0x1 cmp=android/com.android.internal.app.ChooserActivity clip={image/* U:content://media/external/images/media/52} (has extras)} from uid 10061
09-11 03:18:21.192 429-3713/system_process I/ActivityManager: START u0 {act=android.intent.action.ATTACH_DATA dat=content://media/external/images/media/52 typ=image/* flg=0x3000001 cmp=com.android.gallery3d/.app.Wallpaper (has extras)} from uid 10061
09-11 03:18:21.313 429-3713/system_process I/ActivityManager: START u0 {act=android.service.wallpaper.CROP_AND_SET_WALLPAPER dat=content://media/external/images/media/52 flg=0x1 pkg=com.android.wallpapercropper cmp=com.android.wallpapercropper/.WallpaperCropActivity} from uid 10061
在第三方应用中打开图片,并点击“将照片设置为”时:
09-11 03:20:24.024 429-19703/system_process I/ActivityManager: START u0 {act=android.intent.action.VIEW dat=file:///storage/emulated/0/wallpaper_04.jpg typ=image/jpeg flg=0x10000000 cmp=com.android.gallery3d/.app.GalleryActivity} from uid 10065
09-11 03:20:29.024 429-19703/system_process I/ActivityManager: START u0 {act=android.intent.action.CHOOSER flg=0x1 cmp=android/com.android.internal.app.ChooserActivity clip={image/* U:file:///storage/emulated/0/wallpaper_04.jpg} (has extras)} from uid 10061
09-11 03:20:29.121 429-19703/system_process I/ActivityManager: START u0 {act=android.intent.action.ATTACH_DATA dat=file:///storage/emulated/0/wallpaper_04.jpg typ=image/* flg=0x3000001 cmp=com.android.gallery3d/.app.Wallpaper (has extras)} from uid 10061
看到已经先经历了一个chooser后转跳转到com.android.gallery3d.app.Wallpaper这个activity中。在图库中还会跳转到com.android.wallpapercropper.WallpaperCropActivity,而第三方却没有,那么问题应该就是出现在com.android.gallery3d.app.Wallpaper这个activity中了。
到com.android.gallery3d.app.Wallpaper.java文件中看看(大概这份图库的代码是rk px3 android 7.1的)
在onResume()中:
case STATE_PHOTO_PICKED: {
Log.d(TAG, "onResume mState=STATE_PHOTO_PICKED");
Intent cropAndSetWallpaperIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WallpaperManager wpm = WallpaperManager.getInstance(getApplicationContext());
try {
cropAndSetWallpaperIntent = wpm.getCropAndSetWallpaperIntent(mPickedItem);
startActivity(cropAndSetWallpaperIntent);
finish();
return;
} catch (ActivityNotFoundException anfe) {
// ignored; fallthru to existing crop activity
} catch (IllegalArgumentException iae) {
// ignored; fallthru to existing crop activity
}
}
这段代码会打开WallpaperCropActivity,但是有判断条件,有try/catch。
判断条件就先不考虑了,就是对版本限制。
try/catch中,catch到错误了就直接跳过,也没有打印。加上printStackTrace()后编译进机器试试。
} catch (ActivityNotFoundException anfe) {
anfe.printStackTrace();
// ignored; fallthru to existing crop activity
} catch (IllegalArgumentException iae) {
iae.printStackTrace();
// ignored; fallthru to existing crop activity
}
在第三方应用中打开图片,并点击“将照片设置为”。过滤"Wallpaper":
09-11 07:12:27.505 431-1103/system_process I/ActivityManager: START u0 {act=android.intent.action.ATTACH_DATA dat=file:///storage/emulated/0/wallpaper_04.jpg typ=image/* flg=0x3000001 cmp=com.android.gallery3d/.app.Wallpaper (has extras)} from uid 10061
09-11 07:12:27.584 11171-11171/com.android.gallery3d D/Wallpaper: onResume mState=STATE_INIT
onResume mState=STATE_PHOTO_PICKED
09-11 07:12:27.587 11171-11171/com.android.gallery3d W/System.err: java.lang.IllegalArgumentException: Image URI must be of the content scheme type
at android.app.WallpaperManager.getCropAndSetWallpaperIntent(WallpaperManager.java:886)
at com.android.gallery3d.app.Wallpaper.onResume(Wallpaper.java:110)
cropAndSetWallpaperIntent = wpm.getCropAndSetWallpaperIntent(mPickedItem);
这一行代码报了错误。
在网上寻找错误时,找到了一个网址https://stackoverflow.com/questions/23207604/get-a-content-uri-from-a-file-uri上面有解决方法。详细自己去看原文,大概的意思是要使用 content Uri 而不是 File Uri 去让图库打开图片即可。并且提供了一个将路径转换为Content Uri的方法。
public static Uri getImageContentUri(Context context, String absPath) {
Log.v(TAG, "getImageContentUri: " + absPath);
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
, new String[] { MediaStore.Images.Media._ID }
, MediaStore.Images.Media.DATA + "=? "
, new String[] { absPath }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI , Integer.toString(id));
} else if (!absPath.isEmpty()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, absPath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}