Создание приложения для Android для отображения списка местных ресторанов
Всем привет! Прежде всего, я хотел бы поблагодарить вас за то, что вы нашли время прочитать этот пост. Меня зовут Ник, я специализируюсь на компьютерных науках в Университете Центральной Флориды. Недавно я работал над разработкой приложений для Android для некоторых проектов и поэтому пытался улучшить навыки работы с Android Studio IDE вместе с языком JAVA. Чтобы сориентироваться, я сделал приложение, которое находит рестораны, расположенные на определенной долготе и широте. В этом посте я объясню, как работают ключевые компоненты приложения, и предоставлю ссылку на GitHub, содержащий код.
Это упрощенное приложение всего с двумя видами деятельности: MainActivity и DisplayRestaurants. Начнем с обсуждения MainActivity. Здесь пользователь встречает наш целевой экран, отображающий заголовок приложения и красивую зеленую кнопку. Фоновое изображение отображается аккуратно. И заголовок, и кнопка ограничены 16dp как с левой, так и с правой стороны. Заголовок устанавливается на 85 dp от верхней части экрана, а кнопка - на 172 dp от нижней части экрана. Для шрифтов MainActivity я выбрал семейство случайных шрифтов. Вы можете легко импортировать свои собственные шрифты или изменить заданные по умолчанию.
Вот XML-код MainActivity:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id = "@+id/layout" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/food_background" tools:context="com.example.basicswork.MainActivity"> <Button android:id="@+id/button" android:layout_width="153dp" android:layout_height="wrap_content" android:layout_marginBottom="172dp" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:backgroundTint="@android:color/holo_green_light" android:fontFamily="casual" android:radius="80dp" android:text="@string/restaurants" android:textAppearance="@style/TextAppearance.AppCompat.Menu" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.502" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="85dp" android:fontFamily="casual" android:text="@string/restaurant_locator" android:textColor="@android:color/white" android:textSize="30sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
XML-кодом можно легко манипулировать и изменять по своему усмотрению. Фоновое изображение добавляется в нашу папку app / res / drawable, которую можно использовать в нашем XML-файле, как вы можете видеть выше в тексте android: background.
Теперь о коде JAVA, здесь происходит настоящее волшебство. Основная проблема, которую пытается решить наша MainActivity, - это получение разрешения от пользователя на доступ к их местоположению, а затем получение их долготы и широты. Нам нужны их долгота / широта, чтобы передать их следующему действию и использовать это в поиске мест Google, который будет объяснен позже. Чтобы получить местоположение пользователя в приложениях Android, нам сначала нужно добавить строку кода в наш манифест.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.basicswork"> ... <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> ... </manifest>
ACCESS_FINE_LOCATION позволяет нам получить долготу и широту пользователя, которые очень близки к их точному местоположению. Хотя теперь мы должны спросить у пользователя разрешение на использование его местоположения. Я добился этого с помощью уведомлений Snackbar в приложении. Это своего рода дизайнерский виджет, который можно добавить и использовать для повышения эстетики уведомлений. У Snackbar есть несколько параметров, которые нужно включить. Во-первых, макет, текст, который вы хотите отобразить, и продолжительность уведомления. Чтобы использовать это в этом приложении, я добавил следующую строку кода к зависимостям файла build.gradle. Версии могут отличаться, поэтому обязательно проверьте это еще раз.
compile 'com.android.support:design:26.1.0'
Если вы хотите увидеть код MainActivity целиком, пропустите немного вперед.
Начиная сверху, наш общедоступный класс MainActivity расширяет AppCompatActivity и реализует OnRequestPermissionsResultCallback. AppCompatActivity - это просто поддержка Snackbar, а OnRequestPermissionsResultCallback - для получения обратных вызовов для запроса разрешений.
PERMISSION_REQUEST_LOCATION - это просто целочисленная проверка, чтобы узнать, предоставлено ли нам разрешение на использование их местоположения. View mLayout установлен в нашем методе onCreate, который связан с идентификатором нашего макета действий в нашем XML. Внутри onCreate мы устанавливаем простой прослушиватель onClick для запуска метода после нажатия кнопки ресторана.
public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback { private static final int PERMISSION_REQUEST_LOCATION = 0; private View mLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLayout = findViewById(R.id.layout); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showRestaurants(); } }); } ... }
После нажатия мы сначала попадаем в метод showRestaurants. В этом методе мы сначала проверяем, получили ли мы уже разрешение на использование их местоположения, а затем вызываем наш метод startRestaurants. Если у нас нет разрешения, мы переходим к нашему методу requestLocationPermission.
public void showRestaurants(){ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { // Permission is already available, show restaurants Snackbar.make(mLayout, "Location permission available. Show restaurants.", Snackbar.LENGTH_SHORT).show(); startRestaurants(); } else { // Permission is missing and must be requested. requestLocationPermission(); } }
Мы начинаем здесь с shouldShowRequestPermissionRationale, которое может быть дополнительным стимулом для пользователя, позволяющего нам использовать свое местоположение. В случае отклонения при следующем запросе разрешения может появиться сообщение с описанием его использования. Внутри этой Snackbar мы создаем еще одну с прослушивателем onClick, установленным на неопределенное время, до тех пор, пока пользователь не нажмет «ОК», чтобы снова запросить разрешение на использование местоположения. В операторе else мы обрабатываем случай, когда местоположение может быть недоступно, и передаем его в onRequestPermissionResult.
private void requestLocationPermission() { // Permission has not been granted and must be requested. if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { // Provide an additional rationale to the user if the permission was not granted // and the user would benefit from additional context for the use of the permission. // Display a SnackBar with a button to request the missing permission. Snackbar.make(mLayout, "Location access is required to display restaurants near you.", Snackbar.LENGTH_INDEFINITE).setAction("OK", new View.OnClickListener() { @Override public void onClick(View view) { // Request the permission ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_LOCATION); } }).show(); } else { Snackbar.make(mLayout, "Permission is not available. Requesting location permission.", Snackbar.LENGTH_SHORT).show(); // Request the permission. The result will be received in onRequestPermissionResult(). ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_LOCATION); } }
Внутри onRequestPermissionResult мы проверяем статус нашего разрешения. Если это разрешено, у нас есть уведомление Snackbar о том, что разрешение на определение местоположения было предоставлено, и мы переходим к нашему методу startRestaurants. В противном случае мы говорим, что в разрешении на местоположение было отказано. Если вы еще не поняли, это приложение полно уведомлений Snackbar. Вещи становятся загроможденными, но при разборке становятся упрощенными.
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == PERMISSION_REQUEST_LOCATION) { // Request for location permission. if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission has been granted. Start preview Activity. Snackbar.make(mLayout, "Location permission granted. Showing restaurants.", Snackbar.LENGTH_SHORT) .show(); startRestaurants(); } else { // Permission request was denied. Snackbar.make(mLayout, "Location permission request was denied.", Snackbar.LENGTH_SHORT) .show(); } } }
В действии startRestaurants мы дважды проверяем оператор if, чтобы увидеть наши разрешения. В случае неудачи наш метод ничего не сделает. Если это пройдет, мы начнем с создания менеджера местоположения и соберем долготу и широту пользователей. Эти значения представлены в виде двойников, но они нам понадобятся в качестве строк для нашего следующего действия. Мы соответствующим образом конвертируем их, передаем их нашему намерению и переходим к следующему действию.
public void startRestaurants() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { Intent intent = new Intent(this, DisplayRestaurants.class); LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE); Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); Double longitude = location.getLongitude(); Double latitude = location.getLatitude(); String longit = Double.toString(longitude); String lat = Double.toString(latitude); intent.putExtra("long", longit); intent.putExtra("lat", lat); startActivity(intent); } }
В качестве последнего примечания к первому действию, если вы имитируете телефон, вам может потребоваться отправить координаты в приложение. Щелкните многоточие на панели рядом с эмуляцией, перейдите к настройкам местоположения, а затем щелкните отправить, пока приложение все еще находится на главной странице, прежде чем нажимать рестораны.
Вот код основной деятельности полностью.
package com.example.basicswork; import android.Manifest; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationManager; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback { private static final int PERMISSION_REQUEST_LOCATION = 0; private View mLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLayout = findViewById(R.id.layout); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showRestaurants(); } }); } @SuppressLint("MissingPermission") public void startRestaurants() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { Intent intent = new Intent(this, DisplayRestaurants.class); LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE); Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); Double longitude = location.getLongitude(); Double latitude = location.getLatitude(); String longit = Double.toString(longitude); String lat = Double.toString(latitude); intent.putExtra("long", longit); intent.putExtra("lat", lat); startActivity(intent); } } public void showRestaurants(){ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { // Permission is already available, show restaurants Snackbar.make(mLayout, "Location permission available. Show restaurants.", Snackbar.LENGTH_SHORT).show(); startRestaurants(); } else { // Permission is missing and must be requested. requestLocationPermission(); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == PERMISSION_REQUEST_LOCATION) { // Request for location permission. if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission has been granted. Start preview Activity. Snackbar.make(mLayout, "Location permission granted. Showing restaurants.", Snackbar.LENGTH_SHORT) .show(); startRestaurants(); } else { // Permission request was denied. Snackbar.make(mLayout, "Location permission request was denied.", Snackbar.LENGTH_SHORT) .show(); } } } private void requestLocationPermission() { // Permission has not been granted and must be requested. if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { // Provide an additional rationale to the user if the permission was not granted // and the user would benefit from additional context for the use of the permission. // Display a SnackBar with a button to request the missing permission. Snackbar.make(mLayout, "Location access is required to display restaurants near you.", Snackbar.LENGTH_INDEFINITE).setAction("OK", new View.OnClickListener() { @Override public void onClick(View view) { // Request the permission ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_LOCATION); } }).show(); } else { Snackbar.make(mLayout, "Permission is not available. Requesting location permission.", Snackbar.LENGTH_SHORT).show(); // Request the permission. The result will be received in onRequestPermissionResult(). ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_LOCATION); } } }
Теперь переходим к деятельности DisplayRestaurants. XML для этого действия содержит только простой ListView, а стиль установлен на «Widget.DeviceDefault.Light.ListView». Мы также устанавливаем идентификатор нашего списка в listView для использования в коде.
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.basicswork.DisplayRestaurants"> <ListView android:id="@+id/listView" style="@android:style/Widget.DeviceDefault.Light.ListView" android:layout_width="344dp" android:layout_height="495dp" android:layout_marginBottom="8dp" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0" /> </android.support.constraint.ConstraintLayout>
Здесь мы начнем использовать Google Place Search. Для использования этой услуги вам понадобится ключ API. Вы можете получить его на этой странице здесь https://developers.google.com/places/web-service/get-api-key
Мы начинаем наш код с определения группы частных переменных. Эти переменные определяют части HTML-ссылки, которую мы создаем, чтобы получить информацию о ресторанах.
public class DisplayRestaurants extends AppCompatActivity { private ListView mListView; private static final String API_KEY = "YOUR_API_KEY"; private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place"; private static final String TYPE_AUTOCOMPLETE = "/autocomplete"; private static final String TYPE_DETAILS = "/details"; private static final String TYPE_SEARCH = "/nearbysearch"; private static final String OUT_JSON = "/json?"; private static final String LOG_TAG = "ListRest";
Информацию о создании ссылок можно найти здесь https://developers.google.com/places/web-service/search
Сначала мы переходим к нашему методу onCreate. Мы получаем намерение из предыдущего действия и получаем долготу и широту. Затем мы включаем пару ключевых строк кода, использование которых вызывает сомнения. В общем, вы хотите выполнять действия API в фоновом режиме. Поскольку это приложение настолько упрощено, а вся цель действий зависит от возврата API и не имеет другой функции, можно разрешить его в основном потоке.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);
Затем мы анализируем наши строки долготы и широты в Double’s и создаем радиус 1000. В создаваемой нами HTML-ссылке радиус - это расстояние от устройства до поиска ресторанов. Это расстояние в метрах. Не стесняйтесь изменять это расстояние по своему вкусу. Теперь мы создаем ArrayList of Place объектов. Мы устанавливаем этот список равным нашему методу поиска, который принимает в качестве параметров широту, долготу и радиус. Этот метод возвращает ArrayList, заполненный ресторанами рядом с пользователем. Если наш список не равен нулю, мы затем создаем listView, создаем ArrayAdapter, передавая наш ArrayList, и устанавливаем наш адаптер в наш listView.
... Double lng = Double.parseDouble(longitude); Double lat = Double.parseDouble(latitude); int radius = 1000; ArrayList<Place> list = search(lat, lng, radius); if (list != null) { mListView = (ListView) findViewById(R.id.listView); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, list); mListView.setAdapter(adapter); } }
В методе поиска мы начинаем с создания нулевого объекта ArrayList of Place. Здесь мы создаем нашу HTML-ссылку с помощью StringBuilder и добавляем части в требуемом порядке. После того, как мы закончили наш StringBuilder, мы используем sb.toString (), чтобы завершить нашу строку и открыть соединение URL. Мы берем входной поток и читаем его с помощью буфера. Мы добавляем наши результаты в json по мере прохождения. Есть несколько исключений, на которые мы должны обратить внимание, например, некорректная обработка запроса или невозможность подключиться к Places API. Мы завершаем эту часть кода отключением от открытого соединения.
public static ArrayList<Place> search(double lat, double lng, int radius) { ArrayList<Place> resultList = null; HttpURLConnection conn = null; StringBuilder jsonResults = new StringBuilder(); try { StringBuilder sb = new StringBuilder(PLACES_API_BASE); sb.append(TYPE_SEARCH); sb.append(OUT_JSON); sb.append("location=" + String.valueOf(lat) + "," + String.valueOf(lng)); sb.append("&radius=" + String.valueOf(radius)); sb.append("&type=restaurant"); sb.append("&key=" + API_KEY); URL url = new URL(sb.toString()); conn = (HttpURLConnection) url.openConnection(); InputStreamReader in = new InputStreamReader(conn.getInputStream()); int read; char[] buff = new char[1024]; while ((read = in.read(buff)) != -1) { jsonResults.append(buff, 0, read); } } catch (MalformedURLException e) { Log.e(LOG_TAG, "Error processing Places API URL", e); return resultList; } catch (IOException e) { Log.e(LOG_TAG, "Error connecting to Places API", e); return resultList; } finally { if (conn != null) { conn.disconnect(); } } ...
Теперь нам нужно пройти и обработать наши jsonResults. Мы создаем иерархию того, что получили. Мы создаем новый объект json и устанавливаем его равным нашим jsonResults. Затем мы конвертируем это в массив json. Теперь мы можем фактически извлечь рестораны и описания из наших результатов. Мы устанавливаем длину нашего списка массива resultList равной длине только что созданного jsonArray. С помощью цикла for, который проходит через этот массив, мы создаем новый объект Place для каждого элемента и добавляем его в наш список результатов. Если эта попытка не удалась, у нас есть ловушка, которая говорит, что у нас была ошибка где-то при обработке результатов json. Теперь мы наконец можем вернуть наш новый список.
try { // Create a JSON object hierarchy from the results JSONObject jsonObj = new JSONObject(jsonResults.toString()); JSONArray predsJsonArray = jsonObj.getJSONArray("results"); // Extract the descriptions from the results resultList = new ArrayList<Place>(predsJsonArray.length()); for (int i = 0; i < predsJsonArray.length(); i++) { Place place = new Place(); place.reference = predsJsonArray.getJSONObject(i).getString("reference"); place.name = predsJsonArray.getJSONObject(i).getString("name"); resultList.add(place); } } catch (JSONException e) { Log.e(LOG_TAG, "Error processing JSON results", e); } return resultList; }
Наконец, в конце мы создаем класс для наших объектов Place. Это просто определяет объект, который используется в наших списках массивов.
//Value Object for the ArrayList public static class Place { private String reference; private String name; public Place(){ super(); } @Override public String toString(){ return this.name; //This is what returns the name of each restaurant for array list } } }
Вот код целиком
package com.example.basicswork; import android.content.Intent; import android.os.StrictMode; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.ArrayAdapter; import android.widget.ListView; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; public class DisplayRestaurants extends AppCompatActivity { private ListView mListView; private static final String API_KEY = "AIzaSyBO7_U7r1oST2upR26wkjwLQfYSMbAogQ4"; private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place"; private static final String TYPE_AUTOCOMPLETE = "/autocomplete"; private static final String TYPE_DETAILS = "/details"; private static final String TYPE_SEARCH = "/nearbysearch"; private static final String OUT_JSON = "/json?"; private static final String LOG_TAG = "ListRest"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_display_restaurants); Intent intent = getIntent(); String longitude = intent.getStringExtra("long"); String latitude = intent.getStringExtra("lat"); StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); Double lng = Double.parseDouble(longitude); Double lat = Double.parseDouble(latitude); int radius = 1000; ArrayList<Place> list = search(lat, lng, radius); if (list != null) { mListView = (ListView) findViewById(R.id.listView); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, list); mListView.setAdapter(adapter); } } public static ArrayList<Place> search(double lat, double lng, int radius) { ArrayList<Place> resultList = null; HttpURLConnection conn = null; StringBuilder jsonResults = new StringBuilder(); try { StringBuilder sb = new StringBuilder(PLACES_API_BASE); sb.append(TYPE_SEARCH); sb.append(OUT_JSON); sb.append("location=" + String.valueOf(lat) + "," + String.valueOf(lng)); sb.append("&radius=" + String.valueOf(radius)); sb.append("&type=restaurant"); sb.append("&key=" + API_KEY); URL url = new URL(sb.toString()); conn = (HttpURLConnection) url.openConnection(); InputStreamReader in = new InputStreamReader(conn.getInputStream()); int read; char[] buff = new char[1024]; while ((read = in.read(buff)) != -1) { jsonResults.append(buff, 0, read); } } catch (MalformedURLException e) { Log.e(LOG_TAG, "Error processing Places API URL", e); return resultList; } catch (IOException e) { Log.e(LOG_TAG, "Error connecting to Places API", e); return resultList; } finally { if (conn != null) { conn.disconnect(); } } try { // Create a JSON object hierarchy from the results JSONObject jsonObj = new JSONObject(jsonResults.toString()); JSONArray predsJsonArray = jsonObj.getJSONArray("results"); // Extract the descriptions from the results resultList = new ArrayList<Place>(predsJsonArray.length()); for (int i = 0; i < predsJsonArray.length(); i++) { Place place = new Place(); place.reference = predsJsonArray.getJSONObject(i).getString("reference"); place.name = predsJsonArray.getJSONObject(i).getString("name"); resultList.add(place); } } catch (JSONException e) { Log.e(LOG_TAG, "Error processing JSON results", e); } return resultList; } //Value Object for the ArrayList public static class Place { private String reference; private String name; public Place(){ super(); } @Override public String toString(){ return this.name; //This is what returns the name of each restaurant for array list } } }
Вот и все! Теперь мы успешно получили разрешения пользователя, выяснили местоположение пользователя и отобразили рестораны, расположенные для этого пользователя, в виде списка с помощью веб-API Google Place Search. Если вы пытаетесь сделать что-то подобное, надеюсь, это вам поможет. Вот ссылка GitHub на полный проект. Удачного кодирования.