猛禽洛的程式筆記庫

[Android] okhttp3 使用說明

okhttp3為一個網路通訊套件,能夠快速實作出post.get.put等功能。

首先先加入此套件包:build.gradle(app)

implementation 'com.squareup.okhttp3:okhttp:4.8.0'

加入網路權限:manifests

<uses-permission android:name="android.permission.INTERNET" />

這樣子就準備完成了。

 

首先先來了解execute與enqueue的差異:

execute:同步執行,可以用在背景執行緒中,當完成一個任務時,才繼續執行下一個任務,會比較好控管流程;使用Response接收回應狀態。

enqueue:非同步執行,適合用在主執行緒中,會自動產生一個新執行緒,不會卡住畫面,當收到回應需要更新畫面時,記得要切換回主執行緒(runOnUiThread);使用Callback接收回應狀態。

 

接下來是功能使用的部分:

取得伺服器JSON資料(POST):

OkHttpClient client = new OkHttpClient();
//這邊設定為接收JSON
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");

//帶在Body給伺服器的資料
JSONObject data = new JSONObject();
data.put("idNumber", "0123456789");
data.put("password", "987654321");

//將資料放進Body中
RequestBody requestBody = RequestBody.create(data.toString(), mediaType);
Request request = new Request.Builder()
    .url("http://192.168.1.1")//目標網址
    .post(requestBody)
    .build();

//使用非同步執行
client.newCall(request).enqueue(new Callback() {
  @Override
  public void onFailure(final Call call, final IOException e) {
    // Handle the error 失敗訊息
    e.printStackTrace();
  }
  @Override
  public void onResponse(final Call call, final Response response) throws IOException {
    //注意:response.body()只能讀取一次,所以要重複使用的話必須另外存下來
    String responseString = response.body().string();
    int responseCode = response.code();
    LogUtil.d("onResponse", responseCode + "");
    LogUtil.d("onResponse", responseString);

    switch (responseCode){
      case 200:
        //資料處理
        break;
    }
  }
});

 

 

上傳檔案(put):

OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("multipart/form-data");//這邊設定為multipart/form-data
RequestBody requestBody = RequestBody.create(filesUpload[i], mediaType);//將檔案放入Body中

MultipartBody multipartBody = new MultipartBody.Builder()
    .setType(mediaType)
    .addFormDataPart("file", filesUpload[i].getName(), requestBody)
    .build();

Request request = new Request.Builder()
    .url("http://127.0.0.1/upload")//上傳網址
    .addHeader("Auth","123456")//可以帶一些認證
    .put(multipartBody)//使用put上傳
    .build();

//執行上傳
//使用非同步執行
client.newCall(request).enqueue(new Callback() {

  @Override
  public void onFailure(final Call call, final IOException e) {
    // Handle the error 失敗訊息
    e.printStackTrace();
  }

  @Override
  public void onResponse(final Call call, final Response response) throws IOException {
    if (!response.isSuccessful()) {//如果response code介於200-300之間就是成功
      // Handle the error 上傳失敗訊息
      LogUtil.e("onResponse", response.toString());
    }
    // Upload successful 上傳成功
    LogUtil.e("onResponse-successful", response.toString());
  }
});

如果想用同步方式執行(execute),可以這樣子寫:

try {
  Response response = client.newCall(request).execute();
  if(response.isSuccessful()){
    //上傳成功
  }else{
    //上傳失敗
  }
} catch (IOException e) {
  e.printStackTrace();
}

 

OkHttpClient的設定:

client = new OkHttpClient.Builder()
  //設定連線超時
  .connectTimeout(30, TimeUnit.SECONDS)
  .writeTimeout(30, TimeUnit.SECONDS)
  .readTimeout(30, TimeUnit.SECONDS)
  .build();

 

Log顯示 Interceptor功能:

很好用的Log列印功能,會印出每次的連線詳細資訊,方便我們觀看狀況。

加入此套件包:build.gradle(app)

implementation 'com.squareup.okhttp3:logging-interceptor:4.8.0'

注意:interceptor的版本必須跟上面的okhttp版本一樣,才能正常使用

然後在OkHttpClient加入Interceptor:

OkHttpClient client = new OkHttpClient.Builder()
  .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
  .build();

這樣在網路連線時,就會顯示類似以下資料:

I/okhttp.OkHttpClient: --> PUT http://127.0.0.1:8085/v1/devices (49371363-byte body)
I/okhttp.OkHttpClient: <-- 204 No Content http://127.0.0.1:8085/v1/devices (123ms, 0-byte body)

這樣就可以讓我們更清楚連線過程中發生了什麼事情!

 



Kotlin中的用法:

一般GET:

val client = OkHttpClient()
val request = Request.Builder()
    .url("https//xxxxx.nnn")
    .addHeader("Authorization", "自己的驗證訊息")
    .build()
//執行GET
client.newCall(request).enqueue(object : Callback {
    //通常是網路連線錯誤的情況
  override fun onFailure(call: Call, e: IOException) {
    e.printStackTrace()
    runOnUiThread {//因為在執行緒中,所以要用runOnUiThread來更新UI畫面
      Toast.makeText(this@MainActivity, "請檢查網路連線", Toast.LENGTH_LONG).show()
    }
  }
    //收到回覆區域
  override fun onResponse(call: Call, response: Response) {
    var responseString = response.body?.string()
    val responseCode = response.code
    LogUtil.d("onResponse", responseString)
        //進行自己的判斷、下一步
    runOnUiThread {
      when (responseCode) {
        200 -> {
          
        }
        404 -> {
          
        }
        500 -> {
          
        }
        else -> {
        
        }
      }
    }
  }
})

 

POST用法:

//要POST的訊息
val userProfile = JSONObject()
userProfile.put("email", "xxxxxxx")
userProfile.put("name", "nnnnn")
userProfile.put("phone", "09123456")

//將JSON轉換為RequestBody
val requestBody = userProfile.toString().toRequestBody()

val client = OkHttpClient()
val request = Request.Builder()
    .url("https//xxxxx.nnn")
    .method("POST", requestBody)//將RequestBody帶進POST中
    .addHeader("Authorization", "自己的驗證訊息")
    .build()
    
//執行 跟GET一樣
client.newCall(request).enqueue(object : Callback {
    //通常是網路連線錯誤的情況
  override fun onFailure(call: Call, e: IOException) {
    e.printStackTrace()
    runOnUiThread {//因為在執行緒中,所以要用runOnUiThread來更新UI畫面
      Toast.makeText(this@MainActivity, "請檢查網路連線", Toast.LENGTH_LONG).show()
    }
  }
    //收到回覆區域
  override fun onResponse(call: Call, response: Response) {
    var responseString = response.body?.string()
    val responseCode = response.code
    LogUtil.d("onResponse", responseString)
        //進行自己的判斷、下一步
    runOnUiThread {
      when (responseCode) {
        200 -> {
          
        }
        404 -> {
          
        }
        500 -> {
          
        }
        else -> {
        
        }
      }
    }
  }
})

 

 

-待續-

 

 

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *