一、通过HTTP访问网络
在Android中,针对HTTP进行网络通信的方法主要有两种:一种是使用HttpURLConnection实现;另一种是使用HttpClient实现。
1.使用HttpURLConnection访问网络
HttpURLConnection类位于java.net包中,用于发送HTTP请求和获取HTTP响应。由于该类是抽象类,不能直接实例化对象,则需要使用URL的openConnection()方法来获得。
eg.
URL url = new URL("http://www.baidu.com");
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
说明:通过openConnection()方法创建的HttpURLConnection对象,并没有真正执行连接操作,只是创建了一个新的实例,在进行链接前,还可以设置一些属性。例如,连接超时的时间和请求方式等。
创建了HttpURLConnection对象后,就可以使用该对象发送HTTP请求了。HTTP请求通常分为GET请求和POST请求两种。
1)发送GET请求
使用HttpURLConnection对象发送请求时,默认发送的就是GET请求。因此,发送GET请求比较简单,只需要在指定连接地址时,先将要传递的参数通过“?参数名=参数值”进行传递(多个参数间使用英文半角的逗号分隔。例如,?user=wgh,email=wgh717@shouhu.com),然后获取流中的数据,并关闭连接即可。
eg.
public void send(){
String target="";
target="http://192.168.1.66:8081/blog/index.jsp?content="+base64(content.getText().toString().trim());
URL url;
try{
url=new URL(target);
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
InputStreamReader in = new InputStreamReader(urlConn.getInputStream());
BufferedReader buffer = new BufferedReader(in);
String inputLine=null;
while((inputLine=buffer.readLien())!=null){
result+=inputLine+"\n";
}
in.close();
urlConn.disconnect();
}catch(MalformedURLExceotion e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}
}
在应用GET方法传递中文的参数时,会产生乱码,这时可以进行Base64编码来解决乱码问题,为此,需要编写一个base64()方法,对要进行传递的参数进行Base64编码。
public String base64(String content){
try{
content = Base64.encodeToString(content.getBytes("utf-8"),Base64.DEFAULT);
content=URLEcoder.encode(content);
}catch(UnsupportedEncodingException e){
e.printStackTrace
}
return content;
}
要解决应用GET方法传递中文参数时产生乱码的问题,也可以使用Java提供的URLEncoder类来实现。
2)发送POST请求
由于采用GET方式发送请求只适合发送大小在1024个字节以内的数据,所以当要发送的数据较大时,就需要使用POST方式来发送请求。在Android中,使用HttpURLConnection类发送请求时,默认采用的是GET请求,如果要发送POST请求,需要通过其setRequestMethod()方法进行指定。
eg.
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
urlConn.setRequestMethode("POST");
发送POST请求要比发送GET请求复杂一些,它经常需要通过HttpURLConneciton类及其父类URLConneciton提供的方法设置相关内容。
发送POST请求常用的方法:
setDoInput(boolean new Value)
setDoOutput(boolean new Value)
setUseCaches(boolean new Value)
setInstanceFollowRedirects(boolean followRedirects)
setRequestProperty(String field,String new Value)
2.使用HttpClient访问网络
HttpClient实际上是对Java提供的访问网络的方法进行了封装。HttpURLConnection类中的输入/输出流操作,在HttpClient中被封装成了HttpGet、HttpPost和HttpResponse类,这样,就简化了操作。其中,HttpGet类代表发送GET请求;HttpPost类代表发送POST请求;HttpResponse类代表处理响应的对象。
1)发送GET请求
①创建HttpClient对象
②创建HttpGet对象
③如果需要发送请求参数,可以直接将要发送的参数连接到URL地址中,也可以调用HttpGet的setParams()方法来添加请求参数。
④调用HttpClient对象的execute()方法发送请求。执行该方法将返回一个HttpResponse对象。
⑤调用HttpResponse的getEntity()方法,可获得包含服务器响应内容的HttpEntity对象,通过该对象可以获取服务器的相应内容。
eg.
public void send(){
String target="http://192.168.1.66:8081/blog/deal_httpclient.jsp?param=get";
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpRequest = new HttpGet(target);
HttpResponse httpResponse;
try{
httpResponse = httpClient.execute(httpRequest);
if(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
result = EntityUtils.toString(httpResponse.getEntity());
}else{
result="请求失败!";
}
}catch(ClientProtocolException e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}
}
2)发送POST请求
①创建HttpClient对象
②创建HttpPost对象
③如果需要发送请求参数,可以调用HttpPost的setParams()方法来添加请求参数,也可以调用setEntity(0方法来设置请求参数。
④调用HttpClient对象的execute()方法发送请求。执行该方法将返回一个HttpResponse对象。
⑤调用HttpResponse的getEntity()方法,可获得包含服务器响应内容的HttpEntity对象,通过该对象可以获取服务器的响应内容。
eg.
public void send(){
String target="http://192.168.1.66:8081/blog/deal_httpclient.jsp";
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpclient = new HttpPost(target);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("param","post");
params.add(new BasicNameValuePair("nickname","nickename");
params.add(new BasicNameValuePair("content","content");
try{
httpRequest.setEntity(new UrlEncodedFormEntity(params,"utf-8"));
HttpResponse httpResponse = httpClient.execute(httpRequest);
if(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
result+=EntityUtils.toString(httpResponse.getEntity());
}else{rusult="请求失败!";}
}catch(UnsupportedEncodingException e1){e1.printStackTrace();}
catch(ClientProtocolException e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}
}
不过由于HttpClient存在API数量过多、扩展困难等缺点,Android团队越来越不建议我们使用这种方式,终于在Android6.0系统中,HttpClient的功能被完全移除了,标志着此功能被正式弃用,现在官方建议使用HttpURLConnection的用法。
3.使用OkHttp
OkHttp是由鼎鼎大名的Square公司开发的,这个公司在开源事业上面贡献良多,除了OkHttp之外,还开发了像Picasso、Retrofit等著名的开源项目。
在使用OkHttp之前,我们需要现在项目中添加OkHttp库的依赖。编辑app/build.gradle文件,在dependencies闭包中添加如下内容:
dependencies{
compile fileTree(dir:'libs',include:['*.jar'])
compile 'com.android.support:appcompat-v7:24.2.1'
testCompile 'junit:junit:4.12'
compile 'com.squareup.okhttp3:okhttp;3.4.1‘
}
添加上述依赖会自动下载两个库,一个是OkHttp库,一个是Okio库,后者是前者的通信基础。
OkHttp具体用法:
①创建一个OkHttpClient的实例:OkHttpClient client = new OkHttpClient();
②创建一个Request对象:Request request = new Request.Builder().build();
eg.
Request request=new Request.Builder().url("http://www.bbaidu.com").build();
③调用OkHttpClient的newCall()方法来创建一个Call对象,并调用它的execute()方法来发送请求并获取服务器返回的数据:
Response response = client.newCall(request).execute();
其中Response对象就是服务器返回的数据了,可以使用如下写法得到返回的具体内容:
String responseData = response.body().string();
如果是发起一条POST请求,需要先构建出一个RequestBody对象来存放待提交的参数,如下所示:
RequestBody requestBody = new FormBody.Builder().add("username","admin").add("password","123456").build();
然后在Request.Builder中调用一下post()方法,并将RequestBody对象传入:
Request request = new Request.Builder().url("http://www.baidu.com").post(requestBody).build();
接下来的操作就和GET请求一样了,调用execute()方法来发送请求并获取服务器返回的数据即可。
网络编程最佳实践
通常情况下我们应该将这些通用的网络操作提取到一个公共的类里,并提供一个静态方法,当想要发起网络请求的时候,只需简单调用一下这个方法即可。
eg.
public class HttpUtil{
public static String sendHttpRequest(String address){
HttpURLConnection connection=null;
try{
URL url = new URL(address);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.setDoInput(true);
connection.setDooutput(true);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while((line=reader.readLine())!=null){
response.append(line);
}
return response.toString();
}catch(Exception e){
e.printStackTrace();
return e.getMessage();
}
finally{
if(connection!=null){connection.disconnect();}
}
}
}
发起请求时如下:
String address="http://www.baidu.com";
String response = HttpUtil.sendHttpRequest(address);
优化如下:
首先定义一个接口,命名为 HttpCallbackListener,代码如下
public interface HttpCallbackListener{
void onFinish(String response);
void onError(Exception e);
}
我们在接口中定义了两个方法,onFinish()方法表示当服务器成功响应我们请求的时候调用,onError()表示当进行网络操作出现错误的时候调用。这两个方法都带有参数,onFinish()方法中的参数代表着服务器返回的数据,而onError()方法中的参数记录着错误的详细信息。
public class HttpUtil{
public static void sendHttpRequest(final String address,final HttpCallbackListener listener){
new Thread(new Runnable(){
public void run(){
HttpURLConnection connection=null;
try{
URL url = new URL(address);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.setDoInput(true);
connection.setDoOutput(true);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while((line=reader.readLine())!=null){
response.append(line);
}
if(listener!=null){
listener.onFinish(response.toString());
}
}catch(Exception e){
if(listener!=null){
listener.onError(e);
}
}finally{
if(connection!=null){
connection.disconnect();
}
}
}
}).start();
}
}
我们首先给sendHttpRequest()方法添加一个HttpCallbackListener参数,并在方法的内部开启了一个子线程,然后在子线程里去执行具体的网络操作。注意,子线程中时无法通过return语句来返回数据的,因此这里我们将服务器响应的数据传入了HttpCallbackListener的onFinish()方法中,如果出现了异常就将异常原因传入到onError()方法中。
调用上述网络请求方法如下:
HttpUtil.sendHttpRequest(address,new HttpCallbackListener(){
public void onFinish(String response){
//在这里根据返回的内容执行具体的逻辑操作
}
public void onError(Exception e){
//在这里对异常情况进行处理
}
});
使用OkHttp构建网络请求类如下:
public class 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);
}
}
我们在调用sendOkHttpRequest()方法时如下:
HttpUtil。sendOkHttpRequest(“http://www.baidu.com”,new okhttp3.Callback(){
public void onResponse(Call call,Response response) throws IOException{
//得到服务器返回的具体内容
String responseData = response.body().string();
}
public voidd onFailure(Call call,IOException e){
//在这里对异常情况进行处理
}
});
另外需要注意的时,不管是使用HttpURLConnection还是OkHttp,最终的回调接口都还是在子线程中运行的,因此我们不可以在这里执行任何的UI操作,除非借助runOnUiThread()方法来进行线程转换。
二、使用Webview显示网页
1.使用WebView组件浏览网页
2.使用WebView加载HTML代码
3.让WebView支持JavaScript