package com.smart.store.util;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import java.io.File;
import java.util.LinkedList;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.PackageParser;
/**
* this class for install apk on background , and install one by one in queue,
* easy use by addInstallApk(...) function
*/
public class InstallApkQueue {
public final static String Tag = InstallApkQueue.class.getName();
public static InstallApkQueue getInstance(Context ctx) {
if (null == mSelf) {
mSelf = new InstallApkQueue(ctx);
}
return mSelf;
}
public static PackageParser.Package getPackageInfo(Uri packageURI) {
final String archiveFilePath = packageURI.getPath();
PackageParser packageParser = new PackageParser(archiveFilePath);
File sourceFile = new File(archiveFilePath);
DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
PackageParser.Package pkg = packageParser.parsePackage(sourceFile,
archiveFilePath, metrics, 0);
// Nuke the parser reference.
packageParser = null;
return pkg;
}
/**
* maybe not init this object before
*/
public static boolean addInstallApk(Uri packageUri,
IInstallCallBack callBack) {
if (null == mSelf) {
return false;
} else {
mSelf.addInstallApkObj(packageUri,getPackageInfo(packageUri).applicationInfo.packageName, callBack);
return true;
}
}
/**
* give Context when not init this object before will init this
*/
public static void addInstallApk(Context ctx, Uri packageUri,
IInstallCallBack callBack) {
if (null == mSelf) {
getInstance(ctx);
}
mSelf.addInstallApkObj(packageUri, getPackageInfo(packageUri).applicationInfo.packageName, callBack);
}
private static InstallApkQueue mSelf = null;
private InstallApkQueue(Context ctx) {
mContext = ctx;
init();
}
private Context mContext;
private Handler mHandler;
private ThreadWorker mThreadWorker;
private void init() {
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case INSTALL_COMPLETE:
if (msg.arg1 == PackageManager.INSTALL_SUCCEEDED) {
mCurrentObj._callBack.callBack(mCurrentObj._packageUri,
mCurrentObj._packageName,
PackageInstallResult.SUCC);
} else if (msg.arg1 == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE) {
mCurrentObj._callBack.callBack(mCurrentObj._packageUri,
mCurrentObj._packageName,
PackageInstallResult.FAIL);
} else {
mCurrentObj._callBack.callBack(mCurrentObj._packageUri,
mCurrentObj._packageName,
PackageInstallResult.OTHER);
}
unlockinstall();
break;
default:
break;
}
}
};
mQueueObjList = new LinkedList<QueueObj>();
mThreadWorker = new ThreadWorker();
mThreadWorker.start();
}
private static class QueueObj {
public QueueObj(Uri packageUri, String packageName,
IInstallCallBack callBack) {
_packageName = packageName;
_callBack = callBack;
_packageUri = packageUri;
}
Uri _packageUri;
String _packageName;
IInstallCallBack _callBack;
}
private LinkedList<QueueObj> mQueueObjList;
public boolean addInstallApkObj(Uri packageUri, String packageName,
IInstallCallBack callBack) {
boolean ret = true;
synchronized (mQueueObjList) {
for (int i = 0; i < mQueueObjList.size(); i++) {
if (mQueueObjList.get(i)._packageName
.equalsIgnoreCase(packageName)
|| mQueueObjList.get(i)._packageUri.toString()
.equalsIgnoreCase(packageUri.toString())) {
ret = false;
break;
}
}
if (ret) {
mQueueObjList.add(new QueueObj(packageUri, packageName,
callBack));
mQueueObjList.notify();
}
}
return ret;
}
private final int INSTALL_COMPLETE = 1;
class PackageInstallObserver extends IPackageInstallObserver.Stub {
public void packageInstalled(String packageName, int returnCode) {
Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);
msg.arg1 = returnCode;
mHandler.sendMessage(msg);
}
}
private void dealObj(QueueObj obj) {
int installFlags = 0;
PackageManager pm = mContext.getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(obj._packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if (pi != null) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
}
} catch (NameNotFoundException e) {
}
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
}
PackageInstallObserver observer = new PackageInstallObserver();
pm.installPackage(obj._packageUri, observer, installFlags,
"com.smart.store");
}
/**
* flag ,can't use by other function
*/
private boolean isContinueInstall = true;
/**
* flag , can't use by other function
*/
private QueueObj mCurrentObj = null;
private void lockinstall(QueueObj obj) {
isContinueInstall = false;
mCurrentObj = obj;
}
private void unlockinstall() {
synchronized (mQueueObjList) {
isContinueInstall = false;
mCurrentObj = null;
mQueueObjList.notify();
}
}
private boolean islockinstall() {
return isContinueInstall == true ? false : true;
}
private class ThreadWorker extends Thread {
public void run() {
// android.os.Process
// .setThreadPriority(android.os.Process.THREAD_PRIORITY_LOWEST);
QueueObj obj = null;
while (true) {
synchronized (mQueueObjList) {
while (mQueueObjList.isEmpty() || islockinstall()) {
try {
obj = null;
mQueueObjList.wait();
} catch (InterruptedException ignored) {
}
}
obj = mQueueObjList.removeFirst();
}
if (null != obj) {
try {
lockinstall(obj);
dealObj(obj);
} catch (RuntimeException e) {
Log.e(Tag, "err:"+e.toString());
unlockinstall();
}
}
}
}
}
public static enum PackageInstallResult {
SUCC, FAIL, OTHER,
};
public static interface IInstallCallBack {
public void callBack(Uri packageUri, String packageName,PackageInstallResult arge);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
前往页