I'm adding Stripe payment to an app I'm building. I've added the Stripe package, imported it and made sure all the requirements are met. But when I try to add publishable key using Stripe.publishableKey, it's showing: Undefined name 'Stripe'. This is the the code in my main.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
...
import 'package:flutter_stripe/flutter_stripe.dart'; //.....stripe package import....
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Stripe.publishableKey = publishableKey; //.....Undefined name 'Stripe'.......
await Firebase.initializeApp();
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ThemeProvider()),
ChangeNotifierProvider(create: (_) => ApplicationState()),
],
child: Consumer<ThemeProvider>(
builder: (context, _themeProvider, snapshot) {
return MaterialApp(
title: 'Title',
debugShowCheckedModeBanner: false,
theme: themeLight(context),
darkTheme: themeDark(context),
themeMode: (_themeProvider.isDarkTheme == true)
? ThemeMode.dark
: ThemeMode.light,
initialRoute: '/',
routes: {
'/': (context) => const SplashScreen(),
'/on-boarding': (context) => const OnBoardingScreen(),
'/all-login-options': (context) =>
const SocialNetworkSignInScreen(),
...
'/home': (context) => const Home(),
},
);
},
),
);
}
}
Has anyone ever faced a similar issue before? Do you have any solutions for it? Any help will be greatly appreciated.
you can give the import a name and use it to access the Stripe class. this is the solution I came up with when facing the same issue
import 'package:flutter_stripe/flutter_stripe.dart' as stripe;
and then in main
stripe.Stripe.publishableKey = publishableKey;
Related
I wonder how to manage screen navigation when your app is connected to Firebase.
When my app was offline I used a routes table, but Im not sure how to do now. Could I do as I show with my code below; use a streambuilder that switches between the AuthScreen when logged out and HomeScreen when logged in, and a routes table to switch with the following screens also when signed in.
I tried this approach but when im signing out from another screen than the HomeScreen the user stays signed in.
How can I set up my routes so that the user always signs out independent from which screen the user's currently on.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'FlutterApp',
theme: ThemeData(
primarySwatch: Colors.orange,
),
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (
ctx,
userSnapshot,
) {
if (userSnapshot.hasData) {
return HomeScreen();
}
return AuthScreen();
}),
routes: {
Screen1.routeName: (ctx) => Screen1(),
Screen2.routeName: (ctx) => Screen2(),
Screen3.routeName: (ctx) => Screen3(),
Screen4.routeName: (ctx) => Screen4(),
});
}
}
I don't think you're going about this the right way.
They are various ways of doing this. Here's mine.
Firstly, I think you should define an initial route that checks if the user is signed in.
Widget build(BuildContext context) {
return MaterialApp(
title: 'FlutterApp',
theme: ThemeData(
primarySwatch: Colors.orange,
),
initialRoute:
FirebaseAuth.instance.currentUser == null ? "/login" : "/home",
routes: {
"/home": (ctx) => HomeScreen(),
"/login": (ctx) => AuthScreen(),
Screen1.routeName: (ctx) => Screen1(),
Screen2.routeName: (ctx) => Screen2(),
Screen3.routeName: (ctx) => Screen3(),
Screen4.routeName: (ctx) => Screen4(),
});
}
Note: "/home" & "/login" could be whatever you want as long as it's a string.
For logout, you need to replace the current screen with the login page, something like this should do.
Navigator.pushNamedAndRemoveUntil(context, '/login', (route) => false);
I've setup my project with a Scaffold wrapper so all the routes have the AppBar and SideDrawer widgets.
I'm quite annoyed having to pass around my _navigatorKey all the time and running into this error: "Navigator operation requested with a context that does not include a Navigator".
Also when trying to do very specific things like open a dialog I have to pass navigatorKey.currentContext which throws this error: "The argument type 'BuildContext?' can't be assigned to the parameter type 'BuildContext'".
Also when using any widget requiring an overlay like TextFormField or DropdownButton I'm running into this error: "No Overlay widget found.".
I've been able to fix all these issues with roundabout methods that I don't like, but more and more issues keep coming up because of this GlobalKey usage.
Is there a better way to wrap my routes and avoid using GlobalKey?
import 'package:flutter/material.dart';
import 'package:get_it_mixin/get_it_mixin.dart';
import 'package:provider/provider.dart';
import 'pages/blog_page.dart';
import 'pages/landing_page/landing_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget with GetItMixin {
MyApp({Key? key}) : super(key: key);
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<MenuProvider>(
create: (_) => MenuProvider(),
),
ChangeNotifierProvider<MarkdownProvider>(
create: (_) => MarkdownProvider(),
),
],
builder: (context, child) {
return MaterialApp(
title: "test",
navigatorKey: _navigatorKey,
debugShowCheckedModeBanner: false,
builder: (context, child) {
return Overlay(
initialEntries: [
OverlayEntry(
builder: (context) =>
MyScaffold(child: child!, navigatorKey: _navigatorKey),
),
],
);
},
home: const LandingPage(),
routes: {
LandingPage.routeName: (context) => const LandingPage(),
BlogPage.routeName: (context) => const BlogPage(),
MarkdownPage.routeName: (context) => const MarkdownPage(),
},
);
},
);
}
}
After updating/converting a program to null-safety, i'm presented with the following error:
Error: Could not find the correct Provider above this Wrapper Widget
This happens because you used a BuildContext that does not include the provider
of your choice. There are a few common scenarios:
You added a new provider in your main.dart and performed a hot-reload.
To fix, perform a hot-restart.
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
You used a BuildContext that is an ancestor of the provider you are trying to read.
Make sure that Wrapper is under your MultiProvider/Provider.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
}
consider using builder like so:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context) {
// No longer throws
return Text(context.watch<Example>()),
}
),
}
If none of these solutions work, consider asking for help on StackOverflow:
https://stackoverflow.com/questions/tagged/flutter
The error also points to the "relevant error-causing widget" for me it was my call to my Wrapper(), Highlighted below:
The relevant error-causing widget was:
Wrapper Wrapper:file:///home/AlphaUser/AndroidStudioProjects/test/lib/main.dart:78:20
The stack had more lines I didn't think were relevant. (I can add if needed)
Current Code in use:
Main.dart:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:test/screens/authenticate/test_forgot.dart';
import 'package:test/screens/authenticate/test_login.dart';
import 'package:test/screens/authenticate/test_signup.dart';
import 'package:test/screens/faq_screen.dart';
import 'package:test/screens/review_purchase_screen.dart';
import 'package:test/screens/purchased_products_screen.dart';
import 'package:test/screens/search_products_screen.dart';
import 'package:test/screens/test_postImage.dart';
import 'package:test/wrapper/wrapper.dart';
import "package:provider/provider.dart";
import 'package:test/services/auth.dart';
import 'models/user.dart';
import 'package:test/screens/product_detail_screen.dart';
import 'package:test/providers/products_provider.dart';
import 'package:test/providers/shippments_provider.dart';
import 'package:test/providers/orders.dart';
import 'package:test/screens/user_products_screen.dart';
import 'package:test/screens/edit_product_screen.dart';
import 'package:test/screens/product_checkout_screen.dart';
import 'package:test/screens/test_feed.dart';
import 'package:test/screens/profile_screen.dart';
import 'package:test/home/home.dart';
import 'package:test/home/homeUser.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
FirebaseApp app = await Firebase.initializeApp();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
Stripe.publishableKey =
'stripe_publishableKey';
await Stripe.instance.applySettings();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (ctx) => Shippments(),
),
ChangeNotifierProvider(
create: (ctx) => Orders(),
),
ChangeNotifierProvider(
create: (ctx) => Products(),
),
],
child: StreamProvider<User>.value(
value: AuthService().user,
initialData: null,
child: new MaterialApp(
title: 'Test',
theme: ThemeData(
primarySwatch: Colors.grey,
// accentColor: Colors.green,
),
debugShowCheckedModeBanner: false,
//* Login Options **//
home: Wrapper(), //***<-- Error points to this line.***
//home: Home(), //<-- **Works Fine if I use this instead of Wrapper().** //
//* Login Options **//
routes: {
TestLogin.id: (context) => TestLogin(),
TestSignup.id: (context) => TestSignup(),
TestForgot.id: (context) => TestForgot(),
ProductDetailScreen.routeName: (context) => ProductDetailScreen(),
UserProductsScreen.routeName: (context) => UserProductsScreen(),
EditProductScreen.routeName: (context) => EditProductScreen(),
TestPostImageScreen.routeName: (context) => TestPostImageScreen(),
ProductCheckoutScreen.routeName: (context) =>
ProductCheckoutScreen(),
PurchasedProductsScreen.routeName: (context) =>
PurchasedProductsScreen(),
SearchProductsScreen.routeName: (context) => SearchProductsScreen(),
TestFeed.routeName: (context) => TestFeed(),
ReviewPurchaseScreen.routeName: (context) => ReviewPurchaseScreen(),
ProfileScreen.routeName: (context) => ProfileScreen(),
FAQScreen.routeName: (context) => FAQScreen()
},
),
),
);
}
}
wrapper.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test/home/home.dart';
import 'package:test/home/homeUser.dart';
import 'package:test/models/user.dart' as model;
import '../screens/authenticate/test_login.dart';
import 'package:http/http.dart' as http;
import 'package:flutter_spinkit/flutter_spinkit.dart';
class Wrapper extends StatefulWidget {
#override
_WrapperState createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
get lists => null;
bool currentAdmin;
bool loading = false;
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
return FutureBuilder(
future: _checkUser(user),
builder: (context, snapshot) {
String profile = snapshot.data;
print("profile!!!: $profile");
if (profile == 'true') {
print("Snapshot has data: ${snapshot.data}");
return Home();
} else if (profile == 'false') {
print("Snapshot has no data: ${snapshot.data}");
return HomeUser();
} else if (user == null) {
return TestLogin();
} else {
//return CircularProgressIndicator();
return SpinKitFadingCube(
color: Colors.black,
size: 25.0,
);
}
//return null;
},
);
}
_checkUser(User user) async {
...
} //_checkUser()
}
User.dart
class User {
final String uid;
User({this.uid});
}
Just want to add that if I replace Wrapper() with Home() the program works, but that will bypass my "user login/register/forgot password" functionality.
Any help or guidance will be much appreciated.
you are using the User Provider and didn't create the user provider yet
add the User Provider in the MultiProvider in main
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (ctx) => Shippments(),
),
ChangeNotifierProvider(
create: (ctx) => Orders(),
),
ChangeNotifierProvider(
create: (ctx) => Products(),
),
ChangeNotifierProvider( // add this
create: (ctx) => User(),
),
],
child: StreamProvider<User>.value(
I am attempting to share a ChangeNotifierProvider to my main.dart, however the value never gets updated.
How it works
main.dart uses ChangeNotifierProvider to get an instance of the class Location()
main.dart routes to the location_login.dart page where a string in Location() class is set.
The instance of Location() should update in main.dart but it DOES NOT.
Here is the main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
ChangeNotifierProvider<Location>.value( <------ CREATE CHANGENOTIFIERPROVIDER
value: Location(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
Location location = Provider.of<Location>(context, listen: false); <----- LISTEN TO PROVIDER
return MultiProvider(
providers: [
FutureProvider<List<Report>>(
create: (context) =>
Collection<Report>(path: '${location.getLocation}/data/reports') <----- USE PROVIDER STRING IN PATH
.getUsers(),
initialData: [],
),
],
child: MaterialApp(
routes: {
'/': (context) => LocationLogin(),
'/login': (context) => LoginScreen(),
'/home': (context) => HomeScreen(),
},
// Theme
theme: ThemeData(
fontFamily: 'Nunito',
bottomAppBarTheme: BottomAppBarTheme(
color: Colors.black87,
),
// your customizations here
brightness: Brightness.dark,
buttonTheme: ButtonThemeData(),
),
),
);
}
}
Here is the location_login.dart
#override
Widget build(BuildContext context) {
Location location = Provider.of<Location>(context, listen: true);
return Scaffold(
body: TextButton(
child: Text("Submit",
style: GoogleFonts.poppins(
fontSize: 15.sp, color: Colors.white)),
onPressed: () {
location.setLocation('London'); <------- SETTING LOCATION
}),
);
}
}
Here is the location.dart
class Location with ChangeNotifier {
String place = 'none';
String get getLocation => place;
setLocation(String location) {
place = location;
notifyListeners();
}
}
To reiterate, the issue is that when I click the button in the location_login.dart page to set the location to "London"; it does not update the ChangeNotifierProvider with a new instance of the Location() class containing "London". Therefore, I can not update the path in my FurtureProvider. Any ideas of what is going wrong here? I tried to make this as clear as possible but if you don't understand please ask. Thank you
I think you have not consume the ChangeNotifierProvider.
For me below simple implementation work perfectly.
my main.dart file code is as below...
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/app_provider.dart';
import 'providers/favorites_provider.dart';
import 'providers/comments_provider.dart';
import 'providers/home_provider.dart';
import 'providers/details_provider.dart';
import 'providers/gallery_provider.dart';
import 'providers/chat_provider.dart';
import 'ui/splash.dart';
import 'helper/constants.dart';
import 'ui_user/login.dart';
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AppProvider()),
ChangeNotifierProvider(create: (_) => GalleryProvider()),
ChangeNotifierProvider(create: (_) => CommentsProvider()),
ChangeNotifierProvider(create: (_) => ChatProvider()),
ChangeNotifierProvider(create: (_) => HomeProvider()),
ChangeNotifierProvider(create: (_) => DetailsProvider()),
ChangeNotifierProvider(create: (_) => FavoritesProvider()),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<AppProvider>(
builder: (BuildContext context, AppProvider appProvider, Widget child) {
return MaterialApp(
key: appProvider.key,
debugShowCheckedModeBanner: false,
navigatorKey: appProvider.navigatorKey,
title: Constants.appName,
theme: appProvider.theme,
home: appProvider.isLogin == "0" ? LoginPage() : Splash(),
);
},
);
}
}
And my app_provider.dart as below...
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../helper/constants.dart';
class AppProvider extends ChangeNotifier {
AppProvider() {
checkTheme();
}
String isLogin = "0";
ThemeData theme = Constants.lightTheme;
Key key = UniqueKey();
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
void setKey(value) {
key = value;
notifyListeners();
}
void setNavigatorKey(value) {
navigatorKey = value;
notifyListeners();
}
void setTheme(value, c) {
theme = value;
SharedPreferences.getInstance().then((prefs) {
prefs.setString("theme", c).then((val) {
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor:
c == "dark" ? Constants.darkPrimary : Constants.lightPrimary,
statusBarIconBrightness:
c == "dark" ? Brightness.light : Brightness.dark,
));
});
});
notifyListeners();
}
ThemeData getTheme(value) {
return theme;
}
Future<ThemeData> checkTheme() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
ThemeData t;
String r =
prefs.getString("theme") == null ? "light" : prefs.getString("theme");
isLogin = prefs.getString("isLogin") == null? "0" : prefs.getString("isLogin");
if (r == "light") {
t = Constants.lightTheme;
setTheme(Constants.lightTheme, "light");
} else {
t = Constants.darkTheme;
setTheme(Constants.darkTheme, "dark");
}
return t;
}
}
This solution is working very well for me. Hope this will help you too...
I'm New in this FrameWork and here initial Rout is not Accepting the Loggin Session value Please help me with this. I tried to add Home with the splash screen but that also not working I'm not getting What's wrong in this.
This is my main Page
Future main() async {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
));
runApp(Phoenix(child: AmericanCuisine()));
}
class AmericanCuisine extends StatefulWidget {
#override
_AmericanCuisineState createState() => _AmericanCuisineState();
}
class _AmericanCuisineState extends State<AmericanCuisine> {
bool isLoggedIn;
#override
void initState() {
super.initState();
getData();
}
getData() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences storage = await SharedPreferences.getInstance();
setState(() {
isLoggedIn = storage.getBool("loggedIn");
});
}
#override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<LanguageCubit>(
create: (context) => LanguageCubit(),
),
BlocProvider<ThemeCubit>(
create: (context) => ThemeCubit(),
),
],
in this page after using BlockBuilder how i To give the Initial Route
child: BlocBuilder<ThemeCubit, ThemeData>(
builder: (_, theme) {
return BlocBuilder<LanguageCubit, Locale>(
builder: (_, locale) {
return MaterialApp(
localizationsDelegates: [
const AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en'),
],
locale: locale,
theme: theme,
//This initial rout is not working.
initialRoute: isLoggedIn == false ?'/': '/homeOrderAccount',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => OpeningScreen(),
'/homeOrderAccount': (context) => HomeOrderAccount(),
},
);
},
);
},
),
);
}
}
You can't use initialRoute with routes map either delete '/' from the routes map or delete the initialRoute: