废话不多说啦,我们直接学习Android中最常使用的网络技术。
在请求网络之前,我们需要在AndroidManifest中声明访问网络的权限:
uses-permission android:name="android.permission.INTERNET"/>
-HttpURLConnection
在Android上发送HTTP请求的方式一般有两种,HttpURLConnection和HttpClient,但是老师说HttpClient已经被Google弃用了,而HttpURLConnection能够更好的处理网页数据,并且可以减少耗电量。
- 获得HttpURLConnection的实例
在获取实例之前,我们需要一个URL对象,将目标的网络地址传入,然后调用Url的openConnection()方法。
URL url=new URL("http://www.baidu.com");
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
至于问什么要调用url的openConnection()方法,Android源码说是这个方法通过url返回一个指向资源的连接,所以还要进行强制转型;
还要设置HTTP请求所使用的方式,在学习Html时,学到了GET和POST两种方式,其中GET是从服务器端获取数据,POST是从服务器端发送数据,而且GET方式中表单的附加信息会出现在URl上,相比于POST会不安全。
connection.setConnectTimeout(8000);//设置连接超时时间
connection.setReadTimeout(8000); //设置读取超时时间
connection.connect();//开启http连接
下面就是请求baidu数据的实例:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
//请求网络数据,需要申请权限
data = requestData(url);
}
}).start();
}
private String requestData(String url_String) { //第一种方法
try {
String result=null;
URL url=new URL(url_String);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");//设置http请求所使用的方法
connection.setConnectTimeout(8000);//设置连接超时时间
connection.setReadTimeout(8000); //设置读取超时时间
connection.connect();//开启http连接
int response= connection.getResponseCode();//获取响应状态嘛
if(response== HttpURLConnection.HTTP_OK) {
InputStream inputStream = connection.getInputStream();//获取服务器返回的输入流
Reader reader = new InputStreamReader(inputStream, "utf-8");
char[] buffer = new char[1024];
reader.read(buffer);//将reader读到的数据放到char数组中
result=new String(buffer);
}
else if(response== HttpURLConnection.HTTP_NOT_FOUND){
result="304 NOT FOUND!";
}
else{
result="Error!!";
}
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this,"非法网址",Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
finally {
connection.disconnect();//关闭http连接
}
return null;
}
因为获取网络数据是一个同步操作,所以我们需要在一个子线程中去完成耗时操作;
除了使用线程,Android还提供一个很好的工具类——AsyncTask,但是它的实现原理还是基于异步消息处理机制。AsyncTask是一个抽象类,所以使用它必须用一个子类去继承,其中必须要重写的三个方法:onPreExecute() ;doInBackground(String[] params);
onPostExecute(String s);
分别对应三个不同的操作,第一个是在子线程之前,即在主线程中的操作;第二个是全部在子线程中执行;第三个是在子线程之后,进行的相关操作;
所以,使用AsyncTask会使我们方便很多,不需要在去考虑异步消息处理机制了。
-解析XML格式数据
通过上面的requestData()方法,我们得到了xml数据,但是只有将数据解析之后才能得到我们想要的数据。
- SAX解析方式
private void parseXML_WithSAX(String xmlData) { //将SAX方式解析XML
try {
//先创建工程,在创建一个解析器,然后再有一个xml读取器,固定的步骤
SAXParserFactory factory=SAXParserFactory.newInstance();
XMLReader xmlReader=factory.newSAXParser().getXMLReader();
SAX_Handler sax_handler=new SAX_Handler();
//将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(sax_handler);
//开始执行解析,
xmlReader.parse(new InputSource(new StringReader(xmlData)));
} catch (Exception e) {
e.printStackTrace();
}
}
String xmlData就是requestData()所返回的xml数据。
- Pull解析方式
Pull方法相对与SAX方法有点复杂。
private void requestXML_Pull(String data) { //用Pull方式解析XML
try {
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser=factory.newPullParser();
xmlPullParser.setInput(new StringReader(data));
int eventType=xmlPullParser.getEventType();
String id="";
String item="";
while(eventType!=XmlPullParser.END_DOCUMENT){
String nodename=xmlPullParser.getName();
switch (eventType){
//开始解析某个节点
case XmlPullParser.START_TAG:
if("id".equals(nodename)){
id=xmlPullParser.nextText();
}else if("item".equals(nodename)){
item=xmlPullParser.nextText();
}
break;
case XmlPullParser.END_TAG:
if("app".equals(nodename)){
Log.i("TAG","id:"+id);
Log.i("TAG","item:"+item);
}
break;
default:break;
}
eventType=xmlPullParser.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}
setInput()方法是将服务器返回的XML数据传入,并开始解析。通过getEventType()可以得到当前的解析事件,通过while循环进行不断的解析,getItem()方法是得到当前结点的名字,若结点不是结束节点,next()获取下一个节点;若节点满足相应的条件,则调用nextText()方法获取节点中具体的内容。
- 解析JSON格式数据
比起XML,JSON主要优势是在于它的体积更小,在网络上传输的时候可以更省流量。
解析JSON的方法有很多,可以使用官方提供的JSONObject,也可以使用Google的GSON。
private void requestJSON(String xml_json) {//测试JSON
try {
result="";
JSONArray jsonArray=new JSONArray(xml_json);
for(int i=0;i<jsonArray.length();i++){
JSONObject jsonobject=jsonArray.getJSONObject(i);
String id=jsonobject.getString("id");
String name=jsonobject.getString("name");
String version=jsonobject.getString("version");
result = "id:"+id+",name:"+name+",version:"+version+result;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
这里是解析JSON数据中的id和version,通过requestData()从服务器获得返回的JSON数据,然后数据传入一个JSON数组中,通过JSONObject对象的getString()方法,返回所对应的数据。
GSON解析JSON数据
Google提供了一个非常简单的工具,它可以将一段JSON格式的字符串自动映射成一个对象,从而不需要我们在去解析。
使用GSONFormat工具(大家可以自行百度),将我们的JSON数据可以自动映射成一个对象,通过对象的方法我们可以得到JSON中的任何数据,非常方便。
Gson gson=new Gson();
JSon_Bean jSon_bean=gson.fromJson(result,JSon_Bean.class);
JSON_Bean是json数据所影射的类,通过fromJson()方法可以获得对象,从而可以操作JSON中的所有数据。