后台获取手机安装的apk列表,其中分为系统apk与非系统apk以及获取root权限之后的隐藏apk,默认通过apk名称排序。使用RecycleView,RecycleView.Adapter<Adapter.appViewHolder>,appViewHolder继承自RecycleView.Adapter,其中依赖部分开源代码progressWheel,fastScoller,pullToRefreshView等。
先将具体逻辑代码贴上, 后面再介绍AsyncTask的使用。
class getInstalledApps extends AsyncTask<Void, String, Void> {
private Integer totalApps;
private Integer actualApps;
public getInstalledApps() {
actualApps = 0;
appList = new ArrayList<>();
appSystemList = new ArrayList<>();
appHiddenList = new ArrayList<>();
}
@Override
protected Void doInBackground(Void... params) {
final PackageManager packageManager = getPackageManager();
List<PackageInfo> packages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA);
Set<String> hiddenApps = appPreferences.getHiddenApps();
totalApps = packages.size() + hiddenApps.size();
// Get Sort Mode 获取apk列表后的排序方式
switch (appPreferences.getSortMode()) {
default:
// Comparator by Name (default)
Collections.sort(packages, new Comparator<PackageInfo>() {
@Override
public int compare(PackageInfo p1, PackageInfo p2) {
return packageManager.getApplicationLabel(p1.applicationInfo).toString().toLowerCase().compareTo(packageManager.getApplicationLabel(p2.applicationInfo).toString().toLowerCase());
}
});
break;
case "2":
// Comparator by Size
Collections.sort(packages, new Comparator<PackageInfo>() {
@Override
public int compare(PackageInfo p1, PackageInfo p2) {
Long size1 = new File(p1.applicationInfo.sourceDir).length();
Long size2 = new File(p2.applicationInfo.sourceDir).length();
return size2.compareTo(size1);
}
});
break;
case "3":
// Comparator by Installation Date
Collections.sort(packages, new Comparator<PackageInfo>() {
@Override
public int compare(PackageInfo p1, PackageInfo p2) {
return Long.toString(p2.firstInstallTime).compareTo(Long.toString(p1.firstInstallTime));
}
});
break;
case "4":
// Comparator by Last Update
Collections.sort(packages, new Comparator<PackageInfo>() {
@Override
public int compare(PackageInfo p1, PackageInfo p2) {
return Long.toString(p2.lastUpdateTime).compareTo(Long.toString(p1.lastUpdateTime));
}
});
break;
}
// Installed & System Apps
for (PackageInfo packageInfo : packages) {
if (!(packageManager.getApplicationLabel(packageInfo.applicationInfo).equals("") || packageInfo.packageName.equals(""))) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
try {
// Non System Apps
AppInfo tempApp = new AppInfo(packageManager.getApplicationLabel(packageInfo.applicationInfo).toString(), packageInfo.packageName, packageInfo.versionName, packageInfo.applicationInfo.sourceDir, packageInfo.applicationInfo.dataDir, packageManager.getApplicationIcon(packageInfo.applicationInfo), false);
appList.add(tempApp);
} catch (OutOfMemoryError e) {
//TODO Workaround to avoid FC on some devices (OutOfMemoryError). Drawable should be cached before.
AppInfo tempApp = new AppInfo(packageManager.getApplicationLabel(packageInfo.applicationInfo).toString(), packageInfo.packageName, packageInfo.versionName, packageInfo.applicationInfo.sourceDir, packageInfo.applicationInfo.dataDir, getResources().getDrawable(R.drawable.ic_android), false);
appList.add(tempApp);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
// System Apps
AppInfo tempApp = new AppInfo(packageManager.getApplicationLabel(packageInfo.applicationInfo).toString(), packageInfo.packageName, packageInfo.versionName, packageInfo.applicationInfo.sourceDir, packageInfo.applicationInfo.dataDir, packageManager.getApplicationIcon(packageInfo.applicationInfo), true);
appSystemList.add(tempApp);
} catch (OutOfMemoryError e) {
//TODO Workaround to avoid FC on some devices (OutOfMemoryError). Drawable should be cached before.
AppInfo tempApp = new AppInfo(packageManager.getApplicationLabel(packageInfo.applicationInfo).toString(), packageInfo.packageName, packageInfo.versionName, packageInfo.applicationInfo.sourceDir, packageInfo.applicationInfo.dataDir, getResources().getDrawable(R.drawable.ic_android), false);
appSystemList.add(tempApp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
actualApps++;
publishProgress(Double.toString((actualApps * 100) / totalApps));//调用publishProgress()方法,通知onProgressUpdate()更新主线程UI
}
// Hidden Apps
for (String app : hiddenApps) {
AppInfo tempApp = new AppInfo(app);
Drawable tempAppIcon = UtilsApp.getIconFromCache(context, tempApp);
tempApp.setIcon(tempAppIcon);
appHiddenList.add(tempApp);
actualApps++;
publishProgress(Double.toString((actualApps * 100) / totalApps));
}
return null;
}
@Override
protected void onProgressUpdate(String... progress) {
super.onProgressUpdate(progress);
progressWheel.setProgress(Float.parseFloat(progress[0]));//gradle中添加依赖compile 'com.pnikosis:materialish-progress:1.7'
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
appAdapter = new AppAdapter(appList, context);
appSystemAdapter = new AppAdapter(appSystemList, context);
appFavoriteAdapter = new AppAdapter(getFavoriteList(appList, appSystemList), context);
appHiddenAdapter = new AppAdapter(appHiddenList, context);
fastScroller.setVisibility(View.VISIBLE);//compile 'xyz.danoz:recycleviewfastscroller:0.1.3'
recyclerView.setAdapter(appAdapter);
pullToRefreshView.setEnabled(true);//compile 'com.yalantis:phoenix:1.2.2'
progressWheel.setVisibility(View.GONE);
searchItem.setVisible(true);
fastScroller.setRecyclerView(recyclerView);
recyclerView.setOnScrollListener(fastScroller.getOnScrollListener());
setPullToRefreshView(pullToRefreshView);
drawer.closeDrawer();
drawer = UtilsUI.setNavigationDrawer((Activity) context, context, toolbar, appAdapter, appSystemAdapter, appFavoriteAdapter, appHiddenAdapter, recyclerView);
}
}
AsyncTask相对简单的结构。
public class MyTask extends AsyncTask<Object, Integer, Integer> {
//执行前准备
@Override
protected void onPreExecute() {
super.onPreExecute();
}
//执行
@Override
protected void doInBackground(Object... params) {
publishProgress(Integer);//将调用onProgressUpdate()方法通知主线程刷新UI,因为在子线程中刷新UI会报错
}
//进度更新
@Override
protected void onProgressUpdate(Integer... progress) {
//do somthing
}
//执行完
@Override
protected void onPostExecute(Integer result) {
//do somthing
}
//取消执行
@Override
protected void onCancelled() {
super.onCancelled();
}
上例MyTask继承AysncTask使用了3个范型:Object,Integer,Integer。
第1个范型指定了 doInBackground()方法的参数类型是一个不定长的Object数组。当主线程中用execute()方法启动MyTask线程时,我们会传递一些参数给doInBackground()方法。
第2个范型指定了onProgressUpdate()方法的参数类型为Integer不定长数组。因为这个方法只会在调用publishProgress()方法时调用,而我们只在doInBackground()方法中调用过publishProgress()方法。我们只需传递一个表示进度的整数给它就可以了。
第3个范型指定了onPostExecute()方法的参数类型。
doInBackground()方法在线程被execute()启动时调用(只有一次)。在该方法中,建立线程循环以完成某些工作。在每次循环完成时,我们通过手动调用publishProgress()(可调用多次)方法,通知onProgressUpdate方法更新主线程的UI(调用多次)。当所有循环完成后,线程循环结束,自动调用onPostExecute()方法返回结果(调用一次),线程销毁。