开机后台自动安装apk

设备厂商总是会预装很多apk(更奇葩的居然还有病毒,我是不喜欢这种预装的东西,挺讨厌的)

如果把所有apk放到system/app下,也不太现实.比较system分区容量是有限的.

如果把所有apk扔到data/app下.第一次开机时间太久,估计在4-6分钟的样子.显然无法接受.

所以这个安装应运而生,提供了两种方式


1.需要预装的apk都打包到zip文件里

2.需要预装的apk都放到指定文件夹


代码大体结构是这样:


主要安装代码在thread和service里

service里的代码:

public class Ins3rdAppInstallService extends Service {

	private PackageManager pManager = null;
	private IPackageManager ipManager = null;
	private int installLocationInIpm = Ins3rdAppConst.ZERO;
	private Ins3rdAppBinder myBinder = new Ins3rdAppBinder();

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		// pManager.installPackage(arg0, arg1, arg2, arg3);
		return myBinder;

	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		pManager = getPackageManager();
		ipManager = IPackageManager.Stub.asInterface(ServiceManager
				.getService(Ins3rdAppConst.PACKAGE_SERVICE));
		try {
			installLocationInIpm = ipManager.getInstallLocation();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void InstallApkInBackGround(Uri uri, String packagename,
			int location, PackageInstallObserver observer) {
		Log.d(Ins3rdAppConst.LOG_TAG, "install " + uri.toString());

		int flags = Ins3rdAppConst.ZERO;
		flags = ParseInstallLocation(location, flags);

		pManager.installPackage(uri, observer, flags, packagename);
	}

	public void InstallApkInBackGround(Uri uri, String packagename,
			int location, PackageInstallObserverWithDir observer) {
		Log.d(Ins3rdAppConst.LOG_TAG, "install " + uri.toString());

		int flags = Ins3rdAppConst.ZERO;
		flags = ParseInstallLocation(location, flags);

		pManager.installPackage(uri, observer, flags, packagename);
	}
	
	public class Ins3rdAppBinder extends Binder {

		public Ins3rdAppInstallService getService() {
			return Ins3rdAppInstallService.this;
		}
	}

	private int ParseInstallLocation(int locationInPkg, int installflag) {

		switch (locationInPkg) {

		case Ins3rdAppConst.INSTALL_LOCATION_AUTO:
			installflag |= PackageManager.INSTALL_INTERNAL_SD;
			break;

		case Ins3rdAppConst.INSTALL_LOCATION_INTERNAL_ONLY:
			installflag |= PackageManager.INSTALL_INTERNAL;
			break;

		case Ins3rdAppConst.INSTALL_LOCATION_PREFER_EXTERNAL:
			installflag |= PackageManager.INSTALL_INTERNAL_SD;
			break;

		case Ins3rdAppConst.INSTALL_LOCATION_UNSPECIFIED:
			if (installLocationInIpm == PackageHelper.APP_INSTALL_EXTERNAL) {
				installflag |= PackageManager.INSTALL_INTERNAL_SD;
			} else {
				installflag |= PackageManager.INSTALL_INTERNAL;
			}
			break;

		default:
			installflag |= PackageManager.INSTALL_INTERNAL;
			break;

		}

		return installflag;
	}

}

thread里的代码:

public class Ins3rdAppParseThread extends HandlerThread implements Callback {

	private static final int INIT_DATABASE = 1;
	private static final int INSTALL_APK = 2;
	private static final int APK_NOT_INSTALL = 0;
	private static final int APK_HAS_INSTALL = 1;
	private static final String KEY_APK_NAME = "apkname";
	private static final String PACKAGE_NAME = "package";
	private static final String INSTALL_LOCATION = "location";
	private static final String RETRY_TIMES = "retry";
	private static final String END_TAG = "smartictag";
	private static final String UNKOWN_TAG = "unknown";
	private static final int SUCCEEDED = 1;
	private static final int RETRY_INTERVAL = 1;
	private static final int RETRY_MAX_TIMES = 3;
	private static final int COMPLETEPROGRESS = 100;
	// private static final int FAILED = 0;

	private Handler currentHandler;
	private Context mContext;
	private ZipFile tmp;
	private Ins3rdAppDbServer dbServer;
	private Ins3rdAppZipUtil appZipUtil;
	private Ins3rdAppBinder binder;
	private Ins3rdAppInstallService bindService;
	private PackageInstallObserver installObserver;
	private LockObject lock;
	private String apkName;
	private String packageName;
	private int retrytimes;
	private Ins3rdAppNotification notification;
	private int apkcount;
	private int currentprogress;

	private ServiceConnection connection = new ServiceConnection() {

		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			binder = null;
			bindService = null;
		}

		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			binder = (Ins3rdAppBinder) service;
			bindService = binder.getService();

		}

	};

	public class LockObject {

		public void PrintLockLog() {
			Log.d(Ins3rdAppConst.LOG_TAG,
					"Lock the LockObject and installthread wait for notify");
		}

		public void PrintUnlockLog() {
			Log.d(Ins3rdAppConst.LOG_TAG,
					"Unlock the LockObject and installthread resume");
		}
	}

	public class PackageInstallObserver extends IPackageInstallObserver.Stub {

		public void packageInstalled(String packageName, int retCode)
				throws RemoteException {
			// TODO Auto-generated method stub
			Log.d(Ins3rdAppConst.LOG_TAG, "package " + packageName
					+ "install complete and ret " + retCode);
			if (retCode == SUCCEEDED) {
				Log.d(Ins3rdAppConst.LOG_TAG, "package " + packageName
						+ "install success");
				dbServer.update(apkName, APK_HAS_INSTALL);
			} else {
				Log.d(Ins3rdAppConst.LOG_TAG, "package " + packageName
						+ "install failed retry times "
						+ (retrytimes + RETRY_INTERVAL));
				dbServer.update(apkName, APK_NOT_INSTALL, retrytimes
						+ RETRY_INTERVAL);
			}

			appZipUtil.DeleteTmpApkFile(apkName);
			currentprogress += (COMPLETEPROGRESS / apkcount);
			notification.update(currentprogress);
			synchronized (lock) {
				lock.PrintUnlockLog();
				lock.notify();
			}
		}

	}

	public Ins3rdAppParseThread(String name, Context context) {

		super(name);
		this.mContext = context;
		this.lock = new LockObject();
		dbServer = new Ins3rdAppDbServer(this.mContext);
		appZipUtil = new Ins3rdAppZipUtil();
		tmp = appZipUtil.OpenZipFile(Environment
				.getExternalSDStorageDirectory().getPath()
				+ "/"
				+ Ins3rdAppConst.ZIP_NAME);
		if (tmp == null) {
			ExitProcess();
		}
		installObserver = new PackageInstallObserver();
		notification = Ins3rdAppNotification.getInstance(context);

		// TODO Auto-generated constructor stub
	}

	public boolean handleMessage(Message msg) {
		// TODO Auto-generated method stub

		if (currentHandler == null) {
			Log.d(Ins3rdAppConst.LOG_TAG, "ParseThread running");
			currentHandler = new Handler(getLooper(), this);
		}

		switch (msg.what) {

		case INIT_DATABASE:
			InitDataBase();
			break;

		case INSTALL_APK:
			BeginInstallApk();
			break;

		default:
			break;
		}
		return false;
	}

	public void InitDataBase() {

		// File file1 = new File(Environment.getExternalStorageDirectory()
		// .getPath() + "/" + "junfa.apk");
		// ApplicationInfo info = GetApkInfo(file1);
		if (dbServer.queryapk(END_TAG)) {
			Log.d(Ins3rdAppConst.LOG_TAG,
					"all the install.list entry has add into database");
			currentHandler.sendEmptyMessage(INSTALL_APK);
			return;
		}

		appZipUtil.ParseInstallList(appZipUtil.ExactInstallList());
		Log.d(Ins3rdAppConst.LOG_TAG, "keyset " + appZipUtil.apkMap.keySet());
		Iterator<Entry<String, String>> iterator = appZipUtil.apkMap.entrySet()
				.iterator();

		while (iterator.hasNext()) {

			Entry<String, String> entry = iterator.next();
			appZipUtil.apkMap.put(entry.getKey(), UNKOWN_TAG);
			Ins3rdAppItem item = new Ins3rdAppItem(entry.getKey(),
					entry.getValue(), false);
			dbServer.insert(item);
		}

		dbServer.putendtag();
		currentHandler.sendEmptyMessage(INSTALL_APK);
	}

	public void BeginInstallApk() {

		currentThread().setPriority(Process.THREAD_PRIORITY_BACKGROUND);
		currentprogress = Ins3rdAppConst.ZERO;
		Cursor cursor = dbServer.queryinstallstate(APK_NOT_INSTALL);
		Log.d(Ins3rdAppConst.LOG_TAG,
				"now start install in ins3rdappinstallservice");
		apkcount = cursor.getCount();
		if (apkcount != Ins3rdAppConst.ZERO) {
			notification.start();
		}
		File apkfile;
		ApplicationInfo applicationInfo;

		Intent intent = new Intent(mContext, Ins3rdAppInstallService.class);
		mContext.bindService(intent, connection, Service.BIND_AUTO_CREATE);

		while (cursor.moveToNext()) {

			apkName = cursor.getString(cursor.getColumnIndex(KEY_APK_NAME));
			packageName = cursor.getString(cursor.getColumnIndex(PACKAGE_NAME));
			retrytimes = cursor.getShort(cursor.getColumnIndex(RETRY_TIMES));
			int location = cursor.getShort(cursor
					.getColumnIndex(INSTALL_LOCATION));

			if (retrytimes >= RETRY_MAX_TIMES) {
				Log.d(Ins3rdAppConst.LOG_TAG, apkName + " has install "
						+ retrytimes + ", beyond max retry times");
				continue;
			}

			apkfile = appZipUtil.ExtractApk(apkName);

			if (apkfile == null) {
				continue;
			}

			if (packageName.compareTo(UNKOWN_TAG) == 0) {
				applicationInfo = GetApkInfo(apkfile);
				Ins3rdAppItem item = new Ins3rdAppItem(apkName,
						applicationInfo.packageName, false,
						applicationInfo.installLocation);
				location = applicationInfo.installLocation;
				dbServer.update(item);
			}

			if (IsApkInstalled(packageName)) {
				Log.d(Ins3rdAppConst.LOG_TAG, "apk " + apkName + " package "
						+ packageName + " has installed");
			} else {
				bindService.InstallApkInBackGround(Uri.fromFile(apkfile),
						packageName, location, installObserver);
				try {
					synchronized (lock) {
						lock.PrintLockLog();
						lock.wait();
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		if (apkcount != Ins3rdAppConst.ZERO) {
			notification.stop();
		}
		if (bindService != null) {
			mContext.unbindService(connection);
		}
		ExitProcess();
	}

	public ApplicationInfo GetApkInfo(File file) {

		Uri uri = Uri.fromFile(file);
		return Ins3rdAppPackageUtil.getApplicationInfo(uri);
	}

	public Boolean IsApkInstalled(String packageString) {

		PackageManager pm = mContext.getPackageManager();
		try {
			PackageInfo pi = pm.getPackageInfo(packageString,
					PackageManager.GET_UNINSTALLED_PACKAGES);
			if (pi != null) {
				return true;
			}
			return false;
		} catch (NameNotFoundException e) {
			return false;
		}
	}

	public void ExitProcess() {

		Log.d(Ins3rdAppConst.LOG_TAG,
				"Process Kill myslef " + mContext.getPackageName());
		dbServer.closedb();
		Process.killProcess(Process.myPid());
	}
}

与service的交互是通过bind的方式来做的,感觉比onstart方便,好用.

安装线程类里有一个observer的回调

函数里主要处理数据库,做了同步.目的是为了apk能串行化安装.不运行并发.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 在切入后台后会暂停所有正在进行的操作,包括 APK安装过程。因此,如果用户在 APK 安装过程中切入后台,那么 APK 安装过程会被暂停。 如果你想让 APK 在切入后台自动安装,可以考虑使用服务来安装 APK。具体来说,你可以在服务中使用 Intent 来启动系统的安装程序来安装 APK。这样,即使用户切入后台,服务仍然在后台运行,安装程序也会在后台自动安装 APK。 下面是一个示例代码,用于在服务中安装 APK: ``` public class ApkInstallService extends Service { private String mApkFilePath; @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { mApkFilePath = intent.getStringExtra("apk_file_path"); if (mApkFilePath != null) { installApk(); } } return super.onStartCommand(intent, flags, startId); } private void installApk() { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File(mApkFilePath)), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } ``` 在你的 Activity 中,你可以通过以下代码来启动服务: ``` Intent intent = new Intent(this, ApkInstallService.class); intent.putExtra("apk_file_path", "your_apk_file_path"); startService(intent); ``` 这样,即使用户在 APK 安装过程中切入后台,服务仍然会在后台运行,安装程序也会在后台自动安装 APK

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值