Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[firebase_admob] Fixes memory leak by removing static reference for Activities #35

Closed
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/firebase_admob/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.9.0+6

* Fix Android memory leak.

## 0.9.0+5

* Update documentation to reflect new repository location.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class FirebaseAdMobPlugin implements MethodCallHandler {

private final Registrar registrar;
private final MethodChannel channel;
private final MobileAdRegistrar adRegistrar;

RewardedVideoAdWrapper rewardedWrapper;

Expand All @@ -31,12 +32,17 @@ public static void registerWith(Registrar registrar) {
}
final MethodChannel channel =
new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_admob");
channel.setMethodCallHandler(new FirebaseAdMobPlugin(registrar, channel));

final MobileAdRegistrar adRegistry = new MobileAdRegistrar();

channel.setMethodCallHandler(new FirebaseAdMobPlugin(registrar, channel, adRegistry));
}

private FirebaseAdMobPlugin(Registrar registrar, MethodChannel channel) {
private FirebaseAdMobPlugin(
Registrar registrar, MethodChannel channel, MobileAdRegistrar adRegistrar) {
this.registrar = registrar;
this.channel = channel;
this.adRegistrar = adRegistrar;
FirebaseApp.initializeApp(registrar.context());
rewardedWrapper = new RewardedVideoAdWrapper(registrar.activity(), channel);
}
Expand Down Expand Up @@ -84,7 +90,7 @@ private void callLoadBannerAd(
adSize = new AdSize(width, height);
}

MobileAd.Banner banner = MobileAd.createBanner(id, adSize, activity, channel);
MobileAd.Banner banner = adRegistrar.createBanner(id, adSize, activity, channel);

if (banner.status != MobileAd.Status.CREATED) {
if (banner.status == MobileAd.Status.FAILED)
Expand Down Expand Up @@ -143,7 +149,7 @@ private void callLoadRewardedVideoAd(MethodCall call, Result result) {
}

private void callShowAd(int id, MethodCall call, Result result) {
MobileAd ad = MobileAd.getAdForId(id);
MobileAd ad = adRegistrar.getAdForId(id);
if (ad == null) {
result.error("ad_not_loaded", "show failed, the specified ad was not loaded id=" + id, null);
return;
Expand All @@ -164,7 +170,8 @@ private void callShowAd(int id, MethodCall call, Result result) {
}

private void callIsAdLoaded(int id, MethodCall call, Result result) {
MobileAd ad = MobileAd.getAdForId(id);
MobileAd ad = adRegistrar.getAdForId(id);

if (ad == null) {
result.error("no_ad_for_id", "isAdLoaded failed, no add exists for id=" + id, null);
return;
Expand All @@ -182,7 +189,8 @@ private void callShowRewardedVideoAd(MethodCall call, Result result) {
}

private void callDisposeAd(int id, MethodCall call, Result result) {
MobileAd ad = MobileAd.getAdForId(id);
MobileAd ad = adRegistrar.getAdForId(id);

if (ad == null) {
result.error("no_ad_for_id", "dispose failed, no add exists for id=" + id, null);
return;
Expand Down Expand Up @@ -212,7 +220,7 @@ public void onMethodCall(MethodCall call, Result result) {
callLoadBannerAd(id, activity, channel, call, result);
break;
case "loadInterstitialAd":
callLoadInterstitialAd(MobileAd.createInterstitial(id, activity, channel), call, result);
callLoadInterstitialAd(adRegistrar.createInterstitial(id, activity, channel), call, result);
break;
case "loadRewardedVideoAd":
callLoadRewardedVideoAd(call, result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import android.app.Activity;
import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
Expand All @@ -21,15 +20,15 @@

abstract class MobileAd extends AdListener {
private static final String TAG = "flutter";
private static SparseArray<MobileAd> allAds = new SparseArray<MobileAd>();

private final MethodChannel channel;
private final MobileAdRegistrar adRegistrar;
final Activity activity;
final MethodChannel channel;
final int id;
Status status;
double anchorOffset;
double horizontalCenterOffset;
int anchorType;
Status status;

enum Status {
CREATED,
Expand All @@ -39,29 +38,17 @@ enum Status {
LOADED,
}

private MobileAd(int id, Activity activity, MethodChannel channel) {
private MobileAd(
MobileAdRegistrar adRegistrar, int id, Activity activity, MethodChannel channel) {
this.id = id;
this.activity = activity;
this.channel = channel;
this.status = Status.CREATED;
this.anchorOffset = 0.0;
this.horizontalCenterOffset = 0.0;
this.anchorType = Gravity.BOTTOM;
allAds.put(id, this);
}

static Banner createBanner(Integer id, AdSize adSize, Activity activity, MethodChannel channel) {
MobileAd ad = getAdForId(id);
return (ad != null) ? (Banner) ad : new Banner(id, adSize, activity, channel);
}

static Interstitial createInterstitial(Integer id, Activity activity, MethodChannel channel) {
MobileAd ad = getAdForId(id);
return (ad != null) ? (Interstitial) ad : new Interstitial(id, activity, channel);
}

static MobileAd getAdForId(Integer id) {
return allAds.get(id);
this.adRegistrar = adRegistrar;
adRegistrar.register(id, this);
}

Status getStatus() {
Expand All @@ -73,7 +60,7 @@ Status getStatus() {
abstract void show();

void dispose() {
allAds.remove(id);
adRegistrar.unregister(id);
}

private Map<String, Object> argumentsMap(Object... args) {
Expand Down Expand Up @@ -127,8 +114,13 @@ static class Banner extends MobileAd {
private AdView adView;
private AdSize adSize;

private Banner(Integer id, AdSize adSize, Activity activity, MethodChannel channel) {
super(id, activity, channel);
Banner(
MobileAdRegistrar adRegistrar,
Integer id,
AdSize adSize,
Activity activity,
MethodChannel channel) {
super(adRegistrar, id, activity, channel);
this.adSize = adSize;
}

Expand Down Expand Up @@ -195,8 +187,8 @@ void dispose() {
static class Interstitial extends MobileAd {
private InterstitialAd interstitial = null;

private Interstitial(int id, Activity activity, MethodChannel channel) {
super(id, activity, channel);
Interstitial(MobileAdRegistrar adRegistrar, int id, Activity activity, MethodChannel channel) {
super(adRegistrar, id, activity, channel);
}

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

import android.app.Activity;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.ads.AdSize;
import io.flutter.plugin.common.MethodChannel;

/* Class that acts as Factory and registry for MobileAds. */
class MobileAdRegistrar {
private SparseArray<MobileAd> allAds = new SparseArray<>();

/* Returns a MobileAd if it is registered in this Registrar. */
@Nullable
MobileAd getAdForId(Integer id) {
return allAds.get(id);
}

/* Registers a new MobileAd with the given id. */
void register(int id, MobileAd ad) {
allAds.put(id, ad);
}

/* Returns an already registered Banner with the given id or creates a new Banner. */
@NonNull
MobileAd.Banner createBanner(
Integer id, AdSize adSize, Activity activity, MethodChannel channel) {
MobileAd ad = getAdForId(id);
return (ad != null)
? (MobileAd.Banner) ad
: new MobileAd.Banner(this, id, adSize, activity, channel);
}

/* Returns an already registered Interstitial with the given id or creates a new Interstitial. */
@NonNull
MobileAd.Interstitial createInterstitial(Integer id, Activity activity, MethodChannel channel) {
MobileAd ad = getAdForId(id);
return (ad != null)
? (MobileAd.Interstitial) ad
: new MobileAd.Interstitial(this, id, activity, channel);
}

/* Unregisters a MobileAd with the given id. */
void unregister(Integer id) {
allAds.remove(id);
}
}
2 changes: 1 addition & 1 deletion packages/firebase_admob/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase AdMob, supporting
banner, interstitial (full-screen), and rewarded video ads
author: Flutter Team <[email protected]>
homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_admob
version: 0.9.0+5
version: 0.9.0+6

flutter:
plugin:
Expand Down