一、Socket编程
Android网络编程和Java网络编程一样,也可通过Scokcet进行网络通信。
二、HTTP请求
一般有两种方法,通过HttpURLConnection或HttpClient,但HttpClient现在官方不再支持,故选择HttpURLConnection方式。下面为HttpURLConnection方式:
首先编写一个网络处理的类,主要实现post访问和get访问方法,代码如下
public class NetUtils {
public static String post(String url,String content){
HttpURLConnection conn = null;
try {
// 创建一个URL对象
URL mUrl = new URL(url);
// 调用URL的openConnection()方法,获取HttpURLConnection对象
conn = (HttpURLConnection) mUrl.openConnection();
conn.setRequestMethod("POST");// 设置请求方法为post
conn.setReadTimeout(5000);// 设置读取超时为5秒
conn.setConnectTimeout(10000);// 设置连接网络超时为10秒
conn.setDoOutput(true);// 设置此方法,允许向服务器输出内容
// 获得一个输出流,向服务器写数据,默认情况下,系统不允许向服务器输出内容
OutputStream out = conn.getOutputStream();
out.write(content.getBytes());// 获得一个输出流,向服务器写数据
out.flush();
out.close();
int responseCode = conn.getResponseCode();// 调用此方法就不必再使用conn.connect()方法
if(responseCode==200){
InputStream is = conn.getInputStream();
String response = getStringFromInputStream(is);
return response;
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (conn != null) {
conn.disconnect();// 关闭连接
}
}
return "no data";
}
public static String get(String url,String content) {
HttpURLConnection conn = null;
try {
// 利用string url构建URL对象
URL mURL = new URL(url);
conn = (HttpURLConnection) mURL.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
conn.setConnectTimeout(10000);
conn.setDoOutput(true);
OutputStream out = conn.getOutputStream();
out.write(content.getBytes());
out.flush();
out.close();
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
InputStream is = conn.getInputStream();
String response = getStringFromInputStream(is);
return response;
} else {
throw new NetworkErrorException("response status is "+responseCode);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect();
}
}
return null;
}
private static String getStringFromInputStream(InputStream is)
throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
is.close();
String state = os.toString();// 把流中的数据转换成字符串,采用的编码是utf-8(模拟器默认编码)
os.close();
return state;
}
}
Activity主线程里处理
网络请求的操作不要放在主线程里,否则会报错“NetworkOnMainThreadException”。
因为这样会阻塞UI线程,故Google不允许这样做。所以需要单独创建一个线程来处理。在onCreate里代码如下:
Button btnPost = (Button)findViewById(R.id.btn_post);
btnPost.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
new Thread(networkTask).start();
}
});
同时在Activity里添加如下代码:
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bundle data = msg.getData();
String val = data.getString("value");
//Log.i("mylog", "请求结果为-->" + val);
// TODO
// UI界面的更新等相关操作
Toast.makeText(MainActivity.this,val,Toast.LENGTH_LONG).show();
}
};
/**
* 网络操作相关的子线程
*/
Runnable networkTask = new Runnable() {
@Override
public void run() {
// TODO
// 在这里进行 http request.网络请求相关操作
NetUtils netUtils = new NetUtils();
String response = netUtils.get("http://10.0.2.2:80/kjl/Mobie/Index/index","");
Message msg = new Message();
Bundle data = new Bundle();
data.putString("value", "GET请求结果"+response);
msg.setData(data);
handler.sendMessage(msg);
}
};
此外还需注意:
1.在Manifest里添加权限,否则会报“ java.net.SocketException:Permission.denied”
<uses-permission android:name="android.permission.INTERNET" />
2.http服务器在本机时,url不能用localhost或127.0.0.1,因为这样Android会认为其调用的是手机的地址。对此,可用10.0.2.2来代替或者用电脑实际被分配的地址(如:192.168.0.X)
三、URLConnection和HttpURLConnection
URLConnection和HttpURLConnection使用的都是java.net中的类,属于标准的java接口。
HttpURLConnection继承自URLConnection,差别在与HttpURLConnection仅仅针对Http连接。
四、URL类
URL.openConnection()和URL.openStream
String urltext = "";
try {
// 方法一:
URL url = new URL(urltext);
URLConnection conn = url.openConnection();//取得一个新的链接对指定的URL
conn.connect();//本方法不会自动重连
InputStream is = conn.getInputStream();
is.close();//关闭InputStream
// 方法二:
URL url2 = new URL(urltext);
InputStream is2 = url2.openStream();
is2.close();//关闭InputStream
//URL对象也提供取得InputStream的方法。URL.openStream()会打开自动链接,所以不需要运行openConnection
//方法三:本方法同一,但是openConnection返回值直接转为HttpsURLConnection,
//这样可以使用一些Http连接特有的方法,如setRequestMethod
URL url3 = new URL(urltext);
HttpsURLConnection conn3 =(HttpsURLConnection)url.openConnection();
conn3.setRequestMethod("POST");
//允许Input、Output,不使用Cache
conn3.setDoInput(true);
conn3.setDoOutput(true);
conn3.setUseCaches(false);
/*
* setRequestProperty
*/
conn3.setRequestProperty("Connection", "Keep-Alive");
conn3.setRequestProperty("Charset", "UTF-8");
conn3.setRequestProperty("Content-type", "multipart/form-data;boundary=*****");
//在与服务器连接之前,设置一些网络参数
conn3.setConnectTimeout(10000);
conn3.connect();
// 与服务器交互:向服务器端写数据,这里可以上传文件等多个操作
OutputStream outStream = conn3.getOutputStream();
ObjectOutputStream objOutput = new ObjectOutputStream(outStream);
objOutput.writeObject(new String("this is a string…"));
objOutput.flush();
// 处理数据, 取得响应内容
InputStream is3 = conn.getInputStream();
is3.close();//关闭InputStream
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
五、使用URL访问网络资源
通过URL.openStream来获取服务器端的图片
在主Activity的layout里添加ImageView控件,在主Activity里通过线程来获取
ImageView show;
Bitmap bitmap;
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==0x123){
show.setImageBitmap(bitmap);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
show = (ImageView)findViewById(R.id.show);
new Thread(){
@Override
public void run() {
try{
URL url = new URL("https://www.baidu.com/img/baidu_jgylogo3.gif");
InputStream is = url.openStream();
bitmap = BitmapFactory.decodeStream(is);
handler.sendEmptyMessage(0x123);
is.close();
}catch (Exception e){
e.printStackTrace();
}
}
}.start();
}
Im
六、通过HttpURLConnection上传文件,同时带参数
public static String form(String serverUrl,List<Map<String,String>> generalField
,List<Map<String,String>> fileField){
// 每个post参数之间的分隔。随意设定,只要不会和其他的字符串重复即可。
String BOUNDARY = "----------HV2ymHFg03ehbqgZCaKO6jyH";
// 向服务器发送post请求
String strResponse = "";
try {
URL url = null;
url = new URL(serverUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 发送POST请求必须设置如下两行
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Charset", "UTF-8");
connection.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + BOUNDARY);
// 头
String boundary = BOUNDARY;
// 传输内容
StringBuffer contentBody = new StringBuffer("--" + BOUNDARY);
// 尾
String endBoundary = "\r\n--" + boundary + "--\r\n";
OutputStream out = connection.getOutputStream();
// 1. 处理文字形式的POST请求
for (Map<String,String> map : generalField){
contentBody.append("\r\n")
.append("Content-Disposition: form-data; name=\"")
.append(map.get("name") + "\"")
.append("\r\n")
.append("\r\n")
.append(map.get("value"))
.append("\r\n")
.append("--")
.append(boundary);
}
String boundaryMessage1 = contentBody.toString();
out.write(boundaryMessage1.getBytes("utf-8"));
// 2. 处理文件上传
for (Map<String,String> map : fileField){
contentBody = new StringBuffer();
contentBody.append("\r\n")
.append("Content-Disposition:form-data; name=\"")
.append(map.get("name") + "\"; ") // form中field的名称
.append("filename=\"")
.append(map.get("value") + "\"") // 上传文件的文件名,包括目录
.append("\r\n")
.append("Content-Type:application/octet-stream")
.append("\r\n\r\n");
String boundaryMessage2 = contentBody.toString();
out.write(boundaryMessage2.getBytes("utf-8"));
// 开始真正向服务器写文件
File file = new File(map.get("value"));
DataInputStream dis = new DataInputStream(new FileInputStream(file));
int bytes = 0;
byte[] bufferOut = new byte[(int) file.length()];
bytes = dis.read(bufferOut);
out.write(bufferOut, 0, bytes);
dis.close();
contentBody.append(BOUNDARY);
String boundaryMessage = contentBody.toString();
out.write(boundaryMessage.getBytes("utf-8"));
// System.out.println(boundaryMessage);
}
out.write("------------HV2ymHFg03ehbqgZCaKO6jyH--\r\n"
.getBytes("UTF-8"));
// 3. 写结尾
out.write(endBoundary.getBytes("utf-8"));
out.flush();
out.close();
// 4. 从服务器获得回答的内容
String strLine = "";
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while ((strLine = reader.readLine()) != null){
strResponse += strLine + "\n";
}
System.out.print(strResponse);
} catch (Exception e) {
e.printStackTrace();
}
return strResponse;
}
publi