liuyuqi-dellpc 3 years ago
parent
commit
4cfca464e4

+ 4 - 0
README.md

@@ -0,0 +1,4 @@
+## appManager
+
+android 包名查看器,方便开发。
+

+ 9 - 0
app/build.gradle

@@ -1,6 +1,14 @@
 apply plugin: 'com.android.application'
 
 android {
+    signingConfigs {
+        release {
+            storeFile file('C:\\Users\\liuyuqi\\OneDrive\\cert\\android\\coding-android-sign-dev.jks')
+            keyAlias 'key0'
+            keyPassword 'coding321'
+            storePassword 'coding321'
+        }
+    }
     compileSdkVersion 29
 
     defaultConfig {
@@ -17,6 +25,7 @@ android {
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+            signingConfig signingConfigs.release
         }
     }
 }

+ 10 - 0
app/src/main/AndroidManifest.xml

@@ -1,6 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     package="me.yoqi.android.appmanager">
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
+        tools:ignore="ProtectedPermissions" />
+    <uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
+
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 
     <application
         android:allowBackup="true"
@@ -16,6 +25,7 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <activity android:name=".views.SplashActivity"/>
     </application>
 
 </manifest>

+ 28 - 0
app/src/main/java/me/yoqi/android/appmanager/BaseActivity.java

@@ -0,0 +1,28 @@
+package me.yoqi.android.appmanager;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+/**
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-10-01
+ */
+public abstract class BaseActivity extends AppCompatActivity {
+    Context mContext;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mContext = this;
+        initView();
+        initData();
+    }
+
+    public abstract void initView();
+
+    public abstract void initData();
+
+}

+ 84 - 2
app/src/main/java/me/yoqi/android/appmanager/MainActivity.java

@@ -1,14 +1,96 @@
 package me.yoqi.android.appmanager;
 
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.RadioButton;
+import android.widget.TextView;
+
 import androidx.appcompat.app.AppCompatActivity;
 
-import android.os.Bundle;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import me.yoqi.android.appmanager.model.AppInfo;
+import me.yoqi.android.appmanager.model.AppModel;
+import me.yoqi.android.appmanager.views.AppInfoAdapter;
+import me.yoqi.android.utils.SPUtils;
+import me.yoqi.android.utils.SimplexToast;
 
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends AppCompatActivity implements View.OnClickListener {
+
+    public static final String TAG = "MainActivity";
+    RadioButton allApp, dsfApp;
+    ListView listView;
+    TextView tvLoad;
+
+    AppInfoAdapter adapter;
+    List<AppInfo> mdatas = new ArrayList<>();
+    List<AppInfo> appInfos = new ArrayList<>();
+    List<AppInfo> dsfappInfos = new ArrayList<>();
+    Context mContext;
+    SimplexToast simplexToast;
+    SPUtils spUtils;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
+        mContext = this;
+        initView();
+        initData();
+    }
+
+    private void initView() {
+        allApp = findViewById(R.id.allApp); //所有app
+        dsfApp = findViewById(R.id.dsfApp); //第三方app
+        tvLoad = findViewById(R.id.tvLoad); //加载中。。。
+        listView = findViewById(R.id.listView);
+        allApp.setOnClickListener(this);
+        dsfApp.setOnClickListener(this);
+        simplexToast = new SimplexToast(mContext);
+        spUtils = new SPUtils(mContext);
+    }
+
+    private void initData() {
+        Set<String> pkgs = spUtils.getStringSet("hide_app", null);
+        // 构建适配器,并且注册到listView
+        adapter = new AppInfoAdapter(this, mdatas);
+        listView.setAdapter(adapter);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                appInfos = AppModel.queryFilterAppInfo(mContext, AppModel.FILTER_SYSTEM_APP);
+                dsfappInfos = AppModel.queryFilterAppInfo(mContext, AppModel.FILTER_THIRD_APP);
+                runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        mdatas.addAll(appInfos);
+                        adapter.notifyDataSetChanged();
+                        tvLoad.setVisibility(View.GONE);
+                        listView.setVisibility(View.VISIBLE);
+                    }
+                });
+            }
+        }).start();
+
+    }
+
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.allApp:
+                mdatas.clear();
+                mdatas.addAll(appInfos);
+                adapter.notifyDataSetChanged();
+                break;
+            case R.id.dsfApp:
+                mdatas.clear();
+                mdatas.addAll(dsfappInfos);
+                adapter.notifyDataSetChanged();
+                break;
+        }
     }
 }

+ 45 - 0
app/src/main/java/me/yoqi/android/appmanager/model/AppInfo.java

@@ -0,0 +1,45 @@
+package me.yoqi.android.appmanager.model;
+import android.graphics.drawable.Drawable;
+
+/**
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-10-01
+ */
+public class AppInfo {
+    private String appName;
+    private Drawable appIcon;
+    private String packageName;
+    private String luancherActivity;
+
+    public String getAppName() {
+        return appName;
+    }
+
+    public void setAppName(String appName) {
+        this.appName = appName;
+    }
+
+    public Drawable getAppIcon() {
+        return appIcon;
+    }
+
+    public void setAppIcon(Drawable appIcon) {
+        this.appIcon = appIcon;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName) {
+        this.packageName = packageName;
+    }
+
+    public String getLuancherActivity() {
+        return luancherActivity;
+    }
+
+    public void setLuancherActivity(String luancherActivity) {
+        this.luancherActivity = luancherActivity;
+    }
+}

+ 100 - 0
app/src/main/java/me/yoqi/android/appmanager/model/AppModel.java

@@ -0,0 +1,100 @@
+package me.yoqi.android.appmanager.model;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-10-01
+ */
+public class AppModel{
+
+    public static final int FILTER_ALL_APP = 0; // 所有应用程序
+    public static final int FILTER_SYSTEM_APP = 1; // 系统程序
+    public static final int FILTER_THIRD_APP = 2; // 第三方应用程序
+    public static final int FILTER_SDCARD_APP = 3; // 安装在SDCard的应用程序
+
+    private static PackageManager pm;
+
+    // 根据查询条件,查询特定的ApplicationInfo
+    public static List<AppInfo> queryFilterAppInfo(Context context, int filter) {
+        pm = context.getPackageManager();
+        // 查询所有已经安装的应用程序
+        List<ApplicationInfo> listAppcations = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
+        Collections.sort(listAppcations, new ApplicationInfo.DisplayNameComparator(pm));// 排序
+        List<AppInfo> appInfos = new ArrayList<AppInfo>(); // 保存过滤查到的AppInfo
+        // 根据条件来过滤
+        switch (filter) {
+            case FILTER_ALL_APP: // 所有应用程序
+                appInfos.clear();
+                for (ApplicationInfo app : listAppcations) {
+                    appInfos.add(getAppInfo(context,app));
+                }
+                return appInfos;
+            case FILTER_SYSTEM_APP: // 系统程序
+                appInfos.clear();
+                for (ApplicationInfo app : listAppcations) {
+                    if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                        appInfos.add(getAppInfo(context,app));
+                    }
+                }
+                return appInfos;
+            case FILTER_THIRD_APP: // 第三方应用程序
+                appInfos.clear();
+                for (ApplicationInfo app : listAppcations) {
+                    //非系统程序
+                    if ((app.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
+                        appInfos.add(getAppInfo(context,app));
+                    }
+                    //本来是系统程序,被用户手动更新后,该系统程序也成为第三方应用程序了
+                    else if ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0){
+                        appInfos.add(getAppInfo(context,app));
+                    }
+                }
+                break;
+            case FILTER_SDCARD_APP: // 安装在SDCard的应用程序
+                appInfos.clear();
+                for (ApplicationInfo app : listAppcations) {
+                    if ((app.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+                        appInfos.add(getAppInfo(context,app));
+                    }
+                }
+                return appInfos;
+            default:
+                return null;
+        }
+        return appInfos;
+    }
+
+    // 构造一个AppInfo对象 ,并赋值
+    private static AppInfo getAppInfo(Context context,ApplicationInfo app) {
+        AppInfo appInfo = new AppInfo();
+        appInfo.setAppName((String) app.loadLabel(pm));
+        appInfo.setAppIcon(app.loadIcon(pm));
+        appInfo.setPackageName(app.packageName);
+        appInfo.setLuancherActivity(getLauncherActivityNameByPackageName(context,appInfo.getPackageName()));
+        return appInfo;
+    }
+
+    public static String getLauncherActivityNameByPackageName(Context context, String packageName) {
+        String className = null;
+        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);//android.intent.action.MAIN
+        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);//android.intent.category.LAUNCHER
+        resolveIntent.setPackage(packageName);
+        List<ResolveInfo> resolveinfoList = context.getPackageManager().queryIntentActivities(resolveIntent, 0);
+        if (resolveinfoList != null && resolveinfoList.size() > 0) {
+            ResolveInfo resolveinfo = resolveinfoList.iterator().next();
+            if (resolveinfo != null) {
+                className = resolveinfo.activityInfo.name;
+            }
+        }
+        return className;
+    }
+}

+ 11 - 0
app/src/main/java/me/yoqi/android/appmanager/utils/Hanzi2Pinyin.java

@@ -0,0 +1,11 @@
+package me.yoqi.android.appmanager.utils;
+
+/**
+ * 文字转拼音
+ *
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-10-01
+ */
+public class Hanzi2Pinyin {
+
+}

+ 82 - 0
app/src/main/java/me/yoqi/android/appmanager/views/AppInfoAdapter.java

@@ -0,0 +1,82 @@
+package me.yoqi.android.appmanager.views;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+import me.yoqi.android.appmanager.R;
+import me.yoqi.android.appmanager.model.AppInfo;
+
+/**
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-10-01
+ */
+public class AppInfoAdapter extends BaseAdapter {
+
+    private List<AppInfo> mlistAppinfo = null;
+
+    LayoutInflater infater = null;
+
+    public AppInfoAdapter(Context context, List<AppInfo> apps) {
+        infater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        mlistAppinfo = apps;
+    }
+
+    @Override
+    public int getCount() {
+        return mlistAppinfo.size();
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return mlistAppinfo.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return 0;
+    }
+
+    @Override
+    public View getView(int position, View convertview, ViewGroup arg2) {
+        View view = null;
+        ViewHolder holder = null;
+        if (convertview == null || convertview.getTag() == null) {
+            view = infater.inflate(R.layout.lv_item, null);
+            holder = new ViewHolder(view);
+            view.setTag(holder);
+        } else {
+            view = convertview;
+            holder = (ViewHolder) convertview.getTag();
+        }
+        AppInfo Appinfo = (AppInfo) getItem(position);
+        holder.icon.setImageDrawable(Appinfo.getAppIcon());
+        holder.appNmae.setText(Appinfo.getAppName());
+        holder.packageName.setText("包名:" + Appinfo.getPackageName());
+        if (!TextUtils.isEmpty(Appinfo.getLuancherActivity())) {
+            holder.launcherName.setText("启动类名:" + Appinfo.getLuancherActivity());
+        }
+        return view;
+    }
+
+    class ViewHolder {
+        ImageView icon;
+        TextView appNmae;
+        TextView packageName;
+        TextView launcherName;
+
+        public ViewHolder(View view) {
+            this.icon = (ImageView) view.findViewById(R.id.icon);
+            this.appNmae = (TextView) view.findViewById(R.id.appNmae);
+            this.packageName = (TextView) view.findViewById(R.id.packageName);
+            this.launcherName = (TextView) view.findViewById(R.id.launcherName);
+        }
+    }
+}

+ 29 - 0
app/src/main/java/me/yoqi/android/appmanager/views/SplashActivity.java

@@ -0,0 +1,29 @@
+package me.yoqi.android.appmanager.views;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.Random;
+
+import me.yoqi.android.appmanager.MainActivity;
+import me.yoqi.android.appmanager.R;
+
+/**
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-10-01
+ */
+public class SplashActivity extends AppCompatActivity {
+    private static final Random sRandom = new Random(System.currentTimeMillis());
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_splash);
+
+        //随机延时 ns 启动
+        startActivity(new Intent(this, MainActivity.class));
+    }
+}

+ 12 - 0
app/src/main/java/me/yoqi/android/utils/NetUtils.java

@@ -0,0 +1,12 @@
+package me.yoqi.android.utils;
+
+/**
+ * 网络检测工具类
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-08-18
+ */
+public class NetUtils {
+    //检测网络是否可用,wifi or gps
+    
+}
+

+ 22 - 0
app/src/main/java/me/yoqi/android/utils/RegexParser.java

@@ -0,0 +1,22 @@
+package me.yoqi.android.utils;
+
+import android.util.Patterns;
+
+/**
+ * 常用正则表达式
+ *
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-08-17
+ */
+public class RegexParser {
+    static final String PHONE_PATTERN = Patterns.PHONE.pattern();
+    static final String EMAIL_PATTERN = Patterns.EMAIL_ADDRESS.pattern();
+
+    //at、话题、链接匹配表达式
+    static final String MENTION_PATTERN = "@.{1,15}?\\s";
+    static final String HASHTAG_PATTERN = "#.{1,15}?\\s";
+    static final String URL_PATTERN = "(http|https|ftp|svn)://([a-zA-Z0-9]+[/?.?])" +
+            "+[a-zA-Z0-9]*\\??([a-zA-Z0-9]*=[a-zA-Z0-9]*&?)*";
+
+}
+

+ 80 - 0
app/src/main/java/me/yoqi/android/utils/SPUtils.java

@@ -0,0 +1,80 @@
+package me.yoqi.android.utils;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+import java.util.Map;
+import java.util.Set;
+
+public class SPUtils {
+    private static final String SP_NAME = "common";
+    private static SPUtils mSpUtils;
+    private Context context;
+    private SharedPreferences sp;
+    private Editor editor;
+
+    public SPUtils(Context context) {
+        this.context = context;
+        sp = this.context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
+        editor = sp.edit();
+    }
+
+    public static SPUtils getInstance(Context context) {
+
+        if (mSpUtils == null) {
+            synchronized (SPUtils.class) {
+                if (mSpUtils == null) {
+                    mSpUtils = new SPUtils(context);
+                    return mSpUtils;
+                }
+            }
+        }
+
+        return mSpUtils;
+
+    }
+
+    public void putBoolean(String key, Boolean value) {
+        editor.putBoolean(key, value);
+        editor.commit();
+    }
+
+    public boolean getBoolean(String key, Boolean defValue) {
+        return sp.getBoolean(key, defValue);
+    }
+
+    public void putString(String key, String value) {
+        if (key == null) {
+            return;
+        }
+        editor.putString(key, value);
+        editor.commit();
+    }
+
+    public String getString(String key, String defValue) {
+        return sp.getString(key, defValue);
+    }
+
+    public Set<String> getStringSet(String key, Set<String> defValue) {
+        return sp.getStringSet(key, defValue);
+    }
+
+    public void putInt(String key, int value) {
+        editor.putInt(key, value);
+        editor.commit();
+    }
+
+    public int getInt(String key, int defValue) {
+        return sp.getInt(key, defValue);
+    }
+
+    public Map<String, ?> getAll() {
+        return sp.getAll();
+    }
+
+    public void remove(String key) {
+        sp.edit().remove(key).commit();
+    }
+
+}

+ 72 - 0
app/src/main/java/me/yoqi/android/utils/SimplexToast.java

@@ -0,0 +1,72 @@
+package me.yoqi.android.utils;
+
+import android.content.Context;
+import android.view.Gravity;
+import android.widget.Toast;
+
+/**
+ * 以后请用这个吐司,谢谢!!!
+ * <p>
+ * <p>
+ * {@link Toast}的创建都是要inflate一个layout, findViewById之类的
+ * 将一个吐司单例化,并且作防止频繁点击的处理。
+ * <p>
+ * <p>
+ */
+@SuppressWarnings("all")
+public class SimplexToast {
+
+    private static Toast mToast;
+    private static long nextTimeMillis;
+    private static int yOffset;
+    static Context mContext;
+
+    public SimplexToast(Context context) {
+        mContext = context;
+    }
+
+    public static Toast init(Context context) {
+        if (context == null) {
+            throw new IllegalArgumentException("Context should not be null!!!");
+        }
+        if (mToast == null) {
+            mToast = Toast.makeText(context, null, Toast.LENGTH_SHORT);
+            yOffset = mToast.getYOffset();
+        }
+        mToast.setDuration(Toast.LENGTH_SHORT);
+        mToast.setGravity(Gravity.BOTTOM, 0, yOffset);
+        mToast.setMargin(0, 0);
+        return mToast;
+    }
+
+    public static void show(String content) {
+        show(content, Toast.LENGTH_SHORT);
+    }
+
+    public static void show(String content, int duration) {
+        show(mContext, content, Gravity.BOTTOM, duration);
+    }
+
+    public static void show(Context context, int rid) {
+        show(context, context.getResources().getString(rid));
+    }
+
+    public static void show(Context context, String content) {
+        show(context, content, Gravity.BOTTOM);
+    }
+
+    public static void show(Context context, String content, int gravity) {
+        show(context, content, gravity, Toast.LENGTH_SHORT);
+    }
+
+    public static void show(Context context, String content, int gravity, int duration) {
+        long current = System.currentTimeMillis();
+        //if (current < nextTimeMillis) return;
+        if (mToast == null) init(context.getApplicationContext());
+        mToast.setText(content);
+        mToast.setDuration(duration);
+        mToast.setGravity(gravity, 0, yOffset);
+        nextTimeMillis = current + (duration == Toast.LENGTH_LONG ? 3500 : 2000);
+        mToast.show();
+    }
+}

+ 10 - 0
app/src/main/java/me/yoqi/android/utils/StringUtils.java

@@ -0,0 +1,10 @@
+package me.yoqi.android.utils;
+
+/**
+ * @author liuyuqi.gov@msn.cn
+ * @createTime 2020-08-17
+ */
+public class StringUtils {
+
+}
+

+ 51 - 9
app/src/main/res/layout/activity_main.xml

@@ -1,18 +1,60 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout 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"
     tools:context=".MainActivity">
 
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="Hello World!"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <RadioGroup
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_marginTop="10dp"
+                android:layout_marginBottom="10dp"
+                android:orientation="horizontal">
+
+                <RadioButton
+                    android:id="@+id/allApp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:checked="true"
+                    android:text="系统App"
+                    android:textColor="#000" />
+
+                <RadioButton
+                    android:id="@+id/dsfApp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="第三方App"
+                    android:textColor="#000" />
+            </RadioGroup>
+
+            <ListView
+                android:id="@+id/listView"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_weight="1"
+                android:visibility="gone"></ListView>
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/tvLoad"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:text="正在加载中..."
+            android:textColor="#000"
+            android:textSize="18sp"
+            android:visibility="visible" />
+    </FrameLayout>
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 6 - 0
app/src/main/res/layout/activity_splash.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+</LinearLayout>

+ 39 - 0
app/src/main/res/layout/lv_item.xml

@@ -0,0 +1,39 @@
+<?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"
+    android:layout_width="match_parent"
+    android:orientation="horizontal"
+    android:padding="16dp"
+    android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_marginRight="10dp"
+        app:srcCompat="@android:drawable/presence_audio_away" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <TextView
+            android:id="@+id/appNmae"
+            android:text="115"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <TextView
+            android:id="@+id/packageName"
+            android:text="com.xx.123"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <TextView
+            android:id="@+id/launcherName"
+            android:text="com.xx"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+    </LinearLayout>
+
+</LinearLayout>