MLManager 简单的app管理器

MLManager 一个简单的app管理器

MLManager是一个简单的app管理器。如果你想学习如何得到安装在设备中的app的详细信息,那么这个app对你而言是个理想的选择。

这个app的编码风格非常好,值得借鉴。它还有助于你理解如何设计一个遵循Material Design规范的app。

获取 app 信息

通过PackageManager获取手机已安装apk文件信息

final PackageManager packageManager = getPackageManager();
List<PackageInfo> packages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA);

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
        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 (default)
                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));
        }

        // 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]));
    }

    @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);
        recyclerView.setAdapter(appAdapter);
        pullToRefreshView.setEnabled(true);
        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);
    }

}

获取那些信息

AppInfo.java获取系统apk信息:

  • name:packageManager.getApplicationLabel(packageInfo.applicationInfo).toString() 应用程序的标签
  • apk:packageInfo.packageName 此包的名称
  • version:packageInfo.versionName 此包的版本名称
  • source:packageInfo.applicationInfo.sourceDir 应用APK完整路径
  • data:packageInfo.applicationInfo.dataDir apk数据目录的完整路径。
  • icon:packageManager.getApplicationIcon(packageInfo.applicationInfo) 默认的应用程序图标
  • system:(packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 表示不是系统应用

AppInfo对象实现了Serializable接口。序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。至于从什么地方读出来和保存到哪里去都被隐藏在函数参数的背后了。这样子,任何类型只要实现了Serializable接口,就可以被保存到文件中,或者作为数据流通过网络发送到别的地方。也可以用管道来传输到系统的其他程序中。这样子极大的简化了类的设计。只要设计一个保存一个读取功能就能解决上面说得所有问题。

Java 序列化 (Serializable) 的作用
Serializable接口

public class AppInfo implements Serializable {
    private String name;
    private String apk;
    private String version;
    private String source;
    private String data;
    private Drawable icon;
    private Boolean system;

    public AppInfo(String name, String apk, String version, String source, String data, Drawable icon, Boolean isSystem) {
        this.name = name;
        this.apk = apk;
        this.version = version;
        this.source = source;
        this.data = data;
        this.icon = icon;
        this.system = isSystem;
    }

    public AppInfo(String string) {
        String[] split = string.split("##");
        if (split.length == 6) {
            this.name = split[0];
            this.apk = split[1];
            this.version = split[2];
            this.source = split[3];
            this.data = split[4];
            this.system = Boolean.getBoolean(split[5]);
        }
    }

    public String getName() {
        return name;
    }

    public String getAPK() {
        return apk;
    }

    public String getVersion() {
        return version;
    }

    public String getSource() {
        return source;
    }

    public String getData() {
        return data;
    }

    public Drawable getIcon() {
        return icon;
    }

    public void setIcon(Drawable icon) {
        this.icon = icon;
    }

    public Boolean isSystem() {
        return system;
    }

    public String toString() {
        return getName() + "##" + getAPK() + "##" + getVersion() + "##" + getSource() + "##" + getData() + "##" + isSystem();
    }

}

遵循Material Design规范UI设计

Material Design,中文名:材料设计语言,是由Google推出的全新的设计语言,谷歌表示,这种设计语言旨在为手机、平板电脑、台式机和“其他平台”提供更一致、更广泛的“外观和感觉”。

MLManager使用的依赖库

compile 'com.github.navasmdc:MaterialDesign:1.5@aar'
compile('com.github.afollestad.material-dialogs:core:0.8.5.3@aar') { transitive = true; }
compile('com.github.afollestad.material-dialogs:commons:0.8.5.3@aar') { transitive = true; }
compile 'com.pnikosis:materialish-progress:1.7'
compile('com.mikepenz:materialdrawer:4.6.1@aar') { transitive = true; }
compile 'com.mikepenz:google-material-typeface:1.2.0.1@aar'

com.github.navasmdc:MaterialDesign:1.5@aar
com.github.afollestad.material-dialogs:core:0.8.5.3@aar
com.github.afollestad.material-dialogs:commons:0.8.5.3@aar
com.pnikosis:materialish-progress:1.7
com.mikepenz:materialdrawer:4.6.1@aar
com.mikepenz:google-material-typeface:1.2.0.1@aar

浮动菜单FloatingActionsMenu

compile 'com.getbase:floatingactionbutton:1.10.1'

MLManager项目AppActivity.java界面中
这里写图片描述

fab_multiple.xml

<?xml version="1.0" encoding="utf-8"?>
<com.getbase.floatingactionbutton.FloatingActionsMenu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|right"
    android:layout_margin="@dimen/fab_margin"
    app:fab_labelStyle="@style/menu_labels_style"
    app:fab_addButtonColorNormal="@color/primary"
    app:fab_addButtonColorPressed="@color/primary_dark">
    <com.getbase.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_buy"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:fab_icon="@drawable/ic_local_grocery_store_white"
        app:fab_colorNormal="@color/fab"
        app:fab_title="@string/action_buy" />
    <com.getbase.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        app:fab_colorNormal="@color/fab"
        app:fab_title="@string/action_hide" />
    <com.getbase.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:fab_icon="@drawable/ic_send_white"
        app:fab_colorNormal="@color/fab"
        app:fab_title="@string/action_share" />
</com.getbase.floatingactionbutton.FloatingActionsMenu>

activity_app.xml添加布局fab_multiple.xml
fab.isExpanded() 浮动菜单是否是展开
fab.collapse() 折叠浮动菜单

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <include
            android:id="@+id/fab"
            layout="@layout/fab_multiple" />
    </FrameLayout>

左侧抽屉菜单

compile('com.mikepenz:materialdrawer:4.6.1@aar') { transitive = true; }

MLManager项目MainActivity.java界面中
这里写图片描述

drawer = UtilsUI.setNavigationDrawer((Activity) context, context, toolbar, appAdapter, appSystemAdapter, appFavoriteAdapter, appHiddenAdapter, recyclerView);

抽屉菜单的创建drawerBuilder.build()

public static Drawer setNavigationDrawer (Activity activity, final Context context, Toolbar toolbar, final AppAdapter appAdapter, final
        AppAdapter appSystemAdapter, final AppAdapter appFavoriteAdapter, final AppAdapter appHiddenAdapter, final RecyclerView recyclerView) {
    final String loadingLabel = "...";
    int header;
    AppPreferences appPreferences = MLManagerApplication.getAppPreferences();
    String apps, systemApps, favoriteApps, hiddenApps;

    if (getDayOrNight() == 1) {
        header = R.drawable.header_day;
    } else {
        header = R.drawable.header_night;
    }

    if (appAdapter != null) {
        apps = Integer.toString(appAdapter.getItemCount());
    } else {
        apps = loadingLabel;
    }
    if (appSystemAdapter != null) {
        systemApps = Integer.toString(appSystemAdapter.getItemCount());
    } else {
        systemApps = loadingLabel;
    }
    if (appFavoriteAdapter != null) {
        favoriteApps = Integer.toString(appFavoriteAdapter.getItemCount());
    } else {
        favoriteApps = loadingLabel;
    }
    if (appHiddenAdapter != null) {
        hiddenApps = Integer.toString(appHiddenAdapter.getItemCount());
    } else {
        hiddenApps = loadingLabel;
    }

    AccountHeader headerResult = new AccountHeaderBuilder()
            .withActivity(activity)
            .withHeaderBackground(header)
            .build();

    Integer badgeColor = ContextCompat.getColor(context, R.color.divider);
    BadgeStyle badgeStyle = new BadgeStyle(badgeColor, badgeColor).withTextColor(Color.GRAY);

    DrawerBuilder drawerBuilder = new DrawerBuilder();
    drawerBuilder.withActivity(activity);
    drawerBuilder.withToolbar(toolbar);
    drawerBuilder.withAccountHeader(headerResult);
    drawerBuilder.withStatusBarColor(UtilsUI.darker(appPreferences.getPrimaryColorPref(), 0.8));

    if (MLManagerApplication.isPro()) {
        drawerBuilder.addDrawerItems(
                new PrimaryDrawerItem().withName(context.getResources().getString(R.string.action_apps)).withIcon(GoogleMaterial.Icon.gmd_phone_android).withBadge(apps).withBadgeStyle(badgeStyle).withIdentifier(1),
                new PrimaryDrawerItem().withName(context.getResources().getString(R.string.action_system_apps)).withIcon(GoogleMaterial.Icon.gmd_android).withBadge(systemApps).withBadgeStyle(badgeStyle).withIdentifier(2),
                new DividerDrawerItem(),
                new PrimaryDrawerItem().withName(context.getResources().getString(R.string.action_favorites)).withIcon(GoogleMaterial.Icon.gmd_star).withBadge(favoriteApps).withBadgeStyle(badgeStyle).withIdentifier(3),
                new DividerDrawerItem(),
                new PrimaryDrawerItem().withName(context.getResources().getString(R.string.action_hidden_apps)).withIcon(GoogleMaterial.Icon.gmd_visibility_off).withBadge(hiddenApps).withBadgeStyle(badgeStyle).withIdentifier(4),
                new DividerDrawerItem(),
                new SecondaryDrawerItem().withName(context.getResources().getString(R.string.action_settings)).withIcon(GoogleMaterial.Icon.gmd_settings).withSelectable(false).withIdentifier(6),
                new SecondaryDrawerItem().withName(context.getResources().getString(R.string.action_about)).withIcon(GoogleMaterial.Icon.gmd_info).withSelectable(false).withIdentifier(7));
    } else {
        drawerBuilder.addDrawerItems(
                new PrimaryDrawerItem().withName(context.getResources().getString(R.string.action_apps)).withIcon(GoogleMaterial.Icon.gmd_phone_android).withBadge(apps).withBadgeStyle(badgeStyle).withIdentifier(1),
                new PrimaryDrawerItem().withName(context.getResources().getString(R.string.action_system_apps)).withIcon(GoogleMaterial.Icon.gmd_android).withBadge(systemApps).withBadgeStyle(badgeStyle).withIdentifier(2),
                new DividerDrawerItem(),
                new PrimaryDrawerItem().withName(context.getResources().getString(R.string.action_favorites)).withIcon(GoogleMaterial.Icon.gmd_star).withBadge(favoriteApps).withBadgeStyle(badgeStyle).withIdentifier(3),
                new DividerDrawerItem(),
                new SecondaryDrawerItem().withName(context.getResources().getString(R.string.action_buy)).withIcon(GoogleMaterial.Icon.gmd_shop).withBadge(context.getResources().getString(R.string.action_buy_description)).withSelectable(false).withIdentifier(5),
                new SecondaryDrawerItem().withName(context.getResources().getString(R.string.action_settings)).withIcon(GoogleMaterial.Icon.gmd_settings).withSelectable(false).withIdentifier(6),
                new SecondaryDrawerItem().withName(context.getResources().getString(R.string.action_about)).withIcon(GoogleMaterial.Icon.gmd_info).withSelectable(false).withIdentifier(7));
    }

    drawerBuilder.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
        @Override
        public boolean onItemClick(View view, int position, IDrawerItem iDrawerItem) {
            switch (iDrawerItem.getIdentifier()) {
                case 1:
                    recyclerView.setAdapter(appAdapter);
                    break;
                case 2:
                    recyclerView.setAdapter(appSystemAdapter);
                    break;
                case 3:
                    recyclerView.setAdapter(appFavoriteAdapter);
                    break;
                case 4:
                    recyclerView.setAdapter(appHiddenAdapter);
                    break;
                case 5:
                    UtilsDialog.showProFeatures(context);
                    break;
                case 6:
                    context.startActivity(new Intent(context, SettingsActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
                    break;
                case 7:
                    context.startActivity(new Intent(context, AboutActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
                    break;
                default:
                    break;
            }

            return false;
        }
    });

    return drawerBuilder.build();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xhBruce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值