I'm trying to build a video calling app with Agora, I need to show acceptance screen like WhatsApp when user calling, if the app is exited i need to show calling screen when user is calling, I tried lot of thing but nothing works, I trying to do i flutter and but there is nothing much information on this,Please help me
First things first. You need to learn about some concepts before delving into your solution. Actually there isn't an out of the box solution.
You need to use a couple of things together:
Use push notifications to "wake up" your app:
https://pub.dev/packages/firebase_messaging
To start your app using push notifications refers to this post:
https://stackoverflow.com/a/48405551/4335775
Use CallKit (IOS) or ConnectionServices (Android) to show the upcoming call screen. By the day of this answer there are only a few packages to handle these things, here is one that can handle both platforms:
https://pub.dev/packages/flutter_callkeep
If you want a completely different thing and need to run some background process, there are bunch whole of things you should know first. I suggest beginning here: https://flutter.dev/docs/development/packages-and-plugins/background-processes
Here is a usefull package to work with background processes that should be constantly running:
https://pub.dev/packages/background_fetch
Currently there are two packages which provides integration for agora.io:
https://pub.dev/packages/agora_rtc_engine (for Agora Real Time Communication, vĂdeo call included)
https://pub.dev/packages/agora_rtm for real-time messaging
I hope this can help you.
You can try WorkManager plugin.
You can register an call back function to the os when the app is closed.
const myTask = "syncWithTheBackEnd";
void main() {
Workmanager.initialize(callbackDispatcher);
Workmanager.registerOneOffTask(
"1",
myTask, //This is the value that will be returned in the callbackDispatcher
initialDelay: Duration(minutes: 5),
constraints: WorkManagerConstraintConfig(
requiresCharging: true,
networkType: NetworkType.connected,
),
);
runApp(MyApp());
}
void callbackDispatcher() {
Workmanager.executeTask((task) {
switch (task) {
case myTask:
print("this method was called from native!");
break;
case Workmanager.iOSBackgroundTask:
print("iOS background fetch delegate ran");
break;
}
//Return true when the task executed successfully or not
return Future.value(true);
});
}
Maybe this can help you.
The complete article medium article
Related
So, I have migrated Firebase on my project from v#5 to v#14 because push-notifications did not work on android API31+(v12) at all.
NOTE: we use react-native-splash-screen. Folk pointed out on some problems react-native-firebase/issues/4005 and react-native-firebase/issues/2768 and react-native-splash-screen/issues/289 and suggested to move from older splash approach to react-native-bootsplash as an alternatiove, which was not really the solution for us.
PS. any comments inside links above did not help
firebase.messaging().onNotificationOpenedApp - Unlike initial pushes, in background mode push service was performing well as expected.
My problem was resolved by using API from 3d-party library such react-native-push-notification instead of firebase.messaging().getInitialNotification().
const getAndroidInitialNotification = (remoteMessage: ReceivedNotification | null): void => {
const data = remoteMessage?.data;
if (data) {
// Your code such deep links implementation, dispatch to reducer etc...
}
};
PushService.popInitialNotification(handleInitialNotifications);
Hope this will help for somebody like me, who do not understand what is the affection of splash approach on firebase service and all related confusing stuff.
I have code to refresh data from server which I need to run even when screen is off. I tried to do this with an isolate:
static void isolateFunc(SendPort mainSendPort) async{
String _answer = "";
while(true){
Socket socket = await Socket.connect(ipAddress, port, timeout: Duration(seconds: 5));
socket.add(utf8.encode("connection test"));
socket.listen((List<int> event) {
_answer = utf8.decode(event);
});
socket.close();
await Future.delayed(Duration(seconds: 5));
}
}
This works fine when screen is on. But after switching off the screen it refreshs maybe for 5 times normally, then it refreshs for a few times each 30 sesconds(even when the delay is set to 5 seconds) and then it just stops. I am calling the isolate from initState like this:
#override
void initState() {
super.initState();
anotherRefresher();
ReceivePort recievePort = ReceivePort();
Isolate.spawn(isolateFunc, recievePort.sendPort);
}
Battery optimalisation in android settings is off. I do not understand this :/ Any ideas how to deal with this please?
After some time I found that, there is no way how to keep running dart code in the background without setting it as background or foreground process. Both Android and iOS will always restrict your code to increase battery life. Even turning off battery optimisation will not help. So to keep dart code running even when screen is off, you need to set up background or foreground process. For this you can do some platform native coding and connect it through platform channels or use plugins. Since I don't know Swift or Kotlin, I decided to find some plugins. I have tried more of them and after some time I can say that plugin flutter_background_service is one of the best. Or based on your needs you can find another plugins or try to code it by yourself. Wish you good luck :)
We have the problem that we want to protect the complete app with a fingerprint/TouchID/FaceID. I will only mention fingerprint here, which always means all biometric features of local_auth. Partly this works quite well with the function "didChangeAppLifecycleState", but only partly.
Since under iOS the app becomes inactive while the fingerprint is being queried, the query comes in a continuous loop when queried at "AppLifecycleState.resumed". Therefore we set a timestamp at "AppLifecycleState.pause" and query the fingerprint at resume only if x seconds have passed since the app was paused. We have now also set this to a slightly higher time, so that the lock does not go on immediately if you have to switch to the camera from the app. Of course there are more checks, but that's the basic idea right now.
Here is the problem that flutter takes some time to execute paused. Both iOS and Android. So if you now quickly minimize the app and open it again (because minimizing was perhaps an accident?), the fingerprint comes directly. Nothing serious, but unpleasant.
Our real problem, which I can't really understand, since I don't know how to debug it either. If the app hasn't been used for a long time, especially on a Monday after the weekend, then work colleagues have the problem that they can simply start the app without a fingerprint. So far only noticed under iOS, since the colleagues use all iOS, but does not exclude that it could happen under Android as well.
I just don't know how to fix it. Has anyone had any experience with this? Or is there a very simple way to use the fingerprint in flutter in a way that you can open the app only with fingerprint, maybe at a completely different place than "didChangeAppLifecycleState"?
Kind regards,
Jakob
As far as I understand you are using lifecycle hook to prompt for biometric verification and you are having issues. The following is the solution if I understand your query right.
First instead of using lifecycle to verify the biometric check. Can you not use initialization widget which gets called every time before opening up the app. Here is an example.
class Initialize extends StatefulWidget {
_InitializeState createState() => _InitializeState();
}
class _InitializeState extends State<Initialize> {
void initState() {
super.initState();
_initialize();
}
Future<void> _initialize() async {
final userDetails = await getUserSavedDetailsFromStroage();
await doAnyOtherTask();
final user = authService.checkIfPrevLoggedIn(authDetails);
if (user == null) {
_gotoLogin();
} else {
if (userDetails.biometricEnabled) {
final verified = await biometricService.onBiometricVerify();
if (!verified) {
_gotoLogin();
return;
}
}
authService.refreshUser();
_gotoHomePage();
}
}
#override
Widget build(BuildContext context) {
return SplashView();
}
}
And your main.dart file will pretty much look like the following, I am assuming you are using Provider package for state management.
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => AuthService.instance,
child: MaterialApp(
home: Initialize(),
title: 'App Title',
),
);
}
}
you can set a flag that local auth request is pending.
If you got a response then set the flag back to false with a Futuredelay of 150ms.
Request the local auth in your AppLifecycleState.resumed only if the request is not pending.
I'm new to Dart/Flutter and would like to build a simple app where a LinearProgressBar gets updated every second.
Without getting too much into the actual code, I have the following setup working.
A function that calculates the progress, based on passed time.
A LinearProgressBar showing the progress.
A periodic Timer recalculating the progress and updating the progress bar every second.
I debugprint 'tick' every time, the recalculation is done.
Everything is working as expected with one exception. The 'tick' keeps getting printed when I move the app in the background on my Android device.
On native Android, I would cancel my periodic Timer when the 'onPause' event is triggered.
Is there something similar in Flutter? All I could find was 'initState' and 'dispose'. Dispose, however, does not get called when moving the app to background.
I don't want the timer to keep ticking in the background.
On my research, I found this Stack Overflow question onresume-and-onpause-for-widgets-on-flutter. It's answer suggests using TickerProviderStateMixin.
I used it the following way.
class _BarItemState extends State<BarItem> with SingleTickerProviderStateMixin {
Ticker ticker;
num progress = 1.0;
#override
void initState() {
super.initState();
ticker = createTicker((duration) => setState(() {
debugPrint('tick');
progress = duration.inSeconds / 30;
}))
..start();
}
// other stuff omitted
}
It is working, but I'm still not satisfied.
The reason is, that the ticker callback is getting now called every few milliseconds instead of once a second. This seems to me like a waste of resources (I don't need a smooth animation), ... am I overcomplicating things?
Even if it seems that I don't need it for my use case, I still would like to know:
How to handle the onPause/onResume events on my own?
You can override the didChangeAppLifecycleState of the WidgetBindingObserver interface to receive notifications for app lifecycle changes.
There's sample code in this page
You can use lifecycle channel from SystemChannels.
Example:
SystemChannels.lifecycle.setMessageHandler((msg){
debugPrint('SystemChannels> $msg');
});
Output:
I/flutter ( 3672): SystemChannels> AppLifecycleState.paused
I/flutter ( 3672): SystemChannels> AppLifecycleState.resumed
I have being upgrading an application to use the new Mobile Android GNSK but I have noticed that using the new MusicID-Stream is a little bit tricky. If the "identifyAlbumAsync" method get executed before the "audioProcessStart" method(since this need to be executed in a different thread), the application just crashes. In the Gracenote Demo application, the "audioProcessStart" method is continuously running so there is no need to synchronize its execution with the "identifyAlbumAsync" method call. Is it the way it is supposed to be used? It will be convenient if the application didn't crashed at least when the methods are not executed in order. Also in our application, we don't want to have the "audioProcessStart" method continuously like it is done in the demo application. We only want to run the "audioProcessStart" method when the user request identification and when the song playing gets identified , we want to stop the audio processing by calling "audioProcessStop". Is there an easy way to do this? Right now, we are getting the Thread where "identifyAlbumAsync" is running to sleep for 2 seconds in order to make sure that the Thread where the "audioProcessStart" method is supposed to run has time to get executed. Thank you in advance for your prompt response
In the upcoming 1.2 release, IGnMusicIdStreamEvents includes a callback that signals audio-processing has started, and an ID can be synced with this, e.g.:
#Override
public void musicIdStreamProcessingStatusEvent( GnMusicIdStreamProcessingStatus status, IGnCancellable canceller ) {
if (GnMusicIdStreamProcessingStatus.kStatusProcessingAudioStarted.compareTo(status) == 0) {
try {
gnMusicIdStream.identifyAlbumAsync();
} catch (GnException e) { }
}
}
Thanks for the feedback, you're right about this issue. Unfortunately right now sleeping is the best solution. But we are adding support for an explicit sync event in an upcoming release, please stay tuned.