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?
Related
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
File _image;
final picker = ImagePicker();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.camera);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
output :
D/MediaScannerConnection(16161): Scanned
/storage/emulated/0/Android/data/com.xxxx.xxxx/files/Pictures/9d9ed6a1-292c-428a-bf24-38ea1a58742c6940060118053310767.jpg
to null
This problem occurred to me too. I have found that somehow the captured image data is lost due to the MainActivity is killed after the image_picker finishes. To solve this, just add retrieve lost data handler. You can find the example code on the documentation here. (Refer section: Handling MainActivity destruction on Android #)
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!