使用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
下一篇: vue webpack打包优化操作技巧
推荐阅读
-
php使用socket调用http和smtp协议实例小结
-
如何解决Ajax访问不断变化的session的值不一致以及HTTP协议中的GET、POST的区别
-
无法访问,您可能没有权限使用网络资源的解决方法
-
Html5
-
Android通过HTTP协议实现断点续传下载实例
-
Linux下SVN服务器同时支持Apache的http和svnserve独立服务器两种模式且使用相同的访问权限账号
-
Android 使用Picasso加载网络图片等比例缩放
-
Android网络请求库android-async-http介绍
-
Linux网络编程使用多进程实现服务器并发访问
-
Android下基于Iptables的一种app网络访问控制方案(一)