I have a widget to take pictures on my app working like so:
final File imageFile =
await ImagePicker.pickImage(source: ImageSource.camera).then((test) {
print('TEST $test');
return test;
});
I can open the camera without any error and also take the picture but when I try to go back or accept the picture I've taken the app displays an white screen and the console show no errors at all.
This is failing on a real device (Xiaomi Redmi Note 8t) but it works on Android Emulator.
The only message I can see is Lost connection to device. when I take the camera
Fixed adding a try catch:
Future<Null> _pickImageFromCamera(BuildContext context, int index) async {
File imageFile;
try {
imageFile = await ImagePicker.pickImage(source: ImageSource.camera)
.then((picture) {
return picture; // I found this .then necessary
});
} catch (eror) {
print('error taking picture ${error.toString()}');
}
setState(() => this._imageFile = imageFile);
}
I found the solution for flutter 2
In Android
You need to add this to your 3 manifest (debug, main , profile)
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Then pick the image with a try catch, like this
Future getbehind() async {
try{
final pickedFile = await picker.getImage(source: (ImageSource.camera:ImageSource.gallery),)
.then((value) {
setState(() {
if (value != null) {
behind = File(value.path);
} else {
print('No image selected.');
}
});
});
}catch(e){
}
Run the app in a release mode and its done!
Related
I'm building an app that requires me to use the camera of the device. I have followed all the procedures to set it up via the Image Picker Documentation and I am still having issues.
Funny enough, it was working fine when I tested it last time but as I added new widgets to screen and tried testing again, the app crashed with very minimal error message which says:
Lost connection to device.
This is how I capture the image:
Future<void> _pickImage() async {
try {
bool isPermisionGranted = await _requestFilePermission();
if (!isPermisionGranted) {
showToast('Please give us access to your camera.');
return;
}
final image = await ImagePicker().pickImage(source: ImageSource.camera, imageQuality: 90);
if (image == null) return;
final tempImageFile = File(image.path);
setState(() {
_imageFile = tempImageFile;
});
if (!mounted) return;
Navigator.of(context).pushNamed(Routes.chi, arguments: {'image_file': _imageFile});
} on PlatformException catch (e) {
debugPrint('Failed to pick image: $e');
showToast('Failed to pick image');
}
}
Could this be a memory issue? And how can I resolve it?
im learning flutter and now tried to capture the photo with ImagePicker package from the following method, but after I successfully capture the photo, there is always 1 sec until app get the data and jump to next page:
Future pickImage(ImageSource source) async {
try {
var image = await ImagePicker().pickImage(source: source);
if (image == null) return;
final imagePermanent = await saveImagePermanently(image.path);
selectedImage = File(imagePermanent.path);
isUploaded.value = !isUploaded.value;
update();
} on PlatformException catch (e) {
print('Failed to pick image: $e');
}
}
Future<File> saveImagePermanently(String imagePath) async {
final directory = await getApplicationDocumentsDirectory();
final name = basename(imagePath);
final image = File('${directory.path}/$name');
return File(imagePath).copy(image.path);
}
now my solution is adding a listener onInit when image is created with GetX:
#override
void onInit() {
super.onInit();
ever(isUploaded, (value) {
Get.to(
() => AddPersonProfileAddDetails(),
);
});
}
So is there a way to detect the status of capturing the image like finished/failed/progressing, thanks for any clue or let me know a better way to jump to next page after capturing the image, thanks a lot!
In my flutter app, if the user is signing in for the first time, he will be directed to profile page where he gets to key in his personal details and upload his profile pic. now my issue is with the profile pic. First of all, Im using Image picker package.
Future pickImage(ImageSource source) async {
try {
final image = await ImagePicker().pickImage(
source: source);
if (image == null) return;
final UserImage = File(image.path);
setState(() => this.image = UserImage );
}on PlatformException catch (e){
Utils.showSnackBar(e.message);
}
}
But with this code alone, everytime the app gets restarted the image will be null. So I tried to upload the image to the Firebase Storage when the user picks an image and generate a url:
Future uploadImage () async {
FirebaseStorage storage = FirebaseStorage.instance;
Reference ref = storage.ref().child(userID.toString());
UploadTask uploadTask = ref.putFile(image!);
uploadTask.whenComplete(() async {
url = await ref.getDownloadURL(); }
).catchError((onError){
print(onError);
});
return url;
}
But again every time I restart the app, the url will be null.
What is the best way to save the image permenantly when the user signs in for the first time.
edit: I want to store the image locally so that the user doesnt need an internet connection to load the image everytime he open the app.
Your answers and responses are highly appreciated.
you need to get folder directory first
Future<String> getStorageDirectory() async {
if (Platform.isAndroid) {
return (await getExternalStorageDirectory()).path;
} else {
return (await getApplicationDocumentsDirectory()).path;
}
}
Add image in path
uploadImage() async{
String dir= getStorageDirectory();
File directory = new File("$dir");
if (directory.exists() != true) {
directory.create();
}
final image = await ImagePicker().pickImage(
source: source);
if (image == null) return;
final userImage = File(image.path);
var newFile = await userImage.writeAsBytes(/* image bytes*/);
await newFile.create();
}
My app crashes when calling "_submit" function 2 times in a row.
I can pick the picture from gallery and upload it to Firebase Storage but if I call it again the the whole app crashes.
From this button :
floatingActionButton: FloatingActionButton(
onPressed: () => _submit(),
Submit calls a Provider of type Database :
Future<void> _submit() async {
widget.database = Provider.of<Database>(context, listen: false);
await widget.database
.setPicture("regione/citta/comune/lavoro/IDArtista/profilo.png");
return;
}
That calls a function that uploads a picture taken from "imgGallery()" to the database :
Future<void> setPicture(String pathStorage) async {
try {
final File file = await imgFromGallery();
if (file == null) return;
TaskSnapshot task =
await FirebaseStorage.instance.ref(pathStorage).putFile(file);
String image_url = await task.ref.getDownloadURL();
return;
} catch (e) {
print(e);
return;
}
}
imgGallery :
Future<File> imgFromGallery() async {
try {
final ImagePicker _picker = ImagePicker();
final PickedFile imageFile =
await _picker.getImage(source: ImageSource.gallery, imageQuality: 50);
//If there is no image selected, return.
if (imageFile == null) return null;
//File created.
File tmpFile = File(imageFile.path);
//it gives path to a directory - path_provider package.
final appDir = await getApplicationDocumentsDirectory();
//filename - returns last part after the separator - path package.
final fileName = tmpFile.path.split('/').last;
//copy the file to the specified directory and return File instance.
return tmpFile = await tmpFile.copy('${appDir.path}/$fileName');
} catch (e) {
print(e);
return null;
}
}
EDIT : Solved using a real device instead of emulators.
Which device are you experiencing this in? I'm also having this error but only on iOS emulator. It has to do with the Image_Picker package and the FocusNode. Look at this issue on github
I'm facing a problem while using the plugins image_picker: "0.6.1+11" and
barcode_scan: "^1.0.0". Firstly I scan a barcode and then take a picture from the camera.
The problem is most of the times the android app restarts itself after taking image from the camera without any log. The log just prints "Lost connection to the device."
Here is the code:
Future scanCarton() async {
try {
String barcode = await BarcodeScanner.scan();
await getImage().then((imageFile){
if (imageFile != null){
Map<String,String>requestData = new Map<String,String>();
requestData["content"] = barcode;
requestData["type"] = "carton";
requestData["mode"] = "job";
if (widget.orderData.product_type.toLowerCase() == "batched"){
requestData["carton_id"] = "0";
}else{
requestData["carton_id"] = "${scannedCartonCount + 1}";
}
if(this.mounted){
setState(() {
_isLoading = true;
});
}else{
print("Gotcha 2");
}
upload(imageFile, UrlFile.UPLOAD_SCAN_IMAGE, "carton", requestData).then((value){
if(this.mounted){
setState(() {
_isLoading = false;
});
}else{
print("Gotcha 4");
}
incrementCartonCount();
if(widget.orderData.product_type.toLowerCase() == "batched"){
openNextCartonPopup();
}
});
}
});
} on PlatformException catch (e) {
if (e.code == BarcodeScanner.CameraAccessDenied) {
print('The user did not grant the camera permission!');
} else {
print('Unknown error $e') ;
}
} on FormatException{
print( 'null (User returned using the "back"-button before scanning anything. Result)');
} catch (e) {
print('Unknown error: $e');
}
}
You just need to configure to ask for permission beforehand.
For iOS, add the following keys to your Info.plist file, located at <project root>/ios/Runner/Info.plist:
NSPhotoLibraryUsageDescription - describes why your app needs permission for the photo library. This is called Privacy - Photo Library Usage Description in the visual editor.
NSCameraUsageDescription - describes why your app needs access to the camera. This is called Privacy - Camera Usage Description in the visual editor.
NSMicrophoneUsageDescription - describes why your app needs access to the microphone, if you intend to record videos. This is called Privacy - Microphone Usage Description in the visual editor.
In the same way, you need to add permissions in Android.
Try your method with dispose()
#override
void dispose() {
[your method name].dispose();
super.dispose();
}
I got the same issue and found the solution. If you have TextField and imager picker in the same page, please make sure the textfield is unfocused (the cursor should be gone from you TextField) when you pick image.
Do something like FocusScope.of(context).requestFocus(new FocusNode()); in your pickImage method.