kmcgill88 / admob_flutter

Admob Flutter plugin that shows banner ads using native platform views.
https://pub.dartlang.org/packages/admob_flutter
ISC License
434 stars 151 forks source link

Rewarded ads not showing #221

Open shinayser opened 4 years ago

shinayser commented 4 years ago

Hello!

The banners are working fine, but the rewarded, not showing up. This is my test code:

AdmobReward rewardAd = AdmobReward(
                        adUnitId: testRewardedId,
                        listener: (event, args) {
                          print('GOT EVENT $event com args: $args');
                        },
                      );
                      rewardAd.load();

                      if (await rewardAd.isLoaded) {
                        rewardAd.show();
                      }
                    },

My Log:

I/Ads     (21483): This request is sent from a test device.
I/AudioManager(21483): In isSpeakerphoneOn(), calling application: com.shinayser.tapthefab.app
I/ExoPlayerImpl(21483): Init ExoPlayerLib/2.4.2 [montana_n, Moto G (5S), motorola, 27]
D/MetadataUtil(21483): Skipped unknown metadata entry: gsst
D/MetadataUtil(21483): Skipped unknown metadata entry: gstd
W/VideoCapabilities(21483): Unrecognized profile 2130706433 for video/avc
W/VideoCapabilities(21483): Unrecognized profile 2130706434 for video/avc
W/VideoCapabilities(21483): Unrecognized profile 2130706433 for video/avc
W/VideoCapabilities(21483): Unrecognized profile 2130706434 for video/avc
W/VideoCapabilities(21483): Unrecognized profile 2130706433 for video/avc
W/VideoCapabilities(21483): Unrecognized profile 2130706434 for video/avc
I/VideoCapabilities(21483): Unsupported profile 4 for video/mp4v-es
W/VideoCapabilities(21483): Unrecognized profile 2130706433 for video/avc
W/VideoCapabilities(21483): Unrecognized profile 2130706434 for video/avc
I/MediaCodec(21483): name=OMX.google.aac.decoder isType=false encoder=false
I/MediaCodec(21483): (0x7f273940) init name(OMX.google.aac.decoder) isType(0) encoder(0)
I/OMXClient(21483): Treble IOmx obtained
I/MediaCodec(21483): (0x7f273940) Component Allocated (OMX.google.aac.decoder)
I/MediaCodec(21483): (0x7f273940) configure surface(0x0) crypto(0x0) flags(0)
D/MediaCodec(21483): (0x7f273940) configure format: AMessage(what = 0x00000000) = {
D/MediaCodec(21483):       int32_t sample-rate = 44100
D/MediaCodec(21483):       string mime = "audio/mp4a-latm"
D/MediaCodec(21483):       int32_t channel-count = 2
D/MediaCodec(21483):       string language = "und"
D/MediaCodec(21483):       int32_t max-input-size = 547
D/MediaCodec(21483):       Buffer csd-0 = {
D/MediaCodec(21483):         00000000:  12 10                                             ..
D/MediaCodec(21483):       }
D/MediaCodec(21483):     }
W/ExtendedACodec(21483): Failed to get extension for extradata parameter
I/MediaCodec(21483): (0x7f273940) start
I/MediaCodec(21483): (0x7f273940) kWhatStartCompleted
D/MediaCodec(21483): (0x7f273940) kWhatOutputBuffersChanged
D/MediaCodec(21483): (0x7f273940) [OMX.google.aac.decoder] output format changed to: AMessage(what = 0x00000000) = {
D/MediaCodec(21483):       string mime = "audio/raw"
D/MediaCodec(21483):       int32_t channel-count = 2
D/MediaCodec(21483):       int32_t sample-rate = 44100
D/MediaCodec(21483):       int32_t pcm-encoding = 2
D/MediaCodec(21483):     }
I/MediaCodec(21483): name=OMX.qcom.video.decoder.avc isType=false encoder=false
I/MediaCodec(21483): (0x7f274200) init name(OMX.qcom.video.decoder.avc) isType(0) encoder(0)
I/OMXClient(21483): Treble IOmx obtained
I/MediaCodec(21483): (0x7f274200) Component Allocated (OMX.qcom.video.decoder.avc)
I/MediaCodec(21483): (0x7f274200) configure surface(0x87cee000) crypto(0x0) flags(0)
D/MediaCodec(21483): (0x7f274200) configure format: AMessage(what = 0x00000000) = {
D/MediaCodec(21483):       Buffer csd-1 = {
D/MediaCodec(21483):         00000000:  00 00 00 01 68 eb af 20                           ....h.. 
D/MediaCodec(21483):       }
D/MediaCodec(21483):       int32_t max-height = 720
D/MediaCodec(21483):       int32_t max-width = 1280
D/MediaCodec(21483):       string mime = "video/avc"
D/MediaCodec(21483):       int32_t width = 1280
D/MediaCodec(21483):       int32_t max-input-size = 26389
D/MediaCodec(21483):       int32_t rotation-degrees = 0
D/MediaCodec(21483):       int32_t height = 720
D/MediaCodec(21483):       Buffer csd-0 = {
D/MediaCodec(21483):         00000000:  00 00 00 01 67 4d 40 1f  e8 80 28 02 dd 80 b5 01  ....gM@...(.....
D/MediaCodec(21483):         00000010:  01 01 40 00 00 fa 40 00  2e e0 03 c6 0c 44 80     ..@...@......D.
D/MediaCodec(21483):       }
D/MediaCodec(21483):     }
D/SurfaceUtils(21483): connecting to surface 0x87cee008, reason connectToSurface
I/MediaCodec(21483): [OMX.qcom.video.decoder.avc] setting surface generation to 21998593
D/SurfaceUtils(21483): disconnecting from surface 0x87cee008, reason connectToSurface(reconnect)
D/SurfaceUtils(21483): connecting to surface 0x87cee008, reason connectToSurface(reconnect)
I/ACodec  (21483): DRC Mode: Dynamic Buffer Mode
I/ExtendedACodec(21483): setupVideoDecoder()
I/ACodec  (21483): [OMX.qcom.video.decoder.avc] setupVideoDecoder Width Height (1280x720)
I/ACodec  (21483): mime (video/avc) compressionFormat (7)
I/ExtendedACodec(21483): Decoder will be in frame by frame mode
I/MediaCodec(21483): (0x7f274200) start
D/SurfaceUtils(21483): set up nativeWindow 0x87cee008 for 1280x720, color 0x7fa30c04, rotation 0, usage 0x20002900
I/MediaCodec(21483): (0x7f274200) kWhatStartCompleted
W/GrallocMapperPassthrough(21483): buffer descriptor with invalid usage bits 0x2000
I/chatty  (21483): uid=10454(com.shinayser.tapthefab.app) CodecLooper identical 3 lines
W/GrallocMapperPassthrough(21483): buffer descriptor with invalid usage bits 0x2000
D/SurfaceUtils(21483): set up nativeWindow 0x87cee008 for 1280x720, color 0x7fa30c04, rotation 0, usage 0x20002900
D/MediaCodec(21483): (0x7f274200) kWhatOutputBuffersChanged
D/MediaCodec(21483): (0x7f274200) [OMX.qcom.video.decoder.avc] output format changed to: AMessage(what = 0x00000000) = {
D/MediaCodec(21483):       int32_t color-range = 2
D/MediaCodec(21483):       int32_t color-standard = 1
D/MediaCodec(21483):       int32_t color-transfer = 3
D/MediaCodec(21483):       string mime = "video/raw"
D/MediaCodec(21483):       int32_t stride = 1280
D/MediaCodec(21483):       int32_t slice-height = 736
D/MediaCodec(21483):       int32_t color-format = 2141391876
D/MediaCodec(21483):       Rect crop(0, 0, 1279, 719)
D/MediaCodec(21483):       int32_t android._dataspace = 260
D/MediaCodec(21483):       Buffer hdr-static-info = {
D/MediaCodec(21483):         00000000:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
D/MediaCodec(21483):         00000010:  00 00 00 00 00 00 00 00  00                       .........
D/MediaCodec(21483):       }
D/MediaCodec(21483):       int32_t width = 1280
D/MediaCodec(21483):       int32_t height = 720
D/MediaCodec(21483):     }
D/AudioTrack(21483): Client defaulted notificationFrames to 4714 for frameCount 14144
W/AudioTrack(21483): Use of stream types is deprecated for operations other than volume control
W/AudioTrack(21483): See the documentation of AudioTrack() for what to use instead with android.media.AudioAttributes to qualify your playback use case
W/GrallocMapperPassthrough(21483): buffer descriptor with invalid usage bits 0x2000
I/DynamiteModule(21483): Considering local module com.google.android.gms.ads.dynamite:0 and remote module com.google.android.gms.ads.dynamite:22000
I/DynamiteModule(21483): Selected remote version of com.google.android.gms.ads.dynamite, version >= 22000
I/flutter (21483): GOT EVENT AdmobAdEvent.loaded com args: null

As you can see, the ads is being loaded up but not showing =( I am using admob_flutter: ^1.0.0-beta.7

ming-chu commented 4 years ago

Maybe related to iOS 14, did you add the UsageDescription?

<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>
shinayser commented 4 years ago

Nope, it's Android!

ming-chu commented 4 years ago

Nope, it's Android! @shinayser sorry about that.

I guess isLoaded is false here:

if (await rewardAd.isLoaded) {
    rewardAd.show();
}

I recommend you try to show the ad rewardAd.show(); in the listener instead of after check isLoaded immediately if you want to show after it loaded because the isLoaded computed variable seems not waiting for the ad finish it's fetching process.

class TestAds extends StatefulWidget {
  @override
  _TestAdsState createState() => _TestAdsState();
}

class _TestAdsState extends State<TestAds> {
  AdmobReward rewardAd;

  @override
  void initState() {
    rewardAd = AdmobReward(
      adUnitId: testRewardedId,
      listener: (event, args) {
        print('GOT EVENT $event com args: $args');
        if (event == AdmobAdEvent.loaded) {
          print('Ad Loaded!');
          rewardAd.show();
        }
      },
    );
    rewardAd.load();

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
shinayser commented 4 years ago

@ming-chu Jsut tried your solution and nope, it also doesnt work =(

ming-chu commented 4 years ago

@ming-chu Jsut tried your solution and nope, it also doesnt work =(

@shinayser Would you please post the code after you modified? Also, you may want to check the ad unit id used is for AdmobReward or not.

Ad format | Sample ad unit ID
Rewarded Video  | ca-app-pub-3940256099942544/5224354917

https://developers.google.com/admob/android/test-ads

Arie290698 commented 4 years ago

I'm also having the same problem. I've tried to use the test id from Google, but the ad is still not showing. I've changed the algorithm, it's still not showing.

ming-chu commented 4 years ago

I'm also having the same problem. I've tried to use the test id from Google, but the ad is still not showing. I've changed the algorithm, it's still not showing.

@Arie290698 Would you please provide the code that can reproduce the problem? That will be easier to check and discuss. :)

shinayser commented 4 years ago

Sorry for the late response. Here it goes:

Future<int> _showRewardedAlt() async {
  var completer = Completer<int>();

  AdmobReward rewardAd;
  rewardAd = AdmobReward(
    adUnitId: 'ca-app-pub-3940256099942544/5224354917',
    listener: (event, args) {
      print('EVENT ARGS $args');
      switch (event) {
        case AdmobAdEvent.rewarded:          
            completer.complete(args["rewardAmount"]);          
          break;

        case AdmobAdEvent.clicked:
        case AdmobAdEvent.impression:
        case AdmobAdEvent.opened:
        case AdmobAdEvent.started:
        case AdmobAdEvent.completed:
          print('New reward event: $event');
          break;

        case AdmobAdEvent.failedToLoad:
        case AdmobAdEvent.leftApplication:
        case AdmobAdEvent.closed:
          print('Rewarded event ERROR with $event');
          completer.completeError(event);
          break;

        case AdmobAdEvent.loaded:
          print('LOADED');
          rewardAd.show();
          break;
      }
    },
  );

  rewardAd.load();

  return completer.future;
}
ming-chu commented 4 years ago

Sorry for the late response. Here it goes:

Future<int> _showRewardedAlt() async {
  var completer = Completer<int>();

  AdmobReward rewardAd;
  rewardAd = AdmobReward(
    adUnitId: 'ca-app-pub-3940256099942544/5224354917',
    listener: (event, args) {
      print('EVENT ARGS $args');
      switch (event) {
        case AdmobAdEvent.rewarded:          
            completer.complete(args["rewardAmount"]);          
          break;

        case AdmobAdEvent.clicked:
        case AdmobAdEvent.impression:
        case AdmobAdEvent.opened:
        case AdmobAdEvent.started:
        case AdmobAdEvent.completed:
          print('New reward event: $event');
          break;

        case AdmobAdEvent.failedToLoad:
        case AdmobAdEvent.leftApplication:
        case AdmobAdEvent.closed:
          print('Rewarded event ERROR with $event');
          completer.completeError(event);
          break;

        case AdmobAdEvent.loaded:
          print('CARREGOU');
          rewardAd.show();
          break;
      }
    },
  );

  rewardAd.load();

  return completer.future;
}

@shinayser I guess the instance of AdmobReward does not exist after the function is finished before the ad loaded. you should define the variable AdmobReward rewardAd; outside the function

ming-chu commented 4 years ago

@shinayser I tried using a new project with the code below and it works. pubspec.yaml: admob_flutter: ^1.0.0-beta.7

import 'package:admob_flutter/admob_flutter.dart';
import 'package:flutter/material.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Admob.initialize();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  AdmobReward rewardAd;

  @override
  void initState() {
    rewardAd = AdmobReward(
      adUnitId: 'ca-app-pub-3940256099942544/5224354917',
      listener: (event, args) {
        print('GOT EVENT $event, args: $args');
        if (event == AdmobAdEvent.loaded) {
          print('Ad Loaded!');
          rewardAd.show();
        } else if (event == AdmobAdEvent.closed) {
          rewardAd.load();
        }
      },
    );
    rewardAd.load();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Demo the AdmobReward'),
            RaisedButton(
              child: Text('Show Ad!'),
              onPressed: () {
                print('Show ad by clicking button!');
                rewardAd.isLoaded.then((isLoaded) {
                  print('isLoaded: $isLoaded');
                  if (isLoaded) {
                    rewardAd.show();
                  }
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}
shinayser commented 4 years ago

@shinayser I guess the instance of AdmobReward does not exist after the function is finished before the ad loaded. you should define the variable AdmobReward rewardAd; outside the function

This is not true. The variable exists, otherwise it would throw a null pointer exception. The purpose of my function is to provide a streaightfoward way to show and ad and get its result in a single call.

ming-chu commented 4 years ago

@shinayser I tried your code, but the listener of AdmobReward never called. What I guess is the instant was destroyed before the listener is called.

shinayser commented 4 years ago

@ming-chu There isn't much difference from the code you posted. You doign almost the same thing as I, except that I am doing it via future Completer. Perhaps it is another bug on the library?

ming-chu commented 4 years ago

@shinayser I guess the instance of AdmobReward does not exist after the function is finished before the ad loaded. you should define the variable AdmobReward rewardAd; outside the function

This is not true. The variable exists, otherwise it would throw a null pointer exception. The purpose of my function is to provide a streaightfoward way to show and ad and get its result in a single call.

@shinayser You are right!

After some tests, I suspect that is the problem at the listener, I move the listener out and it works. please try the code below.

  Future<int> _showRewardedAlt() async {
    var completer = Completer<int>();

    AdmobReward rewardAd;

    void listener(AdmobAdEvent event, Map<String, dynamic> args) {
      print('>>>>EVENT ARGS $args');
      switch (event) {
        case AdmobAdEvent.rewarded:
          completer.complete(args["rewardAmount"]);
          break;

        case AdmobAdEvent.clicked:
        case AdmobAdEvent.impression:
        case AdmobAdEvent.opened:
        case AdmobAdEvent.started:
        case AdmobAdEvent.completed:
          print('New reward event: $event');
          break;

        case AdmobAdEvent.failedToLoad:
        case AdmobAdEvent.leftApplication:
        case AdmobAdEvent.closed:
          print('Rewarded event ERROR with $event');
          completer.completeError(event);
          break;

        case AdmobAdEvent.loaded:
          print('CARREGOU');
          rewardAd.show();
          break;
      }
    }

    rewardAd = AdmobReward(
      adUnitId: 'ca-app-pub-3940256099942544/5224354917',
      listener: listener,
    );

    rewardAd.load();
    return completer.future;
  }
shinayser commented 4 years ago

void listener(AdmobAdEvent event, Map<String, dynamic> args) {

I tried exactly your code and my rewarded ads don't show up =(

Arie290698 commented 4 years ago

@Arie290698 Would you please provide the code that can reproduce the problem? That will be easier to check and discuss. :)

It's okay. I've solved the problem.

ming-chu commented 4 years ago

@shinayser That's so weird, I try to use your original code and it works too. What I did is just stop the app and start, don't use hot reload / hot restart. Hope this can help.

shinayser commented 4 years ago

@Arie290698 Would you please provide the code that can reproduce the problem? That will be easier to check and discuss. :)

It's okay. I've solved the problem.

Can you share your solution?

Arie290698 commented 4 years ago

@shinayser Add this to initState ()

rewardAd = AdmobReward (
       adUnitId: rewardId,
       listener: (AdmobAdEvent event, Map <String, dynamic> args) {
         if (event == AdmobAdEvent.rewarded) {
           rewardAd.load ();
         }
         if (event == AdmobAdEvent.closed) {
           rewardAd.load ();
         }
       },
     );
loadReward();

Then add a new function loadReward()

loadReward() async{
    if(await rewardAd.isLoaded == false){
      rewardAd.load();
    }
  }

Then add this code to onClick on the button as the trigger

if(await rewardAd.isLoaded == true){
      rewardAd.show();
}else{
//do something if reward not loaded
}

Run flutter clean and try rebuilding your app

Arie290698 commented 4 years ago

If it's still not loading, try using your app's app_id and unit_id. But don't forget to add Admob.initialize (testDeviceIds: ['test_device']); Because when I try to use Google's app_id and unit_id, the ad doesn't show.

ming-chu commented 4 years ago

@shinayser This is my little testing app, it works with your code perfectly. demo2

https://github.com/ming-chu/admob-flutter-reward-test https://github.com/ming-chu/admob-flutter-reward-test/blob/master/lib/main.dart

mehmetyilmaz001 commented 3 years ago

I also faced this problem too. Listener is not firing and ad is not showing.

it-one-mm commented 3 years ago

Don't use admob_flutter. Just use firebase_admob, and it is reliable.

doonfrs commented 3 years ago

The listener function was not being called,


  static Future<bool> showRewardVideo({String adType = 'Reward'}) {
    Completer<bool> completer = Completer<bool>();

    var rewarded = false;

    rewardAd = AdmobReward(
      adUnitId: getRewardBasedVideoAdUnitId(),
      listener: (AdmobAdEvent event, Map<String, dynamic> args) {
        if (event == AdmobAdEvent.closed) {}
        switch (event) {
          case AdmobAdEvent.loaded:
            print('New Admob $adType Ad loaded!');
            rewardAd.show();

            break;
          case AdmobAdEvent.opened:
            print('Admob $adType Ad opened!');
            break;
          case AdmobAdEvent.closed:
            print('Admob $adType Ad closed!');
            if (rewarded) {
              completer.complete(true);
            } else {
              completer.complete(false);
            }
            rewardAd.dispose();
            break;
          case AdmobAdEvent.failedToLoad:
            print('Admob $adType failed to load. :(');
            completer.completeError(false);
            rewardAd.dispose();
            break;
          case AdmobAdEvent.rewarded:
            print('!!!!rewarded');
            rewarded = true;
            break;
          default:
        }
      },
    );

    rewardAd.load();

    return completer.future;
  }

    AdsHelper.showRewardVideo().then((value)  {
      if (!value) {
        // no reward
        return;
      }

      //Rewarded... 
    }).catchError((error) {
      //error loading or showing video
    });

for purpose of the test, use AdmobReward.testAdUnitId to make sure it is not an AdMob setup issue.

amirVirtuenetz commented 2 years ago

where can I call this function? onPress or initState method?