在android手机浏览器里,百度搜索下载某个app时,都会出现安全下载和普通下载两个选项,普通下载会直接通过浏览器下载该App,安全下载会先下载安装百度手机助手,打开百度手机助手会自动下载用户搜索的app。应用宝等手机助手类软件有类似的过程。

安全下载是从app分发渠道的后台去下载app,普通下载是根据指定url去源站下载。本文不探讨安全下载是否下载到安全的app,也不探讨助手类软件捆绑安装的道德问题。本文仅从技术角度探讨一下安全下载的实现问题。

思路

最关键的一点是,助手类软件安装后如何会自动的去下载用户搜索的app,这个参数是如何传递的?

咋一看感觉是,用户点击安全下载的时候,后台把搜索的app信息拼接到手机助手apk的文件名里,比如搜索知乎后下载的百度手机助手的名字的确也是<手机助手_知乎.apk>,手机助手启动时读取文件名里的<知乎>字段去下载,细思不对,安全后apk文件被删除了怎么办,根据一个String类型的应用名称<知乎>怎么去下载。

内心深处一阵排山倒海之后得出一个结论,不可能是通过文件名来传递参数的,那就只能是通过apk包本身传递参数,也就是说对原始的手机助手的apk进行重打包,把搜索的app信息放进新的助手apk里。

最先想起了优先的美团团队的多渠道打包方案,在META-INF文件里直接放置一个空文件,文件名就包含被搜索的app信息,不用重新签名应用,这样后台可以快速生成一个新的apk。但据传说,美团的方案有一些android版本的兼容性问题,所以也暂且不用。

实现

本文最终选把app信息写进apk里某个指定的raw文件,然后重新签名生成新的apk文件来实现安全下载的参数传递。app首次启动时就根据raw文件里的信息去执行任务下载。

重新生成apk在后台服务器端通过执行shell完成。

apk是zip格式压缩包,使用zip命令完成文件写入。$downloadInfo是需要传递的参数,比如被搜索的app的实际下载地址。

1
2
3
4
5
6
echo $downloadInfo >./res/raw/download
cp $APK_FILE_NAME $TEMP_NAME.zip
zip -d $TEMP_NAME.zip /res/raw/download
zip -u $TEMP_NAME.zip ./res/raw/download
zip -d $TEMP_NAME.zip META-INF/\*
mv $TEMP_NAME.zip $TEMP_NAME.apk

签名

1
jarsigner -verbose -digestalg SHA1 -sigalg MD5withRSA -keystore $MMDAEMON_KEY_PATH -storepass $storepass -keypass $keypass -signedjar $OUT_APK_PATH ${TEMP_NAME}.apk $keystoreFile

签名后的$OUT_APK_PATH 对应的apk就是最终下载的助手apk。当然助手apk原本应该有逻辑实现,根据R.raw.download的文件内容去执行下载。