*Ein Service
ist eine Android-Anwendungskomponente, die Folgendes darstellt:
- Der Wunsch einer Anwendung, langwierige Operationen durchzuführen, ohne mit dem Benutzer zu interagieren.
- Eine Komponente zur Bereitstellung von Funktionen für andere Anwendungen.
Wann sollte ich einen "Service" verwenden?
Verwenden Sie einen Service
, wenn Sie eine lang laufende Operation oder eine Aufgabe haben, die einen langen Lebenszyklus hat. Es ist ein gutes Design, dass lange laufende Operationen im Hintergrund ausgeführt werden.
Ein Beispiel ist eine Aufgabe zur Datensynchronisation im Hintergrund.
Bei dieser Art von Aufgabe können Sie einen "Dienst" erstellen, der regelmäßig oder nach Bedarf ausgeführt wird. Sie können einen Systemalarm verwenden.
Dann kann Ihr Service
beendet werden, wenn die Aufgabe beendet ist.
Durch die Ausführung der Aufgabe im Hintergrund wird der Haupt-Thread davon befreit, diese Aufgaben zu erledigen, wodurch verhindert wird, dass die Benutzeroberfläche eingefroren wird, wenn eine intensive Aufgabe ausgeführt wird.
Obwohl wir auch innerhalb einer Activity
einfach einen neuen Thread
abspinnen können, ist es ein viel besserer und saubererer Weg, die Hintergrundoperationen an einen Service
zu delegieren.
Wo läuft der Service
?
Alle Android-Komponenten, einschließlich "Service", laufen im Haupt-Thread des Anwendungsprozesses.
Der Lebenszyklus von Service
unterscheidet sich vom Lebenszyklus von Activity
. Ersterer ist besser geeignet, um lang laufende Operationen zu handhaben als letzterer.
Sobald wir unsere langlaufenden Operationen in einen Thread
im Hintergrund verschoben haben, können wir diesen Thread
innerhalb des Service
starten und behandeln.
Lang laufende Operationen, die keine Benutzerinteraktion erfordern, sind die besten Kandidaten für die Delegation an einen "Service".
Vorteile eines Service
- Ein
Service
bietet uns einen effizienteren Mechanismus, um lang laufende Operationen von der Benutzeroberfläche zu entkoppeln.
Beispiele für die Verwendung eines Service
(a). Dienste
ohne Benutzereingabe
- Anwendungen, die das Netzwerk häufig nutzen, um nach Updates zu fragen.
- App zum Abspielen von Musik.
- Messaging-Anwendung.
(b). Dienste" mit Benutzereingabe
- Foto-Sharing-Anwendung.
Schnelle "Dienst"-Schnipsel und Anleitungen
1. Wie man einen Service
startet
Im ersten Beispiel haben wir den Klassennamen erhalten:
public static void startService(String className) {
try {
startService(Class.forName(className));
} catch (Exception e) {
e.printStackTrace();
}
}
Im zweiten Beispiel haben wir die Klasse selbst und den Kontext angegeben:
public static void startService(Class<?> cls, Context context) {
Intent intent = new Intent(context, cls);
context.startService(intent);
}
2. Wie man einen Service
stoppt
Nehmen wir an, Sie wollen einen Service
stoppen und Sie haben den Klassennamen erhalten:
public static boolean stopService(String className) {
try {
return stopService(Class.forName(className));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
Was ist, wenn Sie die Klasse selbst erhalten haben?
public static boolean stopService(Class<?> cls, Context context) {
Intent intent = new Intent(context, cls);
return context.stopService(intent);
}
3. Wie man einen Service
bindet
Wir haben zwei Beispiele. Here's the first one:
public static void bindService(String className, ServiceConnection conn, int flags) {
try {
bindService(Class.forName(className), conn, flags);
} catch (Exception e) {
e.printStackTrace();
}
}
dann das zweite Beispiel:
public static void bindService(Class<?> cls, ServiceConnection conn, int flags,Context context) {
Intent intent = new Intent(context, cls);
context.bindService(intent, conn, flags);
}
4. Wie man einen Service
entbindet
public static void unbindService(ServiceConnection conn,Context context) {
context.unbindService(conn);
}
5. Wie man alle laufenden Services
erhält
Sie wollen alle laufenden Services
im System ermitteln und deren Namen als Set
zurückgeben.
public static Set getAllRunningService(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> info = activityManager.getRunningServices(0x7FFFFFFF);
Set<String> names = new HashSet<>();
if (info == null || info.size() == 0) return null;
for (RunningServiceInfo aInfo : info) {
names.add(aInfo.service.getClassName());
}
return names;
}
Schnelle Dienst
Beispiele
1. Wie man Songs in eine ArrayList in einem Service
lädt
Wir muessen dies in einem thread
im Hintergrund tun, da wir unsere Benutzeroberflaeche nicht einfrieren moechten.
Wir werden diese Lieder protokollieren, aber natürlich kann man sie auch in einer recyclerview oder listview darstellen und eine Klasse implementieren, um sie abzuspielen.
Beginnen wir mit der Definition eines Song-Objekts. Dies ist unsere Song-Bean-Klasse:
public final class Song {
private String name;
private String artist;
private String coverUri;
private long time;
private String location;
public String getName() {
return name;
}
public Song setName(String name) {
this.name = name;
return this;
}
public String getArtist() {
return artist;
}
public Song setArtist(String artist) {
this.artist = artist;
return this;
}
public String getCoverUri() {
return coverUri;
}
public Song setCoverUri(String coverUri) {
this.coverUri = coverUri;
return this;
}
public long getTime() {
return time;
}
public Song setTime(long time) {
this.time = time;
return this;
}
public String getLocation() {
return location;
}
public Song setLocation(String location) {
this.location = location;
return this;
}
@Override
public String toString() {
return String.format("name = %s, artist = %s, location = %s",
name,
artist,
location);
}
}
Dann fahren wir fort, unseren Service
zu erstellen.
Sie beginnen mit der Erstellung einer Klasse, die den
implementiert:Service
public class ScanMusicService extends Service {...}
Wenn ein Service
erstellt wird, wird normalerweise die onCreate()
Lebenszyklusmethode vom System aufgerufen.
An dieser Stelle werden wir einen Thread
starten, der unsere Songs scannt und sie in eine Array-Liste im Hintergrund Thread
laden wird:
@Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
@Override
public void run() {
ArrayList<Song> songs = scanSongs(ScanMusicService.this);
LogUtils.d(songs);
ToastUtils.showLongToast(songs.toString());
}
}).start();
}
Die Methode scanSongs()
wird für das Scannen und Füllen unserer Arrayliste mit Songs verantwortlich sein.
Hier ist die vollständige Klasse:
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.IBinder;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import com.jiangkang.tools.bean.Song;
import com.jiangkang.tools.utils.LogUtils;
import com.jiangkang.tools.utils.ToastUtils;
import java.util.ArrayList;
public class ScanMusicService extends Service {
@Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
@Override
public void run() {
ArrayList<Song> songs = scanSongs(ScanMusicService.this);
LogUtils.d(songs);
ToastUtils.showLongToast(songs.toString());
}
}).start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
private ArrayList<Song> scanSongs(Context context) {
ArrayList<Song> result = new ArrayList<>();
ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,
null,
null,
null);
if (cursor != null && !cursor.isClosed() && cursor.moveToFirst()) {
while (cursor.moveToNext()) {
String songName = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String location = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
Song song = new Song();
song.setName(songName)
.setArtist(artist)
.setLocation(location);
LogUtils.d(song.toString());
result.add(song);
}
}
return result;
}
}
Und das ist die Klasse, die uns beim Laden von Songs hilft.
2. Wie man den System Download Manager und Service
zum Herunterladen benutzt
Wir wollen sehen, wie man einen Service
erstellt, der Daten mit dem System DownloadManager herunterladen kann.
Fangen wir gleich damit an. Zuerst erstellen wir einen androiden Service
:
public class DownloadService extends Service {
Dann erstellen wir mehrere Klassen und Instanzfelder in dieser Klasse:
private BroadcastReceiver receiver;
private DownloadManager dm;
private long enqueue;
private String downloadUrl = "http://192.168.3.186/StaffAssistant.apk";
private static String apkname = "StaffAssistant.apk";
Diese sind:
- BroadcastReceiver - unsere Broadcast-Empfänger-Instanz.
- DownloadManager - Unser System-Download-Manager.
enqueue
(long) - Die eindeutige Download-Aufgaben-ID, die vom System-Downloader zugewiesen wurde und mit der die Download-Aufgabe abgefragt oder bearbeitet werden kann.- Download-URL" - Die URL, unter der die Apk heruntergeladen werden kann.
- ApK name - Name der Anwendung
Erinnern Sie sich, dass wir den Service
erweitert haben und noch keine der Methoden implementiert haben, die wir überschreiben müssen. Hier ist eine:
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
Wir geben dort null
zurück und gehen zu unserem onStartCommand()
über.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
....
Dort werden wir zuallererst unseren Download-URL-String über Intent
erhalten.
Anschließend instanziieren wir unsere BroadcastReceiver-Klasse und überschreiben die Methode onReceive()
.
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
install(context);
}
};
Innerhalb der Methode onReceive()
können Sie sehen, dass wir die Methode install()
aufrufen. Diese Methode ist eine eigene Methode, die wir erstellen werden, um unsere Anwendung zu installieren.
Außerhalb unserer onReceive()
Methode werden wir unseren BroadcastReceiver registrieren, da es sich um eine Android Komponente handelt.
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
Sie sehen deutlich, dass wir ihn programmatisch registriert haben, da wir ihn als anonyme Klasse erstellt haben.
Dann rufen wir die Methode startDownload()
auf, eine weitere benutzerdefinierte Methode, die wir später erstellen werden.
startDownload ( downloadUrl );
Beachten Sie, dass dies eine Schreibberechtigung für die SD-Karte erfordert. Wenn Sie eine targetSDKVersion größer oder gleich 23 verwenden, können Sie dynamische Berechtigungen verwenden.
Schauen wir uns nun an, wie wir die App nach dem Herunterladen programmatisch installieren können.
Zuerst erstellen wir die Methode install()
. Sie erhält ein Context-Objekt, das es uns ermöglicht, die Methode startActivity()
aufzurufen.
public static void install(Context context) {
Dann instanziieren wir eine java.io.File. Wir übergeben den Pfad, in dem wir die Datei erstellen, und den Dateinamen:
File file = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
, apkname);
Dann erstellen wir ein Intent
Objekt:
Intent intent = new Intent(Intent.ACTION_VIEW);
Da die Activity
nicht in der Activity
Umgebung gestartet wird, setzen wir das folgende Label:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Ob die Version über 7.0 liegt.
if (Build.VERSION.SDK_INT >= 24) {
Anschließend rufen wir die Methode getUriForFile()
der Klasse FileProvider
auf. Dazu gehören:
- Context.
- Host-Adresse des Anbieters.
- Die zu installierende Datei.
Uri apkUri =
FileProvider.getUriForFile(context, "com.hzecool.slhStaff.fileprovider", file);
//Adding this sentence means temporarily authorizing the file represented by the Uri to the target application.
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
}
context.startActivity(intent);
}
Dann kommen wir und überschreiben die onDestroy()
Methode der Service
Klasse. hier deregistrieren wir unseren BroadcastReceiver.
@Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
Schauen wir uns nun an, wie man herunterlädt.
Zuerst erstellen wir die Methode startDownload()
:
private void startDownload(String downUrl) {
Zuerst holen wir den System DownloadManager:
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Wir beginnen mit der Instanziierung der Klasse DownloadManager.Request
. Während der Instanzierung analysieren wir unsere Download-Url mit der Methode parse()
der Klasse Uri
und übergeben sie an unsere Klasse Request
:
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downUrl));
Dann setzen wir unseren Mime-Typ oder den Typ der Datei als APK mit der setMimeType()
Methode:
request.setMimeType("application/vnd.android.package-archive");
Dann setzen wir das Ziel für unseren Download mit der Methode setDestinationInExternalPublicDir()
. In diesem Fall verwenden wir das Download-Verzeichnis.
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkname);
Wir rufen die setNotificationVisibility()
auf, um anzugeben, ob eine Benachrichtigung angezeigt werden soll, wenn der Download abgeschlossen ist.
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
Dann setzen wir den Titel
request.setTitle("Download new version");
Zu guter Letzt führen wir den Download durch und geben die eindeutige ID der Aufgabe zurück
enqueue = dm.enqueue(request);
}
}
Hier ist der vollständige Code für den Service
:
import android.app.DownloadManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import java.io.File;
public class DownloadService extends Service {
private BroadcastReceiver receiver;
private DownloadManager dm;
private long enqueue;
private String downloadUrl = "http://192.168.3.186/StaffAssistant.apk";
private static String apkname = "StaffAssistant.apk";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
downloadUrl = intent.getStringExtra("downloadUrl");
if (TextUtils.isEmpty(downloadUrl)) {
apkname = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1, downloadUrl.length());
}
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
install(context);
}
};
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
startDownload(downloadUrl);
return Service.START_STICKY;
}
public static void install(Context context) {
File file = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
, apkname);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 24) {
Uri apkUri =
FileProvider.getUriForFile(context, "com.hzecool.slhStaff.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
}
context.startActivity(intent);
}
@Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
private void startDownload(String downUrl) {
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downUrl));
request.setMimeType("application/vnd.android.package-archive");
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkname);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setTitle("Download new version");
enqueue = dm.enqueue(request);
}
}
Full Service
Examples
Schauen wir uns die vollständigen Standalone-Beispiele an, die Sie herunterladen und ausführen können.
1. Einfaches gebundenes Service
Beispiel
MainActivity.java
Dies ist die Hauptaktivität. Diese Klasse leitet sich von der AppCompatActivity ab und ist für unsere Benutzeroberfläche verantwortlich.
Hier sind einige API-Definitionen, die Sie vielleicht nicht kennen:
(a). SeviceConnection
Dies ist eine Schnittstelle, die sich im Paket android.content
befindet und dazu dient, den Zustand eines Anwendungsdienstes zu überwachen.
(b). IBinder
IBinder
ist die Basisschnittstelle für remotable Objekte, das Kernstück eines leichtgewichtigen Remote-Procedure-Call-Mechanismus, der für hohe Leistung bei prozessinternen und prozessübergreifenden Aufrufen entwickelt wurde.
package com.example.ankitkumar.boundservice;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
BoundService myService;
boolean isBound = false;
TextView currenttime, time, date;
Button btn_start_service;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Set the activity content from a layout resource
setContentView(R.layout.activity_main);
time = (TextView) findViewById(R.id.tv_time);
date = (TextView) findViewById(R.id.tv_date);
currenttime = (TextView) findViewById(R.id.textView_current_time);
btn_start_service = (Button) findViewById(R.id.button_start_service);
Intent intent = new Intent(MainActivity.this, BoundService.class);
/*
Connect to an application service
Automatically create the service as long as the binding exists
*/
bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
}
public void getcurrenttime(View view) {
currenttime.setText(myService.getCurrentTime());
time.setVisibility(View.VISIBLE);
date.setVisibility(View.VISIBLE);
}
//Setting Up BoundService
private ServiceConnection myConnection = new ServiceConnection() {
//Service Connected
public void onServiceConnected(ComponentName className,
IBinder service) {
BoundService.MyLocalBinder binder = (BoundService.MyLocalBinder) service;
myService = binder.getService();
isBound = true;
}
//Service is Disconnected
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
}
BoundService.java
Dies ist unsere "Service"-Subklasse.
package com.example.ankitkumar.boundservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class BoundService extends Service {
//Base interface for a remotable object, the core part of a lightweight remote procedure call mechanism
private final IBinder myBinder = new MyLocalBinder();
//Binding Service
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return myBinder;
}
//Formatting and parsing dates in a locale-sensitive manner
public String getCurrentTime() {
SimpleDateFormat dateformat = new SimpleDateFormat("HH:mm:ss dd/MMM/yyyy", Locale.US);
return (dateformat.format(new Date()));
}
class MyLocalBinder extends Binder {
BoundService getService() {
return BoundService.this;
}
}
}
activity_main.xml
Das Hauptlayout von activity
.
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
tools_context="com.example.ankitkumar.boundservice.MainActivity" android_background="#efedef" android_layout_height="match_parent" android_layout_width="match_parent" android_id="@+id/activity_main" >
<TextView
android_layout_height="wrap_content" android_layout_width="100sp" android_id="@+id/tv_time" android_visibility="gone" android_textStyle="bold" android_textSize="18sp" android_textColor="@android:color/background_dark" android_text="@string/time" android_gravity="end" android_fontFamily="sans-serif-condensed" android_layout_marginTop="40sp"/>
<TextView
android_layout_height="wrap_content"
android_layout_width="140sp" android_id="@+id/tv_date" android_visibility="gone" android_textStyle="bold" android_textSize="18sp" android_textColor="@android:color/background_dark" android_text="@string/date" android_gravity="bottom" android_fontFamily="sans-serif-condensed" android_layout_marginTop="40sp" android_layout_alignParentRight="true" android_layout_alignParentEnd="true"/>
<TextView
android_layout_height="wrap_content" android_layout_width="match_parent" android_id="@+id/textView_current_time" android_textSize="36sp" android_textColor="#ee6f64" android_gravity="center" android_fontFamily="sans-serif-condensed" android_layout_marginTop="70dp" android_hint="@string/time_label" android_layout_centerHorizontal="true"/>
<Button
android_background="#e54048" android_layout_height="60sp" android_layout_width="200sp" android_id="@+id/button_start_service" android_textStyle="bold" android_textSize="18sp" android_textColor="#ffff" android_text="@string/show_time" android_fontFamily="sans-serif-condensed" android_onClick="getcurrenttime" android_layout_centerInParent="true"/>
</RelativeLayout>
Laden Sie den folgenden Code herunter.
No. | Ort | Link |
---|---|---|
1. | GitHub | Download |
2. | GitHub | Durchsuchen |
2. | GitHub | Original Creator: @AnkitKumar111 |
Android IntentService
public abstract class IntentService
extends Service
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.app.Service
↳ android.app.IntentService
IntentService
ist eine Basisklasse für Services
, die asynchrone Anfragen (ausgedrückt als Intents
) bei Bedarf verarbeiten. Clients senden Anfragen durch startService(Intent
)-Aufrufe; der Service
wird nach Bedarf gestartet, bearbeitet jeden Intent
der Reihe nach mit einem Worker Thread
und stoppt sich selbst, wenn er keine Arbeit mehr hat.
Dieses "Warteschlangen-Prozessor"-Muster wird üblicherweise verwendet, um Aufgaben vom Haupt-Thread einer Anwendung zu entlasten. Die Klasse IntentService
existiert, um dieses Muster zu vereinfachen und sich um die Mechanik zu kümmern. Um sie zu verwenden, erweitern Sie IntentService
und implementieren onHandleIntent(Intent
). Der IntentService
empfängt die Intents
, startet einen Thread
und stoppt den Service
nach Bedarf.
Alle Anfragen werden von einem einzigen Worker-Thread bearbeitet - sie können so lange wie nötig dauern (und werden die Hauptschleife der Anwendung nicht blockieren), aber es wird immer nur eine Anfrage bearbeitet.