I've built a react-native app using expo. The app is nothing but a webview for a responsive website.
The website in the webview needs to use the microphone sometimes to record (ideally the camera as well, but trying to figure this one out for now). The functionality works just fine on web but I am experiencing issues on the app. The permission is never granted/resolved, even though I do grant it when the app itself asks for the permission. The thing is that it doesn't seem to also fail? I've tried adding logs to understand at what point it fails and why, but even they don't print fully.
Here is my app (this is all there is to it)
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
import { StyleSheet } from "react-native";
import { WebView } from "react-native-webview";
export default function App() {
const debugging = `
const consoleLog = (type, log) => window.ReactNativeWebView.postMessage(JSON.stringify({'type': 'Console', 'data': {'type': type, 'log': log}}));
console = {
log: (log) => consoleLog('log', log),
debug: (log) => consoleLog('debug', log),
info: (log) => consoleLog('info', log),
warn: (log) => consoleLog('warn', log),
error: (log) => consoleLog('error', log),
};
`;
const onMessage = (payload: any) => {
let dataPayload;
try {
dataPayload = JSON.parse(payload.nativeEvent.data);
} catch (e: unknown) {
let message = "Parsing failed: ";
if (e instanceof Error) message += e.message;
console.log(message);
}
if (dataPayload) {
if (dataPayload.type === "Console") {
console.info(`[Console] ${JSON.stringify(dataPayload.data)}`);
} else {
console.log(dataPayload);
}
} else {
console.log("No payload");
}
};
return (
<SafeAreaProvider>
<SafeAreaView style={styles.container}>
<WebView
source={{ uri: "https://web.mynders.com" }}
mediaCapturePermissionRequestType="grant"
injectedJavaScript={debugging}
onMessage={onMessage}
style={styles.webView}
/>
</SafeAreaView>
</SafeAreaProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
borderWidth: 0,
},
webView: {
flex: 1,
borderWidth: 0,
},
});
Then in my web app, here's the part that is trying to get the permissions:
import React, { useState } from "react";
import { PiMicrophoneSlashLight } from "react-icons/pi";
const RecordButton: React.FC = () => {
const [permission, setPermission] = useState(false);
const getMicrophonePermission = async () => {
if ("MediaRecorder" in window) {
try {
console.log("trying to get permissions.");
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
});
console.log("received permissions.");
setPermission(true);
console.log("Prmission was set to true.");
stream.getTracks().forEach((t) => t.stop());
console.log("cleared all tracks.");
} catch (err: unknown) {
let message = "Failed to get mic permissions: ";
if (err instanceof Error) message += err.message;
console.log(message);
alert(message);
}
} else {
console.log("The MediaRecorder API is not supported in your browser.");
alert("The MediaRecorder API is not supported in your browser.");
}
};
if (!permission)
return (
<div
onClick={getMicrophonePermission}
className={[
"rounded-full cursor-pointer m-1 transition-all ease-in-out bg-gray-200 p-2",
].join(" ")}
>
<PiMicrophoneSlashLight className="h-5 w-5 text-gray-400 select-none cursor-pointer" />
</div>
);
};
export default RecordButton;
When I click the button, this is the log I get:
INFO [Console] {"type":"log","log":"trying to get."}
Nothing after to indicate either success or failure. It's as if it never finishes awaiting? Or something else, not sure, can't remember ever experiencing something like that.
This is my app.json btw with the permissions I ask for (currently trying to make it work on an Android device):
{
"expo": {
...
"android": {
...
"permissions": [
"android.permission.INTERNET",
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.MODIFY_AUDIO_SETTINGS",
"android.permission.AUDIO_CAPTURE",
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
"android.permission.ACCESS_FINE_LOCATION",
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.FOREGROUND_SERVICE"
]
},
}
}
I can't report on why I got no logs out, but as far as my oiginal issue of gting the permissions needed for the mic and camera, using
expo-avandexpo-cameraI have it working now.Here's the complete setup I have for the component: