首先要知道的是在Android P中要求默认使用加密连接,否则会报错,通过http协议访问网络也是这样,在以前的版本中不受限。
所以要怎么做呢:现在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"
...
<activity android:name=".MainActivity">
....
</activity>
</application>
或直接在AndroidManifest.xml:
<application
...
android:usesCleartextTraffic="true"
...
<activity android:name=".MainActivity">
....
</activity>
</application>
我一开始因为这个问题总是不能给服务器发送请求,后来看了一篇博客后才了解的,这个地址是:
https://blog.csdn.net/gengkui9897/article/details/82863966
同样在AndroidManifest.xml申明权限:
<uses-permission android:name="android.permission.INTERNET"/>
WebView控件的简单用法
WebView控件可以实现在程序中展示网页,简单用法 getSetting().setJavaScriptEnabled()方法设置支持javascript脚本,同样通过getSetting()来设置其他属性;setWebView()方法作用是打开网页中的链接时仍在WebView中;loadUrl(String)方法进入相应的网页;其实WebView也是给服务器发送一个http请求,获取服务器传回来的html代码,解析,知识封装了起来。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.first_webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("http://www.bilibili.com");
}
}
使用HTTP协议访问网络
使用HttpURLConnection
先创建URL对象,通过url.openConnection()方法获取HttpURLConnection对象;然后调用HttpURLConnection对象的setReuqestMethod(“GET”)设置请求使用的方法(或Post),然后就是其他的设置如setConnectTimeout(int),setReadTimeout(int)设置连接超时,获取超时毫秒数,之后通过getInputStream()获得输入流,再创建流缓冲对象读取数据。发送网络请求是很耗时间的,所以要开一个子线程来进行操作,不过不能在子线程中执行UI操作,必须回到主线程才行即调用
public class MainActivity extends AppCompatActivity {
private Button sendrequest;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
sendrequest = (Button) findViewById(R.id.sendrequest_button);
sendrequest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//sendhttprequest();
sendOkHttprequest();
}
});
}
private void sendhttprequest(){
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("http://www.youku.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//获取数据
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
//发送数据
/*connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=fds&password=123");*/
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder result = new StringBuilder();
String line;
while((line=reader.readLine())!=null){
result.append(line);
}
showresponse(result.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
//回到主线程执行UI操作
private void showresponse(final String result){
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(result);
}
});
}
}
使用开源库OkHttp
OkHttp比起原生的HttpURLConnection不错。首先在build.gradle中添加依赖,之后会自动下载相应库。
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
怎么用,首先先创建一个OkHttpClient对象;如果要发送http请求,创建Request对象通过
new Request.Builder.build(),可以在中间添加new Request.Builder.url(“String”).build()如.url指定地址等,然后调用OkHttpClient对象的newCall(request)方法创建Call对象,在调用Call对象的execute()方法获取Response对象为返回的数据;对Response对象.body.string()方法转为String类型;如果要发送数据则创建一个RequestBody对象,再在Request.Builder中调用post(requestbody)方法;
private void sendOkHttprequest(){
new Thread(new Runnable() {
@Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
//获取数据
Request request = new Request.Builder()
//.url("http://10.252.215.101/get_data.xml")
.url("http://10.252.215.101/get_data.json")
.build();
//发送数据
/**
* RequestBody requestbody = new FormBody.Builder()
* .add("username","abc")
* .add("password","123")
* .build();
* Request request = new Request.Builder()
* .url("http://www.bilibili.com")
* .post(requestbody)
* .build();
*/
Response response = client.newCall(request).execute();
String result = response.body().string();
//showresponse(result);
//parsexmlwithpull(result); 通过pull方式解析xml数据
//parsexmlwithsax(result); 通过sax方式解析xml数据
//parsejsonwithjsonobject(result); 通过JSONObject方式解析json数据
parsejsonwithgson(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
解析XML格式数据
在网络上传输数据常用格式为xml,json;首先先来解析xml格式数据。首先获取一段xml数据,我是通过向自己的服务器发送http请求来获取一段xml数据,内容如下(get_data.xml):
<apps>
<app>
<id>1</id>
<name>blue</name>
</app>
<app>
<id>2</id>
<name>red</name>
</app>
<app>
<id>2</id>
<name>green</name>
</app>
</apps>
Pull方式解析:
先创建xmlPullParserFactory对象,再通过其创建XmlPullParser对象,调用XmlPullParser的setInput(new StringReader(String xml))方法将数据输入进去后可以开始解析;通过while循环解析数据并输出
private void parsexmlwithpull(String xmlresult){
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlresult));
int eventype = xmlPullParser.getEventType();
String id = null;
String name = null;
while(eventype!=XmlPullParser.END_DOCUMENT){
String nodename = xmlPullParser.getName();
switch(eventype){
case XmlPullParser.START_TAG:
if(nodename.equals("id")){
id = xmlPullParser.nextText();
}else if(nodename.equals("name")){
name = xmlPullParser.nextText();
}
break;
case XmlPullParser.END_TAG:
if(nodename.equals("app")){
Log.d("MainActivity","id="+id);
Log.d("MainActivity","name="+name);
}
break;
default:
break;
}
eventype = xmlPullParser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
SAX方式解析:
首先需创建一个类继承DefaultHandler,重写其中的五个方法,就是相关的解析方式,startDocument()开始解析xml时调用;startElement()开始解析某个节点时调用;characters()获取内容时调用,会被调用多次,换行符也会被解析出来;endElement()完成解析某个节点时调用;endDocument()完成解析xml时调用。
public class ContentHandler extends DefaultHandler {
private String nodename;
private StringBuilder id;
private StringBuilder name;
@Override
public void startDocument() throws SAXException {
super.startDocument();
id = new StringBuilder();
name = new StringBuilder();
}
//解析xml节点时调用
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
nodename = localName;
}
//获取内容调用
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
if(nodename.equals("id")){
id.append(ch,start,length);
}else if(nodename.equals("name")){
name.append(ch,start,length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if(localName.equals("app")){
Log.d("MainActivity","id="+id);
Log.d("MainActivity","name="+name);
id.setLength(0);
name.setLength(0);
}
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
}
主函数中使用,先创建SAXParserFactory对象,通过其获取XMLReader对象,调用XMLReader对象的setContentHandler()方法,参数是DefaultHandler子类的对象(上面那个解析xml数据的类),再调用parse()方法解析数据:
private void parsexmlwithsax(String xmlresult){
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
xmlReader.setContentHandler(new ContentHandler());
xmlReader.parse(new InputSource(new StringReader(xmlresult)));
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
解析JSON格式数据
相比于xml格式数据,json格式的数据体积更小,网络上传输更省流量;但语义性较差,不如xml直观。同样通过向自己的服务器发送http请求来获取一段json数据,内容如下(get_data.json):
[{"id":"4","name":"ren mushroom"},
{"id":"5","name":"blue mushroom"},
{"id":"6","name":"yellow mushroom"}]
JSONOBJECT方式解析
这是官方提供的,开源库的GSON方式也很好用。先创建JSONArray对象,把json数据传入;循环遍历这个对象,每次取出一个元素是JSONObject对象,在通过JSONObject对象的get…()方法取出数据:
private void parsejsonwithjsonobject(String jsonresult){
try {
JSONArray jsonArray = new JSONArray(jsonresult);
for(int i=0;i<jsonArray.length();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String id = jsonObject.getString("id");
String name = jsonObject.getString("name");
Log.d("MainActivity","id="+id);
Log.d("MainActivity","name="+name);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
GSON方式解析
因为是开源库中的,先在build.gradle中添加依赖来自动下载相应库:
implementation 'com.google.code.gson:gson:2.7'
GSON可以自动将一段json字符串映射成一个类对象,不需要去写代码解析,就像以下一段json数据:
[{"id":"4","name":"ren mushroom"},
可以创建一个类Pokemon,有id和name两个属性,就可以直接通过以下将json数据转化为类对象(jsonresult为字符串类型):
GSON gson = new GSON();
Pokemon pokemon = gson.fromJson(jsonresult,Pokemon.class)
如果是一段json数组:
[{"id":"4","name":"ren mushroom"},
{"id":"5","name":"blue mushroom"},
{"id":"6","name":"yellow mushroom"}]
需要TypeToken来转化为List:
List<Pokemon> monsters = gson.fromJson(jsonresult,new TypeToken<List<Pokemon>>(){}.getType());
最后直接调用类方法获取相应数据:
private void parsejsonwithgson(String jsonresult){
Gson gson = new Gson();
List<Pokemon> monsters = gson.fromJson(jsonresult,new TypeToken<List<Pokemon>>(){}.getType());
for(Pokemon pokemon : monsters){
Log.d("MainActivity","id="+pokemon.getId());
Log.d("MainActivity","name="+pokemon.getName());
}
}