在作项目的过程当中须要链接服务器访问数据,尚未接触过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