Невозможно записать голос в веб-просмотре - PullRequest
1 голос
/ 28 июня 2019

Внутри веб-просмотра Android Я постоянно получаю сообщение об ошибке PermissionDenied от вызова navigator.mediaDevices.getUserMedia, несмотря на то, что сначала запрашиваю разрешение.

Мой процесс начинается с вызова нижеуказанной функции StartRecordAudio с параметром CheckPermissionFirst, установленным в значение true, если работает в Android.

var AudioRecorder ; // recorder
var RawAudioDataArray ; // raw recorded data
var AudioSaveFormat = "audio/wav" ; // waveform audio - alternatives "audio/mpeg-3" and "audio/webm" ;
var AudioStartCallback ; // function to be called at start of input
var AudioErrorCallback ; // function to be called if audio cannot be recorded (no capability orno permission)
var AudioDoneCallback ; // function to be called at end of input

function StartRecordAudio (CheckPermissionFirst,StartCallback,ErrorCallback,DoneCallback) 
{
AudioStartCallback = StartCallback ; 
AudioErrorCallback = ErrorCallback ; 
AudioDoneCallback  = DoneCallback ; 
RawAudioDataArray = [] ;
if (AudioRecorder)
    {
    StartRecording ();
    }
else if (CheckPermissionFirst)
    {
    CheckAppMicrophonePermission ()
    } 
else
    {
    navigator.mediaDevices.getUserMedia ({audio:true}).then (AudioDeviceFound).catch (AudioErrorCallback); 
    };
};

CheckAppMicrophonePermission выглядит следующим образом

function CheckAppMicrophonePermission ()
{
AndroidBridge.call ("CheckMicrophonePermission" , []);
};

Пропуская подробности AndroidBridge, этот вызов вызывает следующую функцию Java в коде оболочки Android

if ("CheckMicrophonePermission".equals(command))
    {
    if (ContextCompat.checkSelfPermission (MainActivity.this, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
        {
        ActivityCompat.requestPermissions (MainActivity.this, new String[]{android.Manifest.permission.RECORD_AUDIO}, requestMicrophoneId );
        }
    else
        {
        MicrophonePermissionsOK ();
        }
    }

, который после завершения запроса пользователь будет вызывать

public void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)
    {
    switch (requestCode)
        {
        case requestMicrophoneId:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                {
                MicrophonePermissionsOK();
                break;
                }
            else if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE))
                {
                MicrophonePermissionsNOTOK(false);
                }
            else
                {
                MicrophonePermissionsNOTOK(true);
                };
            break;
        }
    }

Функция MicrophonePermissionsOK выглядит следующим образом:

public void MicrophonePermissionsOK ()
{
String jsString = "AppMicrophonePermissionGranted()";
mWebView.evaluateJavascript (jsString);
}

Вернемся на исходную сторону Android Bridge

function AppMicrophonePermissionGranted ()
{
AndroidMicrophonePermission = true ; 
ShowAlert ("Please select OK to activate the app microphone link");
AlertCallback = function () {HideAlert (); AudioPermissionGranted ()};
};

Наконец, когда пользователь в порядке моего диалогового окна предупреждения (подробности этой функции здесь не важны, я думаю), мы получаем:

function AudioPermissionGranted ()
{
navigator.mediaDevices.getUserMedia ({audio:true}).then (AudioDeviceFound).catch (AudioErrorCallback); 

};

Для всех, кто интересуется, обещание удачного маршрута -

function AudioDeviceFound (Stream)
{
AudioRecorder = new MediaRecorder (Stream);
AudioRecorder.ondataavailable = function (e)
    {
    RawAudioDataArray.push (e.data);
    if (AudioRecorder.state == "inactive") // recorder has been stopped either by user or after max seconds
        {
        var blob = new Blob (RawAudioDataArray, {type:AudioSaveFormat});
        var reader = new FileReader ();
        reader.onload = function () {AudioDoneCallback (reader.result.split (',')[1])};
        reader.readAsDataURL (blob);
        };    
    };
StartRecording ();
};

function StartRecording ()
{
AudioStartCallback ();
AudioRecorder.start (1000); // record in 1 second chunks
SetAudioTimeout ();
};

function SetAudioTimeout ()
{
AudioTimeout = window.setTimeout (function () {AudioRecorder.stop(); 
AudioTimeout = null}, MaxAudioSeconds * 1000);
};

Весь этот код прекрасно работает в Chrome и внутри Chrome Packaged App.

Однако я проследил код в веб-представлении Android и получил правильную последовательность действий по всему коду вплоть до вызова обещания getUserMedia.

Это касается нового загруженного приложения или существующего загруженного приложения. Кроме того, когда разрешение не было запрошено ранее, когда запрошено разрешение и отказано, и когда разрешение предоставлено, оба через диалоговое окно разрешения, показанное выше непосредственно в приложении настроек.

Однако (в веб-обозревателе Android) вызов обещания getUserMedia всегда вызывает условие перехвата с именем параметра ошибки, для которого установлено PermissionDenied, а для сообщения - пустая строка.

Пожалуйста, кто-нибудь может мне помочь?

...