@capgo/capacitor-twilio-voice 8.1.0 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/ee/forgr/capacitor_twilio_voice/CapacitorTwilioVoicePlugin.java +69 -14
- package/android/src/main/java/ee/forgr/capacitor_twilio_voice/VoiceCallService.java +30 -0
- package/ios/Sources/CapacitorTwilioVoicePlugin/CapacitorTwilioVoicePlugin.swift +1 -1
- package/package.json +1 -1
package/android/src/main/java/ee/forgr/capacitor_twilio_voice/CapacitorTwilioVoicePlugin.java
CHANGED
|
@@ -75,7 +75,7 @@ import org.json.JSONObject;
|
|
|
75
75
|
)
|
|
76
76
|
public class CapacitorTwilioVoicePlugin extends Plugin {
|
|
77
77
|
|
|
78
|
-
private final String pluginVersion = "8.1.
|
|
78
|
+
private final String pluginVersion = "8.1.2";
|
|
79
79
|
|
|
80
80
|
private static final String TAG = "CapacitorTwilioVoice";
|
|
81
81
|
private static final String PREF_ACCESS_TOKEN = "twilio_access_token";
|
|
@@ -240,6 +240,9 @@ public class CapacitorTwilioVoicePlugin extends Plugin {
|
|
|
240
240
|
// Set instance for Firebase messaging service
|
|
241
241
|
instance = this;
|
|
242
242
|
|
|
243
|
+
// Pre-resolve main activity for notification intents when app is cold-started
|
|
244
|
+
resolveMainActivityClass();
|
|
245
|
+
|
|
243
246
|
// Load stored access token
|
|
244
247
|
SharedPreferences prefs = getSafeContext().getSharedPreferences("CapacitorTwilioVoice", Context.MODE_PRIVATE);
|
|
245
248
|
accessToken = prefs.getString(PREF_ACCESS_TOKEN, null);
|
|
@@ -443,6 +446,51 @@ public class CapacitorTwilioVoicePlugin extends Plugin {
|
|
|
443
446
|
this.mainActivityClass = mainActivityClass;
|
|
444
447
|
}
|
|
445
448
|
|
|
449
|
+
private Class<?> resolveMainActivityClass() {
|
|
450
|
+
if (this.mainActivityClass != null) {
|
|
451
|
+
return this.mainActivityClass;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
try {
|
|
455
|
+
Context context = getSafeContext();
|
|
456
|
+
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
|
457
|
+
if (launchIntent != null && launchIntent.getComponent() != null) {
|
|
458
|
+
this.mainActivityClass = Class.forName(launchIntent.getComponent().getClassName());
|
|
459
|
+
return this.mainActivityClass;
|
|
460
|
+
} else {
|
|
461
|
+
Log.w(TAG, "resolveMainActivityClass: launch intent missing component for package " + context.getPackageName());
|
|
462
|
+
}
|
|
463
|
+
} catch (Exception e) {
|
|
464
|
+
Log.e(TAG, "Failed to resolve main activity class", e);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
private Intent createMainActivityIntent() {
|
|
471
|
+
try {
|
|
472
|
+
Context context = getSafeContext();
|
|
473
|
+
Class<?> activityClass = resolveMainActivityClass();
|
|
474
|
+
if (activityClass != null) {
|
|
475
|
+
return new Intent(context, activityClass);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
|
479
|
+
if (launchIntent != null) {
|
|
480
|
+
Intent intent = new Intent(launchIntent);
|
|
481
|
+
intent.setComponent(launchIntent.getComponent());
|
|
482
|
+
intent.setPackage(context.getPackageName());
|
|
483
|
+
return intent;
|
|
484
|
+
} else {
|
|
485
|
+
Log.w(TAG, "createMainActivityIntent: no launch intent available for package " + context.getPackageName());
|
|
486
|
+
}
|
|
487
|
+
} catch (Exception e) {
|
|
488
|
+
Log.e(TAG, "createMainActivityIntent: failed to build intent for main activity", e);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
|
|
446
494
|
private void initializeNotifications() {
|
|
447
495
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
448
496
|
NotificationChannel channel = new NotificationChannel(
|
|
@@ -832,20 +880,21 @@ public class CapacitorTwilioVoicePlugin extends Plugin {
|
|
|
832
880
|
return;
|
|
833
881
|
}
|
|
834
882
|
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
Intent launchIntent = new Intent(context, mainActivityClass);
|
|
838
|
-
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
|
839
|
-
if (pendingPermissionAction == PendingPermissionAction.ACCEPT_CALL && pendingCallSidForPermission != null) {
|
|
840
|
-
launchIntent.putExtra("AUTO_ACCEPT_CALL", true);
|
|
841
|
-
launchIntent.putExtra(EXTRA_CALL_SID, pendingCallSidForPermission);
|
|
842
|
-
}
|
|
843
|
-
Log.d(TAG, "requestMicrophonePermission: launching activity to request permission");
|
|
844
|
-
context.startActivity(launchIntent);
|
|
845
|
-
} else {
|
|
883
|
+
Intent launchIntent = createMainActivityIntent();
|
|
884
|
+
if (launchIntent == null) {
|
|
846
885
|
Log.w(TAG, "Unable to request microphone permission - no activity available");
|
|
847
886
|
handlePermissionFailure();
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
Context context = getSafeContext();
|
|
891
|
+
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
|
892
|
+
if (pendingPermissionAction == PendingPermissionAction.ACCEPT_CALL && pendingCallSidForPermission != null) {
|
|
893
|
+
launchIntent.putExtra("AUTO_ACCEPT_CALL", true);
|
|
894
|
+
launchIntent.putExtra(EXTRA_CALL_SID, pendingCallSidForPermission);
|
|
848
895
|
}
|
|
896
|
+
Log.d(TAG, "requestMicrophonePermission: launching activity to request permission");
|
|
897
|
+
context.startActivity(launchIntent);
|
|
849
898
|
}
|
|
850
899
|
|
|
851
900
|
private void handleMicPermissionResult(Map<String, Boolean> permissions) {
|
|
@@ -1616,11 +1665,17 @@ public class CapacitorTwilioVoicePlugin extends Plugin {
|
|
|
1616
1665
|
|
|
1617
1666
|
private void showIncomingCallNotification(CallInvite callInvite, String callSid, String callerName) {
|
|
1618
1667
|
try {
|
|
1668
|
+
Intent activityIntent = createMainActivityIntent();
|
|
1669
|
+
if (activityIntent == null) {
|
|
1670
|
+
Log.e(TAG, "Error showing notification: unable to resolve activity intent");
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1619
1674
|
// Create intent for accepting the call
|
|
1620
1675
|
PendingIntent acceptPendingIntent;
|
|
1621
1676
|
if (this.bridge == null) {
|
|
1622
1677
|
// App NOT running - launch new activity
|
|
1623
|
-
Intent acceptIntent = new Intent(
|
|
1678
|
+
Intent acceptIntent = new Intent(activityIntent);
|
|
1624
1679
|
acceptIntent.setAction(ACTION_ACCEPT_CALL);
|
|
1625
1680
|
acceptIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
|
1626
1681
|
acceptIntent.putExtra("AUTO_ACCEPT_CALL", true);
|
|
@@ -1656,7 +1711,7 @@ public class CapacitorTwilioVoicePlugin extends Plugin {
|
|
|
1656
1711
|
);
|
|
1657
1712
|
|
|
1658
1713
|
// Create intent for full screen
|
|
1659
|
-
Intent fullScreenIntent = new Intent(
|
|
1714
|
+
Intent fullScreenIntent = new Intent(activityIntent);
|
|
1660
1715
|
fullScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
1661
1716
|
fullScreenIntent.putExtra("INCOMING_CALL", true);
|
|
1662
1717
|
fullScreenIntent.putExtra(EXTRA_CALL_SID, callSid);
|
|
@@ -134,6 +134,7 @@ public class VoiceCallService extends Service {
|
|
|
134
134
|
|
|
135
135
|
// Clean up audio switch
|
|
136
136
|
if (audioSwitch != null) {
|
|
137
|
+
deactivateAudioSwitch();
|
|
137
138
|
audioSwitch.stop();
|
|
138
139
|
audioSwitch = null;
|
|
139
140
|
}
|
|
@@ -164,6 +165,30 @@ public class VoiceCallService extends Service {
|
|
|
164
165
|
});
|
|
165
166
|
}
|
|
166
167
|
|
|
168
|
+
private void activateAudioSwitch() {
|
|
169
|
+
if (audioSwitch == null) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
audioSwitch.activate();
|
|
175
|
+
} catch (Exception e) {
|
|
176
|
+
Log.e(TAG, "Failed to activate AudioSwitch", e);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private void deactivateAudioSwitch() {
|
|
181
|
+
if (audioSwitch == null) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
audioSwitch.deactivate();
|
|
187
|
+
} catch (Exception e) {
|
|
188
|
+
Log.e(TAG, "Failed to deactivate AudioSwitch", e);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
167
192
|
public void setServiceListener(VoiceCallServiceListener listener) {
|
|
168
193
|
this.serviceListener = listener;
|
|
169
194
|
}
|
|
@@ -250,6 +275,7 @@ public class VoiceCallService extends Service {
|
|
|
250
275
|
boolean speakerEnabled = intent.getBooleanExtra(EXTRA_SPEAKER_ENABLED, false);
|
|
251
276
|
|
|
252
277
|
if (audioSwitch != null) {
|
|
278
|
+
activateAudioSwitch();
|
|
253
279
|
List<AudioDevice> audioDevices = audioSwitch.getAvailableAudioDevices();
|
|
254
280
|
AudioDevice selectedDevice = null;
|
|
255
281
|
|
|
@@ -394,6 +420,8 @@ public class VoiceCallService extends Service {
|
|
|
394
420
|
activeCall = call;
|
|
395
421
|
currentCallSid = call.getSid();
|
|
396
422
|
|
|
423
|
+
activateAudioSwitch();
|
|
424
|
+
|
|
397
425
|
// Update notification to show connected state with actions
|
|
398
426
|
updateOngoingCallNotification();
|
|
399
427
|
|
|
@@ -445,6 +473,8 @@ public class VoiceCallService extends Service {
|
|
|
445
473
|
isCallMuted = false;
|
|
446
474
|
isSpeakerEnabled = false;
|
|
447
475
|
|
|
476
|
+
deactivateAudioSwitch();
|
|
477
|
+
|
|
448
478
|
if (serviceListener != null) {
|
|
449
479
|
serviceListener.onCallDisconnected(call, error);
|
|
450
480
|
}
|
|
@@ -27,7 +27,7 @@ public protocol PushKitEventDelegate: AnyObject {
|
|
|
27
27
|
*/
|
|
28
28
|
@objc(CapacitorTwilioVoicePlugin)
|
|
29
29
|
public class CapacitorTwilioVoicePlugin: CAPPlugin, CAPBridgedPlugin, PushKitEventDelegate {
|
|
30
|
-
private let pluginVersion: String = "8.1.
|
|
30
|
+
private let pluginVersion: String = "8.1.2"
|
|
31
31
|
|
|
32
32
|
public let identifier = "CapacitorTwilioVoicePlugin"
|
|
33
33
|
public let jsName = "CapacitorTwilioVoice"
|