Android 联网先拿回数据再解析。HTTP 协议可参考 深入理解HTTP协议。动手前在 manifest 加权限,检查网络是否可用,并把请求放到 UI 线程之外(常用 AsyncTask)。客户端多用 HttpURLConnection,也可用 Apache HttpClient。
一、权限与网络是否可用
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (isGpsConnection() || isWiFiConnection()) {
//网络连接可用
} else {
//网络连接不可用!
}
public boolean isGpsConnection(){
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
return true;
} else {
return false;
}
}
public boolean isWiFiConnection(Context inContext) {
Context context = inContext.getApplicationContext();
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getTypeName().equals("WIFI") && info[i].isConnected()) {
return true;
}
}
}
}
return false;
}
二、AsyncTask 避开 UI 线程延迟
网络会有不可预期延迟,必须在 UI Thread 外执行。doInBackground 调 downloadUrl()(URL 从 execute() 传入,params[0] 是 url),处理完把 String 交给 onPostExecute 更新 UI。
private class DownloadWebpageText extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
// 参数从 execute() 传入, params[0] 表示 url
}
@Override
protected void onPostExecute(String result) {
}
}
三、完整实例:HttpURLConnection GET
布局 activity_httpconnection_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/http_url_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入URL地址" />
<TextView
android:id="@+id/http_content_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button android:id="@+id/http_get_content_btn"
android:layout_width="match_parent"
android:onClick="onConnectionClickHandler"
android:layout_height="wrap_content" />
</LinearLayout>
HttpExampleActivity.java:点按钮先查网络,再异步 GET。注意 getResponseCode() 返回状态码,200 表示成功。
public class HttpExampleActivity extends Activity {
private static final String DEBUG_TAG = "HttpExample";
private EditText mUrlText;
private TextView mShowMessageTxt;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_httpconnection_layout);
mUrlText = (EditText) findViewById(R.id.http_url_edit);
mShowMessageTxt = (TextView) findViewById(R.id.http_content_txt);
}
public void onConnectionClickHandler(View view) {
String stringUrl = mUrlText.getText().toString();
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
new DownloadWebpageText().execute(stringUrl);
} else {
mShowMessageTxt.setText("网络连接不可用!");
}
}
private class DownloadWebpageText extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return "Unable to retrieve web page. URL may be invalid.";
}
}
@Override
protected void onPostExecute(String result) {
mShowMessageTxt.setText(result);
}
}
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
int response = conn.getResponseCode();
Log.d(DEBUG_TAG, "The response is: " + response);
is = conn.getInputStream();
return readIt(is);
} finally {
if (is != null) {
is.close();
}
}
}
public String readIt(InputStream stream) throws IOException, UnsupportedEncodingException {
Reader reader = new InputStreamReader(stream, "UTF-8");
BufferedReader br = new BufferedReader(reader);
String line = null;
StringBuffer sb = new StringBuffer();
while ((line = br.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
}
InputStream 是可读的 byte 源,通常要 decode 成目标类型。下图数据可直接:
InputStream is = null;
...
Bitmap bitmap = BitmapFactory.decodeStream(is);
ImageView imageView = (ImageView) findViewById(R.id.image_view);
imageView.setImageBitmap(bitmap);
四、Apache HttpClient 写法
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(httpUrl);
HttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
Logs.v("statusCode >>> :" + statusCode);
if (statusCode == HttpURLConnection.HTTP_OK) {
InputStream ins = response.getEntity().getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(ins, "utf-8"));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
}
| 步骤 |
要点 |
| 权限 |
INTERNET + ACCESS_NETWORK_STATE |
| 可用性 |
ConnectivityManager + NetworkInfo.isConnected |
| 线程 |
AsyncTask:后台 download,onPostExecute 更新 UI |
| 客户端 |
HttpURLConnection(推荐)或 Apache HttpClient |
| 成功码 |
getResponseCode() == 200 |
一句话总结:联网 = 权限 + 检查 NetworkInfo + 后台 HttpURLConnection GET,把 InputStream 转成 String 或 Bitmap,状态码 200 再当成功。