В этом посте я хотел бы описать, как искать город, используя 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 Criteria static { 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 . |