activity_main.xml

<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.java

/**
* 最近在看天气预报的相关知识,想寻找一个比较合适的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.java

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.java

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);
}
}

获取中央气象台API 完整城市列表简单方式的更多相关文章

  1. vue实现城市列表选择

    成果展示 最后的成果就是下面所展示的内容,因为gif图没有做,只能截图所展示,接下来,会带着大家一步一步的完成下面功能,脚手架搭建和node安装在本次案例不会讲解,如果了解,可以在我的博客园找到有详细 ...

  2. C#开发BIMFACE系列25 服务端API之获取模型数据10:获取楼层对应面积分区列表

    系列目录     [已更新最新开发文章,点击查看详细] 在<C#开发BIMFACE系列22 服务端API之获取模型数据7:获取多个模型的楼层信息>中,返回的楼层信息结果中包含了楼层的具体信 ...

  3. java:struts框架2(方法的动态和静态调用,获取Servlet API三种方式(推荐IOC(控制反转)),拦截器,静态代理和动态代理(Spring AOP))

    1.方法的静态和动态调用: struts.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCT ...

  4. Struts2中获取servlet API的几种方式

    struts2是一个全新的MVC框架,如今被广大的企业和开发者所使用,它的功能非常强大.这给我们在使用servlet 纯java代码写项目的时候带来了福音.但是一般来说,我们的项目不到一定规模并不需要 ...

  5. 【python】获取高德地图省市区县列表

    项目中需要用省市区来进行检索,原想高德地图肯定会有API来获得这些数据,结果没有找到,有一个接口好像可以用,但是会附带大量的边界坐标点. 所以就不如自己把高德的省市区列表扒下来,自己写接口来完成这个功 ...

  6. Android例子源码非第三方实现根据字母排序的城市列表

    values 下dimens.xml <resources> <!-- Default screen margins, per the Android Design guidelin ...

  7. 【高德地图API】从零开始学高德JS API(七)——定位方式大揭秘

    原文:[高德地图API]从零开始学高德JS API(七)——定位方式大揭秘 摘要:关于定位,分为GPS定位和网络定位2种.GPS定位,精度较高,可达到10米,但室内不可用,且超级费电.网络定位,分为w ...

  8. Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)

    Android应用--简.美音乐播放器获取专辑图片(自定义列表适配器) 2013年7月3日简.美音乐播放器开发 第二阶段已增加功能: 1.歌词滚动显示 2.来电监听 3.音量控制 4.左右滑动切换歌词 ...

  9. 剖析Asp.Net Web API路由系统---WebHost部署方式

    上一篇我们剖析了Asp.Net路由系统,今天我们再来简单剖析一下Asp.Net Web API以WebHost方式部署时,Asp.Net Web API的路由系统内部是怎样实现的.还是以一个简单实例开 ...

随机推荐

  1. python 备份脚本

    import osimport timesource= r"out_res.txt"target_dir= r"F:\python\Doc"target=tar ...

  2. WPF事件,路由事件

    直接事件模型或CLR事件模型 1事件拥有者 2事件响应者 3事件订阅关系 例如 Window窗口中的控件Button 事件:拥有者Button 事件:Button.Click 事件响应者:Window ...

  3. JavaScript中的构造函数

    目录: constructor & prototype 为构造函数添加属性和方法的多种不同方法 组合使用this和prototype关键字创建构造函数(常用方法) 用对象直接量作为构造函数的参 ...

  4. pyhon MySQLdb查询出来的数据设置为字典类型

    import MySQLdbimport MySQLdb.cursors cxn=MySQLdb.Connect(host='localhost',user='root',passwd='1234', ...

  5. 如何将mongodb bson文件转成json文件

    使用mongodb自带的命令 bsondump collection.bson > collection.json

  6. Javascript实现DIV的隐藏和出现

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  7. 阿里云ECS每天一件事D9:nginx1.7整合tomcat8.0

    仅通过8080端口访问jsp显然不是一算是一个太好的方法,可以使用nginx的proxy_pass子模块,实现nginx转发jsp请求至tomcat. 典型的配置如下: server { listen ...

  8. 三种客户端访问wcf服务端的方法 C#

    原文 http://blog.csdn.net/zlj002/article/details/7914556 string jsonstr = String.Empty; string url = & ...

  9. 使用自定义脚本扩展程序自动执行 VM 自定义任务

     在 Build 开发者大会上推出VM 扩展程序的其中一个称为"自定义脚本扩展程序",它支持 PowerShell.如果这是您第一次访问这些博客,可能需要查看以前的博客,请单击 ...

  10. Android Studio 代码混淆

    新建一个项目,Android Studio默认关闭代码混淆开关,在build.gradle文件中,如下图所示的minifyEnabled 开关,因此如果需要混淆代码,需将false改为true,然后在 ...