2017-12-19 10 views
2

ich eine laufende App gemacht habe und dafür hat ihm eine Service-Klasse zu aktualisieren Benutzerposition (entfernt unwichtig Code) gemacht:Zählzeit im Hintergrund Service

public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, ILocationConstants { 

    private static final String TAG = LocationService.class.getSimpleName(); 
    protected GoogleApiClient mGoogleApiClient; 
    protected LocationRequest mLocationRequest; 

    private LocationData data; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     data = new LocationData(); 

     startForeground(); 
    } 

    private void startForeground() { 
     //BUIDLING A NOTIFICATION 

     startForeground(101, notification); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 

     data = Parcels.unwrap(intent.getParcelableExtra(LOCATION_MESSAGE)); 

     buildGoogleApiClient(); 

     mGoogleApiClient.connect(); 

     if (mGoogleApiClient.isConnected()) { 
      startLocationUpdates(); 
     } 

     return START_STICKY; 
    } 

    protected synchronized void buildGoogleApiClient() { 

     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 

     createLocationRequest(); 
    } 

    protected void createLocationRequest() { 
     mLocationRequest = new LocationRequest(); 

     mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); 
     mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); 
     mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
    } 

    protected void startLocationUpdates() { 

     try { 

      LocationServices.FusedLocationApi.requestLocationUpdates(
        mGoogleApiClient, mLocationRequest, this); 

     } catch (SecurityException ex) { 


     } catch (Exception e) { 

     } 
    } 

    private void sendUpdates() { 

     data.millisecondTime = SystemClock.uptimeMillis() - data.startTime; 
     data.updateTime = data.timeBuff + data.millisecondTime; 
     data.seconds = (int) (data.updateTime/1000); 
     data.minutes = data.seconds/60; 
     data.hours = data.minutes/60; 
     data.minutes = data.minutes % 60; 
     data.seconds = data.seconds % 60; 
     data.milliSeconds = (int) (data.updateTime % 1000); 

     Intent locationIntent = new Intent(); 
     locationIntent.setAction(LOACTION_ACTION); 
     locationIntent.putExtra(LOCATION_MESSAGE, Parcels.wrap(data)); 

     LocalBroadcastManager.getInstance(this).sendBroadcast(locationIntent); 
    } 

    protected void stopLocationUpdates() { 
     LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 
    } 

    @Override 
    public void onDestroy() { 
     stopLocationUpdates(); 

     mGoogleApiClient.disconnect(); 

     super.onDestroy(); 
    } 

    @Override 
    public void onConnected(Bundle connectionHint) throws SecurityException { 
     Log.i(TAG, "Connected to GoogleApiClient"); 

     if (data.mLastLocation == null) { 
      data.mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
      sendUpdates(); 
     } 

     startLocationUpdates(); 

    } 

    @Override 
    public void onLocationChanged(Location location) { 

     sendLocationChanged(location); 

     Log.d(TAG, "onLocationChanged: " + location.getLatitude() + ", " + location.getLongitude()); 

     sendUpdates(); 

    } 

    public void sendLocationChanged(Location location) { 
     //SEND DATA TO THE SERVER 
    } 

    @Override 
    public void onConnectionSuspended(int cause) { 

     mGoogleApiClient.connect(); 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult result) { 

     Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     throw new UnsupportedOperationException("Not yet implemented"); 
    } 

} 

Nach jeder Location Update Ich bin Berechnung der verstrichenen Zeit (ich muss dies tun, indem ich hinzufüge, weil der Benutzer die Aktivität pausieren kann). Das Problem ist, wenn ich die App in meiner Bürozeit laufen lasse, ist genau (zum Beispiel 35 Minuten), aber wenn ich Fahrrad fahre, ist die Zeit zu kurz (zeigt 15 Minuten, wenn tatsächlich etwa 30 Minuten vergangen sind). Für die Zeit perspective der einzige Unterschied ist, dass es häufiger aufgerufen wird (in Office-GPS wird nur alle 10-20 Sekunden aktualisiert, aber außerhalb kann sogar alle 2 Sekunden). Die Route und die Entfernung sind in Ordnung - Service ist nicht getötet oder so ähnlich. Ich aktualisiere auch die Zeit in der Aktivität, aber ersetze sie bei jedem Update mit der übertragenen (durch den Dienst) Zeit, aber selbst das Entfernen dieses Problems hat das Problem nicht behoben. Warum passiert dies?

Antwort

1

Wie in den SystemClock documentation erwähnt, wird

uptimeMillis() in Millisekunden gezählt, da das System gebootet wurde. Diese Uhr stoppt, wenn das System Tiefschlaf eintritt (CPU aus, Anzeige dunkel, Vorrichtung für die externe Eingabe wartet)

Das mag der Grund sein, warum haben Sie verschiedene Zeiten zu erhalten. Auf der anderen Seite gibt es elapsedRealtime() und elapsedRealtimeNanos() Methoden, die

die Zeit, da das System gebootet wurde zurückkehren und umfassen tiefen Schlaf. Diese Uhr ist garantiert monotone zu sein, und wird auch fortgesetzt ticken, wenn die CPU in Stromsparmodi ist, so ist die Verwendung einer von ihnen Grundlage für Allzweck Intervall Timing

Versuche empfehlen.

+0

Das ist es! Die Verwendung von elapsedRealtime() hat das Problem behoben. Ich habe nie erwartet, dass updateMillis() so funktioniert. – Makalele

0

Ich würde vorschlagen, die Zeit, die Sie in OnLocationChanged mit jedem Standort Update erhalten() verwenden und es zu Ihrem Sendupdates() über Methode

void onLocationChanged(Location location){ 

    long currentTime=location.getTime(); // unix time in milliseconds 

    ....... 

    sendUpdates(currentTime); 

} 

dann in Sendupdates (long current) tun die Zeitberechnungen. Wenn ich richtig verstanden habe, interessiert Sie nur die verstrichene Zeit seit dem Start Ihrer App. In diesem Fall können Sie Ihr Objekt vereinfachen, indem Sie nur data.startTime, data.seconds, data.minutes und data.hours für die verstrichene Zeit verwenden. Sie können die Startzeit vom Ort des ersten Fixes nach dem Start der App erhalten (mit Flag oder ähnlichem, um den ersten Fix zu erkennen).

Dann in Sendupdates (long current) Ich würde die sec, min, Stunde der verstrichenen Zeit wie folgt berechnen:

int elapsedSeconds=int((currentTime-data.StartTime)/1000); 
data.hours=int(elapsedSeconds/3600); 
data.minutes=int(elapsedSeconds/60)-60*data.hours; 
data.seconds=elapsedSeconds-60*(data.minutes+60*data.hours); 
+0

Danke, coole Lösung, doch @Kirill Simonov Lösung ist leichter als diese. – Makalele