Pedometer package in flutter doesn't work with some devices - flutter

I used the pedometer package version ^1.2.0 in my flutter app and I noticed that it doesn't work with some devices like Samsung A30 and others, the version I used doesn't need any permissions and it worked on my device OPPO F7 (Used Android 10) so what is the problem?
Here's the code
StreamSubscription<int> _subscription;
Box<int> stepsBox = Hive.box('steps');
int todaySteps;
#override
void initState() {
super.initState();
startListening();
}
#override
void dispose() {
stopListening();
super.dispose();
}
void startListening() {
_pedometer = Pedometer();
_subscription = _pedometer.pedometerStream.listen(
getTodaySteps,
onError: _onError,
onDone: _onDone,
cancelOnError: true,
);
}
void _onDone() => print("Finished pedometer tracking");
void _onError(error) => print("Flutter Pedometer Error: $error");
Future<int> getTodaySteps(int value) async {
print(value);
int savedStepsCountKey = 999999;
int savedStepsCount = stepsBox.get(savedStepsCountKey, defaultValue: 0);
int todayDayNo = Jiffy(DateTime.now()).dayOfYear;
if (value < savedStepsCount) {
// Upon device reboot, pedometer resets. When this happens, the saved counter must be reset as well.
savedStepsCount = 0;
// persist this value using a package of your choice here
stepsBox.put(savedStepsCountKey, savedStepsCount);
}
// load the last day saved using a package of your choice here
int lastDaySavedKey = 888888;
int lastDaySaved = stepsBox.get(lastDaySavedKey, defaultValue: 0);
// When the day changes, reset the daily steps count
// and Update the last day saved as the day changes.
if (lastDaySaved < todayDayNo) {
lastDaySaved = todayDayNo;
savedStepsCount = value;
stepsBox
..put(lastDaySavedKey, lastDaySaved)
..put(savedStepsCountKey, savedStepsCount);
}
setState(() {
todaySteps = value - savedStepsCount;
});
stepsBox.put(todayDayNo, todaySteps);
return todaySteps; // this is your daily steps value.
}
void stopListening() {
_subscription.cancel();
}

check for permission.
await Permission.activityRecognition.request().isGranted
this will check for permission and request permission if the permission is not allowed
if (await Permission.activityRecognition.request().isGranted) {
_pedestrianStatusStream = Pedometer.pedestrianStatusStream;
_pedestrianStatusStream
.listen(onPedestrianStatusChanged)
.onError(onPedestrianStatusError);
_stepCountStream = Pedometer.stepCountStream;
_stepCountStream.listen(onStepCount).onError(onStepCountError);
}else{
}
if (!mounted) return;

I think that in this case it would be better to ask the question directly in the lib repository, open an issue with your problem.
https://github.com/cph-cachet/flutter-plugins/issues

Related

sqflite is taking too long time to fetch data from database

This is the code which i used to fetch data from database
Future<List<ShadeColorDatabase>?> getShadeColorData() async {
Database? db = await instance.database;
try {
var data = await db!.query(table4);
List<ShadeColorDatabase>? shadeColorDataList = data.isNotEmpty
? data.map((e) => ShadeColorDatabase.fromMap(e)).toList()
: [];
return shadeColorDataList;
} catch (e) {
rethrow;
}
}
and i called this function in my screen like this
filterDatabaseData() async {
final databaseData = await DatabaseHelper.instance.getShadeColorData();
for (int i = 0; i < databaseData!.length; i++) {
print("${databaseData[i].colorName}");
setState(() {
allColorCodeList.add(databaseData[i].colorName);
});
}
}
#override
void initState() {
// TODO: implement initState
super.initState();
filterDatabaseData();
}
but i get this warning saying:- warning-database-has-been-locked-for-00010-000000-make-sure-you-always-use-th. this says when i run my app for the first time. Meaning if someone is running the app for the first time this warning is showing and related data is not showing is there any way i can fix this problem need some help. Thanks

Keep the user logged in flutter (The app has 2 different login and main, one for Client and one for Driver)

I am doing an app in flutter and I am working on the authentication part. I want to know how I can keep my user logged in after I reload the app. Now the thing is that my app has 2 kinds of users (Client and Driver). So each has its own space, like sign in and sign up and main (after logging in).
This is the code that I used for logging.
class Initializer extends StatefulWidget {
// Access to this Screen
static String id = 'initializer';
#override
_InitializerState createState() => _InitializerState();
}
class _InitializerState extends State<Initializer> {
// Firebase Stuff
final _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
User _user;
// To Check if There's a Driver
bool isDriver = true;
void getCurrentUser() async {
try {
final getCurrentUser = _auth.currentUser;
if (getCurrentUser != null) {
getUserKind();
_user = getCurrentUser;
}
} catch (e) {
print(e);
}
}
getUserKind() async {
try {
// To fetch Database for Driver
final QuerySnapshot checkOfDriver =
await _firestore.collection('driver').where('uid', isEqualTo: _user.uid).get().catchError((error) {
print(error);
});
if (checkOfDriver.docs.isEmpty)
setState(() {
isDriver = false;
});
else
setState(() {
isDriver = true;
});
} catch (e) {
print(e);
return null;
}
}
#override
void setState(fn) {
if (mounted) {
super.setState(fn);
}
}
#override
void initState() {
super.initState();
getCurrentUser();
}
#override
Widget build(BuildContext context) {
getCurrentUser();
SizeConfig().init(context);
return _user == null
? WelcomeScreen()
: isDriver
? DriverMain()
: ClientMain();
}
}
It's actually working but not properly, because when I reload the app while I'm logging in as a Client, the app shows me DriverMain at the beginning for one second then it switches to the right side which is ClientMain and that causes me some errors sometimes, and it's not an efficient work anyway.
So, what I should add to the code or ...
Firebase already persists the users credentials, and restores them automatically when the app restarts.
But this is an asynchronous process, as it requires a call to the server. By the time your getCurrentUser = _auth.currentUser code runs, that asynchronous process hasn't finished yet, so you get null.
To properly respond to the auth state being restored (and other changes), you'll want to use an auth state change listener as shown in the documentation on authentication state:
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
});
If you want to use this in your UI, you'll typically wrap it in a StreamBuilder instead of calling listen yourself.

Flutter | audioplayers onDurationChanged Method isn't working on IOS

I'm trying to make some kind of an mp3 player app and i'm using audioplayers package. And it's been working fine on Android, but on IOS the onDurationChanged doesn't seem to be getting called.
And since i'm also showing a slider, it gives an Error on IOS because the max value returns null
Here's my code
class AudioProvider extends ChangeNotifier {
AudioProvider() {
initAudio();
}
AudioPlayer _audioPlayer = AudioPlayer();
Duration totalDuration;
Duration position;
String audioState;
initAudio() {
_audioPlayer.onDurationChanged.listen((updatedDuration) {
totalDuration = updatedDuration; // This doesn't work on IOS, totalDuration == null
notifyListeners();
});
_audioPlayer.onAudioPositionChanged.listen((updatedPosition) {
position = updatedPosition;
notifyListeners();
});
_audioPlayer.onPlayerStateChanged.listen((playerState) {
if (playerState == AudioPlayerState.STOPPED) audioState = "Stopped";
if (playerState == AudioPlayerState.PLAYING) audioState = "Playing";
if (playerState == AudioPlayerState.PAUSED) audioState = "Paused";
notifyListeners();
});
}
playPauseAudio(String url, bool alreadyPlaying) async {
if (!alreadyPlaying) {
position = null;
totalDuration = null;
await _audioPlayer.play(url);
notifyListeners();
}
if (audioState == 'Playing') {
await _audioPlayer.pause();
} else {
await _audioPlayer.resume();
}
notifyListeners();
}
void stop() {
_audioPlayer.stop();
}
void seekToSec(Duration durationToSeek) {
_audioPlayer.seek(durationToSeek);
notifyListeners();
}

flutter in_app_purchases not available on emulator - getting error android

I am trying to implement in_app_purchase: ^0.3.5+1 for 1st time.
I have an active product setup on the Google Developer Console but I can't seem to get my emulator to hit the store. The connection's isAvailable method always returns false. Stepping through the code the connection instance seems to show the following error message in the private property _purchasedUpdatedStream. Not sure what this means. Seems relevant. Not sure what steps to take from here. Any help is much appreciated.
The getter '_purchaseUpdatedStream' isn't defined for the class 'GooglePlayConnection'.
'GooglePlayConnection' is from 'package:in_app_purchase/src/in_app_purchase/google_play_connection.dart' ('../../flutterSDK/.pub-cache/hosted/pub.dartlang.org/in_app_purchase-0.3.5+1/lib/src/in_app_purchase/google_play_connection.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named '_purchaseUpdatedStream'.
_purchaseUpdatedStream
Store class looks like this:
import 'dart:async';
import 'dart:io';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:quifil/models/status_ml.dart';
class StoreAPI {
InAppPurchaseConnection _iap;
bool available = true;
StreamSubscription<List<PurchaseDetails>> _subscription;
final String myProductID = 'quifil_ad_free';
bool _isPurchased = false;
List _purchases = [];
List _products = [];
StoreAPI() {
InAppPurchaseConnection.enablePendingPurchases();
_iap = InAppPurchaseConnection.instance;
}
bool get isPurchased {
return _isPurchased;
}
set isPurchased(bool value) {
_isPurchased = value;
}
List get purchases {
return _purchases;
}
set purchases(List value) {
_purchases = value;
}
List get products {
return _products;
}
set products(List value) {
_products = value;
}
Future<Status> fetchStoreInfo() async {
Status status = Status(true);
bool available = await _iap.isAvailable();
if (available) {
await _getProducts();
await _getPastPurchases();
verifyPurchase();
_subscription = _iap.purchaseUpdatedStream.listen((purchases) {
purchases.addAll(purchases);
verifyPurchase();
});
} else {
status.success = false;
status.error = "Store is unavailable";
}
return status;
}
Future<void> _getProducts() async {
Set<String> ids = Set.from([myProductID]);
ProductDetailsResponse response = await _iap.queryProductDetails(ids);
products = response.productDetails;
}
Future<void> _getPastPurchases() async {
QueryPurchaseDetailsResponse response = await _iap.queryPastPurchases();
for (PurchaseDetails purchase in response.pastPurchases) {
if (Platform.isIOS) {
_iap.consumePurchase(purchase);
}
}
purchases = response.pastPurchases;
}
void verifyPurchase() {
PurchaseDetails purchase = hasPurchased(myProductID);
if (purchase != null && purchase.status == PurchaseStatus.purchased) {
if (purchase.pendingCompletePurchase) {
_iap.completePurchase(purchase);
isPurchased = true;
}
}
}
PurchaseDetails hasPurchased(String productID) {
return purchases.firstWhere((purchase) => purchase.productID == productID,
orElse: () => null);
}
}
Turns out I had 2 items I changed to fix this.
My laptop was using wifi but wifi was not the 1st choice when it came to network access. So I disabled my other other LAN adapters. There is also a way to set the priority of your adaptors so that the wifi is top priority. It seems the emulator likes to pick the top priority.
My laptop wifi adapter DNS was using an address I did not recognize. So I changed it to use Google's DNS as 8.8.8.8 and the alternate as 8.8.4.4.

Flutter Metronome App lagging and updating values as they change

As a first app in flutter, I want to build a metronome app. The UI is already built, but I still encounter the following problems with the actual metronome functionality:
sometimes, the metronome lags a bit, just enough, so you notice it. Is there a way in flutter to achieve a 100% precision of the metronome?
not changing subdivision while playing (you have to stop and start the metronome). How can the values "tempo" and "subdivision" be automatically applied to the metronome subscription, if they change? I know that Flutter provides tools like Listenable, Stream, InheritedWidget, etc. but I haven’t figured out a way how you can implement these in the existing code.
Acreenshot of the UI:
Here is the code (it's not entirely written by me -> credits):
import 'dart:io' show File;
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:quiver/async.dart';
import 'package:audioplayers/audioplayers.dart' show AudioPlayer;
import 'package:flutter/services.dart' show ByteData, rootBundle;
import 'package:path_provider/path_provider.dart' show getTemporaryDirectory;
//credits: "Andi Qu", https://stackoverflow.com/questions/51048402/flutter-audioplayers-or-metronome-lagging
ValueNotifier<int> tempo = ValueNotifier(100);
int subdivision = 1;
bool isPlaying = false;
int soundIndex = 1;
File _soundFile;
StreamSubscription<DateTime> _subscription;
Future<ByteData> _loadSound() async {
return await rootBundle.load('assets/sounds/sound_$soundIndex.wav');
}
void _writeSound() async {
_soundFile = File(
'${(await getTemporaryDirectory()).path}/sounds/sound_$soundIndex.wav');
await _soundFile.writeAsBytes((await _loadSound()).buffer.asUint8List());
print("_writeSound executed");
}
void _playLocal() async {
final AudioPlayer _audioPlayer = AudioPlayer();
AudioPlayer.logEnabled = false;
await _audioPlayer.play(_soundFile.path, isLocal: true);
}
/// The actual method that plays the metronome
void playpause() {
print("playpause triggered");
if (_soundFile == null) {
print("_soundFile = null ---> Soundfile written");
_writeSound();
}
if (isPlaying) {
_subscription.cancel();
isPlaying = false;
print("metronome stopped");
} else {
_subscription = Metronome.periodic(new Duration(
milliseconds: (60000 / (tempo.value * subdivision)).floor()))
.listen((d) => _playLocal());
isPlaying = true;
print("metronome started");
}
}
void increasetempo(int tempochange) {
tempo.value = tempo.value + tempochange;
if (isPlaying) {
_subscription.cancel();
print("_subscription canceled");
_subscription = Metronome.periodic(new Duration(
milliseconds: (60000 / (tempo.value * subdivision)).floor()))
.listen((d) => _playLocal());
}
print("tempo changed to ${tempo.value}");
}
void decreasetempo(int tempochange) {
tempo.value = tempo.value - tempochange;
if (isPlaying) {
_subscription.cancel();
print("_subscription canceled");
_subscription = Metronome.periodic(new Duration(
milliseconds: (60000 / (tempo.value * subdivision)).floor()))
.listen((d) => _playLocal());
}
print("tempo changed to ${tempo.value}");
}
Try to use a library called flutter_sequencer, it helped me to create Metronome without lagging, while any other solution and library didn't work.
https://github.com/mikeperri/flutter_sequencer
https://pub.dev/packages/flutter_sequencer