編輯:關於Android編程
有的時候用多了Android的一些開源框架用多了,就會把最基礎的一些東西給忘了,今天來重溫一下Android的網絡基礎。包括這個Http協議的網絡請求,JSON解析。
使用HTTP協議訪問網絡
在 Android上發送 HTTP 請求的方式一般有兩種,HttpURLConnection 和 HttpClient,先來看一下 HttpURLConnection 的用法。首先需要獲取到 HttpURLConnection 的實例,一般只需 new出一個 URL 對象,並傳入目標的網絡地址,然後調用一下 openConnection()方法即可,下面來看一下HttpURLConnection 一個GET請求方式的例子:
public class HttpActivity extends Activity implements OnClickListener{
private TextView data;
private Button getdata;
private static final int SHOWTEXT=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_http);
initview();
}
private void initview(){
data=(TextView) findViewById(R.id.text);
getdata=(Button) findViewById(R.id.getdata);
getdata.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.getdata:
getdata();
break;
default:
break;
}
}
Handler handler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOWTEXT:
//將msg.obj設置進來
data.setText(msg.obj.toString());
break;
default:
break;
}
};
};
private void getdata() {
//開啟子線程
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection=null;
try {
URL url=new URL("https://www.baidu.com/");
//利用url對象來獲取HttpURLConnection的實例調用openConnection
connection=(HttpURLConnection) url.openConnection();
//讀取超時的毫秒數
connection.setReadTimeout(8000);
//設置請求方式
connection.setRequestMethod("GET");
//連接響應時間
connection.setConnectTimeout(8000);
//獲取到請求回來的輸入流
InputStream inputStream=connection.getInputStream();
//對獲取到的輸入流進行讀取
BufferedReader reader=new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder=new StringBuilder();
String line;
while ((line=reader.readLine())!=null) {
builder.append(line);
}
// 將服務器返回的結果存放到Message中
Message message=new Message();
message.what=SHOWTEXT;
//將返回結果放到message.obj當中
message.obj=builder.toString();
handler.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}finally {
if(connection!=null){
connection.disconnect();//將http連接關閉
}
}
}
}).start();
}
}
添加網絡權限後運行程序:
就可以成功獲取到百度的一些HTML代碼.只是通常情況下浏覽器都會將這些代碼解析成漂亮的網頁後再展示出來。
如果是想要提交數據給服務器的話我們只需將GET 改成POST,並在獲取輸入流之前把要提交的數據寫出即可注意每條數據都要以鍵值對的形式存在,數據與數據之間用&符號隔開,比如說我們想要向服務器提交用戶名和密碼,就可以這樣寫:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=admin&password=123456");
使用 HttpClient
HttpClient是Apache提供的HTTP網絡訪問接口, 從一開始的時候就被引入到了AndroidAPI中。它可以成和 HttpURLConnection 幾乎一模一樣的效果,但兩者之間的用法卻有較大的差別,那麼我們自然要看一下 HttpClient是如何使用的了。
注意:
設置android SDK的編譯版本為23時,且使用了httpClient相關類的庫項目:如xutis3.0以下等等,會出現有一些類找不到的錯誤。
android6.0SDK中刪除HttpClient的相關類的解決方法(android 6.0已經不再支持HttpClient):
1.eclipse:
libs中加入
org.apache.http.legacy.jar
上面的jar包在:**\android-sdk-windows\platforms\android-23\optional下(需要下載android 6.0的SDK)
2.android studio:
在相應的module下的build.gradle中加入:
android {
useLibrary ‘org.apache.http.legacy’
}
注意放置的位置:是在android {}中
下面來看下HttpClient的一個GET請求例子:
public class HttpClientActivity extends Activity{
private TextView data;
private Button getdata;
private static final int SHOW_RESPONSE=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_http);
data=(TextView) findViewById(R.id.text);
getdata=(Button) findViewById(R.id.getdata);
getdata.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getdata();
}
});
}
Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SHOW_RESPONSE:
data.setText(msg.obj.toString());
break;
default:
break;
}
};
};
private void getdata() {
new Thread(new Runnable() {
@Override
public void run() {
HttpClient client=new DefaultHttpClient();
HttpGet get=new HttpGet("https://www.baidu.com/");
try {
HttpResponse response=client.execute(get);
if(response.getStatusLine().getStatusCode()==200){
HttpEntity entity=response.getEntity();
String respon=EntityUtils.toString(entity,"utf-8");
Message message = new Message();
message.what = SHOW_RESPONSE;
// 將服務器返回的結果存放到Message中
message.obj = respon.toString();
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
HttpClient的POST方法:
Post方法稍微會比GET方法復雜一點
HttpPost httpPost = new HttpPost("http://www.baidu.com");
List params = new ArrayList();
params.add(new BasicNameValuePair("username", "admin"));
params.add(new BasicNameValuePair("password", "123456"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "utf-8");
httpPost.setEntity(entity);
httpClient.execute(httpPost)
解析JSON數據
使用 JSONObject
我們在本地apache服務器定義了一組JSON數據,apache的安裝可以自行百度,JSON數據如下:
[{"id":"5","version":"5.5","name":"Angry Birds"},
{"id":"6","version":"7.0","name":"Clash of Clans"},
{"id":"7","version":"3.5","name":"Hey Day"}]
解析:
public class AnalysisJSONActivity extends Activity{
private TextView json;
private Button getjson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xml);
json=(TextView) findViewById(R.id.json);
getjson=(Button) findViewById(R.id.getjson);
getjson.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getData();
}
});
}
Handler handler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
json.setText(msg.obj.toString());
break;
default:
break;
}
};
};
private void getData() {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection=null;
try {
// 指定訪問的服務器地址是電腦本機
URL url=new URL("http://10.0.2.2/test.json");
connection=(HttpURLConnection) url.openConnection();
connection.setReadTimeout(8000);
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
InputStream inputStream=connection.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder=new StringBuilder();
String line;
while ((line=reader.readLine())!=null) {
builder.append(line);
}
// 將服務器返回的結果存放到Message中
Message message=new Message();
message.what=1;
//將返回結果放到message.obj當中
message.obj=builder.toString();
handler.sendMessage(message);
JsonPasring(builder.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(connection!=null){
connection.disconnect();
}
}
}
}).start();
}
private void JsonPasring(String data){
JSONArray array;
try {
array = new JSONArray(data);
for(int i=0;i<=array.length();i++){
JSONObject object=array.optJSONObject(i);
String id=object.optString("id");
String version=object.optString("version");
String name=object.optString("name");
Log.i("id", id);
Log.i("version", version);
Log.i("name", name);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
由於我們在服務器中定義的是一個 JSON 數組,因此這裡首先是將服務器返回的數據傳入到了一個 JSONArray 對象中。 然後循環遍歷這個 JSONArray, 從中取出的每一個元素都是一個 JSONObject 對象,每個 JSONObject 對象中又會包含 id、name 和version這些數據。接下來只需要調用 optString()方法將這些數據取出,並打印出來即可
使用GOSN:
想要使用這個功能的話,則必須要在項目中添加一個GSON的Jar包。 首先我們需要將GSON的資源壓縮包下載下來,下載地址是:http://code.google.com/p/google-gson/downloads/list。
JSON 格式的數據如下所示:
{"name":"Tom","age":20}
就可以定義一個 Person 類,並加入 name 和 age 這兩個字段,然後只需簡單地調用如下代碼就可以將 JSON 數據自動解析成一個 Person 對象了:
Gson gson = new Gson();
Person person = gson.fromJson(jsonData, Person.class);
如果需要解析的是一段 JSON數組會稍微麻煩一點,我們需要借助 TypeToken將期望解析成的數據類型傳入到 fromJson()方法中,如下所示:
List people = gson.fromJson(jsonData, new TypeToken>()
{}.getType());
還是上面JSONObjet的代碼,換了一個方法:
private void gsonPasring(String data) {
Gson gson = new Gson();
List list = gson.fromJson(data, new TypeToken
同樣也可以正常打印出來日志,注意:使用gson的時候對應的對象都得加上json裡面的字段
對網絡請求進行封裝:
而發送 HTTP 請求的代碼基本都是相同的,如果我們每次都去編寫一遍發送 HTTP 請求的代碼,這顯然是非常差勁的做法。沒錯,通常情況下我們應該提高一下代碼的復用性.寫一點高質量代碼.
有的可能會想到這樣寫:
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();
}
}
}
}
但是需要注意,網絡請求通常都是屬於耗時操作,而 sendHttpRequest()方法的內部並沒有開啟線程,這樣就有可能導致在調用 sendHttpRequest()方法的時候使得主線程被阻塞住。
如果在 sendHttpRequest()方法內部開啟一個線程那麼服務器響應的數據是無法進行返回的,所有的耗時邏輯都是在子線程裡進行的,sendHttpRequest()方法會在服務器還來得及響應的時候就執行結束了,當然也就無法返回響應的數據了。
使用一下Java的回調機制就可以很好的解決這個問題:
定義一個接口:
public interface HttpCallBackListener {
void OnSuccess(String response);
void OnError(Exception e);
}
public class HttpUtil {
public static void get(final String url, final HttpCallBackListener listener) {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL urls = new URL(url);
connection = (HttpURLConnection) urls.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) {
// 回調OnSuccess方法
listener.OnSuccess(response.toString());
}
} catch (Exception e) {
if (listener != null) {
// 回調onError()方法
listener.OnError(e);
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}).start();
}
}
在activity當中可以這樣寫:
HttpUtil.get("https://www.baidu.com/", new HttpCallBackListener() {
@Override
public void OnSuccess(String response) {
//服務器返回數據成功
}
@Override
public void OnError(Exception e) {
//服務器返回數據失敗
}
});
以上只是一個Get請求方法,當然post請求方法也是差不多。
目前常用的網絡請求開源框架有:xutis ,okhttp ,volley,android-async-http等等,使用方法可以自行百度.
先看效果圖: @Override public void onCreate(Bundle savedInstanceState) { super.onC
本文實例為大家分享了Android懸浮窗菜單的具體代碼,供大家參考,具體內容如下MainActivity.java代碼:package siso.multilistvie
今天主要說的是對Layout_weight屬性的完全解析,以及利用Layout_weight這個屬性使用ListView來實現表格的效果,我們都知道Android裡面專門
現在,不少人都在手機搜狗輸入法,但是有些用戶反映,在手機上使用搜狗輸入法進行書寫時,因為鍵盤大小而有了一些困擾,這裡有一個方法可以調節鍵盤大小,方便您的書寫