Skip to content

Commit

Permalink
change to promise and add audio device change support to android
Browse files Browse the repository at this point in the history
  • Loading branch information
mathias5r committed Jul 6, 2021
1 parent 71f443e commit 0cba24e
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 18 deletions.
72 changes: 72 additions & 0 deletions android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import android.content.res.Resources;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Icon;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
Expand Down Expand Up @@ -491,6 +493,76 @@ public void toggleAudioRouteSpeaker(String uuid, boolean routeSpeaker) {
}
}

@ReactMethod
public void setAudioRoute(String uuid, String audioRoute, Promise promise){
try {
VoiceConnection conn = (VoiceConnection) VoiceConnectionService.getConnection(uuid);
if (conn == null) {
return;
}
if(audioRoute.equals("Bluetooth")) {
conn.setAudioRoute(CallAudioState.ROUTE_BLUETOOTH);
promise.resolve("Successfully set bluetooth route");
return;
}
if(audioRoute.equals("Headset")) {
conn.setAudioRoute(CallAudioState.ROUTE_WIRED_HEADSET);
promise.resolve("Successfully set headset route");
return;
}
if(audioRoute.equals("Speaker")) {
conn.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
promise.resolve("Successfully set speaker route");
return;
}
conn.setAudioRoute(CallAudioState.ROUTE_WIRED_OR_EARPIECE);
promise.resolve("Successfully set phone route");
} catch (Exception e) {
promise.reject("SetAudioRoute", e.getMessage());
}
}

@ReactMethod
public void getAudioRoutes(Promise promise){
try {
Context context = this.getAppContext();
AudioManager audioManager = (AudioManager) context.getSystemService(context.AUDIO_SERVICE);
WritableArray devices = Arguments.createArray();
ArrayList<String> typeChecker = new ArrayList<>();
AudioDeviceInfo[] audioDeviceInfo = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS + AudioManager.GET_DEVICES_OUTPUTS);
for (AudioDeviceInfo device : audioDeviceInfo){
String type = getAudioRouteType(device.getType());
if(type != null && !typeChecker.contains(type)) {
WritableMap deviceInfo = Arguments.createMap();
deviceInfo.putString("name", type);
deviceInfo.putString("type", type);
typeChecker.add(type);
devices.pushMap(deviceInfo);
}
}
promise.resolve(devices);
} catch(Exception e) {
promise.reject("GetAudioRoutes Error", e.getMessage());
}
}

private String getAudioRouteType(int type){
switch (type){
case(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP):
case(AudioDeviceInfo.TYPE_BLUETOOTH_SCO):
return "Bluetooth";
case(AudioDeviceInfo.TYPE_WIRED_HEADPHONES):
case(AudioDeviceInfo.TYPE_WIRED_HEADSET):
return "Headset";
case(AudioDeviceInfo.TYPE_BUILTIN_MIC):
return "Phone";
case(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER):
return "Speaker";
default:
return null;
}
}

@ReactMethod
public void sendDTMF(String uuid, String key) {
Log.d(TAG, "[VoiceConnection] sendDTMF, uuid: " + uuid + ", key: " + key);
Expand Down
11 changes: 2 additions & 9 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,9 @@ declare module 'react-native-callkeep' {

static getCalls(): Promise<object>

static getAudioRoutes(
errorCallback: (error: any) => void,
successCallback: (data: any) => void
): void
static getAudioRoutes(): Promise<void>

static setAudioRoute: (
inputName: string,
errorCallback: (error: any) => void,
successCallback: (data: any) => void
) => void
static setAudioRoute: (uuid:string, inputName: string) => Promise<void>

/**
* @description supportConnectionService method is available only on Android.
Expand Down
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ class RNCallKeep {
*/
toggleAudioRouteSpeaker = (uuid, routeSpeaker) => isIOS ? null : RNCallKeepModule.toggleAudioRouteSpeaker(uuid, routeSpeaker);

getAudioRoutes = (errorCallback, successCallback) => isIOS ? RNCallKeepModule.getAudioRoutes(errorCallback, successCallback) : null;
getAudioRoutes = () => RNCallKeepModule.getAudioRoutes();

setAudioRoute = (inputName, errorCallback, successCallback) => isIOS ? RNCallKeepModule.setAudioRoute(inputName, errorCallback, successCallback) : null;
setAudioRoute = (uuid, inputName) => RNCallKeepModule.setAudioRoute(uuid, inputName);

checkIfBusy = () =>
isIOS ? RNCallKeepModule.checkIfBusy() : Promise.reject('RNCallKeep.checkIfBusy was called from unsupported OS');
Expand Down
43 changes: 36 additions & 7 deletions ios/RNCallKeep/RNCallKeep.m
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,10 @@ + (void)setup:(NSDictionary *)options {
resolve([RNCallKeep getCalls]);
}

RCT_EXPORT_METHOD(setAudioRoute: (NSString *)inputName errorCallback:(RCTResponseSenderBlock)errorCallback successCallback:(RCTResponseSenderBlock)successCallback)
RCT_EXPORT_METHOD(setAudioRoute: (NSString *)uuid
inputName:(NSString *)inputName
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
#ifdef DEBUG
NSLog(@"[setAudioRoute] - inputName: %@", inputName);
Expand All @@ -411,7 +414,7 @@ + (void)setup:(NSDictionary *)options {
if(!isOverrided){
[NSException raise:@"overrideOutputAudioPort failed" format:@"error: %@", err];
}
successCallback(@"Speaker");
resolve(@"Speaker");
return;
}

Expand All @@ -422,29 +425,30 @@ + (void)setup:(NSDictionary *)options {
if(!isSetted){
[NSException raise:@"setPreferredInput failed" format:@"error: %@", err];
}
successCallback(inputName);
resolve(inputName);
}
}
}
@catch ( NSException *e ){
NSLog(@"%@",e);
errorCallback(@[e]);
reject(@"Failure to set audio route", e, nil);
}
}

RCT_EXPORT_METHOD(getAudioRoutes: (RCTResponseSenderBlock)errorCallback successCallback:(RCTResponseSenderBlock)successCallback)
RCT_EXPORT_METHOD(getAudioRoutes: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
#ifdef DEBUG
NSLog(@"[getAudioRoutes]");
#endif
@try {
NSArray *inputs = [RNCallKeep getAudioInputs];
NSMutableArray *formatedInputs = [RNCallKeep formatAudioInputs: inputs];
successCallback(@[formatedInputs]);
resolve(formatedInputs);
}
@catch ( NSException *e ) {
NSLog(@"%@",e);
errorCallback(@[e]);
reject(@"Failure to get audio routes", e, nil);
}
}

Expand Down Expand Up @@ -520,6 +524,31 @@ + (NSString *) getAudioInputType: (NSString *) type
}
}

+ (NSString *) getAudioInputType: (NSString *) type
{
if ([type isEqualToString:AVAudioSessionPortBuiltInMic]){
return @"Phone";
}
else if ([type isEqualToString:AVAudioSessionPortHeadsetMic]){
return @"Headset";
}
else if ([type isEqualToString:AVAudioSessionPortHeadphones]){
return @"Headset";
}
else if ([type isEqualToString:AVAudioSessionPortBluetoothHFP]){
return @"Bluetooth";
}
else if ([type isEqualToString:AVAudioSessionPortBluetoothA2DP]){
return @"Bluetooth";
}
else if ([type isEqualToString:AVAudioSessionPortBuiltInSpeaker]){
return @"Speaker";
}
else{
return @"Unrecognized";
}
}

- (void)requestTransaction:(CXTransaction *)transaction
{
#ifdef DEBUG
Expand Down

0 comments on commit 0cba24e

Please sign in to comment.