I need help. I have already set up Google Console in the right way, the right API and the right package name and SHA-1 for restricting usage in Android apps and I can see the green checkmark. In other words it worked before, but now the map in Google Map gone, just showing logo, my button and still can detect my LatLong.
My other problem is my Google Map can't show LatLong, my location button, and can't use mark if I turn off GPS. I need to turn ON the GPS outside of the activity. Even I make refresh button but still I need to turn on GPS outside of activity (like before get inside the map activity).
Here is my MapActivity:
public class MapActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private FloatingActionButton fabDone, fabRefresh;
private Location currentLocation;
private boolean gps_enabled = false;
private boolean network_enabled = false;
private Double MyLat, MyLong;
private String kode;
FusedLocationProviderClient fusedLocationProviderClient;
private static final int REQUEST_CODE = 101;
Marker incidentMarker;
Geocoder geo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
Intent intent = getIntent();
kode = intent.getStringExtra("kode");
ActionBar actionBar = getSupportActionBar();
actionBar.setTitle("Map");
fabDone = findViewById(R.id.fab_done);
fabRefresh = findViewById(R.id.fab_refresh);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
geo = new Geocoder(getApplicationContext(), Locale.getDefault());
turnGPSOn();
fetchLocation();
fabRefresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = getIntent();
finish();
startActivity(intent);
}
});
}
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
mMap = googleMap;
LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener locListener = new MyLocationListener();
try {
gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
if (gps_enabled) {
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
currentLocation = locManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
if(network_enabled && currentLocation==null){
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
currentLocation = locManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if (currentLocation != null) {
MyLat = currentLocation.getLatitude();
MyLong = currentLocation.getLongitude();
mMap.setMyLocationEnabled(true);
LatLng latLng = new LatLng(MyLat, MyLong);
mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 12.0f));
} else {
Location loc= getLastKnownLocation(this);
if (loc != null) {
MyLat = loc.getLatitude();
MyLong = loc.getLongitude();
mMap.setMyLocationEnabled(true);
LatLng latLng = new LatLng(MyLat, MyLong);
mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 12.0f));
}
}
locManager.removeUpdates(locListener);
try {
mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
@Override
public void onMapLongClick(LatLng latLng) {
if (incidentMarker != null)
incidentMarker.remove();
MarkerOptions options = new MarkerOptions().position(latLng).title("Incident Location");
try {
Address address = geo.getFromLocation(latLng.latitude, latLng.longitude, 2).get(0);
String addressLine = address.getAddressLine(0); // If any additional
String snippets = addressLine;
Log.d("MAP", snippets);
options.snippet(snippets);
} catch (IOException e) {
e.printStackTrace();
}
incidentMarker = mMap.addMarker(options);
incidentMarker.showInfoWindow();
}
});
fabDone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (incidentMarker == null) {
Toast.makeText(getApplicationContext(), "Points the incident location using Long Click!", Toast.LENGTH_SHORT).show();
return;
} else {
if (kode.equals("1")) {
Intent intent = new Intent(MapActivity.this, AddReportActivity.class);
intent.putExtra("address", incidentMarker.getSnippet());
intent.putExtra("latitude", incidentMarker.getPosition().latitude);
intent.putExtra("longitude", incidentMarker.getPosition().longitude);
startActivity(intent);
finish();//finishing activity
} else if (kode.equals("2")) {
Intent intent = new Intent(MapActivity.this, EditReportActivity.class);
intent.putExtra("address", incidentMarker.getSnippet());
intent.putExtra("latitude", incidentMarker.getPosition().latitude);
intent.putExtra("longitude", incidentMarker.getPosition().longitude);
startActivity(intent);
finish();//finishing activity
}
}
}
});
} catch (Exception e){e.printStackTrace();}
if (gps_enabled && network_enabled && currentLocation!=null){
MyLat = currentLocation.getLatitude();
MyLong = currentLocation.getLongitude();
mMap.setMyLocationEnabled(true);
LatLng latLng = new LatLng(MyLat, MyLong);
mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 12.0f));
} else if (gps_enabled && network_enabled && currentLocation==null){
Toast.makeText(this, "Location can't be found.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Please turn ON the GPS.", Toast.LENGTH_SHORT).show();
}
}
private void fetchLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE);
return;
}
Task<Location> task = fusedLocationProviderClient.getLastLocation();
task.addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
currentLocation = location;
Toast.makeText(getApplicationContext(), currentLocation.getLatitude() "" currentLocation.getLongitude(), Toast.LENGTH_SHORT).show();
SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.fama_map);
assert supportMapFragment != null;
supportMapFragment.getMapAsync(MapActivity.this);
}
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
fetchLocation();
}
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.map_options, menu);
return true;
}
public class MyLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
if (location != null) {
}
}
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
public static Location getLastKnownLocation(Context context) {
Location location = null;
@SuppressLint("WrongConstant") LocationManager locationmanager = (LocationManager)context.getSystemService("location");
List list = locationmanager.getAllProviders();
boolean i = false;
Iterator iterator = list.iterator();
do
{
//System.out.println("---------------------------------------------------------------------");
if(!iterator.hasNext())
break;
String s = (String)iterator.next();
if(i != false && !locationmanager.isProviderEnabled(s))
continue;
@SuppressLint("MissingPermission") Location location1 = locationmanager.getLastKnownLocation(s);
if(location1 == null)
continue;
if(location != null)
{
float f = location.getAccuracy();
float f1 = location1.getAccuracy();
if(f >= f1)
{
long l = location1.getTime();
long l1 = location.getTime();
if(l - l1 <= 600000L)
continue;
}
}
location = location1;
i = locationmanager.isProviderEnabled(s);
// System.out.println("---------------------------------------------------------------------");
} while(true);
return location;
}
public void turnGPSOn(){
try
{
String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if(!provider.contains("gps")){ //if gps is disabled
final Intent poke = new Intent();
poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
sendBroadcast(poke);
}
}
catch (Exception e) {
}
}
// Method to turn off the GPS
public void turnGPSOff(){
String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if(provider.contains("gps")){ //if gps is enabled
final Intent poke = new Intent();
poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
sendBroadcast(poke);
}
}
// turning off the GPS if its in on state. to avoid the battery drain.
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
turnGPSOff();
}
}
CodePudding user response:
I Think this will help you. First see the package name is same you register on console
build.gradle
// google map services
implementation 'com.google.android.gms:play-services-maps:17.0.1'
// location play services
implementation 'com.google.android.gms:play-services-location:18.0.0'
// dexter runtime permissions
implementation 'com.karumi:dexter:4.2.0'
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
Java MapsActivity.java
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
TextView txtLocationResult;
TextView txtUpdatedOn;
Button btnStartUpdates;
Button btnStopUpdates;
// location last updated time
private String mLastUpdateTime;
// location updates interval - 10sec
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
// fastest updates interval - 5 sec
// location updates will be received if another app is requesting the locations
// than your app can handle
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 3000;
private static final int REQUEST_CHECK_SETTINGS = 100;
// bunch of location related apis
private FusedLocationProviderClient mFusedLocationClient;
private SettingsClient mSettingsClient;
private LocationRequest mLocationRequest;
private LocationSettingsRequest mLocationSettingsRequest;
private LocationCallback mLocationCallback;
private Location mCurrentLocation;
private MarkerOptions marker;
private ArrayList<LatLng> locList;
// boolean flag to toggle the ui
private Boolean mRequestingLocationUpdates;
private String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
locList = new ArrayList();
marker = new MarkerOptions();
initViews();
initValues();
onClickMethod();
// restore the values from saved instance state
restoreValuesFromBundle(savedInstanceState);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
LatLng islamabad = new LatLng(33.684422, 73.047882);
mMap.setMinZoomPreference(15.0f);
mMap.setMaxZoomPreference(20.0f);
marker.position(islamabad);
mMap.addMarker(marker);
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(islamabad, 17F));
}
private void mapDrawLocation(LatLng loc){
mMap.clear();
marker.position(loc);
mMap.addMarker(marker);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(loc, 17F));
}
private void initViews(){
txtLocationResult = findViewById(R.id.location_result);
txtUpdatedOn = findViewById(R.id.updated_on);
btnStartUpdates = findViewById(R.id.btn_start_location_updates);
btnStopUpdates = findViewById(R.id.btn_stop_location_updates);
}
private void onClickMethod(){
btnStartUpdates.setOnClickListener(view -> {
startLocationButtonClick();
});
btnStopUpdates.setOnClickListener(view -> {
stopLocationButtonClick();
});
}
private void initValues() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mSettingsClient = LocationServices.getSettingsClient(this);
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
// location is received
mCurrentLocation = locationResult.getLastLocation();
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
};
mRequestingLocationUpdates = false;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
/**
* Restoring values from saved instance state
*/
private void restoreValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("is_requesting_updates")) {
mRequestingLocationUpdates = savedInstanceState.getBoolean("is_requesting_updates");
}
if (savedInstanceState.containsKey("last_known_location")) {
mCurrentLocation = savedInstanceState.getParcelable("last_known_location");
}
if (savedInstanceState.containsKey("last_updated_on")) {
mLastUpdateTime = savedInstanceState.getString("last_updated_on");
}
}
updateLocationUI();
}
/**
* Update the UI displaying the location data
* and toggling the buttons
*/
private void updateLocationUI() {
if (mCurrentLocation != null) {
txtLocationResult.setText(
"Lat: " mCurrentLocation.getLatitude() ", "
"Lng: " mCurrentLocation.getLongitude()
);
mapDrawLocation(new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()));
// giving a blink animation on TextView
txtLocationResult.setAlpha(0);
txtLocationResult.animate().alpha(1).setDuration(300);
// location last updated time
txtUpdatedOn.setText("Last updated on: " mLastUpdateTime);
}
toggleButtons();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("is_requesting_updates", mRequestingLocationUpdates);
outState.putParcelable("last_known_location", mCurrentLocation);
outState.putString("last_updated_on", mLastUpdateTime);
}
private void toggleButtons() {
if (mRequestingLocationUpdates) {
btnStartUpdates.setEnabled(false);
btnStopUpdates.setEnabled(true);
} else {
btnStartUpdates.setEnabled(true);
btnStopUpdates.setEnabled(false);
}
}
/**
* Starting location updates
* Check whether location settings are satisfied and then
* location updates will be requested
*/
private void startLocationUpdates() {
mSettingsClient
.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@SuppressLint("MissingPermission")
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.i(TAG, "All location settings are satisfied.");
Toast.makeText(getApplicationContext(), "Started location updates!", Toast.LENGTH_SHORT).show();
//noinspection MissingPermission
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.myLooper());
updateLocationUI();
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade "
"location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(MapsActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sie) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
String errorMessage = "Location settings are inadequate, and cannot be "
"fixed here. Fix in Settings.";
Log.e(TAG, errorMessage);
Toast.makeText(MapsActivity.this, errorMessage, Toast.LENGTH_LONG).show();
}
updateLocationUI();
}
});
}
public void startLocationButtonClick() {
// Requesting ACCESS_FINE_LOCATION using Dexter library
Dexter.withActivity(this)
.withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.withListener(new PermissionListener() {
@Override
public void onPermissionGranted(PermissionGrantedResponse response) {
mRequestingLocationUpdates = true;
startLocationUpdates();
}
@Override
public void onPermissionDenied(PermissionDeniedResponse response) {
if (response.isPermanentlyDenied()) {
// open device settings when the permission is
// denied permanently
openSettings();
}
}
@Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
token.continuePermissionRequest();
}
}).check();
}
public void stopLocationButtonClick() {
mRequestingLocationUpdates = false;
stopLocationUpdates();
}
public void stopLocationUpdates() {
// Removing location updates
mFusedLocationClient
.removeLocationUpdates(mLocationCallback)
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
Toast.makeText(getApplicationContext(), "Location updates stopped!", Toast.LENGTH_SHORT).show();
toggleButtons();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
Log.e(TAG, "User agreed to make required location settings changes.");
// Nothing to do. startLocationupdates() gets called in onResume again.
break;
case Activity.RESULT_CANCELED:
Log.e(TAG, "User chose not to make required location settings changes.");
mRequestingLocationUpdates = false;
break;
}
break;
}
}
private void openSettings() {
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
@Override
public void onResume() {
super.onResume();
// Resuming location updates depending on button state and
// allowed permissions
if (mRequestingLocationUpdates && checkPermissions()) {
startLocationUpdates();
}
updateLocationUI();
}
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
}
@Override
protected void onPause() {
super.onPause();
if (mRequestingLocationUpdates) {
// pausing location updates
stopLocationUpdates();
}
}
}
activity_maps.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<fragment
android:id="@ id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:context=".MapsActivity"
map:layout_constraintBottom_toTopOf="@ id/bottom_panel"
map:layout_constraintTop_toTopOf="parent"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@ id/bottom_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
map:layout_constraintBottom_toBottomOf="parent"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintEnd_toEndOf="parent"
>
<TextView
android:id="@ id/location_result"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textColor="#333"
android:textSize="18sp"
android:gravity="center"
android:text="Lat: 0.0, Lng: 0.0"
android:layout_gravity="center"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@ id/updated_on"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textSize="12sp"
android:gravity="center"
android:layout_gravity="center"
android:text="Last updated on: "
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintTop_toBottomOf="@ id/location_result"
/>
<Button
android:id="@ id/btn_start_location_updates"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="START LOCATION"
map:layout_constraintTop_toBottomOf="@ id/updated_on"
map:layout_constraintBottom_toBottomOf="parent"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintEnd_toStartOf="@ id/btn_stop_location_updates"
/>
<Button
android:id="@ id/btn_stop_location_updates"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:enabled="false"
android:text="STOP LOCATION"
map:layout_constraintTop_toBottomOf="@ id/updated_on"
map:layout_constraintStart_toEndOf="@ id/btn_start_location_updates"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
CodePudding user response:
I Think this will help you. First see the package name is same you register on console
build.gradle
// google map services
implementation 'com.google.android.gms:play-services-maps:17.0.1'
// location play services
implementation 'com.google.android.gms:play-services-location:18.0.0'
// dexter runtime permissions
implementation 'com.karumi:dexter:4.2.0'
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
Kotlin MapsActivity.kt
import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.content.IntentSender
import android.content.pm.PackageManager
import android.location.Location
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Looper
import android.provider.Settings
import android.util.Log
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.location.*
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.*
import com.karumi.dexter.BuildConfig
import com.karumi.dexter.Dexter
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionDeniedResponse
import com.karumi.dexter.listener.PermissionGrantedResponse
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.single.PermissionListener
import java.text.DateFormat
import java.util.*
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
// location last updated time
private var mLastUpdateTime: String? = null
// location updates interval - 10sec
private val UPDATE_INTERVAL_IN_MILLISECONDS: Long = 10000
// fastest updates interval - 5 sec
// location updates will be received if another app is requesting the locations
// than your app can handle
private val FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS: Long = 3000
private val REQUEST_CHECK_SETTINGS = 100
private val TAG = "MainActivity"
private lateinit var mMap: GoogleMap
// bunch of location related apis
private var mFusedLocationClient: FusedLocationProviderClient? = null
private var mSettingsClient: SettingsClient? = null
private var mLocationRequest: LocationRequest? = null
private var mLocationSettingsRequest: LocationSettingsRequest? = null
private var mLocationCallback: LocationCallback? = null
private var mCurrentLocation: Location? = null
// boolean flag to toggle the ui
private var mRequestingLocationUpdates: Boolean? = null
private lateinit var txtLocationResult: TextView
private lateinit var txtUpdatedOn: TextView
private lateinit var btnStartUpdates: Button
private lateinit var btnStopUpdates: Button
private var marker:MarkerOptions? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
// initialize the necessary libraries
initViews()
initValues()
onClickMethod()
// restore the values from saved instance state
restoreValuesFromBundle(savedInstanceState)
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
// Add a marker in Sydney and move the camera
val islamabad = LatLng(33.684422, 73.047882)
mMap.setMinZoomPreference(15.0f)
mMap.setMaxZoomPreference(20.0f)
marker?.position(islamabad)
mMap.addMarker(marker!!)
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(islamabad, 17F))
}
private fun mapDrawLocation(loc:LatLng){
mMap.clear()
marker?.position(loc)
mMap.addMarker(marker!!)
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(loc, 17F))
}
private fun initViews(){
txtLocationResult = findViewById(R.id.location_result)
txtUpdatedOn = findViewById(R.id.updated_on)
btnStartUpdates = findViewById(R.id.btn_start_location_updates)
btnStopUpdates = findViewById(R.id.btn_stop_location_updates)
}
private fun initValues() {
marker = MarkerOptions()
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
mSettingsClient = LocationServices.getSettingsClient(this)
mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
// location is received
mCurrentLocation = locationResult.lastLocation
mLastUpdateTime = DateFormat.getTimeInstance().format(Date())
updateLocationUI()
}
}
mRequestingLocationUpdates = false
mLocationRequest = LocationRequest.create().apply {
interval = UPDATE_INTERVAL_IN_MILLISECONDS
fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
isWaitForAccurateLocation = true
}
val builder = LocationSettingsRequest.Builder()
builder.addLocationRequest(mLocationRequest!!)
mLocationSettingsRequest = builder.build()
}
private fun onClickMethod(){
btnStartUpdates.setOnClickListener {
startLocationButtonClick()
}
btnStopUpdates.setOnClickListener {
stopLocationButtonClick()
}
}
/**
* Restoring values from saved instance state
*/
private fun restoreValuesFromBundle(savedInstanceState: Bundle?) {
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("is_requesting_updates")) {
mRequestingLocationUpdates = savedInstanceState.getBoolean("is_requesting_updates")
}
if (savedInstanceState.containsKey("last_known_location")) {
mCurrentLocation = savedInstanceState.getParcelable("last_known_location")
}
if (savedInstanceState.containsKey("last_updated_on")) {
mLastUpdateTime = savedInstanceState.getString("last_updated_on")
}
}
updateLocationUI()
}
/**
* Update the UI displaying the location data
* and toggling the buttons
*/
@SuppressLint("SetTextI18n")
private fun updateLocationUI() {
if (mCurrentLocation != null) {
txtLocationResult.text = "Lat: " mCurrentLocation!!.latitude ", "
"Lng: " mCurrentLocation!!.longitude
mapDrawLocation(LatLng(mCurrentLocation!!.latitude, mCurrentLocation!!.longitude))
// giving a blink animation on TextView
txtLocationResult.alpha = 0f
txtLocationResult.animate().alpha(1f).duration = 300
// location last updated time
txtUpdatedOn.text = "Last updated on: $mLastUpdateTime"
}
toggleButtons()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean("is_requesting_updates", (mRequestingLocationUpdates)!!)
outState.putParcelable("last_known_location", mCurrentLocation)
outState.putString("last_updated_on", mLastUpdateTime)
}
private fun toggleButtons() {
if ((mRequestingLocationUpdates)!!) {
btnStartUpdates.isEnabled = false
btnStopUpdates.isEnabled = true
} else {
btnStartUpdates.isEnabled = true
btnStopUpdates.isEnabled = false
}
}
/**
* Starting location updates
* Check whether location settings are satisfied and then
* location updates will be requested
*/
private fun startLocationUpdates() {
mSettingsClient
?.checkLocationSettings(mLocationSettingsRequest!!)
?.addOnSuccessListener(this) {
Log.i(TAG, "All location settings are satisfied.")
showMessage("Started location updates!")
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
}
mFusedLocationClient!!.requestLocationUpdates(
mLocationRequest!!,
mLocationCallback!!, Looper.myLooper()!!
)
updateLocationUI()
}
?.addOnFailureListener(this) { e ->
val statusCode = (e as ApiException).statusCode
when (statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
Log.i(
TAG,
"Location settings are not satisfied. Attempting to upgrade "
"location settings "
)
try {
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
val rae = e as ResolvableApiException
rae.startResolutionForResult(
this,
REQUEST_CHECK_SETTINGS
)
} catch (sie: IntentSender.SendIntentException) {
Log.i(
TAG,
"PendingIntent unable to execute request."
)
}
}
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
val errorMessage = "Location settings are inadequate, and cannot be "
"fixed here. Fix in Settings."
Log.e(TAG, errorMessage)
}
}
updateLocationUI()
}
}
private fun startLocationButtonClick() {
// Requesting ACCESS_FINE_LOCATION using Dexter library
Dexter.withActivity(this)
.withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.withListener(object : PermissionListener {
override fun onPermissionGranted(response: PermissionGrantedResponse?) {
mRequestingLocationUpdates = true
startLocationUpdates()
}
override fun onPermissionDenied(response: PermissionDeniedResponse) {
if (response.isPermanentlyDenied) {
// open device settings when the permission is
// denied permanently
openSettings()
}
}
override fun onPermissionRationaleShouldBeShown(
permission: PermissionRequest?,
token: PermissionToken
) {
token.continuePermissionRequest()
}
}).check()
}
private fun stopLocationButtonClick() {
mRequestingLocationUpdates = false
stopLocationUpdates()
}
private fun stopLocationUpdates() {
// Removing location updates
mFusedLocationClient
?.removeLocationUpdates(mLocationCallback!!)
?.addOnCompleteListener(this) {
showMessage("Location updates stopped!")
toggleButtons()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_CHECK_SETTINGS -> when (resultCode) {
RESULT_OK -> Log.e(
TAG,
"User agreed to make required location settings changes."
)
RESULT_CANCELED -> {
Log.e(
TAG,
"User chose not to make required location settings changes."
)
mRequestingLocationUpdates = false
}
}
}
}
override fun onResume() {
super.onResume()
// Resuming location updates depending on button state and
// allowed permissions
if ((mRequestingLocationUpdates)!! && checkPermissions()) {
startLocationUpdates()
}
updateLocationUI()
}
private fun checkPermissions(): Boolean {
val permissionState = ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
return permissionState == PackageManager.PERMISSION_GRANTED
}
override fun onPause() {
super.onPause()
if ((mRequestingLocationUpdates)!!) {
// pausing location updates
stopLocationUpdates()
}
}
private fun openSettings() {
val intent = Intent()
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
val uri = Uri.fromParts(
"package",
BuildConfig.APPLICATION_ID, null
)
intent.data = uri
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
private fun showMessage(message:String){
Toast.makeText(this,message,Toast.LENGTH_SHORT).show()
}
}
activity_maps.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<fragment
android:id="@ id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:context=".MapsActivity"
map:layout_constraintBottom_toTopOf="@ id/bottom_panel"
map:layout_constraintTop_toTopOf="parent"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@ id/bottom_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
map:layout_constraintBottom_toBottomOf="parent"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintEnd_toEndOf="parent"
>
<TextView
android:id="@ id/location_result"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textColor="#333"
android:textSize="18sp"
android:gravity="center"
android:text="Lat: 0.0, Lng: 0.0"
android:layout_gravity="center"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@ id/updated_on"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textSize="12sp"
android:gravity="center"
android:layout_gravity="center"
android:text="Last updated on: "
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintTop_toBottomOf="@ id/location_result"
/>
<Button
android:id="@ id/btn_start_location_updates"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="START LOCATION"
map:layout_constraintTop_toBottomOf="@ id/updated_on"
map:layout_constraintBottom_toBottomOf="parent"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintEnd_toStartOf="@ id/btn_stop_location_updates"
/>
<Button
android:id="@ id/btn_stop_location_updates"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:enabled="false"
android:text="STOP LOCATION"
map:layout_constraintTop_toBottomOf="@ id/updated_on"
map:layout_constraintStart_toEndOf="@ id/btn_start_location_updates"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>