zoukankan      html  css  js  c++  java
  • Android:获取应用信息,打开、卸载应用

    在项目里有一个需求,点击App介绍里面的官方微信公众号,就可以直接打开微信搜索、关注。这个功能实现起来并不复杂,获取包名,用intent跳转即可。那么如何获取某一个应用的包名呢?可以反编译apk,在文件里查看,这个方法比较麻烦。我们也可以直接通过Android系统为我们提供的类PackageManager来获得PackageInfo,这个类里面包含相关应用程序的很多信息。示例用到了SwipeMenuListView,菜单里提供打开App与卸载App两个功能。主要示例代码如下:

    package com.li.applistdemo;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageInfo;
    import android.content.pm.ResolveInfo;
    import android.graphics.Color;
    import android.graphics.drawable.ColorDrawable;
    import android.net.Uri;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.TypedValue;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import com.baoyz.swipemenulistview.BaseSwipListAdapter;
    import com.baoyz.swipemenulistview.SwipeMenu;
    import com.baoyz.swipemenulistview.SwipeMenuCreator;
    import com.baoyz.swipemenulistview.SwipeMenuItem;
    import com.baoyz.swipemenulistview.SwipeMenuListView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
    
        public final int GET_ALL_APP = 0; // 所有应用程序
        public final int GET_SYSTEM_APP = 1; // 系统程序
        public final int GET_THIRD_APP = 2; // 第三方应用程序
        public final int GET_SDCARD_APP = 3; // 安装在SDCard的应用程序
    
        private List<PackageInfo> mAppList;
        private AppListAdapter mAdapter;
        private SwipeMenuListView mListView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mAppList = getPackageInfos(GET_THIRD_APP);
    
            mListView = (SwipeMenuListView) findViewById(R.id.swipeListView);
            mAdapter = new AppListAdapter();
            mListView.setAdapter(mAdapter);
    
            SwipeMenuCreator creator = new SwipeMenuCreator() {
                @Override
                public void create(SwipeMenu menu) {
                    SwipeMenuItem openItem = new SwipeMenuItem(
                            getApplicationContext());
                    openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,0xCE)));
                    openItem.setWidth(dp2px(100));
                    openItem.setTitle("Open");
                    openItem.setTitleSize(18);
                    openItem.setTitleColor(Color.WHITE);
                    menu.addMenuItem(openItem);
    
                    SwipeMenuItem deleteItem = new SwipeMenuItem(
                            getApplicationContext());
                    deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9, 0x3F, 0x25)));
                    deleteItem.setWidth(dp2px(100));
                    deleteItem.setIcon(R.mipmap.ic_delete);
                    menu.addMenuItem(deleteItem);
                }
            };
    
            mListView.setMenuCreator(creator);
    
            mListView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
                    PackageInfo item = mAppList.get(position);
                    switch (index) {
                        case 0:
                            open(item);
                            break;
                        case 1:
                            uninstall(item);
                            mAppList.remove(position);
                            mAdapter.notifyDataSetChanged();
                            break;
                    }
                    return false;
                }
            });
        }
    
        private List<PackageInfo> getPackageInfos(int type){
            // 0 表示不接受任何参数。其他参数都带有限制
            // 版本号、APP权限只能通过PackageInfo获取,所以这里不使用getInstalledApplications()方法
            List<PackageInfo> packageInfos = getPackageManager().getInstalledPackages(0);
            if (packageInfos == null){
                return null;
            }
    
            List<PackageInfo> result = new ArrayList<>();
            switch (type) {
                case GET_ALL_APP:
                    result = packageInfos;
                    break;
                case GET_SYSTEM_APP: // 系统自带APP
                    for (PackageInfo info : packageInfos) {
                        // FLAG_SYSTEM = 1<<0,if set, this application is installed in
                        // the device's system image.
                        // 下面&运算有两种结果:
                        // 1,则flags的末位为1,即系统APP
                        // 0,则flags的末位为0,即非系统APP
                        if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
                            result.add(info);
                        }
                    }
                    break;
                case GET_THIRD_APP: // 第三方APP
                    for (PackageInfo info : packageInfos) {
                        // FLAG_SYSTEM = 1<<0,同上
                        if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                            result.add(info);
                        }
                        // 本来是系统程序,被用户手动更新后,该系统程序也成为第三方应用程序了
                        // FLAG_UPDATED_SYSTEM_APP = 1<<7, this is set if this
                        // application has been
                        // install as an update to a built-in system application.
                        else if ((info.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1) {
                            result.add(info);
                        }
                    }
                    break;
                case GET_SDCARD_APP: // 安装在SDCard的应用程序
                    for (PackageInfo info : packageInfos) {
                        // FLAG_EXTERNAL_STORAGE = 1<<18,Set to true if the application
                        // is
                        // currently installed on external/removable/unprotected storage
                        if ((info.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 1) {
                            result.add(info);
                        }
                    }
                    break;
            }
            return result;
        }
    
        private void uninstall(PackageInfo item) {
            try {
                Intent intent = new Intent(Intent.ACTION_DELETE);
                intent.setData(Uri.fromParts("package", item.packageName, null));
                startActivity(intent);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private void open(PackageInfo item) {
            Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
            resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            resolveIntent.setPackage(item.packageName);
            List<ResolveInfo> resolveInfoList = getPackageManager()
                    .queryIntentActivities(resolveIntent, 0);
            if (resolveInfoList != null && resolveInfoList.size() > 0) {
                ResolveInfo resolveInfo = resolveInfoList.get(0);
                String activityPackageName = resolveInfo.activityInfo.packageName;
                String className = resolveInfo.activityInfo.name;
    
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.addCategory(Intent.CATEGORY_LAUNCHER);
                ComponentName componentName = new ComponentName(
                        activityPackageName, className);
    
                intent.setComponent(componentName);
                startActivity(intent);
            }
        }
    
        class AppListAdapter extends BaseSwipListAdapter {
    
            @Override
            public int getCount() {
                return mAppList.size();
            }
    
            @Override
            public PackageInfo getItem(int position) {
                return mAppList.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                return position;
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                if (convertView == null) {
                    convertView = View.inflate(getApplicationContext(),
                            R.layout.item_list_app, null);
                    new ViewHolder(convertView);
                }
                ViewHolder holder = (ViewHolder) convertView.getTag();
                PackageInfo item = getItem(position);
    
                holder.iv_icon.setImageDrawable(item.applicationInfo.loadIcon(getPackageManager()));
                holder.tv_name.setText(item.applicationInfo.loadLabel(getPackageManager()) + "
    " + item.packageName);
    
                return convertView;
            }
    
            class ViewHolder {
                ImageView iv_icon;
                TextView tv_name;
    
                public ViewHolder(View view) {
                    iv_icon = (ImageView) view.findViewById(R.id.iv_icon);
                    tv_name = (TextView) view.findViewById(R.id.tv_name);
                    view.setTag(this);
                }
            }
    
            @Override
            public boolean getSwipEnableByPosition(int position) {
                return true;
            }
        }
    
        private int dp2px(int dp) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                    getResources().getDisplayMetrics());
        }
    }
    

    获取App列表信息比较耗时,可能会引起ANR,所以这些操作应该放在子线程里面。

    获取到结果以后,我们要通过Adapter来更新UI,但是Android不允许在非UI线程里面更新UI,可以用Handler去post一个Runnable对象来解决这个问题。为什么Handler可以呢?感兴趣的可以看看 http://blog.csdn.net/ly502541243/article/details/52062179/ ,里面分析得很详细。
    简单来说,通过Handler.post(Runnable r)传入的Runnable,在回调的时候会调用run方法,而直接调用线程的run方法相当于是在一个普通的类调用方法,还是在当前线程执行,并不会开启新的线程。在post中传了个Runnable,还是在主线程中,因此可以更新UI。

  • 相关阅读:
    熟悉常用的Linux操作
    Python基础之五星红旗
    类似于铁道部12306的城市选择框的实现
    使用Django操作数据库入门
    进程和线程
    线程、进程、携程理解
    CentOS6.8部署Python3.6.8的Django项目
    爬取妹子图片
    聚类算法之DBSCAN
    机器学习算法优缺点总结
  • 原文地址:https://www.cnblogs.com/lishbo/p/9956027.html
Copyright © 2011-2022 走看看