Reputation: 584
I am trying to show alert dialog for force update my app on my app version change using firebase remote config, calling versionCheck(context) from initState() everything is fine but getting error when I am calling showVersionDialog() method, here is my code
void main() => runApp(UniApp());
class UniApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => _UniappMainState();
}
class _UniappMainState extends State<UniApp> {
AppTranslationsDelegate _newLocaleDelegate;
@override
void initState() {
super.initState();
setlocaleFromSharedPreference();
_newLocaleDelegate = AppTranslationsDelegate(newLocale: null);
UAAppContext.getInstance().onLocaleChanged = onLocaleChange;
//calling versionCheck
versionCheck(context);
}
versionCheck(context) async {
//Get Current installed version of app
final PackageInfo info = await PackageInfo.fromPlatform();
double currentVersion = double.parse(info.version.trim().replaceAll(".", ""));
//Get Latest version info from firebase config
final RemoteConfig remoteConfig = await RemoteConfig.instance;
try {
// Using default duration to force fetching from remote server.
await remoteConfig.fetch(expiration: const Duration(seconds: 0));
remoteConfig.setConfigSettings(RemoteConfigSettings(debugMode: true));
await remoteConfig.activateFetched();
remoteConfig.getString('force_update_current_version');
double newVersion = double.parse(remoteConfig
.getString('force_update_current_version')
.trim()
.replaceAll(".", ""));
print("cv-"+currentVersion.toString()+"nv--"+newVersion.toString());
if (newVersion > currentVersion) {
_showVersionDialog(context);
}
} on FetchThrottledException catch (exception) {
// Fetch throttled.
print(exception);
} catch (exception) {
print('Unable to fetch remote config. Cached or default values will be '
'used');
}
}
//Show Dialog to force user to update
_showVersionDialog(context) async {
await showDialog<String>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
String title = "New Update Available";
String message =
"There is a newer version of app available please update it now.";
String btnLabel = "Update Now";
String btnLabelCancel = "Later";
return new AlertDialog(
title: Text(title),
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text(btnLabel),
onPressed: () => _launchURL(CommonConstants.PLAY_STORE_URL),
),
FlatButton(
child: Text(btnLabelCancel),
onPressed: () => Navigator.pop(context),
),
],
);
},
);
}
_launchURL(String url) async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
void onLocaleChange(Locale locale) {
setState(() {
UAAppContext.getInstance().changeLanguage(locale.languageCode);
_newLocaleDelegate = AppTranslationsDelegate(newLocale: locale);
});
}
setlocaleFromSharedPreference() {
UAAppContext.getInstance().getLocale().then((locale) {
if (locale == 'en') return;
setState(() {
_newLocaleDelegate = AppTranslationsDelegate(newLocale: Locale(locale));
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => SplashScreen(),
CommonConstants.homeRoute: (context) { RouteParameters r = ModalRoute.of(context).settings.arguments;
if (r != null && r.appId != null && r.appId.isNotEmpty) {
return HomeScreen(
parentAppId: r.appId
);
} else return HomeScreen();},
CommonConstants.loginRoute: (context) => LoginScreen(),
CommonConstants.projectGroupRoute: (context) {
RouteParameters r = ModalRoute.of(context).settings.arguments;
if (r != null && r.appId != null && r.appId.isNotEmpty) {
return ProjectGroupScreen(
appId: r.appId,
attributes: r.groupingAttributes,
sortType: r.sortType,
);
} else
return SplashScreen();
},
CommonConstants.projectListRoute: (context) {
RouteParameters r = ModalRoute.of(context).settings.arguments;
if (r != null && r.appId != null && r.appId.isNotEmpty) {
return ProjectListScreen(
appId: r.appId,
sortType: r.sortType,
groupingKey: r.groupingKey,
groupingValue: r.groupingValue,
projectMasterDataTableList: r.projectMasterDataTableList,
);
} else
return SplashScreen();
},
CommonConstants.projectFormRoute: (context) {
RouteParameters r = ModalRoute.of(context).settings.arguments;
if (r != null && r.appId != null && r.appId.isNotEmpty) {
return ProjectFormScreen(
appId: r.appId,
projectId: r.projectId,
formActiontype: r.formActionType,
projectMasterDataKeyToValueMap: r.projectFieldsKeyToValue,
);
} else
return SplashScreen();
},
CommonConstants.getOTPRoute: (context) => GetOTPScreen(),
CommonConstants.changePasswordRoute: (context) =>
ChangePasswordScreen(),
CommonConstants.userRegistrationRoute: (context) =>
UserRegisterScreen(),
CommonConstants.downloadsRoute: (context) => DownloadScreen(),
CommonConstants.filterRoute: (context) {
RouteParameters r = ModalRoute.of(context).settings.arguments;
if (r != null && r.appId != null && r.appId.isNotEmpty) {
return FilterScreen(
appId: r.appId,
projectList: UAAppContext.getInstance().projectList,
filterKeyToValue:
UAAppContext.getInstance().filterSelectedValueMap,
);
} else
return SplashScreen();
},
CommonConstants.geoTaggingRoute: (context) {
RouteParameters r = ModalRoute.of(context).settings.arguments;
if (r != null &&
r.geoTaggingWidgetId != null &&
r.geoTaggingWidgetId.isNotEmpty) {
return GeotaggingWidget(
ctxt: r.context,
id: r.geoTaggingWidgetId,
gpsValidation: r.gpsValidation,
projLat: r.projLat,
projLon: r.projLon,
);
} else
return SplashScreen();
},
CommonConstants.profileRoute: (context) => UserProfileScreen(),
},
debugShowCheckedModeBanner: false,
// theme: UniappColorTheme.defaultTheme,
theme: UniappColorTheme.getTheme(),
localizationsDelegates: [
_newLocaleDelegate,
//provides localised strings
GlobalMaterialLocalizations.delegate,
//provides RTL support
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale("en", ""),
const Locale("hi", ""),
const Locale("or", "")
],
);
}
}
These are error msg I am getting when showing showVersionDialog() method, not getting what actually means it.
E/flutter (12951): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: No MaterialLocalizations found.
E/flutter (12951): UniApp widgets require MaterialLocalizations to be provided by a Localizations widget ancestor.
E/flutter (12951): Localizations are used to generate many different messages, labels, and abbreviations which are used by the material library.
E/flutter (12951): To introduce a MaterialLocalizations, either use a MaterialApp at the root of your application to include them automatically, or add a Localization widget with a MaterialLocalizations delegate.
E/flutter (12951): The specific widget that could not find a MaterialLocalizations ancestor was:
E/flutter (12951): UniApp
E/flutter (12951): The ancestors of this widget were:
E/flutter (12951): [root]
E/flutter (12951): #0 debugCheckHasMaterialLocalizations.<anonymous closure> (package:flutter/src/material/debug.dart:72:7)
E/flutter (12951): #1 debugCheckHasMaterialLocalizations (package:flutter/src/material/debug.dart:92:4)
E/flutter (12951): #2 showDialog (package:flutter/src/material/dialog.dart:843:10)
E/flutter (12951): #3 _UniappMainState._showVersionDialog (package:Uniapp/main.dart:80:11)
E/flutter (12951): #4 _UniappMainState.versionCheck (package:Uniapp/main.dart:67:9)
E/flutter (12951): <asynchronous suspension>
E/flutter (12951): #5 _UniappMainState.initState (package:Uniapp/main.dart:44:5)
Upvotes: 3
Views: 7197
Reputation: 73
I had a similar problem when using rflutter_alert package for showing pop-up alert dialog. My code structure was :
void main () {
runApp(QuizPage)
}
inside QuizPage , the build method returns:
return MaterialApp(
home: Scaffold())
I was able to solve it by following the second approche in the instructions in this article: https://www.fluttercampus.com/guide/70/how-to-solve-no-materiallocalizations-found-error-exception-in-flutter/
Now my code structure is:
runApp(MaterialApp(home: MyApp()))
MyApp returns QuizPage
Upvotes: 2
Reputation: 584
I just solve this issue by creating a singleton class (MySingletonClass) with a variable
BuildContext get context => _context;
got this variable
MySingletonClass.getInstance().context;
Passing singleton class context to showdialog contex
final context = MySingletonClass.getInstance().context;
//calling showVersionDialong
_showVersionDialog(context);
Upvotes: 2