将原生的Launcher修改成类似MiUI的Launcher
2015-09-23 14:14
615 查看
将原生的Launcher修改成类似MiUi样式的Launcher
上面这个是原生的
上面这个是我们要修改的成果
原生的Launcher已4.2.2版本为base,需要更改一下的几点:
1. Workspace
原生:workspace是存放的App的快捷方式(shortcut)
新生:workspace显示了已经安装的App
2. App的删除方式
原生:在workspace中按住App的快捷方式后,出现Remove的标识,将快捷方式移动到Remove是删除App的快捷方式,并不会卸载此App
新生:在workspace按住App的快捷方式后,出现删除的提示,将App移动到删除提示后,是将此App卸载。
3. 在worksapce中默认是加载的快捷方式,但是原生的App并不一定都是快捷方式,所以需要在Launcher第一次运行的时候,将AllApps加载为Shortcut
那么开始改吧:
1.首先在LauncherModel.java文件中添加一个新类AlreadyInDesktopApps,记录哪些App已经在Desktop上,以及哪个screen已经存在Shortcut
public class AlreadyInDesktopApps { List<Integer> screenList = null; List<ShortcutFlag> shortcutFlagList = null; AlreadyInDesktopApp() { screenList = new ArrayList<Integer>(); shortcutFlagList = new ArrayList<ShortcutFlag>(); } public void addScreen(int screen) { if (!isExistedScreen(screen)) { screenList.add(screen); } } public List<Integer> getScreens() { return screenList; } public void addShortcutFlag(String packegName, String componentName) { ShortcutFlag shortcutFlag = new ShortcutFlag(packegName, componentName); if (!isExistedShortcutFlag(shortcutFlag)) { shortcutFlagList.add(shortcutFlag); } } public boolean isExistedScreen(int screen) { return screenList.contains(screen); } public boolean isExistedShortcutFlag(ShortcutFlag shortcutFlag) { return shortcutFlagList.contains(shortcutFlag); } public boolean isExistedShortcutFlag(String packegName, String componentName) { ShortcutFlag shortcutFlag = new ShortcutFlag(packegName, componentName); return shortcutFlagList.contains(shortcutFlag); } private class ShortcutFlag { String packegName; String componentName; public ShortcutFlag(String packegName, String componentName) { this.packegName = packegName; this.componentName = componentName; } @Override public boolean equals(Object o) { if (o instanceof ShortcutFlag) { ShortcutFlag appFlag = (ShortcutFlag) o; if (appFlag.packegName.equals(packegName) && appFlag.componentName.equals(componentName)) { return true; } } return false; } } }
在LauncherModel.java中添加函数loadNotInDesktopAllAppsByBatch
private void loadNotInDesktopAllAppsByBatch() { final Callbacks oldCallbacks = mCallbacks.get(); if (oldCallbacks == null) { return; } final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); final PackageManager packageManager = mContext.getPackageManager(); List<ResolveInfo> apps = null; int N = Integer.MAX_VALUE; int cellCountX = LauncherModel.getCellCountX(); int cellCountY = LauncherModel.getCellCountY(); int maxItemNumOnePage = cellCountX * cellCountY; int itemTotalNum = 0; List<Integer> blankScreens = getBlankScreens(); int i = 0; int batchSize = -1; while (i < N && !mStopped) { if (i == 0) { mBgAllAppsList.clear(); apps = packageManager.queryIntentActivities(mainIntent, 0); if (apps == null) { return; } N = apps.size(); if (N == 0) { return; } if (mBatchSize == 0) { batchSize = maxItemNumOnePage; } else { batchSize = mBatchSize; } Collections.sort(apps, new LauncherModel.ShortcutNameComparator( packageManager, mLabelCache)); } for (int j = 0; i < N && j < batchSi 4000 ze;) { ApplicationInfo appInfo = new ApplicationInfo( packageManager, apps.get(i), mIconCache, mLabelCache); mBgAllAppsList.add(appInfo); if (!mAlreadyInDesktopApp.isExistedShortcutFlag( appInfo.getPackageName(), appInfo.componentName.getClassName())) { mBgAllAppsList.added.add(appInfo); j++; } i++; } final Callbacks callbacks = tryGetCallbacks(oldCallbacks); final ArrayList<ApplicationInfo> added = mBgAllAppsList.added; mBgAllAppsList.added = new ArrayList<ApplicationInfo>(); final ArrayList<ItemInfo> shortcuts = new ArrayList<ItemInfo>(); if (added.size() > 0 && blankScreens.size() > 0) { for (int n = 0; n < added.size(); n++) { ShortcutInfo sInfo = new ShortcutInfo( (ApplicationInfo) added.get(n)); sInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP; sInfo.screen = blankScreens.get(itemTotalNum / maxItemNumOnePage); sInfo.cellX = n % cellCountX; sInfo.cellY = n / cellCountX; shortcuts.add(sInfo); addItemToDatabase(mApp.getApplicationContext(), sInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP, sInfo.screen, sInfo.cellX, sInfo.cellY, false); sBgWorkspaceItems.add(sInfo); sBgItemsIdMap.put(sInfo.id, sInfo); itemTotalNum++; } } mHandler.post(new Runnable() { public void run() { if (callbacks != null && shortcuts.size() > 0) { callbacks.bindItems( (ArrayList<ItemInfo>) shortcuts, 0, shortcuts.size()); } else { Log.i(TAG, "not binding apps: no Launcher activity"); } } }); } }
在LauncherModel.java中LoaderTask中,添加函数loadAndBindAllNotInDesktopApps,调用上面添加的函数loadNotInDesktopAllAppsByBatch
private void loadAndBindAllNotInDesktopApps() { if (!mAllAppsLoaded) { loadNotInDesktopAllAppsByBatch(); synchronized (LoaderTask.this) { if (mStopped) { return; } mAllAppsLoaded = true; } } }
在LauncherModel.java中的LoaderTask的run中修改
loadAndBindAllNotInDesktopApps(); // second step //if (loadWorkspaceFirst) { // if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps"); loadAndBindAllApps(); //} else { // if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace"); // loadAndBindWorkspace(); //} ...... loadAndBindAllNotInDesktopApps(); // second step //if (loadWorkspaceFirst) { // if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps"); loadAndBindAllApps(); //} else { // if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace"); // loadAndBindWorkspace(); //}
在LauncherModel.java的loaderworksapce函数中添加
mAlreadyInDesktopApp = new AlreadyInDesktopApp();//初始化AlreadyInDesktopApp、 ...... if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { info = getShortcutInfo(manager, intent, context, c, iconIndex, titleIndex, mLabelCache); mAlreadyInDesktopApp //在从数据库查询Favorites的时候,如果是Shortcut或者是ApplicationInfo则添加到mAlreadyInDesktopApp中,记录哪些App已经被loader到workspace中 .addShortcutFlag(ShortcutInfo .getPackageName(intent), info.componentName.getClassName()); } else {
在LauncherModel.java中的PackageUpdatedTask类中修改并添加
if (added != null) { final ArrayList<ApplicationInfo> addedFinal = added; processInstallShortcut(mApp.getApplicationContext(), addedFinal); //mHandler.post(new Runnable() { // public void run() { // Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; // if (callbacks == cb && cb != null) { // callbacks.bindAppsAdded(addedFinal); // } // } //}); } private void processInstallShortcut(Context context, ArrayList<ApplicationInfo> applicationInfos) { String spKey = LauncherApplication.getSharedPreferencesKey(); SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE); LauncherApplication app = (LauncherApplication) context .getApplicationContext(); final int[] result = { InstallShortcutReceiver.INSTALL_SHORTCUT_SUCCESSFUL }; boolean found = false; synchronized (app) { for (int m = 0; m < applicationInfos.size(); m++) { ApplicationInfo applicationInfo = applicationInfos.get(m); final ArrayList<ItemInfo> items = LauncherModel .getItemsInLocalCoordinates(context); final boolean exists = LauncherModel.shortcutExists(context, applicationInfo.title.toString(), applicationInfo.intent); final int screen = Launcher.DEFAULT_SCREEN; for (int i = 0; i < (2 * Launcher.SCREEN_COUNT) + 1 && !found; ++i) { int si = screen + (int) ((i / 2f) + 0.5f) * ((i % 2 == 1) ? 1 : -1); if (0 <= si && si < Launcher.SCREEN_COUNT) { found = installShortcut(context, items, applicationInfo, si, exists, sp, result); } } if (!found) { if (result[0] == InstallShortcutReceiver.INSTALL_SHORTCUT_NO_SPACE) { Toast.makeText( context, context.getString(R.string.completely_out_of_space), Toast.LENGTH_SHORT).show(); } else if (result[0] == InstallShortcutReceiver.INSTALL_SHORTCUT_IS_DUPLICATE) { Toast.makeText( context, context.getString(R.string.shortcut_duplicate, applicationInfo.title.toString()), Toast.LENGTH_SHORT).show(); } } } } } private boolean installShortcut(Context context, ArrayList<ItemInfo> items, ApplicationInfo applicationInfo, final int screen, boolean shortcutExists, final SharedPreferences sharedPrefs, int[] result) { int[] tmpCoordinates = new int[2]; if (findEmptyCell(context, items, tmpCoordinates, screen)) { if (applicationInfo != null) { if (!shortcutExists) { int newAppsScreen = sharedPrefs.getInt( InstallShortcutReceiver.NEW_APPS_PAGE_KEY, screen); Set<String> newApps = new HashSet<String>(); if (newAppsScreen == screen) { newApps = sharedPrefs.getStringSet( InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps); } synchronized (newApps) { newApps.add(applicationInfo.intent.toUri(0).toString()); } final Set<String> savedNewApps = newApps; new Thread("setNewAppsInstallThread") { public void run() { synchronized (savedNewApps) { sharedPrefs .edit() .putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, screen) .putStringSet( InstallShortcutReceiver.NEW_APPS_LIST_KEY, savedNewApps).commit(); } } }.start(); final ArrayList<ItemInfo> shortcuts = new ArrayList<ItemInfo>(); ShortcutInfo sInfo = new ShortcutInfo(applicationInfo); sInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP; sInfo.screen = screen; sInfo.cellX = tmpCoordinates[0]; sInfo.cellY = tmpCoordinates[1]; shortcuts.add(sInfo); addItemToDatabase(mApp.getApplicationContext(), sInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP, sInfo.screen, sInfo.cellX, sInfo.cellY, false); sBgWorkspaceItems.add(sInfo); sBgItemsIdMap.put(sInfo.id, sInfo); final Callbacks callbacks = mCallbacks.get(); Runnable r = new Runnable() { public void run() { Callbacks cb = mCallbacks != null ? mCallbacks .get() : null; if (callbacks == cb && cb != null && shortcuts.size() > 0) { callbacks.bindItemsNotSetLoadOnResume( (ArrayList<ItemInfo>) shortcuts, 0, shortcuts.size()); } else { Log.i(TAG, "not Install apps to desktop"); } } }; runOnMainThread(r); } else { result[0] = InstallShortcutReceiver.INSTALL_SHORTCUT_IS_DUPLICATE; } return true; } } else { result[0] = InstallShortcutReceiver.INSTALL_SHORTCUT_NO_SPACE; } return false; }
在LauncherModel.java中的Callback接口中添加新的接口,用来在新安装了App的时候更新Workspace
public interface Callbacks { public void bindItemsNotSetLoadOnResume(ArrayList<ItemInfo> shortcuts, int start, int end); }
在Launcher.java中变更函数startApplicationUninstallActivity,变更后workspace中长按Shortcut后,拖动图标到上方的垃圾桶,卸载App
void startApplicationUninstallActivity(ShortcutInfo shortcut) { // if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) == 0) { // System applications cannot be installed. For now, show a toast // explaining that. // We may give them the option of disabling apps this way. // int messageId = R.string.uninstall_system_app_text; // Toast.makeText(this, messageId, Toast.LENGTH_SHORT).show(); // } else { // } mWorkspace.addInScreen(createShortcut(shortcut), shortcut.container, shortcut.screen, shortcut.cellX, shortcut.cellY, 1, 1, false); String packageName = shortcut.componentName.getPackageName(); String className = shortcut.componentName.getClassName(); Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts( "package", packageName, className)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); startActivity(intent); }
在Launcher.java中实现LauncherModel.java中新定义的Callback接口
public void bindItemsNotSetLoadOnResume(ArrayList<ItemInfo> shortcuts, int start, int end) { Set<String> newApps = new HashSet<String>(); newApps = mSharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps); Workspace workspace = mWorkspace; for (int i = start; i < end; i++) { final ItemInfo item = shortcuts.get(i); // Short circuit if we are loading dock items for a configuration which has no dock if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT && mHotseat == null) { continue; } switch (item.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: ShortcutInfo info = (ShortcutInfo) item; String uri = info.intent.toUri(0).toString(); View shortcut = createShortcut(info); workspace.addInScreen(shortcut, item.container, item.screen, item.cellX, item.cellY, 1, 1, false); break; } } workspace.requestLayout(); }
上面就是比较关键的代码
相关文章推荐
- 个人信息安全报告发布:有 APP 每分钟调用位置权限 1468 次
- 下载量超过一亿的流行应用被发现含有恶意模块
- 苹果与Siri的七年之痒:“宫斗”戏码不断上演
- Android APP与媒体存储服务的交互
- java实现收藏名言语句台词的app
- 修改Android App样式风格的方法
- 使用ViewPager实现高仿launcher左右拖动效果
- Android App数据格式Json解析方法和常见问题
- 通过Html网页调用本地安卓(android)app程序代码
- PHP实现批量生成App各种尺寸Logo
- Could not load file or assembly "App_Licenses.dll"的问题
- 基于App自适应draw9patch不失真背景的方法详解
- 安卓APP测试之使用Burp Suite实现HTTPS抓包方法
- web app与原生app的区别
- 使用Chrome浏览器调试Android App详解
- Android开发自学笔记(三):APP布局上
- Android开发自学笔记(四):APP布局下
- Android学习笔记(二)App工程文件分析
- 怎么发布打包并发布自己的Android应用(APP)