Skip to content

Commit

Permalink
[firebase_admob] Support v2 embedding (firebase#1365)
Browse files Browse the repository at this point in the history
  • Loading branch information
bparrishMines authored Dec 11, 2019
1 parent 50e84ed commit 68eb9fa
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 35 deletions.
5 changes: 5 additions & 0 deletions packages/firebase_admob/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.9.1

* Support v2 embedding. This will remain compatible with the original embedding and won't require
app migration.

## 0.9.0+10

* Remove the deprecated `author:` field from pubspec.yaml
Expand Down
26 changes: 26 additions & 0 deletions packages/firebase_admob/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,29 @@ android {
api 'com.google.firebase:firebase-ads:18.1.1'
}
}

// TODO(bparrishMines): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348
afterEvaluate {
def containsEmbeddingDependencies = false
for (def configuration : configurations.all) {
for (def dependency : configuration.dependencies) {
if (dependency.group == 'io.flutter' &&
dependency.name.startsWith('flutter_embedding') &&
dependency.isTransitive())
{
containsEmbeddingDependencies = true
break
}
}
}
if (!containsEmbeddingDependencies) {
android {
dependencies {
def lifecycle_version = "1.1.1"
compileOnly "android.arch.lifecycle:runtime:$lifecycle_version"
compileOnly "android.arch.lifecycle:common:$lifecycle_version"
compileOnly "android.arch.lifecycle:common-java8:$lifecycle_version"
}
}
}
}
1 change: 0 additions & 1 deletion packages/firebase_admob/android/gradle.properties

This file was deleted.

5 changes: 0 additions & 5 deletions packages/firebase_admob/android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.flutter.plugins.firebaseadmob">

<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="[ADMOB_APP_ID]"/>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
package io.flutter.plugins.firebaseadmob;

import android.app.Activity;
import android.content.Context;
import android.view.Gravity;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.MobileAds;
import com.google.firebase.FirebaseApp;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
Expand All @@ -17,29 +22,50 @@
import java.util.Locale;
import java.util.Map;

public class FirebaseAdMobPlugin implements MethodCallHandler {

private final Registrar registrar;
private final MethodChannel channel;

RewardedVideoAdWrapper rewardedWrapper;

/**
* Flutter plugin accessing Firebase Admob API.
*
* <p>Instantiate this in an add to app scenario to gracefully handle activity and context changes.
*/
public class FirebaseAdMobPlugin implements FlutterPlugin, ActivityAware, MethodCallHandler {
private Context applicationContext;
private MethodChannel channel;
private Activity activity;
// This is always null when not using v2 embedding.
private FlutterPluginBinding pluginBinding;
private RewardedVideoAdWrapper rewardedWrapper;

/**
* Registers a plugin with the v1 embedding api {@code io.flutter.plugin.common}.
*
* <p>Calling this will register the plugin with the passed registrar. However, plugins
* initialized this way won't react to changes in activity or context.
*
* @param registrar connects this plugin's {@link
* io.flutter.plugin.common.MethodChannel.MethodCallHandler} to its {@link
* io.flutter.plugin.common.BinaryMessenger}.
*/
public static void registerWith(Registrar registrar) {
if (registrar.activity() == null) {
// If a background Flutter view tries to register the plugin, there will be no activity from the registrar.
// We stop the registering process immediately because the firebase_admob requires an activity.
return;
}
final MethodChannel channel =
new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_admob");
channel.setMethodCallHandler(new FirebaseAdMobPlugin(registrar, channel));

final FirebaseAdMobPlugin plugin = new FirebaseAdMobPlugin();
plugin.initializePlugin(registrar.context(), registrar.activity(), registrar.messenger());
}

private FirebaseAdMobPlugin(Registrar registrar, MethodChannel channel) {
this.registrar = registrar;
this.channel = channel;
FirebaseApp.initializeApp(registrar.context());
rewardedWrapper = new RewardedVideoAdWrapper(registrar.activity(), channel);
private void initializePlugin(
Context applicationContext, Activity activity, BinaryMessenger messenger) {
this.activity = activity;
this.applicationContext = applicationContext;
FirebaseApp.initializeApp(applicationContext);

this.channel = new MethodChannel(messenger, "plugins.flutter.io/firebase_admob");
channel.setMethodCallHandler(this);

rewardedWrapper = new RewardedVideoAdWrapper(activity, channel);
}

private void callInitialize(MethodCall call, Result result) {
Expand All @@ -48,7 +74,7 @@ private void callInitialize(MethodCall call, Result result) {
result.error("no_app_id", "a null or empty AdMob appId was provided", null);
return;
}
MobileAds.initialize(registrar.context(), appId);
MobileAds.initialize(applicationContext, appId);
result.success(Boolean.TRUE);
}

Expand Down Expand Up @@ -203,9 +229,45 @@ private void callDisposeAd(Integer id, Result result) {
}

@Override
public void onMethodCall(MethodCall call, Result result) {
public void onAttachedToEngine(FlutterPluginBinding binding) {
pluginBinding = binding;
}

@Override
public void onDetachedFromEngine(FlutterPluginBinding binding) {
pluginBinding = null;
}

Activity activity = registrar.activity();
@Override
public void onAttachedToActivity(ActivityPluginBinding binding) {
initializePlugin(
pluginBinding.getApplicationContext(),
binding.getActivity(),
pluginBinding.getFlutterEngine().getDartExecutor());
}

@Override
public void onDetachedFromActivityForConfigChanges() {
MobileAd.disposeAll();
activity = null;
}

@Override
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
initializePlugin(
pluginBinding.getApplicationContext(),
binding.getActivity(),
pluginBinding.getFlutterEngine().getDartExecutor());
}

@Override
public void onDetachedFromActivity() {
MobileAd.disposeAll();
activity = null;
}

@Override
public void onMethodCall(MethodCall call, Result result) {
if (activity == null) {
result.error("no_activity", "firebase_admob plugin requires a foreground activity", null);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ abstract class MobileAd extends AdListener {
double horizontalCenterOffset;
int anchorType;

enum Status {
public enum Status {
CREATED,
LOADING,
FAILED,
Expand Down Expand Up @@ -73,6 +73,13 @@ void dispose() {
allAds.remove(id);
}

static void disposeAll() {
for (int i = 0; i < allAds.size(); i++) {
allAds.valueAt(i).dispose();
}
allAds.clear();
}

private Map<String, Object> argumentsMap(Object... args) {
Map<String, Object> arguments = new HashMap<String, Object>();
arguments.put("id", id);
Expand Down
1 change: 1 addition & 0 deletions packages/firebase_admob/example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ flutter {
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.flutter.plugins.firebaseadmob;

import androidx.test.rule.ActivityTestRule;
import dev.flutter.plugins.e2e.FlutterRunner;
import io.flutter.plugins.firebaseadmobexample.EmbeddingV1Activity;
import org.junit.Rule;
import org.junit.runner.RunWith;

@RunWith(FlutterRunner.class)
public class EmbeddingV1ActivityTest {
@Rule
public ActivityTestRule<EmbeddingV1Activity> rule =
new ActivityTestRule<>(EmbeddingV1Activity.class);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.flutter.plugins.firebaseadmob;

import androidx.test.rule.ActivityTestRule;
import dev.flutter.plugins.e2e.FlutterRunner;
import io.flutter.plugins.firebaseadmobexample.MainActivity;
import org.junit.Rule;
import org.junit.runner.RunWith;

@RunWith(FlutterRunner.class)
public class MainActivityTest {
@Rule public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
<activity android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
Expand All @@ -18,5 +17,12 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".EmbeddingV1Activity"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
</activity>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.firebaseadmobexample;

import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class EmbeddingV1Activity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@

package io.flutter.plugins.firebaseadmobexample;

import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import dev.flutter.plugins.e2e.E2EPlugin;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.firebaseadmob.FirebaseAdMobPlugin;

public class MainActivity extends FlutterActivity {
// TODO(bparrishMines): Remove this once v2 of GeneratedPluginRegistrant rolls to stable. https://github.com/flutter/flutter/issues/42694
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
public void configureFlutterEngine(FlutterEngine flutterEngine) {
flutterEngine.getPlugins().add(new E2EPlugin());
flutterEngine.getPlugins().add(new FirebaseAdMobPlugin());
}
}
1 change: 1 addition & 0 deletions packages/firebase_admob/example/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.enableJetifier=true
android.useAndroidX=true
10 changes: 9 additions & 1 deletion packages/firebase_admob/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ dependencies:
sdk: flutter
firebase_admob:
path: ../
firebase_core: ^0.4.0
firebase_core: ^0.4.2+1

dev_dependencies:
e2e: ^0.2.1
flutter_driver:
sdk: flutter

flutter:
uses-material-design: true

environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
7 changes: 5 additions & 2 deletions packages/firebase_admob/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: firebase_admob
description: Flutter plugin for Firebase AdMob, supporting
banner, interstitial (full-screen), and rewarded video ads
homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_admob
version: 0.9.0+10
version: 0.9.1

flutter:
plugin:
Expand All @@ -18,12 +18,15 @@ dependencies:
platform: ^2.0.0
flutter:
sdk: flutter
firebase_core: ^0.4.2+1

dev_dependencies:
e2e: ^0.2.1
flutter_driver:
sdk: flutter
mockito: ^3.0.0
flutter_test:
sdk: flutter
firebase_core: ^0.4.0

environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
Expand Down
15 changes: 15 additions & 0 deletions packages/firebase_admob/test/firebase_admob_e2e.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:e2e/e2e.dart';

import 'package:firebase_admob/firebase_admob.dart';

void main() {
E2EWidgetsFlutterBinding.ensureInitialized();

testWidgets('Initialize Firebase Admob', (WidgetTester tester) async {
expect(
FirebaseAdMob.instance.initialize(appId: FirebaseAdMob.testAppId),
completion(isTrue),
);
});
}

0 comments on commit 68eb9fa

Please sign in to comment.