[JAVA] Programmierung ab 51 Jahren Hinweis: Starten Sie Android Sevice nicht mehr als einmal. Bestätigung des Dienststarts

Wenn ich ein Programm mit der Aufschrift "Wenn Sie die Starttaste von MainActivity drücken, wird der Dienst gestartet" erstellt habe, wurden jedes Mal mehrere Dienste gestartet, wenn Sie die Starttaste drücken! .. Es ist also eine Erinnerung daran, wie man doppelte Stiefel vermeidet.

Die Methode zur Verwendung der ActivityManager.RunningServiceInfo () -Methode scheint veraltet zu sein </ font>, und jede Methode von ActivityManager wird im Entwicklungsprozess wie dem Debuggen verwendet. Es war eine Referenz, es nicht in dem Code zu verwenden, der die fertige Anwendung ausführt. Ist es also sinnvoll, die ActivityManager-Methode nicht zu verwenden?

Beispielcode für die Verhaltensbestätigung

Beispielcodeübersicht

  1. API26

  2. ** Hauptdateien **
    MainActivity.java
    MyService.java: erweitert den Service

  3. MainActivity.java ■ Schaltfläche "Start". Klicken Sie auf "Ereignis":
    Beziehen Sie sich auf die globale Variable MyServiceState von MyService.class und starten Sie MyService.java, wenn MyServiceState == false
    ■ Schaltfläche Stopp. Klicken Sie auf Ereignis: Führen Sie
    stopService () aus, um MyService.class zu stoppen

  4. ** MyService.java **
    Globale Variable: public static boolean Set MyServiceState = false;
    When onCreate (): Ersetzen durch MyServiceState = true;
    onStartCommand (): Protokoll ausführen ..
    onDestroy (): Ersetzen durch MyServiceState = false;

■ Erklärung Deklarieren Sie globale und statische Variablen in MyService.class. Der Wert dieser Variablen bestimmt, ob der Dienst ausgeführt wird. Im folgenden Code wird die Variable auf einen booleschen Wert gesetzt. Wenn false, wird sie nicht gestartet, und wenn true, wird sie gestartet. Anhand des Werts der Variablen MyService.class aus ActivityMain.class wird beurteilt, ob der Dienst gestartet wurde oder nicht.

■ Bestätigung des Verhaltens Wenn Sie MyServiceState = false; </ font> in onCreate () von MyService.class festlegen, wird das Protokoll jedes Mal abgespielt, wenn Sie die Starttaste drücken. Mit MyServiceState = true; </ font> wird das Protokoll unabhängig davon, wie oft Sie die Starttaste drücken, nur einmal ausgeführt (wenn Sie die Stopptaste drücken, wird MyService erneut zerstört Sie können Log einmal mit der Starttaste spielen.

(Hinweis) API26 und höher stürzt ab, wenn der Dienst nicht ohne Benachrichtigung und startForeground () </ strong> Ausführung innerhalb von 5 Sekunden </ font> gestartet wird. Wenn Sie im folgenden Code die Benachrichtigung festlegen, ist der Code lang und schwer zu erkennen, sodass die Benachrichtigungsverarbeitung aufgrund von Abstürzen nicht ausgeführt wird. Dieser Code dient nur zur Überprüfung des Verhaltens, den Dienst nicht zweimal zu starten. Fügen Sie am Ende den Nicht-Absturzcode hinzu, der den API 16 bis 29 entspricht ([Beispielcode der residenten Anwendung, gezählt nach Protokoll]).

Damit beginnt der Code unten!

Beispielcode für die Verhaltensbestätigung


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.Siehe die MyServiceState-Variable der Klasse
            // MyServiceState=Wenn false, starten Sie den 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 {
    //Deklarieren Sie die globale statische Variable MyServiceState mit dem Anfangswert false
    // onCreate()Durch Ersetzen von true in
    //Sie können feststellen, ob Service onCreate ist, indem Sie auf MyServiceState verweisen.
    public static boolean MyServiceState = false;

    public MyService() {
    }

    @Override
    public void onCreate(){
        super.onCreate();
        //Setzen Sie den globalen statischen MyServiceState auf 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;
    }
}

Beispielcode der residenten Anwendung, die im Protokoll gezählt werden soll

Ziel-SDK API29
Minimum SDK API16
Manifest hinzugefügt verwendet die Berechtigung android: name = "android.permission.FOREGROUND_SERVICE"
Hauptdateien MainActivity.java
MyService.java
Andere Legen Sie den Benachrichtigungsinhalt fest. Das Benachrichtigungssymbol ist Ihre Wahl

■ Erklärung Der folgende Code bestätigt im Gegensatz zum obigen Beispielcode die API-Version von 16 bis 29. Ich habe eine Benachrichtigung in den Benachrichtigungsbereich eingefügt, um einen Absturz zu verhindern.

Wenn Sie auf dem UI-Bildschirm auf Start drücken, wird eine Zählnachricht im Protokoll abgespielt, eine Stoppschaltfläche stoppt die Nachricht und Start spielt erneut eine Zählnachricht ab. Selbst wenn Sie die Starttaste kontinuierlich drücken, wird die Zählnachricht nicht dupliziert.

Dann, während kindisch (Schande) 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);
        //Start Knopf
        //Starten Sie MyService, wenn der Status der MyService-Variablen false ist
        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);
                    }
                }
            }
        });

        //Stopptaste
        btn_stop.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                stopService(intent);
            }
        });
    }
}

MyService.java

MyService.java


public class MyService extends Service {
    //Variablen, die den Status des Threads bestimmen
    //Thread startet, wenn das Signal wahr ist, stoppt, wenn falsch
    //mit onCreate auf true und mit onDestroy auf false setzen
    private boolean signal;

    //Variable, die bestimmt, ob MyService gestartet werden soll
    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){
        //Benachrichtigungsinhalt erstellen und Benachrichtigungen ausgeben
        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);
        }//Dies ist der Benachrichtigungsausgabecode

        signal = true;
        startThread();
        return START_NOT_STICKY;
    }

    //Thread, der weiterhin ausgeführt wird Protokoll
    public void startThread(){
        new Thread(new Runnable(){
            @Override
            public void run() {
                int i=0;

                //Läuft, bis das Signal bei onDestroy falsch ist
                while(signal){
                    try {
                        sleep(1000);
                        Log.d("COUNT", String.valueOf(i));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                }
            }
        }).start();
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        //Thread-Stopp-Signal ausgeben
        signal = false;

        //Repräsentiert den inaktiven Status des Dienstes
        state  = false;
    }

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

Recommended Posts