android 如何在手机第一次开机的时候,把用户放在外置SD卡上的APK自动安装到手机的存储卡。

时间:2020-11-25 00:50:30
1.    将APK放到SD卡上某个目录,如apks_preInstall目录.
(对那些有在AndroidManifest.xml中声明了存储路径是internalOnly的apk,不建议使用这种安装方法)
2.    在第一次开机的时候,等sd卡mount上来,去读取这个目录安装APK
 blog.csdn.net/sergeycao
实现代码:
1.  修改\packages\apps\PackageInstaller\AndroidManifest.xml
        <!-- 增加一个receiver -->
        <receiver android:name=".FirstInstallReceiver">
<intent-filter>
 <action android:name="android.intent.action.MEDIA_MOUNTED_FOR_FIRTIME" />
</intent-filter>
</receiver>
       <!--end   -->
 
2. \packages\apps\PackageInstaller\src\com\android\packageinstaller下增加FirstInstallReceiver.java文件,用于接收第一次SD卡mount上来的广播,以便安装APK,内容如下:
package com.android.packageinstaller;
 
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.util.Log;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import java.io.File;
import android.net.Uri;
 
public class FirstInstallReceiver extends BroadcastReceiver{
         private final String TAG="FirstInstallReceiver";
         private String action = "android.intent.action.MEDIA_MOUNTED_FOR_FIRTIME";
 
               /*下面变量apksPath是外置sd卡上的某个路径, 要修改默认预置的apk存放路径,请修改这个路径。
                 GB版本、GB2、ICS单卡项目:sd卡路径是/mnt/sdcard
                 GB2双卡项目:  默认外置sd卡路径是/mnt/sdcard/sdcard2, 如打开SDSwap Feature,外置SD卡路径则是:/mnt/sdcard
                 ICS双卡项目: 默认外置SD卡路径是/mnt/sdcard2, 如打开SDSwap Feature,外置SD卡路径则是:/mnt/sdcard
                 因此修改要针对不同情况,首先需要确认外置SD卡的路径。
              */
  blog.csdn.net/sergeycao
         private String apksPath = "/mnt/sdcard/apks_preInstall";    //这个例子假设外置SD卡路径为/mnt/sdcard ///////////////////////
         @Override
         public void onReceive(Context context, Intent intent) {
                   Log.d(TAG,"onReceive:"+intent);
                   new Thread()
                   {
                         public void run() {
                         try
                             {
                            File apksFile = new File(apksPath);
                            PackageManager pm = context.getPackageManager();
                            int installFlags = 0;
                            installFlags |= PackageManager.INSTALL_EXTERNAL;
                            if(apksFile.exists())  {
                                 File[] files = apksFile.listFiles();
                                 for(File f1:files)
  {
                                          String filename = f1.getName();
                                          String type = filename.substring(filename.lastIndexOf(".")+1);
                                          if(type!=null&&type.equals("apk"))
                                        {
                                             Uri mPackageURI = Uri.fromFile(f1);
                                                    pm.installPackage(mPackageURI, null, installFlags, null);
                                         }
                                     }
                            }
                              }
                   catch(Exception e)
                       {
                             Log.d(TAG,"onReceive:install failed:e:"+e);
                        }
                   }
                  }.start();
          }
}
 
3. 修改mountservice.java, 用于发送第一次开机sd卡mount上来的广播
private void notifyVolumeStateChange(String label, String path, int oldState, int newState) { .....
 else if (newState == VolumeState.Mounted) {
         //mtk added
String isFirstBoot = SystemProperties.get("persist.sys.mount_is_first");
if(isFirstBoot == null || isFirstBoot.equals(""))
          {     
Slog.i(TAG, "first boot");
SystemProperties.set("persist.sys.mount_is_first", "DONE");
             Intent firIntent = new Intent("android.intent.action.MEDIA_MOUNTED_FOR_FIRTIME");
            mContext.sendStickyBroadcast(firIntent);
          }
         //mtk added
          
 if (DEBUG_EVENTS)  Slog.i(TAG, "updating volume state mounted");
              updatePublicVolumeState(path, Environment.MEDIA_MOUNTED);
.....