码迷,mamicode.com
首页 > 其他好文 > 详细

根据SIM卡安装系统应用

时间:2015-01-07 14:57:01      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:安装系统应用   aidl   系统服务   systemproperties   

                           根据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里面加上
<receiver android:name=".SIMStateReceiver">	
            <intent-filter>	
                <action android:name="android.intent.action.SIM_STATE_CHANGED" />	
            </intent-filter>	
        </receiver>
    
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()往系统属性里面添加一个系统值,如果安装,则写入值,开机的时候读取这个值,避免重复安装。

根据SIM卡安装系统应用

标签:安装系统应用   aidl   系统服务   systemproperties   

原文地址:http://blog.csdn.net/liu8497/article/details/42488611

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!