2017-02-17 3 views
1

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(b‌​oolean)' 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!

Antwort

1

Sie sollten den Dienst verwenden, um Aufgaben auszuführen, die auch dann ausgeführt werden müssen, wenn die Anwendung nicht ausgeführt wird. Versuche es.

+0

Ich werde das jetzt versuchen. –

+0

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' –

+0

@ k.schaaf versuchen Sie die reguläre. –

0

So habe ich einige Tutorials gefolgt und gesucht und versucht, mehr, um die Lösung herauszufinden:

  1. Machen Sie einen neuen Service:
package com.name.name; 


import android.app.AlertDialog; 
import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.Service; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.graphics.BitmapFactory; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.provider.Settings; 
import android.util.Log; 

import static com.name.name.MapsActivity.NOTIFICATION_ID; 

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; 
    } 

} 
  1. Führen Sie diesen Service jedes Mal, wenn Sie möchten, mit einem Handler und Runable und verwenden Sie einen Wakelock:
    • in OnCreate:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); 
    wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 
      "MyWakelockTag"); 
  • mit den erworbenen Daten Sachen tun bilden die LocationService.
  • Starten Sie diese Funktion, wenn Sie die Daten und Dinge tun, mit ihm brauchen:

public void startDoingStuffWithLocationData() {

   final Runnable runnable= new Runnable() { 
        public void run() { 
         // do stuff here 
         getLocation(); 
         } 

         else { 
          handler.postDelayed(this, 10000); 
         } 
        } 
       }; 
       runnable.run(); 
      } 
    } 
  • die Daten aus der Kundenbetreuung:

public void getLocation() {

wakeLock.acquire(); 

    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); 
    } 

    else { 
     gps.showSettingsAlert(); 
    } 

    wakeLock.release(); 
} 

Seien Sie sicher, dass die Freigabe() Funktion verwenden, um die WakeLock zu beenden Batterie zu schonen.

Verwandte Themen