Skip to content

Commit

Permalink
Fix part of #4410, #4300, #2432: Create dedicated alpha application c…
Browse files Browse the repository at this point in the history
…omponent (#4414)

## Explanation
Fixes part of #4410, #4300, and #2432.

This PR refactors the existing approach for managing application-level build dependencies by splitting up OppiaApplication ApplicationComponent into two: one for the developer build, and one for alpha. The existing OppiaApplication was retrofitted to be a base abstract class for both of the flavor-specific applications, and also for the e2e test TestApplication class (which subsequently simplified that).

This has overall resulted in a decrease in complexity since it now allows us to select specific dependencies per flavor of the app which should significantly simplify ongoing release automation work, plus other flavor-specific gating that we may want to do in the future without having to rely on a human to manually enable/disable certain modules during release time.

A few other small things of note:
- ApplicationContext was removed since it seems to be barely used, and is confusing compared to the regular Context binding that's used almost everywhere
- This PR has led to the app module application package having its own Bazel BUILD file (which is a nice help toward continued modularization work)
- Most of this PR is tested by observing that the corresponding builds still work as expected, other than the changes to the manifest transformation utility
- A bunch of the new classes have been exempted for requiring tests since they (mostly) cannot be effectively tested, or are maintaining the status quo for testing these classes

## Essential Checklist
- [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
- [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation.
- [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
N/A -- This is an infrastructure-only change.

Commits:

* Create dedicated alpha application component.

This simplifies application component management significantly and
allows individual build flavors to have their own unique module lists.

* Fix broken test per earlier changes.

* Update TransformAndroidManifestTest.kt

Correct typos.
  • Loading branch information
BenHenning authored Aug 19, 2022
1 parent cec1182 commit 7562fdf
Show file tree
Hide file tree
Showing 45 changed files with 727 additions and 336 deletions.
3 changes: 2 additions & 1 deletion BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ package_group(
[
transform_android_manifest(
name = "oppia_apk_%s_transformed_manifest" % apk_flavor_metadata["flavor"],
application_relative_qualified_class = ".app.application.dev.DeveloperOppiaApplication",
build_flavor = apk_flavor_metadata["flavor"],
input_file = "//app:src/main/AndroidManifest.xml",
major_version = MAJOR_VERSION,
Expand Down Expand Up @@ -108,7 +109,7 @@ package_group(
},
multidex = apk_flavor_metadata["multidex"],
deps = [
"//app",
"//app/src/main/java/org/oppia/android/app/application/dev:developer_application",
],
)
for apk_flavor_metadata in [
Expand Down
57 changes: 11 additions & 46 deletions app/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -630,9 +630,6 @@ kt_android_library(
"//third_party:androidx_databinding_databinding-runtime",
"//third_party:circularimageview_circular_image_view",
"//utility/src/main/java/org/oppia/android/util/accessibility",
"//utility/src/main/java/org/oppia/android/util/caching:caching_prod_module",
"//utility/src/main/java/org/oppia/android/util/logging:prod_module",
"//utility/src/main/java/org/oppia/android/util/logging/firebase:prod_module",
"//utility/src/main/java/org/oppia/android/util/parser/html:html_parser",
"//utility/src/main/java/org/oppia/android/util/parser/image:image_loader",
"//utility/src/main/java/org/oppia/android/util/parser/image:image_parsing_annonations",
Expand Down Expand Up @@ -668,11 +665,11 @@ kt_android_library(
":listeners",
":resources",
"//app/src/main/java/org/oppia/android/app/shim:intent_factory_shim",
"//app/src/main/java/org/oppia/android/app/utility/datetime:date_time_util",
"//app/src/main/java/org/oppia/android/app/utility/math:math_expression_accessibility_util",
"//app/src/main/java/org/oppia/android/app/viewmodel:observable_array_list",
"//app/src/main/java/org/oppia/android/app/viewmodel:observable_view_model",
"//app/src/main/java/org/oppia/android/app/viewmodel:view_model_provider",
"//app/src/main/java/org/oppia/android/app/utility/datetime:date_time_util",
"//app/src/main/java/org/oppia/android/app/utility/math:math_expression_accessibility_util",
"//domain",
"//domain/src/main/java/org/oppia/android/domain/audio:audio_player_controller",
"//domain/src/main/java/org/oppia/android/domain/clipboard:clipboard_controller",
Expand All @@ -684,11 +681,8 @@ kt_android_library(
"//utility",
"//utility/src/main/java/org/oppia/android/util/extensions:context_extensions",
"//utility/src/main/java/org/oppia/android/util/logging/firebase:debug_event_logger",
"//utility/src/main/java/org/oppia/android/util/logging/firebase:debug_module",
"//utility/src/main/java/org/oppia/android/util/math:fraction_parser",
# TODO(#59): Remove 'debug_util_module' once we completely migrate to Bazel from Gradle as
# we can then directly exclude debug files from the build and thus won't be requiring this module.
"//utility/src/main/java/org/oppia/android/util/networking:debug_util_module",
"//utility/src/main/java/org/oppia/android/util/networking:network_connection_debug_util",
"//utility/src/main/java/org/oppia/android/util/parser/html:html_parser",
],
)
Expand Down Expand Up @@ -757,34 +751,11 @@ kt_android_library(
"//app/src/main/java/org/oppia/android/app/fragment:injectable_dialog_fragment",
"//app/src/main/java/org/oppia/android/app/fragment:injectable_fragment",
"//app/src/main/java/org/oppia/android/app/shim:prod_modules",
"//app/src/main/java/org/oppia/android/app/translation:prod_module",
"//data/src/main/java/org/oppia/android/data/backends/gae:network_config_prod_module",
"//data/src/main/java/org/oppia/android/data/backends/gae:prod_module",
"//domain/src/main/java/org/oppia/android/domain/classify:interactions_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/algebraicexpressioninput:algebraic_expression_input_rule_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/continueinteraction:continue_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/dragAndDropSortInput:drag_and_drop_sort_input_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput:fraction_input_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/imageClickInput:image_click_input_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput:item_selection_input_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/mathequationinput:math_equation_input_rule_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/multiplechoiceinput:multiple_choice_input_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits:number_with_units_rule_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/numericexpressioninput:numeric_expression_input_rule_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput:numeric_input_rule_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput:ratio_input_module",
"//domain/src/main/java/org/oppia/android/domain/classify/rules/textinput:text_input_rule_module",
"//domain/src/main/java/org/oppia/android/domain/locale:locale_application_injector",
"//domain/src/main/java/org/oppia/android/domain/locale:locale_application_injector_provider",
"//domain/src/main/java/org/oppia/android/domain/onboarding:retriever_prod_module",
"//app/src/main/java/org/oppia/android/app/testing/activity:test_activity",
"//domain/src/main/java/org/oppia/android/domain/onboarding:state_controller",
"//domain/src/main/java/org/oppia/android/domain/oppialogger:startup_listener",
"//domain/src/main/java/org/oppia/android/domain/oppialogger/exceptions:logger_module",
"//domain/src/main/java/org/oppia/android/domain/oppialogger/loguploader:worker_module",
"//model/src/main/proto:arguments_java_proto_lite",
"//domain/src/main/java/org/oppia/android/domain/profile:profile_management_controller",
"//domain/src/main/java/org/oppia/android/domain/oppialogger/analytics:prod_module",
"//app/src/main/java/org/oppia/android/app/testing/activity:test_activity",
"//model/src/main/proto:arguments_java_proto_lite",
"//third_party:androidx_databinding_databinding-adapters",
"//third_party:androidx_databinding_databinding-common",
"//third_party:androidx_databinding_databinding-runtime",
Expand All @@ -794,26 +765,14 @@ kt_android_library(
"//third_party:androidx_multidex_multidex",
"//third_party:androidx_viewpager2_viewpager2",
"//third_party:androidx_viewpager_viewpager",
"//third_party:androidx_work_work-runtime-ktx",
"//third_party:com_caverock_androidsvg",
"//third_party:com_google_android_flexbox_flexbox",
"//third_party:javax_annotation_javax_annotation-api_jar",
"//utility",
"//utility/src/main/java/org/oppia/android/util/accessibility:prod_module",
"//utility/src/main/java/org/oppia/android/util/caching:asset_prod_module",
"//utility/src/main/java/org/oppia/android/util/extensions:bundle_extensions",
"//utility/src/main/java/org/oppia/android/util/locale:prod_module",
"//utility/src/main/java/org/oppia/android/util/parser/html:html_parser_entity_type_module",
"//utility/src/main/java/org/oppia/android/util/parser/image:image_loader",
"//utility/src/main/java/org/oppia/android/util/parser/image:glide_image_loader_module",
"//utility/src/main/java/org/oppia/android/util/parser/image:repository_glide_module",
"//utility/src/main/java/org/oppia/android/util/parser/image:image_parsing_annonations",
"//utility/src/main/java/org/oppia/android/util/parser/image:image_parsing_module",
# TODO(#2432): Replace debug_module with prod_module when building the app in prod mode.
"//utility/src/main/java/org/oppia/android/util/networking:debug_module",
"//utility/src/main/java/org/oppia/android/util/logging:console_logger_injector_provider",
"//utility/src/main/java/org/oppia/android/util/statusbar:status_bar_color",
"//utility/src/main/java/org/oppia/android/util/threading:dispatcher_injector_provider",
],
)

Expand Down Expand Up @@ -858,6 +817,10 @@ TEST_DEPS = [
":dagger",
":resources",
":test_deps",
"//app/src/main/java/org/oppia/android/app/application:application_component",
"//app/src/main/java/org/oppia/android/app/application:application_injector",
"//app/src/main/java/org/oppia/android/app/application:application_injector_provider",
"//app/src/main/java/org/oppia/android/app/application:common_application_modules",
"//app/src/main/java/org/oppia/android/app/testing/activity:test_activity",
"//app/src/main/java/org/oppia/android/app/translation/testing:test_module",
"//app/src/main/java/org/oppia/android/app/utility/math:math_expression_accessibility_util",
Expand Down Expand Up @@ -924,7 +887,9 @@ TEST_DEPS = [
"//utility/src/main/java/org/oppia/android/util/accessibility:test_module",
"//utility/src/main/java/org/oppia/android/util/caching:asset_prod_module",
"//utility/src/main/java/org/oppia/android/util/caching/testing:caching_test_module",
"//utility/src/main/java/org/oppia/android/util/logging/firebase:debug_module",
"//utility/src/main/java/org/oppia/android/util/math:math_expression_parser",
"//utility/src/main/java/org/oppia/android/util/networking:debug_module",
"//utility/src/main/java/org/oppia/android/util/parser/html:custom_bullet_span",
"//utility/src/main/java/org/oppia/android/util/parser/html:html_parser",
"//utility/src/main/java/org/oppia/android/util/parser/html:html_parser_entity_type_module",
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<!-- TODO(#56): Reenable landscape support. -->
<application
android:name=".app.application.OppiaApplication"
android:name=".app.application.dev.DeveloperOppiaApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ import org.oppia.android.app.activity.ActivityComponent
import org.oppia.android.app.activity.ActivityComponentFactory
import org.oppia.android.domain.oppialogger.ApplicationStartupListener

/** The root [Application] of the Oppia app. */
class OppiaApplication :
MultiDexApplication(),
/** The root base [Application] of the Oppia app. */
abstract class AbstractOppiaApplication(
createComponentBuilder: () -> ApplicationComponent.Builder
) : MultiDexApplication(),
ActivityComponentFactory,
ApplicationInjectorProvider,
Configuration.Provider {

/** The root [ApplicationComponent]. */
private val component: ApplicationComponent by lazy {
DaggerApplicationComponent.builder()
.setApplication(this)
.build()
createComponentBuilder().setApplication(this).build()
}

override fun createActivityComponent(activity: AppCompatActivity): ActivityComponent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,116 +3,22 @@ package org.oppia.android.app.application
import android.app.Application
import androidx.work.Configuration
import dagger.BindsInstance
import dagger.Component
import org.oppia.android.app.activity.ActivityComponentImpl
import org.oppia.android.app.devoptions.DeveloperOptionsModule
import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.shim.IntentFactoryShimModule
import org.oppia.android.app.shim.ViewBindingShimModule
import org.oppia.android.app.topic.PracticeTabModule
import org.oppia.android.app.translation.ActivityRecreatorProdModule
import org.oppia.android.data.backends.gae.NetworkConfigProdModule
import org.oppia.android.data.backends.gae.NetworkModule
import org.oppia.android.domain.classify.InteractionsModule
import org.oppia.android.domain.classify.rules.algebraicexpressioninput.AlgebraicExpressionInputModule
import org.oppia.android.domain.classify.rules.continueinteraction.ContinueModule
import org.oppia.android.domain.classify.rules.dragAndDropSortInput.DragDropSortInputModule
import org.oppia.android.domain.classify.rules.fractioninput.FractionInputModule
import org.oppia.android.domain.classify.rules.imageClickInput.ImageClickInputModule
import org.oppia.android.domain.classify.rules.itemselectioninput.ItemSelectionInputModule
import org.oppia.android.domain.classify.rules.mathequationinput.MathEquationInputModule
import org.oppia.android.domain.classify.rules.multiplechoiceinput.MultipleChoiceInputModule
import org.oppia.android.domain.classify.rules.numberwithunits.NumberWithUnitsRuleModule
import org.oppia.android.domain.classify.rules.numericexpressioninput.NumericExpressionInputModule
import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModule
import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule
import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule
import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationStorageModule
import org.oppia.android.domain.hintsandsolution.HintsAndSolutionConfigModule
import org.oppia.android.domain.hintsandsolution.HintsAndSolutionDebugModule
import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule
import org.oppia.android.domain.oppialogger.ApplicationStartupListener
import org.oppia.android.domain.oppialogger.LogStorageModule
import org.oppia.android.domain.oppialogger.LoggingIdentifierModule
import org.oppia.android.domain.oppialogger.analytics.ApplicationLifecycleModule
import org.oppia.android.domain.oppialogger.exceptions.UncaughtExceptionLoggerModule
import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule
import org.oppia.android.domain.platformparameter.PlatformParameterModule
import org.oppia.android.domain.platformparameter.PlatformParameterSingletonModule
import org.oppia.android.domain.platformparameter.syncup.PlatformParameterSyncUpWorkerModule
import org.oppia.android.domain.question.QuestionModule
import org.oppia.android.domain.topic.PrimeTopicAssetsControllerModule
import org.oppia.android.domain.workmanager.WorkManagerConfigurationModule
import org.oppia.android.util.accessibility.AccessibilityProdModule
import org.oppia.android.util.caching.AssetModule
import org.oppia.android.util.caching.CachingModule
import org.oppia.android.util.gcsresource.GcsResourceModule
import org.oppia.android.util.locale.LocaleProdModule
import org.oppia.android.util.logging.LoggerModule
import org.oppia.android.util.logging.SyncStatusModule
import org.oppia.android.util.logging.firebase.DebugLogReportingModule
import org.oppia.android.util.logging.firebase.FirebaseLogUploaderModule
import org.oppia.android.util.networking.NetworkConnectionDebugUtilModule
import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule
import org.oppia.android.util.parser.html.HtmlParserEntityTypeModule
import org.oppia.android.util.parser.image.GlideImageLoaderModule
import org.oppia.android.util.parser.image.ImageParsingModule
import org.oppia.android.util.system.OppiaClockModule
import org.oppia.android.util.threading.DispatcherModule
import javax.inject.Provider
import javax.inject.Singleton

/**
* Root Dagger component for the application. All application-scoped modules should be included in
* this component.
*
* At the time of building the app in prod mode -
* Remove: [DeveloperOptionsStarterModule], [DebugLogReportingModule],
* [NetworkConnectionUtilDebugModule], [HintsAndSolutionDebugModule]
* Add: [LogReportingModule], [NetworkConnectionUtilProdModule], [HintsAndSolutionProdModule]
*
* When building with Bazel, please also refer to instructions in app/BUILD.bazel.
* This component will be subclasses for specific contexts (such as test builds, or specific build
* flavors of the app).
*/
@Singleton
@Component(
modules = [
ApplicationModule::class, DispatcherModule::class,
LoggerModule::class, OppiaClockModule::class,
ContinueModule::class, FractionInputModule::class,
ItemSelectionInputModule::class, MultipleChoiceInputModule::class,
NumberWithUnitsRuleModule::class, NumericInputRuleModule::class,
TextInputRuleModule::class, DragDropSortInputModule::class,
InteractionsModule::class, GcsResourceModule::class,
GlideImageLoaderModule::class, ImageParsingModule::class,
HtmlParserEntityTypeModule::class, CachingModule::class,
QuestionModule::class, DebugLogReportingModule::class,
AccessibilityProdModule::class, ImageClickInputModule::class,
LogStorageModule::class, IntentFactoryShimModule::class,
ViewBindingShimModule::class, PrimeTopicAssetsControllerModule::class,
ExpirationMetaDataRetrieverModule::class, RatioInputModule::class,
UncaughtExceptionLoggerModule::class, ApplicationStartupListenerModule::class,
LogUploadWorkerModule::class, WorkManagerConfigurationModule::class,
HintsAndSolutionConfigModule::class, HintsAndSolutionDebugModule::class,
FirebaseLogUploaderModule::class, NetworkModule::class, PracticeTabModule::class,
PlatformParameterModule::class, PlatformParameterSingletonModule::class,
ExplorationStorageModule::class, DeveloperOptionsStarterModule::class,
DeveloperOptionsModule::class, PlatformParameterSyncUpWorkerModule::class,
NetworkConnectionUtilDebugModule::class, NetworkConfigProdModule::class, AssetModule::class,
LocaleProdModule::class, ActivityRecreatorProdModule::class,
NumericExpressionInputModule::class, AlgebraicExpressionInputModule::class,
MathEquationInputModule::class, SplitScreenInteractionModule::class,
LoggingIdentifierModule::class, ApplicationLifecycleModule::class,
// TODO(#59): Remove this module once we completely migrate to Bazel from Gradle as we can then
// directly exclude debug files from the build and thus won't be requiring this module.
NetworkConnectionDebugUtilModule::class, LoggingIdentifierModule::class, SyncStatusModule::class
]
)
interface ApplicationComponent : ApplicationInjector {
@Component.Builder
interface Builder {
@BindsInstance
fun setApplication(application: Application): Builder

fun build(): ApplicationComponent
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,13 @@ package org.oppia.android.app.application

import android.app.Application
import android.content.Context
import dagger.Binds
import dagger.Module
import dagger.Provides
import org.oppia.android.app.activity.ActivityComponentImpl
import javax.inject.Singleton

/** Provides core infrastructure needed to support all other dependencies in the app. */
@Module(subcomponents = [ActivityComponentImpl::class])
class ApplicationModule {
@Provides
@Singleton
@ApplicationContext
fun provideApplicationContext(application: Application): Context {
return application
}

// TODO(#59): Remove this provider once all modules have access to the @ApplicationContext qualifier.
@Provides
@Singleton
fun provideContext(@ApplicationContext context: Context): Context {
return context
}
interface ApplicationModule {
@Binds
fun provideContext(application: Application): Context
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import org.oppia.android.domain.oppialogger.ApplicationStartupListener
/** Binds multiple dependencies that implement [ApplicationStartupListener] into a set. */
@Module
interface ApplicationStartupListenerModule {

@Multibinds
fun bindStartupListenerSet(): Set<ApplicationStartupListener>
}
Loading

0 comments on commit 7562fdf

Please sign in to comment.