В этом посте я хотел бы описать, как искать город, используя openweathermap для получения погодных условий. Есть два способа найти город:
- Используя шаблон имени
- Использование географических координат (Android Location API)
Кроме того, мы познакомимся с некоторыми понятиями об API определения местоположения Android и сервисе определения местоположения .
Поиск города по названию
В этом виде поиска пользователь вставляет часть названия города, и приложение покажет все возможные результаты, соответствующие шаблону. С точки зрения пользовательского интерфейса, мы хотим получить что-то вроде изображения, показанного ниже:
В качестве первого шага мы можем использовать EditText, чтобы пользователь мог вставить название города:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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», чтобы указать действие поиска, когда пользователь завершает вставку шаблона названия города. Теперь в Activity, которая содержит этот макет, мы имеем:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
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 для вызова:
|
1
|
http://api.openweathermap.org/data/2.5/find?mode=json&type=like&q=...&cnt=10 |
где после q мы добавим наше имя шаблона, а cnt представляет количество элементов, которые мы хотим получить (в нашем случае мы хотим максимум 10 результатов).
Как только у нас есть данные, мы их анализируем. Мы ищем тег списка, который содержит результат, и для каждого элемента в результате мы ищем тег имени, который содержит имя , идентификатор и страну. Парсер очень прост:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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, чтобы показать результаты пользователю. Это происходит в методе OnPostExecute AsyncTask . Обратите внимание, что вы можете создать собственный адаптер для отображения этой информации или использовать стандартный адаптер.
Поиск города с использованием географических координат: Android Location API
Еще один способ поиска города — использование текущей позиции пользователя. Мы можем использовать услугу определения местоположения, чтобы найти текущее положение устройства с помощью GPS или WI-FI или сотовой сети. Существует два основных элемента при реализации сервиса на основе местоположения:
- Менеджер местоположений, который является точкой входа в службу на основе местоположения
- Location Provider, представляющий технологию определения местоположения, используемую для определения положения устройства
Первый шаг — получение ссылки на LocationManager . Это системный сервис, тогда мы можем использовать:
|
1
|
LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); |
Как только у нас появится справка по Location Manager, мы сможем найти поставщика. В нашем случае мы не хотим указывать конкретного провайдера (например, GPS), но позволяем системе найти лучшее соответствие критериям поиска, которые мы установили:
|
1
2
3
4
5
6
7
8
|
private static Criteria searchProviderCriteria = new Criteria();// Location Criteriastatic { searchProviderCriteria.setPowerRequirement(Criteria.POWER_LOW); searchProviderCriteria.setAccuracy(Criteria.ACCURACY_COARSE); searchProviderCriteria.setCostAllowed(false);} |
и тогда мы готовы получить провайдера:
|
1
|
String provider = locManager.getBestProvider(searchProviderCriteria, true); |
и:
|
1
|
Location loc = locManager.getLastKnownLocation(provider); |
Теперь мы должны проверить, является ли местоположение нулевым или слишком старым, в этом случае мы получаем новую позицию:
|
1
2
3
4
5
6
7
8
9
|
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, что нам нужен слушатель, который реализует некоторые методы обратного вызова, которые будут вызываться, когда доступна текущая позиция:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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-адреса, который будет вызываться для получения города по географическим координатам. В этом случае URL для вызова:
где% lat% и & lon% будут заменены реальным значением, извлеченным из текущей позиции.
Использование эмулятора для тестирования приложения
Последний шаг — тестирование приложения с передачей координат. Мы можем использовать DDMS DDMS и передать координаты:
Обратите внимание, что вы должны разделять десятичную часть в соответствии с вашим языком и числовым форматом. Другой способ использования
|
1
|
telnet iphost port |
и при подключении отправить
|
1
|
geo fix <longitude value> <latitude value> |
| Ссылка: | Использование API определения местоположения Android в приложении Погода — найдите город у нашего партнера JCG Франческо Аццолы в блоге Surviving с Android . |
![android_weather_app_search_city [4]](/wp-content/uploads/images/jcg/337b000acbd8bb572ce1c763e34700c9.png)
![android_ddms_location [4]](/wp-content/uploads/images/jcg/585fa2d86e674fa7fd77bf0e3d50dbeb.png)