package com.smartisanos.sidebar.util; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import com.smartisanos.sidebar.R; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.provider.BaseColumns; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; public class AppManager extends DataManager { private volatile static AppManager sInstance; public static AppManager getInstance(Context context) { if (sInstance == null) { synchronized (AppManager.class) { if (sInstance == null) { sInstance = new AppManager(context); } } } return sInstance; } private static final List<String> sAutoAddPackageList; static { // package sAutoAddPackageList = new ArrayList<String>(); sAutoAddPackageList.add("com.tencent.mm"); sAutoAddPackageList.add("com.sina.weibo"); sAutoAddPackageList.add("com.tencent.mobileqq"); sAutoAddPackageList.add("com.tencent.mobileqqi"); sAutoAddPackageList.add("com.smartisanos.notes"); sAutoAddPackageList.add("com.android.email"); sAutoAddPackageList.add("com.android.calendar"); sAutoAddPackageList.add("com.taobao.taobao"); sAutoAddPackageList.add("com.evernote"); sAutoAddPackageList.add("com.wunderkinder.wunderlistandroid"); sAutoAddPackageList.add("com.alibaba.android.rimet"); sAutoAddPackageList.add("com.meitu.meiyancamera"); sAutoAddPackageList.add("com.netease.cloudmusic"); sAutoAddPackageList.add("com.eg.android.AlipayGphone"); sAutoAddPackageList.add("com.zhihu.android"); sAutoAddPackageList.add("com.zhihu.daily.android"); sAutoAddPackageList.add("com.youku.phone"); sAutoAddPackageList.add("com.sdu.didi.psnger"); sAutoAddPackageList.add("com.ubercab"); sAutoAddPackageList.add("com.homelink.android"); sAutoAddPackageList.add("com.baidu.BaiduMap"); sAutoAddPackageList.add("com.autonavi.minimap"); sAutoAddPackageList.add("com.smartisanos.appstore"); sAutoAddPackageList.add("com.neuralprisma"); sAutoAddPackageList.add("com.twitter.android"); sAutoAddPackageList.add("com.instagram.android"); sAutoAddPackageList.add("com.whatsapp"); sAutoAddPackageList.add("com.facebook.katana"); sAutoAddPackageList.add("com.google.android.youtube"); sAutoAddPackageList.add("com.android.chrome"); sAutoAddPackageList.add("com.android.browser"); sAutoAddPackageList.add("com.android.vending"); } private static final int sMaxNumber = 20; private Context mContext; private Handler mHandler; private List<AppItem> mAddedAppItems = new ArrayList<AppItem>(); private AppDatabase mDatabase; private Toast mLimitToast; private AppManager(Context context) { mContext = context; mDatabase = new AppDatabase(mContext); HandlerThread thread = new HandlerThread(ResolveInfoManager.class.getName()); thread.start(); mHandler = new AppManagerHandler(thread.getLooper()); mHandler.obtainMessage(MSG_INIT_LIST).sendToTarget(); } public boolean addAppItem(AppItem item) { return addAppItemInternal(item, true); } private boolean addAppItemInternal(AppItem item, boolean showToast) { synchronized (mAddedAppItems) { if (mAddedAppItems.size() >= sMaxNumber) { if (showToast) { showToastDueToLimit(); } return false; } for (int i = 0; i < mAddedAppItems.size(); ++i) { if (mAddedAppItems.get(i).equals(item)) { return true; } } if (mAddedAppItems.size() == 0) { item.setIndex(0); } else { int maxIndex = mAddedAppItems.get(0).getIndex(); for (int i = 1; i < mAddedAppItems.size(); ++i) { if (mAddedAppItems.get(i).getIndex() > maxIndex) { maxIndex = mAddedAppItems.get(i).getIndex(); } } item.setIndex(maxIndex + 1); } item.newAdded = true; mAddedAppItems.add(0, item); } mHandler.obtainMessage(MSG_SAVE, item).sendToTarget(); notifyListener(); return true; } public void removeAppItem(AppItem item) { synchronized (mAddedAppItems) { for (int i = 0; i < mAddedAppItems.size(); ++i) { if (mAddedAppItems.get(i).equals(item)) { mAddedAppItems.remove(i).newRemoved = true; notifyListener(); mHandler.obtainMessage(MSG_DELETE, item).sendToTarget(); return; } } } } public boolean isAppItemAdded(AppItem ai) { synchronized (mAddedAppItems) { for (AppItem addedItem : mAddedAppItems) { if (addedItem == ai || addedItem.equals(ai)) { return true; } } } return false; } public List<AppItem> getAddedAppItem() { List<AppItem> ret = new ArrayList<AppItem>(); synchronized (mAddedAppItems) { ret.addAll(mAddedAppItems); } return ret; } public List<AppItem> getUnAddedAppItem() { List<ResolveInfo> allInfos = Utils.getAllAppsInfo(mContext); List<AppItem> list = new ArrayList<AppItem>(); synchronized (mAddedAppItems) { for (ResolveInfo ri : allInfos) { if (mContext.getPackageName().equals( ri.activityInfo.packageName)) { // pass sidebar ourself continue; } AppItem item = new AppItem(mContext, ri); boolean added = false; for (AppItem addedItem : mAddedAppItems) { if (addedItem.equals(item)) { added = true; break; } } if (!added) { list.add(new AppItem(mContext, ri)); } } } return list; } public void updateOrder() { synchronized (mAddedAppItems) { Collections.sort(mAddedAppItems, new AppItem.IndexComparator()); } notifyListener(); mHandler.obtainMessage(MSG_SAVE_ORDER).sendToTarget(); } public void onPackageRemoved(String packageName){ synchronized (mAddedAppItems) { for (int i = 0; i < mAddedAppItems.size(); ++i) { if (mAddedAppItems.get(i).getPackageName().equals(packageName)) { mHandler.obtainMessage(MSG_DELETE, mAddedAppItems.get(i)).sendToTarget(); mAddedAppItems.remove(i); i--; } } } notifyListener(); } public void onPackageAdded(String packageName) { if (sAutoAddPackageList.contains(packageName)) { addPackage(packageName); } } public void onPackageUpdate(String packageName) { if(!TextUtils.isEmpty(packageName)) { boolean changed = false; synchronized(mAddedAppItems) { for(int i = 0; i < mAddedAppItems.size(); ++ i) { AppItem ai = mAddedAppItems.get(i); if(packageName.equals(ai.getPackageName())) { if(!ai.isValid()) { mHandler.obtainMessage(MSG_DELETE, ai).sendToTarget(); mAddedAppItems.remove(i); i--;; changed = true; } } } } if(changed) { // we remove the old one, now add the new one .. addPackage(packageName); notifyListener(); } } } public void onIconChanged(Set<String> packages) { synchronized (mAddedAppItems) { for (AppItem ai : mAddedAppItems) { if (packages.contains(ai.getPackageName())) { ai.onIconChanged(); } } } notifyListener(); } private void showToastDueToLimit() { if (mLimitToast != null) { mLimitToast.cancel(); } mLimitToast = Toast.makeText(mContext, mContext.getResources() .getString(R.string.add_at_most_app_number, sMaxNumber), Toast.LENGTH_SHORT); mLimitToast.show(); } private void initList() { List<AppItem> list = mDatabase.getAddedAppItem(); synchronized(mAddedAppItems) { mAddedAppItems.clear(); mAddedAppItems.addAll(list); } notifyListener(); } private void addPackage(String packageName) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setPackage(packageName); List<ResolveInfo> ris = mContext.getPackageManager().queryIntentActivities(intent, 0); if (ris != null && ris.size() > 0) { for (ResolveInfo ri : ris) { addAppItemInternal(new AppItem(mContext, ri), false); } } } private static final int MSG_INIT_LIST = 0; private static final int MSG_SAVE = 1; private static final int MSG_DELETE = 2; private static final int MSG_SAVE_ORDER = 3; private class AppManagerHandler extends Handler { public AppManagerHandler(Looper looper) { super(looper, null, false); } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_INIT_LIST: initList(); break; case MSG_SAVE: mDatabase.saveToDatabase((AppItem) msg.obj); break; case MSG_DELETE: mDatabase.deleteFromDatabase((AppItem) msg.obj); break; case MSG_SAVE_ORDER: mDatabase.saveOrderForList(getAddedAppItem()); break; } } } private final class AppDatabase extends SQLiteOpenHelper { private static final int DB_VERSION = 1; private static final String DB_NAME = "apps"; //tables private static final String TABLE_APPS = "apps"; class AppsColumns implements BaseColumns{ static final String PACKAGE_NAME = "packagename"; static final String COMPONENT_NAME = "componentname"; static final String WEIGHT = "weight"; } public AppDatabase(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_APPS + " ( _id INTEGER PRIMARY KEY AUTOINCREMENT," + "packagename TEXT," + "componentname TEXT, " + "weight INTEGER" + ");"); // pre install package List<AppItem> appList = new ArrayList<AppItem>(); for (String packageName : sAutoAddPackageList) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setPackage(packageName); List<ResolveInfo> ris = mContext.getPackageManager().queryIntentActivities(intent, 0); if (ris != null && ris.size() > 0) { for (ResolveInfo ri : ris) { appList.add(new AppItem(mContext, ri)); } } } for (int i = 0; i < appList.size(); ++i) { appList.get(i).setIndex(appList.size() - 1 - i); } for (AppItem ai : appList) { ContentValues cv = new ContentValues(); cv.put(AppsColumns.PACKAGE_NAME, ai.getPackageName()); cv.put(AppsColumns.COMPONENT_NAME, ai.getComponentName()); cv.put(AppsColumns.WEIGHT, ai.getIndex()); db.insert(TABLE_APPS, null, cv); } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // NA } public List<AppItem> getAddedAppItem() { List<AppItem> list = new ArrayList<AppItem>(); Cursor cursor = null; try { cursor = getReadableDatabase().query(TABLE_APPS, null,null, null, null, null, null); if (cursor != null && cursor.moveToFirst()) { do { String pkgName = cursor.getString(cursor.getColumnIndex(AppsColumns.PACKAGE_NAME)); String componentName = cursor.getString(cursor.getColumnIndex(AppsColumns.COMPONENT_NAME)); int weight = cursor.getInt(cursor.getColumnIndex(AppsColumns.WEIGHT)); AppItem ai = AppItem.fromData(mContext, pkgName, componentName); if (ai != null) { ai.setIndex(weight); list.add(ai); } else { getWritableDatabase().delete(TABLE_APPS, "packagename=? and componentname=?", new String[] { pkgName, componentName }); } } while (cursor.moveToNext()); } } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) { cursor.close(); } } Collections.sort(list, new AppItem.IndexComparator()); return list; } private int getId(AppItem item) { Cursor cursor = null; try { cursor = getReadableDatabase().query( TABLE_APPS, null, AppsColumns.PACKAGE_NAME + "=? and " + AppsColumns.COMPONENT_NAME + "=?", new String[] { item.getPackageName(), item.getComponentName() }, null, null, null); if (cursor.moveToFirst()) { return cursor.getInt(cursor.getColumnIndex(AppsColumns._ID)); } } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) { cursor.close(); } } return 0; } public void deleteFromDatabase(AppItem item) { int id = getId(item); if (id != 0) { getWritableDatabase().delete(TABLE_APPS, AppsColumns._ID + "=?", new String[] { id + "" }); } } public void saveToDatabase(AppItem item) { ContentValues cv = new ContentValues(); cv.put(AppsColumns.PACKAGE_NAME, item.getPackageName()); cv.put(AppsColumns.COMPONENT_NAME, item.getComponentName()); cv.put(AppsColumns.WEIGHT, item.getIndex()); getWritableDatabase().insert(TABLE_APPS, null, cv); } public void saveOrderForList(List<AppItem> list) { SQLiteDatabase db = getWritableDatabase(); db.beginTransaction(); try { for (AppItem ai : list) { int id = getId(ai); if (id != 0) { ContentValues cv = new ContentValues(); cv.put(AppsColumns.PACKAGE_NAME, ai.getPackageName()); cv.put(AppsColumns.COMPONENT_NAME,ai.getComponentName()); cv.put(AppsColumns.WEIGHT, ai.getIndex()); db.update(TABLE_APPS, cv, AppsColumns._ID + "=?",new String[] { id + "" }); } } db.setTransactionSuccessful(); } catch (Exception e) { e.printStackTrace(); } finally { if (db != null) { db.endTransaction(); db.close(); } } } } }