I've tried to make an app that has a map activity that as soon as it is opened , the map starts on the users current location. I tried to use guides and help online but it seems that all of these guides are outdated because they have the onResume and onStart method by default in the maps activity and instead i have the onMapReady method and none of these methods. this is the code that i tried writing but it does not work(app crashes),
package com.imt.civilwatch;
import android.content.pm.PackageManager;
import android.location.Location;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
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.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.text.StringCharacterIterator;
public class MapActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private GoogleMap mMap;
protected GoogleApiClient mGoogleApiClient;
Location mLastLocation;
private double mLatitudeText;
private double mLongitudeText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
// 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);
}
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(32, 35);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
//mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
#Override
public void onConnected(Bundle connectionHint) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.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;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
mLatitudeText = (Double.valueOf(mLastLocation.getLatitude()));
mLongitudeText = (Double.valueOf(mLastLocation.getLongitude()));
LatLng last = new LatLng( mLatitudeText,mLongitudeText);
mMap.moveCamera(CameraUpdateFactory.newLatLng(last));
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
From the documentation of Google Maps Android API, the location data available to an Android device includes the current location of the device pinpointed using a combination of technologies - the direction and method of movement, and whether the device has moved across a predefined geographical boundary, or geofence.
Depending upon the needs of your application, you can choose between these options:
Using My Location layer that provides a simple way to display the
device's location on the map. It does not provide data.
Using Google Play services Location
API is
recommended for all programmatic requests for location data.
And using the
LocationSource
interface allows you to provide a custom location provider.
For more information, check this tutorial on how to get the current location:
How to get current location in Android Google Map
Google Map Tutorial in Android Studio: How to get current location in Android Google Map
The method onMapReady runs when the map's fragment is ready and displaying the map.
The onConnected method runs when the device successfully connects with Google Play Location service and (if available) gets your last known location.
If you don't want the camera moving to your current location, delete whats between this condition:
if(mLastLocation != null){...}
For maps, the camera is what's visible on screen. The method mMap.moveCamera(...) tells Map to center the view at specific LatLng.
If your map is ready before your phone connects with Google Play Location API, the current location visible will be this:
if (mLastLocation != null) {
mLatitudeText = (Double.valueOf(mLastLocation.getLatitude()));
mLongitudeText = (Double.valueOf(mLastLocation.getLongitude()));
LatLng last = new LatLng( mLatitudeText,mLongitudeText);
mMap.moveCamera(CameraUpdateFactory.newLatLng(last));
}
Hope I was clear.
See the CameraFactory docs to learn about camera manipulation on Maps: https://developers.google.com/android/reference/com/google/android/gms/maps/CameraUpdateFactory
Bro You Need The GoogleApiClient and LocationRequest for this , and also in manifest two users permission that are "ACCESS FINE LOCATION AND ACCESS COARSE LOCATION" and in order to get the current Location You need to do such something like this:
Include This in Manifest:-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
--> And Current Location Code in Acticity will be like this:
--> Create These Two Variables Globely in the Activity:
GoogleApiClient mGoogleapiClient;
LocationRequest mUserLocationRequest;
--> Then Come To the #override Onconnected() and do like this :-
#Override
public void onConnected(Bundle bundle) {
mUserLocationRequest = LocationRequest.create();
/* Priority = High so that more Correct User Location will be Accessed
up to date information ot highest information get*/
/* Priority = Low if you Don't Want The Exect Location Of The User */
mUserLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
/*For every 1 min I have to Fetch My User Location*/
mUserLocationRequest.setInterval(1000);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleapiClient, mUserLocationRequest, (LocationListener) MainActivity.this);
}
--> Now Impelents The LocationListener in Activity which implents the Method onLocationChanged(): and do such stuff in this , that will give you up to date info whenever user changes its Location:-
#Override
public void onLocationChanged(Location location) {
if (location == null)
{
Toast.makeText(this, "Sorry We Can't able to Get Your Current Location", Toast.LENGTH_SHORT).show();
}
else
{
LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude());
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(latLng,15);
mGoogleMap.animateCamera(update);
}
}
Related
I'm using android studio to create an app, and so I implemented the google maps into my application and everything is working fine, all the implementation are there I triple checked, everything needed for it to operate is there, but my problem is that when I close my application for a long time and reopen the maps activity the fragment showing to me is a random one, no markers no locate button no objects just an empty map with the name of the countries. So I open the google maps application(official application) and close it, then try to reopen my google maps activity and everything reverts to normal, markers showing images are displayed, all the functions operate normally can someone tell me what may be the problem keep in mind everything is added, from an API key to the implementations in the graddle.app and the graddle.app.appname , and in the manifest the metadata is added and so on...thank you !
this is my map activity code where I added some NGOs locations and their images on the map:
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.Bundle;
import android.widget.Toast;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
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.internal.ICameraUpdateFactoryDelegate;
import com.google.android.gms.maps.model.BitmapDescriptor;
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 com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
public class map_act extends FragmentActivity implements OnMapReadyCallback {
Location currentLocation;
FusedLocationProviderClient fusedLocationProviderClient;
private static final int REQUEST_CODE = 101;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
fetchLastLocation();
}
private void fetchLastLocation() {
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(), "Your current location", Toast.LENGTH_SHORT).show();
SupportMapFragment supportMapFragment = (SupportMapFragment)
getSupportFragmentManager().findFragmentById(R.id.google_map);
supportMapFragment.getMapAsync(map_act.this);
}
}
});
}
#Override
public void onMapReady(GoogleMap googleMap) {
LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
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;
}
googleMap.setMyLocationEnabled(true);
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng,12));
LatLng Unicef1 = new LatLng(33.887837297007835, 35.50965848465925 );
googleMap.addMarker(new MarkerOptions().position(Unicef1).title("Unicef")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.unicef1)));
LatLng Unicef2 = new LatLng(33.8865888125746, 35.48744276242378 );
googleMap.addMarker(new MarkerOptions().position(Unicef2).title("Unicef")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.unicef1)));
LatLng Unicef3 = new LatLng( 34.42414282398606, 35.82587499823564 );
googleMap.addMarker(new MarkerOptions().position(Unicef3).title("Unicef")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.unicef1)));
LatLng Unicef4 = new LatLng(33.27906495185468, 35.215073956249924 );
googleMap.addMarker(new MarkerOptions().position(Unicef4).title("Unicef")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.unicef1)));
LatLng Wvision1 = new LatLng(33.86913267946954, 35.576261865395736 );
googleMap.addMarker(new MarkerOptions().position(Wvision1).title("World Vision")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.worldvision1)));
LatLng Wvision2 = new LatLng(33.852201737887476, 35.57339217195826 );
googleMap.addMarker(new MarkerOptions().position(Wvision2).title("World vision")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.worldvision1)));
LatLng Drc = new LatLng(33.892777808313056, 35.52051074415333 );
googleMap.addMarker(new MarkerOptions().position(Drc).title("Danish Refugee Council")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.drc1)));
LatLng Nrc = new LatLng(33.897930365217256, 35.493069449639805 );
googleMap.addMarker(new MarkerOptions().position(Nrc).title("Norwegian Refugee Council")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.nrc1)));
LatLng Oxfam1 = new LatLng(33.88743623998913, 35.50865875340152 );
googleMap.addMarker(new MarkerOptions().position(Oxfam1).title("OXFAM")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.oxfam1)));
LatLng Oxfam2 = new LatLng(33.8484475255134, 35.91956548906049 );
googleMap.addMarker(new MarkerOptions().position(Oxfam2).title("OXFAM")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.oxfam1)));
LatLng Oxfam3 = new LatLng(34.42224203429102, 35.827192870916654);
googleMap.addMarker(new MarkerOptions().position(Oxfam3).title("OXFAM")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.oxfam1)));
LatLng Wfp = new LatLng(33.89447500501417, 35.50479228624766);
googleMap.addMarker(new MarkerOptions().position(Wfp).title("World Food Programme")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.wfp1)));
LatLng Unhcr = new LatLng(33.897930365217256, 35.501776697895714);
googleMap.addMarker(new MarkerOptions().position(Unhcr).title("United Nations High Commissioner for Refugees")
.icon(BitmapFromVector(getApplicationContext(), R.drawable.unhcr1)));
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode){
case REQUEST_CODE:
if(grantResults.length>0 && grantResults[0]== PackageManager.PERMISSION_GRANTED){
fetchLastLocation();
}
break;
}
}
private BitmapDescriptor BitmapFromVector(Context context, int vectorResId) {
// below line is use to generate a drawable.
Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorResId);
// below line is use to set bounds to our vector drawable.
vectorDrawable.setBounds(1, 1, vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight());
// below line is use to create a bitmap for our
// drawable which we have added.
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
// below line is use to add bitmap in our canvas.
Canvas canvas = new Canvas(bitmap);
// below line is use to draw our
// vector drawable in canvas.
vectorDrawable.draw(canvas);
// after generating our bitmap we are returning our bitmap.
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
}
here's my manifest code related to maps:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
In my build.graddle code I added :
google()
jcenter()
and here's my build.graddle.appname code:
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
implementation "com.google.android.gms:play-services-maps:$googlePlayVersion"
implementation "com.google.android.gms:play-services-location:$googlePlayVersion"
So it turns out everything's coded right but there's one step that I didn't know of, I should've went into the google cloud platform and enabled the google maps SDK for my API key, so I went and did that and then redownloaded the google-services.json from the firebase (back-end I'm using) and replaced the old one in my app's folder with the new .json file. What was happening is that my API key added was not enabled for external use so when I was opening my google maps application(the official app) my App's API key was substituted by the google maps official one, and that's why my application's app wasn't functioning unless I open the google maps official application and then close it. So I did that and everything's working fine.
My issue: I am attempting to create an app that can be used university wide. It requires constant access to location. I followed a tutorial online and completed the code underneath. This code works perfectly for my android emulator, but does not work on my device. I get the permission request on my device, but nothing gets updated. Now, the strange thing is, if I use a mock location app on my device, this app DOES work. But only with the mock location app.
Does anyone have any suggestions on how to fix this?
(The xml file is just a single textview. Like i said, I was just testing this first)
package com.example.dylan.locationexample;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private LocationManager locationManager;
private LocationListener locationListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationManager = (LocationManager) this.getSystemService(LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.d("Location: ", location.toString());
TextView tv = findViewById(R.id.textView);
tv.setText(tv.getText() + Double.toString(location.getLatitude()) + "\t" + Double.toString(location.getLongitude()) + "\n");
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_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.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}else{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
}
}
Please ensure you have the following in the manifest
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
And enable gps on your physical device.
If you still face the problem, check the permission settings on your mobile phone for the app. You may have denied permission to access location.
Here is my code am using:
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
com.google.android.gms.location.LocationListener mLocationListener = new com.google.android.gms.location.LocationListener() {
#Override
public void onLocationChanged(final Location location) {
listener.onLocation(location);
}
};
if(location != null) {
listener.onLocation(location);
}else{
locationListener = new android.location.LocationListener() {
#Override
public void onLocationChanged(Location location) {
listener.onLocation(location);
locationManager.removeUpdates(locationListener);
Log.d(TAG,"Location: " + String.valueOf(location.getLongitude()));
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
I'm actually experiencing the same thing and I found a solution to make it work on the physical device. Disable the WI-FI connection and it works. Idk how or why it works though. Now I just opened back the WI-Fi connection and it's working again. If the Wi-fi thing doesn't work for you try restarting the device.
You might also need to wait for a bit before it starts getting the location while moving around the house so it constantly changes.
I made a simple app with geolocation that displays current location of the user in text views, like latitude, longitude and with Geocoder cityname countryname postal-code, etc.
Everything works perfectly in the emulator but for some reason the location doesn't get retrieved in my mobile.
The emulator is running android 7.1 and my mobile is running android 7.0 but that should not be a problem because I made the app with 6.0 marshmallow in mind.
Here is the code
"Mainactivity"
package com.example.slimshady.LocationInfoApp;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
LocationManager locationManager;
LocationListener locationListener;
Geocoder geocoder;
TextView latitude, longitude, city, postcode, country;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
latitude = (TextView)findViewById(R.id.latitude);
longitude = (TextView) findViewById(R.id.longitude);
city = (TextView)findViewById(R.id.city);
postcode = (TextView)findViewById(R.id.postcode);
country = (TextView)findViewById(R.id.country);
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
updateLocationInfo(location);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
// asking permission starts here
if (Build.VERSION.SDK_INT < 23){
// api level lower than 23 so no need to ask for permission
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,0, locationListener);
}
catch (SecurityException e){
e.printStackTrace();
}
}
else {
// api level greater than or equal to 23 checking if has permission if not VVVV this condition
// means go ask for permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0);
}
else{
// means api level greater than or equal to 23 and already has permission
// so no need to go out and ask for permission
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,0, locationListener);
// last known location because we went to this part means we have been here before
Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLocation != null) {
updateLocationInfo(lastKnownLocation);
}
}
}
// asking permission ends here
}
public void updateLocationInfo(Location location) {
geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
try {
List<Address> locationAddress = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(),1);
if (locationAddress != null && locationAddress.size() > 0) {
latitude.setText("Latitude: "+String.valueOf(locationAddress.get(0).getLatitude()));
longitude.setText("Longitude: "+String.valueOf(locationAddress.get(0).getLongitude()));
city.setText("City: "+String.valueOf(locationAddress.get(0).getLocality()));
postcode.setText("Post Code: "+String.valueOf(locationAddress.get(0).getPostalCode()));
country.setText("Country: "+String.valueOf(locationAddress.get(0).getCountryName()));
}
}
catch (Exception e){
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
startListening();
}
}
public void startListening(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,0, locationListener);
}
}
}
The code is simple and basic, everything should work fine but for some reason it doesn't.
I mean the GPS receiver in my physical device works with google-maps so I know its not broken.
See it works in the emulator fine
But the same code does not work on my mobile and I have added all the permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET"/>
See the same app doesn't work on my physical device, this is a screenshot from my physical device
As you see the location is on and I have granted permission when asked in the popup.
And last but not least to show that the GPS receiver works and is not damaged in my physical device.
Screenshot of me using google maps
I circled in red the GPS on and that maps can get my GPS location
If you are using released apk in physical device then you have to add SHA1 for release apk in restriction section of Google API console . I think it helps .
If not, then please show your logcat error by debugging app in physical device.
There are multiple ways that your device can locate itself. These are frequently confused as "GPS" when they are not.
GPS (Global Positioning System) This is a Global Navigation Satellite System (GNSS) which relies on signals from an orbiting constellation of satellites to locate the device. GPS specifically refers to the constellation of satellites deployed by the United States Department of Defense. Alternatives include GLONASS (Russian) and Galileo (European).
Network This uses WiFi or Bluetooth signals to locate your device. The device scans for transmitters IDs, then sends those IDs to a server over its internet connection to lookup in a database. The server responds with a location.
Your code currently uses only LocationManager.GPS_PROVIDER, which uses only satellites to locate your device. Google Maps may be using Network location, which can still work when GPS is disabled.
I suspect you need to either:
Add LocationManager.NETWORK_PROVIDER
or
Enable GPS on your device. This is somewhere under Settings and Location.
I resolved issue like yours totally removed location manager, and make all location work based on FusedLocationProviderClient, also I was have some strange bug on samsung s8 with LocationSettingsRequest that can start default dialog to turn on gps, it was worked with bugs but after removing locationManager.requestLocationUpdates it works perfectlly with fused.
I am trying to get the current location coordinates in longitude and latitude. Here is my code so far:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
MyLocationListener myLocationListener = new MyLocationListener();
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;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, myLocationListener);
}
}
and this class too:
public class MyLocationListener implements LocationListener {
private static final String TAG = "COORDINATES: ";
#Override
public void onLocationChanged(Location location) {
if(location != null){
Log.e(TAG, "Latitude: " + location.getLatitude());
Log.e(TAG, "Longitude: " + location.getLongitude());
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
When I run the app in emulator, I don't get any log message with coordinates. Any suggestions?
The best approach is to use the latest FusedLocationApi provided by Google Play Services library.
If you want to use the old approach, that is fine but you might not get very accurate results.
Either way, make sure you have enabled internet permission, either COARSE_LOCATION or FINE_LOCATION or both in your android manifest.
Also, if you have android 6.0, remember you must request runtime permissions or it won't work for you!
I answered a similar question yesterday and you can find here -which works;
There is also a link to a sample code for FusedLocationApi here.
I hope this helps you and good luck!
UPDATE
You can add Google Play Services to your build.gradle like this:
compile 'com.google.android.gms:play-services:9.2.'
But if you are only interested in one service like location, you can be specific:
compile 'com.google.android.gms:play-services-location:9.2.1'
NOTE
I would highly discourage you from getting user location on your UI thread because it will destroy user experience in the long run! Use a separate thread!!
You have to mimic the location in Emulator. You can do that by accessing the Android Device Manager and Select Emulator Control tab and send the locations to Emulator.
This question is directly related to the same prevailing stackoverflow question at "Android: get current location of user without using gps or internet" where the accepted answer is actually not answering the question.
I should be able to get the current location name (eg:city name, village name) of the device via network provider not with GPS or internet.
Following is the accepted answer in that question. (The following code parts should be included in the onCreate() method)
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
I changed the above code given in the linked answer as following but no success.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView txtView = (TextView) findViewById(R.id.tv1);
txtView.setText("ayyo samitha");
////
// Acquire a reference to the system Location Manager
LocationManager locationManager;
locationManager= (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
private void makeUseOfNewLocation(Location location) {
txtView.setText("sam came in");
txtView.append(location.toString());
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {
// makeUseOfNewLocation(location);
}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
}
How to accomplish what I want by correcting above code or any other method? Note that I want to get the location name, but not the longitudes and latitudes. Can somebody please help me.
What you are referring to here (showing location name on older phones) is done using "Cell Broadcast" (or "CB"). This has absolutely nothing to do with the Location API or any variations on that.
Cell towers can send out broadcast information that can be received by devices (something like "one to many SMS"). Some operators have used Cell Broadcast to broadcast the name of the location where the cell tower is. Some operators have used Cell Broadcast to broadcast the location (lat/long) of the cell tower. Some operators have used Cell Broadcast to send advertising tickers. There are no standards for the information contained in a CB broadcast message and each mobile operator can choose to use this or not.
Since most operators do not send these messages, it probably doesn't make sense to invest any time in trying to receive and decode them. But if you want to try, you can register a BroadcastReceiver listening for this Intent action: android.provider.Telephony.SMS_CB_RECEIVED. See the documentation for more details about what data is contained in the Intent.
The problem is that the code you tried does work, probably just not as well as you wished. For example, the accuracy such a method provides on Samsung Galaxy S3 is 2000m, meaning the actual position is anywhere within a circle of 2 kilometers radius. Additional it would probably take quite a large change in location before your app would be informed of a location change since the margin of error is so big.
A GPS or LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY (if Google Play Services is used) is required to get a reasonably good location. This does require android.permission.ACCESS_FINE_LOCATION, however unless you only require km level accuracy, otherwise this permission is a must.
Finally note that using Google Play Services with LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY I can get location data as accurate as 10m without turning on GPS, so this should still satisfy your requirement.
Below is a complete example:
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
MainActivity.java
import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class MainActivity extends Activity implements
com.google.android.gms.location.LocationListener, ConnectionCallbacks,
OnConnectionFailedListener {
private final FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
private GoogleApiClient mGoogleAPIClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleAPIClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
}
#Override
protected void onResume() {
super.onResume();
mGoogleAPIClient.connect();
}
#Override
protected void onPause() {
super.onPause();
if (mGoogleAPIClient != null) {
mGoogleAPIClient.disconnect();
}
}
#Override
public void onConnected(Bundle arg0) {
final LocationRequest locationRequest = LocationRequest.create();
locationRequest
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
fusedLocationProviderApi.requestLocationUpdates(mGoogleAPIClient,
locationRequest, this);
}
#Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location location) {
// the location is no more than 10 min old, and with reasonable
// accurarcy (50m), done
if (System.currentTimeMillis() < location.getTime() + 10 * 60 * 1000
&& location.getAccuracy() < 50) {
mGoogleAPIClient.disconnect();
mGoogleAPIClient = null;
((TextView) findViewById(R.id.test)).setText(location.toString());
}
}
}
According to android docs using LocationManager is not the current recomended API (see reference):
The Google Play services location APIs are preferred over the
Android framework location APIs (android.location) as a way of
adding location awareness to your app.
To learn how to set up the Google Services client library, see Setup in the Google Play services guide.
Once you have linked Google Services client library to your app you can achieve user location using FusedLocationProviderApi:
import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class MainActivity extends ActionBarActivity
implements ConnectionCallbacks, OnConnectionFailedListener {
// ..
private GoogleApiClient mGoogleAPIClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// create google api client object
mGoogleAPIClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
#Override
protected void onStart() {
super.onStart();
mGoogleAPIClient.connect();
}
#Override
protected void onStop() {
super.onStop();
mGoogleAPIClient.disconnect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this,
"Could not connect to Google Play Services",
Toast.LENGTH_SHORT).show();
finish();
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG,
"Successfuly connect to Google Play Services");
// retrieve last location once connected
Location lastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleAPIClient);
if (lastLocation == null) {
// should request new one
// location should be enabled
Log.i(TAG,
"No location data previously acquired.. should request!");
Toast.makeText(this,
"Requesting location data ..",
Toast.LENGTH_SHORT).show();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(5000);
PendingResult<Status> result = LocationServices.FusedLocationApi
.requestLocationUpdates(mGoogleAPIClient,
locationRequest,
new LocationListener() {
#Override
public void onLocationChanged(Location location) {
makeUseOfNewLocation(location);
}
});
// TODO: use result to retrieve more info
} else {
makeUseOfNewLocation(lastLocation);
}
}
#Override
public void onConnectionSuspended(int i) {
}
private void makeUseOfNewLocation(Location location) {
// do your stuff here
}
I have tested the code above and it works without internet connection but it requires that user enable location feature on device. Also it requires that the user have already enabled Location History feature into location feature.
Hope that this helps you.
You can try getting a country level accuracy using the Locale object or using the Telephony service. No internet or GPS required.
Getting country code from Locale:
String locale = context.getResources().getConfiguration().locale.getCountry();
Getting country code from Android's Telephony service:
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
// Will work on all networks. Only provide the SIM card's country
String countryCode = tm.getSimCountryIso();
// Might not work well on CDMA networks. Will provide the country code
// for the country the device is currently in.
String currentCountryCode = tm.getNetworkCountryIso();
Better code samples and discussion here.
Good luck with this. It's called geocoder. Or more specifically reverse geocoding to turn coordinates into a human readable output. I'm fairly sure the one google provides is a pay service but you get a bunch free. So plan on caching the results and using your cached results when ever possible.
List<Address> list = geoCoder.getFromLocation(location
.getLatitude(), location.getLongitude(), 1);
if (list != null & list.size() > 0) {
Address address = list.get(0);
result = address.getLocality();
return result;
https://developer.android.com/training/location/display-address.html
How to get city name from latitude and longitude coordinates in Google Maps?
try this code..
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
public class AppLocationService extends Service implements LocationListener {
protected LocationManager locationManager;
Location location;
private static final long MIN_DISTANCE_FOR_UPDATE = 10;
private static final long MIN_TIME_FOR_UPDATE = 1000 * 60 * 2;
public AppLocationService(Context context) {
locationManager = (LocationManager) context
.getSystemService(LOCATION_SERVICE);
}
public Location getLocation(String provider) {
if (locationManager.isProviderEnabled(provider)) {
locationManager.requestLocationUpdates(provider,
MIN_TIME_FOR_UPDATE, MIN_DISTANCE_FOR_UPDATE, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(provider);
return location;
}
}
return null;
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
and next class is
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class AndroidLocationActivity extends Activity {
Button btnGPSShowLocation;
Button btnNWShowLocation;
AppLocationService appLocationService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
appLocationService = new AppLocationService(
AndroidLocationActivity.this);
btnGPSShowLocation = (Button) findViewById(R.id.btnGPSShowLocation);
btnGPSShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Location gpsLocation = appLocationService
.getLocation(LocationManager.GPS_PROVIDER);
if (gpsLocation != null) {
double latitude = gpsLocation.getLatitude();
double longitude = gpsLocation.getLongitude();
Toast.makeText(
getApplicationContext(),
"Mobile Location (GPS): \nLatitude: " + latitude
+ "\nLongitude: " + longitude,
Toast.LENGTH_LONG).show();
} else {
showSettingsAlert("GPS");
}
}
});
btnNWShowLocation = (Button) findViewById(R.id.btnNWShowLocation);
btnNWShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Location nwLocation = appLocationService
.getLocation(LocationManager.NETWORK_PROVIDER);
if (nwLocation != null) {
double latitude = nwLocation.getLatitude();
double longitude = nwLocation.getLongitude();
Toast.makeText(
getApplicationContext(),
"Mobile Location (NW): \nLatitude: " + latitude
+ "\nLongitude: " + longitude,
Toast.LENGTH_LONG).show();
} else {
showSettingsAlert("NETWORK");
}
}
});
}
public void showSettingsAlert(String provider) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(
AndroidLocationActivity.this);
alertDialog.setTitle(provider + " SETTINGS");
alertDialog
.setMessage(provider + " is not enabled! Want to go to settings menu?");
alertDialog.setPositiveButton("Settings",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
AndroidLocationActivity.this.startActivity(intent);
}
});
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
and this user permission given At Manifest File
<!-- to get location using GPS -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- to get location using NetworkProvider -->
<uses-permission android:name="android.permission.INTERNET" />