百度翻译API

  • 一、创建平台应用
  • 二、创建及配置项目
  • 三、编码
    • 1. 修改外观与布局
    • 2. 初始化控件
    • 3. 输入框监听
    • 4. 语言选择监听
    • 5. 页面点击事件
    • 6. 翻译
  • 四、源码地址

一、创建平台应用

运行效果图

  百度翻译开放平台也是属于百度智能云的一部分,所以你如果注册过百度的账号都是可以直接登录,当然最好做一下开发者认证,这样一些API的开放力度会大一些,再来说一下写这篇文章的初衷吧,首先我是弄过百度的翻译的,我之前并没有写过这方面的博客,而有读者看过我之前写的关于百度语音识别和百度文字识别的博客,于是问我百度翻译的相关问题,其实他突然这么问我,我也是很懵逼的(´⊙ω⊙`)。因为你光凭一个现象并不足以解决这个问题。一般情况下,按着官方文档来做基本上没问题,剩下的就是细节上的处理了,所以借着这个机会,索性写一篇这样的文章,就当是做个记录吧。
  熟悉我写百度类似文章思路的朋友肯定知道,第一步是创建平台应用,点击百度翻译开放平台进入,至于登录和注册以及实名认证和开发者认证就没有讲述的必要了,如果你自己连这几步都无法独立完成的话,我也没有什么好说的了。如下图所示,我已经登录好了。

点击管理控制台,会让你先完成个人认证,如果你是第一次进入的话,认证完之后会出现

往下滑,你只要填写姓名和身份证号码即可,一个身份证只能认证一个账号,所以如果你已经认证过了,但是又想用另一个账号来做这个测试,你可以点击暂不认证,

这个消息是告诉你,你已经成功注册成为百度翻译的开发者,然后点击开通服务。

选择好之后点击下一步,点击开通标准版,你就不需要申请认证了,直接可以填写申请表格

开始填表



填写完资料之后,点击提交申请

点击前往管理控制台。然后找到你的APP ID,这个很重要,要在项目中使用的。

官方我的文档我就不去介绍了,用自己的理解来写。现在已经有了这个APP ID了,服务也开通好了,下面创建测试项目。

二、创建及配置项目

  开大打开Android Studio,新建一个名为TranslateDemo的项目,如下图所示:

点击Finish完成创建。在这篇文章里,需要去自己去访问网络,所以需要添加一些依赖库
先在工程的build.gradle中添加

maven { url "https://jitpack.io" }

然后在app模块下的build.gradle中添加网络访问依赖库和其他的依赖

 //网络访问implementation 'com.squareup.okhttp3:okhttp:3.10.0'//下拉框implementation 'com.github.arcadefire:nice-spinner:1.4.3'//卡片视图implementation 'androidx.cardview:cardview:1.0.0'//GSON解析implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

  而其中okhttp是一个你做Android开发必须要知道的一个库,很多公司在面试的时候都会问这个库的底层原理,有想法可以详细的去官网了解,这是github上的地址:okhttp,有兴趣就可以去了解。文章中只是简单的使用而已,这里先说明,然后Sync。

然后在AndroidManifest.xml中添加网络访问权限

 <!--网络访问权限--><uses-permission android:name="android.permission.INTERNET"/>


下面可以进入到正式的编码环节了。激动的心,颤抖的手,我相信你已经迫不及待了吧,当然我会尽我所能的讲清楚每一个环节,哪怕你觉得我啰嗦也好。

三、编码

1. 修改外观与布局

既然是编码,首先我要改变主题的外观,作为颜值控,我不运行这个丑的软件在我的手机上运行,这个项目你现在运行看到的页面是很丑的,来看看有多丑。

要想软件过得去,页面总得带点绿,这就是Google的直男审美。下面我都要改成白色,并且去掉它默认的顶部ActionBar。找到styles.xml文件并打开,修改代码如下:

<resources><!-- Base application theme. --><style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"><!-- Customize your theme here. --><item name="colorPrimary">#FFF</item><item name="colorPrimaryDark">#FFF</item><item name="colorAccent">@color/colorAccent</item></style></resources>

这里我将主题样式的颜色从原谅绿改成了白色,并且NoActionBar去掉动作栏。然后你再运行一下

emmm…怎么说呢,感觉怪怪的,不行,还得再改改。打开MainActivity,在onCreate中增加如下代码:

     //设置亮色状态栏模式 systemUiVisibility在Android11中弃用了,可以尝试一下。getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

其实使用这段代码的时候应该先判断Android的版本,这个在Android6.0以上生效,不过这只是做测试,所以我就不做判断了,因为我的手机是10.0,但是在实际的开发中还是要做的,这就涉及到Android版本适配了,比较多复杂,网络上的文章比较多,自行搜索。好了,下面运行一下:

看到状态栏了,不过好像还少了点什么,打开activity_main.xml,修改后代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.andr oid.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"android:orientation="vertical"tools:context=".MainActivity"><!--标题--><androidx.appcompat.widget.Toolbarandroid:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="#FFF"android:elevation="3dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="在线翻译"android:textColor="#000"android:textSize="18sp" /></androidx.appcompat.widget.Toolbar></LinearLayout>

再运行一下:

嗯,效果喜人,看上去就是辣么滴顺眼。然后我贴上完整的布局代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.andr oid.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"android:orientation="vertical"tools:context=".MainActivity"><!--标题--><androidx.appcompat.widget.Toolbarandroid:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="#FFF"android:elevation="3dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="在线翻译"android:textColor="#000"android:textSize="18sp" /></androidx.appcompat.widget.Toolbar><!--滚动视图 当内容高度超出屏幕高度时可以上下滚动--><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"><!--主要操作区域--><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="20dp"><!--翻译前显示的布局--><LinearLayoutandroid:id="@+id/before_lay"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#FFF"android:foreground="@drawable/stroke_gray"><!--下拉框  控制转换的语言--><org.angmarch.views.NiceSpinnerandroid:id="@+id/sp_language"android:layout_width="match_parent"android:layout_height="48dp"app:arrowTint="#000"app:textTint="#000" /></LinearLayout><!--翻译后显示的布局--><LinearLayoutandroid:id="@+id/after_lay"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"android:visibility="gone"><androidx.cardview.widget.CardViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:background="#FFF"app:cardCornerRadius="5dp"><!--翻译源语言--><TextViewandroid:id="@+id/tv_from"android:layout_width="match_parent"android:layout_height="40dp"android:background="@drawable/stroke_black_radus"android:gravity="center"android:textColor="#000"android:textSize="14sp" /></androidx.cardview.widget.CardView><ImageViewandroid:layout_width="30dp"android:layout_height="30dp"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:src="@mipmap/icon_change" /><androidx.cardview.widget.CardViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:background="#FFF"app:cardCornerRadius="5dp"><!--翻译目标语言--><TextViewandroid:id="@+id/tv_to"android:layout_width="match_parent"android:layout_height="40dp"android:background="@drawable/stroke_black_radus"android:gravity="center"android:textColor="#000"android:textSize="14sp" /></androidx.cardview.widget.CardView></LinearLayout><!--内容输入区域--><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="150dp"android:layout_marginTop="20dp"android:background="#FFF"><!--输入框--><EditTextandroid:id="@+id/ed_content"android:layout_width="match_parent"android:layout_height="150dp"android:background="@drawable/stroke_gray"android:gravity="top"android:hint="请输入要翻译的文字内容"android:maxLength="6000"android:paddingLeft="10dp"android:paddingTop="10dp"android:paddingRight="30dp"android:paddingBottom="10dp"android:textColor="#000"android:textColorLink="#ABABAB"android:textCursorDrawable="@drawable/cursor_style" /><!--清空输入内容--><ImageViewandroid:id="@+id/iv_clear_tx"android:layout_width="20dp"android:layout_height="20dp"android:layout_alignParentRight="true"android:layout_alignParentBottom="true"android:layout_marginRight="8dp"android:layout_marginBottom="8dp"android:src="@mipmap/icon_delete"android:visibility="gone" /></RelativeLayout><!--翻译后的结果显示--><LinearLayoutandroid:visibility="gone"android:id="@+id/result_lay"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="翻译结果"android:textColor="#000"android:textSize="14sp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:background="#FFF"android:orientation="vertical"><!--显示翻译的结果--><TextViewandroid:id="@+id/tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="10dp"android:textColor="#000" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="right"android:orientation="horizontal"><!--复制翻译出来的结果--><ImageViewandroid:id="@+id/iv_copy_tx"android:layout_width="24dp"android:layout_height="24dp"android:layout_marginRight="4dp"android:layout_marginBottom="4dp"android:padding="4dp"android:src="@mipmap/icon_copy" /></LinearLayout></LinearLayout></LinearLayout><androidx.cardview.widget.CardViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:background="#FFF"app:cardCornerRadius="5dp"><TextViewandroid:id="@+id/tv_translation"android:layout_width="match_parent"android:layout_height="48dp"android:background="@drawable/stroke_black_radus"android:foreground="?android:attr/selectableItemBackground"android:gravity="center"android:padding="10dp"android:text="翻译"android:textColor="#000"android:textColorLink="#ABABAB"android:textSize="16sp" /></androidx.cardview.widget.CardView></LinearLayout></ScrollView></LinearLayout>

这个布局里面,我现在隐藏了两块区域。第一块是翻译后的语言区域,第二块是翻译后的结果区域。运行的效果如下:

2. 初始化控件

在MainActivity中,声明变量

 private LinearLayout beforeLay;//翻译之前的布局private NiceSpinner spLanguage;//语言选择下拉框private LinearLayout afterLay;//翻译之后的布局private TextView tvFrom;//翻译源语言private TextView tvTo;//翻译目标语言private EditText edContent;//输入框(要翻译的内容)private ImageView ivClearTx;//清空输入框按钮private TextView tvTranslation;//翻译private LinearLayout resultLay;//翻译结果布局private TextView tvResult;//翻译的结果private ImageView ivCopyTx;//复制翻译的结果private String fromLanguage = "auto";//目标语言private String toLanguage = "auto";//翻译语言private ClipboardManager myClipboard;//复制文本private ClipData myClip; //剪辑数据private String appId = "20201125000625305";//APP ID 来源于百度翻译平台 请使用自己的private String key = "6vjmDnNxypmebgbzKxul";//秘钥 来源于百度翻译平台 请使用自己的//配置初始数据private List<String> data = new LinkedList<>(Arrays.asList("自动检测语言", "中文 → 英文", "英文 → 中文","中文 → 繁体中文", "中文 → 粤语", "中文 → 日语","中文 → 韩语", "中文 → 法语", "中文 → 俄语","中文 → 阿拉伯语", "中文 → 西班牙语 ", "中文 → 意大利语"));

然后新写一个initView的方法。在这里对控件进行初始化并给予点击事件,并且数据赋值,

 /*** 初始化控件视图*/private void initView() {//设置亮色状态栏模式 systemUiVisibility在Android11中弃用了,可以尝试一下。getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);//控件初始化beforeLay = findViewById(R.id.before_lay);spLanguage = findViewById(R.id.sp_language);afterLay = findViewById(R.id.after_lay);tvFrom = findViewById(R.id.tv_from);tvTo = findViewById(R.id.tv_to);edContent = findViewById(R.id.ed_content);ivClearTx = findViewById(R.id.iv_clear_tx);tvTranslation = findViewById(R.id.tv_translation);resultLay = findViewById(R.id.result_lay);tvResult = findViewById(R.id.tv_result);ivCopyTx = findViewById(R.id.iv_copy_tx);//点击时间ivClearTx.setOnClickListener(this);ivCopyTx.setOnClickListener(this);tvTranslation.setOnClickListener(this);//设置下拉数据spLanguage.attachDataSource(data);editTextListener();//输入框监听spinnerListener();//下拉框选择监听//获取系统粘贴板服务myClipboard = (ClipboardManager) this.getSystemService(CLIPBOARD_SERVICE);}

3. 输入框监听

editTextListener方法代码:

 /*** 输入监听*/private void editTextListener() {edContent.addTextChangedListener(new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {ivClearTx.setVisibility(View.VISIBLE);//显示清除按钮}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {ivClearTx.setVisibility(View.VISIBLE);//显示清除按钮}@Overridepublic void afterTextChanged(Editable s) {ivClearTx.setVisibility(View.VISIBLE);//显示清除按钮String content = edContent.getText().toString().trim();if (content.isEmpty()) {//为空resultLay.setVisibility(View.GONE);tvTranslation.setVisibility(View.VISIBLE);beforeLay.setVisibility(View.VISIBLE);afterLay.setVisibility(View.GONE);ivClearTx.setVisibility(View.GONE);}}});}

4. 语言选择监听

spinnerListener方法代码如下:

 /*** 语言类型选择*/private void spinnerListener() {spLanguage.setOnSpinnerItemSelectedListener(new OnSpinnerItemSelectedListener() {@Overridepublic void onItemSelected(NiceSpinner parent, View view, int position, long id) {switch (position) {case 0://自动检测fromLanguage = "auto";toLanguage = fromLanguage;break;case 1://中文 → 英文fromLanguage = "zh";toLanguage = "en";break;case 2://英文 → 中文fromLanguage = "en";toLanguage = "zh";break;case 3://中文 → 繁体中文fromLanguage = "zh";toLanguage = "cht";break;case 4://中文 → 粤语fromLanguage = "zh";toLanguage = "yue";break;case 5://中文 → 日语fromLanguage = "zh";toLanguage = "jp";break;case 6://中文 → 韩语fromLanguage = "zh";toLanguage = "kor";break;case 7://中文 → 法语fromLanguage = "zh";toLanguage = "fra";break;case 8://中文 → 俄语fromLanguage = "zh";toLanguage = "ru";break;case 9://中文 → 阿拉伯语fromLanguage = "zh";toLanguage = "ara";break;case 10://中文 → 西班牙语fromLanguage = "zh";toLanguage = "spa";break;case 11://中文 → 意大利语fromLanguage = "zh";toLanguage = "it";break;default:break;}}});}

5. 页面点击事件

同时要实现点击事件的监听,

鼠标点击这一行代码,然后使用快捷键,Alt + 回车

选择第一项,然后回车

点击OK,之后会重写onClick方法。这里不止一个控件,所以要根据view的id来判断才行。

 /*** 页面点击事件* @param v*/@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.iv_clear_tx://清空输入框edContent.setText("");//清除文本ivClearTx.setVisibility(View.GONE);//清除数据之后隐藏按钮break;case R.id.iv_copy_tx://复制翻译后的结果String inviteCode = tvResult.getText().toString();myClip = ClipData.newPlainText("text", inviteCode);myClipboard.setPrimaryClip(myClip);showMsg("已复制");break;case R.id.tv_translation://翻译translation();//翻译break;default:break;}}/*** Toast提示* @param msg*/private void showMsg(String msg) {Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();}

下面重点来看看这个翻译的方法,这里面的东西还挺多的。

6. 翻译

  既然是翻译首先获取到输入的文字,如下所示:

 /*** 翻译*/private void translation() {//获取输入的内容String inputTx = edContent.getText().toString().trim();//判断输入内容是否为空if (!inputTx.isEmpty() || !"".equals(inputTx)) {//不为空tvTranslation.setText("翻译中...");tvTranslation.setEnabled(false);//不可更改,同样就无法点击String salt = num(1);//随机数//拼接一个字符串然后加密String spliceStr = appId + inputTx + salt + key;//根据百度要求 拼接String sign = stringToMD5(spliceStr);//将拼接好的字符串进行MD5加密   作为一个标识//异步Get请求访问网络asyncGet(inputTx, fromLanguage, toLanguage, salt, sign);} else {//为空showMsg("请输入要翻译的内容!");}}

这里先判断了输入框的值是否为null或者“”,不是则改变翻译按钮的文字显示,并且不可点击,给用户一种正在翻译的假象。之后就是生成一个随机数,这个是按照百度的要求来的,方法很简单,就不过多解释了。

 /*** 随机数 (根据百度的要求需要一个随机数)*/public static String num(int a) {Random r = new Random(a);int ran1 = 0;for (int i = 0; i < 5; i++) {ran1 = r.nextInt(100);System.out.println(ran1);}return String.valueOf(ran1);}

然后拼接一个字符串spliceStr,然后通过md5进行小写加密,加密后的值也是作为访问百度翻译API的一个参数。加密方法如下:

 /*** 将字符串转成MD5值** @param string 需要加密的内容* @return 加密后的字符串*/public static String stringToMD5(String string) {byte[] hash;try {hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;} catch (UnsupportedEncodingException e) {e.printStackTrace();return null;}StringBuilder hex = new StringBuilder(hash.length * 2);for (byte b : hash) {if ((b & 0xFF) < 0x10) {hex.append("0");}hex.append(Integer.toHexString(b & 0xFF));}return hex.toString();}

网络请求作为耗时操作,所以通常不会在主线程中进行,所以写一个异步Get请求访问网络的方法,传入刚才写进去的一些参数。

 /*** 异步Get请求** @param content  要翻译的内容* @param fromType 翻译源语言* @param toType   翻译后语言* @param salt     随机数* @param sign     标识*/private void asyncGet(String content, String fromType, String toType, String salt, String sign) {//通用翻译API HTTP地址://http://api.fanyi.baidu.com/api/trans/vip/translate//通用翻译API HTTPS地址://https://fanyi-api.baidu.com/api/trans/vip/translateString httpStr = "http://api.fanyi.baidu.com/api/trans/vip/translate";String httpsStr = "https://fanyi-api.baidu.com/api/trans/vip/translate";//拼接请求的地址String url = httpsStr +"?appid=" + appId + "&q=" + content + "&from=" + fromType + "&to=" +toType + "&salt=" + salt + "&sign=" + sign;OkHttpClient okHttpClient = new OkHttpClient();final Request request = new Request.Builder().url(url).get()//默认就是GET请求,可以不写.build();Call call = okHttpClient.newCall(request);call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, final IOException e) {//异常返回goToUIThread(e.toString(), 0);}@Overridepublic void onResponse(Call call, Response response) throws IOException {//正常返回goToUIThread(response.body().string(), 1);}});}

这里就是OkHttp的简单使用了,而这里我写了两个访问地址,区别就是一个是https一个是http,不知道这两个区别的自行百度,没有解释的必要。你可能会问这个和Android有什么关系,别着急,会让你看到的。GET请求常规的操作就是把参数拼接到URL后面,我这里也是这么找的,

     //拼接请求的地址String url = httpsStr +"?appid=" + appId + "&q=" + content + "&from=" + fromType + "&to=" +toType + "&salt=" + salt + "&sign=" + sign;

  URL的第一个参数要用?开头,后续参数使用&,其他的就是字符串的拼接了,一目了然。然后将地址放入到Request,里面完成请求体的构建,然后通过Call构建一个新的请求回调。在请求队列里监听请求的结果,结果只有两种,成功和失败。之前我是通过异步请求网络的,那么它的回调自然也不会是在主线程中,但是我又要在回调里面控制页面的UI。那么就需要切换到主线程或者UI线程中进行。于是你看到我在成功和失败的返回中都调用了goToUIThread,里面第一个参数作为一个Object对象,失败时传入错误信息,成功时传入返回数据。方法如下:

 /*** 接收到返回值后,回到UI线程操作页面变化** @param object 接收一个返回对象* @param key    表示正常还是异常*/private void goToUIThread(final Object object, final int key) {//切换到主线程处理数据MainActivity.this.runOnUiThread(new Runnable() {@Overridepublic void run() {tvTranslation.setText("翻译");tvTranslation.setEnabled(true);if (key == 0) {//异常返回showMsg("异常信息:" + object.toString());Log.e("MainActivity",object.toString());} else {//正常返回//通过Gson 将 JSON字符串转为实体Beanfinal TranslateResult result = new Gson().fromJson(object.toString(), TranslateResult.class);tvTranslation.setVisibility(View.GONE);//显示翻译的结果tvResult.setText(result.getTrans_result().get(0).getDst());resultLay.setVisibility(View.VISIBLE);beforeLay.setVisibility(View.GONE);afterLay.setVisibility(View.VISIBLE);//翻译成功后的语言判断显示initAfter(result.getFrom(), result.getTo());}}});}

  这种写代码的方式虽然像是套娃一样,一层一层的,看起来好像很复杂的样子,但是其实是有一个思路串联起来的,由上到下,思路清晰就很好理解,我个人觉得比把所有代码写在一个方法里要好。而在上面的代码中,通过传进来的key来区别是成功还是失败。失败里面就是提示失败信息通过打印失败信息。成功里面,通过Gson将返回的JSON字符串转换成实体Bean。TranslateResult代码如下:

package com.llw.translate;import java.util.List;/*** 翻译结果* @author llw */
public class TranslateResult {/*** from : zh* to : en* trans_result : [{"src":"早上","dst":"morning"}]*/private String from;private String to;private List<TransResultBean> trans_result;public String getFrom() {return from;}public void setFrom(String from) {this.from = from;}public String getTo() {return to;}public void setTo(String to) {this.to = to;}public List<TransResultBean> getTrans_result() {return trans_result;}public void setTrans_result(List<TransResultBean> trans_result) {this.trans_result = trans_result;}public static class TransResultBean {/*** src : 早上* dst : morning*/private String src;private String dst;public String getSrc() {return src;}public void setSrc(String src) {this.src = src;}public String getDst() {return dst;}public void setDst(String dst) {this.dst = dst;}}
}

后面就是一些控件的隐藏和显示了,请结合GIF示例图来看,会让你有一个清晰的认识。然后还有最后initAfter一个方法要讲一下:

 /*** 翻译成功后的语言判断显示*/private void initAfter(String from, String to) {if (("zh").equals(from)) {tvFrom.setText("中文");} else if (("en").equals(from)) {tvFrom.setText("英文");} else if (("yue").equals(from)) {tvFrom.setText("粤语");} else if (("cht").equals(from)) {tvFrom.setText("繁体中文");} else if (("jp").equals(from)) {tvFrom.setText("日语");} else if (("kor").equals(from)) {tvFrom.setText("韩语");} else if (("fra").equals(from)) {tvFrom.setText("法语");} else if (("ru").equals(from)) {tvFrom.setText("俄语");} else if (("ara").equals(from)) {tvFrom.setText("阿拉伯语");} else if (("spa").equals(from)) {tvFrom.setText("西班牙语");} else if (("it").equals(from)) {tvFrom.setText("意大利语");}if (("zh").equals(to)) {tvTo.setText("中文");} else if (("en").equals(to)) {tvTo.setText("英文");} else if (("yue").equals(to)) {tvTo.setText("粤语");} else if (("cht").equals(to)) {tvTo.setText("繁体中文");} else if (("jp").equals(to)) {tvTo.setText("日语");} else if (("kor").equals(to)) {tvTo.setText("韩语");} else if (("fra").equals(to)) {tvTo.setText("法语");} else if (("ru").equals(to)) {tvTo.setText("俄语");} else if (("ara").equals(to)) {tvTo.setText("阿拉伯语");} else if (("spa").equals(to)) {tvTo.setText("西班牙语");} else if (("it").equals(to)) {tvTo.setText("意大利语");}}

这个方法很简单,就是根据返回的值得检测到的语言类型,去控制UI的显示而已。
好了,写了这么久,还没有运行过呢?下面运行一下吧。

OK,已经搞定了。还记得之前百度有两个访问地址吗?我之前用的是https的,那么现在用http的,再运行访问一下


你会发现只是用http地址访问怎么就不行了呢?,难道是这个地址有问题,首先这个地址没有问题,而是Android的版本从中作祟,Google规定在Android9.0以后默认是https访问网络,所以刚才使用了http不行。那么如果要用http访问呢?也比较简单,配置一个网络访问许可就行了。
在res下新建一个xml文件夹,文件夹下新建一个network_security_config.xml,里面的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config><base-config cleartextTrafficPermitted="true" ><trust-anchors><certificates src="system" /></trust-anchors></base-config>
</network-security-config>

这个配置文件的意思就是允许明文访问网络,也就是http的许可
然后打开AndroidManifest.xml,在application标签中配置

配置好之后无论,再访问,铁定不报错了。

当然如果你的代码有报错,不妨试试运行我的源码看看,这也可以作为一个排错的方向。

四、源码地址

  写作不易,如果这篇文章对你有帮助的话,不妨点个赞鼓励一下作者,举手之劳而已。

源码地址:
Java版:TranslateDemo
Kotlin版:TranslateDemo-Kotlin

这是APK下载二维码,如果你下载后运行没有问题,那么你的代码运行不了就是你自己的问题,无可争议。

疑难杂症: 有部分读者运行了我的源码,然后发现点击翻译之后会闪退,报错如下

java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object referenceat com.llw.translate.MainActivity$4.run(MainActivity.java:329)

这是报错的原因是翻译是成功的,但是没有获取到翻译后的数据,也可以说是数据为空,然后用这个数据去赋值显示出来,就报错了,那么为什么会为空呢?我也是百思不得其解,因为我的代码我运行在手机或者是模拟器上都是正常的,从来不会闪退。所以我怀疑是百度搞的鬼。问题可能是:① 百度翻译服务可能限制了访问的ip。② 开发者账号需要做个人开发者认证,认证后的appid和密码才能供其他开发者使用。

不过这两个问题没有依据。反正就是一个现象,我运行没有问题,其他人运行就闪退,我能怎么办?只能慢慢跟踪,回头问问百度的开发人员看是怎么回事。

Android 百度翻译API(详细步骤+源码)相关推荐

  1. 实战 | 用Python和MediaPipe搭建一个嗜睡检测系统 (详细步骤 + 源码)

    导读 本文将使用Python和MediaPipe搭建一个嗜睡检测系统 (包含详细步骤 + 源码). 背景介绍 疲劳驾驶的危害不堪设想,据了解,21%的交通事故都因此而生,尤其是高速路上,大多数车辆都是 ...

  2. 实战 | 基于OpenCV的停车场空余车位实时监测系统(详细步骤 + 源码)

    导  读 本文主要介绍如何使用Python和OpenCV实现一个停车场空余车位实时监测系统,并包含详细步骤和源码. 背景介绍 介绍实现步骤之前,先来看看测试视频(小型停车场实时监控画面): ,时长00 ...

  3. Android 百度语音合成 (含离线、在线、API合成方式,详细步骤+源码)

    百度语音合成 声明 前言 正文 一.创建项目 二.离线语音合成 1. 配置AndroidManifest.xml 2. 配置SDK 3. 离线SDK初始化 4. 导包 5. 运行 三.在线语音合成 - ...

  4. Android 高德地图API(详细步骤+源码)

    高德地图API使用详解 前言 正文 一.创建应用 ① 获取PackageName ② 获取调试版安全码SHA1 ③ 获取发布版安全码SHA1 二.配置Android Studio工程 ① 导入SDK ...

  5. Android 百度语音识别(详细步骤+源码)

    前言 因为项目中用到了语音识别的技术,但是项目源码我不能公开,所以,重新写一个简单的集成教程,不喜可不看,不做键盘侠,文明你我他. 效果图 识别结果 最终效果 源码在文章最后,不需要下载积分什么的,哪 ...

  6. Android 百度文字识别(详细步骤+源码)

    运行效果图 识别到的内容: {"words_result":[{"words":"突然间有想看书的冲动"},{"words&quo ...

  7. Android 腾讯位置服务使用(详细步骤+源码)

    腾讯位置服务使用 前言 正文 一.注册腾讯位置服务账号 二.创建平台应用Appkey 三.创建并配置AS工程 四.定位 ① 连续定位 ② 单次定位 ③ 后台定位 ④ 地理围栏 五.地图 ① 基础地图 ...

  8. 使用Keras和OpenCV实时预测年龄、性别和情绪 (详细步骤+源码)

    来源 | https://towardsdatascience.com/real-time-age-gender-and-emotion-prediction-from-webcam-with-ker ...

  9. python在线编程翻译器-【分享】python 翻译器,爬取百度翻译,并附上源码

    [Python] 纯文本查看 复制代码#!/usr/bin/python # -*- coding: cp936 -*- ####################################### ...

  10. python代码翻译器-【分享】python 翻译器,爬取百度翻译,并附上源码

    [Python] 纯文本查看 复制代码#!/usr/bin/python # -*- coding: cp936 -*- ####################################### ...

最新文章

  1. (Incomplete) UVa 719 Glass Beads
  2. NotePad++学习总结
  3. Excel多因素可重复方差分析
  4. 【GitHub】如何合并分支?
  5. 部署及配置Lync Server 2013 监控功能
  6. 纯靠技术,很难进入大厂了。。。
  7. MacBook Pro 如何删除多余专注模式?
  8. 计算机应用基础第十一版答案,计算机应用基础试题十一.xls
  9. 硬件工程师如何零基础入门?
  10. ICO 图标快速制作
  11. gazebo设置_GAZEBO学习笔记(3)
  12. 关于谷歌浏览器全线崩溃的原因及几种解决办法(疑难杂症篇)
  13. 破解不加微信看朋友圈
  14. Android删除系统的WIFI功能
  15. 洛阳等地启动电子劳动合同试点,多家名企选择法大大
  16. 题解 CF133A 【HQ9+】
  17. 手撕鸭腌料批发场 新奥尔良烤肉腌料批发 奥尔良鸡叉骨腌料批发
  18. Caffe中卷基层和全连接层训练参数个数如何确定
  19. ng 无法加载文件 C:\Users\hl\AppData\Roaming\npm\ng.ps1 解决方法
  20. dtoj#4224. 小L的占卜

热门文章

  1. 嵌入式 职位描述 职位要求
  2. 蓝色学校网站模板_中小学网站源码_学校网站管理系统
  3. 互联网盈利模式,网络策划运营模式
  4. 继美国后新加坡电信运营商遭DDoS攻击 部分用户断网
  5. python如何绘制曲线图_Python matplotlib 如何绘制双Y轴曲线图?
  6. 执行maven install命令报java不支持diamond语法
  7. python常用快捷键mac_Mac PHPStorm 常用快捷键,常用设置
  8. win10系统的怎么搭建web服务器,win10系统利用iis搭建web服务器的操作方法
  9. 静止卫星遥感图像太阳及卫星天顶、方位角(SOZ/SOA/SAZ/SAA)计算方法
  10. 智能电视大战背后的秘密