catch answer of WorkManager - android

I want to update the background color of my app in terms of result of my background task.
I use flutter_bloc and WorkManager.
I want my app to be blue during the action, and green if the result is good and red if my function throw an exception.
Or can I update my screen color in terms of result of my repo.getBattery call ?
Here in logs I can read workmanager.result error (bad url) but I can't catch it.
main.dart:
import 'package:batt/test_cubit.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
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 BlocProvider(
create: (context) => TestCubit(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
));
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _sw_value = false;
TextEditingController _controller = TextEditingController(text: "url");
Future<Null> tmp() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_controller = TextEditingController(text: prefs.getString("url"));
});
}
#override
void initState(){
super.initState();
tmp();
}
#override
Widget build(BuildContext context) {
return BlocBuilder<TestCubit, TestState>(builder: (context, state) {
return Scaffold(
backgroundColor: state.status,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextField(
controller: _controller,
maxLines: null,
keyboardType: TextInputType.url,
onChanged: (url) =>
context.read<TestCubit>().urlChanged(url),
),
const SizedBox(
height: 50,
),
CupertinoSwitch(
value: _sw_value,
onChanged: (value){
setState(() {
_sw_value = value;
});
if (value == true){
BlocProvider.of<TestCubit>(context).validate();
}
else {
BlocProvider.of<TestCubit>(context).cancel();
}
}
),
],
),
),
);
});
}
}
and my test_cubit.dart:
import 'dart:async';
import 'package:battery_plus/battery_plus.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:workmanager/workmanager.dart';
import 'data/Repository/battery_repo.dart';
import 'data/data_provider/battery_provider.dart';
import 'package:http/http.dart' as http;
part 'test_state.dart';
const fetchBackground = "fetchBackground";
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
switch (task) {
case fetchBackground:
var battery = Battery();
var batlevel = await battery.batteryLevel;
final urlFinal = inputData!["string"] + batlevel.toString();
try {
await repo.getBattery(urlFinal);
} catch (e) {
return Future.error("bad url");
}
break;
}
return Future.value(true);
});
}
final BatteryRepository repo = BatteryRepository(api: ServerAPI(http.Client()));
class TestCubit extends Cubit<TestState> {
TestCubit() : super(TestState("", Colors.grey));
urlChanged(String url) {
state.path = url;
}
validate() async {
if (state.path != "") {
final SharedPreferences _prefs = await SharedPreferences.getInstance();
_prefs.setString('url', state.path);
}
WidgetsFlutterBinding.ensureInitialized();
await Workmanager().cancelAll();
await Workmanager().initialize(
callbackDispatcher,
isInDebugMode: false,
);
state.status = Colors.blue;
emit(state);
try {
Workmanager().registerPeriodicTask("1", fetchBackground,
backoffPolicy: BackoffPolicy.exponential,
inputData: {
'string': state.path,
});
} catch (e) {
state.status = Colors.red;
emit(state);
}
Workmanager().registerPeriodicTask("2", fetchBackground,
initialDelay: const Duration(minutes: 5),
inputData: {
'string': state.path,
});
Workmanager().registerPeriodicTask("3", fetchBackground,
initialDelay: const Duration(minutes: 10),
inputData: {
'string': state.path,
});
state.status = Colors.green;
emit(state);
}
cancel() async {
await Workmanager().cancelAll();
state.status = Colors.pink;
emit(state);
}
}
please can you help me ? :)
I'm very beginner so I think my code is not good at all too :/

Related

the flutter audio wiveforms package does not display waveforms

I hope you are well, I have a big problem with the flutter audio waveforms package, indeed I want to display the waveforms of my voice files in a folder, but they are not displayed and when I display the value of playerController.bufferData I get a null, please how can I manage this problem, I have already spent days on it.
Sincerely
below are my classes
import 'dart:async';
import 'dart:io';
import 'package:audio_recorder/AudioWaveFormsWidget.dart';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:record/record.dart';
void main() {
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: 'Audio Recorder',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Audio Recorder'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
//late final PlayerController playerController1;
final record = Record();
int _recordDuration = 0;
Timer? _timer;
RecordState _recordState = RecordState.stop;
StreamSubscription<RecordState>? _recordSub;
final List<File> _audioFile = [];
#override
void initState() {
super.initState();
//Listening record state
_recordSub = record.onStateChanged().listen((recordState) {
setState(() => _recordState = recordState);
});
initCheckPermission();
setState(() {
initFileInDir();
});
}
#override
void dispose() {
_timer?.cancel();
_recordSub?.cancel();
record.dispose();
super.dispose();
}
Future initCheckPermission() async {
final statusMicrophone = await Permission.microphone.request();
final statusStorage = await Permission.storage.request();
if (statusMicrophone != PermissionStatus.granted ||
statusStorage != PermissionStatus.granted) {
await Permission.microphone.request();
await Permission.storage.request();
}
}
void _startTimer() {
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
setState(() => _recordDuration++);
});
}
Widget _buildText() {
if (_recordState != RecordState.stop) {
return _buildTimer();
}
return const Text("Waiting to record");
}
String _formatNumber(int number) {
String numberStr = number.toString();
if (number < 10) {
numberStr = '0$numberStr';
}
return numberStr;
}
Widget _buildTimer() {
final String minutes = _formatNumber(_recordDuration ~/ 60);
final String seconds = _formatNumber(_recordDuration % 60);
return Text(
'$minutes : $seconds',
style: const TextStyle(color: Colors.red),
);
}
Future<Directory> _getDir() async {
//Check platform and adjust settings
final tempDir = Platform.isAndroid
? await getExternalStorageDirectory()
: await getApplicationDocumentsDirectory();
Directory finalPath;
if (Platform.isAndroid) {
String buildDir =
tempDir!.path.replaceFirst("/data/", "/media/").split("files").first;
buildDir += "AudioRecorder"; // Plus ajout du nom de l'application
return finalPath = await Directory(buildDir).create(recursive: true);
} else {
return finalPath = await Directory(tempDir!.path).create(recursive: true);
}
}
void initFileInDir() async {
Directory finalPath = await _getDir();
var exists = await finalPath.exists();
if (exists) {
finalPath.list(recursive: false).forEach((element) {
File file = File(element.path);
_audioFile.add(file);
});
}
}
Widget _buildStopAndPlayIcon() {
if (_recordState != RecordState.stop) {
return const Icon(Icons.stop);
} else {
return const Icon(Icons.mic);
}
}
Future<void> _start() async {
Directory finalPath = await _getDir();
//Start recording
await record.start(
path: '${finalPath.path}/${DateTime.now().millisecondsSinceEpoch}.m4a',
encoder: AudioEncoder.aacLc, // by default
bitRate: 128000, // by default
samplingRate: 44100);
_recordDuration = 0;
_startTimer();
}
Future<File?> _stop() async {
_timer?.cancel();
_recordDuration = 0;
final path = await record.stop();
File? file;
if (path != null) {
file = File(path);
if (kDebugMode) {
print("--------------------------$path");
}
}
return file;
}
Future<void> _pause() async {
_timer?.cancel();
await record.pause();
}
Future<void> _resume() async {
_startTimer();
await record.resume();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
LimitedBox(
maxHeight: 650,
child: ListView.builder(
shrinkWrap: true,
itemCount: _audioFile.length,
itemBuilder: (context, index) {
var data = _audioFile[index];
return AudioWaveFormsWidget(path: data);
},
),
),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildText(),
ElevatedButton(
onPressed: () async {
if (_recordState == RecordState.stop) {
_start();
} else {
File? newFile = await _stop();
setState((){ _audioFile.add(newFile!);});
}
},
style: ButtonStyle(
elevation: MaterialStateProperty.all(0),
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
side: BorderSide.none))),
child: _buildStopAndPlayIcon(),
)
],
),
],
),
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
import 'dart:io';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class AudioWaveFormsWidget extends StatefulWidget {
final File path;
//final PlayerController playerController1;
const AudioWaveFormsWidget({Key? key, required this.path}) : super(key: key);
#override
State<AudioWaveFormsWidget> createState() => _AudioWaveFormsWidgetState();
}
class _AudioWaveFormsWidgetState extends State<AudioWaveFormsWidget> {
late final PlayerController playerController1;
#override
void initState() {
playerController1 = PlayerController()
..addListener(() {
if (mounted) setState(() {});
});
_preparePlayer();
super.initState();
}
void _preparePlayer() async {
bool exist = await widget.path.exists();
if (exist) {
playerController1.preparePlayer(widget.path.path);
}
print("--------------------------------${playerController1.bufferData}");
}
void _playOrPausePlayer(PlayerController controller) async {
debugPrint(
'****************************************${controller.playerState.toString()}');
controller.playerState == PlayerState.playing
? await controller.pausePlayer()
: await controller.startPlayer(finishMode: FinishMode.pause);
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
shape: BoxShape.rectangle,
color: Colors.lightGreenAccent,
),
child: Row(
children: [
IconButton(
onPressed: () {
_playOrPausePlayer(playerController1);
},
icon: playerController1.playerState == PlayerState.playing
? const Icon(Icons.pause)
: const Icon(Icons.play_arrow)),
AudioFileWaveforms(
density: 1.0,
enableSeekGesture: true,
size: const Size(100.0, 70.0),
playerController: playerController1),
],
)),
);
}
}
if you're trying to record, try setting the bitRate to 48000 (worked for me on iOS when it wasn't showing the waveforms when recording).
final RecorderController recorderController = RecorderController()
..androidEncoder = AndroidEncoder.aac
..androidOutputFormat = AndroidOutputFormat.mpeg4
..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
..sampleRate = 44100
..bitRate = 48000;

Error: Could not find the correct Provider<AuthState> above this AuthPage Widget

ERROR:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following ProviderNotFoundException was thrown building AuthPage(dirty, state:
_AuthPageState#7ac1c):
Error: Could not find the correct Provider above this AuthPage 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 AuthPage 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>()),
}
),
}
My Code:
AuthPage.dart:-
import 'package:first_app/pages/auth/bloc/auth_state.dart';
import 'package:first_app/pages/auth/widgets/auth_button.dart';
import 'package:first_app/pages/auth/widgets/otp_page.dart';
import 'package:first_app/pages/auth/widgets/phone_page.dart';
import 'package:first_app/pages/auth/widgets/set_up_account.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
class AuthPage extends StatefulWidget {
final int page;
final String? uid;
const AuthPage({
Key? key,
this.page = 0,
this.uid,
}) : super(key: key);
#override
_AuthPageState createState() => _AuthPageState();
}
class _AuthPageState extends State<AuthPage> {
#override
Widget build(BuildContext context) {
final state = Provider.of<AuthState>(context);
final screenSize = MediaQuery.of(context).size;
return
Builder(builder: (context) {
return Stack(
children: [
Container(
height: screenSize.height,
width: screenSize.width,
color: Colors.white,
child: PageView(
controller: state.controller,
onPageChanged: state.onPageChanged,
physics: NeverScrollableScrollPhysics(),
children: [
PhonePage(),
OtpPage(),
SetUpAccount(),
],
),
),
AuthButton(),
],
);
});
}
}
class AuthPageWidget extends StatelessWidget {
final int page;
final String? uid;
const AuthPageWidget({
Key? key,
required this.page,
this.uid,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final state = AuthState(page, uid ?? '');
return ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
);
}
}
AuthState.dart
import 'dart:async';
import 'package:first_app/models/user.dart';
import 'package:first_app/repositories/user_repository.dart';
import 'package:first_app/services/auth.dart';
import 'package:first_app/services/map_services.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
enum PhoneAuthState { initial, success, loading, codeSent, error }
/*part of 'auth_bloc.dart';
abstract class AuthState extends Equatable {
const AuthState();
#override
List<Object> get props => [];
}*/
class AuthState extends ChangeNotifier {
final authService = AuthService.instance;
final userRepo = UserRepository.instance;
PhoneAuthState _phoneAuthState = PhoneAuthState.initial;
String verificationId = '';
TextEditingController phoneController = TextEditingController();
TextEditingController otpController = TextEditingController();
TextEditingController firstNameController = TextEditingController();
TextEditingController lastNameController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController licensePlateController = TextEditingController();
TextEditingController vehicleColorController = TextEditingController();
TextEditingController vehicleTypeController = TextEditingController();
TextEditingController vehicleManufacturersController = TextEditingController();
Roles role = Roles.passenger;
PageController? controller;
int pageIndex = 0;
String uid = '';
int timeOut = 30;
bool get isRoleDriver => role == Roles.driver;
AuthState(int page, String uid) {
this.uid = uid;
controller = PageController(initialPage: page);
pageIndex = page;
notifyListeners();
siginCurrentUser();
}
PhoneAuthState get phoneAuthState => _phoneAuthState;
set changeRoleState(int value) {
role = Roles.values[value];
notifyListeners();
}
set phoneAuthStateChange(PhoneAuthState phoneAuthState) {
_phoneAuthState = phoneAuthState;
notifyListeners();
}
void animateToNextPage(int page) {
controller!.animateToPage(page, duration: Duration(milliseconds: 400), curve: Curves.easeIn);
pageIndex = page;
notifyListeners();
}
void onPageChanged(int value) {
pageIndex = value;
notifyListeners();
}
Future<void> signUp() async {
phoneAuthStateChange = PhoneAuthState.loading;
final address = await MapService.instance?.getCurrentPosition();
try {
final user = User(
uid: uid,
isActive: true,
firstname: firstNameController.text,
lastname: lastNameController.text,
email: emailController.text,
createdAt: DateTime.now(),
isVerified: true,
licensePlate: licensePlateController.text,
phone: "234${phoneController.text}",
vehicleType: vehicleTypeController.text,
vehicleColor: vehicleColorController.text,
vehicleManufacturer: vehicleManufacturersController.text,
role: role,
latlng: address?.latLng,
);
await userRepo.setUpAccount(user);
phoneAuthStateChange = PhoneAuthState.success;
} on FirebaseException catch (e) {
print(e.message);
phoneAuthStateChange = PhoneAuthState.error;
}
}
Future<void> phoneNumberVerification(String phone) async {
await AuthService.instance!.verifyPhoneSendOtp(phone, completed: (credential) async {
if (credential.smsCode != null && credential.verificationId != null) {
verificationId = credential.verificationId ?? '';
notifyListeners();
await verifyAndLogin(credential.verificationId!, credential.smsCode!, phoneController.text);
}
}, failed: (error) {
phoneAuthStateChange = PhoneAuthState.error;
}, codeSent: (String id, int? token) {
verificationId = id;
notifyListeners();
phoneAuthStateChange = PhoneAuthState.codeSent;
codeSentEvent();
print('code sent $id');
}, codeAutoRetrievalTimeout: (id) {
verificationId = id;
notifyListeners();
phoneAuthStateChange = PhoneAuthState.codeSent;
animateToNextPage(1);
print('timeout $id');
});
animateToNextPage(1);
notifyListeners();
}
Future<void> verifyAndLogin(String verificationId, String smsCode, String phone) async {
phoneAuthStateChange = PhoneAuthState.loading;
final uid = await authService?.verifyAndLogin(verificationId, smsCode, phone);
await userRepo.getUser(uid);
this.uid = uid ?? '';
animateToNextPage(2);
notifyListeners();
phoneAuthStateChange = PhoneAuthState.success;
print('completed');
}
Future<void> siginCurrentUser() async {
await userRepo.signInCurrentUser();
}
Future<void> codeSentEvent() async {
animateToNextPage(1);
_startCountDown();
}
void _startCountDown() {
Timer.periodic(Duration(seconds: 1), (timer) {
if (timer.tick > 30) {
timer.cancel();
} else {
--timeOut;
}
notifyListeners();
});
}
}
main.dart
import 'package:first_app/pages/home/home.dart';
import 'package:first_app/repositories/user_repository.dart';
import 'package:first_app/ui/theme.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
UserRepository.instance.signInCurrentUser();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BrilliantDrive',
theme: CityTheme.theme,
home: HomePage(),
);
}
}
Initialize your provider 1st. Refer this https://stackoverflow.com/a/68418866/16467763.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<AuthState>(
create: (context) => AuthState(),
),
],
child: MyApp(),
),
);
}
class AuthPageWidget extends StatelessWidget {
final int page;
final String? uid;
const AuthPageWidget({
Key? key,
required this.page,
this.uid,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final state = AuthState(page, uid ?? '');
return ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
);
}
}
You should move the ChangeNotifierProvider to your main.dart like this
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final state = AuthState(page, uid ?? '');
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
create: (_) => state,
child: AuthPage(page: page, uid: uid),
),
),
);
}
OR
class SomeWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
)
),
);
}
}

Flutter Multiselect Chips From API Contents

I am using this multi-select flutter package. It already has contents to view chips, but I want to load contents from API to do that instead.
I already added a fetchData() function to download the data from the API. Now, how do I get the JSON data into the chips multi-select?
Here is my code:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:multiselect_formfield/multiselect_formfield.dart';
import 'package:multi_select_flutter/multi_select_flutter.dart';
import 'package:http/http.dart' as http;
import 'Includes/APILinks.dart';
void main() => runApp(Sample());
class Sample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List _myActivities;
String _myActivitiesResult;
final formKey = new GlobalKey<FormState>();
#override
void initState() {
super.initState();
_myActivities = [];
this.fetchData();
}
_saveForm() {
var form = formKey.currentState;
if (form.validate()) {
form.save();
setState(() {
_myActivitiesResult = _myActivities.toString();
});
}
}
fetchData() async{
var url = CategorySection;
var response = await http.get(url);
if(response.statusCode == 200){
var items = json.decode(response.body);
print(items);
setState(() {
_myActivities = items;
});
} else {
setState(() {
_myActivities = [];
});
}
}
#override
Widget build(BuildContext context) {
final double maxWidth = MediaQuery.of(context).size.width;
final double maxHeight = MediaQuery.of(context).size.height;
return Scaffold(
appBar: AppBar(
title: Text('MultiSelect Formfield Example'),
),
body: Center(
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
height: maxHeight/2,
width: maxWidth,
padding: EdgeInsets.all(16),
child: getListView(),
),
Container(
padding: EdgeInsets.all(8),
child: RaisedButton(
child: Text('Save'),
onPressed: _saveForm,
),
),
Container(
padding: EdgeInsets.all(16),
child: Text(_myActivitiesResult),
)
],
),
),
),
);
}
Widget getListView() {
return ListView.builder(
itemCount: _myActivities.length,
itemBuilder: (context, index){
return cardView(_myActivities[index]);
},
);
}
Widget cardView(item) {
var fullName = item;
return MultiSelectDialogField(
items: _myActivities,
title: Text("Animals"),
selectedColor: Colors.blue,
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.all(Radius.circular(40)),
border: Border.all(
color: Colors.blue,
width: 2,
),
),
buttonIcon: Icon(
Icons.pets,
color: Colors.blue,
),
buttonText: Text(
"Favorite Animals",
style: TextStyle(
color: Colors.blue[800],
fontSize: 16,
),
),
onConfirm: (results) {
_myActivities = results;
},
);
}
}
You can use a Future function with the return type that you want, in that case it will be Future<List<MultiSelectItem>>, then you would use async and await, it will be something like that:
Future<List<Item>> fetchItems(BuildContext context) async {
http.Response response = await http.get(
Uri.parse('your link for ur api'),
//you can ignore that part
headers: <String, String>{
'Authorization':
'Token ${Provider.of<Token>(context, listen: false).token}'
});
//here you turn the json to a <String, dynamic> map
var data = jsonDecode(response.body);
List<Item> result = [];
for (var item in data) {
//use your factory if you wanna to parse the data the way you want it
result.add(Item.fromJson(item));
}
//that should be your disered list
return result;
}
The FilterChip class provides a multiple select chip. Using FutureBuilder we can fetch future data and build the chips list. We can also call the API first, and then map the results with the filter chips.
Here is an example of a FilterChip, where chips are populated from an API using FutureBuilder:
import 'dart:convert';
import 'package:filterchip_sample/album.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'FilterChip Sample',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'FilterChip Sample'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool favorite = false;
final List<int> _filters = <int>[];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
children: <Widget>[
FutureBuilder<List<Album>>(
future: _fetchAlbums(),
builder:
(BuildContext context, AsyncSnapshot<List<Album>> snapshot) {
Widget result;
if (snapshot.hasData) {
result = Wrap(
spacing: 5.0,
children: snapshot.data!.map((Album album) {
return FilterChip(
label: Text(album.title),
selected: _filters.contains(album.id),
onSelected: (bool value) {
setState(() {
if (value) {
if (!_filters.contains(album.id)) {
_filters.add(album.id);
}
} else {
_filters.removeWhere((int id) {
return id == album.id;
});
}
});
},
);
}).toList(),
);
} else if (snapshot.hasError) {
result = Text('Error: ${snapshot.error}');
} else {
result = const Text('Awaiting result...');
}
return result;
},
),
],
),
),
);
}
Future<List<Album>>? _fetchAlbums() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/'));
if (response.statusCode == 200) {
var json = jsonDecode(response.body);
var albums = List<Album>.from(json.map((i) => Album.fromJson(i)));
return albums;
} else {
throw Exception('Failed to get albums');
}
}
}

Got "The caller does not have permission [403]" when we call apps-script api

Hi every one I am working on google apps-script Api.
import 'package:flutter/material.dart';
import 'package:googleapis/script/v1.dart';
import 'package:googleapis_auth/auth_io.dart';
class ApiTest extends StatefulWidget {
#override
_ApiTestState createState() => _ApiTestState();
}
class _ApiTestState extends State<ApiTest> {
var accountCredentials = new ServiceAccountCredentials.fromJson({
"type": "service_account",
"project_id": "xxxxxxxxx",
"private_key_id": "xxxxxxxxxxxxxxx",
"private_key":
"-----BEGIN PRIVATE KEY-----\nMIIExxxxxxxxxxxxxxxxDJlUBIRuMwo=\n-----END PRIVATE KEY-----\n",
"client_email": "xxxxxxx#yyyyyy.iam.gserviceaccount.com",
"client_id": "0000000000000",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url":
"https://www.googleapis.com/robot/v1/metadata/x509/xxxxxxx%40yyyyyy.iam.gserviceaccount.com"
});
List<String> scopes = [
"https://www.googleapis.com/auth/documents.currentonly",
"https://www.googleapis.com/auth/script.scriptapp",
"https://www.googleapis.com/auth/script.storage",
"https://www.googleapis.com/auth/drive.readonly",
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/script.send_mail",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/sqlservice"
];
#override
void initState() {
super.initState();
main();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Center(child: Text("Hello Worlds")),
),
);
}
void main() {
clientViaServiceAccount(accountCredentials, scopes).then((http_client) {
var service = new ScriptApi(http_client);
ExecutionRequest request = new ExecutionRequest();
request.function = "projectSummary";
service.scripts.run(
request, "1C9zxs82nICdyH_O8BMIU9vLpFLmDIZmzw5-3HVnJRvusrr8zMa8nIKXV");
});
}
}
I have done.
Deploy the script project as an API executable.
Provide a properly scoped OAuth token for the execution.
Ensure that the script and the calling application share a common Cloud Platform (GCP)
project.
Enable the Google Apps Script API
Scopes used in project
I Got Response :- status: 403, message: The caller does not have permission
Please guide me why I got this error.
Hi everyone I got the solution.
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:googleapis/drive/v3.dart' as ga;
import 'package:googleapis/script/v1.dart';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Google Drive',
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: MyHomePage(title: 'Google Drive'),
);
}
}
class GoogleHttpClient extends IOClient {
Map<String, String> _headers;
GoogleHttpClient(this._headers) : super();
#override
Future<http.StreamedResponse> send(http.BaseRequest request) =>
super.send(request..headers.addAll(_headers));
#override
Future<http.Response> head(Object url, {Map<String, String> headers}) =>
super.head(url, headers: headers..addAll(_headers));
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final storage = new FlutterSecureStorage();
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn(scopes: [
'https://www.googleapis.com/auth/drive.appdata',
"https://www.googleapis.com/auth/documents.currentonly",
"https://www.googleapis.com/auth/script.scriptapp",
"https://www.googleapis.com/auth/script.storage",
"https://www.googleapis.com/auth/drive.readonly",
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/script.send_mail",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/sqlservice"
]);
GoogleSignInAccount googleSignInAccount;
ga.FileList list;
var signedIn = false;
Future<void> _loginWithGoogle() async {
signedIn = await storage.read(key: "signedIn") == "true" ? true : false;
googleSignIn.onCurrentUserChanged
.listen((GoogleSignInAccount googleSignInAccount) async {
if (googleSignInAccount != null) {
_afterGoogleLogin(googleSignInAccount);
}
});
if (signedIn) {
try {
googleSignIn.signInSilently().whenComplete(() => () {});
} catch (e) {
storage.write(key: "signedIn", value: "false").then((value) {
setState(() {
signedIn = false;
});
});
}
} else {
final GoogleSignInAccount googleSignInAccount =
await googleSignIn.signIn();
_afterGoogleLogin(googleSignInAccount);
}
}
Future<void> _afterGoogleLogin(GoogleSignInAccount gSA) async {
googleSignInAccount = gSA;
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final AuthResult authResult = await
_auth.signInWithCredential(credential);
final FirebaseUser user = authResult.user;
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
print('signInWithGoogle succeeded: $user');
storage.write(key: "signedIn", value: "true").then((value) {
setState(() {
signedIn = true;
});
});
}
void _logoutFromGoogle() async {
googleSignIn.signOut().then((value) {
print("User Sign Out");
storage.write(key: "signedIn", value: "false").then((value) {
setState(() {
signedIn = false;
});
});
});
}
Future<void> _callApi() async {
var client = GoogleHttpClient(await googleSignInAccount.authHeaders);
var service = new ScriptApi(client);
ExecutionRequest request = new ExecutionRequest();
request.function = "functionName";
var scriptId="1C9zxs82nICdyH_O8BMIU9vLpFLmDIZmzw5-3HVnJRvusrr8zMa8nIKXV";
try {
service.scripts.run(request,scriptId).then((op) {
op.response.forEach((key, value) {
print("key: $key");
print("value: $value");
});
});
} catch (err) {
print('error err');
print(err);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
(signedIn
? FlatButton(
child: Text('Call Api'),
onPressed: _callApi,
color: Colors.green,
)
: Container()),
(signedIn
? FlatButton(
child: Text('Google Logout'),
onPressed: _logoutFromGoogle,
color: Colors.green,
)
: FlatButton(
child: Text('Google Login'),
onPressed: _loginWithGoogle,
color: Colors.red,
)),
],
),
),
);
}
}

Flutter switch toggles off on its own

I have created a flutter starter kit that allowes me to switch between themes in-app.
Now this works great but there is a small issue.
I have placed the switch button in the settings screen,
but when I go to another screen and then back to the settings screen
- it would seem that the switch button goes to Off mode on its own.
I'm attaching an image and my code on github so that you guys can see what I mean.
class ThemeSwitchState extends State {
bool switchControl = false;
Future<bool> darkMode() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.getBool("isDark");
}
#override
Widget build(BuildContext context) {
return FutureBuilder<bool>(
future: darkMode(),
builder: (context, _snapshot) {
return Transform.scale(
scale: 1.5,
child: Switch(
value: _snapshot.data ?? false,
onChanged: (value) {
save(value);
setState(() {
});
},
activeColor: CustomColors().duskBlue,
activeTrackColor: CustomColors().noroGrey,
inactiveThumbColor: CustomColors().lureGrey,
inactiveTrackColor: CustomColors().noroGrey,
),
);
},
);
}
void save(bool value) async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
await sharedPreferences.setBool("isDark", value);
}
void toggleSwitch(bool value) {
ThemeChanger _themeChanger =
Provider.of<ThemeChanger>(context, listen: false);
if (switchControl == false) {
setState(() {
switchControl = true;
});
print('Theme is Dark');
_themeChanger.setTheme(CustomThemes.darkTheme.copyWith(
textTheme:
CustomThemes.darkTextTheme(CustomThemes.darkTheme.textTheme)));
} else {
setState(() {
switchControl = false;
});
print('Theme is Light');
_themeChanger.setTheme(CustomThemes.lightTheme.copyWith(
textTheme:
CustomThemes.lightTextTheme(CustomThemes.lightTheme.textTheme)));
}
}
}
You can use SharedPreferences from https://pub.dev/packages/shared_preferences
to save the last value of the CheckBox
I wrote an example
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Settings extends StatefulWidget {
#override
_SettingsState createState() => _SettingsState();
}
class _SettingsState extends State<Settings> {
Future<bool> darkMode() async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.getBool("isNight");
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
Text("Night Mode"),
FutureBuilder<bool>(
future: darkMode(),
builder: (context, _snapshot){
return Checkbox(
value: _snapshot.data ?? false,
onChanged: (value){
save(value);
setState(() {
toggleSwitch(value);
});
},
);
},
)
],
),
),
);
}
void save(bool value) async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
await sharedPreferences.setBool("isNight", value);
}
}
EDIT: WITH SWITCH
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Settings extends StatefulWidget {
#override
_SettingsState createState() => _SettingsState();
}
class _SettingsState extends State<Settings> {
Future<bool> darkMode() async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.getBool("isNight");
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
Text("Night Mode"),
FutureBuilder<bool>(
future: darkMode(),
builder: (context, _snapshot){
return Switch(
value: _snapshot.data ?? false,
onChanged: (value){
save(value);
setState(() {
});
},
);
},
)
],
),
),
);
}
void save(bool value) async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
await sharedPreferences.setBool("isNight", value);
}
}
UPDATE use value instead of switchControl
void toggleSwitch(bool value) {
ThemeChanger _themeChanger =
Provider.of<ThemeChanger>(context, listen: false);
if (value) {
setState(() {
switchControl = true;
});
print('Theme is Dark');
_themeChanger.setTheme(CustomThemes.darkTheme.copyWith(
textTheme:
CustomThemes.darkTextTheme(CustomThemes.darkTheme.textTheme)));
} else {
setState(() {
switchControl = false;
});
print('Theme is Light');
_themeChanger.setTheme(CustomThemes.lightTheme.copyWith(
textTheme:
CustomThemes.lightTextTheme(CustomThemes.lightTheme.textTheme)));
}
}
}

Categories

Resources