Android
Bedienung
Suche…
Einführung
Ein Dienst wird im Hintergrund ausgeführt , um lange andauernde Vorgänge auszuführen oder um Arbeit für Remote-Prozesse auszuführen. Ein Dienst bietet keine Benutzeroberfläche, die nur im Hintergrund mit Benutzereingaben ausgeführt wird. Beispielsweise kann ein Dienst Musik im Hintergrund abspielen, während sich der Benutzer in einer anderen App befindet, oder er kann Daten aus dem Internet herunterladen, ohne die Interaktion des Benutzers mit dem Android-Gerät zu blockieren.
Bemerkungen
Wenn Sie Ihren Dienst nicht in Ihrer AndroidManifest.xml definiert haben, erhalten Sie beim Starten des Diensts eine ServiceNotFoundException
.
Hinweis:
Informationen zu IntentService
finden Sie hier: IntentService-Beispiel
Service starten
Das Starten eines Dienstes ist sehr einfach. Rufen startService
einfach startService
mit einer Absicht aus einer Aktivität heraus auf:
Intent intent = new Intent(this, MyService.class); //substitute MyService with the name of your service
intent.putExtra(Intent.EXTRA_TEXT, "Some text"); //add any extra data to pass to the service
startService(intent); //Call startService to start the service.
Lebenszyklus eines Dienstes
Der Servicelebenszyklus hat die folgenden Rückrufe
-
onCreate()
:
Wird ausgeführt, wenn der Service zum ersten Mal erstellt wird, um die erforderlichen Anfangskonfigurationen einzurichten. Diese Methode wird nur ausgeführt, wenn der Dienst noch nicht ausgeführt wird.
-
onStartCommand()
:
startService()
jedes Mal ausgeführt, wenn startService()
von einer anderen Komponente wie einer Aktivität oder einem BroadcastReceiver aufgerufen wird. Wenn Sie diese Methode verwenden, wird der Dienst ausgeführt, bis Sie stopSelf()
oder stopService()
. Beachten Sie, dass die Methoden stopSelf()
und stopService()
nur einmal aufgerufen werden müssen, unabhängig davon, wie oft Sie onStartCommand()
stopSelf()
, um den Dienst zu stoppen.
-
onBind()
:
bindService()
ausgeführt, wenn eine Komponente bindService()
und eine Instanz von IBInder zurückgibt, die einen Kommunikationskanal für den Service bereitstellt. Ein Aufruf von bindService()
hält den Dienst so lange an, wie Clients daran gebunden sind.
-
onDestroy()
:
Wird ausgeführt, wenn der Dienst nicht mehr verwendet wird, und ermöglicht die Entsorgung der zugewiesenen Ressourcen.
Es ist wichtig zu beachten, dass während des Lebenszyklus eines Diensts andere Callbacks aufgerufen werden können, z. B. onConfigurationChanged()
und onLowMemory()
https://developer.android.com/guide/components/services.html
Definieren des Prozesses eines Services
Das android:process
Feld definiert den Namen des Prozesses, in dem der Dienst ausgeführt werden soll. Normalerweise werden alle Komponenten einer Anwendung in dem Standardprozess ausgeführt, der für die Anwendung erstellt wurde. Eine Komponente kann jedoch den Standardwert mit einem eigenen Prozessattribut überschreiben, sodass Sie Ihre Anwendung auf mehrere Prozesse verteilen können.
Wenn der diesem Attribut zugewiesene Name mit einem Doppelpunkt (':') beginnt, wird der Dienst in einem separaten Prozess ausgeführt.
<service
android:name="com.example.appName"
android:process=":externalProcess" />
Wenn der Prozessname mit einem Kleinbuchstaben beginnt, wird der Dienst in einem globalen Prozess mit diesem Namen ausgeführt, sofern er dazu berechtigt ist. Dadurch können Komponenten in verschiedenen Anwendungen einen Prozess gemeinsam nutzen, wodurch der Ressourcenverbrauch reduziert wird.
Bound Service mit Hilfe von Binder erstellen
Erstellen Sie eine Klasse, die die Service
Klasse erweitert und in der überschriebenen Methode onBind
Ihre lokale onBind
zurückgeben:
public class LocalService extends Service {
// 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 {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
Dann binden Sie in Ihrer Aktivität an den Service in onStart
callback, verwenden die ServiceConnection
Instanz und binden die Bindung von ihr in onStop
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Defines callbacks for service binding, passed to bindService() */
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;
}
};
}
Remote-Service erstellen (über AIDL)
Beschreiben Sie Ihre Service-Zugriffsschnittstelle über die .aidl
Datei:
// IRemoteService.aidl
package com.example.android;
// Declare any non-default types here with import statements
/** Example service interface */
interface IRemoteService {
/** Request the process ID of this service, to do evil things with it. */
int getPid();
}
Nach dem Erstellen der Anwendung generieren die sdk-Tools die entsprechende .java
Datei. Diese Datei enthält die Stub
Klasse, die unsere Hilfsschnittstelle implementiert und die wir erweitern müssen:
public class RemoteService extends Service {
private final IRemoteService.Stub binder = new IRemoteService.Stub() {
@Override
public int getPid() throws RemoteException {
return Process.myPid();
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
Dann in Tätigkeit:
public class MainActivity extends AppCompatActivity {
private final ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
IRemoteService service = IRemoteService.Stub.asInterface(iBinder);
Toast.makeText(this, "Activity process: " + Process.myPid + ", Service process: " + getRemotePid(service), LENGTH_SHORT).show();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, RemoteService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
unbindService(connection);
}
private int getRemotePid(IRemoteService service) {
int result = -1;
try {
result = service.getPid();
} catch (RemoteException e) {
e.printStackTrace();
}
return result;
}
}
Erstellen eines ungebundenen Dienstes
Als Erstes fügen Sie den Service zu AndroidManifest.xml
im <application>
-Tag hinzu:
<application ...>
...
<service
android:name=".RecordingService"
<!--"enabled" tag specifies Whether or not the service can be instantiated by the system — "true" -->
<!--if it can be, and "false" if not. The default value is "true".-->
android:enabled="true"
<!--exported tag specifies Whether or not components of other applications can invoke the -->
<!--service or interact with it — "true" if they can, and "false" if not. When the value-->
<!--is "false", only components of the same application or applications with the same user -->
<!--ID can start the service or bind to it.-->
android:exported="false" />
</application>
Wenn Sie Ihre Serviceklasse in einem separaten Paket verwalten möchten (z. B. .AllServices.RecordingService), müssen Sie angeben, wo sich Ihr Service befindet. In diesem Fall werden wir Folgendes ändern:
android:name=".RecordingService"
zu
android:name=".AllServices.RecordingService"
oder am einfachsten ist es, den vollständigen Paketnamen anzugeben.
Dann erstellen wir die eigentliche Serviceklasse:
public class RecordingService extends Service {
private int NOTIFICATION = 1; // Unique identifier for our notification
public static boolean isRunning = false;
public static RecordingService instance = null;
private NotificationManager notificationManager = null;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate(){
instance = this;
isRunning = true;
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
// Set the info for the views that show in the notification panel.
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher) // the status icon
.setTicker("Service running...") // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle("My App") // the label of the entry
.setContentText("Service running...") // the content of the entry
.setContentIntent(contentIntent) // the intent to send when the entry is clicked
.setOngoing(true) // make persistent (disable swipe-away)
.build();
// Start service in foreground mode
startForeground(NOTIFICATION, notification);
return START_STICKY;
}
@Override
public void onDestroy(){
isRunning = false;
instance = null;
notificationManager.cancel(NOTIFICATION); // Remove notification
super.onDestroy();
}
public void doSomething(){
Toast.makeText(getApplicationContext(), "Doing stuff from service...", Toast.LENGTH_SHORT).show();
}
}
Dieser Dienst zeigt lediglich eine Benachrichtigung an, wenn er ausgeführt wird, und er kann Toasts anzeigen, wenn seine doSomething()
-Methode aufgerufen wird.
Wie Sie feststellen werden, ist es als Singleton implementiert und verfolgt die eigene Instanz - aber ohne die übliche statische Singleton Factory-Methode, da Services von Natur aus Singletons sind und durch Absichten erstellt werden. Die Instanz ist nach außen nützlich, um den Dienst bei seiner Ausführung "in den Griff zu bekommen".
Zuletzt müssen wir den Dienst aus einer Aktivität heraus starten und stoppen:
public void startOrStopService(){
if( RecordingService.isRunning ){
// Stop service
Intent intent = new Intent(this, RecordingService.class);
stopService(intent);
}
else {
// Start service
Intent intent = new Intent(this, RecordingService.class);
startService(intent);
}
}
In diesem Beispiel wird der Dienst abhängig vom aktuellen Status auf dieselbe Weise gestartet und gestoppt.
Wir können auch die doSomething()
-Methode aus unserer Aktivität aufrufen:
public void makeServiceDoSomething(){
if( RecordingService.isRunning )
RecordingService.instance.doSomething();
}