Flutter Isolate Issue with Platform Channel code - flutter

I tried to clear my app notification count using the platform code. And I try to implement isolate for this function in dart side.
I got the above error message to both compute and isolate ways. Both are failed.
Error
Exception: Null check operator used on a null value
MethodChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:142:86)
MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:148:36)
MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:331:12)
NotificationCountService.computeFunction (package:yellow/services/notificationCountService.dart:32:16)
_IsolateConfiguration.apply (package:flutter/src/foundation/_isolates_io.dart:81:34)
_spawn.<anonymous closure> (package:flutter/src/foundation/_isolates_io.dart:88:65)
_spawn.<anonymous closure> (package:flutter/src/foundation/_isolates_io.dart:87:5)
Timeline.timeSync (dart:developer/timeline.dart:163:22)
_spawn (package:flutter/src/foundation/_isolates_io.dart:85:35)
_delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:286:17)
_RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
Full Code
class NotificationCountService {
static const platform = MethodChannel('path/notificationCount');
static Future<void> setCountCompute(int count) async {
//await compute(computeFunction, count);
spawnNewIsolate(count);
}
static computeFunction(int count) async {
try {
count = (count ?? 0) <= 0 ? 0 : count;
compute(await platform.invokeMethod('setCount', {'count': count}), );
print('result is $result');
} on PlatformException catch (e) {
print("Failed to get battery level: '${e.message}'.");
return null;
}
}
static void spawnNewIsolate(int count) async {
ReceivePort receivePort = ReceivePort();
try {
await Isolate.spawn(createFunction, receivePort.sendPort);
SendPort childSendPort = await receivePort.first;
ReceivePort responsePort = ReceivePort();
childSendPort.send([count, receivePort.sendPort]);
var response = await responsePort.first;
print('response $response');
} catch (e) {
print("Error: $e");
}
}
static void createFunction(SendPort mainPort) async {
ReceivePort childPort = ReceivePort();
mainPort.send(childPort.sendPort);
await for (var message in childPort) {
int count = message[0];
SendPort replyPort = message[1];
var result = await platform.invokeMethod('setCount', {'count': count});
replyPort.send(result);
}
}
}

The engine code dereferences null and crashes when attempting to send a platform message from the secondary isolate. I haven't pinpointed exactly where yet; I get a tombstone, but need to learn how to interpret such a thing.
As a (clumsy) workaround, the secondary isolate could ask the primary one to send the messa
I got the same issue. To track this issue, please subscribe https://github.com/flutter/flutter/issues/13937

Related

Getting "Unhandled Exception: Null check operator used on a null value" while getting data from firestore database

Hello Guys I am working on flutter project where I am getting user information from the firestore database but when I am getting that info it throws an exception
The Error:
E/flutter (18952): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value
E/flutter (18952): #0 _ProfileState.getData (package:recipedia/Tabs/profile.dart:30:86)
E/flutter (18952): <asynchronous suspension>
My Code:
Future<void> getData() async {
emailFromPrefs = (await SharedPreference().getCred('email'))!;
nameFromDatabase = (await UserModel().getUser(emailFromPrefs, 'name'))!;
setState(() {
name = nameFromDatabase;
email = emailFromPrefs;
});
}
My Usermodel Class Get Data function:
Future<String?> getUser(String email, String data) async {
try {
CollectionReference users =
FirebaseFirestore.instance.collection('users');
final snapshot = await users.doc(email!).get();
final data = snapshot.data() as Map<String, dynamic>;
return data['$data'];
} catch (e) {
return 'Error fetching user';
}
}
instead of using ! try to do a null check 1st.
Future<void> getData() async {
final mEmail = await SharedPreference().getCred('email');
if(mEmail==null){
debugPrint("Got null on email");
return;}
emailFromPrefs = mEmail;
final mName = await UserModel().getUser(emailFromPrefs, 'name');
if(mName ==null){
debugPrint("Got null on name");
return;
}
nameFromDatabase = mName;
setState(() {
name = nameFromDatabase;
email = emailFromPrefs;
});
}
Same goes for getUser, on users.doc(email!).get(). try-catch should handle this.

Agora Flutter video call stops after some time with PlatformException(-7, , null, null)

I am working on a Flutter app that uses a video call feature. I have set up engine initialization and everything correctly and am able to make the video call on both ends successfully. Following is my current version of Agora RTC Engine:
agora_rtc_engine: ^5.3.1
Following is the code I used for engine initialization and initiating video calls.
RtcEngine engine;
var _localUid = 0;
await [Permission.camera, Permission.microphone].request();
engine = await RtcEngine.create(Constants.AGORA_APP_ID);
engine.setEventHandler(
RtcEngineEventHandler(
joinChannelSuccess: (channelId, uid, elapsed) { _localUid = uid; /* my_own_logic */ },
leaveChannel: (RtcStats stats) { /* my_own_logic */ },
userJoined: (int remoteUid, int reason) { /* my_own_logic */ },
userOffline: (remoteUid, reason) { /* my_own_logic */ },
));
await engine.enableVideo();
await engine.enableAudio();
await engine.setVideoEncoderConfiguration(VideoEncoderConfiguration(
dimensions: const VideoDimensions(width: 360, height: 640),
frameRate: VideoFrameRate.Fps60,
bitrate: 0,
));
await engine.setDefaultAudioRouteToSpeakerphone(true);
agoraToken = await fetchAgoraToken(uid: _localUid, channelId: "generatedChannelId");
await engine.setChannelProfile(ChannelProfile.LiveBroadcasting);
await engine.setClientRole(ClientRole.Broadcaster);
await engine.startPreview();
await engine.joinChannel(agoraToken, "generatedChannelId", '', _localUid,);
I'm generating call joining tokens with channel ID, Agora APP ID and Certificate from Firebase Functions and the channel name is always unique between the same two callers.
The video call is working well and I can see/hear other people. But after a few seconds, not more than a minute, the video call stops suddenly. Following is the exact error message I receive on my console
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(-7, , null, null)
E/flutter (25342): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:653:7)
E/flutter (25342): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:296:18)
I'm stuck here and unable to work further. Could anybody suggest me how should I fix this?
It turned out that I had earlier placed a timer to schedule cancellation of call if there's no response from the callee. The calling screen was closing after the specified time without leaving channel and destroying the engine, and that was causing the exception.
Timer? callEndTimer;
void scheduleCallEnd() {
callEndTimer = Timer(const Duration(seconds: Constants.INCOMMING_CALL_TIME), () {
if (mounted) {
setState(() {
_onCallEnd(context);
});
}
});
}
Then I cancelled the timer if the call was responded by callee.
void cancelScheduledCallEnd() {
if (callEndTimer != null) callEndTimer!.cancel();
}

How can i change music led controller color with SP107E / Flutter

I want to change my music led color (SP107E) , is that possible with flutter ? What is the correct way for this ? I find some libraries but i couldnt use it.
I am already connected to device but i cant write values.
In this example which i am using this for now.
https://github.com/alvarowolfx/ble-rgb-light-flutter
enter image description here
I just want to change led colors.
UPDATE:
Im getting this error when i try to pick a color.
Tried calling: write(Uint8Array, withoutResponse: true)
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:63:5)
#1 _DeviceScreenState.writeData
package:ble_rgb_lamp/main.dart:305
#2 _DeviceScreenState.onColorChange.<anonymous closure>
package:ble_rgb_lamp/main.dart:320
void writeData(Color color) async {
try {
var colorStr =
color.value.toRadixString(16).padLeft(8, '0').substring(2, 8);
var obj = {'color': colorStr};
var cmd = jsonEncode(obj);
List<int> bytes = utf8.encode(cmd);
print(cmd);
await rxChar.write(bytes, withoutResponse: true);
timer = null;
} on Exception catch (err) {
print(err);
}
}
void onColorChange(BuildContext context, Color color) async {
setState(() => pickerColor = color);
if (rxChar == null) {
await fetchServices(context);
}
if (timer == null) {
timer = Timer(Duration(milliseconds: 100), () => writeData(color));
}
}
I found documentation SP107E
https://images-na.ssl-images-amazon.com/images/I/91v2W3TbWeL.pdf

NoSuchMethod Errors Inside Repository & Data Sources Classes While Using FlutterSecureStorage Package

I am trying to persist the user authentication state of an already working auth system using flutter_bloc and Nodejs, by storing my successfully retrieved and generated JWTs. I have chosen flutter_secure_storage (FSS), for brevity as my key-value cache system.
Whenever I try to read or write data with FSS, I keep running into these kind of errors:
Unhandled Exception: NoSuchMethodError: The method 'write/read/delete' was called on null.
In the case of writing my JWTs to FSS, here's an example snippet:
#override
Future<UserModel> loginUser(Map<String, dynamic> body) async {
final userModel = await dataSource.loginUser(body);
var userId = userModel.id;
Future.delayed(Duration(seconds: 2), () async {
await storage.write(key: APIConstants.USER_ID_KEY, value: userId);
});
return userModel;
}
Have even tried delaying the write operation to see if the value will save, it only logs me in cos of proper credentials and then throws an error, not crashing though, that's great.
Here's the data source class snippet for login user:
abstract class UserRemoteDataSource {
Future<UserModel> loginUser(Map<String, dynamic> body);
Future<UserModel> registerUser(Map<String, dynamic> body);
// Future<User> sendOTP();
// Future<User> verifyOTP();
Future<UserModel> getCurrentUser(String userId);
Future<void> logOut();
}
class UserRemoteDataSourceImpl implements UserRemoteDataSource {
final APIClient client;
var storage = FlutterSecureStorage();
UserRepository repository;
UserRemoteDataSourceImpl({#required this.client});
#override
Future<UserModel> loginUser(Map<String, dynamic> body) async {
final response = await client.postAuthData('login', body);
final userResponseModel = UserResponseModel.fromJSON(response);
final accessToken = userResponseModel.accessToken;
final refreshToken = userResponseModel.refreshToken;
storage = FlutterSecureStorage();
await storage.write(key: APIConstants.ACCESS_TOKEN_KEY, value: accessToken)
.then((value) => print('AccessToken Written to FSS')); // this callback from future logs, so I know that the tokens have been saved
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY, value: refreshToken)
.then((value) => print('RefreshToken Written to FSS'));
return userResponseModel.user;
}
#override
Future<UserModel> registerUser(Map<String, dynamic> body) async {
final response = await client.postAuthData('register', body);
final userResponseModel = UserResponseModel.fromJSON(response);
final accessToken = userResponseModel.accessToken;
final refreshToken = userResponseModel.refreshToken;
storage = FlutterSecureStorage();
await storage.write(key: APIConstants.ACCESS_TOKEN_KEY, value: accessToken)
.then((value) => print('AccessToken Written to FSS'));
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY, value: refreshToken)
.then((value) => print('AccessToken Written to FSS'));
return userResponseModel.user;
}
#override
Future<UserModel> getCurrentUser(String id) {
return null; // cos of write and read operation for userid, had to just return null for now
}
#override
Future<void> logOut() async {
await client.postAuthData('logout', null);
}
}
Now, when I compile my code, cos of the Delayed Future in Repository Snippet (First One Above), I get this error (showing full logs):
I/flutter ( 5048): Login state is LoginStateInitial
I/flutter ( 5048): LoginState Listened is: LoginStateLoading
I/flutter ( 5048): LoginState Building is: LoginStateLoading
I/flutter ( 5048): {success: true, message: Logged in Successfully, user: {_id: 60435f3a0b5da10015bb87b3, username: abc123, email: abc123#gmail.com, password: $2b$10$wgdBFyvWUI4e0bB3KNRBl.WLLVwu2FVZQN9BtSSdxbSzfcwdQyH2K, phone: 89066060484, __v: 0}, accessToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2MTgxMjU2NTEsImV4cCI6MTYyMDcxNzY1MSwiYXVkIjoiNjA0MzVmM2EwYjVkYTEwMDE1YmI4N2IzIiwiaXNzIjoicGlja3VycGFnZS5jb20ifQ.uH3D_v6mYwIOnBgRfoQQYzrN8asPt_Rhfei9wxmAM6A, refreshToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2MTgxMjU2NTEsImV4cCI6MTY0OTY4MzI1MSwiYXVkIjoiNjA0MzVmM2EwYjVkYTEwMDE1YmI4N2IzIiwiaXNzIjoicGlja3VycGFnZS5jb20ifQ.dIgOHlsXdBXUtrLNqiF3mKhmKZU0HJe-IwMDyg23OO0}
D/FlutterSecureStoragePl( 5048): Initializing StorageCipher
I/fluttersecurestorage( 5048): Creating keys!
I/fluttersecurestorage( 5048): Initializing
I/fluttersecurestorage( 5048): Generating key pair
E/KeyStore( 5048): generateKeyInternal failed on request -68
D/FlutterSecureStoragePl( 5048): StorageCipher initialization complete
D/FlutterSecureStoragePl( 5048): StorageCipher already initialized
I/flutter ( 5048): LoginState Listened is: LoginStateSuccess
W/utter_bloc_aut( 5048): Accessing hidden method Lsun/misc/Unsafe;-
>compareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z (greylist, linking, allowed)
E/flutter ( 5048): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception:
// starts from here // NoSuchMethodError: The method 'write' was called on null.
E/flutter ( 5048): Receiver: null
E/flutter ( 5048): Tried calling: write(key: "userId", value: "60435f3a0b5da10015bb87b3") // in repository file
E/flutter ( 5048): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
E/flutter ( 5048): #1 UserRepositoryImpl.loginUser.<anonymous closure> (package:flutter_bloc_auth/data/repositories/user_repository_impl.dart:22:21)
E/flutter ( 5048): #2 UserRepositoryImpl.loginUser.<anonymous closure> (package:flutter_bloc_auth/data/repositories/user_repository_impl.dart:21:42)
E/flutter ( 5048): #3 new Future.delayed.<anonymous closure> (dart:async/future.dart:315:39)
Is this a prime example of using null safety and how? I had previously tried migrating the entire project to null safety but there were cyclic dependencies on the packages, so I continued without null safety.
Is this a case of using FutureBuilder to wait for the value of the strings (tokens and userid). Had tried calling .then but my response body (JSON String) is not a Future, obviously.
What's the cause of this error as we can see it later held the value of userId in E/flutter ( 5048): Tried calling: write(key: "userId", value: "60435f3a0b5da10015bb87b3") but initially it didn't, as per my understanding.
I've run into this error severally and still haven't found a way to deal with it. Any help will be appreciated.
--------EDIT (SIMILAR ISSUE)------
I've gotten the tokens and userid to save when login method is called. However, when I close the app and re-open it, it throws an error for reading the access token key (which was saved previously), like below log:
I/flutter (27570): AuthenticationStateInitial
I/flutter (27570): LoginState Building is: LoginStateInitial
I/flutter (27570): NoSuchMethodError: The method 'read' was called on null.
I/flutter (27570): Receiver: null
I/flutter (27570): Tried calling: read(key: "access_token")
I/flutter (27570): AuthenticationStateFailure
I want the AuthenticationBloc to read the state once it finds the token as Authenticated not Failure, each time a previously logged in or just signed up user opens the app. What's the best strategy for that?
Here's my AuthenticationBloc snippet. Login & Register Blocs Snippets Skipped Due to Brevity and Similarity of Functionality.
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
final UserRepository _repository;
AuthenticationBloc(UserRepository repository)
: assert(repository != null), _repository = repository,
super(AuthenticationStateInitial());
#override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event) async* {
if (event is AppStarted) {
yield* _mapAppStartedToState(event);
}
if(event is UserSignedUp){
yield* _mapUserSignedUpToState(event);
}
if(event is UserLoggedIn){
yield* _mapUserLoggedInToState(event);
}
if(event is UserLoggedOut){
await _repository.deleteTokens(event.accessToken, event.refreshToken);
yield* _mapUserLoggedOutToState(event);
}
}
Stream<AuthenticationState> _mapAppStartedToState(AppStarted event) async*
{
yield AuthenticationStateLoading();
try{
// if(event?.accessToken == null || event.refreshToken == null) {
// yield AuthenticationStateUnAuthenticated();
// } else {
// print('accessToken is\t${event?.accessToken}');
// print('refreshToken is\t${event?.refreshToken}');
// try {
// final currentUser = await _repository.getCurrentUser();
// yield AuthenticationStateAuthenticated(user: currentUser, );
// } catch(error2) {
// print(error2);
// }
// }
final hasTokens = await _repository.checkHasTokens(event.accessToken, event.refreshToken); //simple read operation using the Keys used to write tokens values
print('hasTokens $hasTokens');
final currentUser = await _repository.getCurrentUser();
// if(hasTokens && currentUser != null){
if(hasTokens){
yield AuthenticationStateAuthenticated(user: currentUser, );
} else {
yield AuthenticationStateUnAuthenticated();
}
} catch(err){
print(err);
// yield AuthenticationStateFailure(errorMessage: err.message ?? 'Error Completing Your Request, Try Again!');
yield AuthenticationStateFailure(errorMessage: 'Error Completing Your Request, Try Again!');
}
}
Stream<AuthenticationState> _mapUserSignedUpToState(UserSignedUp event) async* {
yield AuthenticationStateAuthenticated(user: event.user);
}
Stream<AuthenticationState> _mapUserLoggedInToState(UserLoggedIn event) async* {
yield AuthenticationStateAuthenticated(user: event.user);
}
Stream<AuthenticationState> _mapUserLoggedOutToState(UserLoggedOut event) async* {
await _repository.logOut();
yield AuthenticationStateUnAuthenticated();
}
}
and UserRepositoryImpl Snippet, as Suggested:
class UserRepositoryImpl extends UserRepository {
final UserRemoteDataSource dataSource;
UserRepositoryImpl({#required this.dataSource});
var storage;
#override
Future<UserModel> loginUser(Map<String, dynamic> body) async {
final userModel = await dataSource.loginUser(body);
// var userId = userModel.id;
// Future.delayed(Duration(seconds: 2), () async {
// await storage.write(key: APIConstants.USER_ID_KEY, value: userId);
// });
return userModel;
}
#override
Future<UserModel> registerUser(Map<String, dynamic> body) async {
final userModel = await dataSource.registerUser(body);
// await storage.write(key: APIConstants.USER_ID_KEY, value: userModel.id);
return userModel;
}
#override
Future<UserModel> getCurrentUser() async {
// final userId = await storage.read(key: APIConstants.USER_ID_KEY);
// final user = await dataSource.getCurrentUser(userId);
// return user;
return null;
}
#override
Future<void> logOut() async {
storage = FlutterSecureStorage();
await storage.delete(key: APIConstants.ACCESS_TOKEN_KEY);
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY);
await dataSource.logOut();
}
#override
Future<void> saveTokens(String accessToken, String refreshToken) async {
final storage = FlutterSecureStorage();
print('st() accesstokenval\t:$accessToken');
await storage.write(key: APIConstants.ACCESS_TOKEN_KEY, value: accessToken);
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY, value: refreshToken);
}
#override
Future<void> deleteTokens(String accessToken, String refreshToken) async {
storage = FlutterSecureStorage();
await storage.delete(key: APIConstants.ACCESS_TOKEN_KEY);
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY);
}
#override
Future<bool> checkHasTokens(String accessToken, String refreshToken) async{
storage = FlutterSecureStorage();
final hasAT = await storage.read(key: APIConstants.ACCESS_TOKEN_KEY);
final hasRT = await storage.read(key: APIConstants.REFRESH_TOKEN_KEY);
return hasRT == null || hasAT == null ? false : true;
}
}

MissingPluginException(No implementation found for method isAvailable on channel plugins.pauldemarco.com/flutter_blue/methods)

My flutter app.
Im trying to get all BLE devices in the backgroung, activated form printHello() function.
I have the following error:
The error at the following line - FlutterBlue _flutterBlue = FlutterBlue.instance;
Does someone have new information about?
I saw similar questions and try to implement them, but I could not solve the issue.
Here is the logcat:
I/flutter (20509): [2021-02-04 18:39:34.118258] Start Scanning
I/flutter (20509): [2021-02-04 18:39:34.118258] end of scanning
E/flutter (20509): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: MissingPluginException(No implementation found for method isAvailable on channel plugins.pauldemarco.com/flutter_blue/methods)
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final int helloAlarmID = 0;
await AndroidAlarmManager.initialize();
runApp(MyApp());
await AndroidAlarmManager.periodic(const Duration(seconds: 30), helloAlarmID, printHello);
}
void printHello() {
final DateTime now = DateTime.now();
final int isolateId = Isolate.current.hashCode;
print("[$now] Hello, world! isolate=${isolateId} function='$printHello'");
_getDevices();
}
void _getDevices() {
final DateTime now = DateTime.now();
print("[$now] Start Scanning");
bool _found = false;
FlutterBlue _flutterBlue = FlutterBlue.instance;
_flutterBlue.startScan(timeout: Duration(seconds: 4));
var subscription = _flutterBlue.scanResults.listen((results) {
for (ScanResult r in results) {
// print('111 ${r.device.name} 2 ${r.device.id } 3 found! rssi: ${r.rssi}');
if (('${r.device.id }'=="XXX" )& (_found==false)) { print ("[$now] ----------");_found = true;
}
}
});
_flutterBlue.stopScan();
print("[$now] end of scanning");
}
I moved the listener to the initState() in the main screen and its working
flutterBlueInstance.scan().listen((event) {
var _event = event;
if (_event.advertisementData.localName.toString() == ..... }