Skip to content

Commit 1a40056

Browse files
authored
Merge branch 'cybex-dev:master' into fix-call-direction-when-ringing
2 parents 46a9134 + 470cea6 commit 1a40056

33 files changed

+676
-410
lines changed

.firebaserc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "twilio-voice-web"
4+
}
5+
}

.github/workflows/flutter.yml

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# separate terms of service, privacy policy, and support
44
# documentation.
55

6-
name: Flutter Analyze & Test (main)
6+
name: Flutter analyze, test & deploy example web app
77

88
on:
99
push:
@@ -24,7 +24,7 @@ jobs:
2424
- name: Install Flutter
2525
uses: subosito/flutter-action@v2
2626
with:
27-
flutter-version: '3.7.11'
27+
flutter-version: '3.10.6'
2828
channel: 'stable'
2929
cache: true
3030

@@ -37,4 +37,41 @@ jobs:
3737
run: flutter analyze
3838

3939
- name: Run tests
40-
run: flutter test --coverage
40+
run: flutter test --coverage
41+
42+
deploy-example-web:
43+
runs-on: ubuntu-latest
44+
needs: build
45+
46+
steps:
47+
- uses: actions/checkout@v2
48+
49+
- name: Setup Flutter build environment
50+
uses: subosito/flutter-action@v2
51+
with:
52+
flutter-version: '3.10.6'
53+
channel: 'stable'
54+
cache: true
55+
56+
- run: flutter --version
57+
- run: flutter pub get
58+
- run: flutter config --enable-web
59+
- run: cd ./example; flutter build web --release --target=lib/main.dart --output=build/web
60+
61+
- name: Update service worker
62+
run: cat ./example/service-worker/twilio-sw.js >> ./example/build/web/flutter_service_worker.js
63+
64+
- name: Archive Production Artifact
65+
uses: actions/upload-artifact@master
66+
with:
67+
name: web-build
68+
path: example/build/web
69+
70+
- name: Firebase Deploy
71+
uses: FirebaseExtended/action-hosting-deploy@v0
72+
with:
73+
repoToken: '${{ secrets.GITHUB_TOKEN }}'
74+
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_TWILIO_VOICE_WEB }}'
75+
channelId: live
76+
projectId: twilio-voice-web
77+

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,7 @@ build/
4545

4646
# Lock files
4747
*.lock
48+
49+
*.log
50+
51+
.firebase/

CHANGELOG.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
## Next release
2+
3+
* Fix: [Web] Multiple missed call notifications
4+
* Fix: [Android] `openPhoneAccountsSettings` not always opening on various Android (mainly Samsung) devices
5+
6+
## 0.1.0
7+
28
* Feat: [Android] Turn off the screen when a call is active and the head is against the handset. @solid-software (https://solid.software)
39
* Feat: [macOS] Added support for macOS, based on iOS implementation backed by Twilio Voice Web (twilio-voice.js [v2.4.1-dev-custom](https://github.com/cybex-dev/twilio-voice.js/tree/2.4.1-dev-custom)).
410
* Feat: [Web] Web support with notifications (via Service Worker) with live example at https://twilio-voice-web.web.app @cybex-dev
5-
* Feat: [Android, iOS] Add handset call status: `isMuted()`, `isOnSpeaker()` and `isHolding()` @cybex-dev
11+
* Feat: [Android, iOS, web] Add handset call status: `isMuted()`, `isOnSpeaker()` and `isHolding()` @cybex-dev
612
* Refactor: Hold call signature changed to `holdCall({bool shouldHold = true})` @cybex-dev
713
* Feat: [iOS] Add support for changing callkit icon (future plans to extended this for Flutter assets) @cybex-dev
814
* [twilio_voice_mimp:0.2.5) fix 4 Null Pointer execption Android
915
* [twilio_voice_mimp:0.2.4) add Android DE Local
10-
* [twilio_voice_mimp:0.2.4) add Android IT Local
16+
* [twilio_voice_mimp:0.2.4) add Android IT Local
1117
* [twilio_voice_mimp:0.2.3) Upgrade to Twilio Android SDK 6.1.2 / iOS SDK 6.4.2
1218
* [twilio_voice_mimp:0.2.3) small Bugfix for null pointer Exception
1319
* [twilio_voice_mimp:0.2.2) more Magic is needed with FLAG_MUTABLE (Android 12)
@@ -34,29 +40,44 @@
3440
* Feat: [Android] Add CallingAccount (Phone Account) label & description via `strings.xml`. @cybex-dev
3541
* Feat: [Android] Add Calling Account (Phone Account) icon (using current app icon via `getApplicationInfo().getIcon()`). @cybex-dev
3642
* Fix: request Permissions return result via Flutter future.
43+
* Fix: [Android] Missing platform method channel for `getSid()`
44+
* Fix: [Android] Inconsistent caller/recipient names for inbound calls between ringing & connected states.
45+
* Fix: [Android] Incorrect call direction for incoming calls
46+
* Fix: call ringing event always showing `CallDirection.outgoing`
47+
* Fix: [Android] Updated CallKit incoming/outgoing name parameter resolution
48+
* Fix: [Web] Notification actions working intermittently.
49+
* Fix: [Web] Added suggested service worker integration with CI/CD unifying with `flutter_service_worker.js`, see [here](https://firebase.flutter.dev/docs/messaging/usage/#background-messages) for more info regarding service worker limitations.
50+
* Update: [Web] Remove additional service-worker files
3751

3852
## 0.0.9
53+
3954
* Feat: forwarded callInvite custom parameters to flutter
4055

4156
## 0.0.8
57+
4258
* Renamed callkit logo
4359
* Merge-Android: Fixed null pointer exception for eventSink occurs in mute call. @GKPK
4460

4561
## 0.0.7
62+
4663
* Fixed from param on android
4764

4865
## 0.0.6
66+
4967
* Added android extra call params
5068

5169
## 0.0.5
70+
5271
* Updated Twilio SDK versions
5372
* Added example proguard-rules.pro for android
5473

5574
## 0.0.4
75+
5676
* Fixes deprecation error with Xcode 12.5
5777
* removed "client" from ids
5878

5979
## 0.0.3
80+
6081
* Added missed call notifications
6182
* Updated Android SDK
6283
* Added localization files

README.md

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -163,49 +163,72 @@ See [example](https://github.com/cybex-dev/twilio_voice/blob/master/example/andr
163163

164164
### Web Setup:
165165

166-
There are 2 important files for Twilio incoming/missed call notifications to work:
166+
There are 4 important files for Twilio incoming/missed call notifications to work:
167167

168168
- `notifications.js` is the main file, it handles the notifications and the service worker.
169-
- `twilio-sw.js` is the service worker, it is used to handle the incoming calls.
169+
- `twilio-sw.js` is the service worker _content_ used to work with the default `flutter_service_worker.js` (this can be found in `build/web/flutter_service_worker.js` after calling `flutter build web`). This file's contents are to be copied into the `flutter_service_worker.js` file after you've built your application.
170170

171171
Also, the twilio javascript SDK itself, `twilio.min.js` is needed.
172172

173-
To ensure proper/as intended setup:
173+
### To ensure proper/as intended setup:
174174

175-
1. Get all 3 files (`notifications.js`, `twilio.min.js` and `twilio-sw.js`) from `example/web` folder
176-
2. Copy all 3 into your own project,
177-
3. (optional) Review & change the `notifications.js`, `twilio-sw.js) files to match your needs.
175+
1. Copy files `example/web/notifications.js` and `example/web/twilio.min.js` into your application's `web` folder.
176+
2. This step should be done AFTER you've built your application, every time the `flutter_service_worker.js` changes (this includes hot reloads on your local machine unfortunately)
177+
1. Copy the contents of `example/web/twilio-sw.js` into your `build/web/flutter_service_worker.js` file, **at the end of the file**. See [service-worker](#service-worker) for more information.
178+
179+
Note, these files can be changed to suite your needs - however the core functionality should remain the same: responding to `notificationclick`, `notificationclose`, `message` events and associated sub-functions.
178180

179181
Finally, add the following code to your `index.html` file, **at the end of body tag**:
180182

181183
```html
182184
<body>
185+
<!--Start Twilio Voice impl-->
183186
<!--twilio native js library-->
184187
<script type="text/javascript" src="./twilio.min.js"></script>
185-
<!--twilio native js library-->
186-
<script type="text/javascript" src="./notifications.js"></script>
188+
<!--End Twilio Voice impl-->
187189

188190
<script>
189-
if ('serviceWorker' in navigator) {
190-
window.addEventListener('load', async () => {
191-
await navigator.serviceWorker.register('twilio-sw.js').then(value => {
192-
console.log('Twilio Voice Service worker registered successfully.');
193-
}).catch((error) => {
194-
console.warn('Error registering Twilio Service Worker: ' + error.message + '. This prevents notifications from working natively');
195-
});
196-
});
197-
}
198-
</script>
191+
window.addEventListener('load', function(ev) {
192+
// Download main.dart.js
193+
...
199194
</body>
200195
```
201196
202197
#### Web Considerations
203198
204-
Notice should be given to using `firebase-messaging-sw.js` in addition to `twilio-sw.js` since these may cause conflict in service worker events being handled.
205-
206199
_If you need to debug the service worker, open up Chrome Devtools, go to Application tab, and select Service Workers from the left menu. There you can see the service workers and their status.
207200
To review service worker `notificationclick`, `notificationclose`, `message`, etc events - do this using Chrome Devtools (Sources tab, left panel below 'site code' the service workers are listed)_
208201
202+
##### Service Worker
203+
204+
Unifying the service worker(s) is best done via post-compilation tools or a CI/CD pipeline (suggested).
205+
206+
A snippet of the suggested service worker integration is as follows:
207+
208+
```yaml
209+
#...
210+
- run: cd ./example; flutter build web --release --target=lib/main.dart --output=build/web
211+
212+
- name: Update service worker
213+
run: cat ./example/web/twilio-sw.js >> ./example/build/web/flutter_service_worker.js
214+
#...
215+
```
216+
217+
A complete example could be found in the github workflows `.github/workflows/flutter.yml` file, see [here](https://github.com/cybex-dev/twilio_voice/blob/master/.github/workflows/flutter.yml).
218+
219+
##### Web Notifications
220+
221+
2 types of notifications are shown:
222+
- Incoming call notifications with 2 buttons: `Answer` and `Reject`,
223+
- Missed call notifications with 1 button: `Call back`.
224+
225+
Notifications are presented as **alerts**. These notifications may not always been shown, check:
226+
- if the browser supports notifications,
227+
- if the user has granted permissions to show notifications,
228+
- if the notifications display method / notifications is enabled by the system (e.g. macOS notifications are disabled, or Windows notifications are disabled, etc).
229+
- if there are already notifications shown (https://stackoverflow.com/a/36383155/4628115)
230+
- if system is in 'Do Not Disturb' or 'Focus' mode.
231+
209232
### MacOS Setup:
210233
211234
The plugin is essentially a [WKWebView](https://developer.apple.com/documentation/webkit/wkwebview)
@@ -332,12 +355,23 @@ Caller is usually referred to as `call.from` or `callInvite.from`. This can eith
332355
333356
The following rules are applied to determine the caller/recipient name, which is shown in the call screen and heads-up notification:
334357
335-
- If the caller is empty/not provided, the default caller name is shown e.g. "Unknown Caller", else
336-
- if the caller is a number, the plugin will show the number as is, else
337-
- if the caller is a string, the plugin will interpret the string as follows:
338-
- if the `__TWI_CALLER_NAME` parameter is provided, the plugin will show the value of `__TWI_CALLER_NAME` as is, else
339-
- if the `__TWI_CALLER_ID` parameter is provided, the plugin will search for a registered client with the same id and show the client name, else
340-
- if not found or not provided, the plugin will search for a registered client with the `call.from` value and show the client name, as a last resort
358+
##### Incoming Calls:
359+
360+
`__TWI_CALLER_NAME` -> `resolve(__TWI_CALLER_ID)` -> (phone number) -> `registered client (from)` -> `defaultCaller name` -> `"Unknown Caller"`
361+
362+
363+
##### Outgoing Calls:
364+
365+
`__TWI_RECIPIENT_NAME` -> `resolve(__TWI_RECIPIENT_ID)` -> (phone number) -> `registered client (to)` -> `defaultCaller name` -> `"Unknown Caller"`
366+
367+
**Details explaination:**
368+
369+
- if the call is an CallInvite (incoming), the plugin will interpret the string as follows or if the call is outgoing, the twilio `To` parameter field is used to:
370+
- if the `__TWI_CALLER_NAME` (or `__TWI_RECIPIENT_NAME`) parameter is provided, the plugin will show the value of `__TWI_CALLER_NAME` (or `__TWI_RECIPIENT_NAME`) as is, else
371+
- if the `__TWI_CALLER_ID` (or `__TWI_RECIPIENT_ID`) parameter is provided, the plugin will search for a registered client with the same id and show the client name,
372+
- if the caller (`from` or `to` fields) is empty/not provided, the default caller name is shown e.g. "Unknown Caller", else
373+
- else if the caller (`from` or `to` fields) is a number, the plugin will show the number as is, else
374+
- else the plugin will search for a registered client with the `callInvite.from` (or call.to) value and show the client name, as a last resort
341375
- the default caller name is shown e.g. "Unknown Caller"
342376
343377
*Please note: the same approach applies to both caller and recipient name resolution.*

android/src/main/kotlin/com/twilio/twilio_voice/TwilioVoicePlugin.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
100100
private var isBluetoothOn: Boolean = false
101101
private var isMuted: Boolean = false
102102
private var isHolding: Boolean = false
103-
private var callSid: String? = null
103+
private val callSid: String?
104+
get() = TVConnectionService.getActiveCallHandle()
104105

105106
private var hasStarted = false
106107

@@ -1542,7 +1543,6 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
15421543
}
15431544

15441545
TVBroadcastReceiver.ACTION_ACTIVE_CALL_CHANGED -> {
1545-
callSid = intent.getStringExtra(TVBroadcastReceiver.EXTRA_CALL_HANDLE)
15461546
Log.d(TAG, "handleBroadcastIntent: Active call changed to $callSid")
15471547
}
15481548

@@ -1572,7 +1572,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
15721572
put(key, value)
15731573
}
15741574
}.toString()
1575-
callSid = callHandle
1575+
// callSid = callHandle
15761576
logEvents("", arrayOf("Incoming", from, to, CallDirection.INCOMING.label, params))
15771577
logEvents("", arrayOf("Ringing", from, to, CallDirection.INCOMING.label, params))
15781578
}
@@ -1586,7 +1586,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
15861586
)
15871587
return
15881588
}
1589-
callSid = null
1589+
// callSid = null
15901590
Log.d(TAG, "handleBroadcastIntent: Call ended $callHandle")
15911591
logEvent("", "Call ended")
15921592
}
@@ -1639,7 +1639,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
16391639
put(key, value)
16401640
}
16411641
}.toString()
1642-
callSid = callHandle
1642+
// callSid = callHandle
16431643
logEvents("", arrayOf("Answer", from, to, params))
16441644
}
16451645

@@ -1697,7 +1697,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
16971697
val direction = intent.getIntExtra(TVBroadcastReceiver.EXTRA_CALL_DIRECTION, -1)
16981698
val callDirection = CallDirection.fromId(direction).toString()
16991699

1700-
callSid = callHandle
1700+
// callSid = callHandle
17011701
logEvents("", arrayOf("Ringing", from, to, callDirection))
17021702
}
17031703

@@ -1726,8 +1726,8 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
17261726
return
17271727
}
17281728
val direction = intent.getIntExtra(TVBroadcastReceiver.EXTRA_CALL_DIRECTION, -1)
1729-
val callDirection = CallDirection.fromId(direction).toString()
1730-
callSid = callHandle
1729+
val callDirection = CallDirection.fromId(direction)!!.label
1730+
// callSid = callHandle
17311731
logEvents("", arrayOf("Connected", from, to, callDirection))
17321732
}
17331733

0 commit comments

Comments
 (0)