从手机中扫描以com.xx.xxx 为前缀的apk包,使用列表的形式展现

apk 包可以使用PackageManager获取,apk 包中的资源可以获取其对应的Context,再通过Context获取对应的Resouce获取提示2: apk 是指已经安装过的程序,不是存在sdcard. 上的apk安装包.

先上效果图

 

 

 

开始代码部分

首先是布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.nf.applist.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:paddingLeft="16dp"
        android:paddingRight="16dp">

        <Switch
            android:id="@+id/switch_type"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true" />

        <EditText
            android:id="@+id/edit_input"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:hint="请输入包名前缀"
            android:singleLine="true"
            android:textColor="#333333"
            android:textSize="14sp" />

        <Button
            android:id="@+id/btn_scan"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="扫描"
            android:textColor="#333333"
            android:textSize="14sp" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/list_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <TextView
            android:id="@+id/tv_empty"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="没有找到任何包"
            android:textColor="#333333"
            android:textSize="14sp"
            android:visibility="gone" />
    </RelativeLayout>
</LinearLayout>

ListView的item布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="58dp"
    android:gravity="center_vertical"
    android:paddingLeft="16dp"
    android:paddingRight="16dp">

    <!-- tools 域 表示 仅在预览时生效 -->
    <ImageView
        android:id="@+id/iv_app_icon"
        android:layout_width="40dp"
        android:layout_height="40dp"
        tools:src="@mipmap/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_app_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#333333"
            android:textSize="14sp"
            tools:text="应用名称" />

        <TextView
            android:id="@+id/tv_app_package"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="2dp"
            android:textColor="#888888"
            android:textSize="12sp"
            tools:text="应用包名" />
    </LinearLayout>
</LinearLayout>

然后是实体类SimpleAppInfo.class

public class SimpleAppInfo {
    private String appName;
    private String appPackage;
    private Drawable appIcon;
    private String valuesAppName;
    private Drawable drawablePreiewImg;
    private boolean system;
    private String packagePath;
    private String versionName;
    private int versionCode;

    public SimpleAppInfo(String appName, String appPackage, Drawable appIcon, boolean system, String packagePath, String versionName, int versionCode) {
        this.appName = appName;
        this.appPackage = appPackage;
        this.appIcon = appIcon;
        this.system = system;
        this.packagePath = packagePath;
        this.versionName = versionName;
        this.versionCode = versionCode;
    }

    public String getPackagePath() {
        return packagePath;
    }

    public void setPackagePath(String packagePath) {
        this.packagePath = packagePath;
    }

    public String getVersionName() {
        return versionName;
    }

    public void setVersionName(String versionName) {
        this.versionName = versionName;
    }

    public int getVersionCode() {
        return versionCode;
    }

    public void setVersionCode(int versionCode) {
        this.versionCode = versionCode;
    }

    public boolean isSystem() {
        return system;
    }

    public void setSystem(boolean system) {
        this.system = system;
    }

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public String getAppPackage() {
        return appPackage;
    }

    public void setAppPackage(String appPackage) {
        this.appPackage = appPackage;
    }

    public Drawable getAppIcon() {
        return appIcon;
    }

    public void setAppIcon(Drawable appIcon) {
        this.appIcon = appIcon;
    }

    public String getValuesAppName() {
        return valuesAppName;
    }

    public void setValuesAppName(String valuesAppName) {
        this.valuesAppName = valuesAppName;
    }

    public Drawable getDrawablePreiewImg() {
        return drawablePreiewImg;
    }

    public void setDrawablePreiewImg(Drawable drawablePreiewImg) {
        this.drawablePreiewImg = drawablePreiewImg;
    }
}

接下来就是核心代码了MainActivity.class

public class MainActivity extends AppCompatActivity {

    private TextView tvEmpty;
    private ListView listView;
    private Button btnScan;
    private EditText editInput;
    private List<SimpleAppInfo> filterAppList = new ArrayList<>();
    private BaseAdapter appListAdapter;
    private Switch switchType;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvEmpty = findViewById(R.id.tv_empty);
        listView = findViewById(R.id.list_view);
        btnScan = findViewById(R.id.btn_scan);
        editInput = findViewById(R.id.edit_input);
        switchType = findViewById(R.id.switch_type);
        switchType.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                appListAdapter.notifyDataSetChanged();
            }
        });
        btnScan.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //防止重复点击
                btnScan.setEnabled(false);
                listView.setVisibility(View.GONE);
                tvEmpty.setVisibility(View.VISIBLE);
                tvEmpty.setText("正在扫描");
                //开子线程做耗时的工作
                new Thread() {
                    @Override
                    public void run() {
                        final List<SimpleAppInfo> appsInfo = getAppsInfo();
                        //切换到主线程 更新数据
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                String filterStr = editInput.getText().toString().trim();
                                if (TextUtils.isEmpty(filterStr)) {
                                    filterAppList = appsInfo;
                                } else {//过滤
                                    filterAppList.clear();
                                    for (SimpleAppInfo appInfo : appsInfo) {
                                        if (appInfo.getAppPackage().startsWith(filterStr)) {
                                            filterAppList.add(appInfo);
                                        }
                                    }
                                }
                                if (filterAppList.size() == 0) {
                                    tvEmpty.setVisibility(View.VISIBLE);
                                    listView.setVisibility(View.GONE);
                                    tvEmpty.setText("没有任何数据");
                                } else {
                                    tvEmpty.setVisibility(View.GONE);
                                    listView.setVisibility(View.VISIBLE);
                                    appListAdapter.notifyDataSetChanged();
                                }
                                //更新完成后  开放 按钮
                                btnScan.setEnabled(true);
                            }
                        });
                    }
                }.start();
            }
        });

        appListAdapter = new BaseAdapter() {
            @Override
            public int getCount() {
                return filterAppList.size();
            }

            @Override
            public Object getItem(int position) {
                return filterAppList.get(position);
            }

            @Override
            public long getItemId(int position) {
                return 0;
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                ViewHolder holder;
                if (convertView == null) {
                    convertView = View.inflate(MainActivity.this, R.layout.item, null);
                    holder = new ViewHolder(convertView);
                    convertView.setTag(holder);
                } else {
                    holder = (ViewHolder) convertView.getTag();
                }
                SimpleAppInfo appInfo = filterAppList.get(position);
                holder.tvAppPackage.setText(appInfo.getAppPackage());
                if (switchType.isChecked()) {
                    //这里是直接展示appInfo提供的 应用名\包名\Icon
                    holder.tvAppName.setText(appInfo.getAppName());
                    holder.ivAppImage.setImageDrawable(appInfo.getAppIcon());
                } else {
                    //使用 指定资源数据
                    holder.tvAppName.setText(appInfo.getValuesAppName());
                    holder.ivAppImage.setImageDrawable(appInfo.getDrawablePreiewImg());
                }
                return convertView;
            }
        };
        listView.setAdapter(appListAdapter);
    }

    public static class ViewHolder {
        TextView tvAppName;
        TextView tvAppPackage;
        ImageView ivAppImage;

        public ViewHolder(View view) {
            tvAppName = view.findViewById(R.id.tv_app_name);
            tvAppPackage = view.findViewById(R.id.tv_app_package);
            ivAppImage = view.findViewById(R.id.iv_app_icon);
        }
    }

    public List<SimpleAppInfo> getAppsInfo() {
        List<SimpleAppInfo> list = new ArrayList<>();
        PackageManager pm = getPackageManager();
        if (pm == null) return list;
        List<PackageInfo> installedPackages = pm.getInstalledPackages(0);
        for (PackageInfo pi : installedPackages) {
            SimpleAppInfo ai = getBean(pm, pi);
            if (ai == null) continue;
            list.add(ai);
        }
        return list;
    }

    private SimpleAppInfo getBean(final PackageManager pm, final PackageInfo pi) {
        if (pi == null) return null;
        ApplicationInfo ai = pi.applicationInfo;
        String packageName = pi.packageName;
        String name = ai.loadLabel(pm).toString();
        Drawable icon = ai.loadIcon(pm);
        String packagePath = ai.sourceDir;
        String versionName = pi.versionName;
        int versionCode = pi.versionCode;
        boolean isSystem = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != 0;
//        return new SimpleAppInfo(packageName, name, icon, packagePath, versionName, versionCode, isSystem);
        SimpleAppInfo simpleAppInfo = new SimpleAppInfo(name, packageName, icon, isSystem, packagePath, versionName, versionCode);

        try {
            Resources resources = pm.getResourcesForApplication(packageName);
            int appNameId = resources.getIdentifier("app_name", "string", packageName);
            if (appNameId > 0) {
                String appName = resources.getString(appNameId);
                simpleAppInfo.setValuesAppName(appName);
            }
            int previewImgId = resources.getIdentifier("preview_img", "drawable", packageName);
//                                    int previewImgId = resources.getIdentifier("ic_launcher", "drawable", packageName);
            if (previewImgId > 0) {
                Drawable drawable = resources.getDrawable(previewImgId);
                simpleAppInfo.setDrawablePreiewImg(drawable);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return simpleAppInfo;
    }
}

所有代码均已贴出,并未使用任何第三方包,所以也就不上传demo了,

 

最后补充说明一下switch的作用

switch 开关 用于控制 显示  条目 内容 

switch  开 -> 显示默认的appName 和appIcon
switch  关 -> 显示指定的 app_name和preview_img 资源 
 

 

posted @ 2019-08-04 12:11  在云端i  阅读(1155)  评论(0编辑  收藏  举报