diff --git a/packages/react-native-sdk/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt b/packages/react-native-sdk/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt index 06d5a87ec4..58bf5a48bd 100644 --- a/packages/react-native-sdk/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +++ b/packages/react-native-sdk/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt @@ -4,6 +4,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.pm.PackageManager import android.graphics.Bitmap import android.media.AudioAttributes import android.media.AudioFormat @@ -333,6 +334,24 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : } } + @ReactMethod + fun hasAudioOutputHardware(promise: Promise) { + val hasAudioOutput = reactApplicationContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT) + promise.resolve(hasAudioOutput) + } + + @ReactMethod + fun hasMicrophoneHardware(promise: Promise) { + val hasAudioInput = reactApplicationContext.packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE) + promise.resolve(hasAudioInput) + } + + @ReactMethod + fun hasCameraHardware(promise: Promise) { + val hasCamera = reactApplicationContext.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) + promise.resolve(hasCamera) + } + private fun getBatteryStatusFromIntent(intent: Intent): WritableMap { val status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1) val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) diff --git a/packages/react-native-sdk/src/utils/StreamVideoRN/index.ts b/packages/react-native-sdk/src/utils/StreamVideoRN/index.ts index 802562209c..ca45cf4c50 100644 --- a/packages/react-native-sdk/src/utils/StreamVideoRN/index.ts +++ b/packages/react-native-sdk/src/utils/StreamVideoRN/index.ts @@ -5,7 +5,7 @@ import newNotificationCallbacks, { } from '../internal/newNotificationCallbacks'; import { setupIosCallKeepEvents } from '../push/setupIosCallKeepEvents'; import { setupIosVoipPushEvents } from '../push/setupIosVoipPushEvents'; -import { NativeModules } from 'react-native'; +import { NativeModules, Platform } from 'react-native'; // Utility type for deep partial type DeepPartial = { @@ -171,13 +171,49 @@ export class StreamVideoRN { * Play native busy tone for call rejection */ static async playBusyTone() { - return NativeModules.StreamVideoReactNative?.playBusyTone(); + return NativeModules.StreamVideoReactNative.playBusyTone(); } /** * Stop native busy tone */ static async stopBusyTone() { - return NativeModules.StreamVideoReactNative?.stopBusyTone(); + return NativeModules.StreamVideoReactNative.stopBusyTone(); + } + + /** + * Check if the device has audio output hardware + * @returns True if the device has audio output hardware + */ + static async androidHasAudioOutputHardware(): Promise { + if (Platform.OS !== 'android') + throw new Error( + 'androidHasAudioOutputHardware function is only available on Android', + ); + return NativeModules.StreamVideoReactNative.hasAudioOutputHardware(); + } + + /** + * Check if the device has microphone hardware + * @returns True if the device has microphone hardware + */ + static async androidHasMicrophoneHardware(): Promise { + if (Platform.OS !== 'android') + throw new Error( + 'androidHasMicrophoneHardware function is only available on Android', + ); + return NativeModules.StreamVideoReactNative.hasMicrophoneHardware(); + } + + /** + * Check if the device has camera hardware + * @returns True if the device has camera hardware + */ + static async androidHasCameraHardware(): Promise { + if (Platform.OS !== 'android') + throw new Error( + 'androidHasCameraHardware function is only available on Android', + ); + return NativeModules.StreamVideoReactNative.hasCameraHardware(); } }