Background Actions On ios React native - ios

import BackgroundService from 'react-native-background-actions';
const veryIntensiveTask = async (taskDataArguments) => {
const { delay } = taskDataArguments;
await new Promise( async (resolve) => {
for (let i = 0; BackgroundService.isRunning(); i++) {
console.log(i);
await sleep(delay);
}
});
};
const options = {
taskName: 'Example',
taskTitle: 'ExampleTask title',
taskDesc: 'ExampleTask description',
taskIcon: {
name: 'ic_launcher',
type: 'mipmap',
},
color: '#ff00ff',
linkingURI: 'yourSchemeHere://chat/jane', // See Deep Linking for more info
parameters: {
delay: 1000,
},
};
await BackgroundService.start(veryIntensiveTask, options);
await BackgroundService.updateNotification({taskDesc: 'New ExampleTask description'});
await BackgroundService.stop();
Using this code and is working fine on android but not working on IOS also integrated as documentation. But it is not showing notification on IOS.

Related

Playwright Component Testing with ContextApi

I have created a small React app and I want to test it using Playwright component testing
I have 3 components: App -> ChildComponent -> ChildChildComponent
I want to render (mount) the ChildComponent directly, and make assertions on it, but when I do that, some ContextApi functions that are defined in the App in the normal flow, are now undefined as the App component is not part of the component test.
So i'v trying to render the ChildComponent together with a face ContextApi Provider and pass mocks of those undefined functions, and then I get an infinite render loop for some reason.
How can I go about this, as this use case is typical in react component test.
Here is the test with all my failed mocking attempts separated:
test.only("validate CharacterModal", async ({ page, mount }) => {
const data = ['some-mocked-irrelevant-data']
// const setCurrentCharacter = () => {};
// const setIsCharacterModalOpen = () => {};
// const setCurrentCharacterMocked = sinon.stub("setCurrentCharacter").callsFake(() => {});
// const setIsCharacterModalOpenMocked = sinon.stub("setCurrentCharacter").callsFake(() => {});
// const setCurrentCharacter = jest.fn();
// const setIsCharacterModalOpen = jest.fn();
// const setCurrentCharacter = (): void => {};
// const setIsCharacterModalOpen = (): void => {};
// const setIsCharacterModalOpen = (isCharacterModalOpen: boolean): void => {};
const AppContext = React.createContext<any>(null);
await page.route("**/users*", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(data),
});
});
const component = await mount(
<AppContext.Provider value={{ setCurrentCharacterMocked, setIsCharacterModalOpenMocked }}>
<CharacterModal />
</AppContext.Provider>
);
expect(await component.getByRole("img").count()).toEqual(4);
});
The beforeMount hook can be used for this. I recently added docs about this: https://github.com/microsoft/playwright/pull/20593/files.
// playwright/index.jsx
import { beforeMount, afterMount } from '#playwright/experimental-ct-react/hooks';
// NOTE: It's probably better to use a real context
const AppContext = React.createContext(null);
beforeMount(async ({ App, hooksConfig }) => {
if (hooksConfig?.overrides) {
return (
<AppContext.Provider value={hooksConfig.overrides}>
<App />
</AppContext.Provider>
);
}
});
// src/CharacterModal.test.jsx
import { test, expect } from '#playwright/experimental-ct-react';
import { CharacterModal } from './CharacterModal';
test('configure context through hooks config', async ({ page, mount }) => {
const component = await mount(<CharacterModal />, {
hooksConfig: { overrides: 'this is given to the context' },
});
});

Custom iOS notifications sound local notifications package Flutter

I'm using Firebase Cloud Messaging to send notifications to my flutter app, and I'm using the flutter_local_notifications package to handle them, but when I tried to change the default notification sound it worked for android but didn't work for iOS, keep in mind that I add the "sound.aiff" to the root of the native iOS project, can anyone show me what I'm missing here, and thanks in advance
class FCMFunctions {
static final FCMFunctions _singleton = new FCMFunctions._internal();
FCMFunctions._internal();
factory FCMFunctions() {
return _singleton;
}
late FirebaseMessaging messaging;
//************************************************************************************************************ */
/// Create a [AndroidNotificationChannel] for heads up notifications
late AndroidNotificationChannel channel;
/// Initialize the [FlutterLocalNotificationsPlugin] package.
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
//************************************************************************************************************ */
Future initApp() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
messaging = FirebaseMessaging.instance;
if (!kIsWeb) {
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
importance: Importance.high,
sound: RawResourceAndroidNotificationSound('sound'),
playSound: true,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
/// Create an Android Notification Channel.
///
/// We use this channel in the `AndroidManifest.xml` file to override the
/// default FCM channel to enable heads up notifications.
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
//for IOS Foreground Notification
await messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initializeNotifications() async {
var initializationSettingsAndroid =
const AndroidInitializationSettings('icon');
var initializationSettingsIOS = const IOSInitializationSettings();
//var initializationSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onSelectNotification: onSelectNotification,
);
}
Future onSelectNotification(String? payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
navigatorKey.currentState!.pushNamed(Routes.blackCurrency,
arguments: false); //message.data['category']
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Future subscripeToTopics(String topic) async {
await messaging.subscribeToTopic(topic);
}
///Expire : https://firebase.google.com/docs/cloud-messaging/manage-tokens
Future<String?> getFCMToken() async {
final fcmToken = await messaging.getToken();
return fcmToken;
}
void tokenListener() {
messaging.onTokenRefresh.listen((fcmToken) {
print("FCM Token dinlemede");
// TODO: If necessary send token to application server.
}).onError((err) {
print(err);
});
}
/// IOS
Future iosWebPermission() async {
if (Platform.isIOS || kIsWeb) {
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
}
}
///Foreground messages
///
///To handle messages while your application is in the foreground, listen to the onMessage stream.
void foreGroundMessageListener() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print(
'///////////////////////////// NOTIFICATIONS ARE COMMING /////////////////////////////');
print('${message.notification!.body} ');
print("Message data type : ${message.data.runtimeType}");
var bodyRaw = message.data['body'];
var body = List<dynamic>.from(jsonDecode(bodyRaw ?? '[]'));
print("body : $body");
String bodyMessage = '';
if (body.first['sale'] == null) {
bodyMessage = body.first['name'];
} else if (body.first['name'] == null) {
bodyMessage = body.first['sale'];
} else {
bodyMessage =
body.map((e) => e['name'] + '-' + e['sale']).join(', ').toString();
}
RemoteNotification? notification = RemoteNotification(
android: const AndroidNotification(
smallIcon: 'assets/imgs/logo.png',
priority: AndroidNotificationPriority.highPriority,
visibility: AndroidNotificationVisibility.public,
),
apple: const AppleNotification(
sound: AppleNotificationSound(
name: 'sound',
volume: 1.0,
),
),
title: message.data['title'],
body: bodyMessage,
);
// message.notification;
AndroidNotification? android =
notification.android; //message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
importance: Importance.max,
priority: Priority.max,
ticker: 'ticker',
sound: const RawResourceAndroidNotificationSound('sound'),
// icon: "#mipmap/icon",
playSound: true,
styleInformation: const DefaultStyleInformation(true, true),
),
iOS: const IOSNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
sound: 'sound',
),
),
);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
navigatorKey.currentState!.pushNamed(Routes.blackCurrency,
arguments: false); //message.data['category']
// Navigator.pushNamed(
// context,
// '/message',
// arguments: MessageArguments(message, true),
// );
});
}
}
final fcmFunctions = FCMFunctions();
Your server administrator will send you the sound name in notification payload which you added in iOS folder. Payload will look like this
{
aps =
{
alert = "notification message";
sound = "example.caf";
};
}
more information check this reference link
49
49
custom sound file for your app, follow this apple documentation.

How to send an image from React-Native app to the Django server using Expo ImagePicker?

const [image, setImage] = useState(null);
const pickImage = async () => {
// No permissions request is necessary for launching the image library
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result.uri);
if (!result.cancelled) {
setImage(result);
}
};
I study React-Native and Django and I know about FormData, but I don't understand how put into my code.
Try the below code
const pickImage = async () => {
// No permissions request is necessary for launching the image library
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result.uri);
if (!result.cancelled) {
postToServer(result)// must be a object not array, if its array find first element if selecting only one image
setImage(result);
}
};
//just function to upload to server
const postToServer = (img)=>{
const formData = new FormData();
formData.append('photo', {
uri: img.uri,
type: 'image/jpeg', // or photo.type
name: 'testPhotoName'
});
const options = {
method: 'POST',
body: formData,
// If you add this, upload won't work
// headers: {
// 'Content-Type': 'multipart/form-data',
// }
};
fetch('your-upload-url', options);
}

How to make a flutter app recieve push notifications from firebase for IOS

I am currently trying to set up push notifications for my flutter app (on IOS, it works on android). I have tried both the Flutter Local Notifications and Awesome Notifications but neither are yielding any notifications. I am testing on a physical device and I have gone through the process of setting up my APNs with firebase.
import 'dart:io';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
const AndroidNotificationChannel channel = AndroidNotificationChannel(
"general_notifications", " General Notifications",
description: "This channel is used for ALL notification",
importance: Importance.max);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
AwesomeNotifications().createNotificationFromJsonData(message.data);
}
class FirebaseNotifications {
initialize() async {
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
var initalizationSettingsAndroid =
AndroidInitializationSettings("#mipmap/ic_launcher");
var initializationSettingsIOS = IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true);
var initializationSettings = InitializationSettings(
android: initalizationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
if (Platform.isAndroid) {
RemoteNotification? notification = message.notification;
AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails(channel.id, channel.name,
channelDescription: channel.description,
importance: Importance.max,
priority: Priority.high,
groupKey: channel.groupId);
NotificationDetails notificationDetails =
NotificationDetails(android: androidNotificationDetails);
flutterLocalNotificationsPlugin.show(notification.hashCode,
notification!.title, notification.body, notificationDetails);
List<ActiveNotification>? activeNotifications =
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.getActiveNotifications();
if (activeNotifications!.length > 0) {
List<String> lines =
activeNotifications.map((e) => e.title.toString()).toList();
InboxStyleInformation inboxStyleInformation = InboxStyleInformation(
lines,
contentTitle: "${activeNotifications.length - 1} messages",
summaryText: "${activeNotifications.length - 1} messages");
AndroidNotificationDetails groupNotificationDetails =
AndroidNotificationDetails(channel.id, channel.name,
channelDescription: channel.description,
styleInformation: inboxStyleInformation,
setAsGroupSummary: true);
NotificationDetails groupNotificationDetailsPlatformSpefics =
NotificationDetails(android: groupNotificationDetails);
await flutterLocalNotificationsPlugin.show(
0, '', '', groupNotificationDetailsPlatformSpefics);
}
} else if (Platform.isIOS) {
// FirebaseMessaging.instance.setF
RemoteNotification? notification = message.notification;
IOSNotificationDetails iOSNotificationDetails = IOSNotificationDetails(
presentAlert: true, presentBadge: true, presentSound: true);
NotificationDetails notificationDetails =
NotificationDetails(iOS: iOSNotificationDetails);
flutterLocalNotificationsPlugin.show(notification.hashCode,
notification!.title, notification.body, notificationDetails);
}
AwesomeNotifications().initialize(null, [
NotificationChannel(
channelKey: 'basic_channel',
channelName: 'Basic notifications',
channelDescription: 'Notification channel for basic tests',
defaultColor: const Color(0xFF9D50DD),
ledColor: Colors.white,
playSound: true,
)
]);
});
}
Future<String?> getToken() async {
String? token = await FirebaseMessaging.instance.getToken();
print(token);
return token;
}
subscribeToTopic(String topic) async {
await FirebaseMessaging.instance.subscribeToTopic(topic);
}
}
Not sure where the issue is (client side, or inside my apple settings)...

IOS Notification Permission alert does not show

SDK Version: 39.0.0
Platforms(Android/iOS/web/all): All
I am not getting accept or decline notifications permissions alert when loading my app in production.
I have tried clearing certificates and keys and allowing expo to add everything from a clean slate, but still no luck. I am starting to think maybe it’s my code which is the reason why the alert doesn’t get fired.
import Constants from "expo-constants";
import * as Notifications from "expo-notifications";
import { Permissions } from "expo-permissions";
import { Notifications as Notifications2 } from "expo";
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: false
})
});
export default class LoginScreen extends React.Component {
state = {
email: "",
password: "",
notification: {},
errorMessage: null
};
async componentDidMount() {
this.registerForPushNotificationsAsync();
//Notifications.addNotificationReceivedListener(this._handleNotification);
Notifications2.addListener(data => {
this.setState({ notification: data });
});
Notifications.addNotificationResponseReceivedListener(
this._handleNotificationResponse
);
}
_handleNotification = notification => {
this.setState({ notification: notification });
};
_handleNotificationResponse = response => {
console.log(response);
};
handleLogin = async () => {
try {
const { email, password } = this.state;
const expoPushToken = await Notifications.getExpoPushTokenAsync();
console.log(expoPushToken);
const userinfo = await firebase
.auth()
.signInWithEmailAndPassword(email, password);
console.log("user ID ", userinfo.user.uid);
await firebase
.firestore()
.collection("users")
.doc(userinfo.user.uid.toString())
.update({
expo_token: expoPushToken["data"]
})
.then(function() {
console.log("token successfully updated!");
})
.catch(function(error) {
// The document probably doesn't exist.
console.error("Error updating document: ", error);
});
} catch (error) {
console.log("=======Error in login", error);
this.setState({ errorMessage: error.message });
}
};
registerForPushNotificationsAsync = async () => {
if (Constants.isDevice) {
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const { status } = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
finalStatus = status;
}
if (finalStatus !== "granted") {
alert("Failed to get push token for push notification!");
return;
}
const token = await Notifications.getExpoPushTokenAsync();
console.log(token);
//this.setState({ expoPushToken: token });
} else {
alert("Must use physical device for Push Notifications");
}
if (Platform.OS === "android") {
Notifications.setNotificationChannelAsync("default", {
name: "default",
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#FF231F7C"
});
}
};
import { Permissions } from "expo-permissions";
should of been
import * as Permissions from 'expo-permissions';
Sometimes we all make simple mistakes.

Resources