android apk靜默安裝和解除安裝

yangxi_001發表於2016-01-08

轉自:http://blog.csdn.net/gchk125/article/details/8553805

靜默安裝:

在某個觸發點自動後臺安裝指定apk.沒有安裝介面.新軟體自動安裝,有舊版本的默默解除安裝,然後再安裝,並且在不受系統設定中的第三方軟體安裝開關的限制.

 

自己跟蹤記錄的原始碼流程

Filemanager中點選apk包之後傳送了一個intent出去

/*

* uri = file:///storage/sdcard0/download/%E7%99%BE%E9%98%85.apk

* mimeType = application/vnd.android.package-archive

*/

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setDataAndType(uri, mimeType);

startActivity(intent);

 
 

Android會去系統中的packagemanager中查詢哪個apk能響應這個操作.

找到PackageInstaller這個apk.檔案路勁位於packages\apps\PackageInstaller

<activity android:name=".PackageInstallerActivity" …..>

<intent-filter>……

<data android:mimeType="application/vnd.android.package-archive" />

 
 

系統會啟動這個Activity來進行安裝操作

本文件只貼出具體安裝的過程,捨棄ui操作,並加以簡單說明

mPackageURI = intent.getData();   //獲取安裝包路勁

mPm = getPackageManager();     //獲取packagemanager

checkFileInvaild //檢測給定的檔案是否為一個apk.如果自己確定的東西,省略吧

final File sourceFile = new File(mPackageURI.getPath()); //把路勁轉成file型別

PackageParser.Package  mPkgInfo = PackageUtil.getPackageInfo(sourceFile); //解析apk

getIconandTitle //根據mPkgInfo獲取apk的icon和title.並存起來,對本題無用

if (!isInstallingUnknownAppsAllowed())//此處判斷是否允許第三方軟體安裝.在設定裡.

initiateInstall(); //開始初始化安裝

 










String pkgName = mPkgInfo.packageName; //得到包名

String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName });

if (oldName != null && oldName.length > 0 && oldName[0] != null) {

pkgName = oldName[0];  

mPkgInfo.setPackageName(pkgName);

}//以上是檢測是否存在該包名.但是其已經被改變成別的神馬了.*我不知道是神馬意思

mPm.getApplicationInfo(pkgName,PackageManager.GET_UNINSTALLED_PACKAGES);

//檢測是否有已經安裝並未解除安裝的同名apk,有則彈出替代框(略過),無則安裝

startInstallConfirm(); //彈出安裝確認,點選ok

newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,mPkgInfo.applicationInfo);

newIntent.setData(mPackageURI);

newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);

newIntent.setClass(this, InstallAppProgress.class); //把apk的info傳入新的Activity安裝

…..

 
















mAppInfo = intent.getParcelableExtra(XXX);

mPackageURI = intent.getData(); //從上面得到這些東西

String installerPackageName = getIntent().getStringExtra(xxxxPACKAGE_NAME);

PackageInstallObserver observer = new PackageInstallObserver();

pm.installPackage(mPackageURI, observer, installFlags(0), installerPackageName);

//安裝過程就交個packagemanager去吧.我們不用管了.

 








//如果你要等待此apk安裝完了之後還要處理一些東東的話.看下面

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);

intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);

intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);

intentFilter.addDataScheme("package");

registerReceiver(new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

if (Intent.ACTION_PACKAGE_REMOVED) {}

else if (Intent.ACTION_PACKAGE_ADDED || Intent.ACTION_PACKAGE_REPLACED) {}}

}, intentFilter);

//上面主要就是監聽三個事件並在receive中去處理.

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

好了.迴歸主題.靜默安裝的關鍵程式碼已經出來了.只有一行

pm.installPackage(mPackageURI,observer, installFlags(0), installerPackageName);

看原始碼中該函式說明必須要加上android.Manifest.permission#INSTALL_PACKAGES才行,此許可權只有system應用才能使用.所以此應用必須放入system/app下,才能保證其有效.方法就是反射

 

靜默安裝的第一種方法:

  1. package com.tnt.autoinstall;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.File;  
  5. import java.io.InputStream;  
  6. import java.lang.reflect.InvocationTargetException;  
  7. import java.lang.reflect.Method;  
  8.   
  9. import android.net.Uri;  
  10. import android.os.Bundle;  
  11. import android.app.Activity;  
  12.   
  13. public class MainActivity extends Activity {  
  14.     private Uri packageUri;  
  15.       
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.activity_main);  
  20.           
  21.         packageUri = getPackageUri();  
  22.           
  23.         install();  
  24.     }  
  25.       
  26.     private void install()  
  27.     {  
  28.         try {  
  29.             Class<?> pmService;  
  30.             Class<?> activityTherad;  
  31.             Method method;  
  32.               
  33.             activityTherad = Class.forName("android.app.ActivityThread");  
  34.             Class<?> paramTypes[] = getParamTypes(activityTherad , "getPackageManager");  
  35.             method = activityTherad.getMethod("getPackageManager", paramTypes);  
  36.             Object PackageManagerService = method.invoke(activityTherad);  
  37.               
  38.             pmService = PackageManagerService.getClass();  
  39.               
  40.             Class<?> paramTypes1[] = getParamTypes(pmService , "installPackage");  
  41.             method = pmService.getMethod("installPackage", paramTypes1);  
  42.             method.invoke(PackageManagerService , packageUri , null , 0 , null);  
  43.         } catch (NoSuchMethodException e) {  
  44.             e.printStackTrace();  
  45.         } catch (IllegalArgumentException e) {  
  46.             e.printStackTrace();  
  47.         } catch (IllegalAccessException e) {  
  48.             e.printStackTrace();  
  49.         } catch (InvocationTargetException e) {  
  50.             e.printStackTrace();  
  51.         }catch (ClassNotFoundException e1) {  
  52.             e1.printStackTrace();  
  53.         }  
  54.     }  
  55.       
  56.     private Class<?>[] getParamTypes(Class<?> cls, String mName) {  
  57.         Class<?> cs[] = null;  
  58.   
  59.         Method[] mtd = cls.getMethods();  
  60.   
  61.         for (int i = 0; i < mtd.length; i++) {  
  62.             if (!mtd[i].getName().equals(mName)) {  
  63.                 continue;  
  64.             }  
  65.             cs = mtd[i].getParameterTypes();  
  66.         }  
  67.         return cs;  
  68.     }  
  69.       
  70.     private Uri getPackageUri()  
  71.     {  
  72.         File file = new File("/storage/sdcard0/download/1.apk");  
  73.         return Uri.fromFile(file);  
  74.     }  
  75. }  

靜默安裝的第二種方法:

通過adb命令的方式來處理,程式碼如下,把上面的install函式替換下面程式碼

  1.   private boolean install()  
  2.   {  
  3.     String[] args = {"pm""install""-r", packageUri.getPath()};  
  4. String result = null;  
  5. ProcessBuilder processBuilder = new ProcessBuilder(args);;  
  6. Process process = null;  
  7. InputStream errIs = null;  
  8. InputStream inIs = null;  
  9. try{  
  10.     ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  11.     int read = -1;  
  12.     process = processBuilder.start();  
  13.     errIs = process.getErrorStream();  
  14.     while((read = errIs.read()) != -1){  
  15.         baos.write(read);  
  16.     }  
  17.     baos.write('\n');  
  18.     inIs = process.getInputStream();  
  19.     while((read = inIs.read()) != -1){  
  20.         baos.write(read);  
  21.     }  
  22.     byte[] data = baos.toByteArray();  
  23.     result = new String(data);  
  24. }catch(Exception e){  
  25.     e.printStackTrace();  
  26. }finally{  
  27.     try{  
  28.         if(errIs != null){  
  29.             errIs.close();  
  30.         }  
  31.         if(inIs != null){  
  32.             inIs.close();  
  33.         }  
  34.     }catch(Exception e){  
  35.         e.printStackTrace();  
  36.     }  
  37.     if(process != null){  
  38.         process.destroy();  
  39.     }  
  40. }  
  41.   
  42. if(result != null && (result.endsWith("Success")||result.endsWith("Success\n")))  
  43. {  
  44.     return true;  
  45. }  
  46. return false;  
  47.   }  

下面看下解除安裝過程

同樣的.需要增加一個許可權android:name="android.permission.DELETE_PACKAGES".放入system/app中.

解除安裝方式一:adb shell pm方式

  1. private void uninstall2() {  
  2.         String[] args = { "pm""uninstall""com.popcap.pvzthird" };  
  3.         String result = null;  
  4.         ProcessBuilder processBuilder = new ProcessBuilder(args);  
  5.         ;  
  6.         Process process = null;  
  7.         InputStream errIs = null;  
  8.         InputStream inIs = null;  
  9.         try {  
  10.             ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  11.             int read = -1;  
  12.             process = processBuilder.start();  
  13.             errIs = process.getErrorStream();  
  14.             while ((read = errIs.read()) != -1) {  
  15.                 baos.write(read);  
  16.             }  
  17.             baos.write('\n');  
  18.             inIs = process.getInputStream();  
  19.             while ((read = inIs.read()) != -1) {  
  20.                 baos.write(read);  
  21.             }  
  22.             byte[] data = baos.toByteArray();  
  23.             result = new String(data);  
  24.         } catch (Exception e) {  
  25.             e.printStackTrace();  
  26.         } finally {  
  27.             try {  
  28.                 if (errIs != null) {  
  29.                     errIs.close();  
  30.                 }  
  31.                 if (inIs != null) {  
  32.                     inIs.close();  
  33.                 }  
  34.             } catch (Exception e) {  
  35.                 e.printStackTrace();  
  36.             }  
  37.             if (process != null) {  
  38.                 process.destroy();  
  39.             }  
  40.         }  
  41.     }  

解除安裝方式二:反射呼叫系統函式

  1. Class<?> pmService;  
  2.             Class<?> activityTherad;  
  3.             Method method;  
  4.   
  5.             activityTherad = Class.forName("android.app.ActivityThread");  
  6.             Class<?> paramTypes[] = getParamTypes(activityTherad,  
  7.                     "getPackageManager");  
  8.             method = activityTherad.getMethod("getPackageManager", paramTypes);  
  9.             Object PackageManagerService = method.invoke(activityTherad);  
  10.   
  11.             pmService = PackageManagerService.getClass();  
  12.   
  13.             Class<?> paramTypes1[] = getParamTypes(pmService, "deletePackage");  
  14.             method = pmService.getMethod("deletePackage", paramTypes1);  
  15.             method.invoke(PackageManagerService, "com.popcap.pvzthird"null0);  

相關文章