Android 網(wǎng)絡編程-網(wǎng)絡請求
本文介紹一下Android 網(wǎng)絡請求,開發(fā)了簡單demo,適合Android入門人員學習。
為啥要寫這個??給應屆生看的。。。
一、主要內容
1、開發(fā)網(wǎng)絡請求前的基本準備
2、普通網(wǎng)絡請求代碼
3、使用OkHttp網(wǎng)絡框架請求網(wǎng)絡代碼
4、使用Retrofit網(wǎng)絡框架請求網(wǎng)絡代碼
5、使用WebView顯示對應網(wǎng)址的網(wǎng)頁
6、應用demo的相關代碼和apk
二、開發(fā)網(wǎng)絡請求前的基本準備
1、查看需要請求的網(wǎng)址是否有效
(1)通過網(wǎng)頁在線驗證
能驗證get請求和簡單的post 請求,比如只設置幾個參數(shù)的post請求
在線get/post請求測試(里面還有一系列工具):
http://www.jsons.cn/httpurl/
http://coolaf.com/
//可以簡單模擬 get/post返回的數(shù)據(jù)
https://v7.apipost.cn/#/apis/design
(2)使用專用window網(wǎng)咯請求工具
① PostMan
② Apifox (國內自研,PostMan加強版,支持網(wǎng)頁和桌面工具)
https://apifox.com/#pricing
(3)編寫app代碼驗證
一般用于驗證文件上傳的情況,
也可以用windows 工具進行驗證,Apifox 也是支持文件上傳的。
2、學會把服務器的json數(shù)據(jù)轉換成Bean對象
在線轉換Json格式轉換JAVA實體Bean類:
http://www.jsons.cn/json2java/
作用?
把字符串的數(shù)據(jù)賦值到對象,使用的時候直接使用 Object.getXXX 獲取返回的某個信息。
也可以使用Android Studio 插件:GsonFormat
3、具體效果測試
get請求測試,可以找網(wǎng)上天氣網(wǎng)址的api或者笑話類的api網(wǎng)址;
post請求測試,可以找地圖類的api(百度地圖),或者語音類的api網(wǎng)址(訊飛)。
簡單測試的網(wǎng)址:
天氣api:
提供天氣,氣象查詢:https://www.yiketianqi.com/index/doc
get請求網(wǎng)址;
https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=28392918&appsecret=No9zfo8f&adcode=440307000000
apipost調試網(wǎng)址
提供get/post簡單調試功能:https://v7.apipost.cn/#/apis/design
注冊登陸后,看起來是可以設計返回的數(shù)據(jù)的,估計是操作要麻煩一點,有需要的可以自己研究。
post請求網(wǎng)址:
https://demo-api.apipost.cn/api/demo/login
mobile=18289454846&ver_code=123456
(1)get請求,在瀏覽器窗口欄請求的顯示
(2)get請求在在線請求網(wǎng)址的顯示
(3)post請求在在線請求的的網(wǎng)址顯示
post 請求在瀏覽器輸入行直接是無法請求到數(shù)據(jù)的,只能使用專業(yè)的網(wǎng)址或者工具 獲取post請求的數(shù)據(jù)。
(4)json數(shù)據(jù)在線轉換成Bean對象
應用app效果顯示;
主界面:
普通網(wǎng)絡請求:
OkHttp網(wǎng)絡請求:
retrofit網(wǎng)絡請求:
為啥這里TextView顯示的不對,大家可以在代碼里面看看。
WebView界面:
應用demo里面顯示了很多WebView界面,這里只展示其中一個。
代碼資源下載地址:
https://download.csdn.net/download/wenzhi20102321/88215651
三、代碼介紹
1、普通網(wǎng)絡請求
網(wǎng)絡請求一定要在子線程執(zhí)行,否則會報錯。
數(shù)據(jù)返回后要顯示在界面上要切換回主線程。
(1)get網(wǎng)絡請求
//get方法請求網(wǎng)絡
public void getNetwork(View view) {
GET_UTL = et_url_get.getText().toString();
LogUtil.debugInform("GET_UTL = " + GET_UTL);
//創(chuàng)建線程,請求網(wǎng)絡
new Thread(new Runnable() {
@Override
public void run() {
// 創(chuàng)建一個URL對象
URL url = null;
try {
url = new URL(GET_UTL);
// 創(chuàng)建一個HttpURLConnection對象,并設置請求方法為GET
HttpURLConnection connection = null;
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
// 獲取服務器響應的狀態(tài)碼
int responseCode = 0;
responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// 讀取服務器響應的數(shù)據(jù)
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line); //把讀取的數(shù)據(jù)不斷放入response對象中
}
reader.close();
// 在UI線程中更新UI runOnUiThread
String responseData = response.toString();
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.error("", e);
}
}
}).start();
}
(2)Post網(wǎng)絡請求
//post方法請求王網(wǎng)絡
public void postNetwork(View view) {
//創(chuàng)建線程,請求網(wǎng)絡
new Thread(new Runnable() {
@Override
public void run() {
// 創(chuàng)建一個URL對象
URL url = null;
try {
url = new URL(POST_UTL);
// 創(chuàng)建一個HttpURLConnection對象,并設置請求方法為GET
HttpURLConnection connection = null;
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
//------------------------------ 區(qū)別和Get方法 ,Start
connection.setRequestMethod("POST");
// 啟用輸出流,以便向服務器發(fā)送數(shù)據(jù)
connection.setDoOutput(true);
// 創(chuàng)建一個輸出流對象,并將數(shù)據(jù)寫入輸出流
OutputStream outputStream = connection.getOutputStream();
String postData = POST_MESSAGE;
outputStream.write(postData.getBytes());
outputStream.flush();
outputStream.close();
//------------------------------ 區(qū)別和Get方法 ,End
// 獲取服務器響應的狀態(tài)碼
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// 讀取服務器響應的數(shù)據(jù)
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line); //把讀取的數(shù)據(jù)不斷放入response對象中
}
reader.close();
// 在UI線程中更新UI
// 處理服務器響應的數(shù)據(jù)
String responseData = response.toString();
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.error("", e);
}
}
}).start();
}
2、使用OkHttp網(wǎng)絡框架請求網(wǎng)絡
(1)Get網(wǎng)絡請求
//get方法請求網(wǎng)絡
public void getNetwork(View view) {
Request request = new Request.Builder()
.url(GET_UTL)
.get() //默認為get ,不設置也行
.build();
Call call = client.newCall(request);
//網(wǎng)絡請求的回調
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 {
// 處理服務器響應的數(shù)據(jù)
String responseData = response.body().string();
LogUtil.debugInform("responseData = " + responseData);
// TODO: 在這里處理服務器響應的數(shù)據(jù)
}
});
}
(2)Post網(wǎng)絡請求
//post方法請求王網(wǎng)絡
public void postNetwork(View view) {
//創(chuàng)建網(wǎng)絡處理的對象
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(5, TimeUnit.SECONDS)
.build();
//mobile=18289454846&ver_code=123456
//post請求來獲得數(shù)據(jù)
//創(chuàng)建一個RequestBody,存放重要數(shù)據(jù)的鍵值對
RequestBody body = new FormBody.Builder()
.add("mobile", "18289454846")
.add("ver_code", "123456").build();
//創(chuàng)建一個請求對象,傳入URL地址和相關數(shù)據(jù)的鍵值對的對象
Request request = new Request.Builder()
.url(POST_UTL)
.post(body).build();
//創(chuàng)建一個能處理請求數(shù)據(jù)的操作類
Call call = client.newCall(request);
//使用異步任務的模式請求數(shù)據(jù)
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);
}
});
}
3、使用Retrofit網(wǎng)絡框架請求網(wǎng)絡
(1)Get網(wǎng)絡請求
請求示例網(wǎng)址:
https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=28392918&appsecret=No9zfo8f&adcode=440307000000
①創(chuàng)建請求接口對象
package com.example.networkdemo.retrofit;
import com.example.networkdemo.bean.WeatherBean;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
/**
* Get請求
* 這里使用get請求的方式請求數(shù)據(jù)
* 并且到的是字符串數(shù)據(jù)
*/
public interface RetrofitWeatherService {
//鍵值對的定義和數(shù)據(jù)的返回類型的定義這里是String
//https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=28392918&appsecret=No9zfo8f&adcode=440307000000
//這里使用 @Field 是會報錯,是要使用 @Query
@GET("api")//get請求方式
Call<WeatherBean> getWeather(@Query("unescape") String unescape, @Query("version") String version,
@Query("appid") String appid, @Query("appsecret") String appsecret, @Query("adcode") String adcode);
}
② 具體的請求代碼
比如在某個Activity寫如下代碼
//get方法請求網(wǎng)絡
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<WeatherBean> call = weatherService.getWeather("1", "v61", "28392918", "No9zfo8f", "440307000000");
//轉換成Call,在call對象包含Url的完整地址
//可以看到這里使用了create的方法,里面?zhèn)魅肓苏埱蠓盏慕涌陬? //并且后面接的是接口類的方法,方法里面?zhèn)魅險rl地址要的鍵值對的值
//這時call對象就有完整的Url地址,就可以請求數(shù)據(jù)了
//使用call對象進行網(wǎng)絡數(shù)據(jù)請求
call.enqueue(new Callback<WeatherBean>() {
//網(wǎng)絡數(shù)據(jù)請求成功的回調方法
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
runOnUiThread(new Runnable() {
@Override
public void run() {
WeatherBean bean = response.body();
tv_info.setText(TimeUtil.getTimeString() + " \n Get請求的數(shù)據(jù):" + 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();
}
});
}
//網(wǎng)絡數(shù)據(jù)請求失敗的回調方法
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
tv_info.setText(TimeUtil.getTimeString() + " \n Get 請求的失敗日志:" + t.getMessage() + "");
}
});
}
(2)Post網(wǎng)絡請求
Post請求網(wǎng)址:https://demo-api.apipost.cn/api/demo/login
攜帶信息:mobile=18289454846&ver_code=123456
①創(chuàng)建請求接口對象
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請求的方式請求數(shù)據(jù)
* 并且到的是一個自定義的對象數(shù)據(jù)
*/
public interface RetrofitLoginService {
//https://demo-api.apipost.cn/api/demo/login
@POST("api/demo/login")//Post請求方式
@FormUrlEncoded //鍵值對的定義和數(shù)據(jù)的返回類型的定義這里是String
Call<LoginBean> login(@Field("mobile") String mobile, @Field("ver_code") String ver_code);
}
② 具體的請求代碼
//post方法請求王網(wǎng)絡
public void postNetwork(View view) {
Retrofit retrofit = getGsonRetrofit(POST_UTL); //https://demo-api.apipost.cn/
RetrofitLoginService loginService = retrofit.create(RetrofitLoginService.class);
Call<LoginBean> call = loginService.login("18289454846", "123456");
call.enqueue(new Callback<LoginBean>() {
@Override
public void onResponse(Call<LoginBean> call, Response<LoginBean> response) {
// 在UI線程中更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
// 處理服務器響應的數(shù)據(jù)
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: 在這里處理服務器響應的數(shù)據(jù)
tv_info.setText(TimeUtil.getTimeString() + " \n Post請求的數(shù)據(jù):" + response + "");
}
});
}
@Override
public void onFailure(Call<LoginBean> 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;
}
4、使用WebView顯示對應網(wǎng)址的網(wǎng)頁
(1)在布局文件寫入控件WebView
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
(2) 設置基本參數(shù)
web_view = findViewById(R.id.web_view);
WebSettings webSettings = web_view.getSettings();
//如果訪問的頁面中要與Javascript交互,則webview必須設置支持Javascript
webSettings.setJavaScriptEnabled(true);
webSettings.setDefaultTextEncodingName("utf-8");//設置編碼格式
//要顯示的網(wǎng)址:
web_view.loadUrl(url); //設置網(wǎng)址
這里只是基本代碼,還可以設置跳轉監(jiān)聽,前進后退網(wǎng)頁跳轉等,可以自己調試研究。
三、總結
1、網(wǎng)絡請求是要在子線程內進行
2、不同框架的網(wǎng)絡請求根據(jù)項目具體情況使用
如果頻率很多的使用網(wǎng)絡請求,直接使用原生請求即可,不用使用網(wǎng)絡框架。
如果使用頻率很高,可以使用健全的網(wǎng)絡框架:OkHttp/Retrofit;
OkHttp使用簡單,Retrofit 使用復雜一些,但是和很多其他框架可以結合使用,比如Gson,RxJava等。
3、Android 網(wǎng)絡編程要學習些什么
(1)網(wǎng)絡分層和HTTP協(xié)議基本知識,比如請求報文和響應報文
雖然不一定會用到,但是也是要知道里面的知識點。
(2)Java網(wǎng)絡編程基礎,TCP/UDP 進行連接交互
可以寫demo,一個作為客戶端一個作為服務端,連接后進行通訊交互。
(3)Json數(shù)據(jù)轉Gson對象
網(wǎng)絡上數(shù)據(jù)請求基本都是返回json數(shù)據(jù),使用Gson對象可以直接轉換成對應的對象,使用起來比較方便。
但是也有一些網(wǎng)絡請求返回的數(shù)據(jù)不是json數(shù)據(jù)格式,比如xml格式,或者其他特定格式。
這個就需要自己寫工具類進行解析了。
(4)Android基本網(wǎng)絡請求和基本網(wǎng)絡框架使用
不使用網(wǎng)絡框架請求網(wǎng)絡和使用主流網(wǎng)絡框架請求網(wǎng)絡。文章來源:http://www.zghlxwxcb.cn/news/detail-649426.html
(5)加密算法:數(shù)據(jù)加密和解密
因為網(wǎng)絡數(shù)據(jù)是經(jīng)過加密的,所以必須要經(jīng)過解密才能讀取到正常數(shù)據(jù)。
算法是會使用框架就行了的,具體算法一般人寫不出來!文章來源地址http://www.zghlxwxcb.cn/news/detail-649426.html
到了這里,關于Android 網(wǎng)絡編程-網(wǎng)絡請求的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!