Displaying video ads in a row with admob on flutter - firebase

Im interested if there is a way to display more than one RewardVideoAd in a row. Before opening one videoAd it must be loaded, so I tried to load another videoAd when other is opened, so that way when the videoAd is closed/rewarded/completed it shows the new one. But it isn't working here is the code I have tried.
(RewardedVideoAdEvent event, {String rewardType, int rewardAmount}) {
print("RewardedVideoAd event $event");
if (event == RewardedVideoAdEvent.opened) {
setState(() {
RewardedVideoAd.instance.load(
adUnitId: RewardedVideoAd.testAdUnitId,
targetingInfo: targetingInfo);
});
} else if (event == RewardedVideoAdEvent.closed ||
event == RewardedVideoAdEvent.completed ||
event == RewardedVideoAdEvent.rewarded ||
event == RewardedVideoAdEvent.failedToLoad) {
setState(() {
_coins += rewardAmount;
RewardedVideoAd.instance.show();
});
}
};
..and the buttons from where the first ad is started.
RaisedButton(
child: const Text('LOAD REWARDED VIDEO'),
onPressed: () {
RewardedVideoAd.instance.load(
adUnitId: RewardedVideoAd.testAdUnitId,
targetingInfo: targetingInfo);
},
),
RaisedButton(
child: const Text('SHOW REWARDED VIDEO'),
onPressed: () {
RewardedVideoAd.instance.show();
},
),
I wonder if there is a way to show 2 or 3 rewardVideoAds in a row, one after another. Thanks!

Related

How to send flutter search to Firebase Analytics event

Is there a way to catch only the final search to send in Firebase Analytics event?
_searchPressed() {
final FirebaseAnalytics analytics = FirebaseAnalytics.instance;
setState(() {
if (this._searchIcon.icon == Icons.search) {
this._searchIcon = new Icon(Icons.close);
this._appBarTitle = TextField(
decoration: new InputDecoration(
prefixIcon: new Icon(Icons.search),
),
onChanged: (text) {
text = text.toLowerCase();
setState(() {
_itemForDisplay = _item.where((item) {
var itemTitle = item.code.toLowerCase();
return itemTitle.contains(text);
}).toList();
if (text.length > 6) {
analytics.logEvent(
name: text.replaceAll(' ', ''),
parameters: {'term': text.replaceAll(' ', ''), 'vaule': 1});
//space not allowed in firebase
}
});
},
);
} else {
this._searchIcon = new Icon(Icons.search);
this._appBarTitle = new Text( 'Search bar' );
analytics.logEvent(
name: 'search_done',
parameters: {'term': "close", 'vaule': 1});
_itemForDisplay = _item;
}
});
}
A satisfactory solution is to capture the search when closing search is selected. The search is done simultaneously so there is no information when the search is completed. The only information about the end of the search is when you touch the close icon. Another option would be the longest search text.

Flutter: How to remove awaits to take advantage of Firebase Offline Persistence?

I'm using a drop-down list (DropDown), whose elements are obtained from Firebase. The form works right, however when the internet connection is lost the Firebase Offline Persistence property doesn't work and the CircularProgressIndicator stays active. Reading some responses such as Using Offline Persistence in Firestore in a Flutter App, it is indicated that awaits should not be handled, however it is not clear to me how to achieve it:
class EstanqueAlimentarPage extends StatefulWidget {
#override
_EstanqueAlimentarPageState createState() => _EstanqueAlimentarPageState();
}
class _EstanqueAlimentarPageState extends State<EstanqueAlimentarPage> {
final formKey = GlobalKey<FormState>();
AlimentoBloc alimentoBloc = new AlimentoBloc();
AlimentoModel _alimento = new AlimentoModel();
AlimentarModel alimentar = new AlimentarModel();
List<AlimentoModel> _alimentoList;
bool _alimentoDisponible = true;
#override
void dispose() {
alimentoBloc.dispose();
super.dispose();
}
#override
void initState() {
_obtenerListaAlimentoUnaVez();
super.initState();
}
Future<void> _obtenerListaAlimentoUnaVez() async {
_alimentoList = await alimentoBloc.cargarAlimento(idEmpresa); // Await that I want to eliminate
if (_alimentoList.length > 0) { // Here appears a BAD STATE error when the internet connection goes from off to on
_alimento = _alimentoList[0];
_alimentoDisponible = true;
} else {
_alimentoDisponible = false;
}
_cargando = false;
setState(() {});
}
#override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Column(
children: <Widget> [
_crearTipoAlimento(_alimentoList),
SizedBox(height: 8.0),
_crearComentarios(),
]
)
),
_crearBoton('Guardar'),
}
Widget _crearTipoAlimento(List<AlimentoModel> lista) {
return Container(
decoration: _cajaBlanca,
child:
!_cargando // If it isn't loading, Dropdown must be displayed
? DropdownButtonFormField<AlimentoModel>(
decoration: InputDecoration(
labelText: 'Nombre del Alimento',
contentPadding: EdgeInsets.only(top:5.0),
prefixIcon: Icon(FontAwesomeIcons.boxOpen, color: Theme.of(context).primaryColor,),
border: InputBorder.none,
),
value: _alimento,
items: lista.map((AlimentoModel value) {
return DropdownMenuItem<AlimentoModel>(
child: Text(value.nombre),
value: value,
);
}).toList(),
onChanged: (_alimentoDisponible) ? (AlimentoModel _alimentoSeleccionado) {
print(_alimentoSeleccionado.nombre);
_alimento = _alimentoSeleccionado;
setState(() {});
} : null,
disabledHint: Text('No hay Alimento en Bodega'),
onSaved: (value) {
alimentar.idAlimento = _alimento.idAlimento;
alimentar.nombreAlimento = _alimento.nombreRef;
}
)
: Center (child: CircularProgressIndicator(strokeWidth: 1.0,))
);
}
Widget _crearComentarios() {
return TextFormField(
// -- DESIGN OTHER FIELDS -- //
onSaved: (value) {
alimentar.comentarios = value;
}
),
);
}
Widget _crearBoton(String texto) {
return RaisedButton(
// -- DESIGN -- //
onPressed: (_guardando) ? null : _submit,
),
);
}
void _submit() {
// CODE TO WRITE FORM IN FIREBASE
}
}
The function code from my BLOC is:
Future<List<AlimentoModel>> cargarAlimento(String idEmpresa, [String filtro]) async {
final alimento = await _alimentoProvider.cargarAlimento(idEmpresa, filtro); //It's one await more
_alimentoController.sink.add(alimento);
return alimento;
}
And the Query from PROVIDER is:
Future<List<AlimentoModel>> cargarAlimento(String idEmpresa, [String filtro]) async {
Query resp;
final List<AlimentoModel> alimento = new List();
resp = db.child('empresas').child(idEmpresa).child('bodega/1').child('alimento')
.orderByChild('cantidad').startAt(0.000001);
return resp.once().then((snapshot) {
if (snapshot.value == null) return [];
if (snapshot.value['error'] != null) return [];
snapshot.value.forEach((id, alim){
final temp = AlimentoModel.fromJson(Map<String,dynamic>.from(alim));
temp.idAlimento = id;
alimento.add(temp);
});
return alimento;
});
When using Firebase offline, you omit the await only on things that change the server (e.g., creating or updating a record). So you won't wait for the server to say "yes I wrote it", you assume that it's written.
In your case, however, you are not writing data, you are reading data. You will have to keep await in your example. The way you load your data has orderByChild and startAt, maybe those are preventing offline loading. Normally, you get it if it's already in the cache: https://firebase.google.com/docs/firestore/manage-data/enable-offline#get_offline_data
You mention a BAD STATE error, maybe if you provide that, we may be able to pinpoint the issue a bit better.

Banner ads are showing but Interstitial are not while test banner and test interstitial working perfectly

In my application I applied Both test ads (banner and interstitial) they are showing perfectly but when I apply real ads Both of them did not display.
I wait for 1 day and after one day only banner ads are showing now interstitial ads are not showing ( my ads id where generated 1 years before than why I need to wait 1 day to show in my application after uploading to google play store.
Now how can I display Interstitial ads please?
class Afcon extends StatefulWidget {
final String link;
Afcon({this.link});
#override
_AfconState createState() => _AfconState();
}
class _AfconState extends State<Afcon> {
void initState() {
super.initState();
FirebaseAdMob.instance.initialize(appId: AppId);
bannerAd = buildBanner()..load();
interstitialAd = buildInterstitial()..load();
}
#override
Widget build(BuildContext context) {
bannerAd ..load()..show(
anchorOffset: 20.0,
anchorType: AnchorType.bottom,
);
Future<bool> _onBackPressed() {
if(counter<1){
interstitialAd
..load()..show();
counter++;
}
else{
bannerAd.dispose();
Navigator.pop(context, true);
}
}
return WillPopScope(
child: WebviewScaffold(
appBar: AppBar(
title: Text('AFCON'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.open_in_new),
onPressed: (){
_newPage(widget.link);
}
)
],
),
initialChild: SpinKitWave(
color: Colors.black,
size: 30.0,
),
hidden: true,
url: widget.link,
),
onWillPop: _onBackPressed,
);
}
}
_newPage(String link) async {
if (await canLaunch(link)) {
await launch(link);
} else {
throw 'Could not launch $link';
}
}
Here initialized the Functions to show ads
import 'package:firebase_admob/firebase_admob.dart';
final AppId='ca-app-pub-**********************';
final InterstitialAdsUnit='ca-app-pub-**********************';
final BannerAdsUnit='ca-app-pub-**********************';
int counter=0;
final MobileAdTargetingInfo targetingInfo = MobileAdTargetingInfo(
keywords: ['Games', 'Puzzles'],
);
BannerAd bannerAd;
InterstitialAd interstitialAd;
RewardedVideoAd rewardedVideoAd;
BannerAd buildBanner() {
return BannerAd(
adUnitId: BannerAdsUnit,
size: AdSize.banner,
listener: (MobileAdEvent event) {
print(event);
});
}
InterstitialAd buildInterstitial() {
return InterstitialAd(
adUnitId: InterstitialAdsUnit,
targetingInfo: targetingInfo,
listener: (MobileAdEvent event) {
if (event == MobileAdEvent.failedToLoad) {
interstitialAd..load();
} else if (event == MobileAdEvent.closed) {
interstitialAd = buildInterstitial()..load();
}
print(event);
});
}
You have done everything perfectly from your side now you need to check the interstitial ads unit Id I am sure you have issue with ads unit ID. Go and make some new test Id and implement it on your app it will work. after applying new ads unit just wait sometime to let them show.
Never test your own ad, always use test ad units,
If you create a new admob app id, it might take some time for these ad units to go live, so it won't show ad.
So, if you run test ad units, does it work in real device?
Are you testing real ads on debug version of apk ? If yes,
Please try testing in real device with signed version of apk. I've seen many times real ads don't show in debug version of apk.

Flutter: Enable button when RatingBar value has been set

I am new to Flutter and am trying to figure out how to enable my action button only when a rating value has been selected in an AlertDialog. When the "submit" button has been selected with nothing selected, it still changes the value to e.g. 6.0 for some odd reason so an "if" statement may not work comparing it to null as I've tried it previously in the onPressed() method.
This is my method code to show the AlertDialog:
void _showDialog() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
title: Text("Pain Rating"),
content: RatingBar(
onRatingChanged: (rating) {
setState(() {
_rating = rating;
print("rating changed: rating = $_rating");
});
},
maxRating: 10,
filledIcon: Icons.radio_button_checked,
emptyIcon: Icons.radio_button_unchecked,
isHalfAllowed: false,
filledColor: Colors.green,
emptyColor: Colors.green,
size: 28,
),
actions: <Widget>[
FlatButton(
child: const Text('SUBMIT'),
onPressed: () {
print("submit pressed: rating = $_rating");
Navigator.of(context).pop();
},
)
],
);
});
Currently when any or no rating has been selected and the "submit" button has been pressed it will close the dialog. I expect the "submit" button to be disabled until a rating has been selected
This is one suggested way to do it:
var _rating = 0.0
FlatButton(
child: const Text('SUBMIT'),
onPressed: _rating > 0.0
? () {
print("submit pressed: rating = $_rating");
Navigator.of(context).pop();
} : null,
)
If your _rating gets grater than 0, that means the used changed the value (assuming your rating can't be 0). If so, you enable the button by passing that VoidCallback... if not, the null value is called and that disables the button.
If by any reason you need the 0.0 value, then use a bool variable and change the value to true once you reach the onRatingChanged callback and then change my logic from _rating > 0.0 to simply your bool variable.

Flutter Enable/Disable Button based on TextFormField content

How can I activate/deactivate a button based on the content of a TextFormField?
I want to make sure a user can only press Button X if the TextFormField has 10 entered numbers (if it's a mobile number).
Thanks!
The state of the widget can be updated in the Form's onChanged callback which is called whenever any of the form fields' value changes. There you can use a form key to validate the form and set a flag to enable/disable the button. This solution allows you to scale to disable buttons in forms with multiple fields. For example,
/// Key used to reference the form.
final _formKey = GlobalKey<FormState>();
...
Form(
key: _formKey,
onChanged: () => setState(() => _enableBtn = _formKey.currentState.validate()),
child: ListView(
children: <Widget>[
TextFormField(
validator: (value) => value.length < 10 ?
'Number must be at least 10 digits' : // return an error message
null,
...
),
],
),
)
...
FlatButton(
onPressed: _enableBtn ?
() => _doSomething() :
null, // setting onPressed to null disables the button.
...
A simple way would be to set the autovalidate property of our TextFormField to true. This will automatically detect for changes on our TextFormField widget. We can then try to check if our TextFormField's value has a String length of 10 characters on the validator property . After that we can call setState to enable or disable our button (I use FlatButton in this example).
bool _btnEnabled = false;
...
#override
Widget build(BuildContext context){
...
TextFormField(
...
autovalidate: true,
validator: (String txt){
if (txt.length == 10){
setState((){
_btnEnabled = true;
});
} else {
setState((){
_btnEnabled = false;
});
}
}
...
FlatButton(
onPressed: _btnEnabled == true ? yourCallback : null,
child: ...
you can use Flutter Reactive Forms. It's a model-driven approach to handling Forms inputs and validations, heavily inspired in Angular's Reactive Forms.
It's a very simple to use libray and in the documentation there is a section that explains how to Enable/Disable Submit button based on the validity of the entire form, not just a field.
The accepted answer seems to not work using the latest Flutter v1.7.8 (stable), it gives me the following error:
This TestForm widget cannot be marked as needing to build because the framework is already in the process of building widgets
The working version looks like the following:
...
autovalidate: true,
validator: (String txt){
bool isValid = txt.length == 10;
if (isValid != _btnEnabled) {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_btnEnabled = txt.length == 10;
});
});
}
}
...
You can use this method .
bool isEnable = false;
void validateButton() {
bool isValid = true;
isValid = userEmail.isNotEmpty &&
userPassword.isNotEmpty &&
validateEmail(userEmail) &&
userPassword.length >= 8;
setState(() {
isEnable = isValid;
});
}
now in your Textfield onChanged method you have to call this function
like This
onChanged: (email) {
userEmail = email;
setState(() {});
validateButton();
},
and in your Login Button
isEnable?ActiveButton():DisableButton()
Get error "setState() or markNeedsBuild() called during build." with accepted answer. Just add Future.delayed(Duration.zero).then(....) as a trick solution, it's working on flutter 1.12.13
TextFormField(
...
autovalidate: true,
validator: (String txt){
if (txt.length == 10){
Future.delayed(Duration.zero).then((_){
setState((){
_btnEnabled = true;
});
});
} else {
Future.delayed(Duration.zero).then((_){
setState((){
_btnEnabled = false;
});
});
}
}
....

Resources