android12 桌面抽屉应用图标排序

1、应用图标按照安装时间进行排序(最新安装排最前面)在packages/apps/Launcher3/src/com/android/launcher3/allapps/AppInfoComparator.java中compare方法下添加如下

String a_packagename = a.componentName.getPackageName();
	    String b_packagename = b.componentName.getPackageName();
	    int result = getInstallTime(b_packagename).compareTo(getInstallTime(a_packagename));
        if (result != 0) {
        return result;
        }

2、第三方软件图标都放在最前面,并且指定一个第三方图标始终排第一个

2-1、在packages/apps/Launcher3/src/com/android/launcher3/allapps/AlphabeticalAppsList.java中添加依赖

import android.util.Log;
import android.content.BroadcastReceiver;
import android.content.pm.PackageManager;
import android.content.Intent;
import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.content.IntentFilter;
import android.text.TextUtils;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.android.launcher3.AppListDatabaseHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.Cursor;
import android.content.ContentValues;

2-2、添加一会儿需要用到的变量

    private WifiReceiver mWifiReceiver = new WifiReceiver();
    private Context mContext;
    private String packageName;
    private String className;
    private String appPackage = null;
    private String[] newArray = new String[]{};
    List<String> dataListName = new ArrayList<>();
    List<String> dataListClassName = new ArrayList<>();

 2-3、首先需要监听到软件安装卸载所发出的广播,用来获取软件的包名和启动类名,应为抽屉图标展示是用的<包名/启动类名>,例如音乐就是 com.android.music/com.android.music.MusicBrowserActivity,然后把这个包名和启动类名存起来,我是拿了一个数据来存储这些。

//apk安装卸载是走这里
    private class WifiReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d("ceshionReceive, action=",""+ action);
            if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {
                String packageName = intent.getDataString().substring(8);
                Log.d("wwwhhhjjj","-------------------------packageName:   "+packageName);
 
                // 获取包管理器
                PackageManager pm = context.getPackageManager();
                // 获取启动Activity的信息
                Intent launchIntent = pm.getLaunchIntentForPackage(packageName);
                if (launchIntent != null) {
                    // 获取启动Activity的组件名
                    String className = launchIntent.getComponent().getClassName();
                    Log.d("wwwhhhjjj","-------------------------className:   "+className);
                    // 这里可以根据需要处理获取到的包名和启动类名
                    // ...
                    appPackage = packageName + "/" + className;
                    Log.d("wwwhhhjjj","-------------------------appPackage:   "+appPackage);
                    Log.d("wwwhhhjjj","-------------------------witeData:   ");
                    if(isDataExists(packageName)){
                        Log.d("wwwhhhjjj","-------------------------isDataExists:   "+""+isDataExists(packageName));
                    }else{
                        Log.d("wwwhhhjjj","-------------------------isDataExists:   "+""+isDataExists(packageName));
                        witeData(packageName,className);
                    }
                    dataListName.clear();
                    dataListClassName.clear();
                    DataBase();

                }
            }
            if (intent.getAction().equals("android.intent.action.PACKAGE_FULLY_REMOVED")) {
                 String packageName = intent.getDataString().substring(8);
                 Log.d("wwwhhhjjj","-------------------------packageName:   "+packageName);
                 
                 if(isDataExists(packageName)){
                    Log.d("wwwhhhjjj","-------------------------isDataExists:   "+""+isDataExists(packageName));
                    delData(packageName);
                 }else{
                    Log.d("wwwhhhjjj","-------------------------isDataExists:   "+""+isDataExists(packageName));
                 }
                 dataListName.clear();
                 dataListClassName.clear();
                 DataBase();
            }
        }
    }

2-4、启动监听器并过滤广播,需要在 AlphabeticalAppsList.java中的AlphabeticalAppsList方法中添加如下代码

mContext = context;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
filter.addAction("android.intent.action.PACKAGE_ADDED");
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
mContext.registerReceiver(mWifiReceiver, filter);

2-5、在packages/apps/Launcher3/src/com/android/launcher3下创建一个数据库名为 AppListDatabaseHelper.java,代码如下:

package com.android.launcher3;
 
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.util.Log;
 
public class AppListDatabaseHelper extends SQLiteOpenHelper {
 
    // 数据库名称
    private static final String DATABASE_NAME = "appdatabase.db";
    // 数据库版本
    private static final int DATABASE_VERSION = 1;
 
    public AppListDatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        if (!isTableExists("mytable",db)) {
            Log.d("++++++++++++++++++++++++","--------------------------------");
            // 创建表的操作
            String CREATE_TABLE = "CREATE TABLE " + "mytable" + "("
                + "ID" + " INTEGER PRIMARY KEY AUTOINCREMENT," + "NAME" + " TEXT," + "CLASSNAME" + " TEXT"
                + ")";
            db.execSQL(CREATE_TABLE);
            // 插入数据
            // String INSERT_DATA = "INSERT INTO " + "mytable" + " (NAME,CLASSNAME) VALUES ('mypopup,mypopup')";
            // db.execSQL(INSERT_DATA);
        }
        // db.execSQL(CREATE_TABLE);
        // setDefaultLabel(db); // 传递当前的数据库实例
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 更新数据库
        db.execSQL("DROP TABLE IF EXISTS " + "mytable");
        onCreate(db);
    }
 
    public boolean isTableExists(String tableName,SQLiteDatabase db) {
        
        Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table' AND name=?", new String[] {tableName});
        Log.d("++++++++++++++++++++++++++++++++++++++","isTableExists");
        if (cursor != null) {
            if(cursor.getCount() > 0) {
                cursor.close();
                Log.d("++++++++++++++++++++++++++++++++++++++","isTableExists=true");
                return true;
            }
            cursor.close();
        }
        Log.d("++++++++++++++++++++++++++++++++++++++","isTableExists=false");
        return false;
    }
}

2-6、对新安装的应用进行排序并且需要注意开机后第一次加载排序时对最开的排序要保持不变,有个软件需要始终第一位,新安装的软件需要排在它后面,然后把这些软件组成一个列表,代码如下:

/**
    *	在系统列表中取得需要排序的APP组成一个列表
    */
   int m = 0;
    private List<AppInfo> getSortArrayApps(){
        Log.d("------------------------------getSortArrayApps","int :"+m);
        m = m+1;
	//需要排序的APP的包名和启动类
	 String[] appPackageAndClassName = new String[]{
        //联系人,时钟,文档,音乐
			// "com.android.contacts/com.android.contacts.activities.PeopleActivity",
			// "com.android.deskclock/com.android.deskclock.DeskClock",
			// "com.android.documentsui/com.android.documentsui.LauncherActivity",
            // "com.android.music/com.android.music.MusicBrowserActivity"
		};
	 String packageName = null;
	 String className = null;
	 List<AppInfo> sortAppsArray = new ArrayList<>();
     List<AppInfo> sortAppsArray2 = new ArrayList<>();
     if(dataListName.isEmpty()){
        DataBase();
     }

	 for(int i=0; i<dataListName.size(); i++){		
			packageName = dataListName.get(i);
			className = dataListClassName.get(i);
            Log.d("-----------------------------------","packageName:   "+packageName);
            Log.d("-----------------------------------","className:   "+className);
            // sortAppsArray.add(dataListName.get(i)+"/"+dataListClassName.get(i));
			for(int j=0; j<mApps.size(); j++){
				if(mApps.get(j).componentName.getPackageName().equals(packageName)
					&& mApps.get(j).componentName.getClassName().equals(className)){	
                    sortAppsArray2.add(mApps.get(j));
                    sortAppsArray.addAll(sortAppsArray2);
                    Log.d("-----------------------------------","--------sortAppsArray:   "+sortAppsArray);
					break;
				}
			}
            for(int j=0; j<sortAppsArray2.size(); j++){
                if(sortAppsArray2.get(j).componentName.getPackageName().equals("com.leyyy.mypopup")
					&& sortAppsArray2.get(j).componentName.getClassName().equals("com.leyyy.mypopup.MainActivity")){
                        sortAppsArray.clear();
                        sortAppsArray.add(0,sortAppsArray2.get(j));
                        sortAppsArray2.removeAll(sortAppsArray);
                        sortAppsArray.addAll(sortAppsArray2);
                        break;
                }
            }
		}
        Log.d("-----------------------------------","++++++++sortAppsArray:   "+sortAppsArray);
		return sortAppsArray;
	}

2-7、在系统列表中取得不需要排序的APP组成一个列表,代码如下

/**
    *	在系统列表中取得不需要排序的APP组成一个列表
    */
   int c = 0;
    private List<AppInfo> getOutArrayApps(){
         Log.d("------------------------------getOutArrayApps","int :"+c);
          c = c+1; 
		List<AppInfo> outAppsArray = new ArrayList<>(mApps);
		//从mApps中移除需要排序的应用
		outAppsArray.removeAll(getSortArrayApps());
        Collections.sort(outAppsArray, mAppNameComparator);
		return outAppsArray;
	}

2-8、然后就是把这两个列表组合起来就是最终在桌面抽屉里展示的图标列表,代码如下

/**
    *	将需要排序的和不需排序的列表传入,当排序列表放在前面
    */
   int q = 0;
    private void setAndSortNewAllApps(){
        Log.d("------------------------------setAndSortNewAllApps","int :"+q);
        q = q+1;
	 List<AppInfo> newAppsArray = new ArrayList<>();
	 List<AppInfo> arrayApps = getSortArrayApps();
	 List<AppInfo> notArrayApps = getOutArrayApps();
		
	 if(arrayApps.size()>0 && notArrayApps.size()>0){
			//对集合2进行排序
			Collections.sort(notArrayApps, mAppNameComparator);
			if(false){
				//合并集合1和2,并将集合1放在后面
				notArrayApps.addAll(arrayApps);
				newAppsArray = notArrayApps;
			}else{
				//合并集合1和2,并将集合1放在前面
				arrayApps.addAll(notArrayApps);
				newAppsArray = arrayApps;
			}
			//将集合mApps清空				
			mApps.clear();
			//将集合1和集合2合并后放入mApps集合
            Log.d("-----------------------------------","-------+++++++-newAppsArray:   "+newAppsArray);
			mApps.addAll(newAppsArray);
		}

        // mApps.clear();
        // mApps.addAll(newAppsArray);

	}

2-9、 在AlphabeticalAppsList.java中的onAppsUpdated()方法下调用2-8的方法,并且注释掉一些内容就可以了,代码如下:

最后就完成:指定第三方软件(mypopup) 始终排在第一位,其他新安装的软件按照安装时间排在这个软件后面,剩下的系统软件按照安装时间排在第三方软件后面。

最后的最后,欢迎友好交流!!!!

### 实现按字母顺序排列主屏幕应用程序图标Android 设备上,默认情况下,许多 Launcher 应用程序已经支持按照字母顺序对桌面图标进行排序。如果需要确保这一功能正常工作或自定义实现该功能,则可以参考以下方法。 对于大多数标准的 Android Launcher 而言,应用程序列表通常是基于 `AlphabeticalAppsList` 类来管理并保持有序状态[^2]。此组件负责收集所有已安装的应用信息,并依据其标签名(即应用名称)创建一个经过排序的数据集。为了保证图标能按照字母顺序展示: - **确认现有行为**: 验证当前使用的 Launcher 是否提供了选项让用户选择不同的排序方式。 - **调整设置**: 如果存在这样的配置项,可以通过进入设备的设置菜单找到关于主屏布局或者应用抽屉的相关设定来进行更改。 当涉及到修改源代码以强制执行特定排序逻辑时,主要关注点在于 `AppInfoComparator` 这样的比较器类[^3]。这类工具用于定义两个项目之间的相对位置关系;因此,在这里应该重写其中的方法使得对比操作遵循 ASCII 或 Unicode 字符编码规则下的字典序原则。 另外值得注意的是,某些第三方 Launcher 可能会有自己独特的机制去处理这个问题,所以具体实施细节可能会有所差异。但对于官方 AOSP (Android Open Source Project) 提供的基础版本来说,上述路径是比较通用的做法。 ```java // 修改 AppInfoComparator 中的 compare 方法示例 public int compare(AppInfo a, AppInfo b) { String labelA = a.getLabel().toLowerCase(); String labelB = b.getLabel().toLowerCase(); return labelA.compareTo(labelB); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值