我已将AdMob v4.1.0集成到我的应用程序中,它似乎导致了巨大的内存泄漏(非常确定它已经发生在4.0.4上)。
为了隔离问题,我创建了一个具有空白线性布局的新项目,并向其添加了AdView(这实际上是AdMob提供的示例代码中的复制和粘贴)。请参阅我的main.xml,MainActivity.java和清单内容:
main.xml中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/linearLayout">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>
MainActivity.java:
package AdsTry.main;
import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
private final int AD_VIEW_ID = 1000000;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Lookup R.layout.main
LinearLayout layout = (LinearLayout)findViewById(R.id.linearLayout);
// Create the adView
// Please replace MY_BANNER_UNIT_ID with your AdMob Publisher ID
AdView adView = new AdView(this, AdSize.BANNER, "MY_BANNER_UNIT_ID");
adView.setId(AD_VIEW_ID);
// Add the adView to it
layout.addView(adView);
// Initiate a generic request to load it with an ad
AdRequest request = new AdRequest();
adView.loadAd(request);
}
@Override
protected void onPause() {
Log.i("AdsTry", "onPause");
getAdView().stopLoading();
super.onPause();
}
@Override
protected void onDestroy() {
Log.i("AdsTry", "onDestroy");
getAdView().destroy();
super.onDestroy();
}
private AdView getAdView()
{
return (AdView) findViewById(AD_VIEW_ID);
}
}
清单:
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- AdMobActivity definition -->
<activity android:name="com.google.ads.AdActivity"
android:configChanges="orientation|keyboard|keyboardHidden" />
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
这就是我的所有代码。
现在,在运行此应用程序时,我可以看到onPause和onDestory都被调用并且Activity被终止,但问题是它永远不会用于GC,因为它会导致InputMethodManager保持对活动(参见活动销毁后从HPROF输出中获取的图像):
删除与AdView相关的代码后(再次,这是此应用程序的唯一代码)问题就消失了:
编辑: 还尝试从onCreate中删除所有代码并更新main.xml以包含以下内容(仍然得到相同的结果):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/linearLayout">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<com.google.ads.AdView
android:id="@+id/Ad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
ads:adUnitId="MY_ID"
ads:adSize="BANNER"
ads:loadAdOnCreate="true"/>
</LinearLayout>
任何想法????
答案 0 :(得分:6)
我正在使用“play-services-ads:7.5.0”,并且创建de AdMobActivity并不是必需的。它的工作原理是:
以动态方式创建广告
mAdView = new AdView(getApplicationContext(), AdSize.BANNER, banner_ad_unit_id); mAdsContainer.addView(mAdView);
在销毁和销毁adView时删除linearLayout中的所有视图
mAdView.setAdListener(null);
mAdsContainer.removeAllViews();
mAdView.destroy();
不幸的非页内广告仍在泄密
答案 1 :(得分:5)
这是我为这场混乱做的工作:
我通过使用相同的空活动实例来限制内存泄漏:
public final class AdMobActivity
extends Activity {
public static AdMobActivity AdMobMemoryLeakWorkAroundActivity;
public AdMobActivity() {
super();
if (AdMobMemoryLeakWorkAroundActivity != null)
throw new IllegalStateException("This activity should be created only once during the entire application life");
AdMobMemoryLeakWorkAroundActivity = this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finish();
}
public static final void startAdMobActivity(Activity activity) {
Intent i = new Intent();
i.setComponent(new ComponentName(activity.getApplicationContext(), AdMobActivity.class));
activity.startActivity(i);
}
}
可以使用 AdMobActivity.AdMobMemoryLeakWorkAroundActivity 创建更多广告。
您还需要将活动添加到清单中:
<activity
android:launchMode="singleInstance"
android:name="com.nu.art.software.android.modules.admob.AdMobActivity" />
这种实现违背了我对静态引用的看法,这些静态引用不是常量,但是这种实现可以防止泄漏,因为只有一个活动实例用于创建所有广告,因此没有更多的活动泄漏,加上活动的事实完全是空的。
注意:您应该从应用主要活动 onCreate 方法调用 startAdMobActivity 方法。
亚当。
<强>更新强>
此解决方案仅在您动态创建广告时才有效,并使用代码将其添加到布局中...并且不要忘记在Activity.onDestroy()中将其销毁。
答案 2 :(得分:3)
解决此问题的一种方法是使用应用程序的基本活动创建一个单一的adview实例。将此广告添加到您想要的任何活动中,但请记住在destroy方法的活动中将其删除。
这样,adview只会泄漏基本活动,您几乎不应该有多个实例。
示例:
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.venue);
mainLayout = (LinearLayout) findViewById(R.id.venueLayout);
adview = StaticStateClass.getAdview();
AdRequest request = new AdRequest();
request.addKeyword(name);
mainLayout.addView(adview);
adview.loadAd(request);
}
@Override
public void onDestroy() {
mainLayout.removeView(adview);
super.onDestroy();
}
答案 3 :(得分:2)
我发现那个叫: -
mAdView.destroy();
离开活动之前为我解决了泄漏。
以下是我在xml中声明横幅广告的方式: -
<com.google.android.gms.ads.AdView
android:id="@+id/adView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
ads:adSize="BANNER"
ads:adUnitId="@string/banner_ad_unit_id_2" />
在onCreate()中获取admob横幅的引用: -
mAdView = (AdView) findViewById(R.id.adView2);
AdRequest banneradRequest = new AdRequest.Builder().build();
mAdView.loadAd(banneradRequest);
并在活动的ondestroy()中销毁它: -
@Override
protected void onDestroy() {
super.onDestroy();
mAdView.destroy();
}
答案 4 :(得分:1)
我面临同样的问题。唯一有一件事帮助了我 - 它的System.exit(0)。我不喜欢它,但这是我找到的唯一方法 AdMob只停留在RAM 4ever中,不要让我的应用程序正常完成。当我重新启动我的应用程序操作系统时,只会引发该不死应用程序,很快就会导致内存不足异常 My AdMob support forum topic - 迄今为止没有任何支持。看起来像没关心。
答案 5 :(得分:0)
解决此问题的另一个答案,即使这样做很麻烦,也要遵循以下步骤。
取消使用sharedPreferences或任何其他类型的存储持久性所需的所有数据,
将这些值存储在局部变量/对象
擦除所有应用程序数据
重新坚持一切
您可以在应用关闭时启动服务。这会阻止数据因内存泄漏而变得非常大。令人讨厌的方式来解决它,但我已经尝试过它,它的工作原理。
答案 6 :(得分:-1)
Donot将您的用户界面与Admob合并,您可以运行其他线程从Admob获取广告。您也可以按特定时间间隔刷新广告。您可以更轻松地调试内存问题。
由于 迪帕克
答案 7 :(得分:-2)
基本上,这不是一个真正的问题。发生了什么事情是你的活动是接收onDestroy,进行清理,然后等待GC运行。当GC发生时,它会看到这个旧的上下文并清理所有底层的垃圾,但它似乎没有清除该传递中的Activity - 这就是为什么你的“泄露”活动占用的空间很小:它是基本上是一个shell。在下一次GC通过时,它将被清理。
您可以通过激活您的活动,退出(触发onDestroy),返回进程,触发GC和hprof转储,等待一点,然后再触发另一个GC和hprof转储来看到这一点。在第一次转储中 - 至少在我的测试中 - 我看到了类似于你的结果:一个额外的活动,内存占用非常小。在第二个转储中,我只看到了当前正在运行的活动。