简体   繁体   中英

Android Service dies in when I close the Activity that launched it

I'm trying to make an android app that launches a service which runs in the background while the app is open, and doesn't die when the app is closed. However, my service does seem to die upon exit (or at some point, anyhow), because when I restart the app my check to see if the service is running is false. My code:

MainActivity.java

public class MainActivity extends AppCompatActivity {

  private ToggleButton enableButton;
  private boolean isRunning;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    enableButton = findViewById(R.id.enableButton);
    setRunning(MyService.running());
    enableButton.setChecked(isRunning);
    enableButton.setEnabled(true);
    enableButton.setClickable(true);
  }

  private void setRunning(boolean isRunning) {
    this.isRunning = isRunning;
  }

  public void onToggleEnable(View view) {
    boolean enabled = enableButton.isChecked();
    Intent intent = new Intent(this, MyService.class);
    if (enabled) startService(intent);
    else stopService(intent);
    setRunning(enabled);
  }

}

MyService.java

public class MyService extends Service {

  private static boolean running = false;

  public static boolean running() {
    return running;
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    running = true;
    return START_STICKY;
  }

  @Override
  public void onDestroy() {
    running = false;
  }

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

}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.chuckles.iscream">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="false" />
    </application>

</manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ToggleButton
            android:id="@+id/enableButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:onClick="onToggleEnable"
            android:textOff="@string/screamOff"
            android:textOn="@string/screamOn"
            android:layout_gravity="center_horizontal" />

    </LinearLayout>

</ScrollView>

strings.xml

<resources>
    <string name="app_name">iScream</string>
    <string name="screamOn">Disable iScream</string>
    <string name="screamOff">Enable iScream</string>
</resources>

Your Service may killed by the System. From official doc:

The Android system force-stops a service only when memory is low and it must recover system resources for the activity that has user focus. If the service is bound to an activity that has user focus, it's less likely to be killed; if the service is declared to run in the foreground, it's rarely killed.

So if you want to keep running your Service while your app is not open then your Service should be declared to run in the foreground . For this you have to call startForeground(ONGOING_NOTIFICATION_ID, notification);

As stated here:

https://developer.android.com/guide/components/services.html

Caution: A service runs in the main thread of its hosting process; the service does not create its own thread and does not run in a separate process unless you specify otherwise.

Use an IntentService instead if you wish it to run in a seperate thread

https://developer.android.com/guide/components/services.html#ExtendingIntentService

The IntentService class does the following:

It creates a default worker thread that executes all of the intents that are delivered to onStartCommand(), separate from your application's main thread.

在清单文件中的服务标签中,只需添加:

android:process=":externalProcess"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM