前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >静默安装从入门到转行!

静默安装从入门到转行!

作者头像
开发者技术前线
发布2020-11-23 11:33:21
9710
发布2020-11-23 11:33:21
举报
文章被收录于专栏:开发者技术前线

资讯

新浪科技讯 北京时间12月19日下午消息,谷歌母公司Alphabet旗下无人驾驶汽车公司Waymo刚刚展示了该公司与菲亚特-克莱斯勒联合开发的无人驾驶旅行车(第一辆智能无人车在百度问世), 人工智能将是google的下一个方向!

阅读文章需要一首歌时间,不妨伴随?看文章呢

2016了 本篇成了我的开年之博,距上次做静默安装和辅助服务(2015年)已经有一年半年之多,最近一直在做项目中的插件功能,也一直没时间整理平时接触的东西,甚至年终总结,今天就从经常用到的知识来开始2016的道路吧-- (本段写在2016年初)

Android应用管理

Aadroid的应用管理主要由PMS(PackageManagerService)来负责管理;上层由PackageManager来进行管理,通过PM我们可以得到设备上的所有安装包信息,包括未安装和安装过的, 未安装的包信息采用反射和未暴露的API,也可以进行深度解析得到我们想要的信息。而应用的安装和卸载也由PM来负责。

PMS

今天我们主要说一下PackageManager,至于PMS主要是由Binder进行交互, PMS在实际开发中我们很少直接用到,但是我们应用层想通过PM来获取的一些基础信息,都需要PMS来调用底层,当通过看源码得知PackageManager沿用了Android面向接口编程的风格,比如viewRoot,WindowManger,ActivityManager 都采用了面向接口编程,这些Mgr为我们提供了一些基础的功能接口,具体都由各自的Service来动态注入Impl,就是我们通常说的热插拔,至于这么写的好处,这里稍微说两句,在接触过java编程久点的朋友都知道面向接口的可扩展性很强,因为安卓源码也需要升级,谷歌工程师可能在下一个版本中或许就会新增一些api,那么这样设计的理念也便于源码的维护和升级,我们平时开发中也可以借鉴这种优雅的面向协议编程,当然iOS面向协议的思想同样适用。

PackageManager

PackageManager 在android.content.pm包下,它主要来负责应用的解析,和APK的安装,卸载和更新,那么我们可以清晰得看到此类的以下两个重要方法

1)负责安装

代码语言:javascript
复制
 private abstract void installPackage(
    Uri packageURI, IPackageInstallObserver observer, int flags,)

2)卸载

代码语言:javascript
复制
   private abstract void deletePackage(
   String packageName, IPackageDeleteObserver observer, int flags);

安卓系统通过以上api和底层的pms交互进行安装,普通apk无法直接安装的第三方应用的, 因为源码没有开放其方法,只有我们发送一条安装意图才可以交由pms来安装apk,具体由系统级别的apk(包名com.android.packageinstaller)来进行处理。

代码语言:javascript
复制
Intent intent = new Intent(Intent.ACTION_VIEW);
       intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       intent.setAction(Intent.ACTION_VIEW);
       intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
       context.startActivity(intent);

以上安全限制并非是谷歌的撒手锏,除了用未开放安装的api,在调用此方法前系统也会进行权限动态检测,我们可以看看pm的又一重要的方法:

public abstract int checkPermission(String permName, String pkgName);

这就证明了为何普通应用为何没有安装的权限,其内部会对调用此api的进行权限检测,如果是普通应用那么返回int值为1的返回值,在这里我们要和分析下安卓apk的级别内置应用和普通应用

预装程序(即相机,日历和浏览器等)保存在/system/app/中。 用户安装程序(APIDemo,Any.do等)保存在/data/app/中。 当然目前安卓4.4以后内置预装程序的app/下又会新增了pri-app/ 和/app,用来个用户提供卸载内置程序的入口,那么在pri下的apk无法卸载的,除非我们root后才能卸载。

实现静默安装

通过了解了上面pms的简单工作原理,我们就可以想到静默安装的途径。

一. 采用伪造系统PM(PackageManger)

通过伪造自己的Pm实现开放的api,并且采用自己的IPackageInstallObserver,说道这里你估计会不明白此类用来干嘛的。此观察者是用来检测apk是否安装的的回调,那么卸载同样有自己的观察者,此通过aidl和pms进行通讯,我们可以从源码copy一份到自己的项目下面 。注意的是包名和路径必须和源码保持一致。

伪造了安装所需要的observer和PM后 ,在我们的代码里直接掉用pm.installPackager()即可,但是又会来到权限的问题,那么怎么做到绕过权限呢,我通过改checkPermission()方法,但是测试后没用,即使我返回0也无法达到绕过权限的问题,那么,今天的静默安装也到此无法达到大家期望的普通静默安装的效果,但是在root后或者app为系统apk的时候,我们是可以做到静默安装的,至于安装成功时你需要当前显示什么view 我们同样可以在回调中进行处理。

二 .运行PM命令

我们可以直接在拿到系统builder写入pm命令,加入到系统进程中执行install方法进行安装 代码如下:

final ResultBuilder builder = Result.newBuilder();

代码语言:javascript
复制
String[] args = {"pm", "install", "-r", getPackageUri(path).getPath()};
String result = null;
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process= null;
InputStream errIs = null;
InputStream inIs = null;
try{
   ByteArrayOutputStream baos = new ByteArrayOutputStream();    int read=-1;
   process = processBuilder.start();
   errIs=process.getErrorStream();    while((read = errIs.read()) != -1){
       baos.write(read);
   }
   baos.write('\n');
   inIs=process.getInputStream();    while((read=inIs.read())!=-1){
       baos.write(read);
   }   byte[] data=baos.toByteArray();   result = new String(data);} catch (IOException e) {
   e.printStackTrace();
   String log = e.toString() + ":" + "file is write ex!";
   Log.e("", log);
   builder.setCustomMessage(log);
}

当然此方法也不是完美的,也需要root权限或者系统界别的apk,root可以向用户发起申请。代码略!

三 .采用反射

我们也可以采用反射方法,通过java反射原理,反射出PM然后执行insatallPackage(),PM并非直接可以反射,它是需要ActivityTherad进行提供支持,我们通过对系统总线程的反射出PM, 接着反射出installPackage方法即可。

代码语言:javascript
复制
Class<?>pmService;
Class<?> activityTherad;
Method method;activityTherad = Class.forName("android.app.ActivityThread");
Class<?> paramTypes[] = getParamTypes(activityTherad, "getPackageManager");
method = activityTherad.getMethod("getPackageManager", paramTypes);
Object PackageManagerService = method.invoke(activityTherad);
pmService = PackageManagerService.getClass();
Class<?> paramTypes1[] =getParamTypes(pmService, "installPackage");
method = pmService.getMethod("installPackage", paramTypes1);
method.invoke(PackageManagerService, getPackageUri(Path), null, 0, null);

总结

注意:实现静默安装都需要系统级别权限才能执行,具体是否监测系统给予权限

<permission android:name="android.permission.INSTALL_PACKAGES" />

其实root也是拥有系统级别权限的一种方式,本质是系统权限才有运行install的权限,

我们可以请求用户root (此方式个人感觉真心拿客户当牺牲品,建议pm经理不要这么做) 代码:

代码语言:javascript
复制
/**
* check rootPerssion.
* @return
*/private static boolean hasRootPerssion() {   PrintWriter PrintWriter = null;   Process process = null;    try {       process = Runtime.getRuntime().exec("su");       PrintWriter = new PrintWriter(process.getOutputStream());       PrintWriter.flush();       PrintWriter.close();        int value = process.waitFor();        return returnResult(value);   } catch (Exception e) {       e.printStackTrace();   } finally {        if (process!=null) {
           process.destroy();
       }
   }    return false;
}

所以实现静默安装的前提必须内置或者root,其他情况无法做到静默安装。当然到这里我必须要放弃了,因为面向客户的apk是非系统的,那么是不是我们无法做到除了以上内置的静默安装了呢 其实也未必:

目前我们可以采用辅助功能(Accessibility)实现自动安装,用来代替用户点击,监控在com.android.packageinstaller包的界面元素来遍历出所需要的按钮文本,来执行安装操作,微信抢红包插件也是利用此原理,但是采用辅助依旧会显示安装界面的,我们可以在原有的系统界面上添加一个view浮层来伪装静默安装功能(下期将带来免root实现静默安装),此种方式也需要用户主动授权。 到此静默安装又一次装逼失败,放弃

除此之外我们也可以采用动态加载来实现一个apk的安装,其实真正意义上并非静默安装,这需要一个apk来做宿主,只是将我们的apk解析出所用的组件信息,保存到本地,再将宿主的上下文直接注入插件apk中,至于插件实现apk免安装的知识有很多方式,如今讨论方案也十有八九,这里并没有过多的发坟贴!如果如有需要也可以单独出个专题介绍一下。到此如果没有宿主apk存在,那么当你的apk想无缘无故的在手机上安装起来是不可能的,到此你又一次必须要放弃!

疑问

时至今日!这里有人还不服还要装逼一下,认为一定有方案实现静默安装,为何QQ之类的就能实现,这里解释一下当你的产品庞大到用户不能放弃的时候,当你的粘力黏到你都无力呼吸时!那么那个时候你想做什么根本不是难题,就看你想做什么!这种大品牌通过与手机厂家合作的OEM定制利益链,或通过提供开发白名单的方式进行的非法采集勾当,这里就不想再说太多,你懂得! 不死进程一样,你终究要放弃!甚至改行!

---我是分割线---

Tamic开发社区

非专业的移动社区

不只是干货,还有人生

长按二维码关注我们

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-12-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开发者技术前线 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 资讯
  • Android应用管理
  • PMS
    • PackageManager
    • 实现静默安装
    • 一. 采用伪造系统PM(PackageManger)
    • 二 .运行PM命令
      • 三 .采用反射
      • 总结
      • 疑问
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档