Flutter downloader plugin
It is not working in release apk. Specially in android devices.
#pragma('vm:entry-point') must be placed above the callback function to avoid tree shaking in release mode for Android.
#pragma("vm:entry-point") to mark a function (or other entities, as classes) to indicate to the compiler that it will be used from native code. Without this annotation, the dart compiler could strip out unused functions, inline them, shrink names, etc, and the native code would fail to call it.
#pragma('vm:entry-point')
static void downloadCallback(String id, DownloadTaskStatus status, int progress) {
final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port');
send.send([id, status, progress]);
}
Flutter Downloader Readme : https://pub.dev/packages/flutter_downloader#android-integration
Related
I am using Telephony plugin to develop a SMS app, and according to the similar solution, I added a decorator on the top of the background handler at the top level, then run it in release mode,
after running, debug mode is normal, and foreground is also normal in release mode,only both "background" and "terminated" are incorrect
#pragma('vm:entry-point')
Future<void> onBackgroundMessage(SmsMessage message) async {
debugPrint("onBackgroundMessage called");
............
}
after adding, it's still not working and appeared the same Dart error message:
"Dart Error: Dart_LookupLibrary: library 'package:telephony/telephony.dart' not found."
I have already added the decorator #pragma('vm:entry-point'), still doesn't work.
I solved the problem,just need to change or add a git link in pubspec.yaml,
telephony:
git:
url: https://github.com/definev/Telephony.git
ref: develop
I am getting a crash on some android devices when running my Flutter app.
I have been able to debug a release version of the app and this is the only debug output:
W/FlutterJNI(27448): FlutterJNI.loadLibrary called more than once
W/FlutterJNI(27448): FlutterJNI.prefetchDefaultFontManager called more than once
W/FlutterJNI(27448): FlutterJNI.init called more than once
I donĀ“t know where should I begin to look for the reason of the issue.
The device is showing a gray screen and stops working.
Wherever you create the firebaseMessagingBackgroundHandler, annotate it with #pragma('vm:entry-point') like this:
#pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
}
The reason is explained here:
https://github.com/firebase/flutterfire/blob/master/packages/firebase_messaging/firebase_messaging/example/lib/main.dart#L46
When and how we use it?
How it works?
WidgetsFlutterBinding
You have to use it, in this way:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
https://flutter.dev/docs/resources/architectural-overview#architectural-layers
The WidgetFlutterBinding is used to interact with the Flutter engine. Firebase.initializeApp() needs to call native code to initialize Firebase, and since the plugin needs to use platform channels to call the native code, which is done asynchronously therefore you have to call ensureInitialized() to make sure that you have an instance of the WidgetsBinding.
Answerd By https://stackoverflow.com/users/7015400/peter-haddad
Answer Link https://stackoverflow.com/a/63873689
WidgetsBinding.ensureInitialized() This initialised communication between the Dart Layer and Flutter Engine.
We need to call this method if we need the binding to be initialised before calling [runApp]. Flutter cannot directly interact with flutter engine until and unless binding is established.
Example 1: Shows Firebase platform initialisation between flutter and native code, which Firestore class do internally.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firestore.initializeApp();
runApp(
...
)
}
OR
Example 2: Shows device orientation changes before even app starts, for this also we need to established binding connection.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown
]);
runApp(
...
)
}
Internally, WidgetsBinding.ensureInitialized() supports various binding likes GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding
ServicesBinding listens for platform messages and directs them to the handler for incoming messages (BinaryMessenger).
PaintingBinding is responsible for binding to the painting library.
RenderBinding binds the render tree to the Flutter engine.
WidgetBinding binds the widget tree to the Flutter engine.
SchedulerBinding is the scheduler for running immediate tasks.
SemanticsBinding binds the semantics layer and the Flutter engine.
GestureBinding is a binding for the gesture subsystem.
I am trying to force my Flutter app to only use Portrait mode. My main() method looks like this.
void main() {
SystemChrome.setSystemUIOverlayStyle(uiOverlayStyle);
SystemChrome.setPreferredOrientations(ALLOWED_ORIENTATIONS)
.then((_) => runApp(MyApp()));
}
Here is the definition of ALLOWED_ORIENTATIONS:
const List<DeviceOrientation> ALLOWED_ORIENTATIONS = [
DeviceOrientation.portraitUp
];
I just separated all the settings and such to another file to make modifying them later on easier.
When I run this code, I get the following error.
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception:
ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
If you're running an application and need to access the binary messenger before `runApp()`
has been called (for example, during plugin initialization), then you need to explicitly
call the `WidgetsFlutterBinding.ensureInitialized()` first.
It looks like there is some race condition that's failing. I am just not sure what is causing it. Removing the SystemChrome.setPreferredOrientations() line makes the app compile as expected. So, I am thinking the error has something to do with that line.
Any advice?
Like the error says
If you're running an application and need to access the binary
messenger before runApp() has been called (for example, during
plugin initialization), then you need to explicitly call the
WidgetsFlutterBinding.ensureInitialized() first.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setSystemUIOverlayStyle(uiOverlayStyle);
await SystemChrome.setPreferredOrientations(ALLOWED_ORIENTATIONS);
runApp(MyApp());
}
I'd like to update Firestore document every day at 6 AM automatically.
For instance, there is a quote app and update quote to a new one every morning so that the user can see the different quotes.
I don't mind whether executing code on an iOS device or Android because I have both phones.
But I want an app to update the document even if I'm sleeping.
What is the best way of doing this?
Good news it is somewhat possible.
Background Tasks in a nutshell
On Android you would use WorkManager.
You can ask the Android framework to schedule your task somewhere in the future (exact hours are not supported).
On iOS you enable Background Fetch in XCode or manually edit the Info.plist file.
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
</key>
WorkManager Plugin
Since there is a lot of ceremony to wire everything together there is a handy Flutter plugin which helps you.
The flutter_workmanager plugin supports both WorkManager and performFetch in one unified Dart API.
void callbackDispatcher() {
Workmanager.executeTask((backgroundTask) {
switch(backgroundTask) {
case Workmanager.iOSBackgroundTask:
case "firebaseTask":
print("You are now in a background Isolate");
print("Do some work with Firebase");
Firebase.doSomethingHere();
break;
}
return Future.value(true);
});
}
void main() {
Workmanager.initialize(callbackDispatcher);
Workmanager.registerPeriodicTask(
"1",
"firebaseTask",
frequency: Duration(days: 1),
constraints: WorkManagerConstraintConfig(networkType: NetworkType.connected),
);
runApp(MyApp());
}
Sorry, in this case you will need use WorkManager on Android. This is a way to use background service for that case. In iOS I don't know how.
I think that is not possible to create background services in Flutter because it's run in other context.