activity_main.xmlhtml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:id="@+id/get_data_btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="@string/get_data" /> <TextView android:id="@+id/textView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/get_data_btn" android:layout_below="@+id/get_data_btn"/> </RelativeLayout>
MainActivity.javajava
/** * 最近在看天氣預報的相關知識,想尋找一個比較合適的API接口,終於找到了這篇文檔 * http://blog.csdn.net/lzqwebsoft/article/details/7054045 * 裏面詳細說明的怎樣從中國天氣網獲取天氣信息,但是沒用幾天發現文中使用的獲取城市 * 列表的接口貌似被封了,致使原先的方法不使用,後悔可是沒能及時將相關信息保存下來 * ,之前是考慮每次實時的從網絡上獲取城市列表,以防信息有變,可是這種接口自己就是 * 個不穩定的因素,因此仍是得把相關信息下載下來。最後只得本身去分析網頁,需找另外 * 的接口,最後終於找到了,那就老老實實把這些數據保存到數據庫裏面吧。 * 天氣網把城市分爲了3級 * 1級列表獲取地址:http://www.weather.com.cn/data/city3jdata/china.html。經過訪問這個地址,天氣 * 網會返回一級省(自治區)的名稱、ID信息; * 2級城市城市列表獲取地址:http://www.weather.com.cn/data/city3jdata/provshi/10120.html。其中「10120」 * 爲一級城市的ID,返回結果是歸屬於該城市的2級省市的名稱、ID; * 3級城市列表獲取地址:http://www.weather.com.cn/data/city3jdata/station/1012002.html。其中「1012002」 * 爲2級省市ID,返回結果就是3級城市的名稱和ID了。 * 獲取到3級城市的名稱和ID以後,就能夠根據上面那篇博客裏的內容獲取當地的天氣信息了! * */ package com.ns.getweathercity; import java.io.IOException; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.params.HttpClientParams; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.params.ConnManagerParams; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.content.ContentValues; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener{ private Button mGetDataButton = null; private TextView mProgressTextView = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGetDataButton = (Button)findViewById(R.id.get_data_btn); mGetDataButton.setOnClickListener(this); mProgressTextView = (TextView)findViewById(R.id.textView1); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.get_data_btn: new GetDataTask().execute(); break; default: break; } } private class GetDataTask extends AsyncTask<Void, Integer, Integer> { private HttpClient httpClient = null; @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Integer doInBackground(Void... params) { getHttpClient(); CityDataHelper.getInstance(MainActivity.this).delete(null, null); //經過遞歸獲取城市列表 try { getCitys(1, "", "http://www.weather.com.cn/data/city3jdata/china.html"); } catch (ClientProtocolException e) { Log.e("ns", "error", e); return -1; } catch (IOException e) { Log.e("ns", "error", e); return -1; } return 1; } /**這個函數的代碼,參照http://blog.csdn.net/suiyuansanren/article/details/8663824這篇博文 * 寫的不錯*/ private synchronized HttpClient getHttpClient() { if(httpClient == null) { final HttpParams httpParams = new BasicHttpParams(); // timeout: get connections from connection pool ConnManagerParams.setTimeout(httpParams, 5000); // timeout: connect to the server HttpConnectionParams.setConnectionTimeout(httpParams, 5000); // timeout: transfer data from server HttpConnectionParams.setSoTimeout(httpParams, 5000); // set max connections per host //ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(10)); // set max total connections ConnManagerParams.setMaxTotalConnections(httpParams, 20); // use expect-continue handshake HttpProtocolParams.setUseExpectContinue(httpParams, true); // disable stale check HttpConnectionParams.setStaleCheckingEnabled(httpParams, false); HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8); HttpClientParams.setRedirecting(httpParams, false); // set user agent String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2) Gecko/20100115 Firefox/3.6"; HttpProtocolParams.setUserAgent(httpParams, userAgent); // disable Nagle algorithm HttpConnectionParams.setTcpNoDelay(httpParams, true); HttpConnectionParams.setSocketBufferSize(httpParams, 8*1024); // scheme: http and https SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ClientConnectionManager manager = new ThreadSafeClientConnManager(httpParams, schemeRegistry); httpClient = new DefaultHttpClient(manager, httpParams); } return httpClient; } private void getCitys(int level, String pid, String url) throws ClientProtocolException, IOException { Log.i("ns", "The url is " + url); HttpGet httpGet = null; HttpResponse httpResponse = null; String citys = null; String[] citys1Array = null; int index = 0; String cityName = null; String cityID = null; httpGet = new HttpGet(url); if (httpClient != null) { httpResponse = httpClient.execute(httpGet); if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { citys = EntityUtils.toString(httpResponse.getEntity(), HTTP.UTF_8); if (citys != null && citys.trim().length() > 0) { citys1Array = citys.substring(1, citys.length() - 1) .split(","); for (int i = 0; i < citys1Array.length; i++) { index = citys1Array[i].indexOf(":"); //當前城市的ID須要用上一級城市的ID拼接出來,可是有個別的三級城市直接是最終的ID了 //不知道天氣網爲何要這麼作 cityID = citys1Array[i].substring(1, index - 1); if (level != 3 || cityID.length() < 9) { cityID = pid + cityID; } //這裏把當前正在進行的操做提示處理,以確保正在工做 publishProgress(Integer.parseInt(cityID)); cityName = citys1Array[i].substring(index + 2, citys1Array[i].length() - 1); // 插入數據庫 ContentValues values = new ContentValues(); values.put(CityContract.City.NAME, cityName); values.put(CityContract.City.CITY_ID, cityID); values.put(CityContract.City.LEVEL, level); values.put(CityContract.City.PARENT_CITY_ID, pid); CityDataHelper.getInstance(MainActivity.this) .insert(values); // 遞歸下一級列表 if (level == 1) { // 獲取二級列表 getCitys(2, cityID, "http://www.weather.com.cn/data/city3jdata/provshi/" + cityID + ".html"); } else if (level == 2) { // 獲取三級列表 getCitys(3, cityID, "http://www.weather.com.cn/data/city3jdata/station/" + cityID + ".html"); } else if (level == 3) { continue; } } } } } } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); mProgressTextView.setText(values[0].intValue() + ""); } @Override protected void onPostExecute(Integer result) { super.onPostExecute(result); Toast.makeText(MainActivity.this, "數據拉取完畢", Toast.LENGTH_SHORT).show(); //到這裏,全部城市的名稱、ID以及他們之間的關係就存放到數據庫裏面了,下次直接使用便可 } } }
CityContract.javaandroid
package com.ns.getweathercity; import android.provider.BaseColumns; public class CityContract { private CityContract() {} public abstract static class City implements BaseColumns { //數據庫表名 public static final String TABLE_NAME = "city"; //城市名稱 public static final String NAME = "name"; //城市級別 public static final String LEVEL = "level"; //城市ID public static final String CITY_ID = "city_id"; //上一級城市ID public static final String PARENT_CITY_ID = "p_c_id"; } }
CityDataHelper.javaweb
package com.ns.getweathercity; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class CityDataHelper extends SQLiteOpenHelper { private static final int DATABASE_VERSION = 1; private static final String DATABASE_NAME = "city.db"; private static final String SQL_CREATE_STUDENT = "create table " + CityContract.City.TABLE_NAME + " (" + CityContract.City._ID + " INTEGER PRIMARY KEY, " + CityContract.City.NAME + " TEXT, " + CityContract.City.LEVEL + " INTEGER, " + CityContract.City.CITY_ID + " TEXT, " + CityContract.City.PARENT_CITY_ID + " TEXT)"; private static CityDataHelper mDbHelper = null; public static CityDataHelper getInstance(Context context) { if (mDbHelper == null) { mDbHelper = new CityDataHelper(context); } return mDbHelper; } /** * constructor * * @param context * Context object used for create database */ private CityDataHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { //建立「city」表 db.execSQL(SQL_CREATE_STUDENT); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public synchronized long insert(ContentValues values) { long id = getWritableDatabase().insert(CityContract.City.TABLE_NAME, null, values); return id; } public synchronized long update(ContentValues values, String whereClause, String[] whereArgs) { long id = getWritableDatabase().update(CityContract.City.TABLE_NAME, values, whereClause, whereArgs); return id; } public synchronized int delete(String whereClause, String[] whereArgs) { int count = getWritableDatabase().delete(CityContract.City.TABLE_NAME, whereClause, whereArgs); return count; } public synchronized Cursor query(String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) { return getReadableDatabase().query(CityContract.City.TABLE_NAME, columns, selection, selectionArgs, groupBy, having, orderBy); } }