Skip to content

Commit ece4201

Browse files
fix: use ACTION_INCOMING_CALL for receiving background calls
1 parent b1ba68f commit ece4201

File tree

4 files changed

+37
-28
lines changed

4 files changed

+37
-28
lines changed

android/src/main/java/com/hoxfon/react/RNTwilioVoice/Constants.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ public class Constants {
1212
public static final String VOICE_CHANNEL_HIGH_IMPORTANCE = "notification-channel-high-importance";
1313
public static final String INCOMING_CALL_INVITE = "INCOMING_CALL_INVITE";
1414
public static final String CANCELLED_CALL_INVITE = "CANCELLED_CALL_INVITE";
15-
public static final String CANCELLED_CALL_INVITE_ERROR = "CANCELLED_CALL_INVITE_ERROR";
15+
public static final String CANCELLED_CALL_INVITE_EXCEPTION = "CANCELLED_CALL_INVITE_ERROR";
1616
public static final String INCOMING_CALL_NOTIFICATION_ID = "INCOMING_CALL_NOTIFICATION_ID";
17-
public static final String ACTION_OPEN_CALL_INVITE = "com.hoxfon.react.RNTwilioVoice.OPEN_CALL_INVITE";
1817
public static final String ACTION_ACCEPT = "com.hoxfon.react.RNTwilioVoice.ACTION_ACCEPT";
1918
public static final String ACTION_REJECT = "com.hoxfon.react.RNTwilioVoice.ACTION_REJECT";
2019
public static final String ACTION_MISSED_CALL = "MISSED_CALL";

android/src/main/java/com/hoxfon/react/RNTwilioVoice/IncomingCallNotificationService.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,16 @@ public class IncomingCallNotificationService extends Service {
3434

3535
@Override
3636
public int onStartCommand(Intent intent, int flags, int startId) {
37+
if (BuildConfig.DEBUG) {
38+
Log.d(TAG, "onStartCommand() intent: " + intent + ", flags: " + flags);
39+
}
3740
String action = intent.getAction();
3841

3942
CallInvite callInvite = intent.getParcelableExtra(Constants.INCOMING_CALL_INVITE);
4043
int notificationId = intent.getIntExtra(Constants.INCOMING_CALL_NOTIFICATION_ID, 0);
4144

4245
switch (action) {
46+
// when a callInvite is received in the background
4347
case Constants.ACTION_INCOMING_CALL:
4448
handleIncomingCall(callInvite, notificationId);
4549
break;
@@ -64,15 +68,16 @@ public IBinder onBind(Intent intent) {
6468
}
6569

6670
private Notification createNotification(CallInvite callInvite, int notificationId, int channelImportance) {
67-
Context ctx = getApplicationContext();
71+
Context context = getApplicationContext();
6872

69-
Intent intent = new Intent(ctx, getMainActivityClass(ctx));
70-
intent.setAction(Constants.ACTION_OPEN_CALL_INVITE);
73+
Intent intent = new Intent(context, getMainActivityClass(context));
74+
intent.setAction(Constants.ACTION_INCOMING_CALL);
7175
intent.putExtra(Constants.INCOMING_CALL_NOTIFICATION_ID, notificationId);
7276
intent.putExtra(Constants.INCOMING_CALL_INVITE, callInvite);
7377
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
78+
7479
PendingIntent pendingIntent =
75-
PendingIntent.getActivity(ctx, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
80+
PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
7681

7782
/*
7883
* Pass the notification id and call sid to use as an identifier to cancel the
@@ -117,24 +122,24 @@ private Notification buildNotification(String text, PendingIntent pendingIntent,
117122
final CallInvite callInvite,
118123
int notificationId,
119124
String channelId) {
120-
Context ctx = getApplicationContext();
125+
Context context = getApplicationContext();
121126

122-
Intent rejectIntent = new Intent(ctx, IncomingCallNotificationService.class);
127+
Intent rejectIntent = new Intent(context, IncomingCallNotificationService.class);
123128
rejectIntent.setAction(Constants.ACTION_REJECT);
124129
rejectIntent.putExtra(Constants.INCOMING_CALL_INVITE, callInvite);
125130
rejectIntent.putExtra(Constants.INCOMING_CALL_NOTIFICATION_ID, notificationId);
126131
PendingIntent piRejectIntent = PendingIntent.getService(getApplicationContext(), 0, rejectIntent, PendingIntent.FLAG_UPDATE_CURRENT);
127132
NotificationCompat.Action rejectAction = new NotificationCompat.Action.Builder(android.R.drawable.ic_menu_delete, getString(R.string.reject), piRejectIntent).build();
128133

129-
Intent acceptIntent = new Intent(ctx, IncomingCallNotificationService.class);
134+
Intent acceptIntent = new Intent(context, IncomingCallNotificationService.class);
130135
acceptIntent.setAction(Constants.ACTION_ACCEPT);
131136
acceptIntent.putExtra(Constants.INCOMING_CALL_INVITE, callInvite);
132137
acceptIntent.putExtra(Constants.INCOMING_CALL_NOTIFICATION_ID, notificationId);
133138
PendingIntent piAcceptIntent = PendingIntent.getService(getApplicationContext(), 0, acceptIntent, PendingIntent.FLAG_UPDATE_CURRENT);
134139
NotificationCompat.Action answerAction = new NotificationCompat.Action.Builder(android.R.drawable.ic_menu_call, getString(R.string.accept), piAcceptIntent).build();
135140

136141
NotificationCompat.Builder builder =
137-
new NotificationCompat.Builder(ctx, channelId)
142+
new NotificationCompat.Builder(context, channelId)
138143
.setSmallIcon(R.drawable.ic_call_white_24dp)
139144
.setContentTitle(getString(R.string.call_incoming_title))
140145
.setContentText(text)
@@ -149,8 +154,8 @@ private Notification buildNotification(String text, PendingIntent pendingIntent,
149154
.setContentIntent(pendingIntent);
150155

151156
// build notification large icon
152-
Resources res = ctx.getResources();
153-
int largeIconResId = res.getIdentifier("ic_launcher", "mipmap", ctx.getPackageName());
157+
Resources res = context.getResources();
158+
int largeIconResId = res.getIdentifier("ic_launcher", "mipmap", context.getPackageName());
154159
Bitmap largeIconBitmap = BitmapFactory.decodeResource(res, largeIconResId);
155160

156161
if (largeIconResId != 0) {
@@ -166,7 +171,6 @@ private String createChannel(int channelImportance) {
166171
if (channelImportance == NotificationManager.IMPORTANCE_LOW) {
167172
channelId = Constants.VOICE_CHANNEL_LOW_IMPORTANCE;
168173
}
169-
Log.d(TAG, "channel importance: %d" + channelImportance);
170174
NotificationChannel callInviteChannel = new NotificationChannel(channelId,
171175
"Incoming calls", channelImportance);
172176
callInviteChannel.setLightColor(Color.GREEN);
@@ -226,7 +230,7 @@ private void setCallInProgressNotification(CallInvite callInvite, int notificati
226230
int importance = NotificationManager.IMPORTANCE_LOW;
227231
if (!isAppVisible()) {
228232
if (BuildConfig.DEBUG) {
229-
Log.i(TAG, "setCallInProgressNotification - app is NOT visible.");
233+
Log.i(TAG, "app is NOT visible.");
230234
}
231235
importance = NotificationManager.IMPORTANCE_HIGH;
232236
}
@@ -237,6 +241,9 @@ private void setCallInProgressNotification(CallInvite callInvite, int notificati
237241
* Send the CallInvite to the Activity. Start the activity if it is not running already.
238242
*/
239243
private void sendCallInviteToActivity(CallInvite callInvite, int notificationId) {
244+
// TODO in case the app is killed there is not enough time for the incoming call event to be sent to JS
245+
// therefore leaving the heads up notification present is the only way to allow the call to be answered
246+
// endForeground();
240247
if (BuildConfig.DEBUG) {
241248
Log.d(TAG, "sendCallInviteToActivity()");
242249
}

android/src/main/java/com/hoxfon/react/RNTwilioVoice/TwilioVoiceModule.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ public class TwilioVoiceModule extends ReactContextBaseJavaModule implements Act
102102
public TwilioVoiceModule(ReactApplicationContext reactContext,
103103
boolean shouldAskForMicPermission) {
104104
super(reactContext);
105+
105106
if (BuildConfig.DEBUG) {
106107
Voice.setLogLevel(LogLevel.DEBUG);
107108
} else {
@@ -418,7 +419,7 @@ public void onReceive(Context context, Intent intent) {
418419
activeCallInvite = intent.getParcelableExtra(Constants.INCOMING_CALL_INVITE);
419420

420421
switch (action) {
421-
// when the app is visible the call invite is received directly by the activity
422+
// when a callInvite is received in the foreground
422423
case Constants.ACTION_INCOMING_CALL:
423424
handleCallInviteNotification();
424425
break;
@@ -472,7 +473,7 @@ private void handleStartActivityIntent(Intent intent) {
472473
}
473474
String action = intent.getAction();
474475
if (BuildConfig.DEBUG) {
475-
Log.d(TAG, "handleIncomingCallIntent() action: " + action);
476+
Log.d(TAG, "handleStartActivityIntent() action: " + action);
476477
}
477478
activeCallInvite = intent.getParcelableExtra(Constants.INCOMING_CALL_INVITE);
478479

@@ -503,8 +504,8 @@ private void handleStartActivityIntent(Intent intent) {
503504
reject();
504505
break;
505506

506-
case Constants.ACTION_OPEN_CALL_INVITE:
507-
// the notification already brings the activity to the top
507+
case Constants.ACTION_INCOMING_CALL:
508+
handleCallInviteNotification();
508509
break;
509510

510511
case Constants.ACTION_OPEN_CALL_IN_PROGRESS:
@@ -527,13 +528,15 @@ private void handleCallInviteNotification() {
527528
}
528529
SoundPoolManager.getInstance(getReactApplicationContext()).playRinging();
529530

530-
// TODO check whether the following condition is ever true
531-
if (getReactApplicationContext().getCurrentActivity() != null) {
532-
Window window = getReactApplicationContext().getCurrentActivity().getWindow();
533-
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
534-
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
535-
);
536-
}
531+
// TODO refactor this old block as it doesn't work in Android SDK 29
532+
// not called when phone is locked
533+
// the window flags can only be changed by the main View that, on creation of activity?
534+
// if (getReactApplicationContext().getCurrentActivity() != null) {
535+
// Window window = getReactApplicationContext().getCurrentActivity().getWindow();
536+
// window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
537+
// | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
538+
// );
539+
// }
537540
// if the app is VISIBLE, send a call received event
538541
int appImportance = callNotificationManager.getApplicationImportance(getReactApplicationContext());
539542
if (appImportance <= RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
@@ -564,7 +567,7 @@ private void handleCancelCall(Intent intent) {
564567
params.putString(Constants.CALL_SID, cancelledCallInvite.getCallSid());
565568
params.putString(Constants.CALL_FROM, cancelledCallInvite.getFrom());
566569
params.putString(Constants.CALL_TO, cancelledCallInvite.getTo());
567-
String cancelledCallInviteErr = intent.getStringExtra(Constants.CANCELLED_CALL_INVITE_ERROR);
570+
String cancelledCallInviteErr = intent.getStringExtra(Constants.CANCELLED_CALL_INVITE_EXCEPTION);
568571
// pass this to the event even though in v5.0.2 it is always "Call Cancelled"
569572
if (cancelledCallInviteErr != null) {
570573
params.putString(Constants.ERROR, cancelledCallInviteErr);

android/src/main/java/com/hoxfon/react/RNTwilioVoice/fcm/VoiceFirebaseMessagingService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public void run() {
8787
if (context != null) {
8888
appImportance = callNotificationManager.getApplicationImportance((ReactApplicationContext)context);
8989
if (BuildConfig.DEBUG) {
90-
Log.d(TAG, "context is present, appImportance = " + appImportance);
90+
Log.d(TAG, "context not present, appImportance = " + appImportance);
9191
}
9292
}
9393

@@ -140,7 +140,7 @@ private void handleCancelledCallInvite(CancelledCallInvite cancelledCallInvite,
140140
intent.setAction(Constants.ACTION_CANCEL_CALL);
141141
intent.putExtra(Constants.CANCELLED_CALL_INVITE, cancelledCallInvite);
142142
if (callException != null) {
143-
intent.putExtra(Constants.CANCELLED_CALL_INVITE_ERROR, callException.getMessage());
143+
intent.putExtra(Constants.CANCELLED_CALL_INVITE_EXCEPTION, callException.getMessage());
144144
}
145145
startService(intent);
146146
}

0 commit comments

Comments
 (0)