Ich suche nach einer Lösung, um den Standort des Benutzers in einem bestimmten Zeitintervall in Android API 17 (Android 4.2) zu erhalten und wenn das Telefon gesperrt ist.Abrufen des Benutzerstandorts in Android, wenn das Telefon gesperrt ist
Ich habe bereits einen anderen Code ausprobiert, viele Tutorials überprüft und fast überall im Internet gesucht. Die Lösung mag da sein, aber ich denke, es ist eine Kombination aus mangelnder Erfahrung mit Android, die die verschiedenen richtigen Lösungen und Ansätze entwickelt und interpretiert.
Zuerst hatte ich einen ziemlich einfachen Code, der beim Einschalten des Bildschirms sehr gut funktionierte. Sogar im Hintergrund wurde der Standort aktualisiert (wie ich es über eine Toast-Nachricht mit Längen- und Breitengrad überprüfen konnte). benutzte ich einen Handler, dies zu tun:
public void locationRunnable() {
final Handler locationHandler = new Handler();
final int distanceDelay = 5000; // milliseconds
locationHandler.postDelayed(new Runnable(){
public void run() {
// code
mMap.clear();
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;
}
mMap.setMyLocationEnabled(true);
mMap.setBuildingsEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, true);
myLocation = locationManager.getLastKnownLocation(provider);
if (myLocation != null) {
latitudeCurrentPosition = myLocation.getLatitude();
longitudeCurrentPosition = myLocation.getLongitude();
}
currentPattern = shortTest;
Notification.Builder notificationBuilderChecking = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle("Test app")
.setAutoCancel(true)
.setOnlyAlertOnce(false)
.setContentText("Getting location!")
.setPriority(Notification.PRIORITY_MAX)
.setLights(0xffffffff, 200, 200)
.setVibrate(currentPattern);
Notification notification2 = notificationBuilderChecking.build();
NotificationManager notificationMngr2 = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationMngr2.notify(NOTIFICATION_ID, notification2);
locationHandler.postDelayed(this, distanceDelay);
}
}, distanceDelay);
}
Es ist nur ein Ausschnitt und der Zweck ist, dass im Hintergrund, wenn der Bildschirm gesperrt ist, wird diese Schleife alle 10 Sekunden. Und es tut es. Auch wenn das Telefon gesperrt ist, aber nur für ca. 3 mal. Nach 3 Mal geht der Timer an und das Telefon vibriert weniger häufig (Doze-Funktion im Weg?). Außerdem vibriert das Telefon, aber der Standort wird nicht aktualisiert. Wenn ich das Telefon mit der App im Vordergrund entsperre, ist der Standort immer noch an dem Ort, an dem ich das Telefon gesperrt habe. Nach einer Weile (10 Sekunden) wird es aktualisiert. Ich benutze einen Marker auf der Karte, um zu überprüfen.
Noch einmal: Es funktioniert, wenn das Telefon entsperrt ist.
Jetzt versuche ich einen Service, einen Service (Intent Service) oder einen Broadcast Empfänger zu verwenden und einen neuen Thread zu starten, aber ich weiß nicht wie und nichts funktioniert.
Einige der letzten Code Ich habe enthält eine nicht funktionierende Broadcast-Receiver und der letzte Code enthält einen Alarmmanager:
public void getLocation(Context context) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmIntent.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
//After after 30 seconds
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis(), 10000, pi);
context.getSystemService(Context.CONNECTIVITY_SERVICE);
mMap.clear();
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, true);
myLocation = locationManager.getLastKnownLocation(provider);
latitudeCurrentPosition = myLocation.getLatitude();
longitudeCurrentPosition = myLocation.getLongitude();
LatLng latLngCurrent = new LatLng(latitudeCurrentPosition, longitudeCurrentPosition);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLngCurrent));
mMap.animateCamera(CameraUpdateFactory.zoomTo(distZoom));
currentPattern = shortTest;
showNotification(context);
mHereIAm = mMap.addMarker(new MarkerOptions()
.position(new LatLng(latitudeCurrentPosition, longitudeCurrentPosition))
.title(weAreHere)
.draggable(false)
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.marker_iconv3)));
mHereIAm.setTag(0);
mHereIAm.showInfoWindow();
}
AndroidManifest Berechtigungen:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
aber am langen 10000, Android Studio sagt mir: "Der Wert wird ab Android 5.1 auf 60000 erhöht. Verlasse dich nicht darauf, um genau zu sein ..." usw. Ein AlarmManager ist also auch nicht nützlich. Mit dem letzten Code läuft meine App nicht mehr.
Aber immer noch: Vibrationen und so weiter auftreten, aber Standort-Updates nicht.
Kurz gesagt: Ich brauche einige grundlegende (zumindest denke ich, es kann einfach nicht so schwierig sein, da das einzige Problem ist, dass es nicht funktioniert, wenn der Bildschirm gesperrt ist) Code, der meinen Standort auf einem aktualisiert bestimmtes, variables Intervall.
Vielleicht muss ich einen Handler/Runnable verwenden, einen neuen Thread starten, einen Service oder einen Broadcast Receiver verwenden. Vielleicht funktioniert auch ein AlarmManager, aber ich weiß nicht wie und was zu verwenden ist.
Dies ist mein erster Beitrag. Wenn etwas fehlt oder Sie mehr Informationen benötigen, fragen Sie bitte. Ich versuche, so präzise wie möglich zu sein, ohne zu viel Overhead zu verbrauchen.
Bearbeiten 01 Kann ich einen Job Service dazu verwenden? - Ich habe die API auf 21 aktualisiert, damit ich diesen Service nutzen kann, aber ich weiß nicht, ob das die richtige Lösung ist, nach der ich suche? Habe ein paar tolle Tutorials für den Gebrauch davon.
bearbeiten 02 Lassen Sie uns mit weniger Aufwand mehr klar sein: Ich bin auf der Suche nach einer Lösung des Benutzers aktuellen Standort zu erhalten, wenn das Gerät gesperrt ist: mit einer API, eine Dienstleistung, ein IntentService, ein BroadcastReceiver. .. - jedes Tutorial sagt mir etwas anderes, auch hier bei Stack Overflow habe ich Probleme mit der Suche nach der richtigen Lösung. Ich konnte sowohl einen Service als auch einen Intent-Service verwenden, aber ich kann aufgrund einiger Fehler keine Standort-Updates anfordern, wie: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.name.name/com.name.name.MapsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.GoogleMap.setMyLocationEnabled(boolean)' on a null object reference
- Suche nach einer Lösung für diesen Fehler, gibt mir später einen weiteren Fehler, und weiter und weiter ... Ich steckte mich in eine Fehlerschleife und viel unnötigen Code.
Ich hoffe, es gibt eine einfache Möglichkeit, den Standort des Benutzers zu bekommen, und Sie könnten mir helfen. Danke noch einmal.
bearbeiten 03 Ich habe die Anweisungen auf this tutorial und die Lage ist die Überprüfung gefolgt. Siehe den folgenden Code:
public class LocationService extends Service implements LocationListener {
private final Context mContext;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
Location location; // location
double latitude; // latitude
double longitude; // longitude
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
// Declaring a Location Manager
protected LocationManager locationManager;
public LocationService(Context context) {
this.mContext = context;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) mContext
.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
//isNetworkEnabled = locationManager
// .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
this.canGetLocation = true;
// First get location from Network Provider
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
/**
* Stop using GPS listener
* Calling this function will stop using GPS in your app
* */
public void stopUsingGPS(){
if(locationManager != null){
locationManager.removeUpdates(LocationService.this);
}
}
/**
* Function to get latitude
* */
public double getLatitude(){
if(location != null){
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
* */
public double getLongitude(){
if(location != null){
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
* @return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog
* On pressing Settings button will lauch Settings Options
* */
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
@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;
}
}
Ich deaktiviert Netzwerk Standort haben und nur erlaubt, GPS-Position für den Test - getestet beide.
Und mein MapsActivity:
public void getLocation(){
gps = new LocationService(MapsActivity.this);
if(gps.canGetLocation()) { // gps enabled} // return boolean true/false
latitudeCurrentPosition = gps.getLatitude(); // returns latitude
longitudeCurrentPosition = gps.getLongitude(); // returns longitude
latLngCurrent = new LatLng(latitudeCurrentPosition, longitudeCurrentPosition);
Toast toastLatCur = makeText(getApplicationContext(), "Lat Current: " + latitudeCurrentPosition + "" ,Toast.LENGTH_SHORT);
toastLatCur.show();
Toast toastLongCur = makeText(getApplicationContext(), "Long Current: " + longitudeCurrentPosition + "" ,Toast.LENGTH_SHORT);
toastLongCur.show();
}
else {
gps.showSettingsAlert();
}
if(goToLocation){
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLngCurrent));
goToLocation = false;
if(firstStart){
mMap.animateCamera(CameraUpdateFactory.zoomTo(distZoom));
firstStart = false;
}
}
vibrateNotification();
}
Wenn der Bildschirm gesperrt ist, vibriert das Telefon, als ich in vibrateNotificatoin()
gesagt - funktioniert perfekt alle 10 Sekunden. Aber der Standort wird nicht aktualisiert! Ein Service ist also nicht der richtige Weg, dies zu lösen. Hilfe!
Ich werde das jetzt versuchen. –
IntentService oder ein regulärer Service? Der IntentService gibt mir: 'java.lang.RuntimeException: Aktivität kann nicht gestartet werden ComponentInfo {com.name.name/com.name.name.MapsActivity}: java.lang.NullPointerException: Versuch, virtuelle Methode 'void com.google aufzurufen. android.gms.maps.GoogleMap.setMyLocationEnabled (boolean) 'auf eine Null-Objekt-Referenz' –
@ k.schaaf versuchen Sie die reguläre. –