1 從服務(wù)器獲取內(nèi)容
從服務(wù)器獲取內(nèi)容都是以流的方式獲取的,可以獲取字符串,文件,圖片等等,所有的東西都是通過文件流獲取的。
下面是一個從服務(wù)端獲取內(nèi)容的完整步驟
網(wǎng)絡(luò)請求首先需要先開啟權(quán)限
<uses-permission android:name="android.permission.INTERNET" />
進行網(wǎng)絡(luò)請求
//網(wǎng)絡(luò)請求是耗時操作,必須要放在子線程中進行
new Thread(new Runnable() {
@Override
public void run() {
try {
// 0 網(wǎng)絡(luò)請求時需要捕獲一些異常
// 1 創(chuàng)建一個URl對象,傳入url地址
URL url=new URL(sourceUrl);
// 2 開啟HttpUrlConnection
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
// 3 設(shè)置請求方式,必須要大寫
connection.setRequestMethod("GET");
// 4 設(shè)置請求超時時間,單位是毫秒
connection.setConnectTimeout(5000);
// 5 獲取返回碼
int code=connection.getResponseCode();
Log.i("test",""+code);
// 6 根據(jù)返回碼做相應(yīng)處理
if(code==200)
{
// 7 如果連接正常,則獲取返回的輸入流
InputStream in=connection.getInputStream();
// 8 對輸入流進行處理
// 8.1 初始化一個內(nèi)存輸出流,將輸入流讀出到內(nèi)存中
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
// 8.2 設(shè)置每次讀入的字節(jié)數(shù)特,1024,每次讀入1kb
byte[] bytes=new byte[1024];
// 8.3每次讀入的字節(jié)數(shù)
int len=-1;
while((len=in.read(bytes))!=-1)
{
// 8.4 將讀入的字節(jié)寫入內(nèi)存中
outputStream.write(bytes,0,len);
}
//8.4 關(guān)閉輸入流,內(nèi)存輸出流不需要關(guān)閉
in.close();
String output=new String(outputStream.toByteArray());
}
} catch (MalformedURLException e) {
e.printStackTrace();
}catch (IOException e)
{
e.printStackTrace();
}
}
}).start();
上面是一個整個的過程,但是一般網(wǎng)絡(luò)請求,和解析輸入流都會寫成單獨的工具類
將輸入流轉(zhuǎn)換成字符串的工具類
public class MyStreamUtil {
public static String streamToString(InputStream in)
{
byte[] bytes=new byte[1024];
int len=-1;
ByteArrayOutputStream out=new ByteArrayOutputStream();
try {
while((len=in.read(bytes))>0)
{
out.write(bytes,0,len);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
String string=new String(out.toByteArray());
return string;
}
}
網(wǎng)絡(luò)請求的工具類
public class MyHttpUtil {
public static void getNews(final String url1, final Context context)
{
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url=new URL(url1);
HttpURLConnection connection=(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
int code=connection.getResponseCode();
if(code==200)
{
InputStream in=connection.getInputStream();
String jsonString=MyStreamUtil.streamToString(in);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}).start();
}
}
在獲取到輸入流之后,可以根據(jù)相應(yīng)的需求進行如下處理
1 如果是json字符串,則將輸入流轉(zhuǎn)換為String類型的字符串,在對json字符串進行解析
2 如果是文件,圖片等類型,則可以不采用內(nèi)存輸出流,直接使用文件流對文件進行存儲,或者使用BitmapFactory工廠類對圖片類型的流進行處理
2 GET方式向服務(wù)器提交數(shù)據(jù)
GET方式提交數(shù)據(jù)只能用于少量數(shù)據(jù)的提交(小于1kb),GET方式其實就是拼接字符串的方式進行數(shù)據(jù)的發(fā)送。
GET方式提交數(shù)據(jù)和上面網(wǎng)絡(luò)請求區(qū)別很少,只需要吧URL改變即可,
服務(wù)器端就可以按照相應(yīng)的處理GET請求的方式接收數(shù)據(jù)
//GET方式的url用問好分開,前面是地址,后面是以key-value方式傳入的數(shù)據(jù)
//每一對數(shù)據(jù)之間用&分開
private String name="aaa";
private int pwd=123;
private final String getUrl="http://139.129.110.99:8901/test?name="+name+"&pwd="+pwd+"";
3 POST方式提交數(shù)據(jù)
POST方式向服務(wù)端提供數(shù)據(jù)是以流的方式進行的,和GET方式有以下幾點不同
1 url地址中不傳入具體的參數(shù)
2 請求方式變?yōu)镻OST
3 需要設(shè)置請求頭信息
4 通過輸出流的方式將數(shù)據(jù)傳到服務(wù)端
具體過程如下,~~~~~~標出的是和GET方式不同的地方
//設(shè)置URL地址~~~~~~~~~~~~~~~~~~~~~~~~~~
private final String postUrl="http://139.129.110.99:8901/posttest";
//設(shè)置傳入的內(nèi)容,key-value形式,每一對參數(shù)之間用&分開
final String content="name="+name+"&pwd="+pwd;
//網(wǎng)絡(luò)請求是耗時操作,必須要放在子線程中進行
new Thread(new Runnable() {
@Override
public void run() {
try {
// 0 網(wǎng)絡(luò)請求時需要捕獲一些異常
// 1 創(chuàng)建一個URl對象,傳入url地址
URL url=new URL(getUrl);
// 2 開啟HttpUrlConnection
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
// 3 設(shè)置請求方式,必須要大寫~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
connection.setRequestMethod("POST");
// 3.1 設(shè)置請求頭信息,Content-Type設(shè)置為application/x-www-form-urlencoded,
//代表傳入的內(nèi)容是key-value形式的~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
// 3.2 設(shè)置傳入的內(nèi)容的長度,就是content的長度~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
connection.setRequestProperty("Content-Length",""+content.length());
// 4 設(shè)置請求超時時間,單位是毫秒
connection.setConnectTimeout(5000);
// 5設(shè)置允許向服務(wù)端傳數(shù)據(jù)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
connection.setDoOutput(true);
//獲取輸出流,并將內(nèi)容傳入服務(wù)端
OutPutStream out=connection.getOutputStream();
out.write(content.getBytes());
out.close();
// 6 獲取返回碼
int code=connection.getResponseCode();
Log.i("test",""+code);
// 7 根據(jù)返回碼做相應(yīng)處理
if(code==200)
{
// 8 如果連接正常,則獲取返回的輸入流
InputStream in=connection.getInputStream();
// 9 對輸入流進行處理
// 9.1 初始化一個內(nèi)存輸出流,將輸入流讀出到內(nèi)存中
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
// 9.2 設(shè)置每次讀入的字節(jié)數(shù)特,1024,每次讀入1kb
byte[] bytes=new byte[1024];
// 9.3每次讀入的字節(jié)數(shù)
int len=-1;
while((len=in.read(bytes))!=-1)
{
// 8.4 將讀入的字節(jié)寫入內(nèi)存中
outputStream.write(bytes,0,len);
}
//9.4 關(guān)閉輸入流,內(nèi)存輸出流不需要關(guān)閉
in.close();
String output=new String(outputStream.toByteArray());
Log.i("test",output);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}catch (IOException e)
{
e.printStackTrace();
}
}
}).start();
關(guān)于Content-Type
1 application/x-www-form-urlencoded
這種方式代表傳入的為key-value形式,content中的內(nèi)容就像上面的程序那樣,服務(wù)端接收時,根據(jù)傳入的值接收數(shù)據(jù)
2 application/json
這種方式代表傳入一個json字符串,content中的內(nèi)容就是一個json字符串,服務(wù)端接收這個字符串,并解析
3 multipart/form-data
這種方式是最復(fù)雜的,代表表單上傳。實際中很少直接用httpUrlConnection實現(xiàn)表單的上傳,一般都用網(wǎng)絡(luò)請求框架去實現(xiàn)
這種方式可以實現(xiàn)單個文件的上傳,多個文件的上傳,帶有文件的表單的上傳(例如完善注冊信息的功能,需要既上傳文字,又上傳圖片)。
步驟
1 模擬http文件上傳的格式
文件上傳時格式如下,這幾個時主要的必須寫的,其他的可以不寫,都會默認填充。
(boundary是自己定義的,什么樣都可以,
name和filename是自己定義的,其他的都是固定格式。
無論是否傳文件,name和filename都必須有,后臺接收文件時按照name接收,但是filename也需要存在)
Content-Type: multipart/form-data; boundary=-------zzzz(文件頭,一組文件只要一個)
---------zzzz(每一個文件開始的標志,在boundary前面加2個-)
Content-Disposition: form-data; name="ttt"; filename="123"
第一個空行
第二個空行
abece(這個是名字為ttt的內(nèi)容)
---------zzzz
Content-Disposition: form-data; name="aaa"; filename="aaa.jpg"
第一個空行
第二個空行
圖片文件.
.
.(有多少個文件,就按這種方式寫多少個)
.
.
---------zzzz--(文件尾,一組文件只要一個。結(jié)尾另起新的一行,在前面定義的boundary前后各加2個-)
所以按照上面的格式,就可以自己仿照文件上傳的格式進行文件上傳
下面的代碼在一個表單中上傳了2個文件,如果要繼續(xù)上傳文件,按照格式寫就可以
new Thread(new Runnable() {
@Override
public void run() {
try {
//定義自己的boundary
String boundary="------zzzz";
URL url=new URL(postUrl);
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(5000);
connection.setDoOutput(true);
//定義文件頭
connection.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);
//獲取輸出流
OutputStream out=connection.getOutputStream();
//第一個文件開始,這個其實是一個key-value對
//先定義一個sb字符串,用于傳送第一個文件的各種信息
StringBuilder sb=new StringBuilder();
//開頭是--------zzzz,然后加\r\n,回車并換行
sb.append("--").append(boundary).append("\r\n");
//第二行的內(nèi)容,定義好name和filename
sb.append("Content-Disposition:form-data;name=\"ttt\";filename=\"ttt1vv.tt\"");
//再空兩行
sb.append("\r\n\r\n");
//第一個文件的內(nèi)容,這里就是一個字符串,所以直接加了進行
sb.append("zyl");
//將第一個文件的內(nèi)容加入輸出流
out.write(sb.toString().getBytes());
//在輸出流里加入換行,開始第二個文件,每個文件都需要新起一行
out.write("\r\n".getBytes());
//第二個文件開始
//定義字符串
StringBuilder sb1=new StringBuilder();
//開頭是--------zzzz,然后加\r\n,回車并換行
sb1.append("--"+boundary+"\r\n");
//第二行的內(nèi)容,定義好name和filename
sb1.append("Content-Disposition:form-data;name=\"aaa\";filename=\"aaavv\"");
//空兩行,后面是文件的內(nèi)容
sb1.append("\r\n\r\n");
//先將這些加入輸出流,因為這個文件的內(nèi)容是一個文件,所以后面直接把內(nèi)容加入輸出流
out.write(sb1.toString().getBytes());
//獲取到對應(yīng)的問價
File file=new File(Environment.getExternalStorageDirectory(),"Pictures");
Log.i("test",file.getAbsolutePath());
if(!file.exists())
{
file.mkdirs();
}
File newFile=new File(file,"b.png");
if(!newFile.exists())
{
newFile.createNewFile();
}
FileInputStream fileInputStream=new FileInputStream(newFile);
int len=-1;
byte[] bytes=new byte[1024];
//將文件加入輸出流
while ((len=fileInputStream.read(bytes))!=-1)
{
out.write(bytes,0,len);
}
//定義文件組的結(jié)尾
byte[] endData=("\r\n--"+boundary+"--"+"\r\n").getBytes();
//將結(jié)尾加入輸出流
out.write(endData);
//關(guān)閉輸出流,輸出流被上傳到服務(wù)器
out.close();
//后面再開始接收服務(wù)器返回的內(nèi)容,這里就不繼續(xù)寫了
Log.i("test",""+connection.getResponseCode());
} catch (MalformedURLException e) {
e.printStackTrace();
Log.i("test","0");
}catch (IOException e)
{
e.printStackTrace();
Log.i("test","1");
}
}
}).start();