使用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
使用HTTP协议访问网络(Android)的更多相关文章
- Android 使用 HTTP 协议访问网络
正在看<第一行代码>,记录一下使用 HTTP 协议访问网络的内容吧! 在Android发送Http请求有两种方式,HttpURLConnection和HttpClient. 1.使用Htt ...
- Android使用Http协议访问网络——HttpConnection
套路篇 使用HttpConnection访问网络一般有如下的套路: 1.获取到HttpConnection的实例,new出一个URL对象,并传入目标的网址,然后调用一下openConnection() ...
- Android中使用http协议访问网络
HTTP协议的工作原理:客户端向服务器端发送http请求,服务器端收到请求后返回一下数据给客户端,客户端接受消息并进行解析. 在Android中发送http请求的方式有两种,第一种是通过HttpURL ...
- Android使用HTTP协议访问网络——HttpClient
套路篇 1.HttpClient是一个接口,因此无法创建它的实例,通常情况下都会创建一个DefaultHttpClient的实例 HttpClient httpClient=new DefaultHt ...
- 第一行代码 10.2使用HTTP协议访问网络 HttpURLConnection代码中的问题
实现HttpURLConnection代码的时候,遇到了问题. 怎样点击途中Send Request按钮,没有任何改变. 最后将MainActivity中的一段代码URL url = new URL( ...
- 使用HTTP协议访问网络
在Android上发送http请求有2种方式,分别由两个类完成,HttpURLConnection和HttpClient. 一.使用HttpURLConnection方式 1.1 建立连接的基本步骤 ...
- android 使用httpclient访问网络
在主活动类中,调用一个线程访问网络(android4.0以上耗时的操作不能放在主线程中): //声明两个Button对象,与一个TextView对象private TextView mTe ...
- Android访问网络(可以正常使用)
以下是MainActiviy.java,有必要的注释,里面用到了handler,以及线程,workThread如何更新mainThread才能够更新的内容. package com.wyl.httpt ...
- Android访问网络
Android中访问网络用的是HttpClient的方式,即Apache提供的一个jar包.安卓中继承了改jar包,所以安卓adt中不需要专门import该jar,直接就可以使用. 以下是MainAc ...
随机推荐
- Python基础-读取excel
import xlrdbook = xlrd.open_workbook('lanxia.xls')sheet = book.sheet_by_name('sheet1')rows = sheet.n ...
- Java企业微信开发_08_素材管理之下载微信临时素材到本地服务器
一.本节要点 1.获取临时素材接口 请求方式:GET(HTTPS) 请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=AC ...
- swiper轮播 swiper整屏轮播
近期坐了几个移动端 整屏轮播的 效果 之前都是自己一个个写,之前听说过swiper插件,没有使用过,今天一尝试,果然,爽 使用方法示例 <div class="swiper-cont ...
- 关于VGG网络的介绍
本博客参考作者链接:https://zhuanlan.zhihu.com/p/41423739 前言: VGG是Oxford的Visual Geometry Group的组提出的(大家应该能看出VGG ...
- VS2008中宽字节和普通字节的使用
由于麻烦,所以并没有使用宽字节,留待以后.
- xml schema 中如何定义类似Map的结构
利用xs:unique关键字.在xs:element里添加unique节点,任意命名,然后用xs:selector来选择需要唯一的域, xs:field 里指定特定的字段. 例如:定义所有Item里的 ...
- nginx实现防盗链配置方法介绍
有些朋友觉得防盗链就是防止图片,其实有很多东西要进行防盗链了,下面我来介绍在nginx中实现防盗链配置方法有对图片防盗链与下载资源等. 防盗链配置 假设网站域名是 www.php100.com. 编辑 ...
- MyEclipse、Eclipse SVN插件的帐号、密码修改
问题描述: Eclipse的SVN插件Subclipse做得很好,在svn操作方面提供了很强大丰富的功能.但到目前为止,该插件对svn用户的概念极为淡薄,不但不能方便地切换用户,而且一旦用户的帐号.密 ...
- LIBCMTD.lib(wincrt0.obj) : error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用
无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用 出现原因: 连接程序在负责连接可执行程序时,选择相应的c/c++运行时启动函数.如果设定了/s ...
- angularJS中自定义指令
学习了angularJS一周,但是大部分时间被自定义指令占用了.博主表示自学互联网好心塞的,发现问题的视觉很狭窄,这比解决问题要更难.这篇文章首先介绍了自定义,然后介绍了在使用自定义指令遇到的问题. ...