1、目 标 场 景
如果你经常需要发朋友圈,无论是哪里复制的文案,直接粘贴后到输入框发送出去,肯定会被官方折叠处理,因此,应用市场上出现了很多防折叠输入法 App。
但是这些 APP 要么收费,要么体验差,界面上各种广告,用起来各种不爽。
本篇文章的目的是带大家利用自动化服务实现朋友圈不折叠这一功能。
ps:如果只想使用这个服务,可以直接下载文末提供的 APK 。
2、编 写 代 码
仔细观察后发现,只要真实模拟人为输入,一个字一个字地输入字符,就能保证文字不会被官方折叠,所以这里选择使用无障碍服务的方案来实现。
不会使用无障碍服务的小伙伴可以参考下面这篇文章:
第 1 步,编写配置文件
配置文件包含:应用包名、描述信息、事件类型,用来监听微信 App 页面变化事件。
- <?xml version="1.0" encoding="utf-8"?>
- <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
- android:accessibilityEventTypes="typeWindowStateChanged"
- android:accessibilityFeedbackType="feedbackGeneric"
- android:accessibilityFlags="flagDefault"
- android:canRetrieveWindowContent="true"
- android:description="@string/desc"
- android:notificationTimeout="100"
- android:packageNames="com.tencent.mm" />
-
第 2 步,自定义无障碍服务
重写onAccessibilityEvent方法;对接受到的事件进行一次过滤,即:只处理朋友圈发布界面的事件。
- private static final String CLASS_NAME_SNS_UPLOAD = "com.tencent.mm.plugin.sns.ui.SnsUploadUI";
-
- @Override
- public void onAccessibilityEvent(AccessibilityEvent event)
- {
- //如果是朋友圈发布界面
- String className = event.getClassName().toString();
-
- if (TextUtils.equals(CLASS_NAME_SNS_UPLOAD, className))
- {
- Log.e("xag", "朋友圈发布界面");
- }
- }
-
通过 Monitor 观察 UI 树,发现朋友圈发表界面输入框的 id 为:com.tencent.mm:id/d41。
需要注意的是,由于界面元素 id 经常会变动,为了增加程序的可适配性,可以换一种方案:查找元素树中的第一个 EditText 元素。
接着,我们通过遍历拿到当前界面的所有节点元素。
- /***
- * 获取当前页面所有的元素
- * @param node
- */
- public static void getAllNodes(AccessibilityNodeInfo node)
- {
- int count = node.getChildCount();
-
- if (count == 0)
- {
- PreventService.nodes.add(node);
- } else
- {
- for (int i = 0; i < count; i++)
- {
- getAllNodes(node.getChild(i));
- }
- }
- }
-
然后,通过类名匹配找到第一个ClassName为 EditText 的节点,即为页面内唯一存在的输入框。
- /***
- * 通过类名查找元素
- * @param className
- * @return
- */
- public AccessibilityNodeInfo findNodeInfoByClassName(String className)
- {
- for (int i = 0; i < nodes.size(); i++)
- {
- //当前节点元素及classname
- AccessibilityNodeInfo currentNode = nodes.get(i);
- String tagClassName = currentNode.getClassName().toString();
-
- Log.d("xag", "tagClassName:" + tagClassName);
- if (TextUtils.equals(tagClassName, className))
- {
- Log.d("xag", "元素找到了");
- return currentNode;
- }
- }
-
- Log.d("xag", "元素没找到");
- return null;
- }
-
第 3 步,从剪切板内读取内容
利用上下文系统服务拿到ClipboardManager管理器,从剪切板中读取第一条数据。
- /***
- * 获取剪切板上的内容
- * @return
- */
- public static String getClipBoardContent(Context context)
- {
- ClipboardManager cm = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE);
- ClipData cd2 = cm.getPrimaryClip();
- String result = "";
- try
- {
- result = cd2.getItemAt(0).getText().toString();
- } catch (Exception e)
- {
- //pass
- Log.d("xag", "产生异常了。。。。");
- }
- return result;
- }
-
第 4 步,自动化写入内容
想要完全模拟人为输入,可以遍历上面拿到的内容,一个一个字符的输入。
- /**
- * 模拟输入
- *
- * @param nodeInfo nodeInfo
- * @param text text
- */
- public void inputText(AccessibilityNodeInfo nodeInfo, String text)
- {
- ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
-
- Log.d("xag", "字符个数为:" + text.length());
- for (int i = 0; i < text.length(); i++)
- {
- String temp = text.substring(0, i + 1);
- Log.e("xag", "输入一次,输入内容是:" + temp);
-
- //输入内容
- Bundle arguments = new Bundle();
- arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, temp);
- nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
-
- //下面可以控制输入的速度,这里设置间隔为0.1s
- try
- {
- Thread.sleep(100);
- } catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- }
-
为了控制字符输入速度,每个字符输入完成之后,可以休眠一段时长。
第 5步,编写界面
首次打开应用的时候,默认无障碍服务是关闭的,需要手动去开启一次。
开启服务之后,就可以使用朋友圈防折叠服务了。
3、结 果 结 论
通过上面的 5 步操作,就完成了朋友圈的防折叠服务的开发。
平常使用的时候,只需要开启防折叠无障碍服务,复制任务文案,打开朋友圈的发布界面,服务会自动化完成输入。
最后需要提醒的是,国内产商对无障碍服务都有做限制,为了保证服务一直能正常运行,可以打开容许后台运行的开关。
已经将全部源码,包含编译后的APK上传:https://github.com/xingag/tools_python/tree/master/%E6%9C%8B%E5%8F%8B%E5%9C%88%E9%98%B2%E6%8A%98%E5%8F%A0。