2014-01-29 3 views
6

Ich habe einen Dienst, der eine Benachrichtigung sendet, wenn der Benutzer seinen Standort ändert. Dieser Dienst funktioniert einwandfrei, aber das Problem tritt auf, wenn der Benutzer die App schließt, wenn der Dienst ebenfalls geschlossen wird.Halten Sie den Standortdienst am Leben, wenn die App geschlossen wird

Wie kann ich den Dienst noch am Leben erhalten, obwohl die Anwendung geschlossen wurde?

Mein Service ist:

public class LocationService extends Service implements LocationListener { 
    public final static int MINUTE = 1000 * 60; 


    boolean isGPSEnabled = false; 
    boolean isNetworkEnabled = false; 
    boolean canGetLocation = false; 

    Location location; // location 
    double latitude = 0; // latitude 
    double longitude = 0; // longitude 
    String provider; 

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

    // The minimum time between updates in milliseconds 
    private static final long MIN_TIME_BW_UPDATES = 1 * MINUTE; 

    // Declaring a Location Manager 
    protected LocationManager locationManager; 



    // Binder given to clients 
    private final IBinder mBinder = new LocalBinder(); 

    /** 
    * Class used for the client Binder. Because we know this service always 
    * runs in the same process as its clients, we don't need to deal with IPC. 
    */ 
    public class LocalBinder extends Binder { 
     public LocationService getService() { 
      // Return this instance of LocalService so clients can call public 
      // methods 
      return LocationService.this; 
     } 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return mBinder; 
    } 

    public Location getLocation() { 
     try { 
      locationManager = (LocationManager) getBaseContext().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. DEFAULT COORDINATES 


      } else { 
       this.canGetLocation = true; 
       if (isNetworkEnabled) { 
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, 
          this); 
        Log.d("Network", "Network Enabled"); 
        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", "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(); 
     } 
     Log.i("LOCATION", "Latitude: " + latitude + "- Longitude: " + longitude); 


     return location; 
    } 

    @Override 
    public void onLocationChanged(Location arg0) { 

     NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); 
     Intent intent = null; 

     intent = new Intent(this, CompleteSurveyActivity.class); 

     PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 

     NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_launcher).setAutoCancel(true) 
       .setContentIntent(contentIntent).setContentTitle(this.getString(R.string.app_name)).setContentText("text"); 

     // mBuilder.setContentIntent(contentIntent); 
     mNotificationManager.notify((int) System.currentTimeMillis() % Integer.MAX_VALUE, mBuilder.build()); 

     double longitude = location.getLongitude(); 
     double latitude = location.getLatitude(); 

     Log.i("LOCATION", "Latitude: " + latitude + "- Longitude: " + longitude); 

    } 

    @Override 
    public void onProviderDisabled(String arg0) { 
    } 

    @Override 
    public void onProviderEnabled(String arg0) { 
    } 

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

} 

ich von hier genannt:

public class MyActivity extends Activity { 

    LocationService mService; 
    boolean mBound = false; 


    private ServiceConnection mConnection = new ServiceConnection() { 

     @Override 
     public void onServiceConnected(ComponentName className, IBinder service) { 
      // We've bound to LocalService, cast the IBinder and get 
      // LocalService instance 
      LocalBinder binder = (LocalBinder) service; 
      mService = binder.getService(); 
      mBound = true; 

     } 

     @Override 
     public void onServiceDisconnected(ComponentName arg0) { 
      mBound = false; 
     } 
    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.my_activity); 

     exampleButton.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       initService(); 
      } 
     }); 

    } 

    public void initService() { 
     if (mBound) 
      mService.getLocation(); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     // Bind to LocalService 
     Intent intent = new Intent(this, LocationService.class); 
     bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     // Unbind from the service 
     if (mBound) { 
      unbindService(mConnection); 
      mBound = false; 
     } 
    } 
} 

Manifest.xml

<service android:name=".LocationService" android:enabled="true"></service> 
+0

Können Sie uns den neuen Code für unbegrenzten Service bereitstellen? @sany –

Antwort

8

entgegen zu vermeiden, was @ sven-Menschner sagte, ich glaube, ein ungebundenes Service ist genau das, was Sie brauchen, als gebundenes Dienste unterliegen Bind/Unbind-Mechanismen, die Ihren Dienst zerstören würden. Das ist, was ich tun würde:

In Ihrer Manifest-Datei definieren Sie da:

<service 
    android:name=".YourService" 
    android:enabled="true" 
    android:exported="true" 
    android:description="@string/my_service_desc" 
    android:label="@string/my_infinite_service"> 
    <intent-filter> 
    <action android:name="com.yourproject.name.LONGRUNSERVICE" /> 
    </intent-filter> 
</service> 

Hinweis: Es gibt eine Liste von bereits durchgeführten Aktionen, aber Sie können Ihre eigenen Aktionen für die Absicht Start definieren der Service. Erstellen Sie einfach eine Singleton-Klasse und definieren Sie die Strings, die ihnen eine String zuweisen, die eindeutig sein sollte. Wenn "enabled" auf "true" gesetzt ist, wird der Dienst nur instanziiert, und "extended" wird auf "true" gesetzt, wenn Sie andere Anwendungen benötigen, die Absichten an Ihre Service senden. Ist dies nicht der Fall, können Sie letzteres auf false setzen.

Der folgende Schritt würde Ihren Dienst von Ihrer Tätigkeit beginnen. Das kann leicht durch geschehen:

public class MainActivity extends Activity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    Intent servIntent = new Intent("com.yourproject.name.LONGRUNSERVICE"); 
    startService(servIntent); 

    ... 
    } 
} 

Der letzte Schritt Ihre Service Initialisierungen zu definieren ist. Behalten Sie die Methode onBind() im Auge. Da Sie nicht möchten, dass es gebunden wird, geben Sie einfach null zurück. Es wäre so etwas wie diese:

public class MyService extends Service { 
    @Override 
    public IBinder onBind(Intent intent) { 
    // This won't be a bound service, so simply return null 
    return null; 
    } 

    @Override 
    public void onCreate() { 
    // This will be called when your Service is created for the first time 
    // Just do any operations you need in this method. 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
    return super.onStartCommand(intent, flags, startId); 
    } 
} 

Jetzt Ihr Dienst ausgeführt wird, auch wenn Sie Ihre Haupt Activity schließen. Es gibt nur noch einen Schritt: Um zu helfen, dass Ihr Service nicht fertig ist, führen Sie es als Vordergrund-Service aus (tun Sie das in Ihrem Service). Dies wird im Grunde ein Benachrichtigungssymbol in der Statusleiste erstellen. Dies bedeutet nicht, dass Ihre Hauptaktivität auch ausgeführt wird (deshalb möchten Sie keinen gebundenen Dienst), da Aktivitäten und Dienste unterschiedliche Lebenszyklen haben.Um den Service so lange zu unterstützen, sollten Sie versuchen, den Heap so niedrig wie möglich zu halten, damit Android SO nicht verloren geht.

Noch eine Akklimatisierung: Sie können nicht testen, ob der Dienst immer noch läuft, um den DVM zu beenden. Wenn Sie den DVM töten, werden Sie alles töten, also auch den Dienst.

+1

hat es funktioniert! danke :) – SolArabehety

+0

Oh nein! Ich meinte das Recht, schrieb aber das Falsche. Natürlich ist ein gestarteter (oder ungebundener) Dienst der richtige. Ich habe nur die Reihenfolge im ersten Satz vermasselt ... Aber es konnte herausgefunden werden, was ich von dem Rest meiner Antwort beabsichtigte;) –

2

Es gibt zwei Arten von Android-Diensten: gestartet und gebunden. Sie suchen nach letzterem. The documentation zeigt, wie man es benutzt, gibt es ein schönes Lebenszyklusdiagramm unten.

Anstatt den Dienst in einem Schritt unter Verwendung von bindService() zu starten und zu binden, müssen Sie zuerst startService() anrufen. Dann läuft es, bis Sie es stoppen, auch wenn die App geschlossen ist. Aber vergessen Sie nicht, den Dienst an der richtigen Zeit zu stoppen Gedächtnisprobleme usw.

HTH

Verwandte Themen