Flutter - How to write a file from assets? - android

What I need is to "edit" a text file that is on my assets folder.
To read a file from assets I can use this:
`Future<String> setFileData(String path) async {
return await rootBundle.loadString(path);
}`
But how can I write that file from the same path?

This document can help you:
Read and write files - Flutter
Complete example
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(
MaterialApp(
title: 'Reading and Writing Files',
home: FlutterDemo(storage: CounterStorage()),
),
);
}
class CounterStorage {
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/counter.txt');
}
Future<int> readCounter() async {
try {
final file = await _localFile;
// Read the file
String contents = await file.readAsString();
return int.parse(contents);
} catch (e) {
// If encountering an error, return 0
return 0;
}
}
Future<File> writeCounter(int counter) async {
final file = await _localFile;
// Write the file
return file.writeAsString('$counter');
}
}
class FlutterDemo extends StatefulWidget {
final CounterStorage storage;
FlutterDemo({Key key, #required this.storage}) : super(key: key);
#override
_FlutterDemoState createState() => _FlutterDemoState();
}
class _FlutterDemoState extends State<FlutterDemo> {
int _counter;
#override
void initState() {
super.initState();
widget.storage.readCounter().then((int value) {
setState(() {
_counter = value;
});
});
}
Future<File> _incrementCounter() {
setState(() {
_counter++;
});
// Write the variable as a string to the file.
return widget.storage.writeCounter(_counter);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Reading and Writing Files')),
body: Center(
child: Text(
'Button tapped $_counter time${_counter == 1 ? '' : 's'}.',
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Related

How do I migrate this path to download path?

I have this code and i want to migrate this to create the folder into downloads path, so i do not need to get ManageExternal Permission, can Anyone help me with what i should change? so i will not need to set the especial permission, then i could use the app in the newest sdks version
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Folder Storage',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final Dio dio = Dio();
bool loading = false;
double progress = 0;
so here is where i set the permission to read external storage
Future<bool> saveVideo(String url, String fileName) async {
Directory? directory;
try {
if (Platform.isAndroid) {
if (await _requestPermission(Permission.storage)) {
directory = await getExternalStorageDirectory();
String newPath = "";
print(directory);
List<String> paths = directory!.path.split("/");
for (int x = 1; x < paths.length; x++) {
String folder = paths[x];
if (folder != "Android") {
newPath += "/" + folder;
} else {
break;
}
}
newPath = newPath + "/RPSApp";
directory = Directory(newPath);
} else {
return false;
}
} else {
if (await _requestPermission(Permission.photos)) {
directory = await getTemporaryDirectory();
} else {
return false;
}
}
File saveFile = File(directory.path + "/$fileName");
if (!await directory.exists()) {
await directory.create(recursive: true);
}
if (await directory.exists()) {
await dio.download(url, saveFile.path,
onReceiveProgress: (value1, value2) {
setState(() {
progress = value1 / value2;
});
});
if (Platform.isIOS) {
await ImageGallerySaver.saveFile(saveFile.path,
isReturnPathOfIOS: true);
}
return true;
}
return false;
} catch (e) {
print(e);
return false;
}
}
Future<bool> _requestPermission(Permission permission) async {
if (await permission.isGranted) {
return true;
} else {
var result = await permission.request();
if (result == PermissionStatus.granted) {
return true;
}
}
return false;
}
downloadFile() async {
setState(() {
loading = true;
progress = 0;
});
bool downloaded = await saveVideo(
"https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4",
"video.mp4");
if (downloaded) {
print("File Downloaded");
} else {
print("Problem Downloading File");
}
setState(() {
loading = false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('AppBar Demo'),
),
body: Center(
child: loading
? Padding(
padding: const EdgeInsets.all(8.0),
child: LinearProgressIndicator(
minHeight: 10,
value: progress,
),
)
: ElevatedButton.icon(
icon: const Icon(
Icons.download_rounded,
color: Colors.white,
),
onPressed: downloadFile,
label: const Text(
"Download Video",
style: TextStyle(color: Colors.white, fontSize: 25),
)),
),
);
}
}

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;

How to Retrieve Image/ Screenshot from Application Document Directory Flutter?

I'm trying to build an in app gallery function where I can screenshot certain widgets in the app and then display it inside the app's internal gallery screen. Currently, I am using the Flutter screenshot package and then I save the screenshot to the Application document directory path. But how do I retrieve the images back and display them later on the app again?
Here's how I've done it before using the path_provider package.
(this is only for one image, but you can adapt the code to retrieve multiple images).
Create an uninitialized variable:
Image? image;
then, in the initState:
void initState() {
_loadImage();
super.initState();
}
Here is the _loadImage()
Future<void> _loadImage() async {
final path = await imagePath;
final _doesTheImageExist = File('${path}/qr.png').existsSync();
print(_doesTheImageExist);
if (_doesTheImageExist == true) {
setState(() {
image = Image.file(File("${path}/qr.png"));
});
} else {
print('no');
setState(() {
image = null;
});
}
}
Create a getter to get the image path imagePath:
Future<String> get imagePath async {
final directory = (await getApplicationDocumentsDirectory()).path;
return '$directory/qr.png';
}
then, create a function to save the image to the device:
Future<void> _captureAndSaveQRCode() async {
final imageDirectory = await imagePath;
await _screenshotController.captureAndSave(imageDirectory,
fileName: 'qr.png');
await _loadImage();
// setState(() {});
}
Here is the complete runnable example:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:screenshot/screenshot.dart';
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Scaffold(
body: QrCode(),
),
);
}
}
class QrCode extends StatefulWidget {
const QrCode({Key? key}) : super(key: key);
#override
State<QrCode> createState() => _QrCodeState();
}
class _QrCodeState extends State<QrCode> {
final _screenshotController = ScreenshotController();
Image? image;
#override
Widget build(BuildContext context) {
return Scaffold(
body: image != null
? Center(
child: Padding(
padding: const EdgeInsets.only(
top: 100.0,
),
child: Column(
children: [
image!,
],
),
))
: Center(
child: Column(
children: [
TextButton(
onPressed: _captureAndSaveQRCode,
child: Text("Save QrCode")),
Screenshot(
controller: _screenshotController,
child: _buildQRImage('data'))
],
),
),
);
}
Widget _buildQRImage(String data) {
return QrImage(
data: data,
size: 250.0,
version: QrVersions.auto,
errorCorrectionLevel: QrErrorCorrectLevel.H,
gapless: false,
foregroundColor: Colors.black,
backgroundColor: Colors.white,
);
}
Future<String> get imagePath async {
final directory = (await getApplicationDocumentsDirectory()).path;
return '$directory/qr.png';
}
Future<void> _loadImage() async {
final path = await imagePath;
final _doesTheImageExist = File('${path}/qr.png').existsSync();
print(_doesTheImageExist);
if (_doesTheImageExist == true) {
setState(() {
image = Image.file(File("${path}/qr.png"));
});
} else {
setState(() {
image = null;
});
}
}
Future<void> _captureAndSaveQRCode() async {
final imageDirectory = await imagePath;
await _screenshotController.captureAndSave(imageDirectory,
fileName: 'qr.png');
await _loadImage();
}
#override
void initState() {
_loadImage();
super.initState();
}
}

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),
),
)
),
);
}
}

Reading an image file from device storage and converting to Base64 results in an invalid base64 in Flutter

I'm trying to read file from a known path get base64 string from the image. I still don't understand why base64 is broken. This happens only in flutter code.
I did try doing the same conversion using a simple dart program i got the desired base64 string. This issue is happening in flutter.
onPressed: () async {
File imageFile =
await ImagePicker.pickImage(source: ImageSource.camera);
if (imageFile != null) {
Uint8List bytes = await imageFile.readAsBytes();
String base64data = base64.encode(bytes);
print(base64data);
}
}
Following is my console output.
W/ExifInterface(15331): Skip the tag entry since tag number is not defined: 2
W/ExifInterface(15331): Stop reading file since a wrong offset may cause an infinite loop: 0
I/chatty (15331): uid=10271(com.crowdanalytix.datax_app) Binder:15331_5 identical 2 lines
W/ExifInterface(15331): Stop reading file since a wrong offset may cause an infinite loop: 0
I/flutter (15331): /9j/4QGLRXhpZgAATU0AKgAAAAgACAEAAAQAAAABAAAKMgEQAAIAAAAOAAAAbgEBAAQAAAABAAASIAEPAAIAAAAIAAAAfIdpAAQAAAABAAAAmAESAAMAAAABAAAAAAEyAAIAAAAUAAAAhIglAAQAAAABAAABCgAAAABPTkVQTFVTIEEzMDAzAE9uZVBsdXMAMjAxOTowOTowMiAxOTo0MDo1MgAAB6QDAAMAAAABAAAAAIgnAAMAAAABD6AAAJIKAAUAAAABAAAA8oKaAAUAAAABAAAA+pIJAAMAAAABABAAAJIIAAQAAAABAAAAAIKdAAUAAAABAAABAgAAAAAAAAGqAAAAZAAAAkwAACcQAABOIAAAJxAAAQAFAAEAAAAHAAABHAAAAAAyMDAvMTAwAAQBEAACAAAADgAAAVkBDwACAAAACAAAAWcBEgADAAAAAQAAAAABMgACAAAAFAAAAW8AAAAAT05FUExVUyBBMzAwMwBPbmVQbHVzADIwMTk6MDk6MDIgMTk6NDA6NTIA/+AAEEpGSUYAAQEAAAEAAQAA/9sAQwABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB/9sAQwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB/8AAEQgSIAoyAwEiAAIRAQMRAf/EAB8AAAIDAQEBAQEBAQAAAAAAAAQFAwYHAggAAQkKC//EAF0QAAEBBAYHCAIBAwMDAQECHwIBAAMREgQhIjFBUQUyYXGBkfAGE0KhscHR4VLxIwcUYjNDchVTgghjkhYkc4OiNJOjF0RUstIlZISzwsPilMTTGHSkNVW01PP0/8QAHAEAAwEBAQEBAQAAAAAAAAAAAgMEAAEFBgcI/8QAQhEAAAQDBgUFAQEAAQQBAgENAAECEQMhMRJBUWFx8IG
Base64 string which i'm getting is invalid. Can someone try this?
I'm using a OnePlus3t (ONEPLUS A3003).
print function did not print everything.
you can see full result with debug mode
code snippet
List<int> imageBytes = await _imageFile.readAsBytes();
String base64Image = base64Encode(imageBytes);
print(base64Image);
Copy base64 string from debug mode and paste to online converter, you can see result is correct.
full code from offical demo and add base64 convert
// Copyright 2019 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:video_player/video_player.dart';
import 'dart:typed_data';
import 'package:image/image.dart' as ImageProcess;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image Picker Demo',
home: MyHomePage(title: 'Image Picker Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File _imageFile;
dynamic _pickImageError;
bool isVideo = false;
VideoPlayerController _controller;
String _retrieveDataError;
Future<void> _playVideo(File file) async {
if (file != null && mounted) {
await _disposeVideoController();
_controller = VideoPlayerController.file(file);
await _controller.setVolume(1.0);
await _controller.initialize();
await _controller.setLooping(true);
await _controller.play();
setState(() {});
}
}
void _onImageButtonPressed(ImageSource source) async {
if (_controller != null) {
await _controller.setVolume(0.0);
}
if (isVideo) {
final File file = await ImagePicker.pickVideo(source: source);
await _playVideo(file);
} else {
try {
_imageFile = await ImagePicker.pickImage(source: source);
List<int> imageBytes = await _imageFile.readAsBytes();
String base64Image = base64Encode(imageBytes);
print(base64Image);
setState(() {});
} catch (e) {
_pickImageError = e;
}
}
}
#override
void deactivate() {
if (_controller != null) {
_controller.setVolume(0.0);
_controller.pause();
}
super.deactivate();
}
#override
void dispose() {
_disposeVideoController();
super.dispose();
}
Future<void> _disposeVideoController() async {
if (_controller != null) {
await _controller.dispose();
_controller = null;
}
}
Widget _previewVideo() {
final Text retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_controller == null) {
return const Text(
'You have not yet picked a video',
textAlign: TextAlign.center,
);
}
return Padding(
padding: const EdgeInsets.all(10.0),
child: AspectRatioVideo(_controller),
);
}
Widget _previewImage() {
final Text retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_imageFile != null) {
return Image.file(_imageFile);
} else if (_pickImageError != null) {
return Text(
'Pick image error: $_pickImageError',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
Future<void> retrieveLostData() async {
final LostDataResponse response = await ImagePicker.retrieveLostData();
if (response.isEmpty) {
return;
}
if (response.file != null) {
if (response.type == RetrieveType.video) {
isVideo = true;
await _playVideo(response.file);
} else {
isVideo = false;
setState(() {
_imageFile = response.file;
});
}
} else {
_retrieveDataError = response.exception.code;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Platform.isAndroid
? FutureBuilder<void>(
future: retrieveLostData(),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
case ConnectionState.done:
return isVideo ? _previewVideo() : _previewImage();
default:
if (snapshot.hasError) {
return Text(
'Pick image/video error: ${snapshot.error}}',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
},
)
: (isVideo ? _previewVideo() : _previewImage()),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
onPressed: () {
isVideo = false;
_onImageButtonPressed(ImageSource.gallery);
},
heroTag: 'image0',
tooltip: 'Pick Image from gallery',
child: const Icon(Icons.photo_library),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
isVideo = false;
_onImageButtonPressed(ImageSource.camera);
},
heroTag: 'image1',
tooltip: 'Take a Photo',
child: const Icon(Icons.camera_alt),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
backgroundColor: Colors.red,
onPressed: () {
isVideo = true;
_onImageButtonPressed(ImageSource.gallery);
},
heroTag: 'video0',
tooltip: 'Pick Video from gallery',
child: const Icon(Icons.video_library),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
backgroundColor: Colors.red,
onPressed: () {
isVideo = true;
_onImageButtonPressed(ImageSource.camera);
},
heroTag: 'video1',
tooltip: 'Take a Video',
child: const Icon(Icons.videocam),
),
),
],
),
);
}
Text _getRetrieveErrorWidget() {
if (_retrieveDataError != null) {
final Text result = Text(_retrieveDataError);
_retrieveDataError = null;
return result;
}
return null;
}
}
class AspectRatioVideo extends StatefulWidget {
AspectRatioVideo(this.controller);
final VideoPlayerController controller;
#override
AspectRatioVideoState createState() => AspectRatioVideoState();
}
class AspectRatioVideoState extends State<AspectRatioVideo> {
VideoPlayerController get controller => widget.controller;
bool initialized = false;
void _onVideoControllerUpdate() {
if (!mounted) {
return;
}
if (initialized != controller.value.initialized) {
initialized = controller.value.initialized;
setState(() {});
}
}
#override
void initState() {
super.initState();
controller.addListener(_onVideoControllerUpdate);
}
#override
void dispose() {
controller.removeListener(_onVideoControllerUpdate);
super.dispose();
}
#override
Widget build(BuildContext context) {
if (initialized) {
return Center(
child: AspectRatio(
aspectRatio: controller.value?.aspectRatio,
child: VideoPlayer(controller),
),
);
} else {
return Container();
}
}
}

Categories

Resources