问题
I have a BaseActivity
for all activities in my app.
Here I create, add to the view hierarchy and load an AdView
programmatically in onStart.
If I navigate to other activity in my app and then go back, or exit app LeakCanary report a memory leak.
In all the examples on the internet for Admob, the ad is loaded in onCreate, but we may use onStart see this and this
There is more questions about this: SO, issue BUT NOT SOLUTION.
The only solution that I found is to use onStart
y onStop
to use all logic for the AdView
My question is:
Is this approach OK?
Can I have another issues(appart from memory leaks) with this approach?
What is your solution for the admob memory leak??
This is an old question but still not clear answer.
I am using
implementation 'com.google.android.gms:play-services-ads:18.3.0'
Here is some of my code
public abstract class BaseActivity extends AppCompatActivity
implements AdmobHelp.Listener{
@Override protected void onCreate(Bundle savedInstanceState) {
mAdmobHelp = new AdmobHelp(a, this);
}
@Override public void onStart() {
super.onStart();
mAdmobHelp.onStart();
}
//...
}
public class AdmobHelp extends AdListener {
AdmobHelp(Activity a, Listener l) {
mActivity = a;
mContext = a.getApplicationContext();
mResources = a.getResources();
mCb = l;
mLinearRootContainer = a.findViewById(R.id.linear_container_admob);
//call this method only once for app (variable in Application class)
mIsInitialized = MyApplication.isInitializeAdmobDone();
}
void onStart() {
initlzAdmobOrNo();
showAdNoConsent();
}
void onStop() {
destroyRemoveFromContainerAdView();
}
void onResume() {
if(mAdView == null) mAdView.resume();
}
void onPause() {
if(mAdView == null) mAdView.pause();
}
void onDestroy() {
destroyAdView();//just in case
mTv = null;
mLinearRootContainer = null;
mCb = null;
mContext = null;
mActivity = null;
}
private void initlzAdmobOrNo() {
if(!mIsInitialized) {
MobileAds.initialize(mContext, mResources.getString(R.string.admob_app_id_test));
mIsInitialized = true;
MyApplication.setIsInitializeAdmobDone(true);//saved in Application class
}
}
private void showAdNoConsent() {
showAd(-2); //any value but not 1
}
private void showAd(int statusValue) {
if(mAdView == null) {
initNewBannerAddToContainerLoadAdd(statusValue);
} else {
destroyRemoveFromContainerAdView();
initNewBannerAddToContainerLoadAdd(statusValue);
}
}
private void initNewBannerAddToContainerLoadAdd(int statusValue) {
try {
mAdView = new AdView(mContext);
adView.setAdUnitId(mResources.getString(R.string.admob_banner_test));
mAdView.setAdSize(AdSize.SMART_BANNER);
mAdView.setAdListener(this);
mAdView.setVisibility(View.GONE);
if (mLinearRootContainer != null)mLinearRootContainer.addView(mAdView, 0);
AdRequest adRequest= getAdRequestWithConsent(statusValue);
mAdView.loadAd(adRequest);
} catch (Exception e) {}
}
private AdRequest getAdRequestWithConsent(int statusValue) {
AdRequest.Builder builder = new AdRequest.Builder();
if (builder != null) {
addAllTestDevicesIfDebug(builder);
if (statusValue == 1) {
l("YES npa 1 *** NON_PERSONALIZE");
Bundle extras = new Bundle();
extras.putString("npa", "1");
builder.addNetworkExtrasBundle(AdMobAdapter.class, extras);
}
AdRequest adRequest = builder.build();
return adRequest;
}
return null;
}
public void destroyRemoveFromContainerAdView() {
try {
if (mAdView != null) {
mAdView.pause();
mAdView.setAdListener(null);
if (mLinearRootContainer != null) mLinearRootContainer.removeView(mAdView);
mAdView.destroy();
mAdView = null;
}
} catch (Exception e) {}
}
private void destroyAdView() {
try {
if (mAdView != null) {
mAdView.setAdListener(null);
mAdView.destroy();
}
} catch (Exception e) {}
mAdView = null;
}
@Override public void onAdLoaded() {
if (mTv != null) mTv.setVisibility(View.GONE);
if (mAdView != null) mAdView.setVisibility(View.VISIBLE);
}
}
This are my intents to navigate
```
void makeIntentToSecondActivity(){
Intent i = new Intent(...);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
//NOT finish()
}
void makeIntentToThirdActivity(){
Intent i = new Intent(...);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish()
}
And to go back:
void makeIntentToMainActivity(){
Intent i = new Intent(...);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish()
}
来源:https://stackoverflow.com/questions/65643767/android-admob-has-memory-leak