Clipboard是Android提供的一个系统服务,它提供了一个全局的剪贴板,让文字、图片、数据,在多App间共享成为可能,今天,咱们来了解下它的真面目,以及被玩坏的新姿式。javascript
老规矩,Google API文档镇楼:
developer.android.com/guide/topic…html
说实话,若是不是为了让Clipboard玩出花,我真不想写这一篇,由于——这文档写的真是太TM详细了。java
咱们先来看看一些App对Clipboard的应用,例如手机迅雷,若是你复制了一个连接,那么打开迅雷后,会自动检测并提示下载:android
再例如一些翻译软件,例若有道词典、沪江小D,他们都有一个功能,即复制查词,使用的也是这个原理,我这没装这些App,就不截图了,再例如比较经常使用的手淘喵口令,实际上也是利用这个功能,固然,也有一些比较专业的Clipboard App,例如Clipboard Actions:算法
咱们能够看见,实际上,他就是帮你解析了各类可能的剪贴板,并对他们提供了各类后续功能的集合,确实很是实用,不过,看完今天的文章,相信你要写一个这样的App,估计也就分分钟。app
OK,这些就是一些Clipboard的基本使用场景,更多场景,没有作不到,只有想不到。ide
Clipboard的基本使用,就是三部曲。ui
得到ClipboardManager:this
ClipboardManager mClipboardManager = mClipboardManager =
(ClipboardManager) getSystemService(CLIPBOARD_SERVICE);复制代码
Copy:spa
ClipData mClipData;
String text = "hello world";
mClipData = ClipData.newPlainText("test", text);
mClipboardManager.setPrimaryClip(mClipData);复制代码
Paste:
ClipData clipData = mClipboardManager.getPrimaryClip();
ClipData.Item item = clipData.getItemAt(0);
String text = item.getText().toString();复制代码
结束了,简直不能再简单,API文档也写的很是详细,Demo都写了好几个。
咱们能够建立如下三种类型的ClipData:
类型 | 描述 |
---|---|
Text newPlainText(label, text) | 返回ClipData对象,其中ClipData.Item对象包含一个String |
URI newUri(resolver, label, URI) | 返回ClipData对象,其中ClipData.Item对象包含一个URI |
Intent newIntent(label, intent) | 返回ClipData对象,其中ClipData.Item对象包含一个Intent |
对应的,咱们也能获取到不一样类型的ClipData。
ClipboardManager中有不少判断与操做方法:
类型 | 描述 |
---|---|
getPrimaryClip() | 返回剪贴板上的当前Copy内容 |
getPrimaryClipDescription() | 返回剪贴板上的当前Copy的说明 |
hasPrimaryClip() | 若是当前剪贴板上存在Copy返回True |
setPrimaryClip(ClipData clip) | 设置剪贴板上的当前Copy |
setText(CharSequence text) | 设置文本到当前Copy |
getText() | 获取剪贴板复制的文本 |
在了解了上面这些内容后,咱们就能够作一些比较有意思的东西了,例如,咱们能够经过监控用户剪贴板中的内容,来作一些自动的推断,例如,用户复制了一个英文单词,那么咱们能够推断,用户可能要进行翻译,再例如,用户复制了一个连接,那么咱们也能够推断,用户可能须要打开这个连接,等等。
Google在文档中,直接给出了示例的代码:
// Examines the item on the clipboard. If getText() does not return null, the clip item contains the
// text. Assumes that this application can only handle one item at a time.
ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
// Gets the clipboard as text.
pasteData = item.getText();
// If the string contains data, then the paste operation is done
if (pasteData != null) {
return;
// The clipboard does not contain text. If it contains a URI, attempts to get data from it
} else {
Uri pasteUri = item.getUri();
// If the URI contains something, try to get text from it
if (pasteUri != null) {
// calls a routine to resolve the URI and get data from it. This routine is not
// presented here.
pasteData = resolveUri(Uri);
return;
} else {
// Something is wrong. The MIME type was plain text, but the clipboard does not contain either
// text or a Uri. Report an error.
Log.e("Clipboard contains an invalid data type");
return;
}
}复制代码
其实很是简单,就是判断三种复制类型,可是咱们能够在App中设置一些相似Scheme的标记,用来进行一些功能的区分,就好像淘宝的喵口令——『喵口令XXXXXXX喵口令』,咱们能够经过解析这些Scheme,来获取内容,并进行对应的操做。这也是咱们前面提到的Clipboard Actions这个App作的事情。
咱们首先来看ClipData.Item.coerceToText()这样一个方法,这个方法能够将剪贴板里面的内容,直接转化为文字,可是这个转换,是有必定算法的,在API文档中有比较详细的说明,这里简单的看下:
这个东西能干什么呢,咱们知道,有些App会复制以后,打开一个Intent,为了简单,会直接经过ClipData.Item.coerceToText()来返回一个Intent的URI,而后经过解析URI来启动Intent,那么这里就能够被咱们来利用了。
public void fakeClipboard() {
// 添加一个假的Intent,模拟用户最新加入的剪贴板内容
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.hjwordgames", "com.hjwordgames.Splash"));
intent.setAction("android.intent.action.VIEW");
ClipData setClipData;
setClipData = ClipData.newIntent("intent", intent);
mClipboardManager.setPrimaryClip(setClipData);
// 呵呵哒 App觉得获取的是本身须要的Intent,结果却被狸猫换太子
ClipData clipData = mClipboardManager.getPrimaryClip();
ClipData.Item myItem;
myItem = clipData.getItemAt(0);
String clipDataString = myItem.coerceToText(this.getApplicationContext()).toString();
try {
Intent myIntent = Intent.parseUri(clipDataString, 0);
startActivity(myIntent);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}复制代码
其实不必定是经过Fake Intent,其它的文字、图片等等,均可以被『偷天换日』。
另外,要实现这个监听,咱们须要注册一个回调——addPrimaryClipChangedListener,Android真是体贴到没朋友:
mClipboardManager.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
@Override
public void onPrimaryClipChanged() {
Log.d("xys", "onPrimaryClipChanged: ");
}
});复制代码
那么在这里,咱们就能够彻底实现剪贴板的『狸猫换太子』。那么假如咱们是一个『某淘』软件的竞品,那么彻底可让『汪口令』失效,甚至替换为咱们本身的应用,同理,还有一些翻译类软件也是同样,不过还好,也许是个人心里比较阴暗,目前尚未看见这样的App。
欢迎关注个人公众号: