跳到主要內容

有所為有所不為? 談 Airpush 的侵入式廣告

您是否有過這種經驗,安裝了某個 Android App 之後,您手機上方的通知列竟三不五時跳出莫名的廣告?
沒錯! 這有可能是 Airpush 的傑作,只要開發者在 App 中嵌入了 Airpush SDK 並做些設定後,就可以讓您手機的通知列彈出像這樣的廣告。

寫 App 畢竟不是慈善事業,能從中獲取實質的收益也是開發動力之一。除了直接推出付費版或應用程式內付費之外,免費模式結合廣告也是常見的做法。

但說實在,身為開發者其實也不太希望在自己的 App 內放廣告,除了佔用畫面,破壞整體感覺外,大部分使用者也討厭廣告。但在付費購買模式還未被廣泛接受或想更快提高下載量的狀況下(更別說還有外力介入,幹掉整個付費 Market 這種鳥事),免費模式結合廣告就成了一個讓使用者既不用花錢,開發者也能賺取微薄收入的折衷辦法。

那麼 Airpush 的問題是什麼呢?
以傳統的行動廣告模式來說,廣告大多是呈現在 App 內的某個區塊(開發者通常會放在最上方或最下方)。也就是只有在 App 被開啟的時候,使用者才有機會看到廣告。在這種狀況下廣告給使用者感覺是附屬、重要性低的(即便如此,對使用者也是干擾)。

但在通知列跳出廣告我認為是一種中斷行為。當然,中斷行為也有程度之分,最高程度的中斷行為是直接跳出全螢幕視窗或對話框來中斷使用者目前正在做的事,比如來電、鬧鐘響、電量不足...等。而次要程度我認為就是通知列了,比如收到簡訊、磁碟空間不足、軟體下載/安裝...等重要但不需使用者立即處理的事情。Airpush的作法等於提高廣告的重要性來中斷使用者,就像讓你不斷的收到廣告簡訊。

還有一點,在使用者的心目中,通知列通常會被當作是系統的一部份,當通知列三不五時跳出廣告,使用者可能會覺得他的手機被入侵、或中毒了,接下來就是想找出有掛廣告的 App 並移除。

若利用廣告賺錢是必要之惡,開發者可能得考量何種方式最適合自己的 App,以避免錢還沒賺到就先打壞自己名聲。順帶一提,Airpush 除了這種主動推送通知的廣告之外,還有 AppWall Ads(全畫面廣告) 及 Icon Ads(在桌面產生一個廣告連結 Icon),看來 Airpush 是打算以這種爭議性的廣告模式來衝擊市場。

考量到可能的反彈,Airpush 官方也提供了兩個方法給不想看到推送通知廣告的人,一是在手機上另外安裝一個 Airpush Opt-out App,二是在其網站輸入 IMEI 碼做為過濾。另外也可以使用第三方開發的 Airpush 偵測工具來移除有掛載 Airpush 廣告的 App。

至於使用者/開發者會不會接受這種模式,就留待時間來證明了,不過目前看起來情況是一面倒。
最後還是要呼籲,如果有您覺得不錯的軟體,請不要忘了按一下廣告或購買付費版,給開發者實質的鼓勵唷。

2012/7/12補充:
在 Android 4.1 Jelly Bean 中,使用者可以長按跳出的 Notification 以知道是由哪支 App 所發送,使用者可以移除該 App 或禁止所有來自該 App 的 Notification。
2012/8/1補充:
在最新的 Google Play Developer Program Policies 中新增了對廣告行為的規範。(感覺有些是針對類似行為來的)


Protip: don't annoy the user

相關連結:
Airpush 網站: http://www.airpush.com
Airpush 官方提供的廣告移除方式: http://www.airpush.com/optout
Airpush Opt-out App: https://play.google.com/store/apps/details?id=com.airpush.optoutapp(評價挺慘烈的)
第三方的 Airpush 偵測/移除工具: https://play.google.com/store/apps/details?id=com.brosmike.airpushdetector(評價跟上面的有天壤之別 XD)

留言

這個網誌中的熱門文章

App 在 Google Play 被停權與恢復的經驗分享

最近心情真像是洗了三溫暖~ 前幾天把已經很久沒維護的  EZ App安裝器  稍微調整了 UI,修了修 Bug,提交更新。 幾個小時過去發現 Google Play 還沒反應,感覺有點怪...可能是系統忙碌吧。當下也沒想太多就跑去睡了。 隔天一早打開開發者控制台,登愣!又看到熟悉的景象... App 被停權了!!! 為什麼說"又"呢? 出來混總是要還的,被停權也不是第一次了。 多年前剛開始在 Google Play 上架時,學別人在商店描述裡加了一堆 Keyword,其實有沒有用也不知道。然後某次開發人員計劃政策調整後,這種行為被視為違規,於是一下子被停權兩隻 App。 畢竟是自己沒注意到政策調整,而且罪證確鑿,只好摸摸鼻子認了。不過明明是很簡單就能修正的問題,Google 總是完全不給機會就直接停權,手段實在狠毒!這也是最讓人難以接受的地方。 順帶一題,Google Play 的違規處分大概分為以下幾種: 拒絕 :更新版本遭拒,但之前所發佈的版本仍會保留在 Google Play 商店中。 下架 :應用程式會從 Google Play 下架。必須提交符合規範的更新版本,才能讓應用程式重新上架。 停權 :應用程式會從 Google Play 下架。必須更改 package name,才能讓應用程式重新上架。這意味著將失去原本累積的下載數、統計資料和評分,一切重頭來過。 終止開發者帳號 :所有應用皆會下架,無法再上架新應用。"相關帳戶"也會一併處分,不允許再註冊新的開發者帳號。 我三次遇到的都是停權,但這次的原因是為什麼呢? 根據信裡的說明是違反了開發人員發佈協議的"其他商店"條款。 什麼是"其他商店"條款? 4.5 其他商店。凡是「產品」具有任何推廣其他商店之用途,藉此引導使用者透過這類替代性管道發佈 Android 軟體應用程式或遊戲,則一概禁止在「商店」中發佈或提供。 奇怪?我的 App 裡面沒有推廣其他應用程式商店啊? 信中有申訴的管道,寫信去問明白吧。網頁說可以用中文 、 英文 、 日文及韓文提出申訴,就直接寫中文吧。一來比較好溝通,同時看看都是講中文的會不會比較寬大為懷 XDD~ 提出申訴後過了幾個小時,收到回覆了

使用 <uses-feature> 的注意事項

<uses-feature> 最早是在 Android 1.6 SDK (API Level 4) 中出現的,他的用途是用來宣告 App 會使用到哪些軟硬體功能(比如 Camera、Bluetooth、OpenGL ES version...)。不過事實上系統本身並不會去檢查這些設定,但 Google Play 確會用這些設定去過濾要呈現哪些 App 給使用者。 比如說我宣告了下面這行,表示我會使用到 Camera 功能。這樣 Google Play 就不會將我的 App 顯示在沒有 Camera 的裝置上。 <uses-feature android:name="android.hardware.camera" /> 不過後來在 Android 2.0 SDK (API Level 5) 中,<uses-feature> 多了一個屬性叫  android:required 。當某功能在 App 中是 必要 時需設定為  true ,若是 非必要 時則設成  false 。咦?...若是不需要的話,我直接省略 <uses-feature> 不是更省事嗎? 在看完落落長的  開發者文件  後才瞭解,嚴格來說,每個 App 都 應該 要清楚宣告哪些功能是必要或非必要。但因為種種原因,開發者可能忽略或未正確宣告。所以 Google Play 除了檢查 <uses-feature> 外,還會參考 <uses-permission> 的設定。當有設定 <uses-permission> 時, Google Play 會假定相關的功能是 必要 的,並加入過濾。 舉例來說,我的 App 會使用到 Camera,但不是必要的。而我只宣告了 Camera 的 <uses-permission>,卻忽略了 <uses-feature>。 <uses-permission android:name="android.permission.CAMERA" /> 此時 Google Play 發現了這個 <uses-permission>,便會將 Camera 視為 必要 而進行過濾,沒有 Camer

利用 Java Reflection 來呼叫被隱藏 {@hide} 的 API

注意:本文的範例於 Android 8 (Oreo) 上已無法執行,而 Google 也表明為了改善應用程式的安全與穩定,未來將逐步限制這些非正規的存取方式。 如果您有研究過 Android Source Code,應該會發現其中有許多函式都被標註了 @hide。也就是這些函式在 SDK 中是被隱藏的,一般情形下無法被呼叫使用。但有時我們又想使用這些功能該怎麼辦呢? 在不更動 Android System 的前提下,我們可以透過 Java 的反射機制 (Java Reflection) 來達成。 範例: 我們在 Android Source Code 中的 PackageManager 類別裡發現了一個函式 getPackageSizeInfo,可以用來取得應用程式的磁碟空間使用量,但在 SDK 內卻找不到此函式。 我們先試著用 getMethods 列出 PackageManager 中所有的函式 PackageManager pm = getPackageManager(); Method[] methods = pm.getClass().getMethods(); for (int i = 0; i < methods.length; i++) { Log.d(TAG, methods[i].getName()); } 看一下結果,沒錯,裡面確實有 getPackageSizeInfo 這個函式 調用方式: Method getPackageSizeInfo = pm.getClass().getMethod( "getPackageSizeInfo", String.class, IPackageStatsObserver.class); getPackageSizeInfo.invoke(pm, "xxx.xxx.xxx", new IPackageStatsObserver.Stub() { @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteExc