Ứng dụng của chúng tôi bị tấn công khá mạnh do rò rỉ bộ nhớ. Tôi đã tìm thấy nguyên nhân gốc rễ là AdView AdMob giữ tham chiếu đến các hoạt động cũ. Vấn đề là khá tốt tài liệu trong câu hỏi Android AdMob causes memory leak? và các liên kết phụ trong các ý kiến / câu trả lời. Tôi đã nhận thấy rằng vấn đề là không rõ ràng trong ICS khi GC cuối cùng làm sạch các WebViews với các tham chiếu đến các hoạt động. Tuy nhiên, HTC EVO 3D của tôi chạy Gingerbread chứng khoán không bao giờ thu thập các hoạt động và xem xét số lượng các báo cáo chặt chẽ do lỗi OOM, vấn đề là rất phổ biến cho ứng dụng của chúng tôi.Lỗi bộ nhớ AdMob - tránh bằng cách sử dụng hoạt động trống
Tôi muốn thực hiện theo giải pháp được cung cấp bởi TacB0sS, https://stackoverflow.com/a/8364820/684893. Anh ấy đã đề xuất tạo một hoạt động trống và sử dụng cùng hoạt động đó cho từng AdView AdMob. Sự rò rỉ sẽ được chứa kể từ khi AdView sẽ chỉ tiếp tục sống mà một hoạt động trống. Anh ấy đã cung cấp mã cho hoạt động đó và cách tham khảo nó nhưng tôi không biết cách tích hợp nó vào ứng dụng của chúng tôi. Mã của anh ấy không bao giờ gọi bất cứ thứ gì từ AdMob SDK theo như tôi có thể nói.
Hiện tại chúng tôi đang sử dụng AdView trong các bố cục XML để chúng tôi không tự động làm bất kỳ điều gì với quảng cáo trong mã chẳng hạn như loadAdAd(). Tất cả bố cục của chúng tôi với quảng cáo đều dựa vào quảng cáo nằm trong XML vì chúng được đặt ra tương đối so với quảng cáo. Hai câu hỏi của tôi là như vậy, làm cách nào để triển khai mã TacB0sS và làm cách nào để giữ lại các mối quan hệ bố cục XML của mình nếu chúng ta phải chuyển sang tạo các bố cục XML trong mã?
Cập nhật 3/6:
Cảm ơn Adam (TacB0sS) cho đáp ứng! Tôi không có vấn đề gì khi chuyển đổi để tạo Quảng cáo trong mã nhưng tôi vẫn gặp khó khăn khi sử dụng hoạt động giả của bạn khi tạo Quảng cáo. Mã của tôi hiện tại là:
AdMobActivity adActivity = new AdMobActivity();
adActivity.startAdMobActivity(this);
// Create an ad with the activity reference pointing to dummy activity
AdView adView = new AdView(adActivity.AdMobMemoryLeakWorkAroundActivity, AdSize.IAB_BANNER, "myAdUnitID");
// Create an ad request.
AdRequest adRequest = new AdRequest();
// add the ad to the layout and request it to be filled
RelativeLayout root_main = (RelativeLayout) findViewById(R.id.root_main);
root_main.addView(adView);
adView.loadAd(adRequest);
Tôi đã đặt mã này vào phương thức onCreate hoạt động ban đầu của tôi. Tôi nhận được một lực lượng gần trên dòng nơi tôi tạo AdView, "AdView adView = new AdView (...)". Stacktrace snippet:
03-06 00:34:28.098 E/AndroidRuntime(16602): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.udroid.wordgame/org.udroid.wordgame.MainMenu}: java.lang.NullPointerException
03-06 00:34:28.098 E/AndroidRuntime(16602): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1830)
(...)
03-06 00:34:28.098 E/AndroidRuntime(16602): Caused by: java.lang.NullPointerException
03-06 00:34:28.098 E/AndroidRuntime(16602): at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:100)
03-06 00:34:28.098 E/AndroidRuntime(16602): at com.google.ads.AdView.<init>(SourceFile:78)
03-06 00:34:28.098 E/AndroidRuntime(16602): at org.udroid.wordgame.MainMenu.onCreate**(MainMenu.java:71)** <- Line that creates the new AdView
Cách thích hợp để khởi tạo AdMobActivity của bạn và tham khảo nó khi tạo AdView là gì? Cảm ơn một lần nữa!
Cập nhật 2 3/6:
tôi đã tìm ra vấn đề của tôi tạo ra hoạt động này. Tôi đã giải pháp của bạn hoàn toàn được triển khai và phần tốt nhất là nó thực sự giải quyết rò rỉ bộ nhớ của tôi. Sau khi trải qua hai tuần về vấn đề này, tôi rất vui vì nó đã được giải quyết. Dưới đây là các bước đầy đủ tôi đã sử dụng:
Tạo một hoạt động mới gọi là AdMobActivity:
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);
Log.i("CHAT", "in onCreate - AdMobActivity");
finish();
}
public static final void startAdMobActivity(Activity activity) {
Log.i("CHAT", "in startAdMobActivity");
Intent i = new Intent();
i.setComponent(new ComponentName(activity.getApplicationContext(), AdMobActivity.class));
activity.startActivity(i);
}
}
Thêm dòng sau vào AndroidManifest.xml của bạn
<activity android:name="org.udroid.wordgame.AdMobActivity"
android:launchMode="singleInstance" />
Bạn cần phải khởi tạo AdMobActivity giả trước khi cố gắng để tải bất kỳ quảng cáo nào. Hoạt động này sẽ không chứa bất cứ điều gì. Nó sẽ được hiển thị trong một giây và sau đó đóng lại, quay trở lại hoạt động bạn đã gọi nó. Bạn không thể tạo nó trong cùng hoạt động bạn muốn tải Quảng cáo vì nó phải được khởi tạo hoàn toàn kịp thời trước khi sử dụng.Tôi khởi tạo nó trong hoạt động trên màn hình tải khởi động của onCreate trước khi hoạt động chính chứa quảng cáo bắt đầu:
// Start the dummy admob activity. Don't try to start it twice or an exception will be thrown
if (AdMobActivity.AdMobMemoryLeakWorkAroundActivity == null) {
Log.i("CHAT", "starting the AdMobActivity");
AdMobActivity.startAdMobActivity(this);
}
Bây giờ bạn đã sẵn sàng tạo quảng cáo bằng mã. Thêm LinearLayout sau vào bố cục hoạt động XML của bạn. Căn chỉnh tất cả các khung nhìn khác cần thiết xung quanh bố cục này. AdView mà chúng tôi tạo trong mã sẽ được đặt bên trong chế độ xem này.
<LinearLayout
android:id="@+id/adviewLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
Trong hoạt động bạn muốn tải một quảng cáo, tạo một biến toàn cầu cho AdView:
AdView adView;
Trong ứng dụng của chúng tôi, chúng tôi tải bố trí khác nhau khi xoay điện thoại. Vì vậy, tôi gọi đoạn mã sau trên mỗi lần xoay. Nó tạo ra các adView nếu cần thiết và thêm nó vào adviewLayout.
// DYNAMICALLY CREATE AD START
LinearLayout adviewLayout = (LinearLayout) findViewById(R.id.adviewLayout);
// Create an ad.
if (adView == null) {
adView = new AdView(AdMobActivity.AdMobMemoryLeakWorkAroundActivity, AdSize.BANNER, "<ADUNITID>");
// Create an ad request.
AdRequest adRequest = new AdRequest();
// Start loading the ad in the background.
adView.loadAd(adRequest);
// Add the AdView to the view hierarchy. The view will have no size until the ad is loaded.
adviewLayout.addView(adView);
}
else {
((LinearLayout) adView.getParent()).removeAllViews();
adviewLayout.addView(adView);
// Reload Ad if necessary. Loaded ads are lost when the activity is paused.
if (!adView.isReady() || !adView.isRefreshing()) {
AdRequest adRequest = new AdRequest();
// Start loading the ad in the background.
adView.loadAd(adRequest);
}
}
// DYNAMICALLY CREATE AD END
Cuối cùng, hãy chắc chắn bạn gọi adView.destroy() trong các hoạt động onDestroy() phương pháp:
@Override
protected void onDestroy() {
adView.destroy();
super.onDestroy();
}
Bất cứ ai khác mà đọc này, hãy nhớ rằng đây là giải pháp của Adam (TacB0sS), không phải của tôi. Tôi chỉ muốn cung cấp chi tiết triển khai đầy đủ để giúp người khác thực hiện dễ dàng hơn. Lỗi AdMob này là một vấn đề lớn đối với các ứng dụng chạy trước tổ ong và giải pháp của Adam là điều tốt nhất tôi có thể tìm thấy để phá vỡ nó. Và nó hoạt động!
trình như một say mê !! Cảm ơn cả hai bạn @ravishi và @ TacB0sS !! – Regis
Hi ravishi ... Tôi đang gặp rắc rối với giải pháp này. Bạn có thể giúp tôi không. Đây là câu hỏi của tôi http://stackoverflow.com/questions/15583994/activity-does-not-launch-from-the-recent-activities-android –
Có liên kết đến mã đầy đủ @ravishi không? –