Android 系统桌面Launcher 开发

AndroidManifest注册

要想让APP作为Launcher,要添加两个category

 
     
        
        
        
    

查找有桌面图标的APP信息

使用PackageManager的queryIntentActivities(intent,flags)方法获取APP

再intent中设置查找的条件

Intent的action为Intent.ACTION_MAIN

intent的category为Intent.CATEGORY_LAUNCHER

flags: MATCH_DEFAULT_ONLY :Category必须带有CATEGORY_DEFAULT的Activity,才匹配      

           GET_INTENT_FILTERS :匹配Intent条件即可

   GET_RESOLVED_FILTER :匹配Intent条件即可

    PackageManager pm = BaseApp.getContext().getPackageManager();
    Intent intent = new Intent(Intent.ACTION_MAIN, null);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    List resolveInfos = pm.queryIntentActivities(intent, 0);
    for (ResolveInfo resolveInfo : resolveInfos) {
    Log.d(TAG, "static initializer: " + resolveInfo.activityInfo.packageName);
        AppInfo app = new AppInfo();
        app.setName(resolveInfo.loadLabel(pm).toString());
        app.setIcon(resolveInfo.loadIcon(pm));
        app.setIconBase64(PhotoUtil.drawableToBase64(resolveInfo.loadIcon(pm)));
        app.setPackageName(resolveInfo.activityInfo.packageName)
    }

打开APP的方法

方法一:

public static void openApp(Context context, String packageName) {
        try {
            PackageManager pm = context.getPackageManager();
            Intent intent = pm.getLaunchIntentForPackage(packageName);
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
            ToastUtil.showToast(App.getContext(), "打开失败!");
        }
    }

方法二:app有多个入口时,使用该方法

public void openApp(Context context, ResolveInfo resolveInfo){
        Intent intent=new Intent();
        intent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,resolveInfo.activityInfo.name));
        context.startActivity(intent);
}

卸载APP的方法

public static void unstallApp(Context context, String packageName) {
        Intent uninstall_intent = new Intent();
        uninstall_intent.setAction(Intent.ACTION_DELETE);
        uninstall_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        uninstall_intent.setData(Uri.parse("package:" + packageName));
        context.startActivity(uninstall_intent);
}

APP卸载,安装,更新的广播

静态注册(android8以后系统对广播的注册更加严格了,静态注册的广播可能会收不到,推荐使用动态注册)


            
                
                
                
              
            

动态注册(注意要反注册哦,不然可能会出现异常)

mAppChangeBroadcast = new AppChangeBroadcast();
IntentFilter filter=new IntentFilter();
filter.addAction("android.intent.action.PACKAGE_ADDED");
filter.addAction("android.intent.action.PACKAGE_REMOVED");
filter.addAction("android.intent.action.PACKAGE_REPLACED");
filter.addDataScheme("package");
registerReceiver(mAppChangeBroadcast,filter);

广播接收者(注意这里有坑,通过intent.getDataString()拿到的值不是包名,而是package:com.android.xxx,所以在获取包名的时候需要做一下处理)

@Override
public void onReceive(Context context, Intent intent) {
  Log.d(TAG, "onReceive: action=" + intent.getAction());
  if("android.intent.action.PACKAGE_ADDED".equeal(intent.getAction())){
     String package=intent.getDataString().substring(8);
   }
}

广播接收者能收到的只有安装的应用的包名,但是我们需要整个应用的信息,大部分人可能会采用一下的方法来获取apk的信息

PackageManager pm = BaseApp.getContext().getPackageManager();
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);

这种方式存在一点点问题,因为我们安装的应用有可能是没有入口的,我们并不需要展示。使用这种方式我们无法区分应用有没有入口,我们可以使用以下方式,同我们获取所有有入口的apk的方式类似,只需要把我们的包名添加上就可以了。如下:

PackageManager pm = BaseApp.getContext().getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setPackage(packageName);
ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
if (null==resolveInfo){
   Log.d(TAG, "addAppInfo: 安装的APK没有入口");
   return;
}

关于APP信息的展示这里就不写了,直接使用RecycleView和GridLayoutManager去展示就行了

你可能感兴趣的:(Android)