使用HTTP協議訪問網絡(Android)


  在做項目的過程中需要連接服務器訪問數據,還沒有接觸過Android網絡編程方面,參考了《Android第一行代碼》,在做的過程中遇到了很多的問題,這里就此記錄一下。

 

先給出訪問網絡的代碼

 

首先:在AndroidManifest.xml文件中進行聲明,添加如下代碼:

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

 

編寫網絡操作類:

public class HttpUtil{

 public static String sendHttpRequest(String address){

  HttpURLConnection connection=null;
  try{
    URL url=new URL(address);
    connection=(HttpURLConnection)url.openConnection();
    MyLog.d(TAG,"point:2");
    connection.setRequestMethod("GET");
    connection.setConnectTimeout(8000);
    connection.setReadTimeout(8000);
    connection.setDoInput(true);
    connection.setDoOutput(true);
    connection.connect();
    MyLog.d(TAG,"point:3");
    InputStream in=connection.getInputStream();
    MyLog.d(TAG,"point:4");
    BufferedReader reader=new BufferedReader((new InputStreamReader(in)));
    StringBuilder response=new StringBuilder();
    String line;

    while((line=reader.readLine())!=null){
        response.append(line);

    }
    MyLog.d(TAG,"point:5");
    return response.toString();

}catch(Exception e){
    e.printStackTrace();
    return e.getMessage();
}finally{
    if(connection!=null){
        connection.disconnect();
    }
}
}

 

 

發起HTTP請求:

        String address="http://www.baidu.com";

        String reponse=HttpUtil.sendHttpRequest(address);

 

這段代碼看似正確,運行的時候會出現錯誤:java.io.IOException,android.os.NetworkOnMainThreadException

 

先來看第一個錯誤

   java.io.IOException: Cleartext HTTP traffic to www.baidu.com not permitted

    為保證用戶數據和設備的安全,Google針對下一代 Android 系統(Android P) 的應用程序,將要求默認使用加密連接,這意味着 Android P 將禁止 App 使用所有未加密的連接,因此運行 Android P 系統的安卓設備無論是接收或者發送流量,未來都不能明碼傳輸,需要使用下一代(Transport Layer Security)傳輸層安全協議,而 Android Nougat 和 Oreo 則不受影響。
    因此在Android P 使用HttpUrlConnection進行http請求會出現以下異常。

    W/System.err: java.io.IOException: Cleartext HTTP traffic to www.baidu.com not permitted

 

    使用Okhttp請求則出現:

java.net.UnknownServiceException: CLEARTEXT communication ** not permitted by network security policy

 針對這個問題,參考網上的資料,主要有三種解決方法:

       (1)APP改用https請求

            這個比較簡單,這里只需要做如下修改:

          

        String address="https://www.baidu.com";
String response= HttpUtil.sendHttpRequest(address);

 

        (2)targetSdkVersion降到27以下

                  只需要在build.gradle/app里進行修改即可

 

        (3)更改網絡安全配置

              這里我就是用的第三種方法,下面來詳細說一下步驟。

             1、在res文件夾下創建一個xml文件夾,然后創建一個network_security_config.xml文件,文件中內容如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true"/>
</network-security-config>


             2、在AndroidManifest,xml文件下的application標簽添加以下屬性:

  <application

      ...

      android:networkSecurityConfig="@xml/network_security_config"

      ...

 />

      當然還有可以不是用引用的方法,會方便一點,直接在主配置文件中添加如下:

         

   android:usesCleartextTraffic="true"

      這兩個都可以,這個時候App可以訪問網絡了。

 

這里主要參考了博客:https://blog.csdn.net/gengkui9897/article/details/82863966

 

 

解決第二個錯誤

 

主要原因是網絡連接不能放在主線程中,這是為了防止進行網絡連接主線程被阻塞住。

在Android4.0以后,會發現,只要是寫在主線程(就是Activity)中的HTTP請求,運行時都會報錯,這是因為Android在4.0以后為了防止應用的ANR(Aplication Not Response)異常,Android這個設計是為了防止網絡請求時間過長而導致界面假死的情況發生。

 

有兩種解決方案:

1.可以再Activity的onCreate()方法中加入這樣一段代碼,適用於網絡請求數據量很小的話,如下

     if (android.os.Build.VERSION.SDK_INT > 9) {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

     }

 

2、啟動子線程進行網絡請求,更推薦使用這種

      new Thread(new Runnable(){

            @Override

            public void run(){

                   //進行網絡訪問操作

            }).start()

 

 

這里主要參考了博客:https://blog.csdn.net/qq_29477223/article/details/81027716

 

 

 

書中后面也給出了更簡單的方法,使用OkHttp這里我簡單放一下代碼:

     1、在build.gradle/app中添加依賴

          implementation ("com.squareup.okhttp3:okhttp:3.14.2")

 

          注:這里OkHttp的版本會有更改,需要到OkHttp在github的官網進行查看,這里我附上網址自行查看:https://github.com/square/okhttp

 

    2、修改HttpUtil中代碼

import okhttp3.OkHttpClient;
import okhttp3.Request;

public class HttpUtil {

    private static final String TAG = "HttpUtil";

    public static void sendOkHttpRequest(String address,okhttp3.Callback callback){

        OkHttpClient client=new OkHttpClient();

        Request request=new Request.Builder()
                .url(address)
                .build();
        client.newCall(request).enqueue(callback);

    }
}

 

        

    3、調用代碼

String address="http://www.baidu.com";
HttpUtil.sendOkHttpRequest(address,new okhttp3.Callback(){

    @Override
    public void onFailure(Call call, IOException e) {
        //對異常情況進行處理
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        //得到服務器返回的具體內容
        String responseData=response.body().string();
        Log.d(TAG,responseData);
    }
});

 

 

這里使用OkHttp節省了很多代碼,並且OkHttp自帶的回調接口也節省了我們不少事情。

到這里App就可以正常進行網絡訪問並得到返回數據了

剛開始學習Android的知識,如果上面有什么錯誤還請大佬們指出來。

 

參考資料:

《Android第一行代碼》第二版,郭霖著

https://blog.csdn.net/gengkui9897/article/details/82863966

https://blog.csdn.net/qq_29477223/article/details/81027716

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM