I can't receiving notifications when the app is closed or swiped away on huawei device? - flutter

I'm using onsignal notifications with my flutter app,I've tested my app on three Samsunge devices and notifcations working perfectly in all these devices when the app on foreground, background, and also when I swiped it away.
after that I tested the app on huawei device which using EMUI 9.0.1 Os
the notifications only works if the app is active or on background
if I swiped it away I can't receiving any notifications.
Any help would be greatly appreciated, I've been struggling with this for a long time. I'll post my code for setting onesignal below
Future<void> initPlatformState() async {
if (!mounted) return;
OneSignal.shared.setLogLevel(OSLogLevel.verbose, OSLogLevel.none);
OneSignal.shared.setRequiresUserPrivacyConsent(true);
OneSignal.shared.consentGranted(true);
var settings = {
OSiOSSettings.autoPrompt: false,
OSiOSSettings.promptBeforeOpeningPushUrl: true
};
OneSignal.shared.setNotificationReceivedHandler((notification) {
this.setState(() {
print('Notifiaction received');
});
});
OneSignal.shared
.setNotificationOpenedHandler((OSNotificationOpenedResult result) {
this.setState(() {
newUrl = result.notification.payload.additionalData['url'].toString();
});
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => WebNotification(newUrl)));
});
// NOTE: Replace with your own app ID from https://www.onesignal.com
await OneSignal.shared
.init("xxxx-xxxx-xxxx-xxxx-xxxx", iOSSettings: settings);
OneSignal.shared
.setInFocusDisplayType(OSNotificationDisplayType.notification);
OneSignal.shared.inFocusDisplayType();
}

You need to set up a service extension. Take a look at our docs on Background Notifications. Also, consider Notification Behavior when designing your implementation

make sure you sue latest version of onesignal
for huwaii use HMS if possible ( onesignal support HMS )
In your root build.gradle, under buildscript, add the following 2 new lines to your existing repositories and dependencies sections
buildscript {
repositories {
// ...
maven { url 'https://plugins.gradle.org/m2/' } // Gradle Plugin Portal
}
dependencies {
// ...
// OneSignal-Gradle-Plugin
classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.8, 0.99.99]'
}
}
Add the following to the top of your app/build.gradle
apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin'
you need to make user add your app to ignore battry optmztion in huwaii it is (protacted app )
in flutter you can make button and attach it to the app setting ( use these plugin https://pub.dev/packages/app_settings)

Related

Flutter lost focus on phone if Android Auto runs Waze

I launch Waze from App with this code with button click:`enter code here
void launchWaze(String lat, String lng) async {
Uri url = Uri.parse(
'https://waze.com/ul?ll=$lat,$lng&navigate=yes');
Uri fallbackUrl =
Uri.parse('https://waze.com/ul?ll=$lat,$lng&navigate=yes');
try {
bool launched = await launchUrl(
url,
mode: LaunchMode.externalApplication, // or externalNonBrowserApplication,
);
} catch (e) {
await launchUrl(fallbackUrl);
}
}
Waze launched from app, on Android Auto starts and route is fine, but the focus not in my app anymore so I can not use the app to start other location, only a text you use Waze on Android Auto. Back button not working...
Is there any solution to navigate on Android Auto and use the app on phone the same time?

Flutter Push Notification using SignalR

I'm using SignalR for push notifications on my Flutter app and that works ok. I get the message from the backend and show notification using flutter_local_notifications. The problem is that the SignalR service would shut down after some time.
How can I make my app stay on in the background? and even start on reboot?
Here's my code:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:isolate_test/Model/UserMessageModel.dart';
import 'package:signalr_core/signalr_core.dart';
import 'EndPointService.dart';
import 'NotificationService.dart';
class SignalRProvider {
static String appName = "NOTIFICATION";
static String? userName = "";
static String deviceName = "android_app";
static List<UserMessageModel> messages = <UserMessageModel>[];
HubConnection connection = HubConnectionBuilder()
.withUrl(
'my_url',
HttpConnectionOptions(
logging: (level, message) => print(message),
))
.withAutomaticReconnect()
.withHubProtocol(JsonHubProtocol())
.build();
Function(bool update)? onMessagesUpdateCallback;
SignalRProvider({
this.onMessagesUpdateCallback,
});
setUsername(String username) {
userName = username;
}
Future initSignalR(BuildContext context) async {
WidgetsFlutterBinding.ensureInitialized();
await NotificationService().init();
connection.on('SignalRUserReceiveMessage', (message) async {
var data = message!.first;
if (data != null) {
UserMessageModel msg = UserMessageModel.fromJson(data);
messages.add(msg);
msg.showNotification();
}
if (onMessagesUpdateCallback != null) {
onMessagesUpdateCallback!(true);
}
});
connection.on('SignalRMonitoringMessage', (message) async {
var data = message!.first;
if (data != null) {
UserMessageModel msg = UserMessageModel.fromJson(data);
messages.add(msg);
msg.showNotification();
}
if (onMessagesUpdateCallback != null) {
onMessagesUpdateCallback!(true);
}
});
connection.on("SignalRReceiveConnectedMessage", (message) async {
await connection.send(methodName: 'SignalRInit', args: [
userName,
appName,
connection.connectionId,
]);
});
connection.on("SignalRReceiveDisconnectedMessage", (message) async {
if (connection.state == HubConnectionState.disconnected) {
connection.start();
}
});
await connection.start();
}
List<UserMessageModel> getMessages() {
return messages;
}
Future deleteMessage(UserMessageModel _msg) async {
if (_msg == null) return;
var response =
await EndPointService().SetupApi("Message", "", []).httpDelete(
HeaderEnum.BasicHeaderEnum,
ResponseEnum.ResponseModelEnum,
jsonEncode(_msg),
);
}
addOrUpdateMessage(UserMessageModel _msg) {
if (_msg == null) return;
if (messages != null) {
var found =
messages.firstWhere((e) => e.user == _msg.user && e.id == _msg.id);
var index =
messages.indexWhere((e) => e.user == _msg.user && e.id == _msg.id);
if (found != null) {
messages[index] = _msg;
} else {
messages.add(_msg);
}
if (onMessagesUpdateCallback != null) {
onMessagesUpdateCallback!(true);
}
}
}
setMessagesUpdateCallback(Function(bool update) func) {
onMessagesUpdateCallback = func;
}
}
SignalR problems
SignalR for Flutter uses web sockets and SSE to receive messages from the SignalR service. If the app was terminated because the user restarted their phone or the OS shut down the app to save battery, these push notifications would not be received by the app.
To overcome this, app developers (and SignalR) have to use FCM on Android, and APNs on iOS (or FCM which will also use APNs on iOS). All other approaches will be more limited because the operating systems do not allow users to keep background processes running the entire time. This was actually allowed years ago, but the operating systems have made these changes to save the user battery - they enforce that all apps go through the same push notification medium - FCM on Android, APNs on iOS.
SignalR for Flutter uses neither FCM nor APNs. At it's current state, SignalR is not well suited for Android or iOS - take a look at the comments with people struggling with similar problems to you on How to use signalr in Android.
Alternative solution
The simplest / easiest way to get started is to use Firebase Cloud Messaging.
On Android, it will be used directly to send messages to devices, and
on iOS, FCM will use APNs to reach devices reliably
Caveat: On Android, there is a more complicated alternative called unifiedpush, but the limitations include showing a notification to the user at all times to handle background notifications.
My analysis: This is all done based on my quick investigation by reading the pubspec.yaml, the GitHub issues on the original repo, the SignalR documentation, and some experience implementing Push Notifications for Flutter.
Disclosure: I just released a push notification library 2 days ago called push which would be well suited to these types of Push Notification packages making the transformation to using FCM on Android and APNs on iOS. However, as an app developer, in most cases, you should use firebase_messaging, not push.
I worked with SignalR but on native Platform(IOS & Android), I made stock app and get realtime price. When app go to background, I will disconnect with SignalR server after 5 second, and when app go to foreground again, I check if app's current state not connect to server SignalR, I'll connect again. I think it not good if your app still connect and receiver data from signalR server in background state.

Accepting payments in Flutter Web

I am creating an application in Flutter Web that needs to collect payment information to create subscription charges. My plan was to use Stripe to do this, however, after making all the necessary methods for Stripe, I found that Stripe only accepts card data through Stripe Elements. Upon further research, I saw that essentially all payment platforms do this to maintain PCI compliance.
Is there any method of embedding Stripe elements(or any equivalent) into my application or is there an easier method of accepting payments with Flutter Web?
There's an unofficial Flutter Stripe package that might be what you're after: https://pub.dev/packages/stripe_payment
There's a new package called stripe_sdk, that appears to have Web support. I haven't tried it yet, but it says Web support in the description and has a web demo aswell :)
Also the old packages for mobile won't work for web, because they rely on WebView, which is not supported (and wouldn't make much sense) on web.
In case you're using Firebase as a backend, there's a stripe payments extension you can install in Firebase which makes it easy. How it works is you add a checkout_session in to a user collection and keep listening on the document. Stripe extension will update the document with a unique payments url and we just open that URL in a new tab to make the payment in the tab. We're using it in our web app, and it's working.
Something like :
buyProduct(Product pd) async {
setState(() {
loadingPayment = true;
});
String userUid = FirebaseAuth.instance.currentUser!.uid;
var docRef = await FirebaseFirestore.instance
.collection('users')
.doc(userUid)
.collection('checkout_sessions')
.add({
'price': pd.priceId,
'quantity': pd.quantity,
'mode': 'payment',
'success_url': 'https://yourwebsite/purchase-complete',
'cancel_url': 'https://yourwebsite/payment-cancelled',
});
docRef.snapshots().listen(
(ds) async {
if (ds.exists) {
//check any error
var error;
try {
error = ds.get('error');
} catch (e) {
error = null;
}
if (error != null) {
print(error);
} else {
String url = ds.data()!.containsKey('url') ? ds.get('url') : '';
if (url != '') {
//open the url in a new tab
if (!isStripeUrlOpen) {
isStripeUrlOpen = true;
setState(
() {
loadingPayment = false;
},
);
launchUrl(Uri.parse(url));
}
}
}
}
}
},
);
}

Flutter web PWA install prompt from within the app

I'm working on a Flutter Web PWA app and having trouble with triggering the Add To Home Screen prompt from within the flutter app. I understand it can be triggered using Javascript with the code below, but how do I do this from my Flutter dart file?
buttonInstall.addEventListener('click', (e) => {
// Hide the app provided install promotion
hideMyInstallPromotion();
// Show the install prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
deferredPrompt.userChoice.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('User accepted the install prompt');
} else {
console.log('User dismissed the install prompt');
}
})
});
Currently, Flutter web can only prompt PWA installs from the browser. The issue with displaying PWA install prompt is it breaks the compatibility/design with Android/iOS builds as the feature is web-specific.
A different approach that you can take here is by displaying "PWA install" reminders when the app is run on web. Otherwise, it's best to file this as a feature request.
I created the pwa_install package specifically for this purpose.
1. Update index.html
<!-- Capture PWA install prompt event -->
<script>
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
deferredPrompt = e;
});
function promptInstall(){
deferredPrompt.prompt();
}
// Listen for app install event
window.addEventListener('appinstalled', () => {
deferredPrompt = null;
appInstalled();
});
// Track how PWA was launched (either from browser or as PWA)
function getLaunchMode() {
const isStandalone = window.matchMedia('(display-mode: standalone)').matches;
if(deferredPrompt) hasPrompt();
if (document.referrer.startsWith('android-app://')) {
appLaunchedAsTWA();
} else if (navigator.standalone || isStandalone) {
appLaunchedAsPWA();
} else {
window.appLaunchedInBrowser();
}
}
</script>
2. Call PWAInstall().setup()
You can call this method in main.dart before calling runApp()
Future<void> main() async {
// Add this
PWAInstall().setup(installCallback: () {
debugPrint('APP INSTALLED!');
});
runApp(MaterialApp(home: App()));
}
3. Check if the Install Prompt is enabled
Before calling the promptInstall_() method, you can check if the Install Prompt is available using PWAInstall().installPromptEnabled.
installPromptEnabled will be true if:
The app was launched in a browser (It doesn't make sense to prompt a PWA install if the app is already running as a PWA)
The beforeinstallprompt event was captured.
promptInstall_() won't do anything if installPromptEnabled is false so you should check this flag before attempting to call the prompt.
4. Call PWAInstall().promptInstall_()
Finally, call PWAInstall().promptInstall_() to show the install prompt.
Note that this will not work on Safari since Safari does not implement the beforeinstallprompt method this package relies on.

Flutter Square Plugin crashes in release only

Flutter Square plugin crashes only in release when I use invalid card or press back.
But when I use flutter run --release & hook up my mobile. the crashes don't occur & the app works perfectly!
here's the code we used
void _pay() async {
await InAppPayments.setSquareApplicationId(sqAppId);
try {
await InAppPayments.startCardEntryFlowWithBuyerVerification(
money: Money((money) => money
..amount = 0
..currencyCode = 'USD'),
collectPostalCode: true,
contact: Contact((ContactBuilder contact) {
return contact.givenName = username;
}),
buyerAction: "Store",
squareLocationId: sqLocationId,
onBuyerVerificationSuccess: (BuyerVerificationDetails result) {
addCard(result.nonce, result.card.postalCode);
},
onBuyerVerificationFailure: (err) {
return showErrorDialog(context, err.toString());
},
onCardEntryCancel: () {});
} on Exception catch (e) {
print(e);
}
}
What is the difference between flutter build & flutter run --release ?
Could I use the APK out from flutter run & upload it to google play ?
In the release version you have to add the PERMISSIONS explicitly.
Try adding android.permission.INTERNET to the Manifest file.
Add
<uses-permission android:name="android.permission.INTERNET"/>
to the AndroidManifest.xml located in android/app/src/main.
For your question about uploading a debuggable apk, Google Play-Upload will reject your file.
Refer to this link for the differences between release and debug.