在作項目的過程當中須要鏈接服務器訪問數據,尚未接觸過Android網絡編程方面,參考了《Android第一行代碼》,在作的過程當中遇到了不少的問題,這裏就此記錄一下。java
先給出訪問網絡的代碼:android
首先:在AndroidManifest.xml文件中進行聲明,添加以下代碼:git
<uses-permission android:name="android.permission.INTERNET" />github
編寫網絡操做類:編程
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.NetworkOnMainThreadExceptionapp
先來看第一個錯誤ide
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)更改網絡安全配置
這裏我就是用的第三種方法,下面來詳細說一下步驟。
一、在res文件夾下建立一個xml文件夾,而後建立一個network_security_config.xml文件,文件中內容以下:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true"/>
</network-security-config>
二、在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);
}
二、啓動子線程進行網絡請求,更推薦使用這種
new Thread(new Runnable(){
@Override
public void run(){
//進行網絡訪問操做
}).start()
這裏主要參考了博客:https://blog.csdn.net/qq_29477223/article/details/81027716
書中後面也給出了更簡單的方法,使用OkHttp這裏我簡單放一下代碼:
一、在build.gradle/app中添加依賴
implementation ("com.squareup.okhttp3:okhttp:3.14.2")
注:這裏OkHttp的版本會有更改,須要到OkHttp在github的官網進行查看,這裏我附上網址自行查看:https://github.com/square/okhttp
二、修改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); } }
三、調用代碼
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