客户需要我们预置skype到系统里,关于预置第三方app到系统,可以在网上能搜到一大片类似的文章。
详细内容可以参考博客:https://blog.csdn.net/a462533587/article/details/46380795
然而在预置skype的时候,遇到了不一样的结果。内置app到了系统,开机可以看到app的确在列表里,但是打开的时候app崩溃,因为是第三方app,连log调试都不能正常使用。但是当系统开启后,使用adb install 命令可以正常安装可开启skype。
可能的原因是因为内置skype的时候makefile脚本或者编译环境给他设置了一些什么属性导致app无法成为内部app开启。网上的帖子的办法都尝试过,当内置到/data/app目录的时候,即客户使用的app目录时,可以正常开启skype,但是又会导致在恢复工厂设置的时候导致app消失了。即使内置到所谓的/vendor/operator/app目录,也依然在开机后无法打开。
最终考虑的办法是在第一次开机的时候,也就是启动provision的开机引导时候进行app的安装,这样就算是以安装的模式安装到系统里,算是偷换概念的内置吧。
开机引导安装app,需要使用静默安装的办法。由于是要在user版本下安装,Android7.0需要root权限等等问题,导致需要利用反射的原理,获取Packagemanager服务实现静默安装app。
import android.content.pm.IPackageManager; //由于需要引用系统的packageManagerAIDL接口,需要导入此路径
try
{
Class<?> clazz = Class.forName("android.os.ServiceManager");
Method method_getService = clazz.getMethod("getService",
String.class);
IBinder bind = (IBinder) method_getService.invoke(null, "package");
IPackageManager iPm = IPackageManager.Stub.asInterface(bind);
iPm.installPackageAsUser("/system/usr/Skype/Skype.apk", null,2,"com.skype.raider",getUserId(Binder.getCallingUid()));
//其中第一个参数是skype app的系统路径,第四个参数是app的包名
} catch (Exception e)
{
e.printStackTrace();
}
app的路径需要事先编译的时候copy到系统内部,才能在第一次开机的时候去找到app。
实际上由于系统里没有内置的busybox工具,在init.project.rc里写的方法没能实现,而且这个init.{projectname}.rc还可能是根据开发项目的项目名来确定的。所以此方法只适合于在前面所有办法不能用的情况下的下下策。