36
36
import android .telecom .PhoneAccountHandle ;
37
37
import android .telecom .TelecomManager ;
38
38
import android .util .Log ;
39
+ import android .os .SystemClock ;
39
40
40
41
import android .app .ActivityManager ;
41
42
import android .app .ActivityManager .RunningTaskInfo ;
62
63
import static io .wazo .callkeep .RNCallKeepModule .ACTION_ONGOING_CALL ;
63
64
import static io .wazo .callkeep .RNCallKeepModule .ACTION_UNHOLD_CALL ;
64
65
import static io .wazo .callkeep .RNCallKeepModule .ACTION_UNMUTE_CALL ;
66
+ import static io .wazo .callkeep .RNCallKeepModule .ACTION_CHECK_REACHABILITY ;
65
67
import static io .wazo .callkeep .RNCallKeepModule .EXTRA_CALLER_NAME ;
66
68
import static io .wazo .callkeep .RNCallKeepModule .EXTRA_CALL_NUMBER ;
67
69
import static io .wazo .callkeep .RNCallKeepModule .EXTRA_CALL_UUID ;
70
72
// @see https://github.com/kbagchiGWC/voice-quickstart-android/blob/9a2aff7fbe0d0a5ae9457b48e9ad408740dfb968/exampleConnectionService/src/main/java/com/twilio/voice/examples/connectionservice/VoiceConnectionService.java
71
73
@ TargetApi (Build .VERSION_CODES .M )
72
74
public class VoiceConnectionService extends ConnectionService {
73
- private static Boolean isAvailable = false ;
75
+ private static Boolean isAvailable ;
76
+ private static Boolean isInitialized ;
77
+ private static Boolean isReachable ;
78
+ private static Boolean isCheckingReachability ;
79
+ private static String notReachableCallUuid ;
80
+ private static ConnectionRequest currentConnectionRequest ;
74
81
private static String TAG = "RNCK:VoiceConnectionService" ;
75
82
public static Map <String , VoiceConnection > currentConnections = new HashMap <>();
76
83
public static Boolean hasOutgoingCall = false ;
84
+ public static VoiceConnectionService currentConnectionService = null ;
77
85
78
86
public static Connection getConnection (String connectionId ) {
79
87
if (currentConnections .containsKey (connectionId )) {
@@ -85,12 +93,28 @@ public static Connection getConnection(String connectionId) {
85
93
public VoiceConnectionService () {
86
94
super ();
87
95
Log .e (TAG , "Constructor" );
96
+ isReachable = false ;
97
+ isInitialized = false ;
98
+ isAvailable = false ;
99
+ currentConnectionRequest = null ;
100
+ isCheckingReachability = false ;
101
+ currentConnectionService = this ;
88
102
}
89
103
90
104
public static void setAvailable (Boolean value ) {
105
+ Log .d (TAG , "setAvailable: " + (value ? "true" : "false" ));
106
+ if (value ) {
107
+ isInitialized = true ;
108
+ }
109
+
91
110
isAvailable = value ;
92
111
}
93
112
113
+ public static void setReachable () {
114
+ Log .d (TAG , "setReachable" );
115
+ isReachable = true ;
116
+ VoiceConnectionService .currentConnectionRequest = null ;
117
+ }
94
118
95
119
public static void deinitConnection (String connectionId ) {
96
120
Log .d (TAG , "deinitConnection:" + connectionId );
@@ -116,44 +140,44 @@ public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManage
116
140
@ Override
117
141
public Connection onCreateOutgoingConnection (PhoneAccountHandle connectionManagerPhoneAccount , ConnectionRequest request ) {
118
142
VoiceConnectionService .hasOutgoingCall = true ;
143
+ String uuid = UUID .randomUUID ().toString ();
144
+
145
+ if (!isInitialized && !isReachable ) {
146
+ this .notReachableCallUuid = uuid ;
147
+ this .currentConnectionRequest = request ;
148
+ this .checkReachability ();
149
+ }
150
+
151
+ return this .makeOutgoingCall (request , uuid , false );
152
+ }
119
153
154
+ private Connection makeOutgoingCall (ConnectionRequest request , String uuid , Boolean forceWakeUp ) {
120
155
Bundle extras = request .getExtras ();
121
156
Connection outgoingCallConnection = null ;
122
157
String number = request .getAddress ().getSchemeSpecificPart ();
123
158
String extrasNumber = extras .getString (EXTRA_CALL_NUMBER );
124
159
String displayName = extras .getString (EXTRA_CALLER_NAME );
125
- String uuid = UUID . randomUUID (). toString ( );
160
+ Boolean isForeground = VoiceConnectionService . isRunning ( this . getApplicationContext () );
126
161
127
- Log .d (TAG , "onCreateOutgoingConnection :" + uuid + ", number: " + number );
162
+ Log .d (TAG , "makeOutgoingCall :" + uuid + ", number: " + number + ", displayName:" + displayName );
128
163
129
164
// Wakeup application if needed
130
- if (!VoiceConnectionService . isRunning ( this . getApplicationContext ()) ) {
165
+ if (!isForeground || forceWakeUp ) {
131
166
Log .d (TAG , "onCreateOutgoingConnection: Waking up application" );
132
- Intent headlessIntent = new Intent (
133
- this .getApplicationContext (),
134
- RNCallKeepBackgroundMessagingService .class
135
- );
136
- headlessIntent .putExtra ("callUUID" , uuid );
137
- headlessIntent .putExtra ("name" , displayName );
138
- headlessIntent .putExtra ("handle" , number );
139
- ComponentName name = this .getApplicationContext ().startService (headlessIntent );
140
- if (name != null ) {
141
- HeadlessJsTaskService .acquireWakeLockNow (this .getApplicationContext ());
142
- }
143
- } else if (!this .canMakeOutgoingCall ()) {
167
+ this .wakeUpApplication (uuid , number , displayName );
168
+ } else if (!this .canMakeOutgoingCall () && isReachable ) {
169
+ Log .d (TAG , "onCreateOutgoingConnection: not available" );
144
170
return Connection .createFailedConnection (new DisconnectCause (DisconnectCause .LOCAL ));
145
171
}
146
172
147
173
// TODO: Hold all other calls
148
- if (extrasNumber != null && extrasNumber .equals (number )) {
149
- outgoingCallConnection = createConnection (request );
150
- } else {
174
+ if (extrasNumber == null || !extrasNumber .equals (number )) {
151
175
extras .putString (EXTRA_CALL_UUID , uuid );
152
176
extras .putString (EXTRA_CALLER_NAME , displayName );
153
177
extras .putString (EXTRA_CALL_NUMBER , number );
154
- outgoingCallConnection = createConnection (request );
155
178
}
156
179
180
+ outgoingCallConnection = createConnection (request );
157
181
outgoingCallConnection .setDialing ();
158
182
outgoingCallConnection .setAudioModeIsVoip (true );
159
183
outgoingCallConnection .setCallerDisplayName (displayName , TelecomManager .PRESENTATION_ALLOWED );
@@ -164,15 +188,59 @@ public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManage
164
188
sendCallRequestToActivity (ACTION_ONGOING_CALL , extrasMap );
165
189
sendCallRequestToActivity (ACTION_AUDIO_SESSION , null );
166
190
191
+ Log .d (TAG , "onCreateOutgoingConnection: calling" );
192
+
167
193
return outgoingCallConnection ;
168
194
}
169
195
196
+ private void wakeUpApplication (String uuid , String number , String displayName ) {
197
+ Intent headlessIntent = new Intent (
198
+ this .getApplicationContext (),
199
+ RNCallKeepBackgroundMessagingService .class
200
+ );
201
+ headlessIntent .putExtra ("callUUID" , uuid );
202
+ headlessIntent .putExtra ("name" , displayName );
203
+ headlessIntent .putExtra ("handle" , number );
204
+ Log .d (TAG , "wakeUpApplication: " + uuid + ", number : " + number + ", displayName:" + displayName );
205
+
206
+ ComponentName name = this .getApplicationContext ().startService (headlessIntent );
207
+ if (name != null ) {
208
+ HeadlessJsTaskService .acquireWakeLockNow (this .getApplicationContext ());
209
+ }
210
+ }
211
+
212
+ private void wakeUpAfterReachabilityTimeout (ConnectionRequest request ) {
213
+ if (this .currentConnectionRequest == null ) {
214
+ return ;
215
+ }
216
+ Log .d (TAG , "checkReachability timeout, force wakeup" );
217
+ Bundle extras = request .getExtras ();
218
+ String number = request .getAddress ().getSchemeSpecificPart ();
219
+ String displayName = extras .getString (EXTRA_CALLER_NAME );
220
+ wakeUpApplication (this .notReachableCallUuid , number , displayName );
221
+
222
+ VoiceConnectionService .currentConnectionRequest = null ;
223
+ }
224
+
225
+ private void checkReachability () {
226
+ Log .d (TAG , "checkReachability" );
227
+
228
+ final VoiceConnectionService instance = this ;
229
+ sendCallRequestToActivity (ACTION_CHECK_REACHABILITY , null );
230
+
231
+ new android .os .Handler ().postDelayed (
232
+ new Runnable () {
233
+ public void run () {
234
+ instance .wakeUpAfterReachabilityTimeout (instance .currentConnectionRequest );
235
+ }
236
+ }, 2000 );
237
+ }
238
+
170
239
private Boolean canMakeOutgoingCall () {
171
240
return isAvailable ;
172
241
}
173
242
174
243
private Connection createConnection (ConnectionRequest request ) {
175
-
176
244
Bundle extras = request .getExtras ();
177
245
HashMap <String , String > extrasMap = this .bundleToMap (extras );
178
246
extrasMap .put (EXTRA_CALL_NUMBER , request .getAddress ().toString ());
0 commit comments