I'm working on an Android game and I want to add AdMob ads to my game. I have added Banner and interstitial Views but the problem in RewardBasedVideoAd specifically on OnAdRewarded event, when the user closes the video return to the game to earn his reward game crash immediately.
After many tries, I found the code which crashes the game, gameObject.SetActive(true) And gameObject.SetActive(false), is the problem, when I deactivate game panel UI and active reward panel UI game crash immediately.
How can I solve it? why game crash when I use gameObject.SetActive ?
code which make app crashed
public void HandleOnAdRewarded(object sender, EventArgs args)
{
gamePanel.SetActive(false);
rewardPanel.SetActive(true);
}
request reward code
public void RequestReward()
{
AdRequest request = new AdRequest().Builder().Build();
this.rewardAd.LoadAd(request, rewardAdId);
rewardAd.OnAdLoaded += this.HandleOnRewardAdLoaded;
rewardAd.OnAdRewarded += this.HandleOnAdRewarded;
rewardAd.OnAdClosed += this.HandleOnRewardAdClosed;
}
handlers
public void HandleOnRewardAdLoaded(object sender, EventArgs args)
{
if(rewardAd.IsLoaded())
{
rewardAd.Show();
}
}
public void HandleOnAdRewarded(object sender, EventArgs args)
{
gamePanel.SetActive(false);
rewardPanel.SetActive(true);
}
public HandleOnRewardAdClosed(object sender, EventArgs args)
{
rewardAd.OnAdLoaded -= this.HandleOnRewardAdLoaded;
rewardAd.OnAdRewarded -= this.HandleOnAdRewarded;
rewardAd.OnAdClosed -= this.HandleOnRewardAdClosed;
}
for anyone has this issue
the cause of the problem is TextMesh Pro package
JUST UNINSTALL IT.
I had the same issue and in my case i was changing UI and sending requests to server after OnAdClosed and OnRewardEarned and so the crash happens when i close the ad.
I think that the reason is that these changes actually apply before coming back to the app and in that time the app is Paused. So i fixed it by using bool to know that if OnAdClosed and OnRewardEarned are called that then change UI and send requests in OnApplicationPause function like the code below.
Note: I send analytics events in OnAdClosed and OnRewardEarned and they work fine without any problem or crash.
private void OnApplicationPause(bool isPaused)
{
if (!isPaused)
{
if (_isRewardEarned)
{
_onEarnedRewardEvent?.Invoke();
}
if (_isRewardedAdClosed)
{
_onRewardedAdClosedEvent?.Invoke();
InitializeNextRewardedAd();
}
}
}
Related
I'm facing a issue in an app I'm developing that someone may be able to help me with.
I'm working on an app for payment machines that use Android (7.1), with it you are able to pay with credit card. The company that developed these machines offer a java sdk. Since this app is using React Native, I wrote a Native Module to connect with it. The SDK is really simple.
After the app is authenticated (done just once), All I have to do is call the doAsyncPayment method with the right parameters, and once its done, it will call the onSuccess or onError method of the listener.
When either of these methods is called, I call the callback parameter I got from the React Native side. In theory it's supposed to work, and it does, most of the time. Every once in a while, something happens that these callbacks are not called, so the client stays on the loading payment screen forever. No error is reported on sentry.
The only thing I'm thinking is that somehow the bridge is losing it? Maybe because these method runs asyncronously in the native side (another thread?), the connection is maybe lost?
I haven't been able to reproduce it, because it happens rarely and at random (I suppose).
I don't know much of Native Android, so any help is appreciated.
Here is a resumed piece of code of what's happening:
Native method being called:
#ReactMethod
public void startPayment(...other params,
Callback onErrorCallback, Callback onSuccessCallback) {
setPlugPag();
PlugPagPaymentData paymentData = new PlugPagPaymentData(paymentType, amountCents,
installmentType, installments, userReference, printReceipt);
PlugPagInitializationResult initResult = plugPag.initializeAndActivatePinpad(new
PlugPagActivationData(activationCode));
if(initResult.getResult() == PlugPag.RET_OK) {
plugPag.doAsyncPayment(paymentData, new PlugPagPaymentListener() {
PlugPagPrintResult printResult;
#Override
public void onSuccess(#NonNull PlugPagTransactionResult plugPagTransactionResult) {
if(printResult != null) {
WritableMap printResultMap = Arguments.createMap();
printResultMap.putInt("result", printResult.getResult());
printResultMap.putString("message", printResult.getMessage());
printResultMap.putString("errorCode", printResult.getErrorCode());
onSuccessCallback.invoke(TransactionResult.toRNWritableMap(plugPagTransactionResult), printResultMap);
}else {
onSuccessCallback.invoke(TransactionResult.toRNWritableMap(plugPagTransactionResult));
}
}
#Override
public void onError(#NonNull PlugPagTransactionResult plugPagTransactionResult) {
onErrorCallback.invoke(TransactionResult.toRNWritableMap(plugPagTransactionResult));
}
#Override
public void onPaymentProgress(#NonNull PlugPagEventData plugPagEventData) {
WritableMap eventDataMap = Arguments.createMap();
eventDataMap.putString("customMessage", plugPagEventData.getCustomMessage());
eventDataMap.putInt("eventCode", plugPagEventData.getEventCode());
sendEvent(Constants.EVENT_PLUG_PAG_PAYMENT_PROGRESS_CHANGED, eventDataMap);
}
#Override
public void onPrinterSuccess(#NonNull PlugPagPrintResult plugPagPrintResult) {
}
#Override
public void onPrinterError(#NonNull PlugPagPrintResult plugPagPrintResult) {
}
});
}else {
onErrorCallback.invoke(String.valueOf(initResult.getResult()));
}
}
on React native side, I just call:
startPayment(...other params, errorCallback, successCallback);
Maybe because the way the listener is instantiated?
Thanks in advance.
Using the Rewarded ad script found on the Unity Ads SDK, I'm running into an issue where the ShowAd() IUnityAdsShowListener => OnUnityAdsShowComplete is firing the debug log incrementally. The first Ad I watch returns one line stating the ad is completed, the second Ad I watch, fires off 2 logs, the third 3, then 4, etc...As if each ShowAd() subscribes a new listener to the callback. is this normal?
Im not using a button to call the ShowAd method, rather I'm just calling a function with a delegate from an AdsManager class.
public delegate void OnSuccessfulAd();
private OnSuccessfulAd _myCallback = null;
public void ShowAd(OnSuccessfulAd myMethod)
{
_myCallback = myMethod;
Advertisement.Show(_adUnitId, this);
}
public void OnUnityAdsShowComplete(string adUnitId, UnityAdsShowCompletionState showCompletionState)
{
if (adUnitId.Equals(_adUnitId) && showCompletionState.Equals(UnityAdsShowCompletionState.COMPLETED))
{
Debug.Log("Unity Ads Rewarded Ad Completed"); //Gets called more times each ad
// Grant a reward.
_myCallback?.Invoke();
}
}
Experiencing the same issue. As a temporary solution I nullify _myCallback after invoking it
I am working on the Ads 4.0.0 version in Unity.
What I observed even for Button Click is that its giving multiple Logs in Unity Editor.
However if I run the Code in my mobile Build its working as expected only 1 Log gets generated and Reward also remains same on multiple ad watches.
The issues seems to be in the CallBack in unity, My suggestion would be Try the Build in your App Once Hopefully that fixes the issue.
Unity Rewarded Ads Code from Official Page
As Unity has Deprecated most of the Previous Listeners in the New Ads 4.0.0 I think its better to cross check in the Build.
I was facing the exact same issue.
My OnUnityAdsShowComplete event callback is invoking one of my delegate.
Every references in my delegate was not accessible.
Look like the OnUnityAdsShowComplete is done on a different thread than the main one.
If in your delegate callback you have a simple Time.timeScale=1f, this should cause a crash since Time is no reachable.
Also this has observable only with reward Ads type.
My solution was to call the show() method inside a coroutine.
By having a flag set i.e. isAdRunning
You can poll that flag and when the flag is false isAdRunnin = false then you can call your delegate.
Very annoying.
Here an example. To make the code the simpliest as possible. All the IUnityAds interfaces are in the same class. This is why you will see this as listener arguments.
using UnityEngine.Advertisements;
private bool isAdsRunning = false;
// Ads start callback
public void OnUnityAdsShowStart(string placementId)
{
isAdsRunning = true;
}
// Ads complete callback
public void OnUnityAdsShowComplete(string placementId, UnityAdsShowCompletionState showCompletionState)
{
isAdsRunning = false;
}
// Entry point to show reward ads
public void ShowRewardedAd()
{
StartCoroutine(RewardRoutine());
}
IEnumerator RewardRoutine()
{
while (Advertisement.isShowing)
{
yield return null;
}
// In 4.0 Ads need to be loaded first, after initialization
// just another flag to make sure everything is initialized :)
while (!isAdLoaded)
{
yield return null;
}
// Show Ads
Advertisement.Show(adsUnitIdReward, this);
yield return new WaitForSeconds(0.25f);
while(isAdsRunning)
{
yield return null;
}
// My custom delegate
AdAction.Invoke();
}
Peace and Love.
I'm attempting to create a xamarin forms application which will get location updates and feed them to an HTTP endpoint. I'm having a great deal of difficulty understanding how to go about running a service in the background so that I continue to receive location information regardless of if the application is open or not especially in face of the change in API level 26 https://developer.android.com/about/versions/oreo/background.html.
I was using a LocationCallback when the application was in the foreground and that seemed to work okay but I'm wondering if just waking up from time to time and looking at GetLastLocationAsync or if that information is only updated when something actively requests location information.
What's the best way to implement a background service which will feed device location to an endpoint regardless of if the application is in the foreground?
I achieved it by registering another service and subscribed to location updates from within it.
using Xamarin.Essentials;
public class Service
{
private IService service { get; }
public Service(IService service)
{
this.service = service;
}
public async Task StartListening()
{
if (CrossGeolocator.Current.IsListening)
return;
await CrossGeolocator.Current.StartListeningAsync(TimeSpan.FromSeconds(5), 10, true);
CrossGeolocator.Current.PositionChanged += PositionChanged;
CrossGeolocator.Current.PositionError += PositionError;
}
private void PositionChanged(object sender, PositionEventArgs e)
{
service.UpdateLocation(e.Position.Latitude, e.Position.Longitude);
}
private void PositionError(object sender, PositionErrorEventArgs e)
{
//Handle event here for errors
}
public async Task StopListening()
{
if (!CrossGeolocator.Current.IsListening)
return;
await CrossGeolocator.Current.StopListeningAsync();
CrossGeolocator.Current.PositionChanged -= PositionChanged;
CrossGeolocator.Current.PositionError -= PositionError;
}
}
}
I explored mobileCore a month ago and decided to use today. But I couldnt integrate.
My Code for İntegrate Stickeez Ad Type:
MobileCore.init(MainActivity.this, "4U5PUKTA688XO2HBFI8O2SPYVVJ47",
MobileCore.LOG_TYPE.PRODUCTION,MobileCore.AD_UNITS.INTERSTITIAL, MobileCore.AD_UNITS.STICKEEZ);
MobileCore.showStickee(MainActivity.this, MobileCore.AD_UNIT_TRIGGER.APP_START);
I dont know why showStickee but it isnt wrong. How can I fix it?
It seems that you're trying to show the ad unit before it is ready. We recommend to use the Ad Unit Event Listener to confirm that the ad unit is ready before calling showStickee(), or at least to not call it together with MobileCore.Init().
Also, if you're using the latest version (v2.0), note that we've added a new loadAdUnit() method that requires to manually fetch the ads before displaying.
Here's an example using Android SDK v2.0:
First, In the onCreate() method of your main activity, Init the SDK:
MobileCore.init(MainActivity.this, *YOUR_DEVELOPER_HASH_HERE*,
MobileCore.LOG_TYPE.PRODUCTION,MobileCore.AD_UNITS.INTERSTITIAL, MobileCore.AD_UNITS.STICKEEZ);
Now here's an example code that loads the ad unit after Init has finished and then displays the ad upon receiving AD_UNIT_READY event:
MobileCore.setAdUnitEventListener(new AdUnitEventListener() {
#Override
public void onAdUnitEvent(MobileCore.AD_UNITS adUnit, EVENT_TYPE eventType,
MobileCore.AD_UNIT_TRIGGER... trigger) {
if (adUnit == MobileCore.AD_UNITS.STICKEEZ) {
if (eventType == EVENT_TYPE.AD_UNIT_INIT_SUCCEEDED) {
MobileCore.loadAdUnit(MobileCore.AD_UNITS.STICKEEZ, MobileCore.AD_UNIT_TRIGGER.APP_START);
}
else if (eventType == AdUnitEventListener.EVENT_TYPE.AD_UNIT_READY) {
for (MobileCore.AD_UNIT_TRIGGER myTrigger : trigger) {
if (myTrigger.equals(MobileCore.AD_UNIT_TRIGGER.APP_START)) {
MobileCore.showStickee(MainActivity.this,
MobileCore.AD_UNIT_TRIGGER.APP_START);
}
}
}
}
}
});
Feel free to contact us at support#mobilecore.com with any question.
I want to make Radio Web App Android-browser-based.
The key function for my Web App is continuously playing music-list
(mp3 files) ...
JavaScript Code is simple ...
And it works well in PC Browser, iOS safari, and Android Dolphin
Browser (3rd party browser)...
var audioPlayer = new Audio();
audioPlayer.addEventListener('ended', nextSong, false);
function nextSong() {
audioPlayer.src = nextMusic_src;
}
But. in Android Default Browser,
when android is in background mode (Home Screen mode & LCD-off Sleep
mode),
Android Browser's onPause() prevent "ended" event & execution of
nextSong().
So, my web app can play only one music.... and does not work any
more.....
Android Browser's onPause() source code is like this ...
BrowserActivity.java
public class BrowserActivity extends Activity
{
private Controller mController;
// ...
#Override
protected void onPause() {
if (mController != null) {
mController.onPause(); // <<==== here
}
super.onPause();
}
}
Controller.java
public class Controller implements WebViewController, UiController {
protected void onPause() {
// ...
mActivityPaused = true;
// ...
mUi.onPause();
mNetworkHandler.onPause(); // <<==== here
WebView.disablePlatformNotifications(); // <<====here
}
}
NetworkStateHandler.java
public class NetworkStateHandler {
// ...
void onPause() {
// unregister network state listener
mActivity.unregisterReceiver(mNetworkStateIntentReceiver); // <<==== here
}
}
Is there any browser policy for preventing event in background
mode....?
If not, how can I notice this report to the Google developer for
requesting background music play with web app...?
I consider not WebView based web-app (Hybrid) but only browser-based
web-app...
thank you...
Nohyun Kwak
Droid's ended event doesn't fire consistently. It's fixed in ICS, I hear. But Gingerbread and prior have the issue.
Instead of listening for .ended, can you listen for .timeupdate and in that handler, see if the time is the end of the song? That may solve your issue.