I'm building an app that streams two-player at the same time. My sources are react-native-video and react-native-youtube-iframe. I implement react-native-music-control to react-native-video and it works perfectly until youtube-iframe starts. When youtube starts, music control disappears on the notification itself and I don't wanna do that. Is there any option to force keep live? btw artwork also doesn't work but it's not important for now.
const { data, streamer, duration } = this.state;
MusicControl.enableControl("play", true);
MusicControl.enableControl("pause", true);
MusicControl.enableControl("stop", true);
MusicControl.enableControl("seekForward", true); // iOS only
MusicControl.enableControl("seekBackward", true); // iOS only
MusicControl.setNowPlaying({
title: data.name,
artwork: "https://via.placeholder.com/250x250?text=" + data.name,
artist: streamer.name,
duration: duration, // (Seconds)
description: "Description", // Android Only
color: 0xffffff, // Notification Color - Android Only
date: "1983-01-02T00:00:00Z", // Release Date (RFC 3339) - Android Only
rating: 84, // Android Only (Boolean or Number depending on the type)
});
MusicControl.enableBackgroundMode(true);
MusicControl.handleAudioInterruptions(true);
MusicControl.on("play", () => {
this.handleMainButtonTouch();
});
MusicControl.on("pause", () => {
this.handleMainButtonTouch();
});
MusicControl.on("seekForward", () => {
this.jumpSeconds(10);
});
MusicControl.on("seekBackward", () => {
this.jumpSeconds(-10);
});
Platform?
[x] iOS
[x] Android
Device/Simulator
[x] Real device
Related
I am using plugin
https://github.com/seididieci/capacitor-backround-geolocation
to watch the user's location. then I am tracking that location with the help of a pusher. this background location works only for 5 minutes after that it just stops. I am using Capacitor's Background task. But that plugin also keeps data on phone after the user opens the app. the Background task sends data to the pusher.
Here is watch location function
getLocation: async function () {
BackgroundGeolocation.initialize({
notificationText: "Your app is running, tap to open.",
notificationTitle: "App Running",
updateInterval: 10000,
requestedAccuracy: BgGeolocationAccuracy.HIGH_ACCURACY,
// Small icon has to be in 'drawable' resources of your app
// if you does not provide one (or it is not found) a fallback icon will be used.
smallIcon: "ic_small_icon",
// Start getting location updates right away. You can set this to false or not set at all (se below).
startImmediately: true,
});
// const geolocation = new Geolocation.Geolocation();
BackgroundGeolocation.addListener("onLocation", (location) => {
// console.log("Got new location", location);
this.subscribe(location.longitude, location.latitude);
console.log(location)
});
BackgroundGeolocation.addListener("onPermissions", (location) => {
// console.log("BGLocation permissions:", location);
this.subscribe(location.longitude, location.latitude);
// Do something with data
});
BackgroundGeolocation.start();
},
Then calling function in mounted()
mounted(){
this.getLocation
App.addListener("appStateChange", (state) => {
setInterval(this.getLocation, 120000);
if (!state.isActive) {
BackgroundTask.beforeExit(async () => {
setInterval(this.getLocation, 120000);
console.og('Why')
});
}
if (state.isActive) {
setInterval(this.getLocation, 120000);
console.log('Active')
}
});
}
You need to use https://ionicframework.com/docs/native/foreground-service like this for running the background.
I m coding an application who need push notification in background(app was killed).
its notification app for twitch.
I m store channels with redux persist(asyncstorage).
What should i do? do u have any documentation directly about that ?
You can use a push notification library like https://github.com/zo0r/react-native-push-notification and a background task library like https://github.com/transistorsoft/react-native-background-fetch. Then you can call your push notification(s) inside background tasks.
Keep in mind that the minimum interval between background tasks being run is 15 minutes. So the interval can only be 15 minutes or longer.
To make this answer more useful, here is a previous implementation I've used to handle push notifications in the background to give you an idea of how to go about it:
import PushNotification from 'react-native-push-notification';
export default class NotificationService {
constructor(onRegister, onNotification) {
this.configure(onRegister, onNotification);
this.lastId = 0;
}
// Handles a user push notification registration
configure(onRegister, onNotification, gcm = '') {
PushNotification.configure({
// (optional) Called when Token is generated (iOS and Android)
onRegister: onRegister,
// (required) Called when a remote or local notification is opened or received
onNotification: onNotification,
// ANDROID ONLY: GCM Sender ID (optional - not required for local notifications, but is need to receive remote push notifications)
senderID: gcm,
/**
* (optional) default: true
* - Specified if permissions (ios) and token (android and ios) will requested or not,
* - if not, you must call PushNotificationsHandler.requestPermissions() later
*/
requestPermissions: true,
});
}
// Send a direct push notification to the user
localNotif() {
this.lastId++;
PushNotification.localNotification({
/* Android Only Properties */
id: '' + this.lastId,
bigText: 'My big text that will be shown when notification is expanded',
subText: 'This is a subText',
/* iOS and Android properties */
title: 'Local Notification',
message: 'My Notification Message',
actions: '["Yes", "No"]', // (Android only) See the doc for notification actions to know more
});
}
// Schedules a push notification by a given javascript Date object
scheduleNotif(date, title, message) {
this.lastId++;
PushNotification.localNotificationSchedule({
date: date,
/* Android Only Properties */
id: '' + this.lastId,
bigText: '',
subText: '',
/* iOS and Android properties */
title: title,
message: message,
});
}
checkPermission(cbk) {
return PushNotification.checkPermissions(cbk);
}
cancelNotif() {
PushNotification.cancelLocalNotifications({ id: '' + this.lastId });
}
cancelAll() {
PushNotification.cancelAllLocalNotifications();
}
}
// ...
import BackgroundFetch from 'react-native-background-fetch';
const initBackGroundFetch = () => {
BackgroundFetch.configure(
{
minimumFetchInterval: 15, // <-- minutes (15 is minimum allowed)
// Android options
forceAlarmManager: false, // <-- Set true to bypass JobScheduler.
stopOnTerminate: false,
startOnBoot: true,
requiredNetworkType: BackgroundFetch.NETWORK_TYPE_ANY, // Network connection needed
},
async taskId => {
// Do stuff with notifications, for example:
const notificationService = new NotificationService(
() => {//... what to do on register},
() => {//... what to do on notification }
)
const date = new Date(Date.now() + 60 * 1000) // adjust according to your use case
notificationService.scheduleNotif(date, "title", "message");
BackgroundFetch.finish(taskId);
},
error => {
console.log('[js] RNBackgroundFetch failed to start');
},
);
};
const App = () => {
useEffect(() => {
initBackGroundFetch();
}, []);
return (
// ...
);
};
The NotificationService is an adjusted version of an example the react native push notification library provides found here: https://github.com/zo0r/react-native-push-notification/blob/master/example/NotifService.js.
I am trying to send push notification using Expo, and I receive it. But there is no vibrate or sound and no pop up as well on my device. I am using Galaxy S9 with Android 9. I have not tried on Iphone yet.
Push notification is sent by nodejs and the user who installed the app will receive the push notification. User expo token is saved in firebase database. I succeed to save and fetch the token.
Below is from expo app
class App extends Component {
componentWillMount() {
firebase.initializeApp(config);
this.registerForPushNotificationsAsync();
}
async registerForPushNotificationsAsync(){
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = existingStatus;
if (Platform.OS === 'android') {
Notifications.createChannelAndroidAsync('chat-messages', {
name: 'Chat messages',
sound: true,
priority: 'high', // was max
vibrate: [0, 250, 250, 250],
});
}
if (existingStatus !== 'granted') {
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
Below is from nodejs server-side
function sendMessage(to, title, body) {
const expo = new Expo();
let messages = [];
messages.push({
to, // Expo user token
body,
data: { withSome: 'data' },
ios: {
sound: true
},
android: {
"channelId": "chat-messages" //and this
}
})
let chunks = expo.chunkPushNotifications(messages);
let tickets = [];
(async () => {
for (let chunk of chunks) {
try {
let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
tickets.push(...ticketChunk);
} catch (error) {
console.error(error);
}
}
})();
}
Also could we redirect to web page when user click the push notification?
I see three problems on your backend code ( expo push notification docs for reference https://docs.expo.io/versions/latest/guides/push-notifications/):
According to the docs, there should be no ios or android properties on the request body;
sound should be either 'default' or null, instead of true;
You created the notification channel on the device, but when you send the notification, you forgot to tell which channel you are sending to.
All that said, your code that calls the expo push notifications api should look something like this:
messages.push({
to, // Expo user token
title: 'some title', //it is good practice to send title, and it will look better
body,
data: { withSome: 'data' },
priority: 'high', //to make sure notification is delivered as fast as possible. see documentation for more details
sound: true, //for iOS devices and android below 8.0
channelId: 'chat-messages', //for devices on android 8.0 and above
})
I hope this helps.
I feel like the docs at react-native-fcm are a bit of a mess and I am having a hard time figuring this out.
I currently have a production app and my android users are telling me they are not receiving notifications for events where they should be. So this is stressing me out a lot right now. On iOS everything seems fine.
In the react-native-fcm example app you can see the following:
//FCM.createNotificationChannel is mandatory for Android targeting >=8. Otherwise you won't see any notification
componentDidMount() {
FCM.createNotificationChannel({
id: 'default',
name: 'Default',
description: 'used for example',
priority: 'high'
})
}
Do I need to call FCM.createNotificationChannel()?? I mainly use remote notifications so is this relevant in any way?
Here is MY setup:
import FCM, {
FCMEvent,
NotificationType,
RemoteNotificationResult,
WillPresentNotificationResult,
} from 'react-native-fcm';
FCM.on(FCMEvent.Notification, async (notif) => {
// there are two parts of notif. notif.notification contains the notification payload, notif.data contains data payload
FCM.presentLocalNotification({
id: "new_message", // (optional for instant notification)
title: notif.fcm.title, // as FCM payload
body: notif.fcm.body, // as FCM payload (required)
sound: "default", // as FCM payload
priority: "high", // as FCM payload
click_action: "com.myapp.MyCategory", // as FCM payload - this is used as category identifier on iOS.
badge: 10, // as FCM payload IOS only, set 0 to clear badges
number: 10, // Android only
ticker: "My Notification Ticker", // Android only
auto_cancel: true, // Android only (default true)
large_icon: "ic_launcher", // Android only
icon: "ic_launcher", // as FCM payload, you can relace this with custom icon you put in mipmap
color: "blue", // Android only
vibrate: 300, // Android only default: 300, no vibration if you pass 0
wake_screen: true, // Android only, wake up screen when notification arrives
group: "group", // Android only
picture: "https://google.png", // Android only bigPicture style
ongoing: false, // Android only
my_custom_data:'my_custom_field_value', // extra data you want to throw
lights: true, // Android only, LED blinking (default false)
});
if(Platform.OS ==='ios'){
//optional
//iOS requires developers to call completionHandler to end notification process. If you do not call it your background remote notifications could be throttled, to read more about it see https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application.
//This library handles it for you automatically with default behavior (for remote notification, finish with NoData; for WillPresent, finish depend on "show_in_foreground"). However if you want to return different result, follow the following code to override
//notif._notificationType is available for iOS platfrom
switch(notif._notificationType){
case NotificationType.Remote:
notif.finish(RemoteNotificationResult.NewData) //other types available: RemoteNotificationResult.NewData, RemoteNotificationResult.ResultFailed
break;
case NotificationType.NotificationResponse:
notif.finish();
break;
case NotificationType.WillPresent:
notif.finish(WillPresentNotificationResult.All) //other types available: WillPresentNotificationResult.None
break;
}
}
});
FCM.on(FCMEvent.RefreshToken, (token) => {
try {
const { currentUser } = firebase.auth();
let updates = {};
updates[`/allUsers/serviceUsers/${currentUser.uid}/userInfo/fcmToken`] = token;
return firebase.database().ref().update(updates).catch(err => console.log('fcm refresh error', err))
} catch (e) {
console.log('couldnt update fcm refresh token', e)
}
});
const store = createStore(reducers, {}, applyMiddleware(ReduxThunk));
class App extends Component {
componentWillMount() {
let config = {configgg}
!firebase.apps.length ? firebase.initializeApp(config) : firebase.app();
FCM.requestPermissions();
}
render() {
return (
<Provider store={store}>
<Router/>
</Provider>
);
}
}
export default App;
I mainly use remote notifications and it is critical for my app for it to work. Is there anything I am missing in my setup?
Any hint or suggestions will help me out a lot! Thanks!
EDIT:
Found this in adb logcat when receiving a notification (that did not show up)
NotificationService: No Channel found for pkg=com.lisdoworker, channelId=null, id=0, tag=GCM-Notification:9015992, opPkg=com.lisdoworker, callingUid=10487, userId=0, incomingUserId=0, notificationUid=10487, notification=Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x10 color=0x00000000 vis=PRIVATE)
Does this have to do with FCM.createNotificationChannel()??
Yeah, apparently createNotificationChannel was added in version 16 to support Android 8 and it is barely documented.
I am looking around on how to check if network or GPS are enabled on a device when my application starts. And if they are disabled prompt the user to enable it.
Is this posible in React-native?, and is there any class or tool that could help with this type of dialogs?
So I am going to start answering my own question.
For GPS:
there seems to be a sensible solution. IOS seems to natively request if there is a geolocation request. And for Android this is not natively supported but someone has created a module for that ( https://github.com/webyonet/react-native-android-location-services-dialog-box )
so in my action creator I added the next code:
if(Platform.OS === 'android')
LocationServicesDialogBox.checkLocationServicesIsEnabled({
message: "<h2>Use Location?</h2> \
This app wants to change your device settings:<br/><br/>\
Use GPS for location<br/><br/>",
ok: "YES",
cancel: "NO"
}).then(() => {
locationTracking(dispatch, getState, geolocationSettings)
})
For Network:
There is no native support for neither so i end up doing my own action creator to check.
export function networkCheck(){
return (dispatch) => {
const dispatchNetworkState = (isConnected) => dispatch({
type: types.NETWORK_STATE,
state: isConnected
})
const handle = () => NetInfo.isConnected.fetch().done(dispatchNetworkState)
NetInfo.isConnected.addEventListener('change', handle);
}
}
A little extra:
for GPS i added this to check if the user goes and disable GPS on the middle of the task.
export function locationCheck(geolocationSettings = {enableHighAccuracy: true, timeout: 20000, maximumAge: 10000, distanceFilter:10}){
return (dispatch) => {
navigator.geolocation.watchPosition(
() => {
dispatch({
type: types.LOCATION_STATE,
state: true
})
},
() => {
dispatch({
type: types.LOCATION_STATE,
state: false
})
},
geolocationSettings)
}
}
For enabling location/gps on Android I can recommend this module: https://github.com/Richou/react-native-android-location-enabler
It is using the standard Android dialog for location:
If you use any kind of package to get the user's location, most likely they will automatically ask for the user to enable the hardware part when you request it for the first time.
So, you can do something like this to show the prompt:
CheckForGPSEnablement() {
return new Promise(resolve => {
RNLocation.configure({
distanceFilter: 100, // Meters
desiredAccuracy: {
ios: "best",
android: "balancedPowerAccuracy",
},
// Android only
androidProvider: "auto",
interval: 5000, // Milliseconds
fastestInterval: 10000, // Milliseconds
maxWaitTime: 5000, // Milliseconds
// iOS Only
activityType: "other",
allowsBackgroundLocationUpdates: false,
headingFilter: 1, // Degrees
headingOrientation: "portrait",
pausesLocationUpdatesAutomatically: false,
showsBackgroundLocationIndicator: false,
})
.then(x => {
console.log({ x })
resolve(true)
})
.catch(err => {
console.log({ err })
resolve(false)
})
})
}
In my case I've used react-native-location.
In recent versions of iOS (>= iOS8?) and Android you can show the app permissions dialog and let users turn on/off permissions such as camera and location. There is a native module to do that: https://github.com/yonahforst/react-native-permissions