I need to report the current location of the device using a flutter app. I need to do that continiuesly even when the app is closed.
I currently implemented it using background_fetch which does the job about every 15 minutes.
It works well when the app is open or minimized. But when the app is closed, it functions in Headless mode and doesn't work. the Exception is:
MissingPluginException(No implementation found for method getLocation on channel lyokone/location)
It seems that in Headless mode, not all the app is loaded in memory. I don't have any idea how to solve it.
Also I tried using an Isolate but I face with a new exception:
native function 'Window_sendPlatformMessage' (4 arguments) cannot be found.
Anybody knows how to solve these problems or have any new idea to do the location tracking?
Another option is use package https://github.com/Lyokone/flutterlocation https://github.com/Lyokone/flutterlocation/wiki/Background-Location-Updates
Support To get location updates even your app is closed, https://github.com/Lyokone/flutterlocation/wiki/Background-Location-Updates might have bugs
Also from transistorsoft and provide Android Headless Mod but need license
transistorsoft package https://github.com/transistorsoft/flutter_background_geolocation/wiki/Android-Headless-Mode
Android Headless Mod https://github.com/transistorsoft/flutter_background_geolocation/wiki/Android-Headless-Mode
code snippet
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
void headlessTask(bg.HeadlessEvent headlessEvent) async {
print('[BackgroundGeolocation HeadlessTask]: $headlessEvent');
// Implement a 'case' for only those events you're interested in.
switch(headlessEvent.name) {
case bg.Event.TERMINATE:
bg.State state = headlessEvent.event;
print('- State: $state');
break;
case bg.Event.HEARTBEAT:
bg.HeartbeatEvent event = headlessEvent.event;
print('- HeartbeatEvent: $event');
break;
case bg.Event.LOCATION:
bg.Location location = headlessEvent.event;
print('- Location: $location');
break;
case bg.Event.MOTIONCHANGE:
bg.Location location = headlessEvent.event;
print('- Location: $location');
break;
case bg.Event.GEOFENCE:
bg.GeofenceEvent geofenceEvent = headlessEvent.event;
print('- GeofenceEvent: $geofenceEvent');
break;
case bg.Event.GEOFENCESCHANGE:
bg.GeofencesChangeEvent event = headlessEvent.event;
print('- GeofencesChangeEvent: $event');
break;
case bg.Event.SCHEDULE:
bg.State state = headlessEvent.event;
print('- State: $state');
break;
case bg.Event.ACTIVITYCHANGE:
bg.ActivityChangeEvent event = headlessEvent.event;
print('ActivityChangeEvent: $event');
break;
case bg.Event.HTTP:
bg.HttpEvent response = headlessEvent.event;
print('HttpEvent: $response');
break;
case bg.Event.POWERSAVECHANGE:
bool enabled = headlessEvent.event;
print('ProviderChangeEvent: $enabled');
break;
case bg.Event.CONNECTIVITYCHANGE:
bg.ConnectivityChangeEvent event = headlessEvent.event;
print('ConnectivityChangeEvent: $event');
break;
case bg.Event.ENABLEDCHANGE:
bool enabled = headlessEvent.event;
print('EnabledChangeEvent: $enabled');
break;
}
}
void main() {
runApp(HelloWorld());
// Register your headlessTask:
BackgroundGeolocation.registerHeadlessTask(headlessTask);
}
Related
I am having a hard time navigating to a screen when a background FCM message receives. Currently, I am sending an FCM message with some data and when it gets received by a device then it calls this package that shows a calling notification, and when the user clicks on accept call option then I want to open my app and navigate to the desired screen. I use GetX for navigation and when I try to go to another screen it gives this exception:
I have tried almost everything to work this out but I am still unable to solve this problem.
my FirebaseMessaging.onBackgroundMessage Background handler which receives the notification also listens to user feedback on whether the call is accepted or rejected:
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
var incoming = <String, dynamic>{
'id': message.data['callerID'],
'nameCaller': message.data['callerName'],
'appName': 'Callkit',
'avatar': message.data['callerImage'],
'handle': '',
'type': 0,
'duration': 30000,
'extra': <String, dynamic>{'userId': '1a2b3c4d'},
'headers': <String, dynamic>{'apiKey': 'Abc#123!', 'platform': 'flutter'},
'android': <String, dynamic>{
'isCustomNotification': true,
'isShowLogo': false,
'ringtonePath': 'ringtone_default',
'backgroundColor': '#0955fa',
//'backgroundUrl': 'https://i.pravatar.cc/500',
'actionColor': '#4CAF50'
}};
await FlutterCallkitIncoming.showCallkitIncoming(incoming);
try {
FlutterCallkitIncoming.onEvent.listen((event) {
switch (event!.name) {
case CallEvent.ACTION_CALL_INCOMING:
print('INCOMING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
break;
case CallEvent.ACTION_CALL_START:
// TODO: started an outgoing call
// TODO: show screen calling in Flutter
break;
case CallEvent.ACTION_CALL_ACCEPT:
print('accepted');
Get.offAll(()=> Incoming(
userName: null,
userImage: null,
userID: null,
userUsername: null));
break;
case CallEvent.ACTION_CALL_DECLINE:
print('rejected');
break;
case CallEvent.ACTION_CALL_ENDED:
// TODO: ended an incoming/outgoing call
break;
case CallEvent.ACTION_CALL_TIMEOUT:
// TODO: missed an incoming call
break;
case CallEvent.ACTION_CALL_CALLBACK:
// TODO: only Android - click action `Call back` from missed call notification
break;
case CallEvent.ACTION_CALL_TOGGLE_HOLD:
// TODO: only iOS
break;
case CallEvent.ACTION_CALL_TOGGLE_MUTE:
// TODO: only iOS
break;
case CallEvent.ACTION_CALL_TOGGLE_DMTF:
// TODO: only iOS
break;
case CallEvent.ACTION_CALL_TOGGLE_GROUP:
// TODO: only iOS
break;
case CallEvent.ACTION_CALL_TOGGLE_AUDIO_SESSION:
// TODO: only iOS
break;
}
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
});
} on Exception {}
}
Similar to the answer that Peter Koltai gave, your background handler is isolated from your application's context and so it's not possible to route to screens (which require a context) directly from your handler.
One possible solution is to implement an Android service using native code that communicates with Flutter via a MethodChannel and on the event that a call is accepted, you can navigate screens.
You can change your MaterialApp() with GetMaterialApp(), and check if you are using get.to(AnotherPage()), instead use get.to(()=>AnotherPage()).
i never tested it before but i think you should use wakelock to keep your screen awake
enter link description here
I am making a chat application where I want the a user to get a notification when the other user sends a message. I've heard you can do it with a js script and followed the google guidelines but I'm confused where am I actually writing the script? Do I have to do the free trial for the google firebase environment?
You can do like this:-
DatabaseReference ref = FirebaseDatabase.getInstance().getReference(reference)
FirebaseArray snapshots = new FirebaseArray(ref);
snapshots.setOnChangedListener(new FirebaseArray.OnChangedListener() {
#Override
public void onChanged(EventType type, int index, int oldIndex) {
switch (type) {
case Added:
break;
case Changed:
break;
case Removed:
break;
case Moved:
break;
}
}
});
I am using quickblox api for 1 to 1 videochat but I dont know the usage OnVideoChatChangeState() of OnQBVideoChatListener() class and with what changes the event is invoked. I have modified the code but the video doesnt start the click functions but doesn't go to:
` public void onVideoChatStateChange(CallState state, VideoChatConfig receivedVideoChatConfig) {
videoChatConfig = receivedVideoChatConfig;
isCanceledVideoCall = false;
Toast.makeText(getApplicationContext(), "switch", Toast.LENGTH_LONG).show();
switch (state)
{
case ON_CALLING:
Toast.makeText(getApplicationContext(), "After this the showCallDialog() will be called.", Toast.LENGTH_LONG).show();
showCallDialog();
break;
case ON_ACCEPT_BY_USER:
progressDialog.dismiss();
startVideoChatActivity();
break;
case ON_REJECTED_BY_USER:
progressDialog.dismiss();
break;
case ON_DID_NOT_ANSWERED:
progressDialog.dismiss();
break;
case ON_CANCELED_CALL:
isCanceledVideoCall = true;
videoChatConfig = null;
break;
case ON_START_CONNECTING:
progressDialog.dismiss();
startVideoChatActivity();
break;
default:
break;
}
}
};
`
and the showCallDialog(); method is not called this shows the events doesn't occur here.
So I want to know can the event occurs so that the methods are called.
This has been fixed. Master branch is updated. Please try download and use the sample once again.
I am currently using Beem's source code to do developments. I would like to implement the chat state notifications. I have look through the codes and found that there is a setState() method, but I believe it has not been implemented and I have no clues about how to do it. If I use Adium to type a message to the Beem user, the Beem user is able to see that the Adium user is composing a message. But if both users are using Beem, then it does not display if the user is composing a message. Therefore, I would like to try to implement the chat state notification. How do I go about doing it? Is there any guides out there? Can someone help me? Thanks!
Add this code to setState method in ChatAdapter.java file.
org.jivesoftware.smack.packet.Message message = new org.jivesoftware.smack.packet.Message();
ChatStateExtension extension = null;
switch (state) {
case "composing":
extension = new ChatStateExtension(ChatState.composing);
break;
case "active":
extension = new ChatStateExtension(ChatState.active);
break;
case "inactive":
extension = new ChatStateExtension(ChatState.inactive);
break;
case "gone":
extension = new ChatStateExtension(ChatState.gone);
break;
case "paused":
extension = new ChatStateExtension(ChatState.paused);
break;
}
message.addExtension(extension);
try {
mAdaptee.sendMessage(message);
} catch (XMPPException e) {
e.printStackTrace();
}
I am stuck in swich case. Please check code below
Log.e("##################### pos",""+posSel_lay);
String ff=Integer.toString(posSel_lay);
//var ffs=Integer.toString(posSel_lay);
Log.e("##################### pos",""+ff);
if(ff.equals("0")){
Log.e("###################Lagan","");
}else if(ff.equals("1")){
Log.e("###################MBBS","");
}else if(ff.equals("2")){
Log.e("###################JODHA","");
}else if(ff.equals("3")){
Log.e("###################ZINDAGI","");
}
I got log only this line
##################### pos 2
& its not going in swich case why i dont know, can you help me please?
All the answers are good.
but you should at least put any message into message param of Log. otherwise you will not able to see this in logs
Log.e("###################ZINDAGI","some message.");
By default a switch case works WITH integers, why don't you try something like the following:
Log.e("##################### pos",""+posSel_lay);
switch (posSel_lay){
case 0:
Log.e("###################Lagan","");
break;
case 1:
Log.e("###################MBBS","");
break;
case 2:
Log.e("###################JODHA","");
break;
case 3:
Log.e("###################ZINDAGI","");
break;
default:
break;
}
Now instead of converting to a string, and using an if-else chain, you use a select statement, which IMO is much cleaner.
Log.e("##################### pos", "" + posSel_lay );
switch( posSel_lay ) {
case 0:
Log.e("###################Lagan","");
break;
case 1:
Log.e("###################MBBS","");
break;
case 2:
Log.e("###################JODHA","");
break;
case 3:
Log.e("###################ZINDAGI","");
break;
}
I can't really understand your question , but here is SwitchCase
switch(posSel_lay){
case 0:
Log.e("###################Lagan","");
break;
case 1:
Log.e("###################MBBS","");
break;
case 2:
Log.e("###################JODHA","");
break;
case 3:
Log.e("###################ZINDAGI","");
break;
}
I found solution. I get this posSel_lay from bundle which is passed by other activity.Previously i written switch code in on button click so now i changed flow,
When i am getting value of posSel_lay from bundle that time only i written code of switch
& there i am making some boolean values true or false which is declared locally. And when user
clicks on button that time i used boolean variables for checking. Then its done.
Thanks for your reply.