Skip to content

Support self managed capability #237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,15 @@ const options = {
RNCallKeep.hasDefaultPhoneAccount(options);
```

### backToForeground
_This feature is available only on Android._

Use this to display the application in foreground if the application was in background state.
This method will open the application if it was closed.

```js
RNCallKeep.backToForeground();
```

## Events

Expand Down
5 changes: 5 additions & 0 deletions actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const RNCallKeepDidDisplayIncomingCall = 'RNCallKeepDidDisplayIncomingCall';
const RNCallKeepDidPerformSetMutedCallAction = 'RNCallKeepDidPerformSetMutedCallAction';
const RNCallKeepDidToggleHoldAction = 'RNCallKeepDidToggleHoldAction';
const RNCallKeepDidPerformDTMFAction = 'RNCallKeepDidPerformDTMFAction';
const RNCallKeepPerformShowIncomingCallAction = 'RNCallKeepPerformShowIncomingCallAction';
const RNCallKeepProviderReset = 'RNCallKeepProviderReset';
const RNCallKeepCheckReachability = 'RNCallKeepCheckReachability';
const isIOS = Platform.OS === 'ios';
Expand Down Expand Up @@ -49,6 +50,9 @@ const didToggleHoldCallAction = handler =>
const didPerformDTMFAction = handler =>
eventEmitter.addListener(RNCallKeepDidPerformDTMFAction, (data) => handler(data));

const showIncomingCall = handler =>
eventEmitter.addListener(RNCallKeepPerformShowIncomingCallAction, (data) => handler(data));

const didResetProvider = handler =>
eventEmitter.addListener(RNCallKeepProviderReset, handler);

Expand All @@ -66,5 +70,6 @@ export const listeners = {
didToggleHoldCallAction,
didPerformDTMFAction,
didResetProvider,
showIncomingCall,
checkReachability,
};
20 changes: 20 additions & 0 deletions android/src/main/java/io/wazo/callkeep/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.wazo.callkeep;

public class Constants {
public static final String ACTION_ANSWER_CALL = "ACTION_ANSWER_CALL";
public static final String ACTION_AUDIO_SESSION = "ACTION_AUDIO_SESSION";
public static final String ACTION_CHECK_REACHABILITY = "ACTION_CHECK_REACHABILITY";
public static final String ACTION_SHOW_INCOMING_CALL = "ACTION_SHOW_INCOMING_CALL";
public static final String ACTION_DTMF_TONE = "ACTION_DTMF_TONE";
public static final String ACTION_END_CALL = "ACTION_END_CALL";
public static final String ACTION_HOLD_CALL = "ACTION_HOLD_CALL";
public static final String ACTION_MUTE_CALL = "ACTION_MUTE_CALL";
public static final String ACTION_ONGOING_CALL = "ACTION_ONGOING_CALL";
public static final String ACTION_UNHOLD_CALL = "ACTION_UNHOLD_CALL";
public static final String ACTION_UNMUTE_CALL = "ACTION_UNMUTE_CALL";
public static final String ACTION_WAKE_APP = "ACTION_WAKE_APP";

public static final String EXTRA_CALL_IDENTIFIER = "EXTRA_CALL_IDENTIFIER";
public static final String EXTRA_CALL_UUID = "EXTRA_CALL_UUID";
public static final String EXTRA_CALLER_NAME = "EXTRA_CALLER_NAME";
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
import com.facebook.react.bridge.Arguments;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;

import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALLER_NAME;
import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_IDENTIFIER;
import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_UUID;
import static io.wazo.callkeep.Constants.EXTRA_CALLER_NAME;
import static io.wazo.callkeep.Constants.EXTRA_CALL_IDENTIFIER;
import static io.wazo.callkeep.Constants.EXTRA_CALL_UUID;

import javax.annotation.Nullable;

Expand Down
91 changes: 70 additions & 21 deletions android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.WindowManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
Expand All @@ -56,6 +57,7 @@
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;

import java.lang.reflect.Array;
Expand All @@ -68,26 +70,27 @@

import static android.support.v4.app.ActivityCompat.requestPermissions;

import static io.wazo.callkeep.Constants.EXTRA_CALLER_NAME;
import static io.wazo.callkeep.Constants.EXTRA_CALL_UUID;
import static io.wazo.callkeep.Constants.EXTRA_CALL_IDENTIFIER;
import static io.wazo.callkeep.Constants.ACTION_END_CALL;
import static io.wazo.callkeep.Constants.ACTION_ANSWER_CALL;
import static io.wazo.callkeep.Constants.ACTION_MUTE_CALL;
import static io.wazo.callkeep.Constants.ACTION_UNMUTE_CALL;
import static io.wazo.callkeep.Constants.ACTION_SHOW_INCOMING_CALL;
import static io.wazo.callkeep.Constants.ACTION_DTMF_TONE;
import static io.wazo.callkeep.Constants.ACTION_HOLD_CALL;
import static io.wazo.callkeep.Constants.ACTION_UNHOLD_CALL;
import static io.wazo.callkeep.Constants.ACTION_ONGOING_CALL;
import static io.wazo.callkeep.Constants.ACTION_AUDIO_SESSION;
import static io.wazo.callkeep.Constants.ACTION_CHECK_REACHABILITY;
import static io.wazo.callkeep.Constants.ACTION_WAKE_APP;

// @see https://github.com/kbagchiGWC/voice-quickstart-android/blob/9a2aff7fbe0d0a5ae9457b48e9ad408740dfb968/exampleConnectionService/src/main/java/com/twilio/voice/examples/connectionservice/VoiceConnectionServiceActivity.java
public class RNCallKeepModule extends ReactContextBaseJavaModule {
public static final int REQUEST_READ_PHONE_STATE = 1337;
public static final int REQUEST_REGISTER_CALL_PROVIDER = 394859;

public static final String CHECKING_PERMS = "CHECKING_PERMS";
public static final String EXTRA_CALLER_NAME = "EXTRA_CALLER_NAME";
public static final String EXTRA_CALL_UUID = "EXTRA_CALL_UUID";
public static final String EXTRA_CALL_IDENTIFIER = "EXTRA_CALL_IDENTIFIER";
public static final String ACTION_END_CALL = "ACTION_END_CALL";
public static final String ACTION_ANSWER_CALL = "ACTION_ANSWER_CALL";
public static final String ACTION_MUTE_CALL = "ACTION_MUTE_CALL";
public static final String ACTION_UNMUTE_CALL = "ACTION_UNMUTE_CALL";
public static final String ACTION_DTMF_TONE = "ACTION_DTMF_TONE";
public static final String ACTION_HOLD_CALL = "ACTION_HOLD_CALL";
public static final String ACTION_UNHOLD_CALL = "ACTION_UNHOLD_CALL";
public static final String ACTION_ONGOING_CALL = "ACTION_ONGOING_CALL";
public static final String ACTION_AUDIO_SESSION = "ACTION_AUDIO_SESSION";
public static final String ACTION_CHECK_REACHABILITY = "ACTION_CHECK_REACHABILITY";

private static final String E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST";
private static final String REACT_NATIVE_MODULE_NAME = "RNCallKeep";
private static final String[] permissions = { Manifest.permission.READ_PHONE_STATE,
Expand Down Expand Up @@ -119,10 +122,11 @@ public void setup(ReadableMap options) {
VoiceConnectionService.setAvailable(false);
this._settings = options;

if (isConnectionServiceAvailable()) {
if (isConnectionServiceAvailable(_settings)) {
this.registerPhoneAccount(this.getAppContext());
voiceBroadcastReceiver = new VoiceBroadcastReceiver();
registerReceiver();
VoiceConnectionService.setPhoneAccountHandle(handle);
VoiceConnectionService.setAvailable(true);
}
}
Expand Down Expand Up @@ -422,16 +426,37 @@ public static Boolean isConnectionServiceAvailable() {
return Build.VERSION.SDK_INT >= 23;
}

@ReactMethod
public static Boolean isConnectionServiceAvailable(ReadableMap options) {
if (options != null && options.hasKey("selfManaged") && options.getBoolean("selfManaged")) {
// Self managed connection is available since api level 26
return Build.VERSION.SDK_INT >= 26;
} else {
return isConnectionServiceAvailable();
}
}

@ReactMethod
public void backToForeground() {
Context context = getAppContext();
String packageName = context.getApplicationContext().getPackageName();
Intent focusIntent = context.getPackageManager().getLaunchIntentForPackage(packageName).cloneFilter();
Activity activity = getCurrentActivity();
boolean isOpened = activity != null;
Log.d(TAG, "backToForeground, app isOpened ?" + (isOpened ? "true" : "false"));

focusIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
if (isOpened) {
focusIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
activity.startActivity(focusIntent);
} else {

Activity activity = getCurrentActivity();
activity.startActivity(focusIntent);
focusIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK +
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED +
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD +
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

getReactApplicationContext().startActivity(focusIntent);
}
}

private void registerPhoneAccount(Context appContext) {
Expand All @@ -445,8 +470,13 @@ private void registerPhoneAccount(Context appContext) {
handle = new PhoneAccountHandle(cName, appName);

PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, appName)
.addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_VIDEO_CALLING);
.addSupportedUriScheme(PhoneAccount.SCHEME_SIP);

if (_settings != null && _settings.hasKey("selfManaged") && _settings.getBoolean("selfManaged")) {
builder.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED | PhoneAccount.CAPABILITY_VIDEO_CALLING);
} else {
builder.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_VIDEO_CALLING);
}

if (_settings != null && _settings.hasKey("imageName")) {
int identifier = appContext.getResources().getIdentifier(_settings.getString("imageName"), "drawable", appContext.getPackageName());
Expand Down Expand Up @@ -498,6 +528,7 @@ private void registerReceiver() {
intentFilter.addAction(ACTION_ANSWER_CALL);
intentFilter.addAction(ACTION_MUTE_CALL);
intentFilter.addAction(ACTION_UNMUTE_CALL);
intentFilter.addAction(ACTION_SHOW_INCOMING_CALL);
intentFilter.addAction(ACTION_DTMF_TONE);
intentFilter.addAction(ACTION_UNHOLD_CALL);
intentFilter.addAction(ACTION_HOLD_CALL);
Expand Down Expand Up @@ -566,6 +597,12 @@ public void onReceive(Context context, Intent intent) {
args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID));
sendEventToJS("RNCallKeepDidPerformDTMFAction", args);
break;
case ACTION_SHOW_INCOMING_CALL:
args.putString("handle", attributeMap.get(EXTRA_CALL_IDENTIFIER));
args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID));
args.putString("name", attributeMap.get(EXTRA_CALLER_NAME));
sendEventToJS("RNCallKeepPerformShowIncomingCallAction", args);
break;
case ACTION_ONGOING_CALL:
args.putString("handle", attributeMap.get(EXTRA_CALL_IDENTIFIER));
args.putString("callUUID", attributeMap.get(EXTRA_CALL_UUID));
Expand All @@ -578,6 +615,18 @@ public void onReceive(Context context, Intent intent) {
case ACTION_CHECK_REACHABILITY:
sendEventToJS("RNCallKeepCheckReachability", null);
break;
case ACTION_WAKE_APP:
Intent headlessIntent = new Intent(reactContext, RNCallKeepBackgroundMessagingService.class);
headlessIntent.putExtra("callUUID", attributeMap.get(EXTRA_CALL_UUID));
headlessIntent.putExtra("name", attributeMap.get(EXTRA_CALLER_NAME));
headlessIntent.putExtra("handle", attributeMap.get(EXTRA_CALL_IDENTIFIER));
Log.d(TAG, "wakeUpApplication: " + attributeMap.get(EXTRA_CALL_UUID) + ", identifier : " + attributeMap.get(EXTRA_CALL_IDENTIFIER) + ", displayName:" + attributeMap.get(EXTRA_CALLER_NAME));

ComponentName name = reactContext.startService(headlessIntent);
if (name != null) {
HeadlessJsTaskService.acquireWakeLockNow(reactContext);
}
break;
}
}
}
Expand Down
31 changes: 20 additions & 11 deletions android/src/main/java/io/wazo/callkeep/VoiceConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,18 @@

import java.util.HashMap;

import static io.wazo.callkeep.RNCallKeepModule.ACTION_ANSWER_CALL;
import static io.wazo.callkeep.RNCallKeepModule.ACTION_AUDIO_SESSION;
import static io.wazo.callkeep.RNCallKeepModule.ACTION_DTMF_TONE;
import static io.wazo.callkeep.RNCallKeepModule.ACTION_END_CALL;
import static io.wazo.callkeep.RNCallKeepModule.ACTION_HOLD_CALL;
import static io.wazo.callkeep.RNCallKeepModule.ACTION_MUTE_CALL;
import static io.wazo.callkeep.RNCallKeepModule.ACTION_UNHOLD_CALL;
import static io.wazo.callkeep.RNCallKeepModule.ACTION_UNMUTE_CALL;
import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALLER_NAME;
import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_IDENTIFIER;
import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_UUID;
import static io.wazo.callkeep.Constants.ACTION_ANSWER_CALL;
import static io.wazo.callkeep.Constants.ACTION_AUDIO_SESSION;
import static io.wazo.callkeep.Constants.ACTION_SHOW_INCOMING_CALL;
import static io.wazo.callkeep.Constants.ACTION_DTMF_TONE;
import static io.wazo.callkeep.Constants.ACTION_END_CALL;
import static io.wazo.callkeep.Constants.ACTION_HOLD_CALL;
import static io.wazo.callkeep.Constants.ACTION_MUTE_CALL;
import static io.wazo.callkeep.Constants.ACTION_UNHOLD_CALL;
import static io.wazo.callkeep.Constants.ACTION_UNMUTE_CALL;
import static io.wazo.callkeep.Constants.EXTRA_CALLER_NAME;
import static io.wazo.callkeep.Constants.EXTRA_CALL_IDENTIFIER;
import static io.wazo.callkeep.Constants.EXTRA_CALL_UUID;

@TargetApi(Build.VERSION_CODES.M)
public class VoiceConnection extends Connection {
Expand All @@ -72,6 +73,14 @@ public class VoiceConnection extends Connection {
}
}

@Override
public void onShowIncomingCallUi() {
super.onShowIncomingCallUi();
Log.d(TAG, "onShowIncomingCallUi called");

sendCallRequestToActivity(ACTION_SHOW_INCOMING_CALL, handle);
}

@Override
public void onExtrasChanged(Bundle extras) {
super.onExtrasChanged(extras);
Expand Down
Loading