// finds the target screen density to get icons for private int getScreenDensity() { // see Android reference: // http://developer.android.com/reference/android/util/DisplayMetrics.html int value = appsRequest.getScreenDensity(); // apps should not target intermediate densities, instead relying on scaling up/down from // standard densities switch (appsRequest.getScreenDensity()) { case DisplayMetrics.DENSITY_TV: value = DisplayMetrics.DENSITY_HIGH; break; case 400: // api 19: DisplayMetrics.DENSITY_400 case DisplayMetrics.DENSITY_XXHIGH: case 640: // api 18: DisplayMetrics.DENSITY_XXXHIGH value = DisplayMetrics.DENSITY_XHIGH; break; // all other densities are standard densities, let the value remain } return value; }
@Override public void run() { PackageManager pm = baseServer.getContext().getPackageManager(); // get a list of installed apps. Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> resolveInfos = pm.queryIntentActivities(mainIntent, 0); int screenDensity = getScreenDensity(); // create a map of app data from the list of installed apps Map<String, Tuple> appDataMap = new TreeMap<String, Tuple>(); for (ResolveInfo resolveInfo : resolveInfos) { String pkgName = resolveInfo.activityInfo.packageName; String appName = resolveInfo.loadLabel(pm).toString(); Drawable drawable = null; try { Resources resources = pm.getResourcesForApplication(pkgName); if (resources != null) { int iconId = resolveInfo.getIconResource(); if (iconId != 0) drawable = resources.getDrawableForDensity(iconId, screenDensity); } // if (drawable == null) // drawable = pm.getApplicationIcon(pkgName); } catch (Resources.NotFoundException e) { Log.e( TAG, "Failed to find application icon for package '" + pkgName + "':" + e.getMessage()); } catch (PackageManager.NameNotFoundException e) { Log.e( TAG, "Failed to find application info for package '" + pkgName + "':" + e.getMessage()); } byte[] icon = Utility.drawableToBytes(drawable); Tuple tuple = new Tuple(pkgName, appName, icon); // add the tuple to the map appDataMap.put(pkgName, tuple); } // build an AppList AppsResponse.Builder arBuilder = AppsResponse.newBuilder(); arBuilder.setType(AppsResponse.AppsResponseType.REFRESH); // get Request info List<AppInfo> currentApps = appsRequest.getCurrentList(); for (AppInfo appInfo : currentApps) { String pkgName = appInfo.getPkgName(); // compare the client's current apps to our appDataMap if (appDataMap.containsKey(pkgName)) { // we have this package installed, check to see if it's different from the client's records Tuple tuple = appDataMap.remove(pkgName); boolean different = false; String appName = appInfo.getAppName(); byte[] iconHash = null; if (appInfo.hasIconHash()) iconHash = appInfo.getIconHash().toByteArray(); if (!appName.equals(tuple.appName)) { different = true; } else { byte[] tupleIconHash = getIconHash(tuple); if (!Arrays.equals(iconHash, tupleIconHash)) { different = true; } } if (different) { // we have this package installed, but it's different, instruct the client to update it arBuilder.addUpdated(buildAppInfo(tuple)); } // otherwise, the package hasn't changed, don't tell the client to do anything to it } else { // we don't have this package installed, instruct the client to remove it arBuilder.addRemoved(pkgName); } } // for any remaining apps, instruct the client to add it for (Tuple tuple : appDataMap.values()) { arBuilder.addNew(buildAppInfo(tuple)); } // build a Response Response.Builder rBuilder = Response.newBuilder(); rBuilder.setType(Response.ResponseType.APPS); // add the AppList to the Response rBuilder.setApps(arBuilder); baseServer.sendMessage(rBuilder.build()); }