【Service】使用有道翻译API构建翻译服务

来源:互联网 发布:算法流程图模板 编辑:程序博客网 时间:2024/05/22 05:27

声明:Ryan的博客文章欢迎您的转载,但在转载的同时,请注明文章的来源出处,不胜感激! :-) 

http://my.oschina.net/ryanhoo/blog/100589

        今天我们来学习使用现有的服务构建应用的功能模块——利用有道的翻译API构建一个小的翻译程序。之前曾想用Google的翻译API来实现,后来发现这项服务是收费的,所以用有道的,免费才是王道。

        先来看看效果

    功能相当简单,主要提供英汉互译(其实参数无需传入语言,有道翻译机器人会自动识别)。

    实现步骤如下:

  • 申请有道翻译API的key并阅读文档
  • 新建Android项目,编写远程调用服务AIDL
  • 实现服务并供程序调用
  • 实现UI

    申请有道翻译API KEY

    请在这个页面填写必要信息,并记录返回的Key和keyfrom,调用有道的翻译服务将需要使用它。

    在申请到Key以后,请花几分钟时间简短的浏览下有道API调用的文档,就在申请页的下面。

    请求接口非常简单:

1http://fanyi.youdao.com/openapi.do?keyfrom=<keyfrom>&key=<key>&type=data&doctype=<doctype>&version=1.1&q=要翻译的文本

    唯一在变动的参数是翻译文本,这让我们定义AIDL变得非常容易。

    编写AIDL远程服务调用接口

    新建ITranslateService.aidl,定义一个简单的接口,只需传入一个参数——待翻译文本。

1package com.iedgeco.ryan.translate.service;
2 
3interface ITranslate{
4    String traslate(in String text);
5}
    实现服务 

01public class TranslateService extends Service {
02 
03    public static final String TAG = "TranslateService";
04     
05    //binder
06    private final ITranslate.Stub mBinder = new ITranslate.Stub() {
07        @Override
08        public String traslate(String text) throws RemoteException {
09             
10            try {
11                return Translator.translate(text);
12            } catch (Exception e) {
13                Log.e(TAG, "Failed to translate", e);
14                return null;
15            }
16        }
17    };
18     
19    @Override
20    public IBinder onBind(Intent intent) {
21        return mBinder;
22    }
23 
24}
    在AIDL所在的包下实现一个Service类 TranslateService ,实现相当的简单。因为是远程调用服务而非本地服务,后期需要使用bindService,因此我们必须返回IBinder实例。这里的IBinder中具体的翻译操作,我交给一个工具类Translator 的静态方法完成,只需传入待翻译文本即可。 
01public class Translator {
02 
03    private static final String TAG = "Translator";
04 
05    private static final String ENCODING = "UTF-8";
06 
07    /**
08     * <pre>
09     * 请求标准: http://fanyi.youdao.com/openapi.do?
10     *      keyfrom=<keyfrom>&
11     *      key=<key>&
12     *      type=data&
13     *      doctype=<doctype>&
14     *      version=1.1&
15     *      q=要翻译的文本
16     * 版本:1.1,请求方式:get,编码方式:utf-8
17     * 主要功能:
18     *      中英互译,同时获得有道翻译结果和有道词典结果(可能没有)
19     * 参数说明:
20     *      type - 返回结果的类型,固定为data
21     *      doctype - 返回结果的数据格式,xml或json或jsonp
22     *      version - 版本,当前最新版本为1.1
23     *      q - 要翻译的文本,不能超过200个字符,需要使用utf-8编码
24     *  errorCode:  
25     *      0 - 正常  
26     *      20 - 要翻译的文本过长  
27     *      30 - 无法进行有效的翻译  
28     *      40 - 不支持的语言类型  
29     *      50 - 无效的key
30     * </pre>
31     * @throws IOException
32     * @throws ClientProtocolException
33     * */
34    public static String translate(String text) throws Exception {
35        String url = "http://fanyi.youdao.com/openapi.do?keyfrom=" + StaticDef.KEY_FROM
36                + "&key=" + StaticDef.KEY_FOR_TRANSLATE
37                + "&type=data"
38                + "&doctype=json"
39                + "&version=1.1"
40                + "&q=" + text;
41        try{
42            HttpClient client = new DefaultHttpClient();
43            HttpGet httpGet = new HttpGet(url);
44            HttpResponse response = client.execute(httpGet);
45            InputStream is = response.getEntity().getContent();
46            BufferedReader reader = new BufferedReader(new InputStreamReader(is, ENCODING));
47            StringBuffer result = new StringBuffer();
48            String string = null;
49            if(null != (string = reader.readLine()))
50                result.append(string).append('\n');
51            //TODO parse the response json string
52            String translation = (String) new JSONObject(result.toString())
53                .getJSONArray("translation").get(0);
54             
55            Log.i(TAG, "result: " + result.toString());
56            return translation;
57        }finally{
58            //close stream here
59        }
60    }
61}

    实现UI并调用翻译服务

    UI相对简单,具体的布局请见Github中的代码,后面我会给出地址。

    MainActivity中的方法也比较简单,在onCreate中启用服务(doBindService),在onDestory中解除绑定,销毁服务(doUnBindService),可以使用doTranslate进行后台翻译(由于服务是直接运行在Main线程上的,我开启了一个异步线程来完成这个工作,并将结果反馈给Handler,由它来更新UI)。

    doBindService

1private void doBindService(){
2    Intent service = new Intent(StaticDef.ACTION_TRANALATE);
3    bindService(service, serviceConn, Context.BIND_AUTO_CREATE);
4}

    doUnBindService

1private void doUnBindService(){
2    unbindService(serviceConn);
3}

    doTranslate

01//launch a thread for translation
02private void doTranslate(){
03    new Thread(new Runnable() {
04        @Override
05        public void run() {
06            String result = null;
07            try {
08                String input = etInput.getText().toString();
09                //use the translate service
10                result = mTranslateService.traslate(input);
11                //send message callback
12                Message msg = new Message();
13                msg.obj = result;
14                if(result == null){
15                    msg.what = TRANSLATE_ERROR;
16                    throw new Exception("Failed to get a translation...");
17                }
18                msg.what = TRANSLATE_COMPLETED;
19                mHandler.sendMessage(msg);
20            } catch (Exception e) {
21                Log.e(TAG, "Error happened while translating...", e);
22            }
23        }
24    }).start();
25}

    Handler

01private static final int TRANSLATE_COMPLETED = 0;
02private static final int TRANSLATE_ERROR = 1;
03 
04//controller
05private Handler mHandler = new Handler(){
06    @Override
07    public void handleMessage(Message msg) {
08        switch (msg.what) {
09        case TRANSLATE_COMPLETED:
10            String result = (String) msg.obj;
11            etTranslation.setText(result);
12            etInput.selectAll();
13            break;
14        case TRANSLATE_ERROR:
15            Log.e(TAG, "translation error");
16            break;
17        default:
18            break;
19        }
20    }
21     
22};

    总结

    代码不多,逻辑也相对简单,主要是学习如何使用AIDL调用远程服务。

    提示:使用之前,请用申请到的KEY替换config包下的key以及keyfrom!

    代码

    详见我的Github:https://github.com/ryanhoo/TranslateService