Skip to content

Commit

Permalink
feat: Android handle incoming call when the app is closed
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziomoscon committed Dec 26, 2020
1 parent 458b0d4 commit 42b8820
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public void createMissedCallNotification(ReactApplicationContext context, String
/*
* Create the notification shown in the notification drawer
*/
String title = context.getString(R.string.call_missed);
String title = context.getString(R.string.call_missed_title);
NotificationCompat.Builder notification =
new NotificationCompat.Builder(context, VOICE_CHANNEL)
.setGroup(MISSED_CALLS_GROUP)
Expand All @@ -115,7 +115,7 @@ public void createMissedCallNotification(ReactApplicationContext context, String
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setSmallIcon(R.drawable.ic_call_missed_white_24dp)
.setContentTitle(title)
.setContentText(callFrom + " called")
.setContentText(callFrom + context.getString(R.string.call_missed_from))
.setAutoCancel(true)
.setShowWhen(true)
.setExtras(extras)
Expand All @@ -128,9 +128,9 @@ public void createMissedCallNotification(ReactApplicationContext context, String
inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle(title);
} else {
inboxStyle.setBigContentTitle(String.valueOf(missedCalls) + " missed calls");
inboxStyle.setBigContentTitle(String.valueOf(missedCalls) + context.getString(R.string.call_missed_title_plural));
}
inboxStyle.addLine("last call from: " +callFrom);
inboxStyle.addLine(context.getString(R.string.call_missed_more) +callFrom);
sharedPrefEditor.putInt(MISSED_CALLS_GROUP, missedCalls);
sharedPrefEditor.commit();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_CONNECTION_DID_CONNECT;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_CONNECTION_DID_DISCONNECT;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_DEVICE_DID_RECEIVE_INCOMING;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_CALL_INVITE_CANCELLED;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_DEVICE_NOT_READY;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_DEVICE_READY;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_CALL_STATE_RINGING;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_CALL_INVITE_CANCELLED;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_CONNECTION_IS_RECONNECTING;
import static com.hoxfon.react.RNTwilioVoice.EventManager.EVENT_CONNECTION_DID_RECONNECT;

Expand Down Expand Up @@ -111,7 +111,7 @@ public class TwilioVoiceModule extends ReactContextBaseJavaModule implements Act
private AudioFocusRequest focusRequest;
private HeadsetManager headsetManager;
private EventManager eventManager;
private int callInviteIntent;
private int existingCallInviteIntent;

public TwilioVoiceModule(ReactApplicationContext reactContext,
boolean shouldAskForMicPermission) {
Expand Down Expand Up @@ -170,8 +170,8 @@ public void onHostResume() {
if (BuildConfig.DEBUG) {
Log.d(TAG, "Module creation "+action+". Intent "+ intent.getExtras());
}
if (action.equals(ACTION_ACCEPT) && callInviteIntent != currentCallInviteIntent) {
callInviteIntent = currentCallInviteIntent;
if (action.equals(ACTION_ACCEPT) && currentCallInviteIntent != existingCallInviteIntent) {
existingCallInviteIntent = currentCallInviteIntent;
handleIncomingCallIntent(intent);
}
}
Expand All @@ -189,6 +189,11 @@ public void onHostDestroy() {
unsetAudioFocus();
}

@Override
public String getName() {
return TAG;
}

@Override
public void onNewIntent(Intent intent) {
// This is called only when the App is in the foreground
Expand All @@ -198,11 +203,6 @@ public void onNewIntent(Intent intent) {
handleIncomingCallIntent(intent);
}

@Override
public String getName() {
return TAG;
}

private RegistrationListener registrationListener() {
return new RegistrationListener() {
@Override
Expand Down Expand Up @@ -698,26 +698,11 @@ public void connect(ReadableMap params) {
twiMLParams.put(key, params.getString(key));
break;
default:
Log.d(TAG, "Could not convert with key: " + key + ".");
Log.d(TAG, "Could not convert key: " + key + ". ReadableType: "+ readableType.toString());
break;
}
}

// Set<IceServer> iceServers = new HashSet<>();
// iceServers.add(new IceServer("stun:global.stun.twilio.com:3478?transport=udp"));
// iceServers.add(new IceServer("turn:global.turn.twilio.com:3478?transport=udp","8e6467be547b969ad913f7bdcfb73e411b35f648bd19f2c1cb4161b4d4a067be","n8zwmkgjIOphHN93L/aQxnkUp1xJwrZVLKc/RXL0ZpM="));
// iceServers.add(new IceServer("turn:global.turn.twilio.com:3478?transport=tcp","8e6467be547b969ad913f7bdcfb73e411b35f648bd19f2c1cb4161b4d4a067be","n8zwmkgjIOphHN93L/aQxnkUp1xJwrZVLKc/RXL0ZpM="));
// iceServers.add(new IceServer("turn:global.turn.twilio.com:443?transport=tcp","8e6467be547b969ad913f7bdcfb73e411b35f648bd19f2c1cb4161b4d4a067be","n8zwmkgjIOphHN93L/aQxnkUp1xJwrZVLKc/RXL0ZpM="));
//
// IceOptions iceOptions = new IceOptions.Builder()
// .iceServers(iceServers)
// .build();
//
// ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
// .iceOptions(iceOptions)
// .enableDscp(true)
// .params(twiMLParams)
// .build();
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
.enableDscp(true)
.params(twiMLParams)
Expand Down Expand Up @@ -807,7 +792,7 @@ private void setAudioFocus() {
}
savedAudioMode = audioManager.getMode();
// Request audio focus before making any device switch
if (Build.VERSION.SDK_INT >= 26) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AudioAttributes playbackAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
Expand Down Expand Up @@ -845,7 +830,7 @@ private void unsetAudioFocus() {
return;
}
audioManager.setMode(savedAudioMode);
if (Build.VERSION.SDK_INT >= 26) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (focusRequest != null) {
audioManager.abandonAudioFocusRequest(focusRequest);
}
Expand All @@ -864,9 +849,7 @@ private void requestPermissionForMicrophone() {
return;
}
if (ActivityCompat.shouldShowRequestPermissionRationale(getCurrentActivity(), Manifest.permission.RECORD_AUDIO)) {
// Snackbar.make(coordinatorLayout,
// "Microphone permissions needed. Please allow in your application settings.",
// SNACKBAR_DURATION).show();
// TODO
} else {
ActivityCompat.requestPermissions(getCurrentActivity(), new String[]{Manifest.permission.RECORD_AUDIO}, MIC_PERMISSION_REQUEST_CODE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void onNewToken(String token) {

// Notify Activity of FCM token
Intent intent = new Intent(ACTION_FCM_TOKEN);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
LocalBroadcastManager.getInstance(this.getBaseContext()).sendBroadcast(intent);
}

/**
Expand Down Expand Up @@ -86,12 +86,19 @@ public void run() {
ReactInstanceManager mReactInstanceManager = ((ReactApplication) getApplication()).getReactNativeHost().getReactInstanceManager();
ReactContext context = mReactInstanceManager.getCurrentReactContext();

// initialise appImportance to the highest possible importance in case context is null
int appImportance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;

// if the app is closed or not visible, create a heads-up notification
int appImportance = callNotificationManager.getApplicationImportance((ReactApplicationContext)context);
if (BuildConfig.DEBUG) {
Log.d(TAG, "CONTEXT present appImportance = " + appImportance);
if (context != null) {
appImportance = callNotificationManager.getApplicationImportance((ReactApplicationContext)context);
if (BuildConfig.DEBUG) {
Log.d(TAG, "context is present, appImportance = " + appImportance);
}
}
if (context == null || appImportance > ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {

// when the app is not started or in the background
if (appImportance > ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
handleInvite(callInvite, notificationId);
return;
}
Expand Down
6 changes: 5 additions & 1 deletion android/src/main/res/values/values.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@
<string name="hangup" translatable="false">Hang up</string>
<string name="call_in_progress" translatable="false">Call in progress</string>
<string name="call_incoming" translatable="false">Incoming call</string>
<string name="call_missed" translatable="false">Missed call</string>
<string name="call_missed_title" translatable="false">Missed call</string>
<string name="call_missed_more" translatable="false">last call from: </string>
<string name="call_missed_from" translatable="false"> called</string>
<string name="call_missed_title_plural" translatable="false"> missed calls</string>

</resources>

0 comments on commit 42b8820

Please sign in to comment.