非ROOT实现静默安装的一些思考与体会,AIDL获取IPackageManager,反射ServiceManager,系统签名
一.install的思考
- 1.纯手工,点击安装包,安装应用
- 2.adb安装
//安装
adb install xxx.apk
//卸载
adb uninstall xxx.apk
pm install -r
98 if ("install".equals(op)) {
99 runInstall();
100 return;
101 }
102
103 if ("uninstall".equals(op)) {
104 runUninstall();
105 return;
106 }
743 private void runInstall() {
744 int installFlags = 0;
745 String installerPackageName = null;
746
747 String opt;
748 while ((opt=nextOption()) != null) {
749 if (opt.equals("-l")) {
750 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
751 } else if (opt.equals("-r")) {
752 installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
753 } else if (opt.equals("-i")) {
754 installerPackageName = nextOptionData();
755 if (installerPackageName == null) {
756 System.err.println("Error: no value specified for -i");
757 showUsage();
758 return;
759 }
760 } else if (opt.equals("-t")) {
761 installFlags |= PackageManager.INSTALL_ALLOW_TEST;
762 } else if (opt.equals("-s")) {
763 // Override if -s option is specified.
764 installFlags |= PackageManager.INSTALL_EXTERNAL;
765 } else if (opt.equals("-f")) {
766 // Override if -s option is specified.
767 installFlags |= PackageManager.INSTALL_INTERNAL;
768 } else {
769 System.err.println("Error: Unknown option: " + opt);
770 showUsage();
771 return;
772 }
773 }
774
775 final Uri apkURI;
776 final Uri verificationURI;
777
778 // Populate apkURI, must be present
779 final String apkFilePath = nextArg();
780 System.err.println("\tpkg: " + apkFilePath);
781 if (apkFilePath != null) {
782 apkURI = Uri.fromFile(new File(apkFilePath));
783 } else {
784 System.err.println("Error: no package specified");
785 showUsage();
786 return;
787 }
788
789 // Populate verificationURI, optionally present
790 final String verificationFilePath = nextArg();
791 if (verificationFilePath != null) {
792 System.err.println("\tver: " + verificationFilePath);
793 verificationURI = Uri.fromFile(new File(verificationFilePath));
794 } else {
795 verificationURI = null;
796 }
797
798 PackageInstallObserver obs = new PackageInstallObserver();
799 try {
800 mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
801 verificationURI, null);
802
803 synchronized (obs) {
804 while (!obs.finished) {
805 try {
806 obs.wait();
807 } catch (InterruptedException e) {
808 }
809 }
810 if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
811 System.out.println("Success");
812 } else {
813 System.err.println("Failure ["
814 + installFailureToString(obs.result)
815 + "]");
816 }
817 }
818 } catch (RemoteException e) {
819 System.err.println(e.toString());
820 System.err.println(PM_NOT_RUNNING_ERR);
821 }
822 }
mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,verificationURI, null);
mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,installerPackageName);
IPackageManager mPm;
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
二.IPackageManager.aidl
三.静默安装的实现
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp">
<EditText
android:id="@+id/etPackageNmae"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入应用名"/>
<Button
android:id="@+id/btnInstall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="静默安装"/>
</LinearLayout>
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
//反射获取ServiceManager
try {
//指定反射类
Class<?> forName = Class.forName("android.os.ServiceManager");
//获取方法,参数是String类型
Method method = forName.getMethod("getService", String.class);
//传入参数
IBinder iBinder = (IBinder) method.invoke(null, "package");
//初始化AIDL
mPm = IPackageManager.Stub.asInterface(iBinder);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
/**
* 安装apk
*
* @param apkPath 路径
*/
private void runInstall(String apkPath) {
/**
* install方法
* 1.uri:安装文件路径
* 2.observer:观察者,安装成功还是失败
* 3.flags:标记状态
* 4.installer: 整个路径
*/
try {
mPm.installPackage(Uri.fromFile(new File(apkPath)),
new PackInstallObserver(), INSTALL_REPLACE_EXISTING,
new File(apkPath).getPath());
} catch (RemoteException e) {
e.printStackTrace();
}
}
<uses-permission android:name="android.permission.INSTALL_PACKAGES"/>
四.android.uid.system
- platform.pk8
platform.x509.pem
- SignApk.java
package com.liuguilin.silentinstall;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 静默安装 --by 刘桂林
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
//输入框
private EditText etPackageNmae;
//执行按钮
private Button btnInstall;
//安装路径
private String path = Environment.getExternalStorageDirectory().getAbsolutePath();
//安装类
private IPackageManager mPm;
//install flags 状态,详见PackageManager
private static final int INSTALL_REPLACE_EXISTING = 0X00000002;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
/**
* 初始化View
*/
private void initView() {
//反射获取ServiceManager
try {
Class<?> forName = Class.forName("android.os.ServiceManager");
Method method = forName.getMethod("getService", String.class);
IBinder iBinder = (IBinder) method.invoke(null, "package");
//初始化AIDL
mPm = IPackageManager.Stub.asInterface(iBinder);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//初始化
etPackageNmae = (EditText) findViewById(R.id.etPackageNmae);
btnInstall = (Button) findViewById(R.id.btnInstall);
btnInstall.setOnClickListener(this);
}
/**
* 点击事件
*
* @param view
*/
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnInstall:
String apkPath = path + "/" + etPackageNmae.getText().toString().trim();
runInstall(apkPath);
break;
}
}
/**
* 安装apk
*
* @param apkPath 路径
*/
private void runInstall(String apkPath) {
/**
* install方法
* 1.uri:安装文件路径
* 2.observer:观察者,安装成功还是失败
* 3.flags:标记状态
* 4.installer: 整个路径
*/
try {
mPm.installPackage(Uri.fromFile(new File(apkPath)),
new PackInstallObserver(), INSTALL_REPLACE_EXISTING,
new File(apkPath).getPath());
} catch (RemoteException e) {
e.printStackTrace();
}
}
/**
* 观察者
*/
class PackInstallObserver extends IPackageInstallObserver.Stub {
@Override
public void packageInstalled(String packageName, int returnCode) throws RemoteException {
//根据returnCode判断是否成功失败
}
}
}