如今,移动端APP渗透到各行各业,数量难以计数,几乎所有应用都会使用到网络,掌握Android网络编程是APP开发是核心技术,必备技术。这是因为移动设备的计算能力存储能力都是有限的。因此移动设备依赖网络计算、存储就成为了主要的方式,重要程度就不言而喻了。
Android完全支持JDK本身的TCP、UDP网络通信的API,也就是我们在JAVASE阶段讲解的网络编程,也叫Socket编程,Android也支持基于HTTP协议的URLConnection,并内置Apache HttpClient API来简化HTTP的操作。
当前最常用的网络编程技术,包括: URLConnection、Apache HttpClient、WebService、 Volley、android- async-http、WebView。
HTTP是Hyper Text Transfer Protocol(超文本传输协议),它的发展史是万维网协会(World Wide Web Consortium)和Internet工作小组IETF(Internet Engineering Task Force)合作的结果,最终发布了一系列法RFC/RFC1945定义了HTTP/1.0版本。其中最著名的就是RFC 2616。RFC 2616定义了今天最普遍使用的一个版本——HTTP 1.1。
如果在以上过程中的某-步出现错误,那么产生错误的信息将返回到客户端,有显示屏输出。对于用户来说,这些过程是由HTTP自己完成的,用户只要用鼠标点击,等待信息显示就可以了。
添加权限
判断是否有网络连接
public boolean isNetworkConnected(Context context){
if (context!=null){
ConnectivityManager connectivityManager= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
if (networkInfo!=null){
return networkInfo.isAvailable();
}
}
return false;
}
public boolean isWifiConnected(Context context){
if (context!=null){
ConnectivityManager connectivityManager= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wiFiNetworkInfo=connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (wiFiNetworkInfo!=null){
return wiFiNetworkInfo.isAvailable();
}
}
return false;
}
判断网络连接的类型信息
public static int getConnectedType(Context context){
if (context!=null){
ConnectivityManager connectivityManager= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
if (networkInfo!=null&&networkInfo.isAvailable()){
return networkInfo.getType();
}
}
return -1;
}
URL:统一的资源定位符。Web上的每个资源都有唯一的地址,采用的就是URL格式
协议://服务器:端口号/路径/资源
添加权限
访问网络的操作必须在工作线程中操作
public void showNetImageClick(View view){
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("http://g.hiphotos.com/image/pic/item/dbb44aed2e738bd4f58b4e30a38b87d6277ff90d.jpg");
InputStream inputStream=url.openStream();
Bitmap bitmap=BitmapFactory.decodeStream(inputStream);
Message msg=handler.obtainMessage(LOAD_SECCESS,bitmap);
handler.sendMessage(msg);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
设置handler
private static class MyHandler extends Handler{
private final WeakReference weakReference;
public MyHandler(Main2Activity main2Activity){
weakReference=new WeakReference(main2Activity);
}
@Override
public void handleMessage(Message msg) {
Main2Activity main2Activity=weakReference.get();
if (main2Activity!=null){
switch (msg.what){
case LOAD_SECCESS:
main2Activity.imageView.setImageBitmap((Bitmap) msg.obj);
break;
}
}
}
}
HTTP通信中的POST和GET请求方式不同。GET把参数放在URL字符串的后面,传递给服务器。而POST方法的参数是放在HTTP请求中。因此,在编程之前,应当首先明确使用的请求方法,然后再根据所使用的方法选择相应的编程方式。
HttpURLConnection是继承于URLConnection类,二者都是抽象类。其对象主要通过URL的openConnection方法获得。
设置参数
urlConn.setDoOutput(true);//post情况下需要设置DoOutput为true,默认为false
urlConn.setDoInput(true);//设置是否从HttpURLConnection读入,默认情况下是true
urlConn.setRequestMethod(“POST”);
urlConn.setUseCache(false);//设置是否用缓存,post请求不能使用缓存
设置content-type
urlConn.setRequestPropery("content-type","application/x-www-form-urlencoded");
urlConn.setConnectTimeout(30000);//设置连接主机超时
urlConn.setReadTimeout(30000);//设置读取超时
模拟登陆客户端代码
package com.example.httpurlconnection;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
public class Main3Activity extends AppCompatActivity {
private static final int LOAD_SECCESS = 200;
private static final int LOAD_ERROR = 400;
private final Main3Activity.MyHandler handler=new Main3Activity.MyHandler(this);
private TextView textView_info;
private EditText editText_username,editText_password;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
textView_info=findViewById(R.id.info);
editText_username=findViewById(R.id.editText_username);
editText_password=findViewById(R.id.editText_pwd);
}
private static class MyHandler extends Handler {
private final WeakReference weakReference;
public MyHandler(Main3Activity main3Activity){
weakReference=new WeakReference(main3Activity);
}
@Override
public void handleMessage(Message msg) {
Main3Activity main3Activity=weakReference.get();
if (main3Activity!=null){
switch (msg.what){
case LOAD_SECCESS:
String json= (String) msg.obj;
main3Activity.jsonToObject(json);
break;
case LOAD_ERROR:
main3Activity.textView_info.setText("登录失败,请检查用户名或者密码是否正确!");
break;
}
}
}
}
//解析JSON为对象
public void jsonToObject(String json){
Gson gson=new Gson();
JsonObject object=gson.fromJson(json,JsonObject.class);
textView_info.setText(object.toString());
}
//登录功能
public void loginClick(View view){
final String username=editText_username.getText().toString();
if (TextUtils.isEmpty(username)){
Toast.makeText(this, "用户名不能为空!!!", Toast.LENGTH_SHORT).show();
return;
}
final String password=editText_password.getText().toString();
if (TextUtils.isEmpty(password)){
Toast.makeText(this, "密码不能为空!!!", Toast.LENGTH_SHORT).show();
return;
}
//启动登录工作线程
new Thread(new Runnable() {
@Override
public void run() {
String path="http://10.0.2.2:8080/Android_NetServer/LoginServlet";
try {
URL url=new URL(path);
//打开HTTP连接
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setConnectTimeout(1000*30);//连接超时
conn.setReadTimeout(1000*30);//读取超时
conn.setUseCaches(false);
conn.setRequestProperty("content-type","application/x-www-form-urlencoded");
//对服务器端读取或写入数据(使用输入输出流)
//获取连接的输出流
DataOutputStream outputStream=new DataOutputStream(conn.getOutputStream());
outputStream.writeBytes("username="+ URLEncoder.encode("hello","UTF-8"));
outputStream.writeBytes("&password="+URLEncoder.encode("123"+"UTF-8"));
outputStream.flush();
outputStream.close();
//从服务器获取响应数据
BufferedReader br=new BufferedReader(new InputStreamReader(conn.getInputStream()));
String result=br.readLine();
System.out.println("result="+result);
br.close();
conn.disconnect();
Message msg=handler.obtainMessage(LOAD_SECCESS,result);
handler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
handler.sendEmptyMessage(LOAD_ERROR);
}
}
}).start();
}
}