weather
在这篇文章中,我想描述如何使用openweathermap搜索城市以获取天气状况。 我们可以通过两种方式查找城市:
- 使用名称模式
- 使用地理坐标(Android Location API)
此外,我们将介绍有关Android位置API和基于位置的服务的一些概念。
按名称搜索城市
在这种搜索中,用户插入了一部分城市名称,应用程序将显示所有与模式匹配的可能结果。 从UI的角度来看,我们想要获得如下图所示的图像:
第一步,我们可以使用EditText,以便用户可以插入城市名称:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
....
<EditText
android:id="@+id/cityEdtText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/textView1"
android:layout_marginTop="5dp"
android:imeOptions="actionSearch"
android:inputType="text" >
<requestFocus />
</EditText>
....
<ListView android:id="@+id/cityList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/txt1"
android:layout_marginTop="3dp"/>
</RelativeLayout>
注意,在第13行,当用户完成插入城市名称模式时,我们使用imeOptions和“ actionSearch”值来指定搜索操作。 现在在拥有此布局的活动中,我们有:
final EditText edt = (EditText) findViewById(R.id.cityEdtText);
edt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
bar.setVisibility(View.VISIBLE);
JSONSearchTask task = new JSONSearchTask();
String pattern = edt.getEditableText().toString();
task.execute(new String[]{pattern});
return true;
}
return false;
}
});
因此,当用户单击搜索图标时,我们开始搜索匹配的城市名称,最后我们将填充ListView(第18行)。 如您所见,我们启动了AsyncTask ,因为搜索操作可能需要很长时间,并且我们不希望出现ANR问题。现在是时候实现调用远程openweathermap服务并检索城市的逻辑了。 从API中我们知道要调用的URL是:
http://api.openweathermap.org/data/2.5/find?mode=json&type=like&q=...&cnt=10
在q之后,我们将添加模式名称,而cnt表示我们要获取的项目数(在我们的情况下,我们最多希望有10个结果)。一旦有了数据,我们就对其进行解析。 我们寻找包含结果的列表标签,对于结果中的每个项目,我们寻找包含名称, id和国家的名称标签。 解析器非常简单:
public static List<City> getCityList(String data) throws JSONException {
JSONObject jObj = new JSONObject(data);
JSONArray jArr = jObj.getJSONArray("list");
List<City> cityList = new ArrayList<City>();
for (int i=0; i < jArr.length(); i++) {
JSONObject obj = jArr.getJSONObject(i);
String name = obj.getString("name");
String id = obj.getString("id");
JSONObject sys = obj.getJSONObject("sys");
String country = sys.getString("country");
City c = new City(id,name,country);
cityList.add(c);
}
return cityList;
}
..最后我们填充ListView以向用户显示结果。 这发生在AsyncTask的onPostExecute方法中。 请注意,您可以创建一个自定义适配器以显示此信息,也可以使用标准适配器。
使用地理坐标搜索城市:Android Location API
查找城市的另一种方法是使用当前用户位置。 我们可以使用基于位置的服务来通过GPS或WI-FI或蜂窝网络找到当前设备的位置。 实施基于位置的服务时,有两个主要元素:
- 位置管理器,它是基于位置的服务的入口点
- 位置提供者,代表用于查找设备位置的定位技术
第一步是获取LocationManager参考。 这是一项系统服务,然后我们可以使用:
LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
一旦有了我们的位置管理器参考,就可以找到提供商。 在我们的情况下,我们不想指定特定的提供者(例如GPS),而是让系统找到最符合我们设置的搜索条件的提供者:
private static Criteria searchProviderCriteria = new Criteria();
// Location Criteria
static {
searchProviderCriteria.setPowerRequirement(Criteria.POWER_LOW);
searchProviderCriteria.setAccuracy(Criteria.ACCURACY_COARSE);
searchProviderCriteria.setCostAllowed(false);
}
然后我们准备好获取提供者:
String provider = locManager.getBestProvider(searchProviderCriteria, true);
和:
Location loc = locManager.getLastKnownLocation(provider);
现在我们必须检查位置是否为空或太旧,在这种情况下,我们将获得一个新位置:
if (loc == null || (SystemClock.elapsedRealtime() - loc.getTime()) > timeOut) {
// We request another update Location
Log.d("SwA", "Request location");
locManager.requestSingleUpdate(provider, locListener, null);
}
else {
JSONSearchTask task = new JSONSearchTask();
task.execute(new Location[]{loc});
}
否则,我们只需致电该服务即可到达城市。 注意,在第4行,我们需要一个实现一些回调方法的侦听器,当当前位置可用时,将调用该侦听器:
private LocationListener locListener = new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onLocationChanged(Location location) {
Log.d("SwA", "Location changed!");
String sLat = "" + location.getLatitude();
String sLon = "" + location.getLongitude();
Log.d("SwA", "Lat ["+sLat+"] - sLong ["+sLon+"]");
LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locManager.removeUpdates(locListener);
JSONSearchTask task = new JSONSearchTask();
task.execute(new Location[]{location});
}
};
最后一步是创建将被调用以从地理坐标中检索城市的URL。 在这种情况下,要调用的网址是:
http://api.openweathermap.org/data/2.5/find?lat=%lat%&lon=%lon%
其中%lat%和&lon%将替换为从当前位置提取的实际值。
使用模拟器测试应用
最后一步是测试传递坐标的应用程序。 我们可以使用DDMS DDMS并传递坐标:
请注意,您应该根据您的语言和数字格式分隔小数部分。 另一种方法是使用
telnet iphost port
当连接时发送
geo fix <longitude value> <latitude value>
翻译自: https://www.javacodegeeks.com/2014/04/using-android-location-api-in-weather-app-search-city.html
weather