Android无需root实现apk的静默安装

2019-12-10 19:14:28于海丽
易采站长站为您分析Android无需root实现apk的静默安装 的相关资料,需要的朋友可以参考下  

Android的静默安装似乎是一个很有趣很诱人的东西,但是,用普通做法,如果手机没有root权限的话,似乎很难实现静默安装,因为Android并不提供显示的Intent调用,一般是通过以下方式安装apk:

Intent intent = new Intent(Intent.ACTION_VIEW); 
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); 
startActivity(intent); 

但是,这并没有真正的实现静默安装,因为有用户界面,会让用户知道。那么,怎么在后台悄悄的安装APK呢?只能试图去看看Android系统源码正常安装APK的过程,我这边下载的源码是Android5.0系统的,5个G的大小,但是可能由于Android5.0有一些安全方面的更新,跟之前的版本还是有一定的差距的,但是,学会一个之后再去学另一个相似的过程,那就简单许多了,就像学会了C语言,再学Java,也并非什么难事。

Android系统把所有的Permission(权限)依据其潜在风险划分为四个等级,即"normal"、 "dangerous"、 "signature"、 "signatureOrSystem"。APK的安装对应的权限是 INSTALL_PACKAGES,权限等级属于后两者。所以,最终想实现APK的静默安装,必然需要一些特殊的处理,执行安装的这个进程,须为系统进程。
那么,我们就来看看Android自身是如何实现安装APK的。安装的命令是pm install... 我们定位到系统源码的/frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java这个文件,他实现了pm命令,我们看runInstall方法,这就是APK的安装过程。

private void runInstall() { 
  int installFlags = 0; 
  int userId = UserHandle.USER_ALL; 
  String installerPackageName = null; 
 
  String opt; 
 
  String originatingUriString = null; 
  String referrer = null; 
  String abi = null; 
 
  while ((opt=nextOption()) != null) { 
    if (opt.equals("-l")) { 
      installFlags |= PackageManager.INSTALL_FORWARD_LOCK; 
    } else if (opt.equals("-r")) { 
      installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 
    } else if (opt.equals("-i")) { 
      installerPackageName = nextOptionData(); 
      if (installerPackageName == null) { 
        System.err.println("Error: no value specified for -i"); 
        return; 
      } 
    } else if (opt.equals("-t")) { 
      installFlags |= PackageManager.INSTALL_ALLOW_TEST; 
    } else if (opt.equals("-s")) { 
      // Override if -s option is specified. 
      installFlags |= PackageManager.INSTALL_EXTERNAL; 
    } else if (opt.equals("-f")) { 
      // Override if -s option is specified. 
      installFlags |= PackageManager.INSTALL_INTERNAL; 
    } else if (opt.equals("-d")) { 
      installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; 
    } else if (opt.equals("--originating-uri")) { 
      originatingUriString = nextOptionData(); 
      if (originatingUriString == null) { 
        System.err.println("Error: must supply argument for --originating-uri"); 
        return; 
      } 
    } else if (opt.equals("--referrer")) { 
      referrer = nextOptionData(); 
      if (referrer == null) { 
        System.err.println("Error: must supply argument for --referrer"); 
        return; 
      } 
    } else if (opt.equals("--abi")) { 
      abi = checkAbiArgument(nextOptionData()); 
    } else if (opt.equals("--user")) { 
      userId = Integer.parseInt(nextOptionData()); 
    } else { 
      System.err.println("Error: Unknown option: " + opt); 
      return; 
    } 
  } 
 
  if (userId == UserHandle.USER_ALL) { 
    userId = UserHandle.USER_OWNER; 
    installFlags |= PackageManager.INSTALL_ALL_USERS; 
  } 
 
  final Uri verificationURI; 
  final Uri originatingURI; 
  final Uri referrerURI; 
 
  if (originatingUriString != null) { 
    originatingURI = Uri.parse(originatingUriString); 
  } else { 
    originatingURI = null; 
  } 
 
  if (referrer != null) { 
    referrerURI = Uri.parse(referrer); 
  } else { 
    referrerURI = null; 
  } 
 
  // Populate apkURI, must be present 
  final String apkFilePath = nextArg(); 
  System.err.println("tpkg: " + apkFilePath); 
  if (apkFilePath == null) { 
    System.err.println("Error: no package specified"); 
    return; 
  } 
 
  // Populate verificationURI, optionally present 
  final String verificationFilePath = nextArg(); 
  if (verificationFilePath != null) { 
    System.err.println("tver: " + verificationFilePath); 
    verificationURI = Uri.fromFile(new File(verificationFilePath)); 
  } else { 
    verificationURI = null; 
  } 
 
  LocalPackageInstallObserver obs = new LocalPackageInstallObserver(); 
  try { 
    VerificationParams verificationParams = new VerificationParams(verificationURI, 
        originatingURI, referrerURI, VerificationParams.NO_UID, null); 
 
    mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags, 
        installerPackageName, verificationParams, abi, userId); //注意!!最终就是调用这个方法来进行安装的 
 
    synchronized (obs) { 
      while (!obs.finished) { 
        try { 
          obs.wait(); 
        } catch (InterruptedException e) { 
        } 
      } 
      if (obs.result == PackageManager.INSTALL_SUCCEEDED) { 
        System.out.println("Success"); 
      } else { 
        System.err.println("Failure [" 
            + installFailureToString(obs) 
            + "]"); 
      } 
    } 
  } catch (RemoteException e) { 
    System.err.println(e.toString()); 
    System.err.println(PM_NOT_RUNNING_ERR); 
  } 
}