Skip to content

Commit

Permalink
refactor(firebase_core): remove deprecated Tasks.call for android a…
Browse files Browse the repository at this point in the history
…nd replace with `TaskCompletionSource`. (#8581)
  • Loading branch information
russellwheatley committed May 10, 2022
1 parent 9539c92 commit 374c9df
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 95 deletions.
Expand Up @@ -9,6 +9,7 @@
import android.os.Looper;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.TaskCompletionSource;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
Expand Down Expand Up @@ -103,128 +104,183 @@ private Map<String, String> firebaseOptionsToMap(FirebaseOptions options) {
}

private Task<Map<String, Object>> firebaseAppToMap(FirebaseApp firebaseApp) {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<Map<String, Object>> taskCompletionSource = new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
Map<String, Object> appMap = new HashMap<>();
try {
Map<String, Object> appMap = new HashMap<>();

appMap.put(KEY_NAME, firebaseApp.getName());
appMap.put(KEY_OPTIONS, firebaseOptionsToMap(firebaseApp.getOptions()));
appMap.put(KEY_NAME, firebaseApp.getName());
appMap.put(KEY_OPTIONS, firebaseOptionsToMap(firebaseApp.getOptions()));

appMap.put(
KEY_IS_AUTOMATIC_DATA_COLLECTION_ENABLED,
firebaseApp.isDataCollectionDefaultEnabled());
appMap.put(
KEY_PLUGIN_CONSTANTS,
Tasks.await(
FlutterFirebasePluginRegistry.getPluginConstantsForFirebaseApp(firebaseApp)));
appMap.put(
KEY_IS_AUTOMATIC_DATA_COLLECTION_ENABLED,
firebaseApp.isDataCollectionDefaultEnabled());
appMap.put(
KEY_PLUGIN_CONSTANTS,
Tasks.await(
FlutterFirebasePluginRegistry.getPluginConstantsForFirebaseApp(firebaseApp)));

return appMap;
taskCompletionSource.setResult(appMap);
} catch (Exception e) {
taskCompletionSource.setException(e);
}
});

return taskCompletionSource.getTask();
}

private Task<Map<String, Object>> initializeApp(Map<String, Object> arguments) {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<Map<String, Object>> taskCompletionSource = new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
String name = (String) Objects.requireNonNull(arguments.get(KEY_APP_NAME));

@SuppressWarnings("unchecked")
Map<String, String> optionsMap =
(Map<String, String>) Objects.requireNonNull(arguments.get(KEY_OPTIONS));

FirebaseOptions options =
new FirebaseOptions.Builder()
.setApiKey(Objects.requireNonNull(optionsMap.get(KEY_API_KEY)))
.setApplicationId(Objects.requireNonNull(optionsMap.get(KEY_APP_ID)))
.setDatabaseUrl(optionsMap.get(KEY_DATABASE_URL))
.setGcmSenderId(optionsMap.get(KEY_MESSAGING_SENDER_ID))
.setProjectId(optionsMap.get(KEY_PROJECT_ID))
.setStorageBucket(optionsMap.get(KEY_STORAGE_BUCKET))
.setGaTrackingId(optionsMap.get(KEY_TRACKING_ID))
.build();
// TODO(Salakar) hacky workaround a bug with FirebaseInAppMessaging causing the error:
// Can't create handler inside thread Thread[pool-3-thread-1,5,main] that has not called Looper.prepare()
// at com.google.firebase.inappmessaging.internal.ForegroundNotifier.<init>(ForegroundNotifier.java:61)
try {
Looper.prepare();
String name = (String) Objects.requireNonNull(arguments.get(KEY_APP_NAME));

@SuppressWarnings("unchecked")
Map<String, String> optionsMap =
(Map<String, String>) Objects.requireNonNull(arguments.get(KEY_OPTIONS));

FirebaseOptions options =
new FirebaseOptions.Builder()
.setApiKey(Objects.requireNonNull(optionsMap.get(KEY_API_KEY)))
.setApplicationId(Objects.requireNonNull(optionsMap.get(KEY_APP_ID)))
.setDatabaseUrl(optionsMap.get(KEY_DATABASE_URL))
.setGcmSenderId(optionsMap.get(KEY_MESSAGING_SENDER_ID))
.setProjectId(optionsMap.get(KEY_PROJECT_ID))
.setStorageBucket(optionsMap.get(KEY_STORAGE_BUCKET))
.setGaTrackingId(optionsMap.get(KEY_TRACKING_ID))
.build();
// TODO(Salakar) hacky workaround a bug with FirebaseInAppMessaging causing the error:
// Can't create handler inside thread Thread[pool-3-thread-1,5,main] that has not called Looper.prepare()
// at com.google.firebase.inappmessaging.internal.ForegroundNotifier.<init>(ForegroundNotifier.java:61)
try {
Looper.prepare();
} catch (Exception e) {
// do nothing
}
FirebaseApp firebaseApp = FirebaseApp.initializeApp(applicationContext, options, name);
taskCompletionSource.setResult(Tasks.await(firebaseAppToMap(firebaseApp)));
} catch (Exception e) {
// do nothing
taskCompletionSource.setException(e);
}
FirebaseApp firebaseApp = FirebaseApp.initializeApp(applicationContext, options, name);
return Tasks.await(firebaseAppToMap(firebaseApp));
});

return taskCompletionSource.getTask();
}

private Task<List<Map<String, Object>>> initializeCore() {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<List<Map<String, Object>>> taskCompletionSource =
new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
if (!coreInitialized) {
coreInitialized = true;
} else {
Tasks.await(FlutterFirebasePluginRegistry.didReinitializeFirebaseCore());
}
try {
if (!coreInitialized) {
coreInitialized = true;
} else {
Tasks.await(FlutterFirebasePluginRegistry.didReinitializeFirebaseCore());
}

List<FirebaseApp> firebaseApps = FirebaseApp.getApps(applicationContext);
List<Map<String, Object>> firebaseAppsList = new ArrayList<>(firebaseApps.size());
List<FirebaseApp> firebaseApps = FirebaseApp.getApps(applicationContext);
List<Map<String, Object>> firebaseAppsList = new ArrayList<>(firebaseApps.size());

for (FirebaseApp firebaseApp : firebaseApps) {
firebaseAppsList.add(Tasks.await(firebaseAppToMap(firebaseApp)));
}
for (FirebaseApp firebaseApp : firebaseApps) {
firebaseAppsList.add(Tasks.await(firebaseAppToMap(firebaseApp)));
}

return firebaseAppsList;
taskCompletionSource.setResult(firebaseAppsList);
} catch (Exception e) {
taskCompletionSource.setException(e);
}
});

return taskCompletionSource.getTask();
}

private Task<Map<String, String>> firebaseOptionsFromResource() {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<Map<String, String>> taskCompletionSource = new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
final FirebaseOptions options = FirebaseOptions.fromResource(applicationContext);
if (options == null) return null;
return firebaseOptionsToMap(options);
try {
final FirebaseOptions options = FirebaseOptions.fromResource(applicationContext);
if (options == null) {
taskCompletionSource.setResult(null);
return;
}
taskCompletionSource.setResult(firebaseOptionsToMap(options));
} catch (Exception e) {
taskCompletionSource.setException(e);
}
});

return taskCompletionSource.getTask();
}

private Task<Void> setAutomaticDataCollectionEnabled(Map<String, Object> arguments) {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
String appName = (String) Objects.requireNonNull(arguments.get(KEY_APP_NAME));
Boolean enabled = (Boolean) Objects.requireNonNull(arguments.get(KEY_ENABLED));
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
firebaseApp.setDataCollectionDefaultEnabled(enabled);
return null;
try {
String appName = (String) Objects.requireNonNull(arguments.get(KEY_APP_NAME));
Boolean enabled = (Boolean) Objects.requireNonNull(arguments.get(KEY_ENABLED));
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
firebaseApp.setDataCollectionDefaultEnabled(enabled);

taskCompletionSource.setResult(null);
} catch (Exception e) {
taskCompletionSource.setException(e);
}
});

return taskCompletionSource.getTask();
}

private Task<Void> setAutomaticResourceManagementEnabled(Map<String, Object> arguments) {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
String appName = (String) Objects.requireNonNull(arguments.get(KEY_APP_NAME));
boolean enabled = (boolean) Objects.requireNonNull(arguments.get(KEY_ENABLED));
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
firebaseApp.setAutomaticResourceManagementEnabled(enabled);
return null;
try {
String appName = (String) Objects.requireNonNull(arguments.get(KEY_APP_NAME));
boolean enabled = (boolean) Objects.requireNonNull(arguments.get(KEY_ENABLED));
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
firebaseApp.setAutomaticResourceManagementEnabled(enabled);

taskCompletionSource.setResult(null);
} catch (Exception e) {
taskCompletionSource.setException(e);
}
});

return taskCompletionSource.getTask();
}

private Task<Void> deleteApp(Map<String, Object> arguments) {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
String appName = (String) Objects.requireNonNull(arguments.get(KEY_APP_NAME));
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
try {
firebaseApp.delete();
} catch (IllegalStateException appNotFoundException) {
// Ignore app not found exceptions.
String appName = (String) Objects.requireNonNull(arguments.get(KEY_APP_NAME));
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
try {
firebaseApp.delete();
} catch (IllegalStateException appNotFoundException) {
// Ignore app not found exceptions.
}

taskCompletionSource.setResult(null);
} catch (Exception e) {
taskCompletionSource.setException(e);
}

return null;
});

return taskCompletionSource.getTask();
}

@Override
Expand Down
Expand Up @@ -7,6 +7,7 @@

import androidx.annotation.Keep;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.TaskCompletionSource;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.FirebaseApp;
import java.util.HashMap;
Expand Down Expand Up @@ -40,20 +41,27 @@ public static void registerPlugin(
* key) for the provided Firebase App.
*/
static Task<Map<String, Object>> getPluginConstantsForFirebaseApp(FirebaseApp firebaseApp) {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<Map<String, Object>> taskCompletionSource = new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
Map<String, Object> pluginConstants = new HashMap<>(registeredPlugins.size());
try {
Map<String, Object> pluginConstants = new HashMap<>(registeredPlugins.size());

for (Map.Entry<String, FlutterFirebasePlugin> entry : registeredPlugins.entrySet()) {
String channelName = entry.getKey();
FlutterFirebasePlugin plugin = entry.getValue();
pluginConstants.put(
channelName, Tasks.await(plugin.getPluginConstantsForFirebaseApp(firebaseApp)));
}
for (Map.Entry<String, FlutterFirebasePlugin> entry : registeredPlugins.entrySet()) {
String channelName = entry.getKey();
FlutterFirebasePlugin plugin = entry.getValue();
pluginConstants.put(
channelName, Tasks.await(plugin.getPluginConstantsForFirebaseApp(firebaseApp)));
}

return pluginConstants;
taskCompletionSource.setResult(pluginConstants);
} catch (Exception e) {
taskCompletionSource.setException(e);
}
});

return taskCompletionSource.getTask();
}

/**
Expand All @@ -64,14 +72,22 @@ static Task<Map<String, Object>> getPluginConstantsForFirebaseApp(FirebaseApp fi
* Restarts as `initializeCore` can only be called once in Dart.
*/
static Task<Void> didReinitializeFirebaseCore() {
return Tasks.call(
cachedThreadPool,
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();

cachedThreadPool.execute(
() -> {
for (Map.Entry<String, FlutterFirebasePlugin> entry : registeredPlugins.entrySet()) {
FlutterFirebasePlugin plugin = entry.getValue();
Tasks.await(plugin.didReinitializeFirebaseCore());
try {
for (Map.Entry<String, FlutterFirebasePlugin> entry : registeredPlugins.entrySet()) {
FlutterFirebasePlugin plugin = entry.getValue();
Tasks.await(plugin.didReinitializeFirebaseCore());
}

taskCompletionSource.setResult(null);
} catch (Exception e) {
taskCompletionSource.setException(e);
}
return null;
});

return taskCompletionSource.getTask();
}
}

0 comments on commit 374c9df

Please sign in to comment.