Opentok end-user denied permission to hardware devices - ios

I'm setting up a prototype for using Opentok Webrtc in Safari IOS11 for the Iphone. It all worked fine, untill today (and I don't remember changing anything). The error I'm receiving is
OT.Publisher Access Denied: Permission Denied: End-user denied permission to hardware devices (getUserMedia error:
NotAllowedError)
You would say this is local, but i've tried it with the phone of a colleague and the same error now occurred. So it should be somewhere in the code or OpenTok library in my opinion.
Any idea?
// Handling all of our errors here by alerting them
function handleError(error) {
if (error) {
alert(error.message);
}
}
// make the agent id dynamic alteron, now hardcoded
var agentIdAvailable = '007';
var SERVER_BASE_URL = 'https://XXX.herokuapp.com';
fetch(SERVER_BASE_URL + '/room/'+ agentIdAvailable).then(function(res) {
return res.json()
}).then(function(res) {
apiKey = res.apiKey;
sessionId = res.sessionId;
token = res.token;
initializeSession();
}).catch(handleError);
function initializeSession() {
var session = OT.initSession(apiKey, sessionId);
// Subscribe to a newly created stream
session.on('streamCreated', function(event) {
session.subscribe(event.stream, 'subscriber', {
insertMode: 'append',
width: '100%',
height: '100%'
}, handleError);
});
// Create a publisher
var publisher = OT.initPublisher('publisher', {
insertMode: 'append',
width: '100%',
height: '100%'
}, handleError);
// Connect to the session
session.connect(token, function(error) {
// If the connection is successful, initialize a publisher and publish to the session
if (error) {
handleError(error);
} else {
session.publish(publisher, handleError);
console.log('*** publishing', publisher);
}
});
}

I had the same problem with vonage (old opentok). There is an article that was the solution of my problem: https://video-api.support.vonage.com/hc/en-us/articles/4983310908948-Issue-with-screensharing-with-embedded-iFrames
I had forget to put "display-capture" on the iframe (to allow screen share), therefore this exactly error message that you mentioned happened to me, but not in safari (i was trying on chrome)

Related

undefined is not an object (evaluating '_ExponentImagePicker.default.requestMediaLibraryPermissionsAsync') in expo-image-picker

Error from catch error block Image
Hi, I am using expo-image-picker and I stumbled with this error for a while now.
and this is all the necessary code that I use. I'll give a green checkmark for appreciation.
For more information, I have already handled the permission in info.plist.
// Camera & Image Picker
import * as ImagePicker from 'expo-image-picker';
const openImagePicker = async () => {
try {
// Ask the user for the permission to access the media library
const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync()
if (permissionResult.granted === false) {
alert("You've refused to allow this appp to access your photos!");
return;
}
const result = await ImagePicker.launchImageLibraryAsync();
// Explore the result
console.log(result);
if (result.cancelled === false) {
setPickedImagePath(result.uri);
console.log(result.uri);
}
} catch (error) {
alert('Error Occur: ' + error.message)
closeSheet()
}
}
If you are using SDK 44, a permission request is no longer necessary for launching the image picker so you can remove the related code.
Simply call
const result = await ImagePicker.launchImageLibraryAsync({});
If you really want to ask for permission (which as I said is no longer necessary) the correct method is
ImagePicker.getMediaLibraryPermissionsAsync()
and not
ImagePicker.requestMediaLibraryPermissionsAsync()

How to fix Publisher error in Opentok Cordova Plugin for iOS?

I am using cordova-plugin-opentok with Ionic 4, and I have a problem with iOS.
The session connects correctly, but when I publish my video stream, It throws this error
"iOS Publish stream to session
[ERROR] otk_session_private.cpp:3165 - Bad loop or already in a disconnecting/error state"
I have tried changing the Publisher parameters, but the error is still there.
let session;
let publisher;
session = OT.initSession(this.apiKEY, this.sessionID);
session.on('streamCreated', function(event) {
session.subscribe(event.stream, 'subscriber', {
insertMode: 'append',
width: '100%',
height: '100%'
});
OT.updateViews();
});
session.connect(this.token, function(error) {
if (!error) {
publisher = OT.initPublisher('publisher');
session.publish(publisher, (error) => {
if(error){
console.log("Publisher error: " + error);
}
OT.updateViews();
});
} else {
console.log("Error connecting: ", error.name, error.message);
}
});
In case anyone finds this, since it is the only mention of this error on the internet, I was getting this error on C SDK. It turned out I was calling otc_init again by accident after creating the session and publisher. Silly mistake.

Notifications.getExpoPushTokenAsync not working on Stand Alone iOS

I'm trying to my expo/react-native project to send push notifications to my server. It works on standalone Android, but not stand alone iPhone.
The standalone iPhone app never sends the token.
Since the app sends nothing without error, I tried removing:
if (finalStatus !== 'granted') { return; }
This didn't work either.
export async function registerForPushNotificationsAsync(token) {
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = existingStatus;
// Only ask if permissions have not already been determined, for iOS.
if (existingStatus !== 'granted') {
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
// Stop here if the user did not grant permissions
if (finalStatus !== 'granted') {
return;
}
// Get the push token that uniquely identifies this device
let expoToken = await Notifications.getExpoPushTokenAsync();
// Post new push token to backend for user
return axios({
method: 'POST',
url: `${str.ROOT_URL}/account/push/`,
headers: {
Authorization: `Token ${token}`
},
data: {
"token": expoToken,
"status": finalStatus
}
});
}
I expected the token to get sent to the backend, but nothing is sent on the standalone iOS app.
Please let me know if you know a workaround or had this issue before. Thanks!
I think it's too late to give an answer, but I spent 2 days to resolve it... I hope it helps somebody.
Instead this:
import * as Notifications from "expo-notifications";
Try this:
import { Notifications } from "expo";

socket.io can't handle errors

I'm trying to make real time application with node.js and socket.io. As I can see the server can see when new user connects but can't return information to client side or something. This is what I've on client side:
<script src="<?= base_url('assets/js/socket.io.js') ?>"></script>
<script>
var socket;
socket = io('http://***.***.***.***:3030', {query: "key=key"});
socket.on('connect', function (data) {
console.log('Client side successfully connected with APP.');
});
socket.on('error', function (err) {
console.log('Error: ' + err);
});
</script>
and this is the server side:
var app = require("express")();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
http.listen(3030, function () {
globals.debug('Server is running on port: 3030', 'success');
});
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('www.****.com' == domain) {
globals.debug('New user connected', 'warning');
} else {
globals.debug('Bad site authentication data, chat will be disabled.', 'danger');
return accept('Bad site authentication data, chat will be disabled.', false);
}
});
io.use(function (sock, next) {
var handshakeData = sock.request;
var userToken = handshakeData._query.key;
console.log('The user ' + sock.id + ' has connected');
next(null, true);
});
and when someone comes to website I'm expecting to see in console output "New user connected" and I see it: screen shot and the user should see on the browser console output: "Client side successfully connected with APP." but I doesn't show. Also I tried to emit data to user but it doesn't work too. I can't see any errors or something. This is not the first time I'm working with sockets but the first time facing such as problem. Maybe there is any error reporting methods to handle errors or something? Also I can't see output on io.use(....) method
The solution is to pass "OK" sign just after authenticating to do the next method:
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('www.****.com' == domain) {
globals.debug('New user connected', 'warning');
accept(null, true);
} else {
globals.debug('Bad site authentication data, chat will be disabled.', 'danger');
return accept('Bad site authentication data, chat will be disabled.', false);
}
});

Cordova/Phonegap iOS Parse-Push Plugin

I have spent lot of time to find correct cordova plugin for parse push notifications for both Android & iOS platforms.
My requirements are:
To receive parse push notification (in both android & iOS)
Able to store all the incoming push notifications in mobile local storage Sqlite.
I have tried all the below parse push cordova plugins for both Android & iOS platforms.
https://github.com/avivais/phonegap-parse-plugin
https://github.com/taivo/parse-push-plugin
https://github.com/campers/parse-push-plugin
https://github.com/manishiitg/parse-push-plugin
For Android: All the above plugins are working perfectly to fulfill my above mentioned requirements.
For iOS: Only 1st plugin i.e https://github.com/avivais/phonegap-parse-plugin is working. And that too i was not able to save the notifications in local storage sqlite. That means only my 1st requirement is fulfilled but not my 2nd requirement.
All the github pages of remaining plugins (i.e 2nd, 3rd, 4th) states that:
"Please note that I've only worked on the Android aspect of this fork. The iOS side is not yet up to date."
Is there any plugin which will work for both Android & iOS platforms to fulfill my 2 requirements?
(or)
If there is no common plugin for both the platforms, then how can I store the incoming plugins in iOS sqlite?
Please help me. Thanks in advance.
I happen to maintain https://github.com/taivo/parse-push-plugin
It looks like you caught my fork at its infancy. I picked it up when the upstream fork seemed stagnant for a while and at that time I was only addressing the Android aspect. Since then I've provided full iOS support. And it works for parse-server as well as the out-going parse.com. I also did one better and made installation just a matter of
cordova add https://github.com/taivo/parse-push-plugin
and writing a few config.xml tags to indicate server url, and app id.
That should take out the big pain of manually messing with Android Manifest, Java, and Objective C when setting up the plugin.
It should now meet or exceed your requirement. To receive push notification and store in sqlite, all you have to do is set an event handler in javascript. Be sure to wrap it with some sort of device ready or platform ready event handler to ensure the plugin has properly loaded.
$ionicPlatform.ready(function(){
if(window.ParsePushPlugin){
ParsePushPlugin.on('receivePN', function(pn){
console.log('yo i got this notif:' + JSON.stringify(pn) );
//
// do your sqlite storage here
//
});
}
});
You just might be interested in the Azure Push Notifications. It combines both Push notification services so you can send messages to both devices from one central point.
I quote:
Notification Hubs A scalable, cross-platform solution for sending push
notifications to mobile devices, Notification Hubs works well with
Cordova apps. Notification Hubs manages the registrations with each
PNS. More important, Notification Hubs lets you create template
registrations so you can send messages to all registered devices,
regardless of platform, with only a single line of code. You can also
use tags to send targeted notifications only to devices with specific
registrations. For more information about Notification Hubs, see the
Azure Web site at aka.ms/nkn4n4.
Here i have a helper class for registering your device with the pushnotification service. For sending push notifications, you can use an azure portal and send styled push notifications in json format.
var Pushman = {
Initialize: function (hubConnString, hubName, gcmSenderId, callbackRegistered, callbackUnRegistered, callbackInlineNotification, callbackBackgroundNotification, callbackError) {
//store connection and callback information on app startup for Push Registration later
Pushman.HubConnectionString = hubConnString;
Pushman.HubName = hubName;
Pushman.GcmSenderId = gcmSenderId;
//callbacks
Pushman.RegisteredCallback = callbackRegistered;
Pushman.UnRegisteredCallback = callbackUnRegistered;
Pushman.NotificationForegroundCallback = callbackInlineNotification;
Pushman.NotificationBackgroundCallback = callbackBackgroundNotification;
Pushman.ErrorCallback = callbackError;
},
RegisterForPushNotifications: function (tags) {
//setup Azure Notification Hub registration
Pushman.Hub = new WindowsAzure.Messaging.NotificationHub(Pushman.HubName, Pushman.HubConnectionString, Pushman.GcmSenderId);
Pushman.Hub.registerApplicationAsync(tags).then(Pushman.onRegistered, Pushman.onError);
//setup PushPlugin registration
Pushman.Push = window.PushNotification;
var push;
//register depending on device being run
if (device.platform == 'android' || device.platform == 'Android' || device.platform == "amazon-fireos") {
//android
push = Pushman.Push.init(
{ "android": { "senderID": Pushman.GcmSenderId } }
);
push.on('registration', Pushman.onRegistered);
push.on('notification', Pushman.onAndroidNotification);
push.on('error', Pushman.onError);
} else {
//iOS
push = Pushman.Push.init(
{ "ios": { "alert": "true", "badge": "true", "sound": "true" } }
);
push.on('registration', Pushman.onRegistered);
push.on('notification', Pushman.onIOSNotification);
push.on('error', Pushman.onError);
}
},
UnRegisterForPushNotifications: function () {
if (Pushman.Hub != null) {
//dont pass through error handler
//unreg azure
Pushman.Hub.unregisterApplicationAsync()
.then(Pushman.onUnRegistered, null);
//unreg native
Pushman.Push.unregister(Pushman.onUnRegistered, null);
}
},
onRegistered: function (msg) {
Pushman.log("Registered: " + msg.registrationId);
//only call callback if registrationId actually set
if (msg.registrationId.length > 0 && Pushman.RegisteredCallback != null) {
Pushman.RegisteredCallback(msg);
}
},
onUnRegistered: function () {
Pushman.log("UnRegistered");
if (Pushman.UnRegisteredCallback != null) {
Pushman.UnRegisteredCallback();
}
},
onInlineNotification: function (msg) {
Pushman.log("OnInlineNotification: " + msg);
if (Pushman.NotificationForegroundCallback != null) {
Pushman.NotificationForegroundCallback(msg);
}
},
onBackgroundNotification: function (msg) {
Pushman.log("OnBackgroundNotification: " + msg);
if (Pushman.NotificationBackgroundCallback != null) {
Pushman.NotificationBackgroundCallback(msg);
}
},
onColdStartNotification: function (msg) {
Pushman.log("OnColdStartNotification: " + msg);
if (Pushman.NotificationBackgroundCallback != null) {
Pushman.NotificationBackgroundCallback(msg);
}
},
onError: function (error) {
Pushman.log("Error: " + error);
if (Pushman.ErrorCallback != null) {
Pushman.ErrorCallback(error);
}
},
onAndroidNotification: function (e) {
switch (e.event) {
case 'registered':
if (e.regid.length > 0) {
Pushman.onRegistered("Registered");
}
break;
case 'message':
if (e.foreground) {
//if this flag is set, this notification happened while app in foreground
Pushman.onInlineNotification(e.payload.message);
} else {
//otherwise app launched because the user touched a notification in the notification tray.
if (e.coldstart) {
//app was closed
Pushman.onColdStartNotification(e.payload.message);
}
else {
//app was minimized
Pushman.onBackgroundNotification(e.payload.message);
}
}
break;
case 'error':
Pushman.onError(e.msg);
break;
default:
Pushman.onError("Unknown message");
break;
}
},
onIOSNotification: function (event) {
//TODO: not sure how ios works re cold start vs inline msg types?
if (event.alert) {
navigator.notification.alert(event.alert);
}
if (event.badge) {
Push.setApplicationIconBadgeNumber(app.successHandler, app.errorHandler, event.badge);
}
},
tokenHandler: function (result) {
// iOS - not sure its use though appears somewhat important
// Your iOS push server needs to know the token before it can push to this device
// here is where you might want to send it the token for later use.
alert('device token = ' + result);
},
log: function (msg) {
console.log(msg);
},
}
///"class" variables - not sure how to put them into the js "class"
Pushman.Push = null;
Pushman.Hub = null;
Pushman.HubConnectionString = null;
Pushman.HubName = null;
Pushman.GcmSenderId = null;
Pushman.NotificationForegroundCallback = null;
Pushman.NotificationBackgroundCallback = null;
Pushman.RegisteredCallback = null;
Pushman.UnRegisteredCallback = null;
Pushman.ErrorCallback = null;
I did not write this myself, all credit goes to this guy.
Then you just need to initialize the plugin when the application starts:
//azure notificationshub connection information
notificationHubPath = "notificationhub name";
connectionString = "notificatin hub connectionstring";
//sender id for google cloud services
var senderIdGCM = "sender id from google gcm";
//tag registration (csv string), can be empty but not undefined
var registrationTagsCsv = ""; //test1, test2
var app = {
Initialize: function () {
//reg for onload event
this.AppStart();
},
AppStart: function () {
"use strict";
document.addEventListener('deviceready', app.onLoad, false);
document.addEventListener('deviceready', onDeviceReady.bind(this), false);
function onDeviceReady() {
// Handle the Cordova pause and resume events
document.addEventListener('pause', onPause.bind(this), false);
document.addEventListener('resume', onResume.bind(this), false);
// TODO: Cordova has been loaded. Perform any initialization that requires Cordova here.
};
function onPause() {
// TODO: This application has been suspended. Save application state here.
};
function onResume() {
// TODO: This application has been reactivated. Restore application state here.
};
},
onLoad: function () {
app.log("Initializing...");
//setup push notifications
Pushman.Initialize(connectionString, notificationHubPath, senderIdGCM,
app.onNotificationRegistered, app.onNotificationUnRegistered,
app.onNotificationInline, app.onNotificationBackground, app.onNotificationError);
//hookup cmd buttons
app.registerForPush();
//$("#register").click(app.registerForPush);
//$("#unregister").click(app.unRegisterForPush);
app.onAppReady();
},
registerForPush: function (a, c) {
app.log("Registering...");
//register for tags
Pushman.RegisterForPushNotifications(registrationTagsCsv);
},
unRegisterForPush: function (a, c) {
app.log("UnRegistering...");
//register for tags
Pushman.UnRegisterForPushNotifications();
},
onAppReady: function () {
app.log("Ready");
},
onNotificationRegistered: function (msg) {
app.log("Registered: " + msg.registrationId);
},
onNotificationUnRegistered: function () {
app.log("UnRegistered");
},
onNotificationInline: function (data) {
app.log("Inline Notification: " + data);
},
onNotificationBackground: function (data) {
app.log("Background Notification: " + data);
},
onNotificationError: function (error) {
app.log("Error: " + error);
},
log: function (msg) {
console.log(msg);
},
};
If you want to store the messages then you just need to add your code for storing to sql where the messages get received. You'll need an azure account to make this work, here you can get a free trail. It will allow you to send up to 1 million push notifications a month free of charge.
I think this article may be of use, it has more of a direct native workaround for your hybrid app to work
http://www.hiddentao.com/archives/2015/04/10/parse-push-notifications-for-your-android-and-ios-cordova-app/.
I'm working on a Cordova android app, and this seems to be a working solution

Resources