Skip to content

Commit f7f66da

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

24 files changed

+273
-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: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.appdistribution.impl;
16+
17+
import androidx.annotation.Nullable;
18+
import com.google.firebase.FirebaseApp;
19+
import dagger.MembersInjector;
20+
import javax.inject.Inject;
21+
22+
/** Firebase Component used by activities to request dependency injection into them. */
23+
class ActivityInjector {
24+
private final MembersInjector<InstallActivity> installActivityInjector;
25+
26+
@Inject
27+
ActivityInjector(MembersInjector<InstallActivity> installActivityInjector) {
28+
this.installActivityInjector = installActivityInjector;
29+
}
30+
31+
static void injectForApp(@Nullable String firebaseAppName, InstallActivity activity) {
32+
getApp(firebaseAppName)
33+
.get(ActivityInjector.class)
34+
.installActivityInjector
35+
.injectMembers(activity);
36+
}
37+
38+
private static FirebaseApp getApp(@Nullable String name) {
39+
if (name == null) {
40+
return FirebaseApp.getInstance();
41+
}
42+
return FirebaseApp.getInstance(name);
43+
}
44+
}

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: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.appdistribution.impl;
16+
17+
import android.content.Context;
18+
import com.google.firebase.FirebaseApp;
19+
import com.google.firebase.FirebaseOptions;
20+
import com.google.firebase.annotations.concurrent.Blocking;
21+
import com.google.firebase.appdistribution.FirebaseAppDistribution;
22+
import com.google.firebase.inject.Provider;
23+
import com.google.firebase.installations.FirebaseInstallationsApi;
24+
import dagger.Binds;
25+
import dagger.BindsInstance;
26+
import dagger.Component;
27+
import dagger.Module;
28+
import dagger.Provides;
29+
import java.util.concurrent.Executor;
30+
import javax.inject.Named;
31+
import javax.inject.Singleton;
32+
33+
/** @hide */
34+
@Component(modules = AppDistroComponent.MainModule.class)
35+
@Singleton
36+
interface AppDistroComponent {
37+
38+
FirebaseAppDistribution getAppDistribution();
39+
40+
FirebaseAppDistributionLifecycleNotifier getLifecycleNotifier();
41+
42+
ActivityInjector getActivityInjector();
43+
44+
@Component.Builder
45+
interface Builder {
46+
47+
@BindsInstance
48+
Builder setApplicationContext(Context context);
49+
50+
@BindsInstance
51+
Builder setOptions(FirebaseOptions options);
52+
53+
@BindsInstance
54+
Builder setApp(FirebaseApp app);
55+
56+
@BindsInstance
57+
Builder setFis(Provider<FirebaseInstallationsApi> fis);
58+
59+
@BindsInstance
60+
Builder setBlockingExecutor(@Blocking Executor executor);
61+
62+
AppDistroComponent build();
63+
}
64+
65+
@Module
66+
interface MainModule {
67+
@Binds
68+
FirebaseAppDistribution bindAppDistro(FirebaseAppDistributionImpl impl);
69+
70+
@Provides
71+
@Named("appName")
72+
static String providesAppName(FirebaseApp app) {
73+
return app.getName();
74+
}
75+
}
76+
}

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(

0 commit comments

Comments
 (0)