Adding Back Tracks Does Not Work on WebRTC - android

We create an app with React Native WebRTC and Janus Gateway. It works as wanted. Our app is based on push to talk. So when an users in listen mode need to break microphone for other apps. And take back when anyone press to speak button.
Breaking Mic:
if (!globalTrack) {
globalTracks = config.myStream.getTracks();
}
config.myStream.getTracks().forEach(t => {
config.myStream.removeTrack(t);
});
Get Back the Tracks:
globalTracks.forEach(t => {
config.myStream.addTrack(t);
});
pluginHandle.createOffer({
media: { addVideo: true },
success: function(jsep) {
Janus.debug(jsep);
pluginHandle.send({message: {audio: true, video: false}, "jsep": jsep });
},
error: function(error) {
console.log("WebRTC error... " + JSON.stringify(error));
}
});
// also I have try this:
devices = await mediaDevices.getUserMedia({audio: true, video: false})
// devices output https://pastebin.ubuntu.com/p/KQqBq2QRy3/
devices._tracks.forEach(t => {
config.myStream.addTrack(t);
});
pluginHandle.createOffer({
media: {audio: {deviceId: devices._tracks[0]['id']}, replaceAudio: true},
success: function(jsep) {
pluginHandle.send({message: {audio: true, video: false}, "jsep": jsep});
},
error: function(error) {
console.log(("WebRTC error... " + JSON.stringify(error));
}
});
Problem:
Problem: E.g: when a call came to the phone and answered it. The user's voice does not pass anymore even after restarting the app.
On Janus Gateway every things is normal. I think problem is about renegotiation.
Problem occurred only on Android phones. And works after force stopping the app.
Janus Gateway Log which when I speak at room:
There's a message for JANUS AudioBridge plugin
Setting muted property: true (room 20, user 2301490876606211)
Notifying participant 329012611897879 (kardan)
Sending event to transport...
>> 0 (Success)

We can not find a generic solution.
For now restarting app is works with react-native-restart

Related

Can not change camera in mobile Chrome or Safari during WebRTC call

I use navigator.mediaDevices.enumerateDevices to retrieve list of all video devices (element.kind === 'videoinput') and then call navigator.mediaDevices.getUserMedia(constraints) call to rotate video devices (using deviceId as constraint). Everything works fine on Windows Chrome / Firefox, but on android phone (tried Samsung, Asus, Huawei with Android 8/9) this call fails for back camera with NotReadableError / Could not start video source (for Chrome) or AbortError / Starting video failed (for Firefox).
Strangely same code works ok in iOS / Safari.
Also this only happens when WebRTC call is present in browser. If there is no call I can select any video device.
Also if I select back camera first and try to establish the call, it does not work, I get similar error.
I know it's far-fetched but maybe someone had same/similar issue?
All browser versions are up-to-date.
[UPDATE - code snippet and log]
switchCamera() {
try {
if (this.localStream) {
const tracks = this.localStream.getTracks();
console.log('switchCamera stopping this.localStream tracks', tracks);
tracks.forEach((track: MediaStreamTrack) => {
console.log('switchCamera stopping track', track);
track.stop();
});
console.log('switchCamera stop stream');
}
const constraints = {
audio: true,
video: { facingMode: this.faceCamera ? 'environment' : 'face' }
};
this.faceCamera = !this.faceCamera;
console.log('switchCamera constraints: ', constraints);
navigator.mediaDevices.getUserMedia(constraints)
.then(stream => {
console.log('getUserMedia:', stream);
this.logText('got stream');
this.localVideo.srcObject = stream;
const videoTracks = stream.getVideoTracks();
const audioTracks = stream.getAudioTracks();
console.log('videoTracks', videoTracks);
if (videoTracks.length > 0) {
console.log(`Using video device: ${videoTracks[0].label}`);
}
const videoTrack = videoTracks[0];
const audioTrack = audioTracks[0];
console.log('Replacing track for pc', videoTrack, audioTrack);
const pc = this.session.sessionDescriptionHandler.peerConnection;
const videoSender = pc.getSenders().find(s => {
return s.track && s.track.kind === videoTrack.kind;
});
const audioSender = pc.getSenders().find(s => {
return s.track && s.track.kind === audioTrack.kind;
});
if (videoSender) {
console.log('videoSender.replaceTrack', videoTrack);
videoSender.replaceTrack(videoTrack);
}
if (audioSender) {
console.log('audioSender.replaceTrack', audioTrack);
audioSender.replaceTrack(audioTrack);
}
})
.catch(e => {
console.log('getUserMedia error:', e.name, e.code, e.message);
});
} catch (e) {
window.alert(e);
}
}
this is the log from chrome remote device debug:
The error is "NotReadableError", "Could not start video source" which means that the underlying device handle could not be obtained by chrome.
Again, safari/ios works ok.
For mobile devices, there is a dedicated way of how to select between front & back camera.
VideoFacingMode - https://www.w3.org/TR/mediacapture-streams/#dom-videofacingmodeenum
TL;DR
window.navigator.mediaDevices.enumerateDevices().then(devices => {
if (devices.filter(device => device.kind === 'videoinput').length > 1) {
navigator.mediaDevices.getUserMedia({video: {facingMode: 'user' /*'environment'*/}}).then(console.log.bind(this))
}
})
It works for mobile Safari, Chrome and FF.
NOTE
Remember, to stop the previous video track before calling the
getUserMedia with video again, otherwise, you will get an
exception.
Ok, so I narrowed it down to calling navigator.mediaDevices.getUserMedia() in ngInit() (this is Angular app).
Even if I remove all code in .then() handler function, the effect is the same.
Only removing this call solves the issue.
Not sure at this time why such behavior, will investigate it more thoroughly and update.
To switch between front and back cameras on mobile, you need to stop the previous stream before opening a new stream.
if (videoIn.srcObject) {
videoIn.srcObject.getTracks().forEach((track) => {
track.stop();
});

Android - PWA does not open in standalone mode with service worker

While developing a Progressive-Web-App the following Problem occurred:
Standalone mode works perfectly without including the service worker - but does NOT work with.
Without Service-Worker a2hs (added to Homescreen) PWA gets correctly started in "standalone"-Mode.
After adding the Service-Worker (a2hs + installed / Web-APK) PWA opens new Tab in new Chrome-Window.
Chrome-PWA-Audit:
login_mobile_tablet.jsf / include service worker:
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('../serviceWorker.js', {scope: "/application/"})
/* also tried ".", "/", "./" as scope value */
.then(function(registration) {
console.log('Service worker registration successful, scope is: ', registration.scope);
})
.catch(function(error) {
console.log('Service worker registration failed, error: ', error);
});
}
</script>
serviceWorker.js:
var cacheName = 'pwa-cache';
// A list of local resources we always want to be cached.
var filesToCache = [
'QS1.xhtml',
'pdf.xhtml',
'QS1.jsf',
'pdf.jsf',
'login_pages/login_mobile_tablet.jsf',
'login_pages/login_mobile_tablet.xhtml'
];
// The install handler takes care of precaching the resources we always need.
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(cacheName).then(function(cache) {
return cache.addAll(filesToCache);
})
);
})
// The activate handler takes care of cleaning up old caches.
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim());
});
// The fetch handler serves responses for same-origin resources from a cache.
self.addEventListener('fetch', event => {
// Workaround for error:
// TypeError: Failed to execute 'fetch' on 'ServiceWorkerGlobalScope': 'only-if-cached' can be set only with 'same-origin' mode
// see: https://stackoverflow.com/questions/48463483/what-causes-a-failed-to-execute-fetch-on-serviceworkerglobalscope-only-if
if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin')
return;
event.respondWith(
caches.match(event.request, {ignoreSearch: true})
.then(response => {
return response || fetch(event.request);
})
);
});
manifest.json:
{
"name":"[Hidden]",
"short_name":"[Hidden]",
"start_url":"/application/login_pages/login_mobile_tablet.jsf",
"scope":".",
"display":"standalone",
"background_color":"#4688B8",
"theme_color":"#4688B8",
"orientation":"landscape",
"icons":[
{
"src":"javax.faces.resource/images/icons/qsc_128.png.jsf",
"sizes":"128x128",
"type":"image/png"
},
{
"src":"javax.faces.resource/images/icons/qsc_144.png.jsf",
"sizes":"144x144",
"type":"image/png"
},
{
"src":"javax.faces.resource/images/icons/qsc_152.png.jsf",
"sizes":"152x152",
"type":"image/png"
},
{
"src":"javax.faces.resource/images/icons/qsc_192.png.jsf",
"sizes":"192x192",
"type":"image/png"
},
{
"src":"javax.faces.resource/images/icons/qsc_256.png.jsf",
"sizes":"256x256",
"type":"image/png"
},
{
"src":"javax.faces.resource/images/icons/qsc_512.png.jsf",
"sizes":"512x512",
"type":"image/png"
}
]
}
The following questions / answers were considered - but no solution was found:
PWA wont open in standalone mode on android
WebAPK ignores display:standalone flag for PWA running on local network
PWA deployed in node.js running in Standalone mode on Android and iOS
Technical Background
The Moment you add your Service-Worker (along all other PWA-Requirements) your App gets created as an Real PWA - with Web-APK getting installed.
Therefore you also need to use Default-HTTPS-Port 443 - make sure you use a valid HTTPS-Certificate.
Before adding the Service-Worker, this mandatory requirement was missing so your PWA was NOT installed and therefore needed less other requirements to be displayed in "standalone-mode".
It's just a shame that this is nowhere documented... and we had to "find out" for ourselves.
Short-List of Mandatory Requirements for "Installable Web-APK":
(As we could not find a full List, i try to include all Points)
Registered Service-Worker (default-implementation like yours is enough)
manifest.json (yours is valid)
https with valid certificate
https default-port (443, eg. https://yourdomain.com/test/)
... for the rest just check chrome audit tool (HINT: you don't need to pass all requirements - your web-apk should work when switching to https-default-port)

phonegap WFS proxy issue

I encountered a problem when I try to package my sencha-touch app using phonegap. Everything works fine except accessing WFS in phonegap. (And the app has no problem running in browser, WFS access is OK)
My phonegap version is 2.9; openlayer version is 2.13
Here I present my simple code. You can also check the example codes in the following site: http://openlayers.org/dev/examples/wfs-filter.html
var rootUrl = window.location.protocol + "//" + window.location.host + '/';
var map;
function init() {
map = new OpenLayers.Map({
div: "map",
layers: [
new OpenLayers.Layer.WMS(
"Natural Earth",
"http://demo.opengeo.org/geoserver/wms",
{ layers: "topp:naturalearth" }
),
new OpenLayers.Layer.Vector("WFS", {
strategies: [new OpenLayers.Strategy.BBOX()],
protocol: new OpenLayers.Protocol.WFS({
url: rootUrl + 'proxy.py?url=http://demo.opengeo.org/geoserver/wfs',
featureType: "tasmania_roads",
featureNS: "http://www.openplans.org/topp"
}),
styleMap: new OpenLayers.StyleMap({
strokeWidth: 3,
strokeColor: "#333333"
}),
})
],
center: new OpenLayers.LonLat(146.7, -41.8),
zoom: 6
});
}
In phonegap there's no problem accessing WMS, but when I try WFS, it never work.
Comparing to the link I showed you before, there's a road displayed in the map, and it is obtained through WFS. In my phonegap app, the road will not be displayed.
I'm wondering whether it is a WFS issue, or phonegap issue. Something is blocking my access to WFS in my phonegap app.
Please give me some suggestions and hints, guys! I will really appreciate it.
function getLayerList() {
$.ajax({ url: rootUrl + 'proxy.py?url=http://192.168.0.23/LBEService/Service1.svc/GetEventList',
//async: false,
data: JSON.stringify({}),
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (result) {
console.log(result);
$("#demo").html(result[0].event_NAME);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
}).done(function () {
});
}
Have you added the domain that is hosting the WFS to the white list?
http://docs.phonegap.com/en/1.9.0/guide_whitelist_index.md.html
On android PhoneGap window.location.protocol is 'file:' and window.location.hostname is "", so your app will probably be looking for file://proxy.py? which doesn't exist on your device.
To solve this issue I test the protocol, and set up OpenLayers.Proxy accordingly, thus:
if( location.protocol == 'file:' ) {
OpenLayers.ProxyHost = "";
} else {
OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi?url=";
}
So in your case, if protocol is 'file:', I think you need to drop 'proxy.py?'
Tip: debug your android app using Chrome on your PC (chrome://inspect/#devices) and you'll see the request that android is making.

Phonegap navigator.device issue android

I have some problems with camera and geolocation in my app.
WHen i try to use navigator.camera.getPicture or navigator.geolocation.getCurrentPosition,
happens nothing.
Here is my code
options.sourceType = navigator.camera.DestinationType.PHOTOLIBRARY;
options.destinationType navigator.camera.PictureSourceType.FILE_URI;
alert(1);
navigator.camera.getPicture(
function (data) { // Success!
alert(4);
self._mediaDataSuccess(data);
}
,
function (error) { // Fail!
alert(5);
self._mediaDataFail(error);
},
options
);
alert(2);
At first i see message box with 1, then with 2. I haven't see 4 or 5.
All permissions enabled.
Also, i have same code for navigator.geolocation.getCurrentPosition, with same problem.
Where is my mistake?

SoundCloud Stream in Phonegap under Android

I'm currently trying to get the SoundCloud API working under PhoneGap/Cordova and Android. Here's the code that is working fine within the browser:
var track_url = 'http://soundcloud.com/mymusic/mymusic'
;
SC.get('/resolve', {
url : track_url
}, function(track) {
$("#stream").live("click", function() {
SC.stream("/tracks/" + track.id, function(sound) {
sound.play();
$("#stop").live("click", function() {
sound.stop();
});
});
});
});
On my android debug device however there is no sound. LogCat doesn't give any standard or cordova errors. Has anyone encountered this before?
Many Thanks in advance
Your code looks okay and I was able to test it successfully on Android. The only thing I can think of is that the resolve call is returning a 404 or similar. Have you tried checking for an error?
var track_url = 'http://soundcloud.com/your/track';
SC.initialize({
client_id: 'YOUR_CLIENT_ID'
});
SC.get('/resolve', { url: track_url }, function(track, error) {
if (error) {
alert("Error: " + error.message);
return;
}
// ... rest of your code
});
Try that and see if you get anything, if not, leave a comment.

Categories

Resources