(2012-02-04 更新)Android軟體要達到參數傳遞必須要用Bundle或是Intent來把某個變數or物件傳給下一個Activity,這是比較一般的做法,不過還有另外一個繼承Application的做法,讓某些變數變成全域變數,在每個Activity中可以直接取用。這篇文章將對如何繼承Application來做說明。

會使用繼承Application的原因其實在於前一段時間小蛙在串接行動廣告的時候遇到多執行緒的問題,由於原始做法是一個Activity跳到另一個Activity,每個Activity中讀取一次廣告,如此一來,在來回了幾次之後就會發生OOM的情況(不一定會發生,但速度會變得很慢,從DDMS中可以看到執行緒狂開)。

小蛙得知繼承Application可以達到全域變數的功用後,異想天開的想把Google AdWhirl的AdWhirlLayout物件設成全域變數,只有第一次需要做初始化的動作,其他Activity只需要把這個變數拿回來用,如此一來就可以避免掉每個Activity都初始化一次造成的OOM。

試了之後發現還真的可以!直接看code吧!只有一個要注意的地方就是這邊傳入了前景的Activity a,會傳進來的原因是KuBanner建立的時候必須傳入Activity當參數,如果不傳入前景的Activity當參數,會造成kuAD開啟後只有banner大小的視窗以及無法顯示網頁的問題。初始化的動作小蛙把它放在主程式執行時才呼叫。

public class ApplicationBanner extends Application implements AdWhirlInterface{
    // Google AdWhirl Layout
    AdWhirlLayout adWhirlLayout;
    // 傳入主要(前景)的Activity
    Activity a;
    // kuAD banner
    KuBanner banner;
    // Google AdWhril Key
    private static final String ADWHIRL_KEY = "xxxxxxxxxxxxxxxx";
    // kuAD Key, or other keys( vpon … etc)
    private static final String KUAD_KEY        = "xxxxxxxxx";
    // 初始化 adWhirlLayout 供其他 Activity 直接取用
    public void initAdWhirlLayout(Activity a){
        this.a = a;
        adWhirlLayout = new AdWhirlLayout(a, ADWHIRL_KEY);
        AdWhirlManager.setConfigExpireTimeout(1000 * 60);
        AdWhirlTargeting.setAge(28);
        AdWhirlTargeting.setGender(AdWhirlTargeting.Gender.MALE);
        AdWhirlTargeting.setPostalCode("115");
        // 是否為測試模式,上架時要改成false
        AdWhirlTargeting.setTestMode(false);
        adWhirlLayout.setAdWhirlInterface(this);
    }
    // 在 Google AdWhirl 設定的 function
    public void showKuAD(){
        // 這邊要注意,如果這個 activity 一定要是前景視窗的
        banner = new KuBanner(a);
        banner.setAPID(KUAD_KEY);
        banner.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        // 這行改掉,換成 pushSubView
        //adWhirlLayout.handler.post(new ViewAdRunnable(adWhirlLayout, banner));
        adWhirlLayout.pushSubView(banner);
        banner.setkuADListener(new kuADListener() {
            public void onRecevie(String arg0) {
                adWhirlLayout.adWhirlManager.resetRollover();
                adWhirlLayout.rotateThreadedDelayed();
            }
            public void onFailedRecevie(String arg0) {
                banner.setkuADListener(null);
                adWhirlLayout.rollover();
            }
        });
    }
    // 印象中查到的資料這個不保證會執行,但還是放著,在軟體結束的時候,從 Activity 那邊刪程序比較保險些
    @Override
    public void onTerminate() {
        super.onTerminate();
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}

接著在AndroidManifest.xml中加入剛剛建立的Application名稱。加在原本的<application>標籤中。

<application android:name="ApplicationBanner"
android:icon="@drawable/icon"
android:label="@string/app_name">
    <activity> … </activity>
</application>

Layout中加入要放置廣告的區塊,例如小蛙的區塊設定如下:

<LinearLayout
    android:id="@+id/banner"
    android:layout_width="fill_parent"
    android:layout_height="50dp"
    android:layout_alignParentBottom="true">
</LinearLayout>

最後一個步驟了,在Activity中宣告並使用Application內的全域變數。這裡有一個要注意的部分,cleanLayout()的目的在於如果不先把原本layout中的東西清除,到下一個Activity又塞東西進去,會發生錯誤。在這邊小蛙想了很久到底什麼時候要清什麼時候要塞,後來發現只要在每個Activity onPause的時候清空,onResume的時候塞回去就可以了,這邊可以思考一下有沒有更好的方法,但小蛙這樣用到現在沒有發生錯誤!

ApplicationBanner     appState;
AdWhirlLayout        adWhirlLayou;
LinearLayout         layout;

//@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    // 取得剛剛宣告的 Application
    appState = (ApplicationBanner)getApplication();
    // 呼叫內部方法初始化,只有第一個Activity需要初始化,其他Activity可以直接使用
    appState.initAdWhirlLayout(ClassName.this);
    // 取得 Google AdWhirl Layout 物件
    adWhirlLayou = appState.adWhirlLayout;
}
// 刪除 ad banner layout
public void cleanLayout(){
    if(layout != null){
        layout.removeAllViews();
    }
}
@Override
public void onPause() {
    cleanLayout();
    super.onPause();
}
@Override
public void onResume() {
    if(layout == null){
        layout = (LinearLayout)findViewById(R.id.banner);
    }
    if(layout != null){
        layout.removeAllViews();
        layout.addView(adWhirlLayou);
        layout.invalidate();
    }
    super.onResume();
}

希望這篇文章對想在軟體中加入廣告,又不想大費周章把所有寫好的Activity改成Fragment的網友有幫助!

2012-02-04
如果忘了在AndroidManifest.xml加上<activity android:name=”com.kuad.ADDisplay”/>也會造成點擊廣告之後只有banner大小的視窗。

相關文章

SSL For Free – 免費又有綠色鎖頭的 SSL Certificates

之前聽說 Google 會優先搜尋有 https 的網頁 (參考:
2016-07-07 23:00:54
hans

8

Android Vuforia with jPCT-AE (5) – 多重模型載入,以 obj 為例

要進到這系列最後一篇文章了,這篇文章拖了很久,一直沒有時間整理,結果到最後 ... 程式碼留下來了,記憶卻有些模糊了,這邊小蛙配著程式碼盡可能的把還記得的東西寫下來。
2016-07-06 11:24:19
hans

8

Android Vuforia with jPCT-AE (4) – 載入 3DS 測試

延續 jPCT-AE Loader 載入模型的部份,這篇要記錄載入 3ds 檔案格式的方法,基本上跟前面幾個 obj, md2 的方法差不多,只有一些小小的變化而已。
2016-07-06 10:24:33
hans

8

Android Vuforia with jPCT-AE (3) – 載入 md2 測試

前兩篇介紹如何直接透過 jPCT-AE 直接繪圖以及載入 .obj 檔案,這邊繼續介紹 jPCT-AE 載入 md2 的方法,載入動作大致上類似,唯一不同的只有 texture 設定部份。
2016-07-06 09:24:43
hans

8

Android Vuforia with jPCT-AE (2) – 載入 obj 測試

上一篇 Android Vuforia with jPCT-AE (1) –
2016-07-06 08:24:55
hans

8

Android Vuforia with jPCT-AE (1) – 基本範例

說來慚愧,從 Google Adsense 被 ban 之後,就好久沒有發文了,站上 Vuforia 的文章也已經是好久以前的事情了 (遠目),最近有專案要用到 Vuforia,爬以前的文回來看,蛙哩咧 ... 現在已經更新到 Vu
2016-07-06 07:57:58
hans

8

ClickForce (MobiForce) 當機問題

這真是個浪費時間又漫長的過程,CF 推出新版後台以及新版 SDK 的時候,小蛙就下載來測試,一開始小蛙直接套在「我的股票精算師」上,但只要一套上去就當機 ...
2015-09-02 10:32:51
hans

8

我的股票精算師備份功能

常遇到使用者詢問「我的股票精算師」要怎麼備份,這篇記錄一下,需要寫怎麼備份表示軟體設計上有很大的問題,造成使用者使用上的困難,但小蛙最近沒有時間去做修改 ... 只好委屈精算師的使用者了 ><
2015-02-06 18:32:07
hans

8

第一次從淘寶買小米盒子3

最近阿咕有在大螢幕上看韓劇的需求,剛好搭上 Chromecast 的上市,survey 了一些 Android 電視棒。這篇記錄這幾天的經過。

2015-01-04 23:36:33
hans

8

Qualcomm Vuforia 教學 (6) – 3D model -> .obj -> .h

終於來到 Vuforia 記錄的最後一篇了,這篇參考到網路上神人的做法,怎麼把一個 3D model 轉換成 Vuforia 可以使用的 .h 檔,這邊之後都直接使用 An
2014-12-10 11:25:50
hans

8




  8 則留言 to “繼承Application達到Global Variable”

  1. 蛙大,感謝你的回覆~
    問題已找到了,是我自已在換頁的時候,將ListView.removeAllViewsInLayout(),
    但我有將現在ListView畫面紀錄,
    position = ListView.getFirstVisiblePosition();
    在back回到ListView onRestart時,ListView.setSelection(position);
    ListView沒有回到正確的position(看來setSelection沒有動作)
    現在把ListView.removeAllViewsInLayout() 移除就不會再跳到ListView的第一筆資料了(問題是解決了,但仍不清楚為何不是每次都發生!? = =)

  2. 蛙大您好,先謝謝你,這個方法的確可以減少廣告不斷開啟thread,而耗盡資源。
    但我遇到了一個問題,需向您請教,
    我在一個Activity中建立了一個ListView (Adapter: BaseAdapter),當我按下ListView中的Item時,會跳至下一個Activity,按back key後會回來ListView並停留在之前點選的頁面上。

    但我發現有時回復時會回到ListView的第一筆資料,
    後來找到的問題是在按下ListView Item進入下一個activity之前,
    onPause() > cleanLayout(); > layout.removeAllViews(); 似乎會使 getview 又動作,監看position的位置則為 0 開始,依序完成第一頁的各Item。
    不知蛙大是否有碰過類似的問題,或者能提供相關的建議,可以使removeAllViews();後不使getview再次動作。
    謝謝

    SAM

    • Dear SAM:

      小蛙看了一下API,以下是removeAllView的描述,
      public void removeAllViews ()
      Call this method to remove all child views from the ViewGroup.
      layout.removeAllViews() 看起來只會移除layout中的 child views,
      如果您的ListView不屬於 layout 的 child view 應該不至於被重置才對,
      會不會是有什麼其他問題呢?或是查看DDMS有可能是記憶體GC(純猜測)
      祝您好運囉!^__^

  3. 解掉了不少leak,感恩!另外發現就算APP關閉了,廣告似乎還是會在背景跑,造成參照的context無法被回收。目前我是用比較小的activity去new這些物件,減少leak的size,希望可以多少有些幫助…

    • 小蛙在試這個方法的時候,在Activity的onDestroy中加上
      android.os.Process.killProcess(android.os.Process.myPid());
      讓程式結束時把整個process砍掉,剛剛測了一下背景廣告就沒有再撥放了,
      (小蛙的AdWhirl refresh time設定為 Disabled,避免與 kuAD 的 refresh time 衝突造成多開),
      如果是需要背景執行的程式可能就要再想其他讓廣告別在背景跑的方法了!
      也謝謝您提供用較小的Acitivty去new物件的方法喔!! ^_^

    • thx~ 加了這行就沒問題了。
      KuAd的問題我有跟他們工程師反映過,好像是每次切換activity的時候都會重新reload廣告,不過最後會變得狂換廣告,閃來閃去。後來他們給了我們另一版.jar,就不會有這問題了,但不確定會不會更新到接下來的版本。

    • 這個小蛙也有跟他們的技術人員接洽過,
      現在他們已經把官網上的版本改成1.3.5,
      (這個版本以上的jar就不會有狂閃的問題了!)

 回覆

你可以使用以下語法 HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="">

(required)

(required)

   
© 2012 蛙齋 Suffusion theme by Sayontan Sinha