静默安装,就是apk在后台悄悄地安装。很多流氓软件喜欢干。但从现在的情况看,只有root了的手机才能静默安装,或者你能搞到手机厂商的签名。
关于静默安装,在万能的浏览器搜索一下,基本上有两种情况。
1.root情况下静默安装
2.非root下面静默安装
##root情况静默安装##
1.调用pm指令,下面就是调用pm指令(pm install -r)把/sdcard/haha.apk安装掉。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runShellCommand("pm install -r /sdcard/haha.apk"); //执行命令
}
private void runShellCommand(String command) {
Process process = null;
BufferedReader bufferedReader = null;
StringBuilder mShellCommandSB =new StringBuilder();
Log.d("wenfeng", "runShellCommand :" + command);
mShellCommandSB.delete(0, mShellCommandSB.length());
String[] cmd = new String[] { "/system/bin/sh", "-c", command }; //调用bin文件
try {
byte b[] = new byte[1024];
process = Runtime.getRuntime().exec(cmd);
bufferedReader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
mShellCommandSB.append(line);
}
Log.d("wenfeng", "runShellCommand result : " + mShellCommandSB.toString());
process.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
// TODO: handle exception
}
}
if (process != null) {
process.destroy();
}
}
}
2.调用cp指令,把apk拷贝到data/app目录下,把上面的runShellCommand(“pm install -r /sdcard/haha.apk”)替换成下面这句。然后用户下次重启时,apk就会自动安装。
runShellCommand("cp /sdcard/haha.apk /data/app")
##非root下面静默安装##
1.调用辅助功能,跟抢红包原理差不多。其实这种方式并不算严格的静默安装,因为用户可以看到安装的界面。很多应用商店都用到这种方式批量安装apk,下载后自动弹出安装界面,然后自动帮你点击安装。就能抢红包一样,自动打开红包页面,自动点击红包的道理一样一样的。
这个辅助功能最开始google设计是用于残疾人的,让他们更加方便的使用手机。一个应用要获取辅助功能,要在设置里面授权。
2.反射调用PackageManager
这个在百度搜索,大多数是出现这篇文章
Android 无需root实现apk的静默安装
关于这种方式,想法很好。
但是其实是不可行的。
而且文章的实现过于复杂了,其实不需要这么复杂,拉出一大坨类。如果你有Android系统源码的话,在源码环境编译只需要在Android.mk增加一句就可以了,把framework.jar包含进去编译,自然就可以找到那一大坨类。
LOCAL_JAVA_LIBRARIES := \
framework \
然后就可以直接在代码里面引用IPackageManager那些类了。
public static void install()
{
String path = "sdcard";
String fileName = path + "/haha.apk";
File file = new File(fileName);
try {
Class<?> clazz = Class.forName("android.os.ServiceManager");
Method method = clazz.getMethod("getService", String.class);
IBinder iBinder = (IBinder) method.invoke(null, "package");
IPackageManager ipm = IPackageManager.Stub.asInterface(iBinder);
@SuppressWarnings("deprecation")
VerificationParams verificationParams = new VerificationParams(null, null, null, VerificationParams.NO_UID, null);
ipm.installPackageAsUser(fileName, null, 2, null, verificationParams, "armeabi-v7a",0);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
上面我说这种方式是不可行的,原因是:
1.installPackageAsUser会远程调用PackageManagerService进行安装,但安装前需要校验权限,只有System权限以上才能通过校验。所以为了编译System权限的app,需要在AndroidManifest增加一句 android:sharedUserId=“android.uid.system”
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.haha"
android:sharedUserId="android.uid.system"
android:versionName="V1.01" >
2.但你以为你这个System权限的app可以安装到现实手机中吗?不可能的,系统在安装AndroidManifest包含android:sharedUserId="android.uid.system"的app时,都会首先看下app的签名。app签名不对直接就安装失败的。
所以,那篇文章的app根本不可能安装到手机中去。除非,你能搞到手机厂家的签名!!!!签名这个可是重大机密,泄露可是要出人命的。