I am confused about how to use image_picker, this is how I use it in my application (like in many tutorials):
class AddDialogState extends State<AddDialog> {
File galleryFile;
Widget _onlyStatus() {
getLocalImage() async {
var _galleryFile = await ImagePicker.pickImage(
source: ImageSource.gallery
};
setState(() {
galleryFile = _galleryFile;
});
print(_galleryFile.path);
}
return Column(
........
FlatButton.icon(
onPressed: () {
getLocalImage();
}
)
)
}
#override
Widget build(BuildContext context) {
// fullscreen dialog
.........
body: _onlyStatus()
}
}
The problem was, the above code doesn't start ImagePicker, when i click the FlatButton, the above code just produce an error the getter 'path' was called on null, it doesn't start any new activity related to gallery, so what's wrong with my code?
Actually pickImage() is deprecated now. So you have to use ImagePicker.getImage(source: ImageSource.gallery)
Click here for more
void getImage(ImageSource imageSource) async {
PickedFile imageFile = await picker.getImage(source: imageSource);
if (imageFile == null) return;
File tmpFile = File(imageFile.path);
final appDir = await getApplicationDocumentsDirectory();
final fileName = basename(imageFile.path);
tmpFile = await tmpFile.copy('${appDir.path}/$fileName');
setState(() {
_image = tmpFile;
});
}
The code also store image file in device directory. Path pacakage is also used.
Here is my example you only need to call the SelectionItem and pass the required parameters and it's done, also it includes support for Android and iOS.
class SelectionItem {
String text;
GestureTapCallback action;
SelectionItem({
this.text,
this.action,
});
}
Widget _getOptionWidget(SelectionItem item) {
return SimpleDialogOption(
onPressed: item.action,
child: Text(item.text),
);
}
Widget _getCupertinoOptionWidget(SelectionItem item) {
return CupertinoActionSheetAction(
onPressed: item.action,
child: Text(item.text),
);
}
showSelector(
BuildContext context, {
String title,
List<SelectionItem> actions,
}) {
bool isAndroid = Injector.instance.platform == Platform.ANDROID;
if (isAndroid) {
final items = actions.map((action) => _getOptionWidget(action)).toList();
return SimpleDialog(
title: Text(title),
children: items,
);
} else {
final items =
actions.map((action) => _getCupertinoOptionWidget(action)).toList();
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
CupertinoActionSheet(
title: Text(title),
actions: items,
cancelButton: CupertinoActionSheetAction(
onPressed: () {
NavigationUtils.pop(context);
},
child: Text("Cancel"),
),
),
],
);
}
}
your showDialog should be something like this:
Container(
width: 300,
height: 300,
child: GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) => showSelector(
context,
"Select",
actions: [
SelectionItem(
"Camera",
action: () {
getImage(ImageSource.camera);
Navigator.of(context).pop();
},
),
SelectionItem(
"Gallery",
action: () {
getImage(ImageSource.gallery);
Navigator.of(context).pop();
},
)
],
),
);
},
),
)
Here is my code for image_picker: ^0.8.4+4 (flutter 2.8.1)
bool hasImage = false;
File? image;
Future getImage(ImageSource source) async {
try {
final image = await ImagePicker().pickImage(source: source);
if (image == null) return;
final imageTemporary = File(image.path);
setState(() {
this.image = imageTemporary;
hasImage = true;
});
} on PlatformException catch (e) {
debugPrint('Failed to pick image: $e');
}
}
Related
i'm using permission_handler package to get the location
i want to display this message is the user denied the location
like this image
check image
this is the code
Future<bool> getUserLocation() async {
final loc = await Permission.location.request();
final locWhenUse = await Permission.locationWhenInUse.request();
try {
if (loc == PermissionStatus.permanentlyDenied ||
locWhenUse == PermissionStatus.permanentlyDenied) {
//i want to show the pop up like image here
setState(() {
error = "Please enable location permission".tr;
});
return false;
}
if (await userLocation.getUserLocation() == null) {
throw Exception();
}
} on Exception {
setState(() {
error = "Something went wrong".tr;
});
return false;
} catch (e) {
setState(() {
error = "Error Happened while Getting your Location".tr;
});
return false;
}
return true;
}
getLocation() async {
Location location = Location();
bool _serviceEnabled;
PermissionStatus _permissionGranted;
LocationData _locationData;
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
_locationData = await location.getLocation();
print(_locationData.longitude)
}
i solved the problem by create a custom dialog like the image i attached
so if the premission is denied, i will show this dialog
Future<bool> showAlertDialog({
required BuildContext context,
}) async {
if (!Platform.isIOS) {
return await showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Location Services Disabled'),
content: const Text('You need to enable Location Services in Setting'),
actions: <Widget>[
TextButton(
child: const Text('Cancel'),
onPressed: () => Navigator.of(context).pop(false),
),
TextButton(
child: const Text('Setting'),
onPressed: () {
openAppSettings();
Navigator.of(context).pop(false);
},
),
],
),
);
}
// todo : showDialog for ios
return await showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: const Text('Location Services Disabled'),
content: const Text('You need to enable location services in setting'),
actions: <Widget>[
CupertinoDialogAction(
child: const Text('Cancel'),
onPressed: () => Navigator.of(context).pop(false),
),
CupertinoDialogAction(
child: const Text('Setting'),
onPressed: () {
openAppSettings();
Navigator.of(context).pop(false);
},
),
],
),
);
}
My code is view the pdf using by flutter_pdfview from online url. Opening the pdf is no issue. So I wrote the pagination at floatingActionButton. There is "Previous", "Page / Total Page" and "Next". If click page button, Alert Dialog box pop up and user can enter the page and can go to specified page. It is working on iOS. But at Android, after enter the page number on Dialog and click "Move" button and then dialog return the entered value and set the page number at
await snapshot.data!.setPage(pageNumber - 1);
But it is not call the PDFView's onPageChanged. If I don't call the dialog and just simply call snapshot.data!.setPage(pageNumber - 1), it is working.
I think something wrong with dialog.
May I know why it is only happening on android and only happening if set the page number return from dialog?
First Pdf page
Dialog to enter page number
Full source code
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:thitsarparami/helper/enum.dart';
import 'package:thitsarparami/widgets/circular_progress_indicator_widget.dart';
class PdfView extends StatefulWidget {
final String url;
final LoadPDF loadPDF;
final String title;
const PdfView(
{Key? key, required this.title, required this.url, required this.loadPDF})
: super(key: key);
#override
State<PdfView> createState() => _PdfViewerState();
}
class _PdfViewerState extends State<PdfView> with WidgetsBindingObserver {
String? path;
bool _isLoading = true;
TextEditingController? textController;
final Completer<PDFViewController> _controller =
Completer<PDFViewController>();
int? pages = 0;
int? currentPage = 0;
bool isReady = false;
String errorMessage = '';
bool isButtonActive = false;
loadDocument() async {
String fileName = widget.url.split("/").last;
switch (widget.loadPDF) {
case LoadPDF.assets:
fromAsset(widget.url, fileName).then((f) {
setState(() {
path = f.path;
_isLoading = false;
});
});
break;
case LoadPDF.url:
createFileOfPdfUrl().then((f) {
setState(() {
path = f.path;
_isLoading = false;
});
});
break;
case LoadPDF.file:
File file = File(widget.url);
setState(() {
path = file.path;
_isLoading = false;
});
break;
}
}
Future<File> createFileOfPdfUrl() async {
Completer<File> completer = Completer();
//print("Start download file from internet!");
try {
final url = widget.url;
final filename = url.substring(url.lastIndexOf("/") + 1);
var request = await HttpClient().getUrl(Uri.parse(url));
var response = await request.close();
var bytes = await consolidateHttpClientResponseBytes(response);
var dir = await getApplicationDocumentsDirectory();
//print("Download files");
//print("${dir.path}/$filename");
File file = File("${dir.path}/$filename");
await file.writeAsBytes(bytes, flush: true);
completer.complete(file);
} catch (e) {
throw Exception('Error parsing asset file!');
}
return completer.future;
}
Future<File> fromAsset(String asset, String filename) async {
// To open from assets, you can copy them to the app storage folder, and the access them "locally"
Completer<File> completer = Completer();
try {
var dir = await getApplicationDocumentsDirectory();
File file = File("${dir.path}/$filename");
var data = await rootBundle.load(asset);
var bytes = data.buffer.asUint8List();
await file.writeAsBytes(bytes, flush: true);
completer.complete(file);
} catch (e) {
throw Exception('Error parsing asset file!');
}
return completer.future;
}
#override
void initState() {
super.initState();
loadDocument();
textController = TextEditingController();
}
#override
void dispose() {
textController?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
appBar: AppBar(
centerTitle: true,
backgroundColor: Theme.of(context).backgroundColor,
elevation: 0,
title: AutoSizeText(
widget.title,
style: Theme.of(context).appBarTheme.titleTextStyle,
),
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.arrow_back,
color: Theme.of(context).primaryIconTheme.color!,
),
),
),
body: Center(
child: _isLoading
? const CircularProgressIndicatorWidget()
: PDFView(
filePath: path,
enableSwipe: true,
swipeHorizontal: false,
autoSpacing: false,
pageFling: true,
pageSnap: true,
defaultPage: currentPage!,
fitPolicy: FitPolicy.BOTH,
preventLinkNavigation:
false, // if set to true the link is handled in flutter
onRender: (_pages) {
setState(() {
pages = _pages;
isReady = true;
});
},
onError: (error) {
setState(() {
errorMessage = error.toString();
});
//print(error.toString());
},
onPageError: (page, error) {
setState(() {
errorMessage = '$page: ${error.toString()}';
});
//print('$page: ${error.toString()}');
},
onViewCreated: (PDFViewController pdfViewController) {
_controller.complete(pdfViewController);
},
onLinkHandler: (String? uri) {
//print('goto uri: $uri');
},
onPageChanged: (int? page, int? total) {
//print('page change: $page/$total');
setState(
() {
currentPage = page;
},
);
},
),
),
floatingActionButton: FutureBuilder<PDFViewController>(
future: _controller.future,
builder: (context, AsyncSnapshot<PDFViewController> snapshot) {
if (snapshot.hasData) {
return FloatingActionButton.extended(
label: Row(
children: [
IconButton(
icon: Icon(Icons.navigate_before,
color: (currentPage! > 0) ? Colors.white : Colors.grey),
onPressed: (currentPage! < pages!)
? () async {
await snapshot.data!.setPage(currentPage! - 1);
}
: null,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
side: const BorderSide(
color: Colors.white,
),
minimumSize: Size.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
onPressed: () async {
final result = await openDialog();
if (result == null || result.isEmpty) return;
int pageNumber = int.parse(result);
await snapshot.data!.setPage(pageNumber - 1);
},
child: Text("${currentPage! + 1}"),
),
Text(" / $pages"),
IconButton(
icon: Icon(Icons.navigate_next,
color: (currentPage! + 1 < pages!)
? Colors.white
: Colors.grey),
onPressed: (currentPage! < pages!)
? () async {
await snapshot.data!.setPage(currentPage! + 1);
}
: null,
),
],
),
onPressed: null,
);
}
return Container();
},
),
);
}
Future<String?> openDialog() => showDialog<String>(
context: context,
builder: (context) => StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: const Text('Go to page'),
content: TextField(
autofocus: true,
decoration: const InputDecoration(hintText: 'Page number'),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
controller: textController,
onChanged: (value) {
if (value.isNotEmpty) {
int pageNumber = int.parse(value);
setState(() {
isButtonActive = pageNumber < pages!;
});
}
},
onSubmitted: (_) => gotToPage(),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
textController?.clear();
},
child: const Text('Cancel'),
),
TextButton(
style: TextButton.styleFrom(
onSurface: Theme.of(context).primaryColor),
onPressed: isButtonActive
? () {
gotToPage();
textController?.clear();
}
: null,
child: const Text('Move'),
),
],
);
},
),
);
void gotToPage() {
Navigator.of(context).pop(textController?.text);
}
}
I am not sure why this error occurred in android. It is happening because opening the keyboard. So Now I am using number picker and it is working now.
I need help regrading the scan using qr_code_scanner, the scanner successful but don't know how to call response either success or not. here example.
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) async {
controller.pauseCamera();
var response = await ScanApi.scan(scanData.code);
print(response);
result = scanData;
setState(() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("check"),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('Data: ${scanData.code}'),
],
),
),
actions: <Widget>[
TextButton(
child: Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
).then((value) => controller.resumeCamera());
and my example api post to get reponse.
static Future<dynamic> scan() async {
final url = Uri.parse(url);
final response = await http.post(url);
if (response.statusCode == 200) {
final String msg = json.decode(response.body)["status"];
print(msg);
return msg;
} else {
throw Exception();
}}
code like this and calling this class into widget.
class ScanResponse {
String status;
ScanResponse({this.status});
factory ScanResponse.fromJson(Map<String, dynamic> jsonData) {
return ScanResponse(
status: jsonData['status'],
);
}
}
I'm trying to capture a video and upload it to firebase storage.
The problem is, the recorded video format is .mov and this format seems to be incompatible with browsers.
How could I convert the recorded file to .mp4?
Below is the code I use to record and upload my videos.
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:video_player/video_player.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:path_provider/path_provider.dart';
class CameraTestPage extends StatefulWidget {
const CameraTestPage({Key? key}) : super(key: key);
#override
_CameraTestPageState createState() => _CameraTestPageState();
}
class _CameraTestPageState extends State<CameraTestPage> {
List<CameraDescription>? cameras;
CameraController? controller;
bool frontCamera = false;
XFile? videoFile;
VideoPlayerController? videoController;
VoidCallback? videoPlayerListener;
#override
void initState() {
initCamera();
super.initState();
}
initCamera() async {
if (cameras == null) {
cameras = await availableCameras();
}
if (controller?.value.isInitialized ?? false) {
controller!.dispose();
}
controller = CameraController(
cameras!.firstWhere(
(element) => element.lensDirection == (frontCamera ? CameraLensDirection.front : CameraLensDirection.back),
),
ResolutionPreset.medium,
enableAudio: false,
);
controller!.initialize().then((value) {
setState(() {});
});
}
void onVideoRecordButtonPressed() {
startVideoRecording().then((_) {
if (mounted) setState(() {});
});
}
void onStopButtonPressed() {
stopVideoRecording().then((file) {
if (mounted) setState(() {});
if (file != null) {
print('Video recorded to ${file.path}');
videoFile = file;
_startVideoPlayer();
}
});
}
Future<void> _startVideoPlayer() async {
if (videoFile == null) {
return;
}
final VideoPlayerController vController = VideoPlayerController.file(File(videoFile!.path));
videoPlayerListener = () {
if (videoController != null && videoController!.value.size != null) {
// Refreshing the state to update video player with the correct ratio.
if (mounted) setState(() {});
videoController!.removeListener(videoPlayerListener!);
}
};
vController.addListener(videoPlayerListener!);
await vController.setLooping(true);
await vController.initialize();
await videoController?.dispose();
if (mounted) {
setState(() {
videoController = vController;
});
}
await vController.play();
}
Future<void> startVideoRecording() async {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isInitialized) {
print('Error: select a camera first.');
return;
}
if (cameraController.value.isRecordingVideo) {
// A recording is already started, do nothing.
return;
}
try {
await cameraController.startVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
return;
}
}
Future<XFile?> stopVideoRecording() async {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isRecordingVideo) {
return null;
}
try {
return cameraController.stopVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
return null;
}
}
void _showCameraException(CameraException e) {
print('Error: ${e.code}\n${e.description}');
}
_uploadVideo() async {
Reference ref = FirebaseStorage.instance.ref("test/test.mov");
UploadTask uploadTask = ref.putFile(File(videoFile!.path), SettableMetadata(contentType: 'video/mov'));
print("uploading");
uploadTask.whenComplete(() async {
String downloadUrl = await ref.getDownloadURL();
print("download url: $downloadUrl");
});
}
Widget _thumbnailWidget() {
final VideoPlayerController? localVideoController = videoController;
return Expanded(
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
child: (localVideoController == null)
? Center(
child: Container(
child: Text("none"),
),
)
: Container(
child: AspectRatio(
aspectRatio: localVideoController.value.aspectRatio,
child: VideoPlayer(localVideoController),
),
decoration: BoxDecoration(
border: Border.all(color: Colors.pink),
),
),
),
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Camera Test")),
body: Column(
children: [
if (controller != null)
Container(
child: CameraPreview(controller!),
height: 400,
),
Row(
children: [
ElevatedButton(
onPressed: () {
frontCamera = !frontCamera;
initCamera();
},
child: Text("Switch"),
),
ElevatedButton(
onPressed: () {
controller?.value.isRecordingVideo ?? false ? onStopButtonPressed() : onVideoRecordButtonPressed();
},
child: Text(controller?.value.isRecordingVideo ?? false ? "Stop" : "Record"),
),
ElevatedButton(
onPressed: videoFile != null ? _uploadVideo : null,
child: Text("Upload video"),
),
],
),
_thumbnailWidget(),
],
),
);
}
}
You can use the video_compress package to convert the video to mp4.
Here is your _uploadVideo() method updated to include this:
_uploadVideo() async {
Reference ref = FirebaseStorage.instance.ref("test/test.mp4");
MediaInfo? mediaInfo = await VideoCompress.compressVideo(
videoFile!.path,
quality: VideoQuality.DefaultQuality,
deleteOrigin: false, // It's false by default
);
UploadTask uploadTask = ref.putFile(
File(mediaInfo!.path!), SettableMetadata(contentType: 'video/mp4'));
print("uploading");
uploadTask.whenComplete(() async {
String downloadUrl = await ref.getDownloadURL();
print("download url: $downloadUrl");
});
}
Ensure you import the package by including this line:
import 'package:video_compress/video_compress.dart';
I am showing i simple drop down but my options are not opening mean its not showing a dropdown.
I have a simple list like this
[352094083791878, 358480083322091, 358480081409924]
This is my code
class _SettingPageState extends State<SettingPage> {
bool isSwitched = false;
bool _shoW = true;
var items = [];
#override
void initState() {
super.initState();
getImi();
}
getImi() async {
final storage = new FlutterSecureStorage();
String userNumber = await storage.read(key: "userNumber");
String userPassword = await storage.read(key: "userPassword");
print('showimi');
print(userNumber);
print(userPassword);
var map = new Map<String, dynamic>();
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return Center(
child: SpinKitWave(
color: Color(0xff00abb5), type: SpinKitWaveType.center));
});
var url =
'http://api.igiinsurance.com.pk:8888/drive_api/login.php?number=${userNumber}&password=${userPassword}';
print(url);
http.Response res = await http.get(
url,
headers: <String, String>{'token': 'c66026133e80d4960f0a5b7d418a4d08'},
);
var data = json.decode(res.body.toString());
print(data);
if (data['status'].toString() == "Success") {
Navigator.pop(context);
_shoW = true;
data['data'].forEach((row) {
print(row['imei_number']);
items.add(row['imei_number']);
print(items);
});
} else {
Navigator.pop(context);
_shoW = false;
}
}
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Scaffold(
body: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("images/sidebg.png"), fit: BoxFit.cover),
),
child: Column(
children: [
_shoW
? DropdownButton(
hint: Text('Select Vechile'),
items: items.map((val) {
return DropdownMenuItem<String>(
value: val,
child: new Text(val),
);
}).toList(),
onChanged: null)
: Container()
],
),
),
);
}
}
I am simply adding values in the Items array. I need to show the array in the select down list. But it's not opening the options i have try to put static list but that's also not working .
You need to set onChanged to not null value. onChanged without listener cannot allow you to open list.
If you need to showing current selected value, pass value parameter to DropdownButton. Also you can find more examples in Official Flutter Documentation.
Change Your Code Like THis :
if (data['status'].toString() == "Success") {
Navigator.pop(context);
setState(){
_shoW = true;
}
data['data'].forEach((row) {
print(row['imei_number']);
items.add(row['imei_number']);
print(items);
});
} else {
Navigator.pop(context);
setState(){
_shoW = false;
}
}