为了减少系统打包次数,主流厂家做法都会新增一个分区,用于客制一些常规需求。
通过烧写工具或者 fastboot 指令单独烧写替换资源及配置,这里提供一个直接将文件夹打包成 img 脚本
执行此脚本需要 root 权限
#!/bin/bash -x
IMG_SIZE=409600
rm customer.img
dd if=/dev/zero of=customer.img bs=1024 count=$IMG_SIZE
mkfs.ext4 -F customer.img
rm -rf t
mkdir t
sudo mount customer.img t
sudo cp customer/* t/ -r
sudo chmod 666 -R ./t
sudo chmod 777 -R ./t/bin
sudo find ./t -type d | while read line; do
sudo chmod 777 $line
done
sudo umount t
rm -rf t
e2fsck -f customer.img
resize2fs -M customer.img
接下来进入正题
建议先看下壁纸服务启动流程,可以参考如下资料
以下是测试的几种方式
方式一、在 java 层修改
通过 WallpaperManager api 就可以成功修改默认壁纸,同时需要增加 权限
为了便利和时效性考虑,在 SystemUI 中增加核心代码进行尝试
try {
java.io.FileInputStream inputStream = new java.io.FileInputStream(new java.io.File("/customer/wallpaper/default.png"));
android.app.WallpaperManager.getInstance(mContext).setStream(inputStream);
Log.i("PowerUI","set oemwallpaper success");
} catch (Exception e) {
e.printStackTrace();
}
验证结果,在收到开机广播后调用上面的 java 代码进行设置,SystemUI 进程会挂掉重启然后壁纸可成功设置
原因应该是这时候壁纸相关的服务还没完全启动,这种方式不推荐
方式二、在 sh 中修改
用户手动设置的壁纸,其实原理就是在 /data/system/users/0/wallpaper 下
所以通过 cp 指令将壁纸文件直接复制到固定目录即可,wallpaper.sh 脚本如下
因为 data/system 目录需要 root 权限才可范围,所以选择在 init.rc 中加载 wallpaper.sh 自动执行
如下脚本的大概意思,先判断壁纸文件夹是否存在,存在则继续创建用户设置壁纸文件夹
#!/system/bin/sh
PICTURES_DIR=/data/media/0/Pictures
WALLPAPER_OEM_DIR=/customer/wallpaper
DEFAULT_WALLPAPER_OEM=$WALLPAPER_OEM_DIR/default.png
SYS_DEFAULT_WALLPAPER=/data/system/users/0/wallpaper
if [ ! -e $WALLPAPER_OEM_DIR ]
then
exit 0
fi
function mkdirIfNotExist() {
local path=$1
if [ ! -e $path ]
then
mkdirIfNotExist $(dirname $path)
mkdir $path
chmod 777 $path
fi
}
mkdirIfNotExist $PICTURES_DIR
mkdirIfNotExist $(dirname $SYS_DEFAULT_WALLPAPER)
for i in `find $WALLPAPER_OEM_DIR -name "*.png"`
do
if [ ! -e $PICTURES_DIR/$(basename $i) ]
then
cp $i $PICTURES_DIR
fi
done
if [ -e $DEFAULT_WALLPAPER_OEM ]
then
if [ ! -e $SYS_DEFAULT_WALLPAPER ]
then
cp $DEFAULT_WALLPAPER_OEM $SYS_DEFAULT_WALLPAPER
chmod 666 $SYS_DEFAULT_WALLPAPER
fi
fi
验证结果,烧写 customer.img 开机启动时执行脚本,这时创建完壁纸信息,但默认壁纸加载流程已经结束
需要再重启一次设备才能看到客制默认壁纸,这种方式不推荐
方式三、修改 prop 值配置客制壁纸路径
String PROP_WALLPAPER = “ro.config.wallpaper”;
将 ro.config.wallpaper=/customer/wallpaper/default.png 配置一下即可
要修改 ro 开头 prop 属性值需要去除 property_service.cpp 中限制
默认壁纸加载顺序
1、用户自己设置的壁纸,也就是 /data/system/users/0/wallpaper
2、ro.config.wallpaper 对应壁纸是否存在
3、framework 目录下默认 default_wallpaper
frameworks\base\core\java\android\app\WallpaperManager.java
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static InputStream openDefaultWallpaper(Context context, @SetWallpaperFlags int which) {
final String whichProp;
final int defaultResId;
if (which == FLAG_LOCK) {
/* Factory-default lock wallpapers are not yet supported
whichProp = PROP_LOCK_WALLPAPER;
defaultResId = com.android.internal.R.drawable.default_lock_wallpaper;
*/
return null;
} else {
whichProp = PROP_WALLPAPER;
defaultResId = com.android.internal.R.drawable.default_wallpaper;
}
final String path = SystemProperties.get(whichProp);
final InputStream wallpaperInputStream = getWallpaperInputStream(path);
if (wallpaperInputStream != null) {
return wallpaperInputStream;
}
final String cmfPath = getCmfWallpaperPath();
final InputStream cmfWallpaperInputStream = getWallpaperInputStream(cmfPath);
if (cmfWallpaperInputStream != null) {
return cmfWallpaperInputStream;
}
try {
return context.getResources().openRawResource(defaultResId);
} catch (NotFoundException e) {
// no default defined for this device; this is not a failure
}
return null;
}
验证结果,当 ro.config.wallpaper 对应壁纸存在时,开机显示客制壁纸,推荐此种灵活方式