本文介绍一下Android 网络请求,开发了简单demo,适合Android入门人员学习。
为啥要写这个??给应届生看的。。。
1、开发网络请求前的基本准备
2、普通网络请求代码
3、使用OkHttp网络框架请求网络代码
4、使用Retrofit网络框架请求网络代码
5、使用WebView显示对应网址的网页
6、应用demo的相关代码和apk
能验证get请求和简单的post 请求,比如只设置几个参数的post请求
在线get/post请求测试(里面还有一系列工具):
http://www.jsons.cn/httpurl/
http://coolaf.com/
//可以简单模拟 get/post返回的数据
https://v7.apipost.cn/#/apis/design
① PostMan
② Apifox (国内自研,PostMan加强版,支持网页和桌面工具)
https://apifox.com/#pricing
一般用于验证文件上传的情况,
也可以用windows 工具进行验证,Apifox 也是支持文件上传的。
在线转换Json格式转换JAVA实体Bean类:
http://www.jsons.cn/json2java/
作用?
把字符串的数据赋值到对象,使用的时候直接使用 Object.getXXX 获取返回的某个信息。
也可以使用Android Studio 插件:GsonFormat
get请求测试,可以找网上天气网址的api或者笑话类的api网址;
post请求测试,可以找地图类的api(百度地图),或者语音类的api网址(讯飞)。
提供天气,气象查询:https://www.yiketianqi.com/index/doc
get请求网址;
https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=28392918&appsecret=No9zfo8f&adcode=440307000000
提供get/post简单调试功能:https://v7.apipost.cn/#/apis/design
注册登陆后,看起来是可以设计返回的数据的,估计是操作要麻烦一点,有需要的可以自己研究。
post请求网址:
https://demo-api.apipost.cn/api/demo/login
mobile=18289454846&ver_code=123456
post 请求在浏览器输入行直接是无法请求到数据的,只能使用专业的网址或者工具 获取post请求的数据。
普通网络请求:
retrofit网络请求:
为啥这里TextView显示的不对,大家可以在代码里面看看。
应用demo里面显示了很多WebView界面,这里只展示其中一个。
代码资源下载地址:
https://download.csdn.net/download/wenzhi20102321/88215651
网络请求一定要在子线程执行,否则会报错。
数据返回后要显示在界面上要切换回主线程。
//get方法请求网络
public void getNetwork(View view) {
GET_UTL = et_url_get.getText().toString();
LogUtil.debugInform("GET_UTL = " + GET_UTL);
//创建线程,请求网络
new Thread(new Runnable() {
@Override
public void run() {
// 创建一个URL对象
URL url = null;
try {
url = new URL(GET_UTL);
// 创建一个HttpURLConnection对象,并设置请求方法为GET
HttpURLConnection connection = null;
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
// 获取服务器响应的状态码
int responseCode = 0;
responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// 读取服务器响应的数据
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line); //把读取的数据不断放入response对象中
}
reader.close();
// 在UI线程中更新UI runOnUiThread
String responseData = response.toString();
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.error("", e);
}
}
}).start();
}
//post方法请求王网络
public void postNetwork(View view) {
//创建线程,请求网络
new Thread(new Runnable() {
@Override
public void run() {
// 创建一个URL对象
URL url = null;
try {
url = new URL(POST_UTL);
// 创建一个HttpURLConnection对象,并设置请求方法为GET
HttpURLConnection connection = null;
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
//------------------------------ 区别和Get方法 ,Start
connection.setRequestMethod("POST");
// 启用输出流,以便向服务器发送数据
connection.setDoOutput(true);
// 创建一个输出流对象,并将数据写入输出流
OutputStream outputStream = connection.getOutputStream();
String postData = POST_MESSAGE;
outputStream.write(postData.getBytes());
outputStream.flush();
outputStream.close();
//------------------------------ 区别和Get方法 ,End
// 获取服务器响应的状态码
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// 读取服务器响应的数据
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line); //把读取的数据不断放入response对象中
}
reader.close();
// 在UI线程中更新UI
// 处理服务器响应的数据
String responseData = response.toString();
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.error("", e);
}
}
}).start();
}
//get方法请求网络
public void getNetwork(View view) {
Request request = new Request.Builder()
.url(GET_UTL)
.get() //默认为get ,不设置也行
.build();
Call call = client.newCall(request);
//网络请求的回调
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
Toast.makeText(OkhttpNetworkActivity.this, "请求错误:" + e.getMessage(), Toast.LENGTH_LONG).show();
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
// 处理服务器响应的数据
String responseData = response.body().string();
LogUtil.debugInform("responseData = " + responseData);
// TODO: 在这里处理服务器响应的数据
}
});
}
//post方法请求王网络
public void postNetwork(View view) {
//创建网络处理的对象
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(5, TimeUnit.SECONDS)
.build();
//mobile=18289454846&ver_code=123456
//post请求来获得数据
//创建一个RequestBody,存放重要数据的键值对
RequestBody body = new FormBody.Builder()
.add("mobile", "18289454846")
.add("ver_code", "123456").build();
//创建一个请求对象,传入URL地址和相关数据的键值对的对象
Request request = new Request.Builder()
.url(POST_UTL)
.post(body).build();
//创建一个能处理请求数据的操作类
Call call = client.newCall(request);
//使用异步任务的模式请求数据
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
LogUtil.error("", e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 在UI线程中更新UI
String responseData = response.body().string();
LogUtil.debugInform("result = " + responseData);
}
});
}
请求示例网址:
https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=28392918&appsecret=No9zfo8f&adcode=440307000000
package com.example.networkdemo.retrofit;
import com.example.networkdemo.bean.WeatherBean;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
/**
* Get请求
* 这里使用get请求的方式请求数据
* 并且到的是字符串数据
*/
public interface RetrofitWeatherService {
//键值对的定义和数据的返回类型的定义这里是String
//https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=28392918&appsecret=No9zfo8f&adcode=440307000000
//这里使用 @Field 是会报错,是要使用 @Query
@GET("api")//get请求方式
Call getWeather(@Query("unescape") String unescape, @Query("version") String version,
@Query("appid") String appid, @Query("appsecret") String appsecret, @Query("adcode") String adcode);
}
比如在某个Activity写如下代码
//get方法请求网络
public void getNetwork(View view) {
Retrofit retrofit = getGsonRetrofit(GET_UTL);
RetrofitWeatherService weatherService = retrofit.create(RetrofitWeatherService.class);
//?unescape=1&version=v61&appid=28392918&appsecret=No9zfo8f&adcode=440307000000"
Call call = weatherService.getWeather("1", "v61", "28392918", "No9zfo8f", "440307000000");
//转换成Call,在call对象包含Url的完整地址
//可以看到这里使用了create的方法,里面传入了请求服务的接口类
//并且后面接的是接口类的方法,方法里面传入Url地址要的键值对的值
//这时call对象就有完整的Url地址,就可以请求数据了
//使用call对象进行网络数据请求
call.enqueue(new Callback() {
//网络数据请求成功的回调方法
@Override
public void onResponse(Call call, Response response) {
runOnUiThread(new Runnable() {
@Override
public void run() {
WeatherBean bean = response.body();
tv_info.setText(TimeUtil.getTimeString() + " \n Get请求的数据:" + bean + "");
String air_tips = bean.getAir_tips();
String update_time = bean.getUpdate_time();
String tem1 = bean.getTem1();
String tem2 = bean.getTem2();
String tem = bean.getTem();
Toast.makeText(RetrofitNetworkActivity.this, "天气时间:" + update_time
+ "\n 当前温度:" + tem + ",温度变化" + tem2 + "--" + tem1 +
"\n 温馨提示:" + air_tips, Toast.LENGTH_LONG).show();
}
});
}
//网络数据请求失败的回调方法
@Override
public void onFailure(Call call, Throwable t) {
tv_info.setText(TimeUtil.getTimeString() + " \n Get 请求的失败日志:" + t.getMessage() + "");
}
});
}
Post请求网址:https://demo-api.apipost.cn/api/demo/login
携带信息:mobile=18289454846&ver_code=123456
package com.example.networkdemo.retrofit;
import com.example.networkdemo.bean.LoginBean;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
/**
* 登陆服务器的请求
* 这里使用post请求的方式请求数据
* 并且到的是一个自定义的对象数据
*/
public interface RetrofitLoginService {
//https://demo-api.apipost.cn/api/demo/login
@POST("api/demo/login")//Post请求方式
@FormUrlEncoded //键值对的定义和数据的返回类型的定义这里是String
Call login(@Field("mobile") String mobile, @Field("ver_code") String ver_code);
}
//post方法请求王网络
public void postNetwork(View view) {
Retrofit retrofit = getGsonRetrofit(POST_UTL); //https://demo-api.apipost.cn/
RetrofitLoginService loginService = retrofit.create(RetrofitLoginService.class);
Call call = loginService.login("18289454846", "123456");
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
// 在UI线程中更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
// 处理服务器响应的数据
LoginBean loginBean = response.body();
LogUtil.debugInform("loginBean = " + loginBean);
int code = loginBean.getCode();
LoginBean.DataBean data = loginBean.getData();
String msg = loginBean.getMsg();
Toast.makeText(RetrofitNetworkActivity.this, "登陆信息:" +
"\n code = " + code + ", msg = " + msg, Toast.LENGTH_LONG).show();
LogUtil.debugInform("data getToken = " + data.getToken());
// TODO: 在这里处理服务器响应的数据
tv_info.setText(TimeUtil.getTimeString() + " \n Post请求的数据:" + response + "");
}
});
}
@Override
public void onFailure(Call call, Throwable t) {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_info.setText(TimeUtil.getTimeString() + " \n Post请求的失败日志:" + t.getMessage() + "");
}
});
}
});
}
//返回一个Gson类型的对象
public Retrofit getGsonRetrofit(String url) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
//返回一个Gson类型的字符串,
public Retrofit getStringRetrofit(String url) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(url)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
return retrofit;
}
web_view = findViewById(R.id.web_view);
WebSettings webSettings = web_view.getSettings();
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
webSettings.setJavaScriptEnabled(true);
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
//要显示的网址:
web_view.loadUrl(url); //设置网址
这里只是基本代码,还可以设置跳转监听,前进后退网页跳转等,可以自己调试研究。
如果频率很多的使用网络请求,直接使用原生请求即可,不用使用网络框架。
如果使用频率很高,可以使用健全的网络框架:OkHttp/Retrofit;
OkHttp使用简单,Retrofit 使用复杂一些,但是和很多其他框架可以结合使用,比如Gson,RxJava等。
虽然不一定会用到,但是也是要知道里面的知识点。
可以写demo,一个作为客户端一个作为服务端,连接后进行通讯交互。
网络上数据请求基本都是返回json数据,使用Gson对象可以直接转换成对应的对象,使用起来比较方便。
但是也有一些网络请求返回的数据不是json数据格式,比如xml格式,或者其他特定格式。
这个就需要自己写工具类进行解析了。
不使用网络框架请求网络和使用主流网络框架请求网络。
因为网络数据是经过加密的,所以必须要经过解密才能读取到正常数据。
算法是会使用框架就行了的,具体算法一般人写不出来!