笔者最近用图灵V2版本,V2跟V1版比起来,很大的区别是网络请求,V1版只需一条网址链接即可请求数据,V2版本则需要以请求参数格式为 json的post请求数据,无疑增大了难度
打开图灵官网API V2.0接入文档
文档给我们提供了请求示例和返回示例,看着数据十分复杂,复杂的数据就不必用android原生的json解析方式了,因为很容易出错。这里用谷歌的神器gson以及它的插件GsonFormat(用来生成json数据对应的javabean)
请求示例:
{
"reqType":0,
"perception": {
"inputText": {
"text": "附近的酒店"
},
"inputImage": {
"url": "imageUrl"
},
"selfInfo": {
"location": {
"city": "北京",
"province": "北京",
"street": "信息路"
}
}
},
"userInfo": {
"apiKey": "",
"userId": ""
}
}
根据你的用途,选择你需要的数据,比如说我根本不需要图片聊天和定位,那我可以删掉上面的
"inputImage": {
"url": "imageUrl"
},
"selfInfo": {
"location": {
"city": "北京",
"province": "北京",
"street": "信息路"
}
}
然后把剩下的json数据复制,在项目里建立一个javabean类,名字就叫Ask.class吧,表示
发送数据实体类,根据发送给图灵api的json,使用GsonFormat工具生成请求数据实体类Ask(请求体)
给Android Studio安装好Gsonformat,在建好的Ask.class里按alt+s,把json数据示例复制进去,点击ok即可生成对应代码,这个Ask.class就搞定了
打开谷歌浏览器的postman插件,测试一下发送数据给图灵api,看有没有返回数据,text里面自己写想跟图灵聊的内容,apiKey和userId要上图灵官网自取
点击Send得到返回数据
然后把返回的数据复制一下,建立一个Take.class,作为接收的Json数据实体类,然后用把这些返回数据复制到GsonFormat里生成代码就好啦。
接下来,咱们就要进行写代码进行网络请求了,这里用retrofit2网络框架,它结合了gson和okHttp3,是个集网络请求和数据处理的强大工具,具体使用可以看Android:手把手带你深入剖析 Retrofit 2.0 源码和
这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)
在build.gradle里添加依赖
// Retrofit
// retrofit
implementation 'com.squareup.okhttp3:okhttp:3.1.2'
implementation 'com.squareup.retrofit2:retrofit:2.0.1'
implementation 'com.squareup.retrofit2:converter-gson:2.0.1'
添加网络权限
创建 用于描述网络请求 的接口
Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数
/**
* 描述: Retrofit的实现接口
*/
public interface Api {
//发送json数据形式的post请求,把网络请求接口的后半部分openapi/api/v2写在里面
//Get是请求数据实体类,Take接受数据实体类
@POST("openapi/api/v2") //Post请求发送数据
Call request(@Body Ask ask);//@body即非表单请求体,被@Body注解的ask将会被Gson转换成json发送到服务器,返回到Take。 // 其中返回类型为Call<*>,*是接收数据的类
}
关于请求体:
可以指定一个对象用作带有 @Body 注释的 HTTP 请求体。
该对象也将使用 Retrofit 实例上指定的转换器(ConverterFactory)进行转换。 如果没有添加转换器,则只能使用 RequestBody。
创建 Retrofit 实例
// 创建Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://openapi.tuling123.com/")//设置网络请求url,后面一段写在网络请求接口里面
.addConverterFactory(GsonConverterFactory.create())//添加Gson支持,然后Retrofit就会使用Gson将响应体(api接口的Take)转换我们想要的类型。
.build();
baseUrl其实就是我们请求地址的域名,这个域名配合上文的Api.class接口中的参数才是一个完整的请求路径。
把数据填入ask,形成json格式的请求体
private void request(String text) {
// 把输入的文本数据存储在请求实体类中,赋予了各个字段的数据
Ask ask = new Ask();
Ask.UserInfoBean info = new Ask.UserInfoBean();//用户信息
info.setApiKey("申请的key");//将机器人的key值填入
info.setUserId("用户id");//将用户id填入
ask.setUserInfo(info);
Ask.PerceptionBean.InputTextBean pre = new Ask.PerceptionBean.InputTextBean(text);//将要发送给机器人的文本数据text的对象(就像遥控器)命名为pre
ask.setPerception(new Ask.PerceptionBean(pre));
创建 网络请求接口实例
// 创建网络请求接口的实例,这样才能调用接口
Api api = retrofit.create(Api.class);
// Take为响应实体类,用来接受机器人返回的回复数据,以下为接口调用
//// 用法和OkHttp的call如出一辙,
//// 不同的是:如果是Android系统,回调方法执行在主线程
Call call = api.request(ask);//ask在前面赋予了各个字段的数据,在接口api中转成了json格式的数据,发送请求
发送网络请求(异步 / 同步)
封装了 数据转换、线程切换的操作
推荐直接用异步请求,因为同步请求需要写在子线程里,增加了代码量。
以下是异步请求:
//发送网络请求(异步)
call.enqueue(new Callback() {
// 请求成功
@Override
public void onResponse(Call call, Response response) {
// 接受到的机器人回复的数据
mText= response.body().getResults().get(0).getValues().getText();
// 把接受到的数据传入addData方法中,类型是TYPE_RECEIVED接受数据
addData(mText, Chat.TYPE_RECEIVED,getCurrentTime());//机器人说的话添加到接收文本框里
saveReceiveData();//保存接收到的数据
speakText(mText);//读出图灵机器人说的话的文本
Log.d(TAG,"接受到的机器人回复的数据: "+mText);
}
// 请求失败
@Override
public void onFailure(Call call, Throwable t) {
Log.d(TAG,"请求失败: "+t.toString());
}
});
}
调用call中的enqueue方法,这是一个异步请求,不会阻塞线程,类似于OKHttp中的enqueue,不同的是这里的两个回调方法onResponse和onFailure都是在主线程中执行,意味着我们可以直接在这两个回调方法中更新UI,爽吧!
Call 实例可以同步或异步执行。 每个实例只能使用一次,但调用 clone()将创建一个可以使用的新实例。
处理返回数据
通过response类的 body()对返回的数据进行处理
上述代码里就有这部分,就是返回体里面取出你所需要的数据(Results里面有个数组,第一个元素{}里就有Values,里面有需要的text)
mText= response.body().getResults().get(0).getValues().getText();
至此,搞定啦!
参考文章:
【Android 进阶】Retrofit2 目前最优雅的网络请求框架
一个App带你学会Retrofit2.0,麻麻再也不用担心我的网络请求了!