Android桌面小图标终极解决方案

来源:互联网 发布:网络节点怎么查 编辑:程序博客网 时间:2024/06/08 07:07

`本来安卓创建桌面小图标大家都知道是有系统Api的,也很简单,但是有些定制神机改了后就比较蛋疼了,像OPPO的ColorOS3.0。但是都出自与安卓原理基本都是一样的,一般桌面的东西都会保存在一个叫launcher数据库里面,路径的话不同手机可能不太一样,一般是以xxx.xxx.xxx.launcher目录下,通过代码也是可以获取的,launcher数据库里面的几张表就是放这些东西的,有一张叫favorites(OPPOColor3.0叫singledesktopitems)的表就是放桌面图标信息的。所以不管你怎么做最后还是把图标信息插入这里。


要操作这种系统的数据库一般是通过Content Provider,所以第一步是拿到uri,之后无非就

是增删改查的一些炒作。这种直接操作数据库的方式除了麻烦点很实用,如果开发中遇到不能添

加的可以这样尝试。

系统Api创建的方法:

 Intent addShortcutIntent = new Intent(ACTION_ADD_SHORTCUT);        // 是否允许重复创建        addShortcutIntent.putExtra("duplicate", allowRepeat);        // 快捷方式的标题        addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);        // 快捷方式的图标        addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, iconBitmap);        // 快捷方式的动作        addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent);        context.sendBroadcast(addShortcutIntent);
直接插入数据库的方式:

private void addShortCut2DB() {        Uri uriFromLauncher = getUriFromLauncher(this);        ContentValues contentValues = new ContentValues();        contentValues.put("title","剑西");//        id尽量大点,严谨点可以先查询数据库现在最大id是多少然后往后+1        contentValues.put("_id",4855);//        这里自己定义intent        contentValues.put("intent","#Intent;action=android.intent.action.CREATE_SHORTCUT;category=android.intent.category.DEFAULT;component=com.henanjianye.soon.communityo2o/.activity.OpenDoor2Shortcut;end");//       改成自己的包名        contentValues.put("packageName","com.henanjianye.soon.communityo2o");        contentValues.put("container",-100);        contentValues.put("screenId",1005);        contentValues.put("cellX",2);        contentValues.put("cellY",2);        contentValues.put("spanX",1);        contentValues.put("spanY",1);        contentValues.put("itemType",1);        contentValues.put("appWidgetId",-1);        contentValues.put("iconType",1);        contentValues.put("modelState",0);        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);        ByteArrayOutputStream baos = new ByteArrayOutputStream();        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);        contentValues.put("icon",  baos.toByteArray());        getContentResolver().insert(uriFromLauncher,contentValues);    }    private String getAuthorityFromPermissionDefault(Context context) {        return getAuthorityFromPermission(context, "com.android.launcher.permission.READ_SETTINGS");    }    private Uri getUriFromLauncher(Context context) {        StringBuilder uriStrBuilder = new StringBuilder();        //为了速度考虑,这里我们先查找默认的 看是否能查找到 因为多数手机的rom还是用的默认的lanucher        String authority = getAuthorityFromPermissionDefault(context);        //如果找不到的话 就说明这个rom一定是用的其他的自定义的lanucher。那就拼一下 这个自定义的lanucher的permission再去查找一次        if (authority == null || authority.trim().equals("")) {            authority = getAuthorityFromPermission(context, getCurrentLanucherPackageName(context) + ".permission.READ_SETTINGS");        }        uriStrBuilder.append("content://");        //如果连上面的方法都查找不到这个authority的话 那下面的方法 就肯定查找到了 但是很少有情况会是如下这种        //多数都是else里面的逻辑        if (TextUtils.isEmpty(authority)) {            int sdkInt = android.os.Build.VERSION.SDK_INT;            if (sdkInt < 8) { // Android 2.1.x(API 7)以及以下的                uriStrBuilder.append("com.android.launcher.settings");            } else if (sdkInt < 19) {// Android 4.4以下                uriStrBuilder.append("com.android.launcher2.settings");            } else {// 4.4以及以上                uriStrBuilder.append("com.android.launcher3.settings");            }        } else {            uriStrBuilder.append(authority);        }        uriStrBuilder.append("/favorites?notify=true");        return Uri.parse(uriStrBuilder.toString());    }    //此函数返回 要查找的permission的 provider的 authority    private String getAuthorityFromPermission(Context context, String permission) {        //返回安装的app的 provider的信息        List<PackageInfo> packs = context.getPackageManager().getInstalledPackages(PackageManager.GET_PROVIDERS);        //遍历获取到的安装包的信息        for (PackageInfo pack : packs) {            //每个安装包提供的provider 都在这个数组里面            ProviderInfo[] providers = pack.providers;            if (providers != null) {                //遍历每个provider 看需要的权限是否与我们传进来的权限参数相等                for (ProviderInfo providerInfo : providers) {                    if (permission.equals(providerInfo.readPermission) || permission.equals(providerInfo.writePermission)) {                        return providerInfo.authority;                    }                }            }        }        return "";    }    //此函数返回当前rom下的lanucher的包名    private String getCurrentLanucherPackageName(Context context) {        //这个intent很好理解 就是启动lanucher的intent        Intent intent = new Intent(Intent.ACTION_MAIN);        intent.addCategory(Intent.CATEGORY_HOME);        //getPackageManager().resolveActivity 这个函数就是查询是否有符合条件的activity的        ResolveInfo res = context.getPackageManager().resolveActivity(intent, 0);        //为避免空指针 我们要判定下空,虽然你我都知道这种情况不会发生        if (res == null || res.activityInfo == null) {            return "";        }        return res.activityInfo.packageName;    }

当然有写定制机的uri也许不太一样,比如oppo的,它launcher数据库里面的表名称变了,而且变态的加了一张白名单

的表,只要把自己的应用包名加入这个白名单你调用系统Api就能生成桌面小图标。添加方法如下:

 public static void add2OppoWhiteList(Context context) {        if (Build.BRAND.contains("OPPO")) {            try {                ContentValues contentValues = new ContentValues();                contentValues.put("itemName", context.getPackageName());                contentValues.put("itemType", 0);                contentValues.put("_id", 5201314);                context.getContentResolver().insert(ShortcutHelper.getOppoWhiteUriFromLauncher(context), contentValues);            } catch (Exception e) {            }        }    }

终极解决方案:

上面自然可以适配一些机型,但是百家争鸣的Android的并不那么好完全适配,经过我们团队的摸索得出一个通用方案,其实很简单,既然没法创建小图标那么我就不创建呗,安装一个应用后你总得给我创建一个桌面图标吧!当用户点击“创建桌面快捷方式”的时候判断当前用户的机型时候需要采用这种特殊方式创建,如果需要那么跳转的APK安装界面,完成后生产小图标,接下里就是自己的业务了!!!!有没有很屌









0 0
原创粉丝点击