後臺獲取手機安裝的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()方法返回結果(調用一次),線程銷燬。