The first time I install this application, and when I launch MapsActivity, I am asked for permissions, which is normal. But the problem is that the application closes in the meantime. How can I modify my code to keep the application open, and the permission pop-up just overlaps. Thank you very much for your answer.
Error code in logcat :
2020-02-02 11:17:01.340 11559-11574/? E/le.rsr_pechhlu: Unable to peek into adb socket due to error. Closing socket.: Connection reset by peer
2020-02-02 11:17:01.470 11559-11636/? E/AwareLog: AtomicFileUtils: readFileLines file not exist: android.util.AtomicFile#2f88384
2020-02-02 11:17:01.470 11559-11636/? E/AwareLog: AtomicFileUtils: readFileLines file not exist: android.util.AtomicFile#7fa676d
2020-02-02 11:17:01.471 11559-11603/? E/MemoryLeakMonitorManager: MemoryLeakMonitor.jar is not exist!
2020-02-02 11:17:10.787 11559-11559/com.example.rsr_pechhlup E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.rsr_pechhlup, PID: 11559
java.lang.RuntimeException: Unable to pause activity {com.example.rsr_pechhlup/com.example.rsr_pechhlup.MapsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.location.LocationManager.removeUpdates(android.location.LocationListener)' on a null object reference
at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:4742)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4691)
at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4626)
at android.app.servertransaction.PauseActivityItem.execute(PauseActivityItem.java:45)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2199)
at android.os.Handler.dispatchMessage(Handler.java:112)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.location.LocationManager.removeUpdates(android.location.LocationListener)' on a null object reference
at com.example.rsr_pechhlup.MapsActivity.onPause(MapsActivity.java:159)
at android.app.Activity.performPause(Activity.java:7663)
at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1536)
at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:4726)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4691)
at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4626)
at android.app.servertransaction.PauseActivityItem.execute(PauseActivityItem.java:45)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2199)
at android.os.Handler.dispatchMessage(Handler.java:112)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
public class MapsActivity extends FragmentActivity implements LocationListener {
private GoogleMap googleMap; //google map is contained in the fragment work on it to change the position of the map and so on.
private Marker marker;
private Button buttonCallNow;
private RelativeLayout callPanelWrapper;
private static final int PERMS_CALL_ID = 1234; //permission identifier, unique identifier
private static final int REQUEST_PHONE_CALL = 4321;
private LocationManager locationManager; // Android manager service of android platform.
private SupportMapFragment mapFragment;
private Utils utils;
private PhoneCallListener phoneCallListener;
private boolean firstTime;
private String adresse;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps2);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
mapFragment= (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
}
/**
* //When the activity comes back to the foreground, I have to subscribe to the different location information providers, so I will receive the new location information and I will be able to resynchronize my mapping on this location.
*/
#Override
protected void onResume() {
super.onResume();
checkPermissions();
firstTime=true;
}
private void checkPermissions(){
//For older versions of android we check that the ACCES_FINE_LOCATION and ACCES_COARSE_LOCATION permissions are enabled.
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, Manifest.permission.ACCESS_COARSE_LOCATION },PERMS_CALL_ID); //We must provide three parameters: it is the activity that requires the activation of these permissions (here it is this), then a table that specifies the set of permissions to allow. And we need a request code.
return;
}
locationManager= (LocationManager) getSystemService(LOCATION_SERVICE);//I ask android to give me that service locationManager. LOCATION SERVICE comes inheritance FragmentActivity, which inherits from Context, which contains this constant.
if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){//If on this locationManager, a particular provider here : LocationManager.GPS_PROVIDER is allowed. If I have a GPS type sensor that is enabled, on the locationManager I will be able to subscribe to events.
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,0,this);//This function requires the type of provider: LocationManager.GPS.it needs the frequency in milliseconds at which I want new location information(Here all the seconds).It needs to notify a person, who is going to receive this notification information, it's the MapsActivity, so this.
}
if(locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)){//If on this locationManager, a particular provider here : LocationManager.PASIVE_PROVIDER is allowed. If I have a GPS type sensor that is enabled, on the locationManager I will be able to subscribe to events.
locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,1000,0,this);//This function requires the type of provider: LocationManager.GPS.it needs the frequency in milliseconds at which I want new location information(Here all the seconds).It needs to notify a person, who is going to receive this notification information, it's the MapsActivity, so this.
}
if(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){//If on this locationManager, a particular provider here : NETWORK is allowed. If I have a GPS type sensor that is enabled, on the locationManager I will be able to subscribe to events.
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,1000,0,this);//This function requires the type of provider: LocationManager.GPS.it needs the frequency in milliseconds at which I want new location information(Here all the seconds).It needs to notify a person, who is going to receive this notification information, it's the MapsActivity, so this.
}
dispMap();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==PERMS_CALL_ID){ //This method will be activated each time a permission request is made. And to know where I'm coming from I need the requestCode. This request is coupled with this requestCode here.
checkPermissions(); //i call again chack permission do disp again pop-up permission.
}
}
/**
* //When my application leaves the foreground, I unsubscribe from the different providers of location information so as not to consume a lot of resources.
*/
#Override
protected void onPause() {
super.onPause();
//If the locationManager has been initialized, I make one of this, one of the earphone of all suppliers
locationManager.removeUpdates(this);
}
private void dispMap(){
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
MapsActivity.this.googleMap=googleMap;
marker = googleMap.addMarker(new MarkerOptions().position(new LatLng(43.799345,6.725426)));
}
});
}
/**
* React each time new positioning information is calculated
* #param location
*/
#Override
public void onLocationChanged(Location location) { //This location is obtained through the provider. Of course this can be any provider, GPS_PROVIDER is more accurate than PASSIVE_PROVIDER etc..
double latitude= location.getLatitude();//I'm getting the latitude.
double longitude=location.getLongitude();// I'm getting the longitude.
Toast.makeText(this, "Location: " + latitude + "/" + longitude,Toast.LENGTH_SHORT).show();
LatLng googleLocation=new LatLng(latitude,longitude);
if(firstTime){
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(googleLocation, 16.2f));
adresse= Utils.getCompleteAddressString(latitude, longitude,this);
BitmapDescriptor subwayBitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.map_marker);
marker = googleMap.addMarker(new MarkerOptions().position(googleLocation).icon(subwayBitmapDescriptor).title(adresse));
googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter(this));
}
firstTime=false;
if(this.googleMap!=null){//If my map is correctly displayed
adresse = Utils.getCompleteAddressString(latitude, longitude,this);
googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter(this));
marker.setTitle(adresse);
marker.setPosition(googleLocation);
marker.showInfoWindow();
}
}
/**
* To react to every change of state
* #param provider
* #param status
* #param extras
*/
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
/**
* When a location provider is closed.
* #param provider
*/
#Override
public void onProviderEnabled(String provider) {
}
/**
* When a location provider is closed.
* #param provider
*/
#Override
public void onProviderDisabled(String provider) {
}
public void btnBackClick(View view) {
Intent myIntent = new Intent(this, HomeActivity.class);
startActivity(myIntent);
}
public void btnCallMapclicked(View view) {
callPanelWrapper.setVisibility(View.VISIBLE);
buttonCallNow.setVisibility(View.GONE);
}
public void buttonFinalCallClicked(View view) {
call();
}
public void popupClosedClicked(View view) {
callPanelWrapper.setVisibility(View.GONE);
buttonCallNow.setVisibility(View.VISIBLE);
}
}
}
I'm not able to put comment,Thus forward my answer as post.
you may should describe about your problem more but do you add ACCESS_FINE_LOCATION and
ACCESS_COARSE_LOCATION to your Manifest file?
EDIT:
just change onPause to following:
#Override
protected void onPause() {
super.onPause();
if(locationManager != null) // add this line to your code
locationManager.removeUpdates(this);
}
Cause:
When Permission dialog has been shown your activity onPause() is called, and since you not initialize location manager yet, it throws NullPointerException.
Try this code to initialize map with required run time permission.
public class MapActivity extends AppCompatActivity implements OnMapReadyCallback,
GoogleApiClient.OnConnectionFailedListener{
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onMapReady(GoogleMap googleMap) {
Toast.makeText(this, "Map is Ready", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onMapReady: map is ready");
mMap = googleMap;
if (mLocationPermissionsGranted) {
getDeviceLocation();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
init();
}
}
private static final String TAG = "MapActivity";
private static final String FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
private static final String COURSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1234;
//vars
private Boolean mLocationPermissionsGranted = false;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
getLocationPermission();
}
private void initMap(){
Log.d(TAG, "initMap: initializing map");
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(MapActivity.this);
}
private void getLocationPermission(){
Log.d(TAG, "getLocationPermission: getting location permissions");
String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION};
if(ContextCompat.checkSelfPermission(this.getApplicationContext(),
FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
if(ContextCompat.checkSelfPermission(this.getApplicationContext(),
COURSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
mLocationPermissionsGranted = true;
initMap();
}else{
ActivityCompat.requestPermissions(this,
permissions,
LOCATION_PERMISSION_REQUEST_CODE);
}
}else{
ActivityCompat.requestPermissions(this,
permissions,
LOCATION_PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult: called.");
mLocationPermissionsGranted = false;
switch(requestCode){
case LOCATION_PERMISSION_REQUEST_CODE:{
if(grantResults.length > 0){
for(int i = 0; i < grantResults.length; i++){
if(grantResults[i] != PackageManager.PERMISSION_GRANTED){
mLocationPermissionsGranted = false;
Log.d(TAG, "onRequestPermissionsResult: permission failed");
return;
}
}
Log.d(TAG, "onRequestPermissionsResult: permission granted");
mLocationPermissionsGranted = true;
initMap(); // once permission granted then only initMap()
}
}
}
}
}
Related
My basic location application doesent work on my Galaxy A20 running API 29 but works fine on all my emuultors running the same API. im not sure what the problem could be as im not experianced with LOGCAT but the error states as following:
Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object reference.
THE ERROR IS ON LINE 117 on my project (At the end). But ive highlighted it here
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
LocationManager locationManager;
LocationListener locationListener;
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1){
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);
}
}
}
#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);
}
/**
* 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;
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title("Marker in user house"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
if (ContextCompat.checkSelfPermission(this , Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this , new String[]{Manifest.permission.ACCESS_FINE_LOCATION} , 1);
}
else{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER , 0 , 0 , locationListener);
Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
LatLng userLocation = new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()); // ◅ THE ERROR OCCOURS HERE********
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title("Marker in user house"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));
}
}
}
Maybe your phone has not managed to get a GPS fix yet. Check if lastKnowLocation is null before using it, and test the app outside where your phone can "see" the sky.
I have been working on an app which implements google maps. When I am on my homescreen and presses the "start map" button the message "Skipped 85 frames! The application may be doing too much work on its main thread." is shown in the Android Monitor. I have been looking around for a solution but have not been able to find one that works for me. Does anyone have any idea how to prevent this?
My maps activity:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mMap;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
private boolean initiateApp;
double CO2data = 1.02;
double N2data = 0.002;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
// 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);
initiateApp = true;
}
/**
* 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;
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
/* Here we create the infoWindow **/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
public View getInfoWindow(Marker arg0) {
View v = getLayoutInflater().inflate(R.layout.custom_infowindow, null);
TextView tv = (TextView) v.findViewById(R.id.infoText);
tv.setText("CO2 data: "+String.valueOf(CO2data) +"\n" + "N2 data: "+String.valueOf(N2data));
return v;
}
public View getInfoContents(Marker arg0) {
return null;
}
});
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(2000);
mLocationRequest.setFastestInterval(2000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
Log.d("ADebugTag", "Value: " + Double.toString(location.getLatitude()));
Log.d("ADebugTag", "Value: " + Double.toString(location.getLongitude()));
//move map camera
if(initiateApp){
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
}
initiateApp = false;
boolean contains = mMap.getProjection()
.getVisibleRegion()
.latLngBounds
.contains(latLng);
if(!contains){
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission(){
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Do the
// contacts-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
} else {
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
// other 'case' lines to check for other permissions this app might request.
// You can add here other case statements according to your requirement.
}
}
}
My maps XML
<fragment 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:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.kasper.map_app.MapsActivity" />
Based from this thread, if you have a lot of code in your UI events then you will see this error message. Also this will occur with asynchronous events like fetching data from a URL. The workaround given is to use threads or async tasks.
You want to off load any heavy code off of your UI Threads and onto another area - a new thread or in your main activity.
Here are some SO posts which might also help:
The application may be doing too much work on its main thread
The application may be doing too much work on its main thread - Android
After updated my app to support Android 7 the GPS listner no longer is invoked when the GPS on/off is triggerd. If I refresh my activity it works as expected on Android 6, but not in Android 7. Does anyone have any idea. I have added both my listner, and code releated to gps change in my activity.
I have if its difficult a theory to override the backpressed or activity resumed to recreate view, but havn't suceeded with that either .
GPSListner.java
public abstract class GPSListener implements LocationListener {
private Context context;
public GPSListener(Context context) {
this.context = context;
}
#Override
public void onProviderEnabled(String provider) {
onGPSOn();
}
#Override
public void onProviderDisabled(String provider) {
onGPSOff();
}
public abstract void onGPSOff();
public abstract void onGPSOn();
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
My class
gpsListener = new GPSListener(this) {
#Override
public void onGPSOff() {
gpsImg.setImageResource(R.drawable.notok);
}
#Override
public void onGPSOn() {
gpsImg.setImageResource(R.drawable.ok);
}
};
final LocationManager manager;
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
final ImageView gpsImg = (ImageView) findViewById(R.id.gpsstatus);
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
gpsImg.setImageResource(R.drawable.ok);
} else {
gpsImg.setImageResource(R.drawable.notok); //not ok
}
This last method opens the gps settings.
public View.OnClickListener onButtongpsClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(gpsOptionsIntent);
}
};
Obtaining location is a bit tricky itself. Only GPS can have line-of-sight issues and would vary depending on device too, not just Android version. Over the years Android location services have matured and using up-to-date standard practices does result in higher consistency with respect to results.
By the way, LocationClient is deprecated. FusedLocationProviderApi does not use it anymore.
It works through a GoogleApiClient and this part makes the GooglePlayServices mandatory. You have options if this does not suit your app.
Making your app location aware suggests:
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. If you are currently using the Android
framework location APIs, you are strongly encouraged to switch to the
Google Play services location APIs as soon as possible.
You can break it into parts to understand it better, like;
Building the GoogleApiClient
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this) //this = activity
.addApi(LocationServices.API)
.addConnectionCallbacks(this) //interfaces implemented
.addOnConnectionFailedListener(this)
.build();
}
Requesting location,
// Create the location request
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
// Request location updates
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
Try the last known location, if that requirement works for you,
#Override
public void onConnected(Bundle bundle) {
Location mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
...}
onConnected() is the callback from GoogleApiClient...
So there is more to location than initialising a client and implementing the listener. I recommend you go through a few questions or android docs to ensure you implement what suits your requirement.
Also,
instead of
Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); ,
use SettingsApi
can refer to Enabling location mode...
Some useful Q&As:
Comprehensive answer for obtaining location
Good to go through LocationRequest part here if you want to avoid reading in detail
final LocationManager manager;
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Do i even have to comment on this one? Read it again and you will understand what is wrong with it.
Hint. Try:
final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
You can used fused location api to get the location
Fused Location Api :
Fused Location Provider automatically decides best location from the available options for that it uses GPS and Network Provider, So if the device GPS is off we can still get the location from Network provider vice versa.
Why Fused Location Api ?
Consumption of power while fetching location.
It will give accurate
location based on user priority.
Piggyback which means you can get
location every time when other application hits for location for you
advantage is user not blame you for that you just getting those
location which other application request.
We don’t have to pick the
provider(GPS or network provider)
please refer code for following for getting location.
LocationService : We required these for getting continues location and these register as pending intent so whenever device got new location these service invoke.
public class LocationService extends IntentService {
private String TAG = this.getClass().getSimpleName();
public LocationService() {
super("Fused Location");
}
public LocationService(String name) {
super("Fused Location");
}
#Override
protected void onHandleIntent(Intent intent) {
Location location = intent.getParcelableExtra(LocationClient.KEY_LOCATION_CHANGED);
if(location !=null){
Log.i(TAG, "onHandleIntent " + location.getLatitude() + "," + location.getLongitude());
// write your code here.
}
}
}
MainActivity : which register callbacks for it which tell us whether we are connected or disconnected with api.
public class MainActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener,LocationListener {
private String TAG = this.getClass().getSimpleName();
private LocationClient locationclient;
private LocationRequest locationrequest;
private Intent mIntentService;
private PendingIntent mPendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIntentService = new Intent(this,LocationService.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);
int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(resp == ConnectionResult.SUCCESS){
locationclient = new LocationClient(this,this,this);
locationclient.connect();
}
else{
Toast.makeText(this, "Google Play Service Error " + resp, Toast.LENGTH_LONG).show();
}
}
public void buttonClicked(View v){
if(v.getId() == R.id.btnLastLoc){
if(locationclient!=null && locationclient.isConnected()){
Location loc =locationclient.getLastLocation();
Log.i(TAG, "Last Known Location :" + loc.getLatitude() + "," + loc.getLongitude());
txtLastKnownLoc.setText(loc.getLatitude() + "," + loc.getLongitude());
}
}
if(v.getId() == R.id.btnStartRequest){
if(locationclient!=null && locationclient.isConnected()){
if(((Button)v).getText().equals("Start")){
locationrequest = LocationRequest.create();
locationrequest.setInterval(Long.parseLong(etLocationInterval.getText().toString()));
locationclient.requestLocationUpdates(locationrequest, this);
((Button) v).setText("Stop");
}
else{
locationclient.removeLocationUpdates(this);
((Button) v).setText("Start");
}
}
}
if(v.getId() == R.id.btnRequestLocationIntent){
if(((Button)v).getText().equals("Start")){
locationrequest = LocationRequest.create();
locationrequest.setInterval(100);
locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
((Button) v).setText("Stop");
}
else{
locationclient.removeLocationUpdates(mPendingIntent);
((Button) v).setText("Start");
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(locationclient!=null)
locationclient.disconnect();
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "onConnected");
txtConnectionStatus.setText("Connection Status : Connected");
}
#Override
public void onDisconnected() {
Log.i(TAG, "onDisconnected");
txtConnectionStatus.setText("Connection Status : Disconnected");
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "onConnectionFailed");
txtConnectionStatus.setText("Connection Status : Fail");
}
#Override
public void onLocationChanged(Location location) {
if(location!=null){
Log.i(TAG, "Location Request :" + location.getLatitude() + "," + location.getLongitude());
}
}
}
For more reference refer below link
https://github.com/riteshreddyr/fused-location-provider
https://github.com/kpbird/fused-location-provider-example
Hope these help you.
Hey Im new to Android and wondering if someone can help me. I have a MapsActivity which crashes when navigating to it. I think I've narrowed down to exactly where it is from looking through the errors but I cant figure out what to change.
I've added the whole MapsActivity class below. The problem is occuring in the onConnected method on this line mLocationManager.requestLocationUpdates(provider, 5000, 0, this);
. Android Studio recommends I cast 'this' to LocationListener but this doesn't work and the error I get from doing so is listed below the MapsActivity code.
I have also tried entering mLocationListener in the place of 'this' but doesn't work and I get errors which are listed below too.
ANY HELP IS GREATLY APPRECIATED. THANKS!
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
private static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private static final int MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 2;
private GoogleMap mMap;
private GoogleApiClient mGoogleApiClient;
private LocationManager mLocationManager;
private Location mLastLocation;
private LocationListener mLocationListener;
private String mLatitude;
private String mLongitude;
#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);
// Create an instance of GoogleAPIClient.
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
//create instance of location manager and get location service
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
}
/**
* 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;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
#Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
//mLocationManager.removeUpdates((LocationManager) this);
super.onStop();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(true);
criteria.setBearingRequired(true);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
String provider = mLocationManager.getBestProvider(criteria, true);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationManager.requestLocationUpdates(provider, 5000, 0, this);
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(mLastLocation != null){
mLatitude = String.valueOf(mLastLocation.getLatitude());
mLongitude = String.valueOf(mLastLocation.getLongitude());
Toast.makeText(this, mLatitude + " , " + mLongitude, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "Permission denied, please accept permission..", Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){
switch (requestCode){
case MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION:{
//if request cancelled the results array is empty
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
//do task you wish to do
//Intent intent = (new Intent(this, MapsActivity.class));
//startActivity(intent);
}else{
//permission denied, disable functionality(GPS)
}
return;
}
//other cases go here
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
}
}
Casting errors -
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.a8460p.locationotes, PID: 23305
java.lang.ClassCastException: com.example.a8460p.locationotes.MapsActivity cannot be cast to android.location.LocationListener
at com.example.a8460p.locationotes.MapsActivity.onConnected(MapsActivity.java:106)
at com.google.android.gms.common.internal.zzm.zzq(Unknown Source)
at com.google.android.gms.internal.zzaal.zzo(Unknown Source)
at com.google.android.gms.internal.zzaaj.zzvE(Unknown Source)
at com.google.android.gms.internal.zzaaj.onConnected(Unknown Source)
at com.google.android.gms.internal.zzaan.onConnected(Unknown Source)
at com.google.android.gms.internal.zzzy.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzl$1.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzf$zzj.zzwZ(Unknown Source)
at com.google.android.gms.common.internal.zzf$zza.zzc(Unknown Source)
at com.google.android.gms.common.internal.zzf$zza.zzu(Unknown Source)
at com.google.android.gms.common.internal.zzf$zze.zzxa(Unknown Source)
at com.google.android.gms.common.internal.zzf$zzd.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Replacing 'this' with mLocationListener errors -
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.a8460p.locationotes, PID: 24073
java.lang.IllegalArgumentException: invalid listener: null
at android.location.LocationManager.checkListener(LocationManager.java:1733)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:461)
at com.example.a8460p.locationotes.MapsActivity.onConnected(MapsActivity.java:106)
at com.google.android.gms.common.internal.zzm.zzq(Unknown Source)
at com.google.android.gms.internal.zzaal.zzo(Unknown Source)
at com.google.android.gms.internal.zzaaj.zzvE(Unknown Source)
at com.google.android.gms.internal.zzaaj.onConnected(Unknown Source)
at com.google.android.gms.internal.zzaan.onConnected(Unknown Source)
at com.google.android.gms.internal.zzzy.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzl$1.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzf$zzj.zzwZ(Unknown Source)
at com.google.android.gms.common.internal.zzf$zza.zzc(Unknown Source)
at com.google.android.gms.common.internal.zzf$zza.zzu(Unknown Source)
at com.google.android.gms.common.internal.zzf$zze.zzxa(Unknown Source)
at com.google.android.gms.common.internal.zzf$zzd.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Make MapsActivity implements android.location.LocationListener instead of com.google.android.gms.location.LocationListener
For First crash: this crash is occuring due to the incorrect import for location listener class which you have implements to your Activity.
Change com.google.android.gms.location.LocationListener with android.location.LocationListener
and for second crash use bellow LocationListener, this crash is occuring due your null reference of location listener object.
private LocationListener mLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
Your requestLocationUpdates could not find instance of Listener so add MapsActivity.this to requestLocationUpdates
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationManager.requestLocationUpdates(provider, 5000, 0, MapsActivity.this);//Changed here
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(mLastLocation != null){
mLatitude = String.valueOf(mLastLocation.getLatitude());
mLongitude = String.valueOf(mLastLocation.getLongitude());
Toast.makeText(this, mLatitude + " , " + mLongitude, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "Permission denied, please accept permission..", Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
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.