Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android如何安裝系統應用,及自己增加安裝系統應用的接口

Android如何安裝系統應用,及自己增加安裝系統應用的接口

編輯:關於Android編程

根據SIM卡安裝系統應用

功能:

1:如何安裝系統應用,apk放在system/app系統分區下面。 2:根據SIM卡的歸屬國家選擇性的安裝應用。

一:本人使用方法:

在開機的服務裡面添加接口(PackageManagerService.java),檢測到SIM卡的信息調用該接口。 下面是具體的方法: 系統服務PackageManager服務調用的是aidl接口,所以添加接口要添加兩個地方,一個是IpackageManager.aidl,還有一個是PackageManagerService.java裡面添加接口。下面在PackageManagerService.java裡面添加的接口
   private static String[] mAddedApks = { "HandwritePack.apk", "PinyinPack.apk",	
»       »       »       "ChtPack_.apk", "TouchPal.apk" };
 
    
    public String[] getApks(){	
    »       return mAddedApks;	
    }	
    	
    public void scanApkAndInstallAll(){
»       »       File systemAppDir = new File(Environment.getRootDirectory(), "app");

»       »       for (String appName : mAddedApks) {
»       »       »       File installApp = new File(systemAppDir, appName);

»       »       »       if(!installApp.exists()){
»       »       »       »       continue;	
»       »       »       }
»       »       »       
»       »       »       String addedPackage = null;	
»       »       »       int addedAppId = -1;	
»       »       »       int[] addedUsers = null;	

»       »       »       /*	
»       »       »        * if (!isPackageFilename(installApp)) { // Ignore entries which are
»       »       »        * not apk's continue; }	
»       »       »        */	
»       »       »       // Set flag to monitor and not change apk file paths when	
»       »       »       // scanning install directories.	
»       »       »       int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME;
»       »       »       int flags = (PackageParser.PARSE_IS_SYSTEM	
»       »       »       »       »       | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_CH
ATTY);
»       »       »       if (mNoDexOpt) {	
»       »       »       »       scanMode |= SCAN_NO_DEX;	
»       »       »       }	
»       »       »       synchronized (mInstallLock) {

»       »       »       »       PackageParser.Package pkg = scanPackageLI(installApp, flags	
»       »       »       »       »       »       | PackageParser.PARSE_MUST_BE_APK, scanMode,	
»       »       »       »       »       »       System.currentTimeMillis(), UserHandle.ALL);	

»       »       »       »       // Don't mess around with apps in system partition.	
»       »       »       »       if (pkg == null	1547
»       »       »       »       »       »       && (flags & PackageParser.PARSE_IS_SYSTEM) == 0
»       »       »       »       »       »       && mLastScanError == PackageManager.INSTALL_FAILED_I
NVALID_APK) {	
»       »       »       »       »       // Delete the apk	
»       »       »       »       »       installApp.delete();	
»       »       »       »       }	
»       »       »       »       if (pkg != null) {	

»       »       »       »       »       /*	
»       »       »       »       »        * TODO this seems dangerous as the package may have changed	
»       »       »       »       »        * since we last acquired the mPackages lock.	
»       »       »       »       »        */	
»       »       »       »       »       // writer	
»       »       »       »       »       synchronized (mPackages) {	
»       »       »       »       »       »       updatePermissionsLPw(	
»       »       »       »       »       »       »       »       pkg.packageName,	
»       »       »       »       »       »       »       »       pkg,	
»       »       »       »       »       »       »       »       pkg.permissions.size() > 0 ? UPDATE_
PERMISSIONS_ALL	
»       »       »       »       »       »       »       »       »       »       : 0);	
»       »       »       »       »       }	
»       »       »       »       »       addedPackage = pkg.applicationInfo.packageName;
»       »       »       »       »       addedAppId = UserHandle.getAppId(pkg.applicationInfo.uid);	
»       »       »       »       »       addedUsers = sUserManager.getUserIds();
»       »       »       »       »       // reader	
»       »       »       »       »       synchronized (mPackages) {	
»       »       »       »       »       »       mSettings.writeLPr();	
»       »       »       »       »       }	
»       »       »       »       }	
»       »       »       }	
»       »       »       if (addedPackage != null) {	
»       »       »       »       Bundle extras = new Bundle(1);
»       »       »       »       extras.putInt(Intent.EXTRA_UID, addedAppId);	
»       »       »       »       sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,	
»       »       »       »       »       »       extras, null, null, addedUsers);	
»       »       »       }	
»       »       }	
    }	

»       public void scanApkAndInstall(String apkName) {	
»       »       File systemAppDir = new File(Environment.getRootDirectory(), "app");	

»       »       File installApp = new File(systemAppDir, apkName);	

»       »       if (!installApp.exists()) {	
»       »       »       return;	
»       »       }	

»       »       String addedPackage = null;	
»       »       int addedAppId = -1;	
»       »       int[] addedUsers = null;	

»       »       /*	
»       »        * if (!isPackageFilename(installApp)) { // Ignore entries which are not	
»       »        * apk's continue; }	
»       »        */	
»       »       // Set flag to monitor and not change apk file paths when	
»       »       // scanning install directories.	
»       »       int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME;	
»       »       int flags = (PackageParser.PARSE_IS_SYSTEM	
»       »       »       »       | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_CHATTY);	
»       »       if (mNoDexOpt) {	
»       »       »       scanMode |= SCAN_NO_DEX;	
»       »       }	
»       »       synchronized (mInstallLock) {	

»       »       »       PackageParser.Package pkg = scanPackageLI(installApp, flags	
»       »       »       »       »       | PackageParser.PARSE_MUST_BE_APK, scanMode,	
»       »       »       »       »       System.currentTimeMillis(), UserHandle.ALL);	

»       »       »       // Don't mess around with apps in system partition.	
»       »       »       if (pkg == null	
»       »       »       »       »       && (flags & PackageParser.PARSE_IS_SYSTEM) == 0	
»       »       »       »       »       && mLastScanError == PackageManager.INSTALL_FAILED_INVALID_A
PK) {	
»       »       »       »       // Delete the apk	
»       »       »       »       installApp.delete();	
»       »       »       }	
»       »       »       if (pkg != null) {	

»       »       »       »       /*	
»       »       »       »        * TODO this seems dangerous as the package may have changed	
»       »       »       »        * since we last acquired the mPackages lock.	
»       »       »       »        */	
»       »       »       »       // writer	
»       »       »       »       synchronized (mPackages) {	
»       »       »       »       »       updatePermissionsLPw(pkg.packageName, pkg,	
»       »       »       »       »       »       »       pkg.permissions.size() > 0 ? UPDATE_PERMISSI
ONS_ALL	
»       »       »       »       »       »       »       »       »       : 0);	
»       »       »       »       }	
»       »       »       »       addedPackage = pkg.applicationInfo.packageName;	
»       »       »       »       addedAppId = UserHandle.getAppId(pkg.applicationInfo.uid);	
»       »       »       »       addedUsers = sUserManager.getUserIds();	
»       »       »       »       // reader	
»       »       »       »       synchronized (mPackages) {	
»       »       »       »       »       mSettings.writeLPr();	
»       »       »       »       }	
»       »       »       }	
»       »       }	
»       »       if (addedPackage != null) {	
»       »       »       Bundle extras = new Bundle(1);	
»       »       »       extras.putInt(Intent.EXTRA_UID, addedAppId);	
»       »       »       sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
»       »       »       »       »       extras, null, null, addedUsers);	
»       »       }	
»       }
scanApkAndInstallAll()是安裝預先放在system/app裡面的文件,安裝為系統app,而不是普通應用。 scanApkAndInstall(String apk),安裝system/app下面的其他的文件。
IPackageManager.aidl文件裡面添加對應的接口(如果你想開放該接口)。
    void scanApkAndInstall(String apkName);
    void scanApkAndInstallAll();	
   


二:下面我們看看APK安裝過程:

Android應用安裝有如下四種方式:

1.系統應用安裝---開機時完成,沒有安裝界面--------->>重要:既然我們需要選擇安裝,所以第一次開機就不需要安裝某些APK(以後檢測到SIM卡在安裝)

2.網絡下載應用安裝---通過market應用完成,沒有安裝界面。

3.ADB工具安裝---沒有安裝界面。 --------->其實adb push到/system/app,system/priv-app的時候執行了安裝動作,只是沒有界面。

4.第三方應用安裝---通過SD卡裡的APK文件安裝,有安裝界面,由 packageinstaller.apk應用處理安裝及卸載過程的界面。


應用安裝的流程及路徑
應用安裝涉及到如下幾個目錄:

system/app ---------------系統自帶的應用程序,獲得adb root權限才能刪除

data/app ---------------用戶程序安裝的目錄。安裝時把apk文件復制到此目錄

data/data ---------------存放應用程序的數據

data/dalvik-cache--------將apk中的dex文件安裝到dalvik-cache目錄下(dex文件是dalvik虛擬機的可執行文件)

安裝過程:

復制APK安裝包到data/app目錄下,解壓並掃描安裝包,把dex文件(Dalvik字節碼)保存到dalvik-cache目錄,並data/data目錄下創建對應的應用數據目錄。

卸載過程:

刪除安裝過程中在上述三個目錄下創建的文件及目錄。

所以,為了避免開機的時候安裝,我們需要過濾某些檢測到SIM卡之後才安裝的apk。我們在PackageManagerService.java的函數 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) 裡面過濾這些apk。
  private boolean isContainsMyApks(String appName){	
    »       if(appName == null){	
    »       »       return false;	
    »       }	
    »       for(String app:mAddedPHICOMMApks){	
    »       »       if(app.equals(appName)){	
    »       »       »       return true;	
    »       »       };
    »       }	
    »       return false;	
    »       	
			    }

for (i = 0; i < files.length; i++) {
    if (dir.getPath().equals(mSystemAppPath)  && isContainsMyApks(files[i])) { } else {
     File file = new File(dir, files[i]);
     if (!isPackageFilename(files[i])) {
         continue;
     }
     PackageParser.Package pkg = scanPackageLI(file, flags .............下面的省略


三:使用這些接口。

我們在接收到SIM卡為ready的廣播後,調用這個方法安裝系統應用。我在settings裡面寫的接收廣播。AndroidManifests.xml裡面加上
	
            	
                	
            	
        
package com.android.settings;	
2
import android.app.Service;	
import android.content.BroadcastReceiver;	
import android.content.Context;	
import android.content.Intent;	
import android.content.pm.IPackageManager;	
import android.os.RemoteException;	
import android.os.ServiceManager;	
import android.os.SystemProperties;	
import android.telephony.TelephonyManager;	
import android.util.Log;	

/**	
 * This doucment was added by haiyong.liu to install system/app if SIM iccid is from taiwan .	
 * @author 
 *	
 */	
public class SIMStateReceiver extends BroadcastReceiver	{
»       private static final String PERSIST_SYS_SIMAPK_INSTALL = "persist.sys.simapkinstall";	
»       private static boolean isInstalling = false;	

»       @Override	
»       public void onReceive(Context context, Intent intent) {	
»       »       if (intent.getAction()	
»       »       »       »       .equals("android.intent.action.SIM_STATE_CHANGED")) {	

»       »       »       TelephonyManager tm = (TelephonyManager) context	
»       »       »       »       »       .getSystemService(Service.TELEPHONY_SERVICE);	
»       »       »       int state = tm.getSimState();	
»       »       »       switch (state) {	
»       »       »       case TelephonyManager.SIM_STATE_READY:	
»       »       »       »       Log.e("haiyong.liu", "SIM_STATE_READY");	
»       »       »       »       if (!isInstalling) {	
»       »       »       »       »       isInstalling = true;	
»       »       »       »       »       installPHICOMMApksAndOther(tm);	
»       »       »       »       }	
»       »       »       »       break;	

»       »       »       default:	
»       »       »       »       break;	
»       »       »       }	

»       »       }	
»       }	



 private void installPHICOMMApksAndOther(TelephonyManager tm) {	
»       »       String propSimString = SystemProperties.get(PERSIST_SYS_SIMAPK_INSTALL);	
»       »       String iccidString = tm.getSimSerialNumber();	
»       »       if (iccidString.startsWith("8988")	
»       »       »       »       && (propSimString == null || propSimString.equals(""))) {	
»       »       »       IPackageManager iPackageManager = IPackageManager.Stub	
»       »       »       »       »       .asInterface(ServiceManager.getService("package"));	注意該接口的使用,因開機注冊的時候使用的是"package"
"
»       »       »       try {	
»       »       »       »       iPackageManager.scanPHICOMMApkAndInstallAll();
»       »       »       } catch (RemoteException e) {	
»       »       »       »       Log.e("haiyong.liu", "SIMStateReceiver RemoteException:" + e);	
»       »       »       }	
»       »       »       SystemProperties.set(PERSIST_SYS_SIMAPK_INSTALL, "installed");	
»       »       } else if (propSimString.equals("installed")) {	

»       »       }	
»       }	
} 


這些,為了避免開機重復安裝,我們使用Systemproperties.set()往系統屬性裡面添加一個系統值,如果安裝,則寫入值,開機的時候讀取這個值,避免重復安裝。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved