@capgo/capacitor-stream-call 0.0.42 → 0.0.50

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/README.md CHANGED
@@ -6,136 +6,39 @@
6
6
  <h2><a href="https://capgo.app/consulting/?ref=plugin"> Fix your annoying bug now, Hire a Capacitor expert 💪</a></h2>
7
7
  </div>
8
8
 
9
- Uses the https://getstream.io/ native SDK to implement calling in Capacitor
9
+ A Capacitor plugin that uses the [Stream Video SDK](https://getstream.io/) to enable video calling functionality in your app.
10
10
 
11
- ## Install
11
+ ## Installation
12
12
 
13
13
  ```bash
14
14
  npm install @capgo/capacitor-stream-call
15
15
  npx cap sync
16
16
  ```
17
17
 
18
- ## Android Setup
18
+ ## Configuration
19
19
 
20
- ### MainActivity.java
21
- Modify your `MainActivity.java` to handle incoming calls:
22
-
23
- ```java
24
- @Override
25
- protected void onCreate(Bundle savedInstanceState) {
26
- // Save initial intent for StreamCallPlugin (handles killed-state notification)
27
- ee.forgr.capacitor.streamcall.StreamCallPlugin.saveInitialIntent(getIntent());
28
-
29
- super.onCreate(savedInstanceState);
30
-
31
- // Ensure the activity is visible over the lock screen when launched via full-screen intent
32
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O_MR1) {
33
- setShowWhenLocked(true);
34
- setTurnScreenOn(true);
35
- } else {
36
- getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
37
- }
38
- }
39
-
40
- @Override
41
- protected void onNewIntent(Intent intent) {
42
- super.onNewIntent(intent);
43
- setIntent(intent);
44
- String action = intent.getAction();
45
- if ("io.getstream.video.android.action.ACCEPT_CALL".equals(action)) {
46
- android.app.KeyguardManager km = (android.app.KeyguardManager) getSystemService(KEYGUARD_SERVICE);
47
- if (km != null && km.isKeyguardLocked()) {
48
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
49
- km.requestDismissKeyguard(this, new KeyguardManager.KeyguardDismissCallback() {
50
- @Override
51
- public void onDismissSucceeded() {
52
- forwardAcceptIntent(intent);
53
- }
54
- });
55
- }
56
- } else {
57
- forwardAcceptIntent(intent);
58
- }
59
- }
60
- }
61
-
62
- private void forwardAcceptIntent(Intent intent) {
63
- ee.forgr.capacitor.streamcall.StreamCallPlugin.saveInitialIntent(intent);
64
- PluginHandle pluginHandle = getBridge().getPlugin("StreamCall");
65
- if (pluginHandle != null) {
66
- com.getcapacitor.Plugin pluginInstance = pluginHandle.getInstance();
67
- if (pluginInstance instanceof ee.forgr.capacitor.streamcall.StreamCallPlugin) {
68
- ((ee.forgr.capacitor.streamcall.StreamCallPlugin) pluginInstance).handleAcceptCallIntent(intent);
69
- }
70
- }
71
- }
72
- ```
73
-
74
- ### Application Class
75
- Create or modify your Application class to pre-initialize the plugin:
76
-
77
- ```java
78
- @Override
79
- public void onCreate() {
80
- super.onCreate();
81
-
82
- // Initialize Firebase
83
- com.google.firebase.FirebaseApp.initializeApp(this);
84
-
85
- try {
86
- StreamCallPlugin.preLoadInit(this, this);
87
- } catch (Exception e) {
88
- Log.e("App", "Failed to pre-initialize StreamVideo Plugin", e);
89
- }
90
- }
91
- ```
20
+ ### iOS Setup
92
21
 
93
- ## Setting up Android StreamVideo apikey
94
- 1. Add your apikey to the Android project:
95
- ```
96
- your_app/android/app/src/main/res/values/strings.xml
97
- ```
22
+ #### 1. API Key Configuration
23
+ Add your Stream Video API key to `ios/App/App/Info.plist`:
98
24
 
99
- 2. Add your apikey to the Android project:
100
- ```xml
101
- <string name="CAPACITOR_STREAM_VIDEO_APIKEY">your_api_key</string>
102
- ```
103
-
104
- ## Setting up iOS StreamVideo apikey
105
- 1. Add your apikey to the iOS project:
106
- ```
107
- your_app/ios/App/App/Info.plist
108
- ```
109
-
110
- Add the following to the Info.plist file:
111
25
  ```xml
112
26
  <dict>
113
27
  <key>CAPACITOR_STREAM_VIDEO_APIKEY</key>
114
- <string>n8wv8vjmucdw</string>
28
+ <string>your_api_key_here</string>
115
29
  <!-- other keys -->
116
30
  </dict>
117
31
  ```
118
32
 
119
- ## Native Localization
120
-
121
- ### iOS
33
+ #### 2. Localization (Optional)
34
+ To support multiple languages:
122
35
 
123
- 1. Add `Localizable.strings` and `Localizable.stringsdict` files to your Xcode project if you don't have them:
124
- ```
125
- /App/App/en.lproj/Localizable.strings
126
- /App/App/en.lproj/Localizable.stringsdict
127
- ```
128
-
129
- 2. Add new languages to your project in Xcode:
130
- - Open project settings
131
- - Select your project
132
- - Click "Info" tab
133
- - Under "Localizations" click "+"
134
- - Select the languages you want to add
36
+ 1. Add localization files to your Xcode project:
37
+ - `/App/App/en.lproj/Localizable.strings`
38
+ - `/App/App/en.lproj/Localizable.stringsdict`
135
39
 
136
- 3. Add the translations in your `Localizable.strings`:
137
- ```
138
- // en.lproj/Localizable.strings
40
+ 2. Add translations in `Localizable.strings`:
41
+ ```swift
139
42
  "stream.video.call.incoming" = "Incoming call from %@";
140
43
  "stream.video.call.accept" = "Accept";
141
44
  "stream.video.call.reject" = "Reject";
@@ -144,14 +47,13 @@ Add the following to the Info.plist file:
144
47
  "stream.video.call.reconnecting" = "Reconnecting...";
145
48
  ```
146
49
 
147
- 4. Configure the localization provider in your `AppDelegate.swift`:
50
+ 3. Configure localization in your `AppDelegate.swift`:
148
51
  ```swift
149
52
  import StreamVideo
150
53
 
151
54
  @UIApplicationMain
152
55
  class AppDelegate: UIResponder, UIApplicationDelegate {
153
56
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
154
- // Set localization provider to use your app's bundle
155
57
  Appearance.localizationProvider = { key, table in
156
58
  Bundle.main.localizedString(forKey: key, value: nil, table: table)
157
59
  }
@@ -160,12 +62,62 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
160
62
  }
161
63
  ```
162
64
 
163
- You can find all available localization keys in the [StreamVideo SDK repository](https://github.com/GetStream/stream-video-swift/blob/main/Sources/StreamVideoSwiftUI/Resources/en.lproj/Localizable.strings).
65
+ ### Android Setup
66
+
67
+ #### 1. API Key Configuration
68
+ Add your Stream Video API key to `android/app/src/main/res/values/strings.xml`:
69
+
70
+ ```xml
71
+ <string name="CAPACITOR_STREAM_VIDEO_APIKEY">your_api_key_here</string>
72
+ ```
73
+
74
+ #### 2. MainActivity Configuration
75
+ Modify your `MainActivity.java` to handle incoming calls:
76
+
77
+ ```java
78
+ @Override
79
+ protected void onCreate(Bundle savedInstanceState) {
80
+ super.onCreate(savedInstanceState);
81
+
82
+ // Enable activity to show over lock screen
83
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O_MR1) {
84
+ setShowWhenLocked(true);
85
+ setTurnScreenOn(true);
86
+ } else {
87
+ getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
88
+ }
89
+ }
90
+ ```
91
+
92
+ #### 3. Application Class Configuration
93
+ Create or modify your Application class to initialize the plugin:
164
94
 
165
- ### Android
166
- 1. Create string resources in `/app/src/main/res/values/strings.xml`:
95
+ ```java
96
+ import ee.forgr.capacitor.streamcall.StreamCallPlugin;
97
+
98
+ @Override
99
+ public void onCreate() {
100
+ super.onCreate();
101
+
102
+ // Initialize Firebase
103
+ com.google.firebase.FirebaseApp.initializeApp(this);
104
+
105
+ // Pre-initialize StreamCall plugin
106
+ try {
107
+ StreamCallPlugin.preLoadInit(this, this);
108
+ } catch (Exception e) {
109
+ Log.e("App", "Failed to pre-initialize StreamVideo Plugin", e);
110
+ }
111
+ }
112
+ ```
113
+
114
+ > **Note:** If you don't have an Application class, you need to create one and reference it in your `AndroidManifest.xml` with `android:name=".YourApplicationClass"`.
115
+
116
+ #### 4. Localization (Optional)
117
+ Add string resources for different languages:
118
+
119
+ **Default (`values/strings.xml`):**
167
120
  ```xml
168
- <?xml version="1.0" encoding="utf-8"?>
169
121
  <resources>
170
122
  <string name="stream_video_call_incoming">Incoming call from %1$s</string>
171
123
  <string name="stream_video_call_accept">Accept</string>
@@ -176,9 +128,8 @@ You can find all available localization keys in the [StreamVideo SDK repository]
176
128
  </resources>
177
129
  ```
178
130
 
179
- 2. Add translations for other languages in their respective folders (e.g., `/app/src/main/res/values-fr/strings.xml`):
131
+ **French (`values-fr/strings.xml`):**
180
132
  ```xml
181
- <?xml version="1.0" encoding="utf-8"?>
182
133
  <resources>
183
134
  <string name="stream_video_call_incoming">Appel entrant de %1$s</string>
184
135
  <string name="stream_video_call_accept">Accepter</string>
@@ -189,94 +140,98 @@ You can find all available localization keys in the [StreamVideo SDK repository]
189
140
  </resources>
190
141
  ```
191
142
 
192
- The SDK will automatically use the system language and these translations.
143
+ ## Displaying Caller Information
144
+
145
+ When receiving incoming calls, you can access caller information including name, user ID, and profile image. This information is automatically extracted from the call data and passed through the event system.
146
+
147
+ ### Getting Caller Information
193
148
 
194
- To receive all on Android from lockscreen you need to listen to specific event `incomingCall`:
149
+ The caller information is available in two ways:
195
150
 
196
- Here is one exemple in angular from our demo app:
151
+ **1. Through Call Events**
197
152
 
198
- ```ts
199
- StreamCall.addListener('incomingCall', async (payload: any) => {
200
- console.log('[incomingCall] lock-screen payload', payload);
201
- this.incomingCallId = payload.cid;
202
- this.isLockscreenIncoming = true;
203
- this.cdr.detectChanges();
153
+ The `callEvent` listener provides caller information for incoming calls:
154
+
155
+ ```typescript
156
+ StreamCall.addListener('callEvent', (event) => {
157
+ if (event.state === 'ringing' && event.caller) {
158
+ console.log('Incoming call from:', event.caller.name || event.caller.userId);
159
+ console.log('Caller image:', event.caller.imageURL);
160
+ // Update your UI to show caller information
161
+ showIncomingCallUI(event.caller);
162
+ }
204
163
  });
205
164
  ```
206
- This will allow you to display a custom call screen and then enter or reject the call with :
207
165
 
208
- ```ts
209
- async acceptCall() {
210
- if (!this.incomingCallId) return;
211
-
212
- try {
213
- await StreamCall.acceptCall();
214
- await this.presentToast('Call accepted', 'success');
215
- } catch (error) {
216
- console.error('Failed to accept call:', error);
217
- await this.presentToast('Failed to accept call', 'danger');
218
- }
219
- }
166
+ **2. Through Incoming Call Events (Android lock-screen)**
220
167
 
221
- async rejectCall() {
222
- if (!this.incomingCallId) return;
223
-
224
- try {
225
- await StreamCall.rejectCall();
226
- this.incomingCallId = null;
227
- await this.presentToast('Call rejected', 'success');
228
- } catch (error) {
229
- console.error('Failed to reject call:', error);
230
- await this.presentToast('Failed to reject call', 'danger');
231
- }
168
+ The `incomingCall` listener also includes caller information:
169
+
170
+ ```typescript
171
+ StreamCall.addListener('incomingCall', (payload) => {
172
+ if (payload.caller) {
173
+ console.log('Lock-screen call from:', payload.caller.name || payload.caller.userId);
174
+ // Update your lock-screen UI
175
+ updateLockScreenUI(payload.caller);
232
176
  }
177
+ });
233
178
  ```
234
- This is the only way we found to allow the app to use the same UI when phone is lock for the video call.
235
- This can be done that way only on Android on IOS this part is handle by the OS.
236
179
 
180
+ ### Caller Information Structure
237
181
 
238
- Also, for Android you need to change your main activity like so:
239
- ```java
240
- @Override
241
- protected void onCreate(Bundle savedInstanceState) {
242
- // Ensure the activity is visible over the lock screen when launched via full-screen intent
243
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O_MR1) {
244
- setShowWhenLocked(true);
245
- setTurnScreenOn(true);
246
- } else {
247
- getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
248
- }
182
+ ```typescript
183
+ interface CallMember {
184
+ userId: string; // User ID (always present)
185
+ name?: string; // Display name (optional)
186
+ imageURL?: string; // Profile image URL (optional)
187
+ role?: string; // User role (optional)
249
188
  }
250
189
  ```
251
190
 
252
- Furthermore, you need to edit your Application class like so:
253
- ```java
254
- import ee.forgr.capacitor.streamcall.StreamCallPlugin;
191
+ ### Example Implementation
255
192
 
256
- @Override
257
- public void onCreate() {
258
- super.onCreate();
259
- initializeApp();
260
- }
193
+ Here's how to implement a proper incoming call screen with caller information:
261
194
 
262
- private void initializeApp() {
263
- Log.i(TAG, "Initializing application...");
264
- // Initialize Firebase
265
- com.google.firebase.FirebaseApp.initializeApp(this);
266
- try {
267
- StreamCallPlugin.preLoadInit(this, this);
268
- Log.i(TAG, "StreamVideo Plugin preLoadInit invoked successfully");
269
- } catch (Exception e) {
270
- Log.e(TAG, "Failed to pre-initialize StreamVideo Plugin", e);
195
+ ```typescript
196
+ export class CallService {
197
+ private callerInfo: CallMember | null = null;
198
+
199
+ constructor() {
200
+ this.setupCallListeners();
201
+ }
202
+
203
+ private setupCallListeners() {
204
+ StreamCall.addListener('callEvent', (event) => {
205
+ if (event.state === 'ringing') {
206
+ this.callerInfo = event.caller || null;
207
+ this.showIncomingCallScreen();
208
+ } else if (event.state === 'joined' || event.state === 'left') {
209
+ this.callerInfo = null;
210
+ this.hideIncomingCallScreen();
211
+ }
212
+ });
213
+
214
+ // Android lock-screen support
215
+ if (Capacitor.getPlatform() === 'android') {
216
+ StreamCall.addListener('incomingCall', (payload) => {
217
+ this.callerInfo = payload.caller || null;
218
+ this.showLockScreenIncomingCall();
219
+ });
271
220
  }
272
- Log.i(TAG, "Application initialization completed");
221
+ }
222
+
223
+ private showIncomingCallScreen() {
224
+ const callerName = this.callerInfo?.name || 'Unknown Caller';
225
+ const callerImage = this.callerInfo?.imageURL || 'default-avatar.png';
226
+
227
+ // Update your UI components
228
+ document.getElementById('caller-name').textContent = callerName;
229
+ document.getElementById('caller-image').src = callerImage;
230
+ document.getElementById('incoming-call-screen').style.display = 'block';
231
+ }
273
232
  }
274
233
  ```
275
234
 
276
- > ⚠️ **WARNING**
277
- >
278
- > You may not have the Application class in your project, if so you need to create it.
279
-
280
235
  ## API
281
236
 
282
237
  <docgen-index>
@@ -296,6 +251,7 @@ private void initializeApp() {
296
251
  * [`getCallStatus()`](#getcallstatus)
297
252
  * [`setSpeaker(...)`](#setspeaker)
298
253
  * [`switchCamera(...)`](#switchcamera)
254
+ * [`getCallInfo(...)`](#getcallinfo)
299
255
  * [Interfaces](#interfaces)
300
256
  * [Type Aliases](#type-aliases)
301
257
  * [Enums](#enums)
@@ -533,6 +489,23 @@ Switch camera
533
489
  --------------------
534
490
 
535
491
 
492
+ ### getCallInfo(...)
493
+
494
+ ```typescript
495
+ getCallInfo(options: { callId: string; }) => Promise<CallEvent>
496
+ ```
497
+
498
+ Get detailed information about an active call including caller details
499
+
500
+ | Param | Type | Description |
501
+ | ------------- | -------------------------------- | -------------------------------- |
502
+ | **`options`** | <code>{ callId: string; }</code> | - Options containing the call ID |
503
+
504
+ **Returns:** <code>Promise&lt;<a href="#callevent">CallEvent</a>&gt;</code>
505
+
506
+ --------------------
507
+
508
+
536
509
  ### Interfaces
537
510
 
538
511
 
@@ -567,12 +540,14 @@ Switch camera
567
540
 
568
541
  #### CallEvent
569
542
 
570
- | Prop | Type | Description |
571
- | ------------ | ----------------------------------------------- | -------------------------------------------------------------- |
572
- | **`callId`** | <code>string</code> | ID of the call |
573
- | **`state`** | <code><a href="#callstate">CallState</a></code> | Current state of the call |
574
- | **`userId`** | <code>string</code> | User ID of the participant in the call who triggered the event |
575
- | **`reason`** | <code>string</code> | Reason for the call state change, if applicable |
543
+ | Prop | Type | Description |
544
+ | ------------- | ------------------------------------------------- | -------------------------------------------------------------- |
545
+ | **`callId`** | <code>string</code> | ID of the call |
546
+ | **`state`** | <code><a href="#callstate">CallState</a></code> | Current state of the call |
547
+ | **`userId`** | <code>string</code> | User ID of the participant in the call who triggered the event |
548
+ | **`reason`** | <code>string</code> | Reason for the call state change, if applicable |
549
+ | **`caller`** | <code><a href="#callmember">CallMember</a></code> | Information about the caller (for incoming calls) |
550
+ | **`members`** | <code>CallMember[]</code> | List of call members |
576
551
 
577
552
 
578
553
  #### CallState
@@ -766,12 +741,23 @@ The JSON representation for <a href="#listvalue">`ListValue`</a> is JSON array.
766
741
  | **`sessionId`** | <code>string</code> | the user sesion_id to pin, if not provided, applies to all sessions |
767
742
 
768
743
 
744
+ #### CallMember
745
+
746
+ | Prop | Type | Description |
747
+ | -------------- | ------------------- | ----------------------------- |
748
+ | **`userId`** | <code>string</code> | User ID of the member |
749
+ | **`name`** | <code>string</code> | Display name of the user |
750
+ | **`imageURL`** | <code>string</code> | Profile image URL of the user |
751
+ | **`role`** | <code>string</code> | Role of the user in the call |
752
+
753
+
769
754
  #### IncomingCallPayload
770
755
 
771
- | Prop | Type | Description |
772
- | ---------- | ----------------------- | ---------------------------------------- |
773
- | **`cid`** | <code>string</code> | Full call CID (e.g. default:123) |
774
- | **`type`** | <code>'incoming'</code> | Event type (currently always "incoming") |
756
+ | Prop | Type | Description |
757
+ | ------------ | ------------------------------------------------- | ---------------------------------------- |
758
+ | **`cid`** | <code>string</code> | Full call CID (e.g. default:123) |
759
+ | **`type`** | <code>'incoming'</code> | Event type (currently always "incoming") |
760
+ | **`caller`** | <code><a href="#callmember">CallMember</a></code> | Information about the caller |
775
761
 
776
762
 
777
763
  #### CameraEnabledResponse