Skip to content

Commit 7e6d794

Browse files
draft
1 parent 64c59fa commit 7e6d794

File tree

5 files changed

+214
-41
lines changed

5 files changed

+214
-41
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package com.hoxfon.react.RNTwilioVoice;
2+
3+
import android.app.ActivityManager;
4+
import android.content.BroadcastReceiver;
5+
import android.content.Context;
6+
import android.content.Intent;
7+
import android.os.Bundle;
8+
import android.util.Log;
9+
10+
import com.facebook.react.HeadlessJsTaskService;
11+
12+
import java.util.List;
13+
//import java.util.Random;
14+
//
15+
//import androidx.localbroadcastmanager.content.LocalBroadcastManager;
16+
//
17+
//import com.facebook.react.ReactApplication;
18+
//import com.facebook.react.ReactInstanceManager;
19+
//import com.facebook.react.bridge.ReactApplicationContext;
20+
//import com.facebook.react.bridge.ReactContext;
21+
//import com.hoxfon.react.RNTwilioVoice.CallNotificationManager;
22+
//
23+
//import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.ACTION_INCOMING_CALL;
24+
//import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.INCOMING_CALL_INVITE;
25+
//import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.INCOMING_CALL_NOTIFICATION_ID;
26+
import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.TAG;
27+
28+
public class BackgroundCallReceiver extends BroadcastReceiver {
29+
30+
@Override
31+
public void onReceive(final Context context, final Intent intent) {
32+
Log.d(TAG, "### onReceive");
33+
/**
34+
This part will be called every time network connection is changed
35+
e.g. Connected -> Not Connected
36+
**/
37+
if (!isAppOnForeground((context))) {
38+
// ReactApplicationContext ctx = new ReactApplicationContext(context);
39+
//
40+
// Random randomNumberGenerator = new Random(System.currentTimeMillis());
41+
// final int notificationId = randomNumberGenerator.nextInt();
42+
// CallNotificationManager callNotificationManager = new CallNotificationManager();
43+
//
44+
// int appImportance = callNotificationManager.getApplicationImportance(ctx);
45+
// if (BuildConfig.DEBUG) {
46+
// Log.d(TAG, "CONTEXT not present appImportance = " + appImportance);
47+
// }
48+
// Intent launchIntent = callNotificationManager.getLaunchIntent(
49+
// ctx,
50+
// notificationId,
51+
// intent.getStringExtra("call_sid"),
52+
// intent.getStringExtra("call_from"),
53+
// intent.getStringExtra("call_to"),
54+
// true,
55+
// ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND
56+
// );
57+
// context.startActivity(launchIntent);
58+
//// Intent callInviteIntent = new Intent(ACTION_INCOMING_CALL);
59+
//// callInviteIntent.putExtra(INCOMING_CALL_NOTIFICATION_ID, notificationId);
60+
//// LocalBroadcastManager.getInstance(context).sendBroadcast(callInviteIntent);
61+
//// callNotificationManager.createIncomingCallNotification(
62+
//// ctx,
63+
//// intent.getStringExtra("call_sid"),
64+
//// intent.getStringExtra("call_from"),
65+
//// notificationId,
66+
//// launchIntent
67+
//// );
68+
69+
70+
71+
/**
72+
We will start our service and send extra info about
73+
network connections
74+
**/
75+
Bundle extras = intent.getExtras();
76+
Intent serviceIntent = new Intent(context, BackgroundCallTaskService.class);
77+
serviceIntent.putExtras(extras);
78+
context.startService(serviceIntent);
79+
HeadlessJsTaskService.acquireWakeLockNow(context);
80+
}
81+
}
82+
83+
private boolean isAppOnForeground(Context context) {
84+
/**
85+
We need to check if app is in foreground otherwise the app will crash.
86+
http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
87+
**/
88+
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
89+
List<ActivityManager.RunningAppProcessInfo> appProcesses =
90+
activityManager.getRunningAppProcesses();
91+
if (appProcesses == null) {
92+
return false;
93+
}
94+
final String packageName = context.getPackageName();
95+
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
96+
if (appProcess.importance ==
97+
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
98+
appProcess.processName.equals(packageName)) {
99+
return true;
100+
}
101+
}
102+
return false;
103+
}
104+
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.hoxfon.react.RNTwilioVoice;
2+
3+
import android.content.Intent;
4+
import android.os.Bundle;
5+
import android.util.Log;
6+
7+
import com.facebook.react.HeadlessJsTaskService;
8+
import com.facebook.react.bridge.Arguments;
9+
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
10+
11+
import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.TAG;
12+
13+
public class BackgroundCallTaskService extends HeadlessJsTaskService {
14+
@Override
15+
protected HeadlessJsTaskConfig getTaskConfig(Intent intent) {
16+
Bundle extras = intent.getExtras();
17+
Log.d(TAG, "###getTaskConfig"+ extras.toString());
18+
if (extras != null) {
19+
return new HeadlessJsTaskConfig(
20+
"BackgroundCallTaskService",
21+
Arguments.fromBundle(extras),
22+
5000, // timeout for the task
23+
false // optional: defines whether or not the task is allowed in foreground. Default is false
24+
);
25+
}
26+
return null;
27+
}
28+
}

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

+11-8
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ public Class getMainActivityClass(ReactApplicationContext context) {
8686

8787
public Intent getLaunchIntent(ReactApplicationContext context,
8888
int notificationId,
89-
CallInvite callInvite,
89+
String callInviteSid,
90+
String callInviteFrom,
91+
String callInviteTo,
9092
Boolean shouldStartNewTask,
9193
int appImportance
9294
) {
@@ -107,14 +109,15 @@ public Intent getLaunchIntent(ReactApplicationContext context,
107109
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
108110
);
109111

110-
if (callInvite != null) {
111-
launchIntent.putExtra(INCOMING_CALL_INVITE, callInvite);
112-
}
112+
launchIntent.putExtra("callSid", callInviteSid);
113+
launchIntent.putExtra("callFrom", callInviteFrom);
114+
launchIntent.putExtra("callTo", callInviteTo);
113115
return launchIntent;
114116
}
115117

116118
public void createIncomingCallNotification(ReactApplicationContext context,
117-
CallInvite callInvite,
119+
String callInviteSid,
120+
String callInviteFrom,
118121
int notificationId,
119122
Intent launchIntent)
120123
{
@@ -131,7 +134,7 @@ public void createIncomingCallNotification(ReactApplicationContext context,
131134
*/
132135
Bundle extras = new Bundle();
133136
extras.putInt(INCOMING_CALL_NOTIFICATION_ID, notificationId);
134-
extras.putString(CALL_SID_KEY, callInvite.getCallSid());
137+
extras.putString(CALL_SID_KEY, callInviteSid);
135138
extras.putString(NOTIFICATION_TYPE, ACTION_INCOMING_CALL);
136139
/*
137140
* Create the notification shown in the notification drawer
@@ -145,7 +148,7 @@ public void createIncomingCallNotification(ReactApplicationContext context,
145148
.setCategory(NotificationCompat.CATEGORY_CALL)
146149
.setSmallIcon(R.drawable.ic_call_white_24dp)
147150
.setContentTitle("Incoming call")
148-
.setContentText(callInvite.getFrom() + " is calling")
151+
.setContentText(callInviteFrom + " is calling")
149152
.setOngoing(true)
150153
.setAutoCancel(true)
151154
.setExtras(extras)
@@ -180,7 +183,7 @@ public void createIncomingCallNotification(ReactApplicationContext context,
180183
notificationBuilder.addAction(R.drawable.ic_call_white_24dp, "ANSWER", pendingAnswerIntent);
181184

182185
notificationManager.notify(notificationId, notificationBuilder.build());
183-
TwilioVoiceModule.callNotificationMap.put(INCOMING_NOTIFICATION_PREFIX+callInvite.getCallSid(), notificationId);
186+
TwilioVoiceModule.callNotificationMap.put(INCOMING_NOTIFICATION_PREFIX+callInviteSid, notificationId);
184187
}
185188

186189
public void initCallNotificationsChannel(NotificationManager notificationManager) {

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

+4-5
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,7 @@ private void handleIncomingCallIntent(Intent intent) {
461461
if (BuildConfig.DEBUG) {
462462
Log.d(TAG, "handleIncomingCallIntent");
463463
}
464-
activeCallInvite = intent.getParcelableExtra(INCOMING_CALL_INVITE);
465-
if (activeCallInvite != null) {
464+
if (intent != null) {
466465
callAccepted = false;
467466
SoundPoolManager.getInstance(getReactApplicationContext()).playRinging();
468467

@@ -479,9 +478,9 @@ private void handleIncomingCallIntent(Intent intent) {
479478
appImportance == RunningAppProcessInfo.IMPORTANCE_SERVICE) {
480479

481480
WritableMap params = Arguments.createMap();
482-
params.putString("call_sid", activeCallInvite.getCallSid());
483-
params.putString("call_from", activeCallInvite.getFrom());
484-
params.putString("call_to", activeCallInvite.getTo()); // TODO check if needed
481+
params.putString("call_sid", intent.getStringExtra("callSid"));
482+
params.putString("call_from", intent.getStringExtra("callFrom"));
483+
params.putString("call_to", intent.getStringExtra("callTo"));
485484
eventManager.sendEvent(EVENT_DEVICE_DID_RECEIVE_INCOMING, params);
486485
}
487486
} else {

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

+66-28
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.app.ActivityManager;
44
import android.content.Intent;
5+
import android.os.Bundle;
56
import android.os.Handler;
67
import android.os.Looper;
78
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@@ -60,7 +61,7 @@ public void onNewToken(String token) {
6061
@Override
6162
public void onMessageReceived(RemoteMessage remoteMessage) {
6263
if (BuildConfig.DEBUG) {
63-
Log.d(TAG, "Bundle data: " + remoteMessage.getData());
64+
Log.d(TAG, "VoiceFirebaseMessagingService onMessageReceived: " + remoteMessage.getMessageType());
6465
}
6566

6667
// Check if message contains a data payload.
@@ -74,7 +75,6 @@ public void onMessageReceived(RemoteMessage remoteMessage) {
7475
boolean valid = Voice.handleMessage(data, new MessageListener() {
7576
@Override
7677
public void onCallInvite(final CallInvite callInvite) {
77-
7878
// We need to run this on the main thread, as the React code assumes that is true.
7979
// Namely, DevServerHelper constructs a Handler() without a Looper, which triggers:
8080
// "Can't create handler inside thread that has not called Looper.prepare()"
@@ -93,7 +93,9 @@ public void run() {
9393
Intent launchIntent = callNotificationManager.getLaunchIntent(
9494
(ReactApplicationContext)context,
9595
notificationId,
96-
callInvite,
96+
callInvite.getCallSid(),
97+
callInvite.getFrom(),
98+
callInvite.getTo(),
9799
false,
98100
appImportance
99101
);
@@ -106,28 +108,53 @@ public void run() {
106108
intent.putExtra(INCOMING_CALL_INVITE, callInvite);
107109
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
108110
} else {
109-
// Otherwise wait for construction, then handle the incoming call
110-
mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
111-
public void onReactContextInitialized(ReactContext context) {
112-
int appImportance = callNotificationManager.getApplicationImportance((ReactApplicationContext)context);
113-
if (BuildConfig.DEBUG) {
114-
Log.d(TAG, "CONTEXT not present appImportance = " + appImportance);
115-
}
116-
Intent launchIntent = callNotificationManager.getLaunchIntent((ReactApplicationContext)context, notificationId, callInvite, true, appImportance);
117-
context.startActivity(launchIntent);
118-
Intent intent = new Intent(ACTION_INCOMING_CALL);
119-
intent.putExtra(INCOMING_CALL_NOTIFICATION_ID, notificationId);
120-
intent.putExtra(INCOMING_CALL_INVITE, callInvite);
121-
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
122-
callNotificationManager.createIncomingCallNotification(
123-
(ReactApplicationContext) context, callInvite, notificationId,
124-
launchIntent);
125-
}
126-
});
127-
if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
128-
// Construct it in the background
129-
mReactInstanceManager.createReactContextInBackground();
130-
}
111+
Intent callKeepIntent = new Intent();
112+
callKeepIntent.setAction("com.hoxfon.HoxFon.DEV.debug.BACKGROUND_CALL");
113+
callKeepIntent.setPackage("com.hoxfon.HoxFon.DEV.debug");
114+
Bundle bundle = new Bundle();
115+
bundle.putString("call_state", "PENDING");
116+
bundle.putString("call_sid", callInvite.getCallSid());
117+
bundle.putString("call_from", callInvite.getFrom());
118+
bundle.putString("call_to", callInvite.getTo());
119+
callKeepIntent.putExtras(bundle);
120+
Log.d(TAG, "BACKGROUND onCallInvite, callKeepIntent "+ callKeepIntent);
121+
122+
sendBroadcast(callKeepIntent);
123+
124+
// // Otherwise wait for construction, then handle the incoming call
125+
// mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
126+
// public void onReactContextInitialized(ReactContext context) {
127+
// int appImportance = callNotificationManager.getApplicationImportance((ReactApplicationContext)context);
128+
// if (BuildConfig.DEBUG) {
129+
// Log.d(TAG, "CONTEXT not present appImportance = " + appImportance);
130+
// }
131+
// Intent launchIntent = callNotificationManager.getLaunchIntent(
132+
// (ReactApplicationContext)context,
133+
// notificationId,
134+
// callInvite.getCallSid(),
135+
// callInvite.getFrom(),
136+
// callInvite.getTo(),
137+
// true,
138+
// appImportance
139+
// );
140+
// context.startActivity(launchIntent);
141+
// Intent intent = new Intent(ACTION_INCOMING_CALL);
142+
// intent.putExtra(INCOMING_CALL_NOTIFICATION_ID, notificationId);
143+
// intent.putExtra(INCOMING_CALL_INVITE, callInvite);
144+
// LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
145+
// callNotificationManager.createIncomingCallNotification(
146+
// (ReactApplicationContext) context,
147+
// callInvite.getCallSid(),
148+
// callInvite.getFrom(),
149+
// notificationId,
150+
// launchIntent
151+
// );
152+
// }
153+
// });
154+
// if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
155+
// // Construct it in the background
156+
// mReactInstanceManager.createReactContextInBackground();
157+
// }
131158
}
132159
}
133160
});
@@ -160,8 +187,19 @@ public void run() {
160187
*/
161188
private void sendCancelledCallInviteToActivity(CancelledCallInvite cancelledCallInvite) {
162189
SoundPoolManager.getInstance((this)).stopRinging();
163-
Intent intent = new Intent(ACTION_CANCEL_CALL_INVITE);
164-
intent.putExtra(CANCELLED_CALL_INVITE, cancelledCallInvite);
165-
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
190+
// Intent intent = new Intent(ACTION_CANCEL_CALL_INVITE);
191+
// intent.putExtra(CANCELLED_CALL_INVITE, cancelledCallInvite);
192+
// LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
193+
194+
Intent callKeepIntent = new Intent();
195+
callKeepIntent.setAction("com.hoxfon.react.RNTwilioVoice.BACKGROUND_CALL");
196+
callKeepIntent.setPackage("com.hoxfon.react.RNTwilioVoice");
197+
Bundle bundle = new Bundle();
198+
bundle.putString("call_state", "CANCELLED");
199+
bundle.putString("call_sid", cancelledCallInvite.getCallSid());
200+
bundle.putString("call_from", cancelledCallInvite.getFrom());
201+
bundle.putString("call_to", cancelledCallInvite.getTo());
202+
callKeepIntent.putExtras(bundle);
203+
sendBroadcast(callKeepIntent);
166204
}
167205
}

0 commit comments

Comments
 (0)