Android通过queryIntentActivities自定义发送功能

Android通过queryIntentActivities自定义发送功能

一、目标

自定义发送功能,使列表按指定顺序排列。

1. 实现效果

第二栏显示的为支持发送的第三方应用列表。

2. 下载地址

神马笔记最新版本:【神马笔记 版本1.2.0.apk

二、功能设计

通过Context#startActivity()可以直接调用手机上的第三方应用。

但是无法控制第三方应用的显示顺序,比例“发送给朋友”、“发送到朋友圈”、“微博”是我比较经常使用的应用。通过直接调用startActivity()无法保证显示在前3个的位置。

因此,我们需要自定义发送的功能。

三、准备工作

1. 查询列表

PackageManager提供了3个方法用于查询Intent相应的Activity。

1
2
3
4
5
6
7
8
public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
@ResolveInfoFlags int flags);

public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
@ResolveInfoFlags int flags, @UserIdInt int userId);

public abstract List<ResolveInfo> queryIntentActivityOptions(@Nullable ComponentName caller,
@Nullable Intent[] specifics, Intent intent, @ResolveInfoFlags int flags);

调用第一个方法可以获取到ResolveInfo列表。

2. 处理排序

排序分成2个部分。

  1. 指定排序顺序
  2. 按名称排序

通过配置文件,指定优先显示的Activity及先后顺序。不在配置文件中的Activity则按名称进行排序。

以下是神马笔记使用的配置文件,按照个人使用频率进行了排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{
"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": "面对面快传(免流量)"
},
{
"id": "com.sina.weibo.weiyou.share.WeiyouShareDispatcher",
"name": "私信"
},
{
"id": "cooperation.qqfav.widget.QfavJumpActivity",
"name": "保存到QQ收藏"
}

]
}

3. 启动指定的Activity

通过设置Intent#setComponent()可以指定启动的Activity。

1
2
3
4
String pkg = resolveInfo.activityInfo.packageName;
String cls = resolveInfo.activityInfo.name;
ComponentName cn = new ComponentName(pkg, cls);
intent.setComponent(cn);

四、组合起来

1. ResolveProvider

为RecyclerView提供数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private static class ResolveProvider implements ClazzAdapterProvider<ResolveEntity> {

List<ResolveEntity> list;

ResolveProvider(Activity context, Intent[] intents) {

{
this.list = new ArrayList<>();
}

{
PackageManager pm = context.getPackageManager();

for (int i = 0; i < intents.length; i++) {

Intent intent = intents[i];
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
for (ResolveInfo info : list) {
this.add(context, info);
}
}
}
}

void add(Activity context, ResolveInfo resolveInfo) {
if (indexOf(resolveInfo.activityInfo.name) >= 0) {
return;
}

list.add(new ResolveEntity(context, resolveInfo));
}

int indexOf(String id) {
ResolveEntity entity = list.stream().filter(e -> e.getId().equals(id)).findAny().orElse(null);
if (entity == null) {
return -1;
}

return list.indexOf(entity);
}

void sort(Comparator<ResolveEntity> comparator) {
list.sort(comparator);
}

@Override
public ResolveEntity get(int position) {
return list.get(position);
}

@Override
public int size() {
return list.size();
}
}

需要注意的是这里使用Intent[]数组,而不是单个Intent

1
2
3
4
Intent[] intents = new Intent[] {
new Intent().setAction(Intent.ACTION_SEND).setType("*/*"),
new Intent().setAction(Intent.ACTION_SEND).setType("image/*")
};

原先使用的第一个Intent,setType("*/*"),这种方式无法获取到微信7.0.0发送到朋友圈功能,必须通过setType("image/*")方式才能实现。

因此,使用Intent[]数组方式最为保险。

2. ResolveViewHolder

RecyclerView的ViewHolder实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private class ResolveViewHolder extends BridgeViewHolder<ResolveEntity> {

static final int LAYOUT_RES_ID = R.layout.layout_action_list_item;

ImageView iconView;
TextView nameView;

@Keep
public ResolveViewHolder(View itemView) {
super(itemView);
}

@Override
public int getLayoutResourceId() {
return LAYOUT_RES_ID;
}

@Override
public void onViewCreated(@NonNull View view) {
view.setOnClickListener(this::onItemClick);

this.iconView = view.findViewById(R.id.iv_icon);
iconView.setClipToOutline(true);

this.nameView = view.findViewById(R.id.tv_name);
}

@Override
public void onBind(ResolveEntity item, int position) {
iconView.setImageDrawable(item.getIcon());
nameView.setText(item.getTitle());
}

void onItemClick(View view) {
dismiss();

if (onResolveItemClickListener != null) {
onResolveItemClickListener.onResolveItemClick(getItem().item);
}
}
}

3. ResolveEntity

包装了一下ResolveInfo,方便调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private static class ResolveEntity {

ResolveInfo item;

Activity context;

ResolveEntity(Activity context, ResolveInfo item) {
this.context = context;

this.item = item;
}

String getId() {
return item.activityInfo.name;
}

Drawable getIcon() {
return item.loadIcon(context.getPackageManager());
}

CharSequence getTitle() {
return item.loadLabel(context.getPackageManager());
}

}

4. ResolveComparator

ResolveEntity的比较器,实现排序。

通过传入的ID列表实现排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
private static class ResolveComparator implements Comparator<ResolveEntity> {

List<String> array;

ResolveComparator(List<String> array) {
this.array = array;
}

int indexOf(String id) {

int index = -1;
for (int i = 0; i < array.size(); i++) {
if (array.get(i).equalsIgnoreCase(id)) {
index = i;
break;
}
}

return index;
}

int getPriority(String id) {
int index = indexOf(id);
if (index < 0) {
return index;
}

return array.size() - index;
}

@Override
public int compare(ResolveEntity o1, ResolveEntity o2) {
int p1 = getPriority(o1.getId());
int p2 = getPriority(o2.getId());

return (p2 - p1);
}
}

五、Final

除了更新到微信7.0.0版本时,发现无法获取到发送到朋友圈外,一切工作如预期展开。

最后的最后,还是存在的一个问题。

同一篇笔记,生成了同样的图片,同样通过微信发送。

发送方式 结果
发送给朋友 清晰
发送到朋友圈 模糊,图片被压缩
添加到微信收藏 清晰

发送到朋友圈的图片变得模糊,被压缩过,另外2种方式是清晰的。

~奈何~奈何~