SharedPreferences working on android emulator but not on real device - android

As said in the title, I have some bools and Strings stored in SharedPreferences. It work like a charm with the emulator and when i install my app on my real device, the bool and Strings are just not sotred. I'm using api 29 on the emulator and 30 on my device, can it be this? (I just checked and when debugging on my real phone it worked!! But still not when i'm installing the app with the apk file from the build task...)
Any ideas? I don't think my code will be very relevant here but if needeed I can add it!
Thanks for your help!
Also, the app is much heavier when debugging (almost 5 times) and much less smooth, any ideas why? maybe because of the SharedPrefs?
Edit of the code:
Switch(
value: appsLoad.instagram ?? false,
onChanged: (value) {
setState(() {
appsLoad.instagram = value;
sharedPref.save("user", appsLoad);
});
},
),
This is how i save the value, the sharePref.save refers to
save(String key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, json.encode(value) ?? false);
}
i used a lot of this website for the sharedPreferences.

If you read the setState comment section
Generally it is recommended that the setState method only be
used to wrap the actual changes to the state, not any computation
that might be associated with the change. For example, here a
value used by the [build] function is incremented, and then the
change is written to disk, but only the increment is wrapped in
the setState:
Future<void> _incrementCounter() async {
setState(() {
_counter++;
});
Directory directory = await getApplicationDocumentsDirectory();
final String dirName = directory.path;
await File('$dir/counter.txt').writeAsString('$_counter');
}
Following the example you shouldn't call the future inside setState
Switch(
value: appsLoad.instagram ?? false,
onChanged: (value) async {
setState(() {
appsLoad.instagram = value;
});
await sharedPref.save("user", appsLoad);
},
),
Take note an emulator doesn't run as fast as a device (with the profile/debug mode its slower than a real one) so that's why in an emulator you cannot perceive this kind of error

Related

expo-camera takePictureAsync() not working on Android

I recently updated several lines of code in a managed expo project, unrelated to the camera functionality. It still works fine on iOS, only Android does not work. I had released a previous version one month ago that worked well. When I revert back to the old commit from then, though, it also does not work on Android (iOS fine).
expo 44.0.6
expo-camera 12.1.2
react 17.0.1
react-native 0.64.3
There is no issue launching the camera, etc. Rather, the issue occurs at takePictureAsync, which hangs and then does not return anything.
const snapPic = async () => {
const { status } = await Camera.getCameraPermissionsAsync();
if (status != 'granted') {
alert('Please grant access to camera and retry.');
await Camera.requestCameraPermissionsAsync();
return;
}
const options = { quality: 0.1 };
const photo = await this.camera.takePictureAsync(options);
this.camera.pausePreview();
this.setState({imageSource: photo.uri});
};
<Camera style={styles.cameraBox} ref={ref => {this.camera = ref}} />
Please let me know what other information I can provide, if necessary. Thanks in advance!
Instead of pause preview method. Try it with skipProcessing to false inside option object

Flutter - How to know if user shared my app or not?

I have implemented the below given code to let user share my app. It works fine, but how can I know if the user actually shared my app or not? Because my app unlocks a certain feature if the user shares the app.
[Package used:- share_plus 3.0.4 ]
onTap: () async {
const _textShareUrl =
'https://www.youtube.com/watch?v=CNUBhb_cM6E&list=PLk6qkmrzOcdx5R4-UqI_jDPYsLWNnZ1dq&index=2';
await Share.share(
'Social share test\n\n$_textShareUrl');
Future.delayed(const Duration(seconds: 10), () {
setState(() => _share = true);
});
},
There is already an open issue:
https://github.com/fluttercommunity/plus_plugins/issues/386

React native: requestTechnology called only if the app is brought from background to foreground

I am currently working on a simple app for scanning, reading data from an NFC card (in my case a Mifare NFC card) and displaying in on the screen. I have built it using this example.
The app should work both on Android and iOS, but for the moment, I have tested it only on an android device (an Oppo device with NFC capablities and developer mode activated).
At the launch of the app, everything seems to be working fine, the NfcManager has been successfully started, but there is an issue when the app tries to request the technology for reading the card, namely, I have to bring the app first in the background and then again in the foreground so that the message requestTechnology success is displayed, otherwise, it's simply not called.
After this, the promise NfcManager.getTag() gets rejected with the error message: no reference available.
Here is my code:
componentDidMount() {
NfcManager.start({
onSessionClosedIOS: () => {
alert('ios session closed');
},
}).then(() => console.warn('NfcManager started')) // successfully started
.catch((error) => alert('Error starting NfcManager: ', error));
}
{... componentWillUnmount and render method ...}
_read = async () => {
try {
let tech = Platform.OS === 'ios'
? NfcTech.MifareIOS : [NfcTech.MifareClassic, NfcTech.NfcA, NfcTech.IsoDep, NfcTech.Ndef];
let resp = await NfcManager.requestTechnology(tech, {
alertMessage: 'Ready to do some custom Mifare cmd!'
})
.then((value) => alert('requestTechnology success', value)) // here the value is empty, so no NfcTech
.catch(() => console.warn('reuqestTechnology error'));
const tag = await NfcManager.getTag()
.then((value) => alert('Tag event: ', value))
.catch((err) => console.warn('error getting tag: ', err));
// this part of the code is reached, but not working properly since the tag.id is not correctly retrieved
if (Platform.OS === 'ios') {
resp = await NfcManager.sendMifareCommandIOS([0x30, 0x00]);
} else {
resp = await NfcManager.transceive([0x30, 0x00]);
}
console.warn('Response: ', resp);
this._cleanUp();
} catch (ex) {
console.warn(ex);
this._cleanUp();
}
}
If I scan the card against the device, it makes the sound like it has been scanned, but nothing seems to be displayed.
Does anyone know why does the app needs to be brought to the background so that the technology is requested? And second, does the fail of the getTag() method have anything to do with it?
I hope anyone can help me with this issue, I have been struggling with this problem for quite some time and I haven't found any solution.
May be related to github.com/revtel/react-native-nfc-manager/issues/423 ?? there seems to be a scenario where this package does not correctly configure enableForegroundDispatch and manually pausing and resuming the App by sending it to the background would fix it.

How to share image downloaded from flutter

I use flutter to save a widget as an image in flutter. I have no problem with downloading the image but im having troubke with sharing the image. Is there a way i way share the downlaoded image without leaving the application?
Here's my present code
onPressed: () async {
if (await Permission.storage.request().isGranted) {
screenshotController.capture(pixelRatio: 1.5);
screenshotController.capture().then((File image) async {
await ImageGallerySaver.saveImage(image.readAsBytesSync());
Navigator.of(context, rootNavigator: true).pop();
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text("Image Saved to Gallery"),
duration: const Duration(seconds: 1),
),
);
}).catchError((onError) {
// print(onError);
});
} else {
await Permission.storage.request();
}
}
You need to handle the image as any other file.
If you do not intend to use a server between the two users, its a bit tricky because one of them must act as one, but if you will use a server, i suggest you to follow this post:
https://dev.to/carminezacc/advanced-flutter-networking-part-1-uploading-a-file-to-a-rest-api-from-flutter-using-a-multi-part-form-data-post-request-2ekm
It's pretty recent and will help you with the app code and even with a server sample writen in nodejs. The next parts of the post teach you to do what you want.

How do you get the value from a JavaScript function in Flutter WebView?

Hi I have a webView and I'm simply trying to get the value from the WebView to return true or false when the user presses a button, I have managed to console.log it, but how do I get this value and put it into flutter? Thanks.
web.WebView(
initialUrl: "https://www.tiktok.com/#tiktok",
javascriptMode: web.JavascriptMode.unrestricted,
onWebViewCreated: (web.WebViewController webViewController) {
_controller.complete(webViewController);
_myController = webViewController;
},
onPageFinished: (String url) {
_myController.evaluateJavascript("""
window.onclick = e => {
console.log(e.target.className);
console.log(e.target.tagName);
}
var element = document.getElementsByClassName('jsx-4074580611');
element[0].addEventListener('click', function(event) {
setTimeout(function (){
if(element[0].innerText == 'Following') {
console.log("True");
//RETURN TRUE TO FLUTTER
}else{
console.log("False");
//RETURN FALSE TO FLUTTER
}
}, 1500);
});
""");
},
javascriptChannels: Set.from([
])
),
);
}
}
You won't get anything back from the webpage like this, because the page doesn't know how to talk back to your Flutter container. You need a callback, which you interestingly already defined in your code, but not used. It's the javascriptChannels:
https://pub.dev/documentation/webview_flutter/latest/webview_flutter/WebView/javascriptChannels.html
It will create a JS window object with your chosen name, which you can then call from JS with your value. You get the value back in Flutter. Basically whole Cordova is built on such mechanism.
Some more practical suggestions:
give your channel as unique name as possible, to avoid namespace fight with other JS libraries. Definitely not "Print" like in the example.
the callback will most likely be asynchronous. Don't expect the WebView to drop everything just to deliver a value immediately in your Channel callback. It will most probably go on doing other things in JavaScript, and the callback will appear later.
Disclaimer: i have zero experience with Flutter, but i have tons of experience with WebView interoperability on iOS and Android. Please create a new issue for any further advanced Flutter questions you may want to ask now.

Categories

Resources