1. 程式人生 > >AdMob在Android中的回撥造成崩潰的處理方式

AdMob在Android中的回撥造成崩潰的處理方式

遊戲開發總是要接入各種各樣的SDK,廣告也成了一種常用的變現方式。而AdMob對於遊戲開發的老鳥來說一定不會陌生。 AdMob for Unity

RewardBasedVideoAd.Instance.OnAdFailedToLoad;
RewardBasedVideoAd.Instance.OnAdLoaded;
RewardBasedVideoAd.Instance.OnAdOpening;
RewardBasedVideoAd.Instance.OnAdStarted;
RewardBasedVideoAd.Instance.OnAdRewarded;
RewardBasedVideoAd.Instance
.OnAdClosed; RewardBasedVideoAd.Instance.OnAdLeavingApplication;

關鍵的地方無非就是監聽這幾個事件。本人在最初測試工程中並未發現任何異常,但是同樣的指令碼放在專案中時卻出現了崩潰和UI顯示異常的狀況。具體現象:無論在OnAdRewarded還是在OnAdClosed中,如果有UI相關的邏輯,那麼就會出現顯示異常,如果有粒子特效,那麼就會出現崩潰後自動重啟應用。

Unity捕獲不到相關異常,但是Android日誌中會有這樣一個錯誤:call to OpenGL ES API with no current context (logged once per thread)

從內容和崩潰現象上看,這個是渲染異常造成的。根據之前瞭解的部分Android開發知識分析,廣告視訊在Android中會由單獨的Activity去播放,no current context,是否因為回調發生在廣告視訊的Activity中,而此時Unity的Activity被掛起造成了渲染失敗呢?

於是想出了一個解決辦法:

RewardBasedVideoAd.Instance.OnAdRewarded += HandleOnAdRewarded;
private void HandleAdRewarded(object sender, Reward reward)
{
    reward = true
; } void OnApplicationPause(bool pauseStatus) { if (!pauseStatus && reward) { // do reward reward = false; } }

果然,在這種先標記然後等待Unity的OnApplicationPause訊息去呼叫的情況下,回撥會在廣告播放完畢UnityActivity變為活動狀態時執行,崩潰重啟的情況沒有再出現。

但是問題又來了,在iOS中並不是Activity這種機制,廣告播放時遊戲並不會暫停,也就不會出現OnApplicationPause訊息。解決方案很簡單,將回調放到Update裡去執行即可。

另外,需要監聽的訊息並不是只有這一個。在簡單優化後,程式碼如下

private Queue<Action> callbackQueue = new Queue<Action>();

private void HandleAdRewarded(object sender, Reward reward)
{
    callbackQueue.Enqueue(delegate { Debug.Log("rewarded"); });
}
private void HandleAdClosed(object sender, EventArgs args)
{
    callbackQueue.Enqueue(delegate { Debug.Log("closed"); });
}

void Update()
{
    while (callbackQueue.Count > 0)
    {
        callbackQueue.Dequeue().Invoke();
    }
}

這樣就能避免在Android上的崩潰,同時在iOS下也能保證獎勵回撥成功。

PS:雖然有人指出call to OpenGL ES API with no current context (logged once per thread)造成崩潰的情況應該算是OpenGL的Bug,但是作為Unity的SDK,AdMob for Unity的回撥並不在Unity的Activity中,這也實在是不太合理。

相關推薦

AdMob在Android造成崩潰處理方式

遊戲開發總是要接入各種各樣的SDK,廣告也成了一種常用的變現方式。而AdMob對於遊戲開發的老鳥來說一定不會陌生。 AdMob for Unity RewardBasedVideoAd.Instance.OnAdFailedToLoad; RewardBa

C語言學習及應用筆記之七:C語言函式及使用方式

  我們在使用C語言實現相對複雜的軟體開發時,經常會碰到使用回撥函式的問題。但是回撥函式的理解和使用卻不是一件簡單的事,在本篇我們根據我們個人的理解和應用經驗對回撥函式做簡要的分析。 1、什麼是回撥函式   既然談到了回撥函式,首先我們就要搞清楚什麼是回撥函式。在討論回撥函式之前,我們需要說明另一個概念,

Kafka consumer在項目的多線程處理方式

-m all ade exec 線程處理 rop while log 安全 對於KafkaConsumer而言,它不像KafkaProducer,不是線程安全的,狀態是在consumer中維護的,所以實現時要註意多線程的使用,一般有2種使用方法: 1:每個Consume

JS函式(一)

一.前奏 多用在使用 js 寫元件時,尤其是元件的事件很多都需要回調函式的支援 假設   A是回撥函式,B是呼叫者,B引數裡一個是指向A的函式指標,即回撥A,同時另外的引數傳遞給A作為引數 二.JS中函式可作為引數傳遞,甚至在另一個函式內部返回 一旦作為引數

機器學習不平衡資料的處理方式

https://blog.csdn.net/pipisorry/article/details/78091626 不平衡資料的場景出現在網際網路應用的方方面面,如搜尋引擎的點選預測(點選的網頁往往佔據很小的比例),電子商務領域的商品推薦(推薦的商品被購買的比例很低),信用卡欺詐檢測,網路攻擊識別

前端全棧工程化開發專題 — JS函式的深入解讀

1、回撥函式核心原理分析 js中的定時器及動畫 完整版動畫庫封裝 回撥函式初步講解 擴充套件更多的運動方式(非勻速) options物件引數的應用 ... 什麼是回撥函式? 把一個函式當做實參值傳遞給函式的形參變數(或者傳遞給函式,通過函式arguments獲取),在另外一個函

python Scrapy的spider函式的引數傳遞方法

通常有兩種方法,一種是使用meta進行引數傳遞。另一種是使用lambda進行引數傳遞。 方法一: 使用meta進行引數傳遞。 舉例如下: from scrapy.spiders import S

C# 安全的非同步處理的封裝

 在視窗 load 裡呼叫 AsyncTask.InitUIContext(); 初始化同步上下文 SwitchToUI  可以在多執行緒裡切換到UI執行緒執行委託程式碼 AsyncSend  以阻塞模式執行回撥 AsyncPost  以非阻塞模式執行回撥

對js函式的理解

一、什麼是回撥函式 一直接觸回撥函式這個名詞,但是不知道具體是幹什麼的,今天在百度上看到了一句話讓對回撥函式產生了一點興趣,那就是回撥函式的英文解釋: A callback is a function that is passed as an argument to an

Spring異常的統一的處理方式

在具體的SSM專案開發中,由於Controller層為處於請求處理的最頂層,再往上就是框架程式碼的。 因此,肯定需要在Controller捕獲所有異常,並且做適當處理,返回給前端一個友好的錯誤碼。 不過,Controller一多,我們發現每個Controller裡都有大量重複的、冗餘的異常處

android.database.ContentObserver#onChange(boolean, android.net.Uri) 多次的妥協處理方案

android.database.ContentObserver#onChange(boolean, android.net.Uri) 在呼叫資料庫監聽的方法的時候發現,該方法會被多次觸發。比如,只是

關於對Java函式的理解

先來看幾段程式: 1.  首先定義一個類Caller,這個類裡面儲存一個介面引用。        public class Caller {     private MyCallInter

Android 呼叫系統相機後的處理

宣告一個路徑: protected static String tempFileDic = Environment.getExternalStorageDirectory() + File.separator + Constant.PROJECT_

詳解Android機制與RecyclerView的Item點選事件實現

總是看書上寫著回調回調,以為就是函式呼叫換了個名字,尤其是看了Button的點選事件實現後,覺得不就是觸發機制。 A事件發生->後臺處理邏輯->告訴前臺怎麼做->結束。 Android常見button點選事件: loginB

python的multiprocessing在map函式的加鎖lock處理方式

def send_request(data): api_url = 'http://api.xxxx.com/?data=%s' start_time = clock() print urllib2.urlopen(api_url % data).read() end_time = clock()

面試多執行緒併發處理方式

1.首先我們要搞清楚什麼是併發 什麼是並行?概念:在單CPU系統中,系統排程在某一時刻只能讓一個執行緒執行,雖然這種除錯機制有多種形式(大多數是時間片輪巡為主),但無論如何,要通過不斷切換需要執行的執行緒讓其執行的方式就叫併發(concurrent)。而在多CPU系統中,可以

Glide使用過程遇到timeout異常的處理方式

在使用glide的使用過程中,當網路不好或是服務端反應不給力的時候,會經常丟擲timeout異常,通過fiddler抓包來看,其實圖片是會獲取到的。但是比較慢。 然後就想到像httpclient和httpurlconnect的使用那樣,為glide的設定超時時間,不過並沒有找到api。 記得

Android ndk jnijava的方法&欄位描述符

一、jobject和jclass 1.如果定義native方法時使用了static關鍵字,那麼生成的標頭檔案裡就會傳入jclass,代表這個類的引用。 2.如果沒有使用static關鍵字,那麼就會傳入jobject,代表類的物件的引用。 二、jni回撥

Ajax值為當前HTML頁面程式碼問題

問題: 在寫一個三級聯動的時候, 通過非同步獲取對應城市資訊,在點選select時觸發click事件把當前select值傳遞過去。 在success(data)回撥裡console.log(data)一直為當前HTML頁面程式碼 原因: URL傳遞路徑沒有寫對,直接

Angular4函式內資料繫結無法及時更新

解決辦法:1. 匯入 ChangeDetectorRef :import { ChangeDetectorRef } from '@angular/core'; constructor( private changeDetectorRef: ChangeDetectorR