Android项目实战---指尖翻译系列0x01

从这次开始,我就会带着大家一步一步的实现指尖翻译这个项目.首先要做到即时的翻译就需要获取到粘贴板的内容.因为我们的项目是通过复制内容然后从粘贴板中获取再进行翻译的.所以首先我们要先获取粘贴板的内容.

粘贴板API的使用

通过查看官网手册的粘贴板的API,我们可以通过getSystemService(CLIPBOARD_SERVICE)得到ClipboardManager对象,系统粘贴板中每次只会持有一个ClipData对象,而一个ClipData对象包含一个ClipDescription和一个或多个的ClipData.Item对象.其中的ClipData.Item对象包含的就是我们需要的数据.这些数据包含文本,URI或是Intent data.我们只需关注文本即可.
从粘贴板获取我们所需的文本基本上可以通过下面的步骤实现:

  1. 获取全局的ClipboardManager对象

    1
    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
  2. 判断当前的粘贴板的数据格式是否符合要求

    1
    2
    3
    4
    5
    6
    7
    // 粘贴板是否有数据
    if (!(clipboard.hasPrimaryClip())) {
    } else if (!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))) {
    // 数据格式不符合要求
    } else {
    // 数据格式符合要求
    }
  3. 从粘贴板获取文本数据

    1
    2
    3
    4
       // 假设应用每次只处理一个item
    ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
    // 将数据转换为文本
    String text = item.coerceToText(context).toString();

    对复制的行为设置监听

    我们清楚了如何获取粘贴板的内容后,那么我们该在什么时候获取呢?根据项目的功能,我们想要在用户进行复制时得到翻译后的内容,所以我们应该在用户进行复制时获取粘贴板的内容,然后进行处理.
    这时我们就需要对用户的复制行为进行监听了.通过查看API,发现了ClipboardManager中的addPrimaryClipChangedListener()方法能对粘贴板的改变进行监听,我们利用这个方法便能实现所需的功能.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class MainActivity extends AppCompatActivity implements ClipboardManager.OnPrimaryClipChangedListener {

    ClipboardManager clipboardManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    clipboardManager = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE);
    clipboardManager.addPrimaryClipChangedListener(this);
    }

    @Override
    public void onPrimaryClipChanged() {
    ClipData.Item item = clipboardManager.getPrimaryClip().getItemAt(0);
    String text = item.coerceToText(getApplicationContext()).toString();
    Log.e("Text", "粘贴板的内容是:" + text);
    }
    }

我们运行一下代码,然后在手机其他的应用进行一下复制操作,可以在日志输出中看到,我们已经得到了想要的效果
Log
上面的是测试用的代码,现在我们来将代码封装一下.
首先创建一个Application类,FingerApp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 作为全局的Application
*/

public class FingerApp extends Application {
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static FingerApp get(){
return (FingerApp) mContext.getApplicationContext();
}
}

创建完成后记得替换AndroidManifest.xml文件的Application节点的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
<application
android:name=".FingerApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar">

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
...

创建一个管理粘贴板的类ClipBoard.java,我们采用单例模式

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
56
57
58
59
60
/**
* the clipboard
*/

public class Clipboard {

private ClipboardManager mClipboard;
private List<ClipboardManager.OnPrimaryClipChangedListener> listeners = new ArrayList<>();

private Clipboard() {
this.mClipboard = (ClipboardManager) FingerApp.get().getSystemService(Context.CLIPBOARD_SERVICE);
}

/**
* 获取粘贴板的文本数据
* @return
*/

public String getText() {
return mClipboard.getPrimaryClip().getItemAt(0).coerceToText(FingerApp.get()).toString();
}

/**
* 判断是否有监听对象
* @return
*/

public boolean isStartListened() {
return listeners.size() != 0;
}

/**
* 设置监听
* @param listener
*/

public void setPrimaryClipChangedListener(ClipboardManager.OnPrimaryClipChangedListener listener) {
if (listener == null) {
removeAllListener();
return;
}
mClipboard.addPrimaryClipChangedListener(listener);
listeners.add(listener);
}

/**
* 移除所有监听
*/

public void removeAllListener() {
for (ClipboardManager.OnPrimaryClipChangedListener l : listeners)
mClipboard.removePrimaryClipChangedListener(l);
}

/**
* 单例模式
* @return
*/

public static Clipboard getInstance() {
return SingletonHolder.instance;
}
static class SingletonHolder {
public static final Clipboard instance = new Clipboard();
}
}

我们已经完成了获取粘贴板的文本数据以及对复制行为的监听,下次我们将会实现悬浮窗的功能.