简体   繁体   中英

Getting Current Location on Android - Currently crashing only on first app launch [Broadcast error]

So I am trying to add a some functionality to my app so that it can allow the user to get his location in a editbox instead of having to type it.

At the moment I have a "working example" but there is a strange bug in it: The first time you launch the app and click the button to get the location, the app crashes. It doesn't happen ever again, unless you reinstall the app and again it will crash only once ever. This seems to only be happening to Android 6.0 + devices (doesn't crash at all on 4.4 and 5.0). Also sometimes it doesn't really get the location, just keeps returning null.

I suppose there is a better way to get Location, but this is my first time trying to get user's location so I don't know it.

So my question is essentially 2 questions - is there a better way to get location that will work on Android 4.4+ and why is my application crashing with pretty strange error.

The error:

system_process E/ActivityManager: Sending non-protected broadcast projekt.substratum.APP_CRASHED from system 820:system/1000 pkg android
                                                               java.lang.Throwable
                                                                   at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:17973)
                                                                   at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18545)
                                                                   at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:18636)
                                                                   at android.app.ContextImpl.sendBroadcast(ContextImpl.java:881)
                                                                   at com.android.server.am.AppErrors.crashApplicationInner(AppErrors.java:370)
                                                                   at com.android.server.am.AppErrors.crashApplication(AppErrors.java:305)
                                                                   at com.android.server.am.ActivityManagerService.handleApplicationCrashInner(ActivityManagerService.java:13554)
                                                                   at com.android.server.am.ActivityManagerService.handleApplicationCrash(ActivityManagerService.java:13536)
                                                                   at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:1660)
                                                                   at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2813)
                                                                   at android.os.Binder.execTransact(Binder.java:565)

The Location class that I'm using (not written by me, only minor edits done)

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class ProviderLocationTracker implements LocationListener,LocationTracker {

  // The minimum distance to change Updates in meters
  private static final long MIN_UPDATE_DISTANCE = 10;

  // The minimum time between updates in milliseconds
  private static final long MIN_UPDATE_TIME = 1000 * 60;

  private LocationManager lm;

  public enum ProviderType{
      NETWORK,
      GPS
  };
  private String provider;

  private Location lastLocation;
  private long lastTime;

  private boolean isRunning;

  private LocationUpdateListener listener;

  public ProviderLocationTracker(Context context, ProviderType type) {
    lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
    Criteria crit = new Criteria();
    crit.setAccuracy(Criteria.ACCURACY_FINE);

    if(type == ProviderType.NETWORK){
        provider = LocationManager.NETWORK_PROVIDER;
    }
    else{
        provider = LocationManager.GPS_PROVIDER;
    }

    provider = lm.getBestProvider(crit, true);

  }

  public String returnProvider(){
      return provider;
  }

  public void start(){
      if(isRunning){
          //Already running, do nothing
          return;
      }

      //The provider is on, so start getting updates.  Update current location
      isRunning = true;
      lm.requestLocationUpdates(provider, MIN_UPDATE_TIME,MIN_UPDATE_DISTANCE, this);
      lastLocation = null;
      lastTime = 0;
      return;
  }

  public void start(LocationUpdateListener update) {
      start();
      listener = update;

  }

  public void stop(){
      if(isRunning){
          lm.removeUpdates(this);
          isRunning = false;
          listener = null;
      }
  }

  public boolean hasLocation(){
      if(lastLocation == null){
          return false;
      }
      if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
          return false; //stale
      }
      return true;
  }

  public boolean hasPossiblyStaleLocation(){
      if(lastLocation != null){
          return true;
      }
      return lm.getLastKnownLocation(provider)!= null;
  }

  public Location getLocation(){
      if(lastLocation == null){
          return null;
      }
      if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
          return null; //stale
      }
      return lastLocation;
  }

  public Location getPossiblyStaleLocation(){
      if(lastLocation != null) {
          return lastLocation;
      }
      return lm.getLastKnownLocation(provider);
  }

  public void onLocationChanged(Location newLoc) {
      long now = System.currentTimeMillis();
      if(listener != null){
          listener.onUpdate(lastLocation, lastTime, newLoc, now);
      }
      lastLocation = newLoc;
      lastTime = now;
  }

  public void onProviderDisabled(String arg0) {
  }

  public void onProviderEnabled(String arg0) {
  }

  public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
  }

}

Getting the location on button click listener:

if (checkLocationPermission()) {
  if (ContextCompat.checkSelfPermission(getContext(),
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {

     //Request location updates:
     getLocation();
   }
 }

getLocation method:

 public void getLocation(){

    //In case we havent started it somehow, just returns if we did
    location.start();

    double alti;
    double longti;

    if(location.hasLocation()){
        if (location.getLocation() != null) {
            alti = location.getLocation().getLatitude();
            longti = location.getLocation().getLongitude();

            locationText.setText(alti +","+longti);

        }else{
            locationText.setText("1Couldn't get location, check your GPS/NETWORK");
        }
    }else{
        if (location.getPossiblyStaleLocation() != null) {
            alti = location.getPossiblyStaleLocation().getLatitude();
            longti = location.getPossiblyStaleLocation().getLongitude();

            locationText.setText(alti + "," + longti);
        }else{
            locationText.setText("2Couldn't get location, check your GPS/NETWORK");
        }
    }
}

Solved the crash, as @Giovanni Terlingen suggested, it was caused by the theme engine that I had on my phone. The problem that remains is that the GPS location getting is not always working - For older phones it doesn't get the location via GPS but the Criteria assigns GPS as provider anyway. Is there a better way to get locations for devices from KitKat to possibly Oreo?

This seems to only be happening to Android 6.0 + device

Since Android 6.0, permissions has been introduced. Make sure that your app has location access on Android 6.0+. You should inform the user that your want to access his/her location. See this useful link:

https://developer.android.com/training/permissions/requesting.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM