I have an android app created with Unity, I can send notifications to this app from OneSignal web site and from my php website successfully. Now I want to send notifications from a flutter app (android). I tried the onesignal sdk for flutter example but it sends the notification to the flutter app and not to Unity app. I don't know where am I wrong :
Future<void> initPlatformState() async {
if (!mounted) return;
var settings = {
OSiOSSettings.autoPrompt: false,
OSiOSSettings.promptBeforeOpeningPushUrl: true
};
// NOTE: Replace with your own app ID from https://www.onesignal.com
await OneSignal.shared
.init("9a98990f-40fa-455e-adda-ccd474594f41", iOSSettings: settings);
OneSignal.shared
.setInFocusDisplayType(OSNotificationDisplayType.notification);
bool requiresConsent = await OneSignal.shared.requiresUserPrivacyConsent();
this.setState(() {
_enableConsentButton = requiresConsent;
});
}
void _handleSendNotification() async {
var status = await OneSignal.shared.getPermissionSubscriptionState();
var playerId = status.subscriptionStatus.userId;
var imgUrlString =
"https://vaars.000webhostapp.com/MrNutella/logonutella.png";
var notification = OSCreateNotification(
playerIds: [playerId],
content: "this is a test from OneSignal's Flutter SDK",
heading: "Test Notification",
iosAttachments: {"id1": imgUrlString},
bigPicture: imgUrlString,
buttons: [
OSActionButton(text: "test1", id: "id1"),
OSActionButton(text: "test2", id: "id2")
]);
var response = await OneSignal.shared.postNotification(notification);
this.setState(() {
_debugLabelString = "Sent notification with response: $response";
});
}
It sounds like you're looking for P2P (user-user) notifications. You will need a way to get the player id of the target app (Unity) from the Flutter app.
Related
I'm trying to send Expo push notifications to multiple devices. I'm retrieving the Expo tokens from Firestore. When I enter the tokens manually, it works! It sends the notification to both devices I'm using, but when I retrieve the data from Firestore, it only sends the notification to one device.
async function sendPushNotification(readx) {
const message = {
to: readx,
sound: "default",
title: "Original Title",
body: "And here is the body!",
data: { someData: "goes here" },
};
const retrieveNetwork = async () => {
try {
//const querySnapshot = await getDocs(collection(db, "cities"));
const q = query(collection(db, "users"));
const querySnapshot = await getDocs(q);
setRead(querySnapshot.docs.map((doc) => doc.data().expoUser));
setReadx(JSON.stringify(read));
} catch (e) {
alert(e);
}
};
The retrieving of data from the firestore seems to be an issue , as your code is using the Snapshot for querying the data ,it should get the token id for both the devices in the loop and then return to the await sync to call the notification function.As per the Firebase documentation on reading multiple documents, you'll see that it uses the data() function on each DocumentSnapshot to get at the fields of that document.
So try to modify accordingly,like use doc.role and doc.token instead of doc.data().role and doc.data().token.
Check this example code below:
let tokenList = []; const userNotificationTokenDocs = await db.collection("userToken").doc(userId).get() .then(querySnapshot => { querySnapshot.forEach((doc) => { console.log(doc.data().Tokens); tokenList.push(doc.data().Tokens); }); return null; });
Also you may try adding the below to your code:
userToken.forEach((token) => { console.log(token); tokens.push(token); });
Checkout these following with similar implementation:
Push notification firestore
Triggering expo sdk to push notification to users
Notification to a collection of token
Array token sending notification
Just solved. Need to change
<Button
title="Press to Send Notification"
onPress={async () => {
await sendPushNotification(expoPushToken);
}}
/>
to
<Button
title="Press to Send Notification"
onPress={async () => {
await sendPushNotification(readx);
}}
/>
I am trying to access Accessibility from my background service app which uses flutter_background_service plugin. But I can't listen to the Accessibility events. I am also receiving an error:
Tried to send a platform message to Flutter, but FlutterJNI was detached from native C++. Could not send. Channel: x-slayer/accessibility_event. Response ID: 34
But when the app is open(in recent app) the service is working fine. How do I fix it?
Here is my code. I am trying to fix this for a day, but cant find a way out:
Future<void> initializeService() async {
final service = FlutterBackgroundService();
await service.configure(
androidConfiguration: AndroidConfiguration(
// this will be executed when app is in foreground or background in separated isolate
onStart: onStart,
// auto start service
autoStart: true,
isForegroundMode: true,
),
iosConfiguration: IosConfiguration(
// auto start service
autoStart: true,
// this will be executed when app is in foreground in separated isolate
onForeground: onStart,
// you have to enable background fetch capability on xcode project
onBackground: onIosBackground,
),
);
service.startService();
}
bool onIosBackground(ServiceInstance service) {
WidgetsFlutterBinding.ensureInitialized();
print('FLUTTER BACKGROUND FETCH');
return true;
}
void onStart(ServiceInstance service) async {
// Only available for flutter 3.0.0 and later
DartPluginRegistrant.ensureInitialized();
// For flutter prior to version 3.0.0
// We have to register the plugin manually
if (service is AndroidServiceInstance) {
service.on('setAsForeground').listen((event) {
service.setAsForegroundService();
});
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
}
service.on('stopService').listen((event) {
service.stopSelf();
});
// bring to foreground
Timer.periodic(const Duration(seconds: 1), (timer) async {
if (service is AndroidServiceInstance) {
service.setForegroundNotificationInfo(
title: "My App Service",
content: "Updated at ${DateTime.now()}",
);
}
/// you can see this log in logcat
print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}');
void PeaceBox() {
StreamSubscription<AccessibilityEvent>? _subscription;
List<AccessibilityEvent?> events = [];
overlayRequest();
print("Started listening");
// FlutterOverlayWindow.overlayListener.listen((event) {
// print("$event");
// });
String text = "";
// print(text.split(" "));
FlutterAccessibilityService.accessStream.listen((event) {
});
}
PeaceBox();
// test using external plugin
final deviceInfo = DeviceInfoPlugin();
String? device;
if (Platform.isAndroid) {
final androidInfo = await deviceInfo.androidInfo;
device = androidInfo.model;
}
if (Platform.isIOS) {
final iosInfo = await deviceInfo.iosInfo;
device = iosInfo.model;
}
service.invoke(
'update',
{
"current_date": DateTime.now().toIso8601String(),
"device": device,
},
);
});
}
My app has chatting function. And I have implemented Firebase Cloud Messaging and Local Notification.
So when someone sends me a message, notification(one inside android status bar) and local notification(one on the upper part of the screen that holds for like 3 seconds) is shown. They show up when app is opened, on background, and also when app is terminated. (So far so good)
But I don't want both notifications(1. fcm notification, 2. local notification) to show up when I'm already in the chat page with that person. And I have no idea where to start.
Below is my code for handling fcm and show local notification. They are inside main.dart and the main function calls initializeFCM before returning my root page.
Future<void> initializeFCM() async {
await Firebase.initializeApp();
FirebaseMessaging messaging = FirebaseMessaging.instance;
// Firebase Messaging
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
// print('User granted permission');
} else
if (settings.authorizationStatus == AuthorizationStatus.provisional) {
// print('User granted provisional permission');
} else {
// print('User declined or has not accepted permission');
}
// Get any messages which caused the application to open from
// a terminated state.
RemoteMessage? initialMessage = await messaging.getInitialMessage();
if (initialMessage != null) {
handleMessage(initialMessage);
}
// initialize local notification
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
// terminated app을 local notification 눌러서 열었을 때 - payload가 정상적으로 동작하지 않음
final NotificationAppLaunchDetails? notificationAppLaunchDetails = await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
final didNotificationLaunchApp = notificationAppLaunchDetails?.didNotificationLaunchApp ?? false;
if (didNotificationLaunchApp) {
onSelectNotification(notificationAppLaunchDetails!.payload);
}
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
showLocalNotification(message);
});
FirebaseMessaging.onBackgroundMessage(showLocalNotification);
FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
}
void handleMessage(RemoteMessage message) {
if (message.data["screen"] == "message") {
Navigator.push(
navigatorKey.currentContext!,
MaterialPageRoute(
builder: (context) => MessageListPage(),
)
);
}
}
Future<void> onSelectNotification(payload) async {
if(payload != null) {
Map<String, dynamic> data = json.decode(payload);
if (data['screen'] == "message") {
Navigator.push(
navigatorKey.currentContext!,
MaterialPageRoute(
builder: (context) => MessageListPage(),
)
);
}
}
}
Future<void> showLocalNotification(RemoteMessage message) async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
// String screen = message.data['screen'];
// iOS heads up notification setting
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true, // Required to display a heads up notification
badge: true,
sound: true,
);
// android channel setting
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
importance: Importance.max,
);
// initialize local notification
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin.initialize(InitializationSettings(
android: AndroidInitializationSettings('#drawable/mentea_ic_stat_name'),
iOS: IOSInitializationSettings()),
onSelectNotification: onSelectNotification);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
// If `onMessage` is triggered with a notification, construct our own
// local notification to show to users using the created channel.
if (notification != null && android != null) {
// print('Message also contained a notification: ${message.notification}');
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
'high_importance_channel', //channel.id,
'High Importance Notifications', //channel.name,
icon: android.smallIcon,
color: primaryColor,
// other properties...
),
),
payload: json.encode(message.data)
);
}
}
I don't know if you still have this problem, but I'll post my solution here.
It happens that when we send a push notification with the notification message feature, the FCM plugin automatically sends a notification on the device if the App is in background and finished, where we can only customize the foreground notification through Local Notifications or other solutions within of the App. So the solution pointed out in the Firebase documentation for this situation is to send the push notification only as a data message, without including the notification object. Below I show the examples and the documentation link.
Documentation: https://firebase.google.com/docs/cloud-messaging/concept-options?authuser=1&hl=pt#notifications_and_data_messages
Combined notification example:
const payload = {
notification: {
title: '$FooCorp up 1.43% on the day',
body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
},
data: {
stock: 'GOOG',
open: '829.62',
close: '635.67'
}
};
Notification example with data message only:
const payload = {
data: {
score: '850',
time: '2:45'
}
};
Notification example with notification message only:
const payload = {
notification: {
title: '$FooCorp up 1.43% on the day',
body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
}
};
So, so that you can customize all forms of notification (foreground, background and terminated), send a push notification through your backend as a data message only.
I have a flutter project (iOS, Android) that uses WebRTC. I need to send video from camera (working correctly) and screen capture by WebRTC. How to share the screen on WebRTC with the flutter_webrtc package?
You can use the flutter_webrtc plugin and do like this method ( use getDisplayMedia method in webRTC to get display ) :
class ScreenSharing {
MediaStream? _localStream;
final RTCVideoRenderer _localRenderer = RTCVideoRenderer();
Future<void> _makeScreenSharing() async {
final mediaConstraints = <String, dynamic>{'audio': true, 'video': true};
try {
var stream = await navigator.mediaDevices.getDisplayMedia(mediaConstraints);
_localStream = stream;
_localRenderer.srcObject = _localStream;
} catch (e) {
print(e.toString());
}
}
}
I want to store the onesignal User Id in the database when the user install my app first time. I wrote the following code which is not allowing me to do so.
However when the user Logged out from the app and re-login then I am able to retrieve the onesignal user ID and able to save in the Database.
Future<void> initPlatformState(username) async {
if (!mounted) return;
OneSignal.shared.setLogLevel(OSLogLevel.verbose, OSLogLevel.none);
OneSignal.shared.setRequiresUserPrivacyConsent(_requireConsent);
var settings = {
OSiOSSettings.autoPrompt: false,
OSiOSSettings.promptBeforeOpeningPushUrl: true
};
OneSignal.shared
.setSubscriptionObserver((OSSubscriptionStateChanges changes) {
print("SUBSCRIPTION STATE CHANGED: ${changes.jsonRepresentation()}");
});
OneSignal.shared.setPermissionObserver((OSPermissionStateChanges changes) {
print("PERMISSION STATE CHANGED: ${changes.jsonRepresentation()}");
});
OneSignal.shared.setEmailSubscriptionObserver(
(OSEmailSubscriptionStateChanges changes) {
print("EMAIL SUBSCRIPTION STATE CHANGED ${changes.jsonRepresentation()}");
});
await OneSignal.shared
.init("MY Onesignal APP ID", iOSSettings: settings);
OneSignal.shared
.setInFocusDisplayType(OSNotificationDisplayType.notification);
var status = await OneSignal.shared.getPermissionSubscriptionState();
onesignalUserId = status.subscriptionStatus.userId;
print("player ID: "+ onesignalUserId.toString()); // printing only in re-login
_saveOneSignalId(onesignalUserId,username); // my save funtion into the DB
}
You can call the below function inside your main.dart file when initialising the One Signal to get playerId/userId. The below function is called when user opend the app for first time or when the userId (playerId) changes.
OneSignal.shared.setSubscriptionObserver((OSSubscriptionStateChanges changes) async {
String onesignalUserId = changes.to.userId;
print('Player ID: ' + onesignalUserId);
}
The playerId/userId can be used to send test notification or notifications to particular user.
Please try this.
OneSignal.shared.setSubscriptionObserver((OSSubscriptionStateChanges changes)
async{
var status = await OneSignal.shared.getPermissionSubscriptionState();
if (status.subscriptionStatus.subscribed){
String onesignalUserId = status.subscriptionStatus.userId;
print('Player ID: ' + onesignalUserId);
}