AndroidL预置第三方应用
1. 预置有源码的APK
a) 将apk源码拷贝到在packages/apps/文件夹下,然后写好apk源码下创建Android.mk文件,添加以下内容:
LOCAL_PATH:= $(call my-dir) #调用my-dir脚本来获取当前路径
include $(CLEAR_VARS) #调用CLEAR_VARS来初始化除LOCAL_PATH以外以LOCAL_开头的变量
LOCAL_MODULE_TAGS := optional #表明这个应用是在所有编译模式都编译的,
LOCAL_SRC_FILES := $(call all-subdir-java-files)#指定要编译的java文件
LOCAL_PACKAGE_NAME := Test #指定这个应用模块的名称
include $(BUILD_PACKAGE) #编译这个模块
a) 在packages/apps/下创建Test文件夹,将apk拷贝到这个文件夹中,在这个文件下创建一个Android.mk的文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Test
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
#指定这是APPS类型,还有DATA,ETC之类的类型,编译后放到不同的地方,如ETC放etc目录,data放data目录。
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
@lib/armeabi/libtest.so \
@lib/armeabi/libtest2.so
# 以下内容是说这个apk已经签过名了,不用再签名了,方便以后apk的升级
LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
b) 如果有多个对应的库,则可以用下述方式来进行匹配
若apk支持不同cpu类型的so,针对so的部分的处理:
Ifeq ($(TARGET_ARCH),arm)
LOCAL_PREBUILT_JNI_LIBS := \
@lib/armeabi-v7a/xxx.so\
@ lib/armeabi-v7a/xxxx.so
else ifeq ($(TARGET_ARCH),x86)
LOCAL_PREBUILT_JNI_LIBS := \
@lib/x86/xxx.so
else ifeq ($(TARGET_ARCH),arm64)
LOCAL_PREBUILT_JNI_LIBS := \
@lib/armeabi-v8a/xxx.so
…
即将和TARGET_ARCH对应的so抽离出来
c) 将以上模块build进系统,操作如1.b)
d) 指定编译后apk所在位置
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) #预置到data/app下
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/app #预置到system/app下
LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/app #预置到system/vendor/app下
想要恢复出厂设置时恢复apk,则手机中一定会有个备份,以便恢复出厂设置时恢复。
1. 定义两个变,THIRDAPP_DIR为应用安装目录,必须在不可察除分区内
private static final String THIRDAPP_DIR= "/system/vendor/thirdapp";
private static final String THIRDAPP_FILTER_DIR= "/data/data/app";
2. 定义一个可恢复且可卸载的目录
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
……
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// add start
File customersAppDir = new File(THIRDAPP_DIR);
try {
customersAppDir = customersAppDir.getCanonicalFile();
} catch (IOException e) {
}
scanDirLI(customersAppDir, 0, scanFlags, 0);
// add end
……
}
3. 定义以下两个方法
private boolean filterthirdparyPackage(String scanPath, String pkgName) {
if (scanPath.startsWith(THIRDAPP_DIR)) {
final File filter = new File(THIRDAPP_FILTER_DIR, pkgName);
return filter.isDirectory();
}
return false;
}
private void updateVendorthirdpartyFilter(PackageSetting ps) {
String packageName = ps.name;
Slog.e(TAG, "packageName---- " + packageName);
if (ps.pkg != null) {
String packagePath = ps.pkg.codePath;
Slog.e(TAG, "packagePath---- " + packagePath);
if (packagePath != null && packagePath.startsWith(THIRDAPP_DIR)) {
SystemProperties.set("persist.sys.thirdapp.deleted", "1");
final File filter = new File(THIRDAPP_FILTER_DIR, packageName);
filter.mkdirs();
}
}
}
4. 实现重启后删除的apk不再显示
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
boolean success = false;
// add start
final File scanFile = new File(pkg.codePath);
if (filterthirdparyPackage(scanFile.getPath(), pkg.packageName)) {
if(SystemProperties.getInt("persist.sys.thirdapp.deleted", -1) == 1){
return null;
}
}
// add end
……
}
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
……
final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
// modified start
/*if ((isSystemApp(pkg) && !isUpdatedSystemApp(pkg))){*/
if ((isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) ||
(codePath.startsWith(THIRDAPP_DIR))) {
// modified end
……
}
……
private boolean deleteInstalledPackageLI(PackageSetting ps,
boolean deleteCodeAndResources, int flags,
int[] allUserHandles, boolean[] perUserInstalled,
PackageRemovedInfo outInfo, boolean writeSettings) {
……
// add start
updateVendorthirdpartyFilter(ps);
// add end
return true;
1. 在ActivityManagerService中设置一个系统变量(可以是在流程中任意地方)
boolean startHomeActivityLocked(int userId) {
installThirdPartApp();
……
}
private void installThirdPartApp() {
if ("".equals(SystemProperties.get("persist.sys.installapp", "0"))
|| SystemProperties.get("persist.sys.installapp", "0").equals(null)
|| SystemProperties.get("persist.sys.installapp", "0").equals("0")) {
try{
SystemProperties.set("persist.sys.installapp", "1");
Slog.d(TAG, "<==> test " + result);
}catch(Exception e){
Slog.d(TAG, "<==> test failed" );
e.printStackTrace();
}
}
2. 在Init.rc中定义一个拷贝动作
on property:persist.sys.installapp=1
copy /system/installapp /data/app
1. 预置有源码的APK
a) 将apk源码拷贝到在packages/apps/文件夹下,然后写好apk源码下创建Android.mk文件,添加以下内容:
LOCAL_PATH:= $(call my-dir) #调用my-dir脚本来获取当前路径
include $(CLEAR_VARS) #调用CLEAR_VARS来初始化除LOCAL_PATH以外以LOCAL_开头的变量
LOCAL_MODULE_TAGS := optional #表明这个应用是在所有编译模式都编译的,
LOCAL_SRC_FILES := $(call all-subdir-java-files)#指定要编译的java文件
LOCAL_PACKAGE_NAME := Test #指定这个应用模块的名称
include $(BUILD_PACKAGE) #编译这个模块
b) 上述模块加到PRODUCT_PACKAGES中,重新进行编译整个工程。
build/target/product/customers_preset_apackage.mk文件中添加 PRODUCT_PACKAGES += Test
a) 在packages/apps/下创建Test文件夹,将apk拷贝到这个文件夹中,在这个文件下创建一个Android.mk的文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Test
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
#指定这是APPS类型,还有DATA,ETC之类的类型,编译后放到不同的地方,如ETC放etc目录,data放data目录。
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
#如果有lib则可以添加以下内容,@是将apk的lib抽离出来build进apk同级目录下的lib文件夹中
#lib/armebai/libtest.so是apk减压出来的so的相对路径。这个属性有些应用不写也可以正常预置。
LOCAL_PREBUILT_JNI_LIBS:= \@lib/armeabi/libtest.so \
@lib/armeabi/libtest2.so
# 以下内容是说这个apk已经签过名了,不用再签名了,方便以后apk的升级
LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
b) 如果有多个对应的库,则可以用下述方式来进行匹配
若apk支持不同cpu类型的so,针对so的部分的处理:
Ifeq ($(TARGET_ARCH),arm)
LOCAL_PREBUILT_JNI_LIBS := \
@lib/armeabi-v7a/xxx.so\
@ lib/armeabi-v7a/xxxx.so
else ifeq ($(TARGET_ARCH),x86)
LOCAL_PREBUILT_JNI_LIBS := \
@lib/x86/xxx.so
else ifeq ($(TARGET_ARCH),arm64)
LOCAL_PREBUILT_JNI_LIBS := \
@lib/armeabi-v8a/xxx.so
…
即将和TARGET_ARCH对应的so抽离出来
c) 将以上模块build进系统,操作如1.b)
d) 指定编译后apk所在位置
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) #预置到data/app下
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/app #预置到system/app下
LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/app #预置到system/vendor/app下
想要恢复出厂设置时恢复apk,则手机中一定会有个备份,以便恢复出厂设置时恢复。
apk可卸载并可恢复的两种方式 :
一种是在PackageManagerService中做修改,指定system下的某个目录可以卸载,然后将apk预置到指定的目录中
一种是将apk预置一个不可用目录当备份,然后第一次开机时将此备份后拷贝到data/app目录下即可做一般安装的应用使用。
a) 在PackageManagerService中做修改,指定system分区中某个目录为可卸载目录。将apk安装到目录下。1. 定义两个变,THIRDAPP_DIR为应用安装目录,必须在不可察除分区内
private static final String THIRDAPP_DIR= "/system/vendor/thirdapp";
private static final String THIRDAPP_FILTER_DIR= "/data/data/app";
2. 定义一个可恢复且可卸载的目录
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
……
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// add start
File customersAppDir = new File(THIRDAPP_DIR);
try {
customersAppDir = customersAppDir.getCanonicalFile();
} catch (IOException e) {
}
scanDirLI(customersAppDir, 0, scanFlags, 0);
// add end
……
}
3. 定义以下两个方法
private boolean filterthirdparyPackage(String scanPath, String pkgName) {
if (scanPath.startsWith(THIRDAPP_DIR)) {
final File filter = new File(THIRDAPP_FILTER_DIR, pkgName);
return filter.isDirectory();
}
return false;
}
private void updateVendorthirdpartyFilter(PackageSetting ps) {
String packageName = ps.name;
Slog.e(TAG, "packageName---- " + packageName);
if (ps.pkg != null) {
String packagePath = ps.pkg.codePath;
Slog.e(TAG, "packagePath---- " + packagePath);
if (packagePath != null && packagePath.startsWith(THIRDAPP_DIR)) {
SystemProperties.set("persist.sys.thirdapp.deleted", "1");
final File filter = new File(THIRDAPP_FILTER_DIR, packageName);
filter.mkdirs();
}
}
}
4. 实现重启后删除的apk不再显示
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
boolean success = false;
// add start
final File scanFile = new File(pkg.codePath);
if (filterthirdparyPackage(scanFile.getPath(), pkg.packageName)) {
if(SystemProperties.getInt("persist.sys.thirdapp.deleted", -1) == 1){
return null;
}
}
// add end
……
}
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
……
final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
// modified start
/*if ((isSystemApp(pkg) && !isUpdatedSystemApp(pkg))){*/
if ((isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) ||
(codePath.startsWith(THIRDAPP_DIR))) {
// modified end
……
}
……
private boolean deleteInstalledPackageLI(PackageSetting ps,
boolean deleteCodeAndResources, int flags,
int[] allUserHandles, boolean[] perUserInstalled,
PackageRemovedInfo outInfo, boolean writeSettings) {
……
// add start
updateVendorthirdpartyFilter(ps);
// add end
return true;
}
1. 在ActivityManagerService中设置一个系统变量(可以是在流程中任意地方)
boolean startHomeActivityLocked(int userId) {
installThirdPartApp();
……
}
private void installThirdPartApp() {
if ("".equals(SystemProperties.get("persist.sys.installapp", "0"))
|| SystemProperties.get("persist.sys.installapp", "0").equals(null)
|| SystemProperties.get("persist.sys.installapp", "0").equals("0")) {
try{
SystemProperties.set("persist.sys.installapp", "1");
Slog.d(TAG, "<==> test " + result);
}catch(Exception e){
Slog.d(TAG, "<==> test failed" );
e.printStackTrace();
}
}
2. 在Init.rc中定义一个拷贝动作
on property:persist.sys.installapp=1
copy /system/installapp /data/app
3. 这个将apk预置到/system/installapp目录中