2015-04-15 6 views
28

Ich habe eine Android-Anwendung, die aktuelle Gerätestandort (Längen- und Breitengrad) benötigen. Ich habe einige Tutorials im Netz und vor allem einige Lösungen vom Stack Overflow ausprobiert, aber sie funktionieren nicht gut für mich. Meine Anforderung ist so einfach: Zuerst brauche ich es schnell und brauche den Ort einmal wenn ich das Fragment starte. Zweitens brauche ich es so präzise wie möglich, ich meine, es sollte GPS zuerst verwenden, wenn GPS nicht verfügbar ist, dann verwenden Sie den Netzwerkanbieter.Holen Sie sich den aktuellen Standort schnell und einmal in Android

Zum Beispiel habe ich versucht this solution, aber es gibt null nach 30 Sekunden, aber ich weiß, es gibt einige alle Dinge ist in Ordnung, weil Google Map und andere Anwendung gut funktioniert !!!

Etwas, das fast alle Antworten vorschlagen, ist getLastKnownLocation() zu verwenden, aber ich nehme an, es ist nicht die aktuelle und ich will es nicht, wenn es so ist.

kann jemand mir eine Art von einfachen und schnellen Weg vorschlagen, um die Lage nur einmal zu bekommen?!

Vielen Dank im Voraus

Antwort

46

Hier können Sie diese verwenden ...

Beispiel Nutzung:

public void foo(Context context) { 
    // when you need location 
    // if inside activity context = this; 

    SingleShotLocationProvider.requestSingleUpdate(context, 
    new SingleShotLocationProvider.LocationCallback() { 
    @Override public void onNewLocationAvailable(GPSCoordinates location) { 
     Log.d("Location", "my location is " + location.toString()); 
    } 
    }); 
} 

Sie könnten die lat/long überprüfen möchten, sind die tatsächlichen Werte und nicht 0 oder so etwas. Wenn ich mich richtig erinnere, sollte dies keine NPE werfen, aber Sie sollten das überprüfen.

public class SingleShotLocationProvider { 

    public static interface LocationCallback { 
     public void onNewLocationAvailable(GPSCoordinates location); 
    } 

    // calls back to calling thread, note this is for low grain: if you want higher precision, swap the 
    // contents of the else and if. Also be sure to check gps permission/settings are allowed. 
    // call usually takes <10ms 
    public static void requestSingleUpdate(final Context context, final LocationCallback callback) { 
     final LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 
     boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 
     if (isNetworkEnabled) { 
      Criteria criteria = new Criteria(); 
      criteria.setAccuracy(Criteria.ACCURACY_COARSE); 
      locationManager.requestSingleUpdate(criteria, new LocationListener() { 
       @Override 
       public void onLocationChanged(Location location) { 
        callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude())); 
       } 

       @Override public void onStatusChanged(String provider, int status, Bundle extras) { } 
       @Override public void onProviderEnabled(String provider) { } 
       @Override public void onProviderDisabled(String provider) { } 
      }, null); 
     } else { 
      boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); 
      if (isGPSEnabled) { 
       Criteria criteria = new Criteria(); 
       criteria.setAccuracy(Criteria.ACCURACY_FINE); 
       locationManager.requestSingleUpdate(criteria, new LocationListener() { 
        @Override 
        public void onLocationChanged(Location location) { 
         callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude())); 
        } 

        @Override public void onStatusChanged(String provider, int status, Bundle extras) { } 
        @Override public void onProviderEnabled(String provider) { } 
        @Override public void onProviderDisabled(String provider) { } 
       }, null); 
      } 
     } 
    } 


    // consider returning Location instead of this dummy wrapper class 
    public static class GPSCoordinates { 
     public float longitude = -1; 
     public float latitude = -1; 

     public GPSCoordinates(float theLatitude, float theLongitude) { 
      longitude = theLongitude; 
      latitude = theLatitude; 
     } 

     public GPSCoordinates(double theLatitude, double theLongitude) { 
      longitude = (float) theLongitude; 
      latitude = (float) theLatitude; 
     } 
    } 
} 
+3

Es funktioniert wie ein Charme, es ist schnell genug für mich, vielen Dank. – Evil

+0

nicht funktionieren, muss ich in meinem Manifest hinzufügen? – delive

+1

Sehr nützlich. Danke. –

1

Was möchten Sie tun ist, erreicht die LocationManager#requestSingleUpdate verwenden. Diese Methode hängt einen Listener in einem gegebenen Looper an (wenn Sie wollen oder haben) und benachrichtigt den Ort ASAP, der empfangen wird, nur einmal. Die Methode, die Sie vorschlagen, wird nur als ungenaue Position verwendet, bevor Ihnen die echte gegeben wird.

In jedem Fall ist es schneller als Millisekunden (es sei denn, Sie haben das Glück zu hören, wenn ein Ort auf das Gerät kam). Stellen Sie sich das GPS als ein Element vor, das Sie beim Warten auf Standorte aktivieren und deaktivieren Sie es, wenn Sie dieses Abhören entfernen. Dieses Verhalten wird vorgenommen, um zu vermeiden, dass die Batterie des Benutzers entleert wird.

Also, um es zusammenzufassen:

  • Die Zeit zwischen Sie beginnen zu hören, und Sie erhalten die Position auf dem GPS des Geräts hängt (Herstellung, Standort des Benutzers, Satellitenabdeckung ...)
  • Es ist eine Methode im Android SDK, die auf ein einzelnes Update wartet.
  • Durch die Angabe eines Kriterienobjekts können Sie verwalten, welche Kriterien für einen Standort akzeptabel sind. Stärkere Kriterien bedeuten mehr Zeit für eine genaue Antwort.
0
// Get LocationManager object 
    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 

    // Create a criteria object to retrieve provider 
    Criteria criteria = new Criteria(); 

    // Get the name of the best provider 
    String provider = locationManager.getBestProvider(criteria, true); 

    // Get Current Location 
    Location myLocation = locationManager.getLastKnownLocation(provider); 

    //latitude of location 
    double myLatitude = myLocation.getLatitude(); 

    //longitude og location 
    double myLongitude = myLocation.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; 
    } 
+0

Warum die if-Anweisung '&&' und nicht '||' verwendet ? Sie benötigen nur eine der Berechtigungen, um auf den Standort zuzugreifen? – DAVIDBALAS1

1

AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-feature android:name="android.hardware.location.gps" /> 

MainActivity.java:

public class MainActivity extends AppCompatActivity implements LocationListener { 

    private LocationManager locationManager; 
    private Location onlyOneLocation; 
    private final int REQUEST_FINE_LOCATION = 1234; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
      ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION); 
    } 

    @Override public void onLocationChanged(Location location) { 
     onlyOneLocation = location; 
     locationManager.removeUpdates(this); 
    } 
    @Override public void onStatusChanged(String provider, int status, Bundle extras) { } 
    @Override public void onProviderEnabled(String provider) { } 
    @Override public void onProviderDisabled(String provider) { } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { 
     switch (requestCode) { 
     case REQUEST_FINE_LOCATION: 
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       Log.d("gps", "Location permission granted"); 
       try { 
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
        locationManager.requestLocationUpdates("gps", 0, 0, this); 
       } 
       catch (SecurityException ex) { 
        Log.d("gps", "Location permission did not work!"); 
       } 
      } 
      break; 
    } 
} 
1

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-feature android:name="android.hardware.location.gps" /> 

Requesting User Permissions


build.gradle (Modul: app)

dependencies { 
    ... 
    implementation 'com.google.android.gms:play-services-location:11.8.0' 
    ... 
} 

Wenn Sie einen Fehler erhalten, überprüfen tha t Ihre Top-Level-build.gradle einen Verweis auf die Google() Repo enthält oder Maven {url "https://maven.google.com"}

Set Up Google Play Services


LocationService.kt

import android.Manifest 
import android.annotation.SuppressLint 
import android.app.Activity 
import android.content.Intent 
import android.content.pm.PackageManager 
import android.location.Location 
import android.net.Uri 
import android.os.Looper 
import android.provider.Settings 
import android.support.v4.app.ActivityCompat 
import android.support.v4.content.ContextCompat 
import com.google.android.gms.common.api.ApiException 
import com.google.android.gms.common.api.ResolvableApiException 
import com.google.android.gms.location.* 
import org.jetbrains.anko.alert 
import org.jetbrains.anko.doAsync 
import org.jetbrains.anko.okButton 

object LocationService { 

    @SuppressLint("StaticFieldLeak") 
    private lateinit var fusedLocationProviderClient: FusedLocationProviderClient 
    private lateinit var locationRequest: LocationRequest 
    private val locationCallback = object : LocationCallback() { 
     override fun onLocationResult(locationResult: LocationResult) { 
      doAsync { 
       location = locationResult.lastLocation 
       onSuccess(location) 
      } 
     } 
    } 
    private lateinit var onSuccess: (location : Location) -> Unit 
    private lateinit var onError:() -> Unit 
    lateinit var location: Location 

    fun init(activity: Activity) { 
     fusedLocationProviderClient = FusedLocationProviderClient(activity) 
     locationRequest = LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(1000).setFastestInterval(1000).setNumUpdates(1) 
    } 

    private fun checkLocationStatusAndGetLocation(activity: Activity) { 
     doAsync { 
      when { 
       ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED -> LocationServices.getSettingsClient(activity).checkLocationSettings(LocationSettingsRequest.Builder().addLocationRequest(locationRequest).setAlwaysShow(true).build()).addOnCompleteListener { task -> 
        doAsync { 
         try { 
          task.getResult(ApiException::class.java) 
          fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) 
         } catch (exception: ApiException) { 
          when (exception.statusCode) { 
           LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> { 
            try { 
             (exception as ResolvableApiException).startResolutionForResult(activity, 7025) 
            } catch (ex: Exception) { 
             promptShowLocation(activity) 
            } 
           } 
           LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> { 
            promptShowLocation(activity) 
           } 
          } 
         } 
        } 
       } 
       ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION) -> activity.runOnUiThread { 
        activity.alert("To continue, allow the device to use location, witch uses Google's Location Service") { 
         okButton { 
          val ite = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", activity.packageName, null)) 
          ite.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 
          activity.startActivity(ite) 
          onError() 
         } 
         negativeButton("Cancelar", { onError() }) 
         onCancelled { onError() } 
        }.show() 
       } 
       else -> ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 7024) 
      } 
     } 
    } 

    private fun promptShowLocation(activity: Activity) { 
     activity.runOnUiThread { 
      activity.alert("To continue, allow the device to use location, witch uses Google's Location Service") { 
       okButton { 
        activity.startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)) 
        onError() 
       } 
       negativeButton("Cancelar", { onError() }) 
       onCancelled { onError() } 
      }.show() 
     } 
    } 

    fun onRequestPermissionsResult(activity: Activity, requestCode: Int, grantResults: IntArray) { 
     if (requestCode == 7024) { 
      if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       checkLocationStatusAndGetLocation(activity) 
      } else { 
       onError() 
      } 
     } 
    } 

    fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int) { 
     if (requestCode == 7025) { 
      if (resultCode == Activity.RESULT_OK) { 
       checkLocationStatusAndGetLocation(activity) 
      } else { 
       onError() 
      } 
     } 
    } 

    fun getLocation(activity: Activity, onSuccess:() -> Unit, onError:() -> Unit) { 
     this.onSuccess = onSuccess 
     this.onError = onError 
     checkLocationStatusAndGetLocation(activity) 
    } 

} 

Ihre Aktivität

override fun onCreate(savedInstanceState: Bundle?) { 
    ... 
    LocationService.init(this) 
} 

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults) 
    LocationService.onRequestPermissionsResult(this, requestCode, grantResults) 
} 

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 
    super.onActivityResult(requestCode, resultCode, data) 
    LocationService.onActivityResult(this, requestCode, resultCode) 
} 

private fun yourFunction() { 
    LocationService.getLocation(this, { location -> 
     //TODO: use the location 
    }, { 
     //TODO: display error message 
    }) 
} 
Verwandte Themen