不可以在 Activity 的 Main Thread 裡直接呼叫網路存取,因為很有可能出現五秒鐘的 ANR。
另外要在 AndroidManifest.xml 開啟網路權限 android.permission.INTERNET。
記得測試的時候,若要連到本機,不可以用 localhost 或者 127.0.0.1,因為這時的本機指的是手機或 Emulator,不是開發的電腦。
網路連線的 Exception 可以分成三類:
- 傳輸:網路不通或者不穩。
- 通訊協定:權限相關。
- Timeout:包括 Connection timeout 與 Socket timeout,分別是 request timeout 與 response timeout。
- HttpClient 負責偵測並重試。
- 開發時就會發現。
- 唯一要處理的,使用重試機制。
public class SingleHttpClient { private static final String TAG = "SingleHttpClient"; private static HttpClient httpClient; private SingleHttpClient() { // singleton } public static synchronized HttpClient get() { if (httpClient == null) { Log.i(TAG, "建立 Singleton HttpClient..."); HttpParams params = new BasicHttpParams(); // 取得 connection ConnManagerParams.setTimeout(params, 1000); // request timeout HttpConnectionParams.setConnectionTimeout(params, 5000); // response timeout HttpConnectionParams.setSoTimeout(params, 10000); SchemeRegistry schreg = new SchemeRegistry(); schreg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schreg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); // 因為 HttpClient 是 Singleton,所以使用特別的 ConnectionManager ClientConnectionManager ccMgr = new ThreadSafeClientConnManager( params, schreg); httpClient = new DefaultHttpClient(ccMgr, params); } return httpClient; } }HttpGetActivity
public class HttpGetActivity extends Activity { private static final String TAG = "HttpGetActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { String response = this.doGetWithRetry(); } catch (Exception e) { Log.e(TAG, "不幸的事發生了"); } } /** * 實做重試機制 * @return * @throws Exception */ private String doGetWithRetry() throws Exception { int retry = 3; int current = 0; while (current < retry) { current++; try { return this.doGet(); } catch (IOException e) { Log.e(TAG, current + ".網路發生錯誤 - " + e.getMessage()); if (current >= retry) { Log.e(TAG, "重試失敗"); throw e; } } catch (Exception e) { Log.e(TAG, current + ".發生未知的錯誤 - " + e.getMessage()); if (current >= retry) { Log.e(TAG, "重試失敗"); throw e; } } } return null; } /** * 網路讀取 * @return * @throws IOException */ private String doGet() throws IOException { BufferedReader in = null; try { // 使用 Singleton 且 ThreadSafe 的 HttpClient HttpClient client = SingleHttpClient.get(); HttpGet request = new HttpGet("http://cw1057.blogspot.com/"); // 網址有參數的作法 // request = new HttpGet("http://cw1057.blogspot.com/search?updated-max=2011-12-11T16:33:00%2B08:00&max-results=5"); // 可以透過 HttpGet 來覆蓋 HttpClient 的設定,不會因為使用 Singleton 的 HttpClient 而受限 HttpParams params = request.getParams(); // 取得 connection ConnManagerParams.setTimeout(params, 1000); // request timeout HttpConnectionParams.setConnectionTimeout(params, 5000); // response timeout HttpConnectionParams.setSoTimeout(params, 10000); // 原始的方法:逐行讀取資料 // HttpResponse response = client.execute(request); // in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); // StringBuilder html = new StringBuilder(); // String line; // while ((line = in.readLine()) != null) { // html.append(line + "\n"); // } // in.close(); // String responseText = html.toString(); // 快速的方法:將 response 打包成 String String responseText = client.execute(request, new BasicResponseHandler()); Log.d(TAG, "取得 HTML(" + responseText.length() + ") - " + TextUtils.substring(responseText, 0, 10) + " ... "); return responseText; } // 不處理 Execption,交由重試機制負責 finally { if (in != null) { try { in.close(); } catch (IOException e) { } } } } }
網路沒有開的情況:
正常的狀況,第二次再進來就沒有建立 HttpClient:
相關文章
沒有留言:
張貼留言