您的位置:首页 > 移动开发 > Android开发

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

2016-11-29 14:44 330 查看
`本来安卓创建桌面小图标大家都知道是有系统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安装界面,完成后生产小图标,接下里就是自己的业务了!!!!有没有很屌













内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息