知道了这个过程之后,就大概知道怎么做了。既然系统底层把这个API屏蔽了,那就想办法去绕过这层屏蔽,来使用它。首先想到的就是使用AIDL,不知道AIDL这东西的,先问度娘去吧~~在上面的代码中,最终实现安装的那一句话,mPm.installPackageAsUser(...),mPm是个什么东西?不难发现,IPackageManager类型,那么这个类从哪里来?搜寻一下,位于/frameworks/base/core/java/android/content/pm这个包底下,拷贝到我们工程目录底下,包名不能变,只拷贝这一个文件的话,一定是不行了,会报其他的一些aidl找不到,相应地也拷贝过来。Android5.0中,aidl改动还是比较大的,所以要拷贝很多东西过来,还要进行一些改动...我也是花了挺久才改到他没报错。
最终,工程的目录如下所示~~

那么,如何来使用它呢?
- 1、先获取系统服务android.os.ServiceManager,这个又是隐藏的,怎么办?考验Java水平的时候到了~~没错,用反射机制,来获取ServiceManager类,以及该类里面的方法;
- 2、有了服务之后,我们就要去拿到IPackageManager这个对象;
-
3、调用IPackageManager里面的installPackage方法进行安装;
实现代码如下:
package com.example.autoinstall; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; import android.app.Activity; import android.content.Intent; import android.content.pm.IPackageInstallObserver2; import android.content.pm.IPackageManager; import android.content.pm.VerificationParams; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /** * Button点击事件 * @param view */ public void install(View view) { String path = ""; if (FileUtils.isSdcardReady()) { path = FileUtils.getSdcardPath(); } else { path = FileUtils.getCachePath(this); } String fileName = path + "/AidlServerDemo.apk"; File file = new File(fileName); try { if(!file.exists()) copyAPK2SD(fileName); Uri uri = Uri.fromFile(new File(fileName)); // 通过Java反射机制获取android.os.ServiceManager 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.installPackage(fileName, new PackageInstallObserver(), 2, null, verificationParams, ""); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 用于显示结果 class PackageInstallObserver extends IPackageInstallObserver2.Stub { @Override public void onUserActionRequired(Intent intent) throws RemoteException { // TODO Auto-generated method stub } @Override public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) throws RemoteException { //returnCode<span style="font-family: Arial, Helvetica, sans-serif;">为1,就是安装成功</span> } }; /** * 拷贝assets文件夹的APK插件到SD * * @param strOutFileName * @throws IOException */ private void copyAPK2SD(String strOutFileName) throws IOException { FileUtils.createDipPath(strOutFileName); InputStream myInput = this.getAssets().open("AidlServerDemo.apk"); OutputStream myOutput = new FileOutputStream(strOutFileName); byte[] buffer = new byte[1024]; int length = myInput.read(buffer); while (length > 0) { myOutput.write(buffer, 0, length); length = myInput.read(buffer); } myOutput.flush(); myInput.close(); myOutput.close(); } }










