@nativetalkcommunications/react-native-call-sdk 0.1.0 → 0.1.1

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.
Files changed (2) hide show
  1. package/README.md +128 -224
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @nativetalkcommunications/react-native-call-sdk
2
2
 
3
- > Plug-and-play SIP / VoIP calling for React Native, powered by [Linphone](https://www.linphone.org/).
3
+ > Plug-and-play SIP / VoIP calling for React Native.
4
4
  >
5
5
  > Drop-in `<CallProvider>`, a `useCall()` hook, optional UI screens — and a
6
6
  > native Android + iOS layer that handles backgrounding, foreground services,
@@ -13,7 +13,6 @@
13
13
  | Feature | Notes |
14
14
  |---|---|
15
15
  | **Plug-and-play** | One provider, one hook. No coupling to your auth, navigation, or HTTP client. |
16
- | **Cross-platform** | Android (Linphone SDK 5.x) and iOS (Linphone 5.x + CallKit-ready). |
17
16
  | **Backgrounded calls** | Android foreground service keeps the registration warm. iOS supports VoIP push. |
18
17
  | **Bundled UI** | Optional `<Dialer />`, `<IncomingCallView />`, `<OutgoingCallView />`. Use them or roll your own. |
19
18
  | **Typed** | First-class TypeScript types throughout. |
@@ -26,7 +25,6 @@
26
25
  - React Native ≥ 0.73
27
26
  - iOS ≥ 13.0
28
27
  - Android `minSdkVersion` ≥ 24 (Android 7.0)
29
- - Linphone SDK 5.4.x (Android pulled automatically via Maven; iOS xcframeworks downloaded automatically on first `pod install`)
30
28
  - **React Native < 0.82:** set `newArchEnabled=false` in `android/gradle.properties`. React Native ≥ 0.82 runs New Architecture by default and the SDK works via the interop layer — the flag is not needed.
31
29
 
32
30
  ---
@@ -67,12 +65,6 @@ If your app uses Expo, the config plugin handles all native configuration automa
67
65
  npx expo prebuild
68
66
  ```
69
67
 
70
- This automatically configures:
71
- - **Android** — adds the Linphone Maven repository to `android/build.gradle`
72
- - **iOS** — adds `NSMicrophoneUsageDescription` and `UIBackgroundModes` to `Info.plist`, and adds the `pod 'linphonesw'` line to the `Podfile`
73
-
74
- Prebuild also runs `pod install` automatically. On the first run, the linphonesw pod downloads the Linphone xcframeworks (~90 seconds, one-time per machine). No SPM step, no manual setup.
75
-
76
68
  ---
77
69
 
78
70
  ### Installing from a local path (development only)
@@ -161,226 +153,153 @@ Same as the npm install path — the plugin configures Android and iOS automatic
161
153
 
162
154
  ---
163
155
 
164
- ## React Native CLI setup
165
-
166
- If you are **not** using Expo, follow the Android and iOS setup sections below manually.
167
-
168
- ### Local installs only — update Metro config
169
-
170
- **Skip this step for published npm installs.** If installing from a local path (e.g. `"file:../nativetalk-call-sdk"`), merge the following into your `metro.config.js`. If you already have a `watchFolders`, `extraNodeModules`, or `nodeModulesPaths` config, add the SDK entries to your existing arrays/objects rather than replacing them.
171
-
172
- ```js
173
- const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
174
- const path = require('path');
175
-
176
- const sdkPath = path.resolve(__dirname, '../nativetalk-call-sdk'); // adjust path as needed
177
-
178
- const sdkConfig = {
179
- watchFolders: [sdkPath],
180
- resolver: {
181
- unstable_enableSymlinks: true,
182
- extraNodeModules: {
183
- '@nativetalkcommunications/react-native-call-sdk': sdkPath,
184
- 'react': path.resolve(__dirname, 'node_modules/react'),
185
- 'react-native': path.resolve(__dirname, 'node_modules/react-native'),
186
- },
187
- nodeModulesPaths: [
188
- path.resolve(__dirname, 'node_modules'),
189
- path.resolve(sdkPath, 'node_modules'),
190
- ],
191
- },
192
- };
193
-
194
- module.exports = mergeConfig(getDefaultConfig(__dirname), sdkConfig);
195
- ```
196
-
197
- > **If your metro.config.js already calls `mergeConfig`**, pass `sdkConfig` as an additional argument: `mergeConfig(getDefaultConfig(__dirname), yourExistingConfig, sdkConfig)`.
198
-
199
- ### Local installs only — remove duplicate react/react-native
200
-
201
- **Skip this step for published npm installs.** Check if duplicates exist and delete them:
202
-
203
- ```bash
204
- ls ../nativetalk-call-sdk/node_modules | grep react # check first
205
- rm -rf ../nativetalk-call-sdk/node_modules/react
206
- rm -rf ../nativetalk-call-sdk/node_modules/react-native
207
- ```
208
-
209
- ---
210
-
211
- ## Android setup
212
-
213
- ### 1. Add the Linphone Maven repository
214
-
215
- The Linphone SDK is not published to Maven Central. You need to add their repository to `android/settings.gradle`.
156
+ ## Quick start
216
157
 
217
- **If your `settings.gradle` already has a `dependencyResolutionManagement` block**, add the Linphone `maven { }` entry inside the existing `repositories { }` block.
158
+ ```tsx
159
+ import React, { useState } from 'react';
160
+ import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert } from 'react-native';
161
+ import { CallProvider, useCall } from '@nativetalkcommunications/react-native-call-sdk';
162
+ import { Dialer } from '@nativetalkcommunications/react-native-call-sdk/ui';
218
163
 
219
- **If your `settings.gradle` does not have a `dependencyResolutionManagement` block** (common in fresh RN 0.73+ projects), add the entire block at the bottom of the file:
164
+ function LoginScreen({ onLogin }) {
165
+ const [username, setUsername] = useState('100');
166
+ const [password, setPassword] = useState('secret');
167
+ const [domain, setDomain] = useState('pbx.example.com');
168
+ const [transport, setTransport] = useState('tcp');
220
169
 
221
- ```groovy
222
- // android/settings.gradle add at the bottom
223
- dependencyResolutionManagement {
224
- repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
225
- repositories {
226
- google()
227
- mavenCentral()
228
- maven { url "https://www.jitpack.io" }
229
- maven {
230
- name = "linphone.org maven repository"
231
- url = uri("https://download.linphone.org/maven_repository")
232
- content {
233
- includeGroup("org.linphone")
234
- }
235
- }
170
+ const handleLogin = () => {
171
+ if (!username || !password || !domain) {
172
+ Alert.alert('Error', 'Please fill in all fields');
173
+ return;
236
174
  }
237
- }
238
- ```
239
-
240
- > **Important:** `repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)` means only repositories listed in this block are used — adding repos elsewhere (e.g. `android/build.gradle`) will be silently ignored. Make sure `google()` and `mavenCentral()` are included here too.
241
-
242
- Without the Linphone repo your build will fail with:
243
- ```
244
- Could not find org.linphone:linphone-sdk-android:5.4.x.
245
- ```
246
-
247
- > **Wrong URL**: The older Linphone URL (`linphone.org/maven/repository`) is dead. Use `download.linphone.org/maven_repository` as shown above.
248
-
249
- ### 2. Disable New Architecture
250
-
251
- The SDK uses the Old Architecture (NativeModules/NativeEventEmitter) bridge. Open `android/gradle.properties` and set:
252
-
253
- ```properties
254
- newArchEnabled=false
255
- ```
256
-
257
- If you previously had this set to `true`, you must do a clean reinstall:
258
-
259
- ```bash
260
- # Uninstall the old APK from the device first
261
- adb uninstall com.yourapp
262
-
263
- # Then full clean rebuild
264
- cd android && ./gradlew clean && cd ..
265
- npx react-native run-android
266
- ```
267
-
268
- Without the clean uninstall, the old New Architecture binary might remain on-device and could crash with:
269
- ```
270
- PlatformConstants could not be found. Verify that it is available as a TurboModule.
271
- ```
272
-
273
- ### 3. Autolink
274
-
275
- No `MainApplication` edits needed — the SDK autolinks.
276
-
277
- ### 4. Runtime permissions
175
+ onLogin({ username, password, domain, transport });
176
+ };
278
177
 
279
- `RECORD_AUDIO` must be granted before the first call. The provider handles this automatically when `requestMicPermission={true}` (the default). To request it manually:
280
-
281
- ```ts
282
- import { CallEngine } from '@nativetalkcommunications/react-native-call-sdk';
283
- await CallEngine.requestMicPermission(); // Android only, no-op on iOS
284
- ```
285
-
286
- ### 5. Inbound calls — use a real device for testing
287
-
288
- Inbound calls do not work on the Android emulator. The emulator is behind a nested NAT (`10.0.2.15` is not reachable from outside). The SIP server cannot route an INVITE back to the emulator's contact address, so the caller gets "number does not exist" and Linphone never sees the INVITE.
289
-
290
- Outbound calls, registration, and all other features work fine on the emulator.
291
-
292
- **Test inbound calls on a real Android device.**
293
-
294
- ---
295
-
296
- ## iOS setup
297
-
298
- ### 1. Declare linphonesw in your Podfile
299
-
300
- The SDK bundles a self-contained `linphonesw-pod` inside the npm package. Add one line to your `ios/Podfile` inside the target block:
301
-
302
- ```ruby
303
- target 'YourApp' do
304
- config = use_native_modules!
305
-
306
- pod 'linphonesw', :path => '../node_modules/@nativetalkcommunications/react-native-call-sdk/linphonesw-pod'
307
-
308
- # ... rest of Podfile
309
- end
310
- ```
311
-
312
- Then run:
313
-
314
- ```bash
315
- cd ios && pod install
316
- ```
317
-
318
- On the first install, the pod automatically downloads the Linphone xcframeworks (~90 seconds). This is a one-time operation — CocoaPods caches the result so subsequent installs are instant.
319
-
320
- > **No SPM step required.** The old workflow of adding the Linphone Swift Package in Xcode is no longer needed.
321
-
322
- ### 3. Info.plist
323
-
324
- Add to `ios/YourApp/Info.plist`:
325
-
326
- ```xml
327
- <key>NSMicrophoneUsageDescription</key>
328
- <string>Microphone access is required for calls.</string>
329
-
330
- <key>UIBackgroundModes</key>
331
- <array>
332
- <string>audio</string>
333
- <string>voip</string>
334
- </array>
335
- ```
336
-
337
- Without `NSMicrophoneUsageDescription` your app will crash when Linphone requests the mic. Without `UIBackgroundModes`, iOS will kill the SIP connection when your app is backgrounded.
338
-
339
- ### 4. Xcode capabilities
340
-
341
- In Xcode → your target → **Signing & Capabilities**:
342
-
343
- - Add **Background Modes** → tick **Audio, AirPlay and Picture in Picture** and **Voice over IP**
344
-
345
- This mirrors the `UIBackgroundModes` in Info.plist — both are required.
346
-
347
- ### 5. Simulator vs real device
348
-
349
- Registration and foreground calls work on the iOS Simulator. What does **not** work on the simulator is PushKit — VoIP push tokens are never delivered to simulators, so background/killed-app inbound calls won't work there. For testing push-driven inbound calls, use a real iPhone.
178
+ return (
179
+ <View style={styles.loginContainer}>
180
+ <Text style={styles.title}>SIP Credentials</Text>
181
+ <TextInput
182
+ style={styles.input}
183
+ placeholder="Username"
184
+ value={username}
185
+ onChangeText={setUsername}
186
+ />
187
+ <TextInput
188
+ style={styles.input}
189
+ placeholder="Password"
190
+ value={password}
191
+ onChangeText={setPassword}
192
+ secureTextEntry
193
+ />
194
+ <TextInput
195
+ style={styles.input}
196
+ placeholder="Domain"
197
+ value={domain}
198
+ onChangeText={setDomain}
199
+ />
200
+ <TextInput
201
+ style={styles.input}
202
+ placeholder="Transport (tcp/udp)"
203
+ value={transport}
204
+ onChangeText={setTransport}
205
+ />
206
+ <TouchableOpacity style={styles.button} onPress={handleLogin}>
207
+ <Text style={styles.buttonText}>Login</Text>
208
+ </TouchableOpacity>
209
+ </View>
210
+ );
211
+ }
350
212
 
351
- ### 6. CallKit + VoIP push (for background/killed-app incoming calls)
213
+ function DialerWithSignout({ onLogout }) {
214
+ const { isRegistered } = useCall();
352
215
 
353
- Without VoIP push, inbound calls only arrive when the SIP socket is already open (app foregrounded). For reliable incoming calls when the app is backgrounded or killed, you need CallKit + PushKit. See [docs/push-notifications.md](docs/push-notifications.md) for the copy-pasteable AppDelegate template.
216
+ return (
217
+ <View style={styles.dialerContainer}>
218
+ {isRegistered && (
219
+ <TouchableOpacity style={styles.signoutButton} onPress={onLogout}>
220
+ <Text style={styles.signoutText}>Sign Out</Text>
221
+ </TouchableOpacity>
222
+ )}
223
+ <Dialer />
224
+ </View>
225
+ );
226
+ }
354
227
 
355
- ---
228
+ export default function App() {
229
+ const [config, setConfig] = useState(null);
356
230
 
357
- ## Quick start
231
+ const handleLogin = (credentials) => {
232
+ setConfig(credentials);
233
+ };
358
234
 
359
- ```tsx
360
- import React, { useState } from 'react';
361
- import { Alert } from 'react-native';
362
- import { CallProvider, useCall } from '@nativetalkcommunications/react-native-call-sdk';
363
- import { Dialer } from '@nativetalkcommunications/react-native-call-sdk/ui';
235
+ const handleLogout = () => {
236
+ setConfig(null);
237
+ };
364
238
 
365
- const sip = {
366
- username: '100',
367
- password: 'secret',
368
- domain: 'yourcompany.nativetalk.io', // must be a *.nativetalk.io domain
369
- transport: 'tcp',
370
- };
239
+ if (!config) {
240
+ return <LoginScreen onLogin={handleLogin} />;
241
+ }
371
242
 
372
- export default function App() {
373
243
  return (
374
244
  <CallProvider
375
- config={sip}
245
+ config={config}
376
246
  onIncomingCall={(info) => console.log('Incoming from', info.phone)}
377
247
  onRegistrationStateChanged={(r) => console.log('SIP:', r.state)}
378
248
  onError={(e) => Alert.alert('SDK Error', e.message)}
379
249
  >
380
- <Dialer />
250
+ <DialerWithSignout onLogout={handleLogout} />
381
251
  </CallProvider>
382
252
  );
383
253
  }
254
+
255
+ const styles = StyleSheet.create({
256
+ loginContainer: {
257
+ flex: 1,
258
+ padding: 16,
259
+ justifyContent: 'center',
260
+ },
261
+ dialerContainer: {
262
+ flex: 1,
263
+ },
264
+ title: {
265
+ fontSize: 24,
266
+ fontWeight: 'bold',
267
+ marginBottom: 24,
268
+ textAlign: 'center',
269
+ },
270
+ input: {
271
+ backgroundColor: '#fff',
272
+ borderRadius: 8,
273
+ paddingHorizontal: 12,
274
+ paddingVertical: 10,
275
+ marginBottom: 12,
276
+ borderWidth: 1,
277
+ borderColor: '#ddd',
278
+ },
279
+ button: {
280
+ backgroundColor: '#2196F3',
281
+ paddingVertical: 12,
282
+ borderRadius: 8,
283
+ alignItems: 'center',
284
+ },
285
+ buttonText: {
286
+ color: '#fff',
287
+ fontSize: 16,
288
+ fontWeight: '600',
289
+ },
290
+ signoutButton: {
291
+ backgroundColor: '#F44336',
292
+ paddingHorizontal: 16,
293
+ paddingVertical: 8,
294
+ borderRadius: 6,
295
+ alignItems: 'center',
296
+ margin: 12,
297
+ },
298
+ signoutText: {
299
+ color: '#fff',
300
+ fontSize: 14,
301
+ },
302
+ });
384
303
  ```
385
304
 
386
305
  **Error handling** — all SDK errors are surfaced through `onError`. The callback receives `{ code: string, message: string }`. Common codes:
@@ -417,27 +336,12 @@ function CallControls() {
417
336
 
418
337
  ---
419
338
 
420
- ## Common errors
421
-
422
- | Error | Cause | Fix |
423
- |---|---|---|
424
- | `Could not find org.linphone:linphone-sdk-android` | Wrong or missing Maven repo | Add `download.linphone.org/maven_repository` to `android/build.gradle` in the `allprojects { repositories { } }` block |
425
- | `PlatformConstants could not be found` | New Architecture enabled but SDK uses Old Arch | Set `newArchEnabled=false` in `gradle.properties`, uninstall APK, clean rebuild |
426
- | `TurboModuleRegistry … was not found` | Duplicate react-native in SDK node_modules | Delete `nativetalk-call-sdk/node_modules/react` and `.../react-native` |
427
- | `Unable to load script` | Metro not running after clean build | Start Metro separately (`npx react-native start`), then run the app |
428
- | `No podspec found for linphonesw` | Podfile missing the `pod 'linphonesw'` line | Add `pod 'linphonesw', :path => '../node_modules/@nativetalkcommunications/react-native-call-sdk/linphonesw-pod'` to your Podfile |
429
- | `'jni.h' file not found` | Linphone xcframeworks embedded directly in NativetalkCallSdk module | Ensure linphonesw is a separate pod — do not vendor the xcframeworks directly in NativetalkCallSdk |
430
- | Inbound calls not received (Android emulator) | Emulator NAT — SIP server can't reach `10.0.2.15` | Test on a real Android device |
431
- | Inbound calls not received (iOS) | App backgrounded without VoIP push | Wire up CallKit + PushKit; see `docs/push-notifications.md` |
432
-
433
- ---
434
-
435
339
  ## Documentation
436
340
 
437
341
  | Topic | Where |
438
342
  |---|---|
439
343
  | **Android setup deep-dive** — services, channels, manifest, Maven repo | [docs/android-setup.md](docs/android-setup.md) |
440
- | **iOS setup deep-dive** — Linphone SPM, CallKit, PushKit | [docs/ios-setup.md](docs/ios-setup.md) |
344
+ | **iOS setup deep-dive** — CallKit, PushKit | [docs/ios-setup.md](docs/ios-setup.md) |
441
345
  | **Configuration** — every prop on `<CallProvider>` | [docs/configuration.md](docs/configuration.md) |
442
346
  | **API reference** — every export, every type | [docs/api-reference.md](docs/api-reference.md) |
443
347
  | **Bundled UI components** — props, theming, customization | [docs/ui-components.md](docs/ui-components.md) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nativetalkcommunications/react-native-call-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Plug-and-play SIP/VoIP calling SDK for React Native, powered by Linphone. Provides registration, dial, answer, hold, mute, speaker, DTMF, and call logs — plus optional UI components.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -62,7 +62,7 @@
62
62
  ],
63
63
  "repository": {
64
64
  "type": "git",
65
- "url": "https://github.com/Tech4mation/nativetalk-call-sdk.git"
65
+ "url": "git+https://github.com/Tech4mation/nativetalk-call-sdk.git"
66
66
  },
67
67
  "license": "MIT",
68
68
  "peerDependencies": {