专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
stormzhang  ·  最后一次通知 ·  17 小时前  
鸿洋  ·  Android Gradle Plugin插件详解 ·  昨天  
鸿洋  ·  简洁高效:类抖音视频列表设计思路 ·  2 天前  
鸿洋  ·  HarmonyOS NEXT启程,送10本入门书籍 ·  5 天前  
51好读  ›  专栏  ›  安卓开发精选

Clipboard 还能玩出花

安卓开发精选  · 公众号  · android  · 2016-11-17 22:54

正文

(点击上方公众号,可快速关注)


来源:伯乐在线专栏作者 - eclipse_xu 

链接:http://android.jobbole.com/85178/

点击 → 了解如何加入专栏作者


Clipboard还能玩出花


Clipboard是Android提供的一个系统服务,它提供了一个全局的剪贴板,让文字、图片、数据,在多App间共享成为可能,今天,我们来了解下它的真面目,以及被玩坏的新姿势。


老规矩,Google API文档镇楼:

https://developer.android.com/guide/topics/text/copy-paste.html


说实话,如果不是为了让Clipboard玩出花,我真不想写这一篇,因为——这文档写的真是太TM详细了。


Clipboard应用


我们先来看看一些App对Clipboard的应用,例如手机迅雷,如果你复制了一个链接,那么打开迅雷后,会自动检测并提示下载:



再例如一些翻译软件,例如有道词典、沪江小D,他们都有一个功能,即复制查词,使用的也是这个原理,我这没装这些App,就不截图了,再例如比较常用的手淘喵口令,实际上也是利用这个功能,当然,也有一些比较专业的Clipboard App,例如Clipboard Actions:



我们可以看见,实际上,他就是帮你解析了各种可能的剪贴板,并对他们提供了各种后续功能的集合,确实非常实用,不过,看完今天的文章,相信你要写一个这样的App,估计也就分分钟。


OK,这些就是一些Clipboard的基本使用场景,更多场景,没有做不到,只有想不到。


基本使用


Clipboard的基本使用,就是三部曲。


获得ClipboardManager:


ClipboardManager mClipboardManager = mClipboardManager =

(ClipboardManager) getSystemService(CLIPBOARD_SERVICE);


Copy:


ClipData mClipData;

span class="hljs-built_in">Stringspan> text = span class="hljs-string">"hello world"span>;

mClipData = ClipData.newPlainText(span class="hljs-string">"test"span>, text);

mClipboardManager.setPrimaryClip(mClipData);


Paste:


ClipData clipData = mClipboardManager.getPrimaryClip();

ClipData.Item item = clipData.getItemAt(span class="hljs-number">0span>);

span class="hljs-built_in">Stringspan> 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管理


ClipboardManager中有很多判断与操作方法:


类型描述
getPrimaryClip()返回剪贴板上的当前Copy内容
getPrimaryClipDescription()返回剪贴板上的当前Copy的说明
hasPrimaryClip()如果当前剪贴板上存在Copy返回True
setPrimaryClip(ClipData clip)设置剪贴板上的当前Copy
setText(CharSequence text)设置文本到当前Copy
getText()获取剪贴板复制的文本


玩出一朵小FaFa


在了解了上面这些内容后,我们就可以做一些比较有意思的东西了,例如,我们可以通过监控用户剪贴板中的内容,来做一些自动的推断,例如,用户复制了一个英文单词,那么我们可以推断,用户可能要进行翻译,再例如,用户复制了一个链接,那么我们也可以推断,用户可能需要打开这个链接,等等。


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做的事情。


玩出一朵大FaFa


我们首先来看ClipData.Item.coerceToText()这样一个方法,这个方法可以将剪贴板里面的内容,直接转化为文字,但是这个转换,是有一定算法的,在API文档中有比较详细的说明,这里简单的看下:



这个东西能干什么呢,我们知道,有些App会复制之后,打开一个Intent,为了简单,会直接通过ClipData.Item.coerceToText()来返回一个Intent的URI,然后通过解析URI来启动Intent,那么这里就可以被我们来利用了。


public span class="hljs-keyword">voidspan> fakeClipboard() {

    span class="hljs-comment">// 添加一个假的Intent,模拟用户最新加入的剪贴板内容

    Intent intent = span class="hljs-keyword">newspan> Intent();

    intent.setComponent(span class="hljs-keyword">newspan> ComponentName(span class="hljs-string">"com.hjwordgames"span>, span class="hljs-string">"com.hjwordgames.Splash"span>));

    intent.setAction(span class="hljs-string">"android.intent.action.VIEW"span>);

    ClipData setClipData;

    setClipData = ClipData.newIntent(span class="hljs-string">"intent"span>, intent);

    mClipboardManager.setPrimaryClip(setClipData);

 

    span class="hljs-comment">// 呵呵哒 App以为获取的是自己需要的Intent,结果却被狸猫换太子

    ClipData clipData = mClipboardManager.getPrimaryClip();

    ClipData.Item myItem;

    myItem = clipData.getItemAt(span class="hljs-number">0span>);

    span class="hljs-built_in">Stringspan> clipDataString = myItem.coerceToText(span class="hljs-keyword">thisspan>.getApplicationContext()).toString();

    span class="hljs-keyword">tryspan> {

        Intent myIntent = Intent.parseUri(clipDataString, span class="hljs-number">0span>);

        startActivity(myIntent);

    } span class="hljs-keyword">catchspan> (URISyntaxException e) {

        e.printStackTrace();

    }

}


其实不一定是通过Fake Intent,其它的文字、图片等等,都可以被『偷天换日』。


另外,要实现这个监听,我们需要注册一个回调——addPrimaryClipChangedListener,Android真是体贴到没朋友:


mClipboardManager.addPrimaryClipChangedListener(span class="hljs-keyword">newspan> ClipboardManager.OnPrimaryClipChangedListener() {

    @Override

    public span class="hljs-keyword">voidspan> onPrimaryClipChanged() {

        Log.d(span class="hljs-string">"xys"span>, span class="hljs-string">"onPrimaryClipChanged: "span>);

    }

});


那么在这里,我们就可以完全实现剪贴板的『狸猫换太子』。那么假如我们是一个『某淘』软件的竞品,那么完全可以让『汪口令』失效,甚至替换为我们自己的应用,同理,还有一些翻译类软件也是一样,不过还好,也许是我的内心比较阴暗,目前还没有看见这样的App。


专栏作者简介( 点击 → 加入专栏作者 


eclipse_xu:Android 高级开发工程师;《Android群英传》、《Android群英传:神兵利器》作者、慕课网Android讲师;CSDN博客专家

打赏支持作者写出更多好文章,谢谢!



 关注「安卓开发精选

看更多精选文章
↓↓↓