Dauerhaft laufender Service, auch wenn App in Übersicht geschlossen wird

  • 7 Antworten
  • Letztes Antwortdatum
Status
Dieses Thema wurde gelöst! Zur Lösung springen…
AnnaBauer21

AnnaBauer21

Neues Mitglied
4
Hallo ihr Lieben,

ich hänge an einem Problem fest und verstehe nicht so ganz, warum das so nicht geht.
Vermutlich habe ich noch zu wenig Verständnis in der ganzen Thematik.
Und ich muss gestehen, alles was ich bis jetzt an Code habe ist aus dem Internet und ich verstehe teilweise nicht, warum das so gemacht wird.
Ich habe aktuell leider nicht die Zeit um mich genauer in diese Thematik einzuarbeiten und hoffe ihr könnt mir helfen das zum Laufen zu bringen :D

Folgendes möchte ich erreichen:
  • Nach dem Starten der App gibt es im Activity 2 Buttons
    • Service starten
    • Service beenden
  • Der Service soll dauerhaft weiterlaufen, auch wenn ich die App in der Übersicht schließe
  • Wenn ich jetzt wieder auf das App-Symbol drücke soll die GUI der App wieder geöffnet werden (und das geht aktuell leider nicht)

AndroidManifest.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.kugs.mydailyreminder">
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme">
        
        <activity
            android:name=".Activities.MainMenu"
            android:launchMode="singleTask"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".Helper.YourService"/>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>
    </application>
</manifest>


MainMenu.java
Java:
@SuppressLint("SetTextI18n")
public class MainMenu extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        FirstStartActions();

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_mainmenu);

        final Button bu1 = findViewById(R.id.button1);
        bu1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(new Intent( getApplicationContext(), YourService.class ) );
            }
        });

        final Button bu2 = findViewById(R.id.button2);
        bu2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(new Intent( getApplicationContext(), YourService.class ) );
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
    }

    private void FirstStartActions() {
        if (ContextCompat.checkSelfPermission(MainMenu.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(MainMenu.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
        }
        if (ContextCompat.checkSelfPermission(MainMenu.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(MainMenu.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }
        if (ContextCompat.checkSelfPermission(MainMenu.this, Manifest.permission.FOREGROUND_SERVICE) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(MainMenu.this, new String[]{Manifest.permission.FOREGROUND_SERVICE}, 1);
        }
        if (ContextCompat.checkSelfPermission(MainMenu.this, Manifest.permission.SYSTEM_ALERT_WINDOW) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(MainMenu.this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}, 1);
        }
        if (ContextCompat.checkSelfPermission(MainMenu.this, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(MainMenu.this, new String[]{Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}, 1);
        }
    }
}


YourService.java
Java:
public class YourService extends Service {
    public YourService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId){
        onTaskRemoved(intent);

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Log.d("Service", "" + i++);
        startForegroundService(intent);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Intent restartServiceIntent = new Intent(getApplicationContext(),this.getClass());
        restartServiceIntent.setPackage(getPackageName());
        startService(restartServiceIntent);
        super.onTaskRemoved(rootIntent);
    }

    @Override
    public ComponentName startForegroundService(final Intent service) {
        return super.startForegroundService(service);
    }
}


Info:
  • Wenn ich die App in der Übersicht beende, läuft der Service dennoch weiter (Habe ich mit Logs im Logcat geprüft) allerdings wird onDestroy() nicht aufgerufen.
  • Wenn ich die App erneut öffne sehe ich nur weiß, allerdings wird jetzt onDestroy durchlaufen und ich sehe weiterhin die Logs des Services laufen.
  • Nach sehr sehr langer Zeit (5:30 Minuten) zeigt es mir endlich das MainMenu Activity an, bis dahin sind einige Logs eingegangen, ich weiß leider nicht was diese bedeuten.
    • Bash:
      2024-12-30 21:02:35.503 14053-14053/de.mydailyreminder D/_MainMenu_onDestroy
      2024-12-30 21:02:45.559 14053-14053/de.mydailyreminder I/Choreographer: Skipped 1208 frames!  The application may be doing too much work on its main thread.
      2024-12-30 21:03:25.665 14053-14053/de.mydailyreminder W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@1b045d6
      2024-12-30 21:03:25.682 14053-14053/de.mydailyreminder D/_MainMenu_onCreate
      2024-12-30 21:04:56.351 14053-14053/de.mydailyreminder I/Choreographer: Skipped 5412 frames!  The application may be doing too much work on its main thread.
      2024-12-30 21:06:26.814 14053-14058/de.mydailyreminder I/mydailyreminde: Compiler allocated 4MB to compile void android.widget.TextView.<init>(android.content.Context, android.util.AttributeSet, int, int)
      2024-12-30 21:07:56.998 14053-14053/de.mydailyreminder I/Choreographer: Skipped 10836 frames!  The application may be doing too much work on its main thread.
      2024-12-30 21:07:57.050 14053-14082/de.mydailyreminder D/EGL_emulation: eglMakeCurrent: 0x7f892d642f80: ver 3 1 (tinfo 0x7f891c8bb6c0)
      2024-12-30 21:07:57.073 14053-14082/de.mydailyreminder I/OpenGLRenderer: Davey! duration=180682ms; Flags=0, IntendedVsync=11531791668133, Vsync=11712391660909, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=11712402493540, AnimationStart=11712402768040, PerformTraversalsStart=11712407089640, DrawStart=11712408677140, SyncQueued=11712452209040, SyncStart=11712454714640, IssueDrawCommandsStart=11712454813540, SwapBuffers=11712456359840, FrameCompleted=11712476759940, DequeueBufferDuration=414000, QueueBufferDuration=808000,
  • Die Logs vom Service laufen weiterhin

Was übersehe ich? Was ist falsch oder muss anders gemacht werden?
Ich hoffe, ihr könnt mir helfen.
Vielen lieben Dank!
 
Empfohlene Antwort(en)
Frohes Neues Anna,

ich fange mal hinten an :
ich empfinde es als störend wenn dort Hinweise über im Hintergrund laufende Apps stehen, die man nicht wegwischen kann.
Das wäre nur bis Android 13 der Fall - ab da kann man sie wegwischen.

ABER :
Du bist mit dem ForegroundService bei deiner Anforderung dem Holzweg. (Kanonen auf Spatzen)
Ich vermute, du magst dir einen eigenen Wecker - ähnlich einem PillReminder - basteln.


Das was du benötigst, ist ein TimeScheduler , dem man die/mehrere Uhrzeit(en) vorgibt, wann er reagieren soll.
Kommt die Notification, soll mit einem Druck darauf die entsprechende Activity geöffnet werden - Richtig ?

Dazu kannst du dir den AlarmManager nehmen, oder besser die NachfolgeVariante wäre der WorkManager.

Achte darauf, dass du ab Android 13 auch noch eine zusätzlich Permisson beim Nutzer anfragen musst , um eine Notification erstellen zu können.
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Ergo, deinen Service kannst du getrost in die Tonne hauen .....
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: AnnaBauer21 und jogimuc
Alle Antworten (7)
Moin Anna,

sehr schwer, aus deinem Code die Ursache des Activity - Bugs direkt zu erkennen, denn auf den ersten Blick sieht es recht gut aus.

Deutet allerdings darauf hin, dass die UI zu viel ackern muss.

a)
Klammere mal bitte FirstStartActions(); und das Handling der Buttons aus
Startet dann die App ordungsgemäß beim zweiten Male ?

b)
Etwas Bauchschmerzen habe ich, dass du FirstStartActions(); vor der LayoutIniialisierung durchführst.
Setze Diese mal auch auf einen dritten Button-
Zweck : Gibt der UI erst mal Luft , Diese aufzubauen
Wenn das klappt , nimm einen Thread, warte ~ 2000ms und frage erst dann deine Permissions ab.
(Bei Fragen dazu -> melden)

c)
Wenn das nicht hilfft, dann

Code:
 @Override
    public void onTaskRemoved(Intent rootIntent) {
        Intent restartServiceIntent = new Intent(getApplicationContext(),this.getClass());
        restartServiceIntent.setPackage(getPackageName());
        startService(restartServiceIntent);
        super.onTaskRemoved(rootIntent);
    }

aus dem Service raus ... was bezweckst du damit ?



  • Der Service soll dauerhaft weiterlaufen, auch wenn ich die App in der Übersicht schließe
Bitte erkläre einmal genau, was der Service tun soll.

Bei Deinem Foregroundservice fehlt nämlich auch das komplette Notificatiion- Handling.

Hintergrund : Wenn ein (Foreground) Service startet, muss der Nutzer darüber mit einer Notification hingewiesen werden.
Bis A12 bleibt sie dauerhaft sichtbar, ab A13 kann man sie wegwischen (Service bleibt dennoch aktiv)
Mit einem Klick auf diese Notification (PendingIntent) soll sich dann i.d.R. die Activity öffnen


-----------------------------------------------------------------------------------------
Kleine Anmerkung :
Dieser wie auch die vorherigen Beiträge Deinerseits sind eine Wohltat - Präzise, verständlich im Layout , auf den Punkt gebracht und alle Informationen die man benötigt - da macht es Spass zu helfen .. :)

So Mancher kann sich da mal eine Scheibe abschneiden ....
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: Lommel
Hallo swa00,

freut mich sehr, dass du mir wieder hilfst :D

Ich habe die Punkte a-c umgesetzt und es läuft nun um einiges schneller, aber leider noch nicht optimal. (1:20 statt 5:30 Min)

Bash:
2024-12-31 13:51:18.944 15557-15557/de.mydailyreminder D/_MainMenu_onDestroy
2024-12-31 13:51:28.982 15557-15557/de.mydailyreminder I/Choreographer: Skipped 604 frames!  The application may be doing too much work on its main thread.
2024-12-31 13:51:59.007 15557-15557/de.mydailyreminder W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@56a39ae
2024-12-31 13:51:59.025 15557-15557/de.mydailyreminder D/_MainMenu_onCreate
2024-12-31 13:52:19.256 15557-15557/de.mydailyreminder I/Choreographer: Skipped 1201 frames!  The application may be doing too much work on its main thread.
2024-12-31 13:52:39.656 15557-15557/de.mydailyreminder I/Choreographer: Skipped 1221 frames!  The application may be doing too much work on its main thread.
2024-12-31 13:52:39.904 15557-15627/de.mydailyreminder D/EGL_emulation: eglMakeCurrent: 0x7f892bde25c0: ver 3 1 (tinfo 0x7f891c1664c0)

Das Finale Ziel der App soll sein, dass ich die App starte, Einstellungen vornehme und ich täglich eine Erinnerung (Benachrichtigung) erhalte. (Gibt unzählige Apps, die sowas machen, aber da ich was spezielles brauche, wollte ich mir selbst eine einfache App ohne viel Schnickschnack schreiben).
Auch wenn die App (GUI) in der Übersicht geschlossen wird, möchte ich dennoch eine tägliche Benachrichtigung erhalten (dafür der Service). Wenn das Handy neu startet, soll der Service automatisch wieder starten.

Aktuell konzentriere ich mich aber darauf, dass der Service läuft und ich die App wieder öffnen kann, ohne dass es solange braucht.
Ich habe im Bezug auf Services folgende Aussage gefunden:
Caution: A service runs in the same process as the application in which it is declared and in the main thread of that application by default. If your service performs intensive or blocking operations while the user interacts with an activity from the same application, the service slows down activity performance. To avoid impacting application performance, start a new thread inside the service.

Trifft das evtl. auf mich zu?
Wie kann ich das in Verbindung mit startForegroundService umsetzen?
Und ist es überhaupt richtig, dass immer wieder startForegroundService aufgerufen wird?
 
Zuletzt bearbeitet:
Hallo Anna ,

a) Hast du auch die Anzahl von Skippes, wenn du nur a und b umsetzt ?
b) Ich bin mir mittlerweile nicht mehr sicher, ob du überhaupt einen Foregroundservice benötigst.
Welches Ereignis soll denn die Notifcation auslösen ? Zeit ? Datenänderung ?
Umreiße mal bitte, was das Ziel sein soll ...

Wie kann ich das in Verbindung mit startForegroundService umsetzen?
c) Könnte ich erst beantworten, wenn ich die Antwort von b hätte :)

Und ist es überhaupt richtig, dass immer wieder startForegroundService aufgerufen wird?
Nein
 
Zuletzt bearbeitet:
Hallo Stefan,
nur a + b bleibt unverändert, das ausschlaggebende für die Besserung war c.

Jeden Tag um eine bestimmte Uhrzeit möchte ich eine Benachrichtigung erhalten mit einem kurzen Text.
Beim Drücken darauf soll sich eine bestimmte Activity öffnen.

Was ich nicht möchte ist, dass während der Service läuft in der Statusleiste durchgehend was angezeigt wird, ich empfinde es als störend wenn dort Hinweise über im Hintergrund laufende Apps stehen, die man nicht wegwischen kann.
 
Frohes Neues Anna,

ich fange mal hinten an :
ich empfinde es als störend wenn dort Hinweise über im Hintergrund laufende Apps stehen, die man nicht wegwischen kann.
Das wäre nur bis Android 13 der Fall - ab da kann man sie wegwischen.

ABER :
Du bist mit dem ForegroundService bei deiner Anforderung dem Holzweg. (Kanonen auf Spatzen)
Ich vermute, du magst dir einen eigenen Wecker - ähnlich einem PillReminder - basteln.


Das was du benötigst, ist ein TimeScheduler , dem man die/mehrere Uhrzeit(en) vorgibt, wann er reagieren soll.
Kommt die Notification, soll mit einem Druck darauf die entsprechende Activity geöffnet werden - Richtig ?

Dazu kannst du dir den AlarmManager nehmen, oder besser die NachfolgeVariante wäre der WorkManager.

Achte darauf, dass du ab Android 13 auch noch eine zusätzlich Permisson beim Nutzer anfragen musst , um eine Notification erstellen zu können.
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Ergo, deinen Service kannst du getrost in die Tonne hauen .....
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: AnnaBauer21 und jogimuc
Hallo Stefan,

ich habs mit dem WorkManager gerade fertig getestet und es funktioniert wunderbar, auch dass die Notification kommt, obwohl die App beendet oder das Handy neu gestartet wurde!
Vielen lieben Dank für deine Hilfe :D
 
  • Danke
Reaktionen: swa00
Hallo Anna,

Immer wieder gerne :)
 
Status
Dieses Thema wurde gelöst! Zur Lösung springen…

Ähnliche Themen

E
Antworten
25
Aufrufe
1.978
evgkop
E
BerndFfm
Antworten
7
Aufrufe
749
swa00
swa00
D
  • Data2006
3 4 5
Antworten
84
Aufrufe
5.695
jogimuc
J
Zurück
Oben Unten