Android中的网络连接
如果我们的Android应用需要联网,那么我们就需要一个网络连接专用类。比如我们要访问一个网站,因此我们新建一个名为network的java类。
network类拥有两个方法,getUrlBytes(String)和getUrlString(String)两个方法。
getUrlBytes(String)方法从指定的URL获取原始数据并返回一个字节流数组。
getUrlString(String)方法则将getUrlBytes(String)方法返回的结果转换为String。
以下是该类的代码
public class network{
public byte[] getUrlBytes(String url) throws IOException{
URL url = new URL(url);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
try{
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = connection.getInputStream();
if(connection.getResponseCode()==200){
int bytes =0;
byte[] buffer = new byte[1024];
while((bytes = in.read(buffer) > 0){
out.write(buffer,0,bytes);
}
out.close();
return out.toByteArray();
}
}catch(Exception e){
}finally{
connection.disconnect();
}
}
public String getUrlString(String url) throws IOException{
return new Stirng(getUrlBytes(url));
}
}
在getUrlBytes(String)方法中,首先根据传入的字符串参数创建一个URL对象(https://www.baidu.com),
然后调用openConnection()方法创建一个纸箱要访问URL的连接对象。因为我们连接的是一个http url,所以我们需要将openConnetion()的返回类型进行强制转换,转换成HttpURLConnection对象。之后我们才能调用它的getInputStream()、getResponseCode()等方法。
虽然我们用openConnection()得到了一个连接,但是只有在调用了getInputStream()方法的时候,才会真正的连接到知道的URL地址。(POST请求,则是getOuputStream())。
创建了URL并打开网络连接之后,我们便可循环调用read()方法读取网络数据,直到取完为止。
同时,要连接网络,我们还需要做一件事,就是获得网络的权限
在AndroidManifest.xml里添加如下代码
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="*">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
除了使用URLconnection进行网络连接,我们还可以使用HttpClient类去进行网络连接,代码如下。
HttpClient client = new DefaultHttpClient();//创建一个默认实现的client类
HttpResponse response;
HttpPost httpPost = new HttpPost("http://115.29.184.56:8090/api/user/auth");
//通过URL新建一个post请求
JsonObject object = new JsonObject();
object.addProperty("username","nanguangtailang");
object.addProperty("password","123");
//通过json的格式发送请求数据
StringEntity entity = new StringEntity(object.toString());
entity.setContentEncoding(HTTP.UTF_8);
entity.setContentType("application/json");
httpPost.setEntity(entity);
response = client.execute(httpPost);
int code;
code = response.getStatusLine().getStatusCode();
Log.d(TAG,"" + code);
if (code == 200){
Gson gson = new Gson();
BasicUser user = gson.fromJson(EntityUtils.toString(response.getEntity()),Student.class);
Log.d(TAG, user.toString());
}else {
Log.e(TAG,"网络错误");
}
在我们完成了网络连接类的编写之后,就需要测试我们的网络连接代码,但是我们不能直接在主线程中进行网络连接,因为Android不允许在主线程里进行耗时操作,包括网络连接,这样会报错android.os.NetworkOnMainThreadException,所以我们需要新建一个线程来完成网络连接,我上一篇博客有写过在android中如何使用线程,我们这次使用AsyncTask工具类来完成线程的创建
public class netTask extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... params){
try{
String result = new netWork().getUrlString("http://115.29.184.56:8090/api/user/auth");
}catch(IOException e){
Log.e("netTask","Failed",e);
}
}
}
结果如下:
最后,我们来说下android中的线程与主线程,因为网络连接需要时间,Web服务器可能需要1~2秒的时间来响应访问请求,如果是文件下载,则会消耗更多的时间,考虑到这个因素,所以Android禁止任何主线程的网络连接行为。如果强行进行网络连接,则会抛出android.os.NetworkOnMainThreadException异常。
所有的Android运行都是从主线程开始的,然而主线程并不是像普通线程那样的有预订的执行序列,相反,它是处于一个无线循环的运行状态,等待着用户或系统触发事件的发生。事件触发之后,主线程便负责执行代码,以响应这些事件。
参照《Android编程权威指南》