Step 1. Add the JitPack repository to your build file
Add it in your root settings.gradle at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Add it in your settings.gradle.kts at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Add to pom.xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add it in your build.sbt at the end of resolvers:
resolvers += "jitpack" at "https://jitpack.io"
Add it in your project.clj at the end of repositories:
:repositories [["jitpack" "https://jitpack.io"]]
Step 2. Add the dependency
dependencies {
implementation 'com.github.cookingfox:android-app-lifecycle:0.3.1'
}
dependencies {
implementation("com.github.cookingfox:android-app-lifecycle:0.3.1")
}
<dependency>
<groupId>com.github.cookingfox</groupId>
<artifactId>android-app-lifecycle</artifactId>
<version>0.3.1</version>
</dependency>
libraryDependencies += "com.github.cookingfox" % "android-app-lifecycle" % "0.3.1"
:dependencies [[com.github.cookingfox/android-app-lifecycle "0.3.1"]]
In an Android app, activities control the lifecycle. However, when attempting to separate logic from Android components, and when the application spans multiple activities, the custom code is typically more interested in the APPLICATION lifecycle. Questions that arise can contain:
This library makes working with the application lifecycle easier, by providing clear hooks
(onAppCreated
, onAppStopped
, etc.) and by allowing activities to trigger lifecycle events with
little extra effort.
This library is compatible with Android from SDK 9 (Gingerbread).
This library uses JitPack for distribution.
Add the JitPack repository to your Android project's ROOT build.gradle
file:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
Add the dependency to your app's build.gradle
file:
dependencies {
compile 'com.github.cookingfox:android-app-lifecycle:0.3.0'
}
There's a sample application showing the basic usage of the library in the /sample
directory.
The recommended way to start using the library is to subclass the android.app.Application
class
and call the provider's initialize method in the onCreate()
method:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
AppLifecycleProvider.initialize(this);
}
}
There are probably some operations you would like to perform every time the app is created and finished (destroyed), e.g. initializing and disposing your favorite dependency injection library. For an example of the recommended way to implement this, see Persistent listener.
Don't forget to add a reference to this class to your AndroidManifest.xml
, for example:
<application
android:name=".App"
android:...>
If you're using Android SDK >= version 14 (Ice Cream Sandwich), you're done. SDK 14 introduced
android.app.Application.ActivityLifecycleCallbacks
,
which is implemented by this library.
However, if you want to target lower SDKs, you'll need to integrate the library in your activities
by subclassing the provided AppLifecycleActivity
classes. Here's an example for an
AppCompatActivity
:
public class MainActivity extends LifecycleAppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// make sure you call super
super.onCreate(savedInstanceState);
...
}
}
As shown above, make sure you always call super when you override the Activity
lifecycle methods.
If you have a custom Activity
implementation which cannot subclass the provided
AppLifecycleActivity
classes, then it is easy to integrate the library. Just call the
corresponding methods on the app lifecycle manager. The only exception is the onStop()
method,
which must also contain the onFinish()
call:
@Override
protected void onStop() {
super.onStop();
AppLifecycleProvider.getManager().onStop(this);
if (isFinishing()) {
AppLifecycleProvider.getManager().onFinish(this);
}
}
The following application lifecycle events are supported:
onAppCreated
: When the first activity is created.onAppStarted
: When a new activity is started, or when the current activity is brought back from
background to foreground.onAppResumed
: When the current activity is resumed by bringing it back to foreground, or after
starting a new activity.onAppPaused
: When the current activity is paused by bringing it to background, or by starting a
new activity.onAppStopped
: When the current activity is brought to background.onAppFinished
: When the last activity finished (exit application).If you want to listen for all app lifecycle events, it is most useful to implement
AppLifecycleListener
:
AppLifecycleProvider.getManager().addListener(new AppLifecycleListener() {
@Override
public void onAppCreated(Class<?> origin) {
}
...
@Override
public void onAppFinished(Class<?> origin) {
}
});
In these cases origin
is a reference to the activity that triggered the event. The wildcard type
is used instead of typing to Activity, to make it easier to test these methods in a context that
is not directly bound to Android (e.g. a controller or presenter).
If you're only interested in a few app lifecycle events, it is useful to override
DefaultAppLifecycleListener
, which is a no-operation implementation of AppLifecycleListener
.
There are also listener interfaces available for every app lifecycle event, which can be used if you are only interested in a single event, for example:
AppLifecycleProvider.getManager().addListener(new OnAppCreated() {
@Override
public void onAppCreated(Class<?> origin) {
}
});
AppLifecycleListenable
Only activities must call the event trigger methods (e.g. AppLifecycleManager.onCreate(activity)
).
To prevent non-activity components from calling these methods, and also to decouple your app
lifecycle-interested code from Android, it is recommended to depend on the AppLifecycleListenable
interface, which is extended by AppLifecycleManager
. This interface allows you to add and remove
event listeners.
For example, when using the Chefling dependency injection container, it is smart to map the manager to the listenable interface:
// create chefling container
Container container = Chefling.createContainer();
// map listenable interface to manager instance
container.mapInstance(AppLifecycleListenable.class, AppLifecycleProvider.getManager());
And then use it somewhere else:
// implement chefling lifecycle interface
public class ExampleController implements LifeCycle {
final AppLifecycleListenable appLifecycle;
// dependency resolved by chefling
public ExampleController(AppLifecycleListenable appLifecycle) {
this.appLifecycle = appLifecycle;
}
// chefling lifecycle: initialize
public void initialize() {
appLifecycle.addListener(appLifecycleListener);
}
// chefling lifecycle: dispose
public void dispose() {
appLifecycle.removeListener(appLifecycleListener);
}
final AppLifecycleListener appLifecycleListener = new AppLifecycleListener() { ... }
}
When you press the back button on an Android device from the "main" (root) activity, the
onAppFinished
app lifecycle event is triggered. This can be interpreted as the application having
exited. However, there will still be an application process running, which means you can start it
again from the background processes (e.g. by opening the "switch to application" menu from the
device).
The issue that occurs is that, after the onAppFinished
app lifecycle event is triggered, all app
lifecycle listeners are removed, as clean-up. However, we want one listener to persist, to listen
for the onAppCreated
app lifecycle event. This can be accomplished by adding a persistent
listener, which will not be removed during the clean-up process.
Typically you will not have more than one persistent listener in your application. It is recommended
to add this listener after initialization in your android.app.Application
implementation (see
Library initialization):
AppLifecycleProvider.getManager().addListener(new PersistentAppLifecycleListener() {
@Override
public void onAppCreated(Class<?> origin) {
}
@Override
public void onAppFinished(Class<?> origin) {
}
});