diff --git a/android/libraries/rib-android-core/build.gradle b/android/libraries/rib-android-core/build.gradle
new file mode 100644
index 000000000..7db3b1541
--- /dev/null
+++ b/android/libraries/rib-android-core/build.gradle
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+buildscript {
+ dependencies {
+ classpath deps.build.gradlePlugins.android
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion deps.build.compileSdkVersion
+ buildToolsVersion deps.build.buildToolsVersion
+
+ defaultConfig {
+ minSdkVersion deps.build.minSdkVersion
+ targetSdkVersion deps.build.targetSdkVersion
+ }
+
+ compileOptions {
+ sourceCompatibility deps.build.javaVersion
+ targetCompatibility deps.build.javaVersion
+ }
+
+ testOptions {
+ unitTests {
+ includeAndroidResources = true
+ }
+ }
+}
+
+dependencies {
+ implementation deps.apt.javaxInject
+ implementation deps.androidx.annotations
+ implementation deps.androidx.appcompat
+ testImplementation deps.external.roboelectricBase
+ testImplementation deps.androidx.appcompat
+}
+
+apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
diff --git a/android/libraries/rib-android-core/gradle.properties b/android/libraries/rib-android-core/gradle.properties
new file mode 100755
index 000000000..a5e264e55
--- /dev/null
+++ b/android/libraries/rib-android-core/gradle.properties
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2017. Uber Technologies
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+POM_NAME=RIBs (Android Core)
+POM_ARTIFACT_ID=rib-android-core
+POM_PACKAGING=android
diff --git a/android/libraries/rib-android-core/src/main/AndroidManifest.xml b/android/libraries/rib-android-core/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..598377718
--- /dev/null
+++ b/android/libraries/rib-android-core/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/ActivityDelegate.java b/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/ActivityDelegate.java
new file mode 100644
index 000000000..b1f6a9f3c
--- /dev/null
+++ b/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/ActivityDelegate.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.core;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import androidx.annotation.IntRange;
+import androidx.annotation.Nullable;
+
+/**
+ * This class represents a delegate which you can use to extend CoreAppCompatActivity's
+ * functionality. This allows RibActivity and any other type of Activity that you need to support to
+ * share CoreAppCompatActivity as a common parent.
+ */
+public interface ActivityDelegate {
+ /** @see {@link Activity#onCreate(Bundle) } */
+ default void onCreate(@Nullable Bundle savedInstanceState) {}
+
+ /** @see {@link Activity#onStart() } */
+ default void onStart() {}
+
+ /** @see {@link Activity#onResume() } */
+ default void onResume() {}
+
+ /** @see {@link Activity#onPause() } */
+ default void onPause() {}
+
+ /** @see {@link Activity#onStop() } */
+ default void onStop() {}
+
+ /** @see {@link Activity#onDestroy() } */
+ default void onDestroy() {}
+
+ /** @see {@link Activity#onActivityResult(Activity, int, int, Intent) } */
+ default void onActivityResult(
+ Activity activity, int requestCode, int resultCode, @Nullable Intent data) {}
+
+ /** @see {@link Activity#onRequestPermissionsResult(Activity, int, String[], int[]) } */
+ default void onRequestPermissionsResult(
+ Activity activity,
+ @IntRange(from = 0, to = 255) int requestCode,
+ String[] permissions,
+ int[] grantResults) {}
+}
diff --git a/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/CoreAppCompatActivity.java b/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/CoreAppCompatActivity.java
new file mode 100644
index 000000000..5e4380d00
--- /dev/null
+++ b/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/CoreAppCompatActivity.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.core;
+
+import android.content.Intent;
+import android.os.Bundle;
+import androidx.annotation.CallSuper;
+import androidx.annotation.IntRange;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+/** Core Support v7 AppCompat Activity. */
+public abstract class CoreAppCompatActivity extends AppCompatActivity {
+
+ @Nullable private ActivityDelegate activityDelegate;
+
+ @CallSuper
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ if (getApplicationContext() instanceof HasActivityDelegate) {
+ activityDelegate = ((HasActivityDelegate) getApplicationContext()).activityDelegate();
+ }
+ super.onCreate(savedInstanceState);
+ if (activityDelegate != null) {
+ activityDelegate.onCreate(savedInstanceState);
+ }
+ }
+
+ @CallSuper
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (activityDelegate != null) {
+ activityDelegate.onStart();
+ }
+ }
+
+ @CallSuper
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (activityDelegate != null) {
+ activityDelegate.onResume();
+ }
+ }
+
+ @CallSuper
+ @Override
+ protected void onPause() {
+ if (activityDelegate != null) {
+ activityDelegate.onPause();
+ }
+ super.onPause();
+ }
+
+ @CallSuper
+ @Override
+ protected void onStop() {
+ if (activityDelegate != null) {
+ activityDelegate.onStop();
+ }
+ super.onStop();
+ }
+
+ @CallSuper
+ @Override
+ protected void onDestroy() {
+ if (activityDelegate != null) {
+ activityDelegate.onDestroy();
+ activityDelegate = null;
+ }
+ super.onDestroy();
+ }
+
+ @CallSuper
+ @Override
+ public void onRequestPermissionsResult(
+ @IntRange(from = 0, to = 255) int requestCode, String[] permissions, int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (activityDelegate != null) {
+ activityDelegate.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
+ }
+ }
+
+ @CallSuper
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (activityDelegate != null) {
+ activityDelegate.onActivityResult(this, requestCode, resultCode, data);
+ }
+ }
+}
diff --git a/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/HasActivityDelegate.java b/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/HasActivityDelegate.java
new file mode 100644
index 000000000..a27fdb630
--- /dev/null
+++ b/android/libraries/rib-android-core/src/main/java/com/uber/rib/core/HasActivityDelegate.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.core;
+
+/** Interface to indicate an object has a CoreAppCompatActivity.Delegate. */
+public interface HasActivityDelegate {
+
+ /**
+ * Get the delegate.
+ *
+ * @return The delegate.
+ */
+ ActivityDelegate activityDelegate();
+}
diff --git a/android/libraries/rib-android-core/src/test/resources/robolectric.properties b/android/libraries/rib-android-core/src/test/resources/robolectric.properties
new file mode 100644
index 000000000..a240a2bd7
--- /dev/null
+++ b/android/libraries/rib-android-core/src/test/resources/robolectric.properties
@@ -0,0 +1 @@
+constants=com.uber.rib.android.test.BuildConfig
diff --git a/android/libraries/rib-android/build.gradle b/android/libraries/rib-android/build.gradle
index a33a45c30..03542ef0f 100644
--- a/android/libraries/rib-android/build.gradle
+++ b/android/libraries/rib-android/build.gradle
@@ -44,6 +44,7 @@ android {
}
dependencies {
+ api project(":libraries:rib-android-core")
api project(":libraries:rib-base")
api deps.external.rxrelay2
api deps.external.rxjava2
diff --git a/android/libraries/rib-android/src/main/java/com/uber/rib/core/RibActivity.java b/android/libraries/rib-android/src/main/java/com/uber/rib/core/RibActivity.java
index 49d216c41..4fbd0efa4 100644
--- a/android/libraries/rib-android/src/main/java/com/uber/rib/core/RibActivity.java
+++ b/android/libraries/rib-android/src/main/java/com/uber/rib/core/RibActivity.java
@@ -31,13 +31,11 @@
import com.uber.autodispose.lifecycle.LifecycleScopes;
import com.uber.rib.core.lifecycle.ActivityCallbackEvent;
import com.uber.rib.core.lifecycle.ActivityLifecycleEvent;
-
import io.reactivex.CompletableSource;
import io.reactivex.Observable;
-import androidx.appcompat.app.AppCompatActivity;
/** Base implementation for all VIP {@link android.app.Activity}s. */
-public abstract class RibActivity extends AppCompatActivity
+public abstract class RibActivity extends CoreAppCompatActivity
implements ActivityStarter, LifecycleScopeProvider, RxActivityEvents {
/**
diff --git a/android/settings.gradle b/android/settings.gradle
index 22fd39b44..aca53a2e7 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,5 +1,6 @@
include ':libraries:rib-test'
include ':libraries:rib-android'
+include ':libraries:rib-android-core'
include ':libraries:rib-base'
include ':libraries:rib-compiler-app'
include ':libraries:rib-compiler-test'