Skip to content

Commit

Permalink
Add asking for camera & microphone permissions on Android device + re…
Browse files Browse the repository at this point in the history
…duce audio delay (by reducing audio buffer size)
  • Loading branch information
sierpinskid committed Sep 19, 2024
1 parent 47122ac commit 9195cd7
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
using StreamVideo.ExampleProject.UI.Screens;
using StreamVideo.Libs.Utils;
using UnityEngine;
#if UNITY_ANDROID
using UnityEngine.Android;
#endif

namespace StreamVideo.ExampleProject.UI
{
Expand All @@ -17,6 +20,75 @@ public class UIManager : MonoBehaviour
public VideoResolution SenderVideoResolution => new VideoResolution(_senderVideoWidth, _senderVideoHeight);
public int SenderVideoFps => _senderVideoFps;

public void RequestCameraPermissions(Action onGranted = null, Action onDenied = null)
{
#if UNITY_ANDROID
var callbacks = new PermissionCallbacks();
Permission.RequestUserPermission(Permission.Camera, callbacks);

callbacks.PermissionGranted += _ => { onGranted?.Invoke(); };
callbacks.PermissionDenied += permissionName =>
{
onDenied?.Invoke();
Debug.LogError($"{permissionName} permission was not granted. Video capturing will not work.");
};
callbacks.PermissionDeniedAndDontAskAgain += (permissionName) =>
{
onDenied?.Invoke();
Debug.LogError($"{permissionName} permission was not granted. Video capturing will not work.");
};
#else
Debug.LogError($"Handling permissions not implemented for platform: " + Application.platform);
#endif
}

public bool HasUserAuthorizedCameraPermission()
{
#if UNITY_STANDALONE
return true; //StreamTodo: check if this is true for all platforms
#endif
#if UNITY_ANDROID
return Permission.HasUserAuthorizedPermission(Permission.Camera);
#else
Debug.LogError($"Handling permissions not implemented for platform: " + Application.platform);
#endif
}

public void RequestMicrophonePermissions(Action onGranted = null, Action onDenied = null)
{
#if UNITY_ANDROID
var callbacks = new PermissionCallbacks();

Permission.RequestUserPermission(Permission.Microphone, callbacks);

callbacks.PermissionGranted += _ => { onGranted?.Invoke(); };
callbacks.PermissionDenied += permissionName =>
{
onDenied?.Invoke();
Debug.LogError($"{permissionName} permission was not granted. Video capturing will not work.");
};
callbacks.PermissionDeniedAndDontAskAgain += (permissionName) =>
{
onDenied?.Invoke();
Debug.LogError($"{permissionName} permission was not granted. Video capturing will not work.");
};
#else
Debug.LogError($"Handling permissions not implemented for platform: " + Application.platform);
#endif
}

public bool HasUserAuthorizedMicrophonePermission()
{
#if UNITY_STANDALONE
return true; //StreamTodo: check if this is true for all platforms
#endif
#if UNITY_ANDROID
return Permission.HasUserAuthorizedPermission(Permission.Microphone);
#else
Debug.LogError($"Handling permissions not implemented for platform: " + Application.platform);
#endif
}

protected void Awake()
{
_videoManager.Init();
Expand All @@ -29,9 +101,28 @@ protected void Awake()

_mainScreen.Init(_videoManager, uiManager: this);
_callScreen.Init(_videoManager, uiManager: this);

SelectFirstWorkingCameraOrDefaultAsync().LogIfFailed();
SelectFirstMicrophone();

if (!HasUserAuthorizedCameraPermission())
{
RequestCameraPermissions(onGranted: () => { SelectFirstWorkingCameraOrDefaultAsync().LogIfFailed(); },
onDenied: ()
=> Debug.LogError("Camera permission was not granted. Video capturing will not work."));
}
else
{
SelectFirstWorkingCameraOrDefaultAsync().LogIfFailed();
}

if (!HasUserAuthorizedMicrophonePermission())
{
RequestMicrophonePermissions(onGranted: SelectFirstMicrophone,
onDenied: ()
=> Debug.LogError("Microphone permission was not granted. Audio capturing will not work."));
}
else
{
SelectFirstMicrophone();
}
}

protected void Start() => ShowMainScreen();
Expand Down Expand Up @@ -81,7 +172,7 @@ private void ShowCallScreen(IStreamCall call)
_mainScreen.Hide();
_callScreen.Show(new CallScreenView.ShowArgs(call));
}

private void OnMicrophoneDeviceChanged(MicrophoneDeviceInfo previousDevice, MicrophoneDeviceInfo currentDevice)
{
Debug.Log($"Changed selected MICROPHONE from `{previousDevice}` to `{currentDevice}`");
Expand All @@ -94,31 +185,50 @@ private void OnCameraDeviceChanged(CameraDeviceInfo previousDevice, CameraDevice
var webCamTexture = _videoManager.Client.VideoDeviceManager.GetSelectedDeviceWebCamTexture();
LocalCameraChanged?.Invoke(webCamTexture);
}

private async Task SelectFirstWorkingCameraOrDefaultAsync()
{
if (!_videoManager.Client.VideoDeviceManager.EnumerateDevices().Any())
{
Debug.LogError("No camera devices found! Video streaming will not work. Please ensure that a camera device is plugged in.");
Debug.LogError(
"No camera devices found! Video streaming will not work. Please ensure that a camera device is plugged in.");
return;
}


#if UNITY_ANDROID || UNITY_IOS
foreach (var device in _videoManager.Client.VideoDeviceManager.EnumerateDevices())
{
if (!device.IsFrontFacing)
{
continue;
}

var isWorking = await _videoManager.Client.VideoDeviceManager.TestDeviceAsync(device);
if (isWorking)
{
_videoManager.Client.VideoDeviceManager.SelectDevice(device, enable: false);
return;
}
}
#endif

var workingDevice = await _videoManager.Client.VideoDeviceManager.TryFindFirstWorkingDeviceAsync();
if (workingDevice.HasValue)
{
_videoManager.Client.VideoDeviceManager.SelectDevice(workingDevice.Value, enable: false);
return;
}

Debug.LogWarning("No working camera found. Falling back to first device.");

var firstDevice = _videoManager.Client.VideoDeviceManager.EnumerateDevices().FirstOrDefault();
if (firstDevice == default)
{
Debug.LogError("No camera devices found! Video streaming will not work. Please ensure that a camera device is plugged in.");
Debug.LogError(
"No camera devices found! Video streaming will not work. Please ensure that a camera device is plugged in.");
return;
}

_videoManager.Client.VideoDeviceManager.SelectDevice(firstDevice, enable: false);
}

Expand All @@ -128,10 +238,11 @@ private void SelectFirstMicrophone()
var microphoneDevice = _videoManager.Client.AudioDeviceManager.EnumerateDevices().FirstOrDefault();
if (microphoneDevice == default)
{
Debug.LogError("No microphone devices found! Audio streaming will not work. Please ensure that a microphone device is plugged in.");
Debug.LogError(
"No microphone devices found! Audio streaming will not work. Please ensure that a microphone device is plugged in.");
return;
}

_videoManager.Client.AudioDeviceManager.SelectDevice(microphoneDevice, enable: false);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void SelectDevice(MicrophoneDeviceInfo device, bool enable)
var targetAudioSource = GetOrCreateTargetAudioSource();

targetAudioSource.clip
= Microphone.Start(SelectedDevice.Name, true, 3, AudioSettings.outputSampleRate);
= Microphone.Start(SelectedDevice.Name, true, 1, AudioSettings.outputSampleRate);
targetAudioSource.loop = true;

#if STREAM_DEBUG_ENABLED
Expand Down

0 comments on commit 9195cd7

Please sign in to comment.