J'ai créé un programme qui dit "Lorsque vous appuyez sur le bouton de démarrage de MainActivity, le service démarre", et chaque fois que vous appuyez sur le bouton de démarrage, plusieurs services démarrent! .. C'est donc un rappel sur la façon d'éviter les bottes en double.
La méthode d'utilisation de la méthode ActivityManager.RunningServiceInfo () semble être obsolète </ font>, et chaque méthode d'ActivityManager est utilisée dans le processus de développement tel que le débogage. , C'était une référence pour ne pas l'utiliser dans le code qui exécute l'application terminée, est-ce donc judicieux de ne pas utiliser la méthode ActivityManager?
API26
** Fichiers principaux **
MainActivity.java
MyService.java: étend le service
MainActivity.java
■ Bouton Démarrer. Événement de clic:
Reportez-vous à la variable globale MyServiceState de MyService.class et démarrez MyService.java lorsque MyServiceState == false
■ Bouton Arrêter. Cliquez sur l'événement: exécutez
stopService () pour arrêter MyService.class
** MyService.java **
Variable globale: public static boolean Set MyServiceState = false;
When onCreate (): Replace with MyServiceState = true;
onStartCommand (): Run Log ..
onDestroy (): Remplacez par MyServiceState = false;
■ Explication Déclarez les variables globales et statiques dans MyService.class. La valeur de cette variable détermine si le service est en cours d'exécution. Dans le code ci-dessous, la variable est définie sur une valeur booléenne, et si elle est fausse, elle n'est pas démarrée, et si elle est vraie, elle est démarrée. En se référant à la valeur de la variable MyService.class d'ActivityMain.class, il est jugé si le service est démarré ou non.
■ Confirmation du comportement Si vous définissez MyServiceState = false; </ font> dans onCreate () de MyService.class, le journal sera lu chaque fois que vous appuyez sur le bouton de démarrage. Si vous définissez MyServiceState = true; </ font>, le journal ne circulera qu'une seule fois, quel que soit le nombre de fois que vous appuyez sur le bouton de démarrage (MyService sera détruit lorsque vous appuyez sur le bouton d'arrêt, donc à nouveau. Vous pouvez jouer à Log une fois avec le bouton de démarrage)
(Mise en garde) API26 et versions ultérieures planteront si le service n'est pas démarré sans notification et exécution de startForeground () </ strong> dans les 5 secondes </ font>. Dans le code ci-dessous, si vous définissez la notification, le code sera long et difficile à voir, de sorte que le traitement des notifications n'est pas effectué en raison de plantages. Ce code sert uniquement à vérifier le comportement de ne pas démarrer le service deux fois. Ajoutez le code de non-crash correspondant à l'API 16 à 29 à la fin ([Exemple de code d'application résidente compté par Log]).
Avec cela, le code commence ci-dessous!
ActivityMain.java
ActivityMain.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_start = findViewById(R.id.btn_start);
Button btn_stop = findViewById(R.id.btn_stop);
final Intent intent = new Intent(this,MyService.class);
btn_start.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
// MyService.Reportez-vous à la variable MyServiceState de la classe
// MyServiceState=Si faux, démarrez le service
if(MyService.MyServiceState == false){
startForegroundService(intent);
}
}
});
btn_stop.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
stopService(intent);
}
});
}
MyService.java
MyService.java
public class MyService extends Service {
//Déclarez la variable statique globale MyServiceState avec une valeur initiale de false
// onCreate()En substituant vrai dans
//Vous pouvez déterminer si le service est onCreate en vous référant à MyServiceState.
public static boolean MyServiceState = false;
public MyService() {
}
@Override
public void onCreate(){
super.onCreate();
//Définir le MyServiceState statique global sur true
MyServiceState = true;
}
@Override
public int onStartCommand(Intent intent,int flags,int startId){
Log.d("Service","Started");
return START_NOT_STICKY;
}
@Override
public void onDestroy(){
super.onDestroy();
MyServiceState = false;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
SDK cible td> | API29 td> |
SDK minimum td> | API16 td> |
Manifeste ajouté td> | uses-permission android: name = "android.permission.FOREGROUND_SERVICE" td> |
Fichiers principaux td> | MainActivity.java MyService.java td> |
Autre td> | Définissez le contenu de la notification. L'icône de notification est votre choix td> |
■ Explication Le code ci-dessous, contrairement à l'exemple de code ci-dessus, confirme la version de l'API de 16 à 29. J'ai mis une notification dans la zone de notification pour éviter qu'elle ne plante.
Lorsque vous appuyez sur Démarrer sur l'écran de l'interface utilisateur, un message de comptage sera lu dans le journal, un bouton d'arrêt arrêtera le message et Start relira un message de comptage. Même si vous appuyez continuellement sur le bouton de démarrage, le message de comptage ne sera pas dupliqué.
Puis, tout en étant enfantin (honte) MainActivity.java
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_start = findViewById(R.id.btn_start);
Button btn_stop = findViewById(R.id.btn_stop);
final Intent intent = new Intent(this,MyService.class);
//Bouton Start
//Démarrez MyService si l'état de la variable MyService est faux
btn_start.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
if(MyService.state == false){
if(Build.VERSION.SDK_INT >=26){
startForegroundService(intent);
}else{
startService(intent);
}
}
}
});
//Bouton d'arrêt
btn_stop.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
stopService(intent);
}
});
}
}
MyService.java
MyService.java
public class MyService extends Service {
//Variables qui déterminent l'état du thread
//Le fil démarre lorsque le signal est vrai, s'arrête lorsqu'il est faux
//défini sur true avec onCreate et false avec onDestroy
private boolean signal;
//Variable qui détermine s'il faut démarrer MyService
public static boolean state = false;
public MyService() {
}
@Override
public void onCreate(){
super.onCreate();
state = true;
}
@Override
public int onStartCommand(Intent intent,int flags,int startId){
//Création de contenu de notification et émission de notifications
Notification notification;
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"id");
Intent intentm = new Intent(this,MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intentm,0);
notification = builder.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("title")
.setContentText("text")
.setContentIntent(pendingIntent)
.build();
if(Build.VERSION.SDK_INT >=26){
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel("id","name",importance);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
startForeground(1,notification);
}else{
notification = builder.setPriority(NotificationCompat.PRIORITY_LOW).build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
managerCompat.notify(1,notification);
}//Ceci est le code d'émission de notification
signal = true;
startThread();
return START_NOT_STICKY;
}
//Thread qui continue d'exécuter le journal
public void startThread(){
new Thread(new Runnable(){
@Override
public void run() {
int i=0;
//Fonctionne jusqu'à ce que le signal soit faux sur onDestroy
while(signal){
try {
sleep(1000);
Log.d("COUNT", String.valueOf(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}).start();
}
@Override
public void onDestroy(){
super.onDestroy();
//Émettre un signal d'arrêt de fil
signal = false;
//Représente l'état inactif du service
state = false;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Recommended Posts