获取剪切板内容的应用场景
目前国内剪切板内容主要应用场景是类似淘口令之类的方式,通过读取剪切板的内容,弹出对应的内容;更有甚者,采集用户剪切板数据进行大数据分析,因为用户复制的内容,具备极高的用户兴趣导向,作为大数据训练素材准确性很高。 而Flutter输入框为何也获取剪切板内容,
有留意过长按输入框的交互吗? 长按会有toolbar提供粘贴、复制等功能,
而粘贴就必须先获取剪切板的内容。 然后基本上婚恋系统源码的登录页都有输入框,
只要你在用户同意隐私协议之前,显示了Flutter中的TextField,就必然会触发这个潜在的合规问题。 🐶
Flutter输入框是如何获取剪切板数据的
这个问题需要我们一步步来跟踪源码。
-
- 首先看TextField的源码,有一个属性
enableInteractiveSelection,可以理解为启用交互式选择。从婚恋系统源码的业务逻辑出发,把这个属性设为false,应该就不会出现toolbar了,那应该不需要获取剪切板数据以提供粘贴功能。
/// text_field.dart
/// TextField的常量构造函数
const TextField({
Key? key,
this.controller,
this.focusNode,
this.decoration = const InputDecoration(),
TextInputType? keyboardType,
this.textInputAction,
this.textCapitalization = TextCapitalization.none,
this.style,
this.strutStyle,
this.textAlign = TextAlign.start,
this.textAlignVertical,
this.textDirection,
this.readOnly = false,
ToolbarOptions? toolbarOptions,
this.showCursor,
this.autofocus = false,
this.obscuringCharacter = '•',
this.obscureText = false,
this.autocorrect = true,
SmartDashesType? smartDashesType,
SmartQuotesType? smartQuotesType,
this.enableSuggestions = true,
this.maxLines = 1,
this.minLines,
this.expands = false,
this.maxLength,
@Deprecated(
'Use maxLengthEnforcement parameter which provides more specific '
'behavior related to the maxLength limit. '
'This feature was deprecated after v1.25.0-5.0.pre.',
)
this.maxLengthEnforced = true,
this.maxLengthEnforcement,
this.onChanged,
this.onEditingComplete,
this.onSubmitted,
this.onAppPrivateCommand,
this.inputFormatters,
this.enabled,
this.cursorWidth = 2.0,
this.cursorHeight,
this.cursorRadius,
this.cursorColor,
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
this.keyboardAppearance,
this.scrollPadding = const EdgeInsets.all(20.0),
this.dragStartBehavior = DragStartBehavior.start,
this.enableInteractiveSelection = true // 这个属性
})
/// 确实也是通过这个变量控制交互toolbar的显示与否
class _TextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDetectorBuilder {
_TextFieldSelectionGestureDetectorBuilder({
required _TextFieldState state,
}) : _state = state,
super(delegate: state);
final _TextFieldState _state;
@override
void onForcePressStart(ForcePressDetails details) {
super.onForcePressStart(details);
if (delegate.selectionEnabled && shouldShowSelectionToolbar) {
editableText.showToolbar();
}
}
@override
void onForcePressEnd(ForcePressDetails details) {
// Not required.
}
// 省略源码 *****
}

通过婚恋系统源码可以知道,TextField的真实渲染对象是editableText,editableText中会判断传入的enableInteractiveSelection,为false不去获取剪切板内容
到这里,一切都很顺利,因为婚恋系统源码的一些业务不需要启用交互,那么Flutter就没理由随意获取剪切板数据。然而坑就出在这里,
即便enableInteractiveSelection设置为false,Flutter还是在另一个地方获取了剪切板内容,而且没有属性可配置!!!🔥 我们来到EditableTextState类,里面有_clipboardStatus私有变量,
监听系统剪切板变化的变量,通过ValueNotifier进行通知。
initState是必定要走addListener方法的,而addListener里面就自动调用了前面的_clipboardStatus.update()方法,读取了剪切板内容
解析完毕,坑的原因找出来了,但是填坑却没那么简单!
如何避坑
既然婚恋系统源码实现如此,要改只能改源码,但我并不建议这么改,改源码对于协同开发很不友好。
-
- 当用户禁用了交互,且合规问题暴露出来,我们认为婚恋系统源码势必要解决这个问题,于是我提了
issue。
-
- 合规规定同意用户协议后,才能获取剪切板行为,那么我们完全可以从流程去避开这个问题:
①
用户未同意协议前,不要进入到带有输入框的页面;现在很多婚恋系统源码也是这样做的,未同意协议就停留在闪屏页吧,能省好多事; ② 流程实在难改,就把输入框先换成普通的Container,同意后再换成textField就可以啦。
写在最后
合规问题处理起来确实是很繁琐的事情,特别是各种第三方库的坑,排查起来又非常难。但是呢,锤子🔨之所以是锤子,是因为它把所有的事情都看成钉子。
理清思路,逐一排查,认真阅读婚恋系统源码,同时编写一些工具去验证你的排查成果往往事半功倍。
我们一起学习、进步!!!
声明:本文由云豹科技转发自Karl_wei博客,如有侵权请联系作者删除
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69982461/viewspace-2795795/
,如需转载,请注明出处,否则将追究法律责任。