工作背景:根据客户的需求需要在系统中集成一些apk,并且对集成的要求不同,有些需要集成后不能卸载,有些需要集成后可以卸载。要求不同,实现的方法也不同。目前遇到的几种需求如下:
A)在安卓系统中预置可以卸载的应用apk,手动可以卸载,恢复出厂设置时,系统会重新安装这些应用apk。
实现方法:
1、在device/XXXX/x6818下面建立preinstall文件夹,在该文件夹内创建init.preload.sh文件:
#!/system/bin/sh # ln preload apks if [ ! -f "/data/app/exist" ]; then echo "preloading application ..." for FILE in `ls /system/preload`;do ln -s /system/preload/$FILE/$FILE.apk /data/app/preload_$FILE.apk done sync echo "completed!" > /data/app/exist chmod 777 /data/app/exist sync fi
(1、首先会判断标识(即/data/app/exist这个节点)是否存在,如果存在则不执行链接命令,如果不存在,则执行Linux命令link,把预装应用安装包链接到data/app下。注:在终端设备第一次开机前不在data分区设置标识。
2、在data分区添加标识。
3、扫描data分区的链接文件,根据链接文件实际扫描到预装应用安装包。开机过程中,Package Manager Service会分别扫描system分区和data 分区的应用程序目录,根据应用程序所在分区为其设置相应属性。扫描完后,根据应用程序的相应属性将其安装到终端设备。
4、终端设备非第一次开机时,直接获取终端设备第一次开机时建立的链接文件。开机时,仍会执行init.preload.sh脚本,由于已添加标识,因此当判断出存在标识时,则不执行链接命令。
5、恢复出厂设置会删除data分区的数据,也就是链接文件和标识都将被删除。)
2、在preinstall文件夹内创建Android.mk文件:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := init.preload.sh LOCAL_MODULE_TAGS := optional eng LOCAL_MODULE_CLASS := ETC LOCAL_SRC_FILES := init.preload.sh include $(BUILD_PREBUILT) include $(LOCAL_PATH)/preload/preload.mk
3、在preinstall文件夹内创建preload文件夹,在该文件夹下创建preload.mk文件:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := meiweibudengdai LOCAL_SRC_FILES := meiweibudengdai/meiweibudengdai.apk LOCAL_MODULE_CLASS := APPS LOCAL_MODULE_TAGS := optional LOCAL_CERTIFICATE := PRESIGNED LOCAL_DEX_PREOPT := false LOCAL_MODULE_SUFFIX := .apk LOCAL_MODULE_PATH := $(TARGET_OUT)/preload include $(BUILD_PREBUILT)
注:LOCAL_CERTIFICATE:= PRESIGNED指用软件自带的签名。对应的LOCAL_CERTIFICATE:= platforms 是指用android源码中的platform对其进行签名
LOCAL_CERTIFICATE指签名方式,如果是platform,代表签名成系统软件, 如果还是PRESIGND,表示用的是apk原本的签名。
4、在preload文件夹内创建应用程序文件夹***,将应用程序***.apk放在应用程序文件夹***内
5、修改device/XXXX/init.x6818.rc文件,定义在init.x6818.rc中的服务preload-sh,其作用是执行init.preload.sh脚本。代码如下:
service preload-sh /system/bin/sh /system/etc/init.preload.sh class main user root oneshot
(此文件格式由安卓初始化语言定义,service为关键字用来声明一个Service:
preload-sh代表Service的名字,
/system/bin/sh代表所要执行的服务的路径,
/system/etc/init.preload.sh代表传给服务的参数,
class为服务制定一个类别,该Service属于main类别,
user执行服务前切换到用户root,该Service属于root用户,
oneshot代表服务只启动一次,一旦关闭就不能再启动)
6、修改device/XXXX/x6818.mk文件,增加代码:
PRODUCT_PACKAGES += init.preload.sh PRODUCT_PACKAGES += \ ***
目录结构如下:
device/XXXX/init.x6818.rc
device/XXXX/x6818.mk
device/XXXX/preinstall/init.preload.sh
device/XXXX/preinstall/Android.mk
device/XXXX/preinstall/preload/prelod.mk
device/XXXX/preinstall/preload/***/***.apk
注:该方法预装apk跟手动安装相同,无需预先导入lib库中的.so文件
B)在安卓系统中预置不可卸载的应用apk,实现方法:
1、在vendor/XXXX/apps目录下建立app文件夹,在该文件夹内创建应用程序文件夹***,将应用程序***.apk放在应用程序文件夹***内
2、在vendor/XXXX/apps目录下建立Android.mk文件,增加代码:
LOCAL_PATH :=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := *** LOCAL_SRC_FILES := app/***/***.apk LOCAL_MODULE_PATH := $(TARGET_OUT_APPS) LOCAL_MODULE_CLASS := APPS LOCAL_MODULE_OWNER := XXXX LOCAL_MODULE_TAGS := optional LOCAL_CERTIFICATE := PRESIGNED include $(BUILD_PREBUILT) include $(CLEAR_VARS) LOCAL_MODULE := &&& LOCAL_SRC_FILES := app/&&&/&&&.apk LOCAL_MODULE_PATH := $(TARGET_OUT)/priv-app/ LOCAL_MODULE_CLASS := APPS LOCAL_MODULE_OWNER := XXXX LOCAL_MODULE_TAGS := optional LOCAL_CERTIFICATE := PRESIGNED include $(BUILD_PREBUILT)
(注:1)默认预置apk到system/app/目录,LOCAL_MODULE_PATH:= $(TARGET_OUT_APPS) 普通系统apk,不可卸载
2)LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) 放在该目录下的apk可以卸载,卸载后,恢复出厂设置时,应用不会恢复。
3)LOCAL_MODULE_PATH := $(TARGET_OUT)/priv-app/ 放在该目录下的apk可以获得系统权限,系统核心apk,不可卸载(或者加入一句: LOCAL_CERTIFICATE:= PRESIGNED)。
4)?LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/operator/app, 预置APK使得用户可以卸载,并且恢复出厂设置时能够恢复?自测试不管用啊)
对于包含lib库文件的apk,还需要根据预置目标路径,在mk脚本文件中做不同的处理:
情况一:对于预置到data/app目录下的apk,包括可恢复和不可恢复(即上面的3、4情况)可以不用手动添加lib库,apk在首次运行时,会自动将吱声的lib库抽取安装到自身的根目录。
情况二:对于预置到system/app/和system/priv-app目录下面的apk(即上面的1、2情况)因为在android系统中。system分区是不允许应用执行写操作的,因此需要在Android.mk脚本中进行配置,手动添加lib库文件到编译环境,以便lib库文件在编译之后拷贝到对应编译后的apk目录下,否则apk执行时会因为找不到lib库而报错。方法为:手动解压取出lib文件中的库文件到当前apk的编译目录,在Android.mk中添加并配置变量(注意路径对应):PRODUCT_COPY_FILES += \ vendor/9tripod/apps/app/itms/lib/libbsdiffjni.so:system/lib/libbsdiffjni.so
3、在vendor/XXXX/apps目录下建立nxapps.mk文件,增加代码
PRODUCT_PACKAGES += \ *** PRODUCT_COPY_FILES += \ vendor/XXXX/apps/app/***/lib/###1.so:system/priv-app/***/lib/arm/###1.so\ vendor/XXXX/apps/app/***/lib/###2.so:system/priv-app/***/lib/arm/###2.so
(注:需要在该文件中预先导入lib库中的.so文件)
4、在device/XXXX/x6818/device.mk文件,增加代码,这样安卓系统就会编译nxapp.mk文件:
$(call inherit-product-if-exists, vendor/XXXX/apps/nxapps.mk)