Android通过queryIntentActivities自定义发送功能
- 一、目标
- 二、功能设计
- 三、准备工作
- 1. 查询列表
- 2. 处理排序
- 3. 启动指定的Activity
- 四、组合起来
- 1. ResolveProvider
- 2. ResolveViewHolder
- 3. ResolveEntity
- 4. ResolveComparator
- 五、Final
一、目标
自定义发送功能,使列表按指定顺序排列。
1. 实现效果
第二栏显示的为支持发送的第三方应用列表。
2. 下载地址
神马笔记最新版本:【神马笔记 版本1.2.0.apk】
二、功能设计
通过Context#startActivity()可以直接调用手机上的第三方应用。
但是无法控制第三方应用的显示顺序,比例“发送给朋友”、“发送到朋友圈”、“微博”是我比较经常使用的应用。通过直接调用startActivity()无法保证显示在前3个的位置。
因此,我们需要自定义发送的功能。
三、准备工作
1. 查询列表
PackageManager
提供了3个方法用于查询Intent相应的Activity。
public abstract List<ResolveInfo> queryIntentActivities(Intent intent,&#64;ResolveInfoFlags int flags);public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,&#64;ResolveInfoFlags int flags, &#64;UserIdInt int userId);public abstract List<ResolveInfo> queryIntentActivityOptions(&#64;Nullable ComponentName caller,&#64;Nullable Intent[] specifics, Intent intent, &#64;ResolveInfoFlags int flags);
调用第一个方法可以获取到ResolveInfo列表。
2. 处理排序
排序分成2个部分。
- 指定排序顺序
- 按名称排序
通过配置文件&#xff0c;指定优先显示的Activity及先后顺序。不在配置文件中的Activity则按名称进行排序。
以下是神马笔记使用的配置文件&#xff0c;按照个人使用频率进行了排序。
{"list":[{"id": "com.tencent.mm.ui.tools.ShareImgUI","name": "发送给朋友"},{"id": "com.tencent.mm.ui.tools.ShareToTimeLineUI","name": "发送到朋友圈"},{"id": "com.sina.weibo.composerinde.ComposerDispatchActivity","name": "微博"},{"id": "com.weico.international.activity.compose.SeaComposeActivity","name": "微博国际版"},{"id": "com.tencent.mobileqq.activity.JumpActivity","name": "发送给好友"},{"id": "com.alibaba.android.rimet.biz.BokuiActivity","name": "钉钉"},{"id": "com.tencent.mm.ui.tools.AddFavoriteUI","name": "添加到微信收藏"},{"id": "com.tencent.mobileqq.activity.qfileJumpActivity","name": "发送到我的电脑"},{"id": "cooperation.qlink.QlinkShareJumpActivity","name": "面对面快传&#xff08;免流量&#xff09;"},{"id": "com.sina.weibo.weiyou.share.WeiyouShareDispatcher","name": "私信"},{"id": "cooperation.qqfav.widget.QfavJumpActivity","name": "保存到QQ收藏"}]
}
3. 启动指定的Activity
通过设置Intent#setComponent()可以指定启动的Activity。
String pkg &#61; resolveInfo.activityInfo.packageName;
String cls &#61; resolveInfo.activityInfo.name;
ComponentName cn &#61; new ComponentName(pkg, cls);
intent.setComponent(cn);
四、组合起来
1. ResolveProvider
为RecyclerView提供数据。
private static class ResolveProvider implements ClazzAdapterProvider<ResolveEntity> {List<ResolveEntity> list;ResolveProvider(Activity context, Intent[] intents) {{this.list &#61; new ArrayList<>();}{PackageManager pm &#61; context.getPackageManager();for (int i &#61; 0; i < intents.length; i&#43;&#43;) {Intent intent &#61; intents[i];List<ResolveInfo> list &#61; pm.queryIntentActivities(intent, 0);for (ResolveInfo info : list) {this.add(context, info);}}}}void add(Activity context, ResolveInfo resolveInfo) {if (indexOf(resolveInfo.activityInfo.name) >&#61; 0) {return;}list.add(new ResolveEntity(context, resolveInfo));}int indexOf(String id) {ResolveEntity entity &#61; list.stream().filter(e -> e.getId().equals(id)).findAny().orElse(null);if (entity &#61;&#61; null) {return -1;}return list.indexOf(entity);}void sort(Comparator<ResolveEntity> comparator) {list.sort(comparator);}&#64;Overridepublic ResolveEntity get(int position) {return list.get(position);}&#64;Overridepublic int size() {return list.size();}
}
需要注意的是这里使用Intent[]数组&#xff0c;而不是单个Intent。
Intent[] intents &#61; new Intent[] {new Intent().setAction(Intent.ACTION_SEND).setType("*/*"),new Intent().setAction(Intent.ACTION_SEND).setType("image/*")
};
原先使用的第一个Intent&#xff0c;setType("*/*")
&#xff0c;这种方式无法获取到微信7.0.0的发送到朋友圈功能&#xff0c;必须通过setType("image/*")
方式才能实现。
因此&#xff0c;使用Intent[]数组方式最为保险。
2. ResolveViewHolder
RecyclerView的ViewHolder实现。
private class ResolveViewHolder extends BridgeViewHolder<ResolveEntity> {static final int LAYOUT_RES_ID &#61; R.layout.layout_action_list_item;ImageView iconView;TextView nameView;&#64;Keeppublic ResolveViewHolder(View itemView) {super(itemView);}&#64;Overridepublic int getLayoutResourceId() {return LAYOUT_RES_ID;}&#64;Overridepublic void onViewCreated(&#64;NonNull View view) {view.setOnClickListener(this::onItemClick);this.iconView &#61; view.findViewById(R.id.iv_icon);iconView.setClipToOutline(true);this.nameView &#61; view.findViewById(R.id.tv_name);}&#64;Overridepublic void onBind(ResolveEntity item, int position) {iconView.setImageDrawable(item.getIcon());nameView.setText(item.getTitle());}void onItemClick(View view) {dismiss();if (onResolveItemClickListener !&#61; null) {onResolveItemClickListener.onResolveItemClick(getItem().item);}}
}
3. ResolveEntity
包装了一下ResolveInfo&#xff0c;方便调用。
private static class ResolveEntity {ResolveInfo item;Activity context;ResolveEntity(Activity context, ResolveInfo item) {this.context &#61; context;this.item &#61; item;}String getId() {return item.activityInfo.name;}Drawable getIcon() {return item.loadIcon(context.getPackageManager());}CharSequence getTitle() {return item.loadLabel(context.getPackageManager());}}
4. ResolveComparator
ResolveEntity的比较器&#xff0c;实现排序。
通过传入的ID列表实现排序。
private static class ResolveComparator implements Comparator<ResolveEntity> {List<String> array;ResolveComparator(List<String> array) {this.array &#61; array;}int indexOf(String id) {int index &#61; -1;for (int i &#61; 0; i < array.size(); i&#43;&#43;) {if (array.get(i).equalsIgnoreCase(id)) {index &#61; i;break;}}return index;}int getPriority(String id) {int index &#61; indexOf(id);if (index < 0) {return index;}return array.size() - index;}&#64;Overridepublic int compare(ResolveEntity o1, ResolveEntity o2) {int p1 &#61; getPriority(o1.getId());int p2 &#61; getPriority(o2.getId());return (p2 - p1);}
}
五、Final
除了更新到微信7.0.0版本时&#xff0c;发现无法获取到发送到朋友圈外&#xff0c;一切工作如预期展开。
最后的最后&#xff0c;还是存在的一个问题。
同一篇笔记&#xff0c;生成了同样的图片&#xff0c;同样通过微信发送。
发送方式 | 结果 |
---|
发送给朋友 | 清晰 |
发送到朋友圈 | 模糊&#xff0c;图片被压缩 |
添加到微信收藏 | 清晰 |
发送到朋友圈的图片变得模糊&#xff0c;被压缩过&#xff0c;另外2种方式是清晰的。
&#xff5e;奈何&#xff5e;奈何&#xff5e;