skip to Main Content

I want to show the list of nearby hospitals, but I cannot get the data from Google Maps.
(But when I use the API key of the user from where I have learned to display the map in android, I am able to get the data.)

Things I have already done:

  1. Enable Map API and place API from google cloud console
  2. Setup billing account

Code
XML file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:background="@color/white"
    android:orientation="vertical"
    android:weightSum="10">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimaryDark"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/imageDrawer"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:contentDescription="@string/app_name"
            android:gravity="center_vertical"
            android:src="@drawable/back_arrows" />

        <TextView
            android:id="@+id/textTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_24sdp"
            android:background="@drawable/title_stroke"
            android:fontFamily="@font/ubuntu_bold"
            android:gravity="center_vertical"
            android:paddingStart="@dimen/_8sdp"
            android:paddingTop="@dimen/_2sdp"
            android:paddingEnd="@dimen/_8sdp"
            android:paddingBottom="@dimen/_2sdp"
            android:text="@string/nearby"
            android:textColor="@color/white"
            android:textSize="@dimen/_16ssp" />
    </androidx.appcompat.widget.Toolbar>

    <fragment
        android:id="@+id/googleMap"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="5"
        tools:ignore="FragmentTagUsage" />

    <ListView
        android:id="@+id/centersListView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="5" />

</LinearLayout>

Java Class

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.ListView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.FragmentActivity;

import com.aaienafit.R;
import com.aaienafit.databinding.ActivityDoctorBinding;
import com.aaienafit.utils.ProgressDialog;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class DoctorActivity extends FragmentActivity implements OnMapReadyCallback {

    ActivityDoctorBinding binding;

    StringBuffer stringBuffer;
    ListView centersListView;
    double latitude, longitude;
    LocationManager locationManager;
    Location location;
    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityDoctorBinding.inflate(LayoutInflater.from(this));
        setContentView(binding.getRoot());

        stringBuffer = new StringBuffer();
        centersListView = findViewById(R.id.centersListView);

        centersListView.setOnItemClickListener((adapterView, view, i, l) -> new AlertDialog.Builder(DoctorActivity.this).setCancelable(true).setTitle(LocationController.detailArrayList.get(i).getHospitalName()).setMessage(LocationController.detailArrayList.get(i).getAddress()).setIcon(R.drawable.marker).show());

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.googleMap);
        if (mapFragment != null) {
            mapFragment.getMapAsync(this);

        }
        getList();


    }


    @Override
    public void onMapReady(@NonNull GoogleMap googleMap) {
        mMap = googleMap;

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            mMap.setMyLocationEnabled(true);
            setUpCameraAndMarkers();
            LatLng latLng = new LatLng(latitude, longitude);
            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11f));
            Objects.requireNonNull(mMap.addMarker(new MarkerOptions().position(latLng))).setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));

        }

    }

    public void updateLoc() {
        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            throw new IllegalArgumentException("No GPS");
        } else if (!isGooglePlayServicesAvailable(this)) {
            throw new IllegalArgumentException("No Google Play Services Available");
        } else getLocation();

    }

    public boolean isGooglePlayServicesAvailable(Context context) {
        GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
        int resultCode = googleApiAvailability.isGooglePlayServicesAvailable(context);
        return resultCode == ConnectionResult.SUCCESS;
    }

    void getLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            try {
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                if (location != null) {
                    Log.d("latitude=>", location.getLatitude() + ", longitude=> " + location.getLongitude());
                    latitude = location.getLatitude();
                    longitude = location.getLongitude();

                }

            } catch (Exception e) {
                Log.d("LOCATION_UPDATE", "getLocation: ");
            }


        }


    }

    protected void fillList() {
        ArrayList<String> placeName = new ArrayList<>();
        for (int i = 0; i < LocationController.detailArrayList.size(); i++) {
            placeName.add(LocationController.detailArrayList.get(i).getHospitalName());
        }


        ArrayList<String> address = new ArrayList<>();
        for (int i = 0; i < LocationController.detailArrayList.size(); i++) {
            address.add(LocationController.detailArrayList.get(i).getAddress());
        }

        PlacesListAdapter placesListAdapter = new PlacesListAdapter(this, placeName, address);
        centersListView.setAdapter(placesListAdapter);
    }

    void loadLocation() {
        try {
            RetrieveFeedTask();
            new Thread(() -> {
                while (stringBuffer.length() == 0) Log.d("Message", "buffer reading");
                LocationController.manipulateData(stringBuffer);
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    void RetrieveFeedTask() {

        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(() -> {

            try {
                String string =
                        "https://maps.googleapis.com/maps/api/place/search/json?rankby=distance&keyword=hospital&location=" +
                                latitude +
                                "," +
                                longitude +
                                "&key=" + getString(R.string.google_api_key) + "&libraries=places";
               

                URL url = new URL(string);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = connection.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuffer buffer = new StringBuffer();

                String n;
                while ((n = bufferedReader.readLine()) != null) {
                    buffer.append(n);
                }

                stringBuffer = buffer;
            } catch (Exception e) {
                Toast.makeText(DoctorActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
            }

        });
    }

    void getList() {
        try {
            updateLoc();
            LocationController.loading = true;
            loadLocation();
            while (LocationController.loading) {
                Log.d("GeometryResponse", "Waiting for response");
            }
            fillList();
        } catch (IllegalArgumentException e) {
            Toast.makeText(DoctorActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
        }
        if (ProgressDialog.isProgressShowing()) {
            ProgressDialog.dismissProgressDialog();
        }
    }

    void setUpCameraAndMarkers() {
        LatLng latLng;
        for (int i = 0; i < LocationController.detailArrayList.size(); i++) {
            latLng = new LatLng(LocationController.detailArrayList.get(i).getGeometry()[0], LocationController.detailArrayList.get(i).getGeometry()[1]);
            mMap.addMarker(new MarkerOptions().position(latLng).title(LocationController.detailArrayList.get(i).getHospitalName()));
            mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        }


    }


}

PlacesListAdapter Class

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.aaienafit.R;

import java.util.ArrayList;

public class PlacesListAdapter extends BaseAdapter {


    private final Context context;
    private final ArrayList<String> placeName;
    private final ArrayList<String> openNowText;


    public PlacesListAdapter(Context context, ArrayList<String> placeName, ArrayList<String> openNowText) {
        this.context = context;
        this.placeName = placeName;
        this.openNowText = openNowText;
    }


    @Override
    public int getCount() {
        return placeName.size();
    }

    @Override
    public Object getItem(int i) {
        return placeName.get(i);
    }

    @Override
    public long getItemId(int i) {
        return 3232;
    }

    @SuppressLint("SetTextI18n")
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {

        if (view == null) view = View.inflate(context, R.layout.doctor_list_item, null);

        TextView placeTextView = view.findViewById(R.id.textDoctorName);
        TextView address = view.findViewById(R.id.textAddress);

        placeTextView.setText(placeName.get(i));
        address.setText(openNowText.get(i));

        return view;
    }
}

HospitalModel Class

import androidx.annotation.NonNull;

import java.util.Arrays;

public class HospitalModel {

    private String hospitalName;
    private String rating;
    private String openingHours;
    private String address;
    private double[] geometry;

    public String getHospitalName() {
        return hospitalName;
    }

    public void setHospitalName(String hospitalName) {
        this.hospitalName = hospitalName;
    }

    public String getRating() {
        return rating;
    }

    public void setRating(String rating) {
        this.rating = rating;
    }

    public String getOpeningHours() {
        return openingHours;
    }

    public void setOpeningHours(String openingHours) {
        this.openingHours = openingHours;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public double[] getGeometry() {
        return geometry;
    }

    public void setGeometry(double[] geometry) {
        this.geometry = geometry;
    }

    @NonNull
    @Override
    public String toString() {
        return "NearbyHospitalsDetail{" +
                ", hospitalName='" + hospitalName + ''' +
                ", rating=" + rating +
                ", openingHours='" + openingHours + ''' +
                ", address='" + address + ''' +
                ", geometry=" + Arrays.toString(geometry) +
                '}';
    }
}

LocationController class

import android.util.Log;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;


public class LocationController {

    public static boolean loading;
    public static ArrayList<HospitalModel> detailArrayList = new ArrayList<>();

    public static void manipulateData(StringBuffer buffer) {
        loading = true;
        try {
            detailArrayList.clear();
            JSONObject object = new JSONObject(buffer.toString());
            JSONArray array = object.getJSONArray("results");
            for (int i = 0; i < array.length(); i++) {
                try {
                    JSONObject jsonObject = array.getJSONObject(i);
                    HospitalModel hospitalsDetail = new HospitalModel();

                    jsonObject.getString("name");
                    hospitalsDetail.setHospitalName(jsonObject.getString("name"));

                    try {
                        hospitalsDetail.setRating(String.valueOf(jsonObject.getDouble("rating")));
                    } catch (Exception e) {
                        hospitalsDetail.setRating("Not Available");
                    }
                    try {
                        if (jsonObject.getJSONObject("opening_hours").getBoolean("open_now"))
                            hospitalsDetail.setOpeningHours("Opened");
                        else hospitalsDetail.setOpeningHours("closed");
                    } catch (Exception e) {
                        hospitalsDetail.setOpeningHours("Not Available");
                    }

                    hospitalsDetail.setAddress(jsonObject.getString("vicinity"));
                    hospitalsDetail.setGeometry(new double[]{jsonObject.getJSONObject("geometry").getJSONObject("location").getDouble("lat"),
                            jsonObject.getJSONObject("geometry").getJSONObject("location").getDouble("lng")});

                    detailArrayList.add(hospitalsDetail);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        loading = false;
        Log.d("Array Loaded with size ", "Size of " + detailArrayList.size());
    }
}

Manifest file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example">
    <!--
         The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
         Google Maps Android API v2, but you must specify either coarse or fine
         location permissions for the "MyLocation" functionality.
    -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission
        android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
    <uses-permission android:name="android.permission.CAMERA" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />

    <queries>
        <intent>
            <action android:name="com.google.android.youtube.api.service.START" />
        </intent>
    </queries>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:requestLegacyExternalStorage="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AaienaFit"
        android:usesCleartextTraffic="true"
        tools:ignore="AllowBackup"
        tools:targetApi="m">
        <activity
            android:name=".activities.youtubePlayer.YoutubePlayerActivity"
            android:configChanges="orientation|screenSize"
            android:noHistory="true" />

        <uses-library
            android:name="org.apache.http.legacy"
            android:required="false" />

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_api_key" />
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity android:name=".activities.doctor.DoctorActivity" />
        <activity
            android:name=".utils.SplashScreen"
            android:noHistory="true"
            android:theme="@style/Splash"
            tools:ignore="IntentFilterExportedReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".activities.authentication.AuthenticationActivity" />
        <activity android:name=".activities.main.MainActivity" />

        <receiver
            android:name=".broadcasts.NotificationBroadcast"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="button_click" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

2

Answers


  1. Try the API endpoint maps/api/place/nearbysearch:

    https://maps.googleapis.com/maps/api/place/nearbysearch/output?parameters
    

    Based on your example code in the "Java class" file, the URL construction would look like this

    "https://maps.googleapis.com/maps/api/place/nearbysearch/json?" +
        "rankby=distance&" +
        "keyword=hospital&" + 
        "location=" + latitude + "," + longitude + "&" +
        "key=" + getString(R.string.google_api_key);
    

    A Quick Sidenote

    I’d highly recommend that you look into StackOverflow’s guide for creating a Minimal, Reproducible Example of your issue. Of the six source files and hundreds of lines of code you posted in your original answer, no more than a few dozen lines were pertinent to the specific task of getting nearby hospital data from Google’s Maps API. Focusing your question and code samples to just the specific issue at hand will make it orders of magnitude easier for volunteers to help answer your question and may even help you discover the answer on your own.

    Login or Signup to reply.
  2. Try this :

    • Outside your app, Test the endpoint on the browser (Firefox/ chrome/ safari e.t.c..), if you get a list of nearby hospitals, move now to your app.

    • On the app, Once you have tested the end point on the browser, now make sure your parameters Required Parameters ( those required to be passed to the endpoint ) actually exist. You can achieve this by placing break points on where you r making the api call / consuming the api , or place break point on he target parameters.

    • if you are able to get values, use this approach to consume the google maps api, or use retrofit.

    If none works kindly reach out.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search