6262import static io .wazo .callkeep .RNCallKeepModule .ACTION_ONGOING_CALL ;
6363import static io .wazo .callkeep .RNCallKeepModule .ACTION_UNHOLD_CALL ;
6464import static io .wazo .callkeep .RNCallKeepModule .ACTION_UNMUTE_CALL ;
65+ import static io .wazo .callkeep .RNCallKeepModule .ACTION_CHECK_REACHABILITY ;
6566import static io .wazo .callkeep .RNCallKeepModule .EXTRA_CALLER_NAME ;
6667import static io .wazo .callkeep .RNCallKeepModule .EXTRA_CALL_NUMBER ;
6768import static io .wazo .callkeep .RNCallKeepModule .EXTRA_CALL_UUID ;
7071// @see https://github.com/kbagchiGWC/voice-quickstart-android/blob/9a2aff7fbe0d0a5ae9457b48e9ad408740dfb968/exampleConnectionService/src/main/java/com/twilio/voice/examples/connectionservice/VoiceConnectionService.java
7172@ TargetApi (Build .VERSION_CODES .M )
7273public class VoiceConnectionService extends ConnectionService {
73- private static Boolean isAvailable = false ;
74+ private static Boolean isAvailable ;
75+ private static Boolean isInitialized ;
76+ private static Boolean isReachable ;
77+ private static String notReachableCallUuid ;
78+ private static ConnectionRequest currentConnectionRequest ;
7479 private static String TAG = "RNCK:VoiceConnectionService" ;
7580 public static Map <String , VoiceConnection > currentConnections = new HashMap <>();
7681 public static Boolean hasOutgoingCall = false ;
82+ public static VoiceConnectionService currentConnectionService = null ;
7783
7884 public static Connection getConnection (String connectionId ) {
7985 if (currentConnections .containsKey (connectionId )) {
@@ -85,12 +91,27 @@ public static Connection getConnection(String connectionId) {
8591 public VoiceConnectionService () {
8692 super ();
8793 Log .e (TAG , "Constructor" );
94+ isReachable = false ;
95+ isInitialized = false ;
96+ isAvailable = false ;
97+ currentConnectionRequest = null ;
98+ currentConnectionService = this ;
8899 }
89100
90101 public static void setAvailable (Boolean value ) {
102+ Log .d (TAG , "setAvailable: " + (value ? "true" : "false" ));
103+ if (value ) {
104+ isInitialized = true ;
105+ }
106+
91107 isAvailable = value ;
92108 }
93109
110+ public static void setReachable () {
111+ Log .d (TAG , "setReachable" );
112+ isReachable = true ;
113+ VoiceConnectionService .currentConnectionRequest = null ;
114+ }
94115
95116 public static void deinitConnection (String connectionId ) {
96117 Log .d (TAG , "deinitConnection:" + connectionId );
@@ -116,44 +137,44 @@ public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManage
116137 @ Override
117138 public Connection onCreateOutgoingConnection (PhoneAccountHandle connectionManagerPhoneAccount , ConnectionRequest request ) {
118139 VoiceConnectionService .hasOutgoingCall = true ;
140+ String uuid = UUID .randomUUID ().toString ();
141+
142+ if (!isInitialized && !isReachable ) {
143+ this .notReachableCallUuid = uuid ;
144+ this .currentConnectionRequest = request ;
145+ this .checkReachability ();
146+ }
147+
148+ return this .makeOutgoingCall (request , uuid , false );
149+ }
119150
151+ private Connection makeOutgoingCall (ConnectionRequest request , String uuid , Boolean forceWakeUp ) {
120152 Bundle extras = request .getExtras ();
121153 Connection outgoingCallConnection = null ;
122154 String number = request .getAddress ().getSchemeSpecificPart ();
123155 String extrasNumber = extras .getString (EXTRA_CALL_NUMBER );
124156 String displayName = extras .getString (EXTRA_CALLER_NAME );
125- String uuid = UUID . randomUUID (). toString ( );
157+ Boolean isForeground = VoiceConnectionService . isRunning ( this . getApplicationContext () );
126158
127- Log .d (TAG , "onCreateOutgoingConnection :" + uuid + ", number: " + number );
159+ Log .d (TAG , "makeOutgoingCall :" + uuid + ", number: " + number + ", displayName:" + displayName );
128160
129161 // Wakeup application if needed
130- if (!VoiceConnectionService . isRunning ( this . getApplicationContext ()) ) {
162+ if (!isForeground || forceWakeUp ) {
131163 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 ()) {
164+ this .wakeUpApplication (uuid , number , displayName );
165+ } else if (!this .canMakeOutgoingCall () && isReachable ) {
166+ Log .d (TAG , "onCreateOutgoingConnection: not available" );
144167 return Connection .createFailedConnection (new DisconnectCause (DisconnectCause .LOCAL ));
145168 }
146169
147170 // TODO: Hold all other calls
148- if (extrasNumber != null && extrasNumber .equals (number )) {
149- outgoingCallConnection = createConnection (request );
150- } else {
171+ if (extrasNumber == null || !extrasNumber .equals (number )) {
151172 extras .putString (EXTRA_CALL_UUID , uuid );
152173 extras .putString (EXTRA_CALLER_NAME , displayName );
153174 extras .putString (EXTRA_CALL_NUMBER , number );
154- outgoingCallConnection = createConnection (request );
155175 }
156176
177+ outgoingCallConnection = createConnection (request );
157178 outgoingCallConnection .setDialing ();
158179 outgoingCallConnection .setAudioModeIsVoip (true );
159180 outgoingCallConnection .setCallerDisplayName (displayName , TelecomManager .PRESENTATION_ALLOWED );
@@ -164,15 +185,59 @@ public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManage
164185 sendCallRequestToActivity (ACTION_ONGOING_CALL , extrasMap );
165186 sendCallRequestToActivity (ACTION_AUDIO_SESSION , null );
166187
188+ Log .d (TAG , "onCreateOutgoingConnection: calling" );
189+
167190 return outgoingCallConnection ;
168191 }
169192
193+ private void wakeUpApplication (String uuid , String number , String displayName ) {
194+ Intent headlessIntent = new Intent (
195+ this .getApplicationContext (),
196+ RNCallKeepBackgroundMessagingService .class
197+ );
198+ headlessIntent .putExtra ("callUUID" , uuid );
199+ headlessIntent .putExtra ("name" , displayName );
200+ headlessIntent .putExtra ("handle" , number );
201+ Log .d (TAG , "wakeUpApplication: " + uuid + ", number : " + number + ", displayName:" + displayName );
202+
203+ ComponentName name = this .getApplicationContext ().startService (headlessIntent );
204+ if (name != null ) {
205+ HeadlessJsTaskService .acquireWakeLockNow (this .getApplicationContext ());
206+ }
207+ }
208+
209+ private void wakeUpAfterReachabilityTimeout (ConnectionRequest request ) {
210+ if (this .currentConnectionRequest == null ) {
211+ return ;
212+ }
213+ Log .d (TAG , "checkReachability timeout, force wakeup" );
214+ Bundle extras = request .getExtras ();
215+ String number = request .getAddress ().getSchemeSpecificPart ();
216+ String displayName = extras .getString (EXTRA_CALLER_NAME );
217+ wakeUpApplication (this .notReachableCallUuid , number , displayName );
218+
219+ VoiceConnectionService .currentConnectionRequest = null ;
220+ }
221+
222+ private void checkReachability () {
223+ Log .d (TAG , "checkReachability" );
224+
225+ final VoiceConnectionService instance = this ;
226+ sendCallRequestToActivity (ACTION_CHECK_REACHABILITY , null );
227+
228+ new android .os .Handler ().postDelayed (
229+ new Runnable () {
230+ public void run () {
231+ instance .wakeUpAfterReachabilityTimeout (instance .currentConnectionRequest );
232+ }
233+ }, 2000 );
234+ }
235+
170236 private Boolean canMakeOutgoingCall () {
171237 return isAvailable ;
172238 }
173239
174240 private Connection createConnection (ConnectionRequest request ) {
175-
176241 Bundle extras = request .getExtras ();
177242 HashMap <String , String > extrasMap = this .bundleToMap (extras );
178243 extrasMap .put (EXTRA_CALL_NUMBER , request .getAddress ().toString ());
0 commit comments