Skip to content

Commit 68b1e4b

Browse files
committed
[Prototype] Migrate app distro to dagger.
1 parent 1ae9488 commit 68b1e4b

24 files changed

+245
-147
lines changed

firebase-appdistribution/firebase-appdistribution.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
plugins {
1616
id 'firebase-library'
17+
id 'firebase-vendor'
1718
}
1819

1920
firebaseLibrary {
@@ -51,6 +52,12 @@ dependencies {
5152
testImplementation project(path: ':firebase-appdistribution')
5253
runtimeOnly project(':firebase-installations')
5354

55+
implementation 'javax.inject:javax.inject:1'
56+
vendor ('com.google.dagger:dagger:2.43.2') {
57+
exclude group: "javax.inject", module: "javax.inject"
58+
}
59+
annotationProcessor 'com.google.dagger:dagger-compiler:2.43.2'
60+
5461
testImplementation 'junit:junit:4.13.2'
5562
testImplementation "org.robolectric:robolectric:$robolectricVersion"
5663
testImplementation "com.google.truth:truth:$googleTruthVersion"

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/AabUpdater.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@
2525
import androidx.annotation.GuardedBy;
2626
import androidx.annotation.NonNull;
2727
import androidx.annotation.VisibleForTesting;
28+
import com.google.firebase.annotations.concurrent.Blocking;
2829
import com.google.firebase.appdistribution.FirebaseAppDistribution;
2930
import com.google.firebase.appdistribution.FirebaseAppDistributionException;
3031
import com.google.firebase.appdistribution.UpdateStatus;
3132
import java.io.IOException;
3233
import java.util.concurrent.Executor;
34+
import javax.inject.Inject;
3335
import javax.net.ssl.HttpsURLConnection;
3436

3537
/** Class that handles updateApp functionality for AABs in {@link FirebaseAppDistribution}. */
@@ -51,17 +53,11 @@ class AabUpdater {
5153
@GuardedBy("updateAabLock")
5254
private boolean hasBeenSentToPlayForCurrentTask = false;
5355

54-
AabUpdater(@NonNull Executor blockingExecutor) {
55-
this(
56-
FirebaseAppDistributionLifecycleNotifier.getInstance(),
57-
new HttpsUrlConnectionFactory(),
58-
blockingExecutor);
59-
}
60-
56+
@Inject
6157
AabUpdater(
6258
@NonNull FirebaseAppDistributionLifecycleNotifier lifecycleNotifier,
6359
@NonNull HttpsUrlConnectionFactory httpsUrlConnectionFactory,
64-
@NonNull Executor blockingExecutor) {
60+
@NonNull @Blocking Executor blockingExecutor) {
6561
this.lifecycleNotifier = lifecycleNotifier;
6662
this.httpsUrlConnectionFactory = httpsUrlConnectionFactory;
6763
lifecycleNotifier.addOnActivityStartedListener(this::onActivityStarted);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.google.firebase.appdistribution.impl;
2+
3+
import androidx.annotation.Nullable;
4+
import com.google.firebase.FirebaseApp;
5+
import dagger.MembersInjector;
6+
import javax.inject.Inject;
7+
8+
/** Firebase Component used by activities to request dependency injection into them. */
9+
class ActivityInjector {
10+
private final MembersInjector<InstallActivity> installActivityInjector;
11+
12+
@Inject
13+
ActivityInjector(MembersInjector<InstallActivity> installActivityInjector) {
14+
this.installActivityInjector = installActivityInjector;
15+
}
16+
17+
static void injectForApp(@Nullable String firebaseAppName, InstallActivity activity) {
18+
getApp(firebaseAppName)
19+
.get(ActivityInjector.class)
20+
.installActivityInjector
21+
.injectMembers(activity);
22+
}
23+
24+
private static FirebaseApp getApp(@Nullable String name) {
25+
if (name == null) {
26+
return FirebaseApp.getInstance();
27+
}
28+
return FirebaseApp.getInstance(name);
29+
}
30+
}

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/ApkInstaller.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,30 @@
2424
import com.google.android.gms.tasks.TaskCompletionSource;
2525
import com.google.firebase.appdistribution.FirebaseAppDistribution;
2626
import com.google.firebase.appdistribution.FirebaseAppDistributionException;
27+
import javax.inject.Inject;
28+
import javax.inject.Named;
2729

2830
/** Class that handles installing APKs in {@link FirebaseAppDistribution}. */
2931
class ApkInstaller {
3032
private static final String TAG = "ApkInstaller:";
33+
private final String appName;
3134
private final FirebaseAppDistributionLifecycleNotifier lifeCycleNotifier;
3235

3336
@GuardedBy("installTaskLock")
3437
private TaskCompletionSource<Void> installTaskCompletionSource;
3538

3639
private final Object installTaskLock = new Object();
3740

38-
ApkInstaller(FirebaseAppDistributionLifecycleNotifier lifeCycleNotifier) {
41+
@Inject
42+
ApkInstaller(
43+
@Named("appName") String appName,
44+
FirebaseAppDistributionLifecycleNotifier lifeCycleNotifier) {
45+
this.appName = appName;
3946
this.lifeCycleNotifier = lifeCycleNotifier;
4047
lifeCycleNotifier.addOnActivityStartedListener(this::onActivityStarted);
4148
lifeCycleNotifier.addOnActivityDestroyedListener(this::onActivityDestroyed);
4249
}
4350

44-
ApkInstaller() {
45-
this(FirebaseAppDistributionLifecycleNotifier.getInstance());
46-
}
47-
4851
void onActivityStarted(@Nullable Activity activity) {
4952
synchronized (installTaskLock) {
5053
if (installTaskCompletionSource == null
@@ -78,6 +81,7 @@ Task<Void> installApk(String path, Activity currentActivity) {
7881
private void startInstallActivity(String path, Activity currentActivity) {
7982
Intent intent = new Intent(currentActivity, InstallActivity.class);
8083
intent.putExtra("INSTALL_PATH", path);
84+
intent.putExtra("FIREBASE_APP_NAME", appName);
8185
currentActivity.startActivity(intent);
8286
LogWrapper.getInstance().v(TAG + "Prompting tester with install activity ");
8387
}

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/ApkUpdater.java

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import androidx.annotation.VisibleForTesting;
2828
import com.google.android.gms.tasks.Task;
2929
import com.google.android.gms.tasks.TaskCompletionSource;
30-
import com.google.firebase.FirebaseApp;
30+
import com.google.firebase.annotations.concurrent.Blocking;
3131
import com.google.firebase.appdistribution.FirebaseAppDistribution;
3232
import com.google.firebase.appdistribution.FirebaseAppDistributionException;
3333
import com.google.firebase.appdistribution.FirebaseAppDistributionException.Status;
@@ -38,6 +38,7 @@
3838
import java.io.InputStream;
3939
import java.util.concurrent.Executor;
4040
import java.util.jar.JarFile;
41+
import javax.inject.Inject;
4142
import javax.net.ssl.HttpsURLConnection;
4243

4344
/** Class that handles updateApp functionality for APKs in {@link FirebaseAppDistribution}. */
@@ -61,22 +62,9 @@ class ApkUpdater {
6162

6263
private final Object updateTaskLock = new Object();
6364

65+
@Inject
6466
public ApkUpdater(
65-
@NonNull FirebaseApp firebaseApp,
66-
@NonNull ApkInstaller apkInstaller,
67-
@NonNull Executor blockingExecutor) {
68-
this(
69-
blockingExecutor,
70-
firebaseApp.getApplicationContext(),
71-
apkInstaller,
72-
new FirebaseAppDistributionNotificationsManager(firebaseApp.getApplicationContext()),
73-
new HttpsUrlConnectionFactory(),
74-
FirebaseAppDistributionLifecycleNotifier.getInstance());
75-
}
76-
77-
@VisibleForTesting
78-
public ApkUpdater(
79-
@NonNull Executor blockingExecutor,
67+
@NonNull @Blocking Executor blockingExecutor,
8068
@NonNull Context context,
8169
@NonNull ApkInstaller apkInstaller,
8270
@NonNull FirebaseAppDistributionNotificationsManager appDistributionNotificationsManager,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.google.firebase.appdistribution.impl;
2+
3+
import android.content.Context;
4+
import com.google.firebase.FirebaseApp;
5+
import com.google.firebase.FirebaseOptions;
6+
import com.google.firebase.annotations.concurrent.Blocking;
7+
import com.google.firebase.appdistribution.FirebaseAppDistribution;
8+
import com.google.firebase.inject.Provider;
9+
import com.google.firebase.installations.FirebaseInstallationsApi;
10+
import dagger.Binds;
11+
import dagger.BindsInstance;
12+
import dagger.Component;
13+
import dagger.Module;
14+
import dagger.Provides;
15+
import java.util.concurrent.Executor;
16+
import javax.inject.Named;
17+
import javax.inject.Singleton;
18+
19+
/** @hide */
20+
@Component(modules = AppDistroComponent.MainModule.class)
21+
@Singleton
22+
interface AppDistroComponent {
23+
24+
FirebaseAppDistribution getAppDistribution();
25+
26+
FirebaseAppDistributionLifecycleNotifier getLifecycleNotifier();
27+
28+
ActivityInjector getActivityInjector();
29+
30+
@Component.Builder
31+
interface Builder {
32+
33+
@BindsInstance
34+
Builder setApplicationContext(Context context);
35+
36+
@BindsInstance
37+
Builder setOptions(FirebaseOptions options);
38+
39+
@BindsInstance
40+
Builder setApp(FirebaseApp app);
41+
42+
@BindsInstance
43+
Builder setFis(Provider<FirebaseInstallationsApi> fis);
44+
45+
@BindsInstance
46+
Builder setBlockingExecutor(@Blocking Executor executor);
47+
48+
AppDistroComponent build();
49+
}
50+
51+
@Module
52+
interface MainModule {
53+
@Binds
54+
FirebaseAppDistribution bindAppDistro(FirebaseAppDistributionImpl impl);
55+
56+
@Provides
57+
@Named("appName")
58+
static String providesAppName(FirebaseApp app) {
59+
return app.getName();
60+
}
61+
}
62+
}

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionImpl.java

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import com.google.android.gms.tasks.Task;
3232
import com.google.android.gms.tasks.TaskCompletionSource;
3333
import com.google.android.gms.tasks.Tasks;
34-
import com.google.firebase.FirebaseApp;
3534
import com.google.firebase.appdistribution.AppDistributionRelease;
3635
import com.google.firebase.appdistribution.BinaryType;
3736
import com.google.firebase.appdistribution.FirebaseAppDistribution;
@@ -40,6 +39,7 @@
4039
import com.google.firebase.appdistribution.UpdateProgress;
4140
import com.google.firebase.appdistribution.UpdateStatus;
4241
import com.google.firebase.appdistribution.UpdateTask;
42+
import javax.inject.Inject;
4343

4444
/**
4545
* This class is the "real" implementation of the Firebase App Distribution API which should only be
@@ -49,7 +49,7 @@ class FirebaseAppDistributionImpl implements FirebaseAppDistribution {
4949

5050
private static final int UNKNOWN_RELEASE_FILE_SIZE = -1;
5151

52-
private final FirebaseApp firebaseApp;
52+
private final Context applicationContext;
5353
private final TesterSignInManager testerSignInManager;
5454
private final NewReleaseFetcher newReleaseFetcher;
5555
private final FirebaseAppDistributionLifecycleNotifier lifecycleNotifier;
@@ -74,16 +74,16 @@ class FirebaseAppDistributionImpl implements FirebaseAppDistribution {
7474
private TaskCompletionSource<Void> showSignInDialogTask = null;
7575
private TaskCompletionSource<Void> showUpdateDialogTask = null;
7676

77-
@VisibleForTesting
77+
@Inject
7878
FirebaseAppDistributionImpl(
79-
@NonNull FirebaseApp firebaseApp,
79+
@NonNull Context applicationContext,
8080
@NonNull TesterSignInManager testerSignInManager,
8181
@NonNull NewReleaseFetcher newReleaseFetcher,
8282
@NonNull ApkUpdater apkUpdater,
8383
@NonNull AabUpdater aabUpdater,
8484
@NonNull SignInStorage signInStorage,
8585
@NonNull FirebaseAppDistributionLifecycleNotifier lifecycleNotifier) {
86-
this.firebaseApp = firebaseApp;
86+
this.applicationContext = applicationContext;
8787
this.testerSignInManager = testerSignInManager;
8888
this.newReleaseFetcher = newReleaseFetcher;
8989
this.apkUpdater = apkUpdater;
@@ -170,18 +170,19 @@ private Task<Void> showSignInConfirmationDialog(Activity hostActivity) {
170170
() -> {
171171
signInConfirmationDialog = new AlertDialog.Builder(hostActivity).create();
172172

173-
Context context = firebaseApp.getApplicationContext();
174-
signInConfirmationDialog.setTitle(context.getString(R.string.signin_dialog_title));
175-
signInConfirmationDialog.setMessage(context.getString(R.string.singin_dialog_message));
173+
signInConfirmationDialog.setTitle(
174+
applicationContext.getString(R.string.signin_dialog_title));
175+
signInConfirmationDialog.setMessage(
176+
applicationContext.getString(R.string.singin_dialog_message));
176177

177178
signInConfirmationDialog.setButton(
178179
AlertDialog.BUTTON_POSITIVE,
179-
context.getString(R.string.singin_yes_button),
180+
applicationContext.getString(R.string.singin_yes_button),
180181
(dialogInterface, i) -> showSignInDialogTask.setResult(null));
181182

182183
signInConfirmationDialog.setButton(
183184
AlertDialog.BUTTON_NEGATIVE,
184-
context.getString(R.string.singin_no_button),
185+
applicationContext.getString(R.string.singin_no_button),
185186
(dialogInterface, i) ->
186187
showSignInDialogTask.setException(
187188
new FirebaseAppDistributionException(
@@ -357,15 +358,15 @@ private Task<Void> showUpdateConfirmationDialog(
357358
showUpdateDialogTask = new TaskCompletionSource<>();
358359
}
359360

360-
Context context = firebaseApp.getApplicationContext();
361361
dialogHostActivity = hostActivity;
362362

363363
// We should already be on the main (UI) thread here, but be explicit just to be safe. If we are
364364
// already on the main thread, this will execute immediately.
365365
hostActivity.runOnUiThread(
366366
() -> {
367367
updateConfirmationDialog = new AlertDialog.Builder(hostActivity).create();
368-
updateConfirmationDialog.setTitle(context.getString(R.string.update_dialog_title));
368+
updateConfirmationDialog.setTitle(
369+
applicationContext.getString(R.string.update_dialog_title));
369370

370371
StringBuilder message =
371372
new StringBuilder(
@@ -380,12 +381,12 @@ private Task<Void> showUpdateConfirmationDialog(
380381

381382
updateConfirmationDialog.setButton(
382383
AlertDialog.BUTTON_POSITIVE,
383-
context.getString(R.string.update_yes_button),
384+
applicationContext.getString(R.string.update_yes_button),
384385
(dialogInterface, i) -> showUpdateDialogTask.setResult(null));
385386

386387
updateConfirmationDialog.setButton(
387388
AlertDialog.BUTTON_NEGATIVE,
388-
context.getString(R.string.update_no_button),
389+
applicationContext.getString(R.string.update_no_button),
389390
(dialogInterface, i) ->
390391
showUpdateDialogTask.setException(
391392
new FirebaseAppDistributionException(

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionLifecycleNotifier.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import androidx.annotation.GuardedBy;
2121
import androidx.annotation.NonNull;
2222
import androidx.annotation.Nullable;
23-
import androidx.annotation.VisibleForTesting;
2423
import com.google.android.gms.tasks.SuccessContinuation;
2524
import com.google.android.gms.tasks.Task;
2625
import com.google.android.gms.tasks.TaskCompletionSource;
@@ -29,7 +28,10 @@
2928
import java.util.ArrayDeque;
3029
import java.util.Queue;
3130
import java.util.concurrent.Executor;
31+
import javax.inject.Inject;
32+
import javax.inject.Singleton;
3233

34+
@Singleton
3335
class FirebaseAppDistributionLifecycleNotifier implements Application.ActivityLifecycleCallbacks {
3436

3537
/** An {@link Executor} that runs tasks on the current thread. */
@@ -45,7 +47,6 @@ interface ActivityFunction<T> {
4547
T apply(Activity activity) throws FirebaseAppDistributionException;
4648
}
4749

48-
private static FirebaseAppDistributionLifecycleNotifier instance;
4950
private final Object lock = new Object();
5051

5152
@GuardedBy("lock")
@@ -71,16 +72,9 @@ interface ActivityFunction<T> {
7172
@GuardedBy("lock")
7273
private final Queue<OnActivityDestroyedListener> onDestroyedListeners = new ArrayDeque<>();
7374

74-
@VisibleForTesting
75+
@Inject
7576
FirebaseAppDistributionLifecycleNotifier() {}
7677

77-
static synchronized FirebaseAppDistributionLifecycleNotifier getInstance() {
78-
if (instance == null) {
79-
instance = new FirebaseAppDistributionLifecycleNotifier();
80-
}
81-
return instance;
82-
}
83-
8478
interface OnActivityCreatedListener {
8579
void onCreated(Activity activity);
8680
}

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionNotificationsManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import androidx.annotation.Nullable;
2424
import androidx.annotation.VisibleForTesting;
2525
import androidx.core.app.NotificationCompat;
26+
import javax.inject.Inject;
2627

2728
class FirebaseAppDistributionNotificationsManager {
2829
private static final String TAG = "NotificationsManager:";
@@ -35,6 +36,7 @@ class FirebaseAppDistributionNotificationsManager {
3536
private final Context context;
3637
private final AppIconSource appIconSource;
3738

39+
@Inject
3840
FirebaseAppDistributionNotificationsManager(Context context) {
3941
this(context, new AppIconSource());
4042
}

0 commit comments

Comments
 (0)