├── .gitignore
├── .metadata
├── CHANGELOG.md
├── LICENSE
├── README.md
├── android
├── .gitignore
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── kotlin
│ └── com
│ └── truecallersdk
│ ├── Constants.kt
│ └── TruecallerSdkPlugin.kt
├── example
├── .gitignore
├── .metadata
├── README.md
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── truecaller_sdk_example
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── Runner-Bridging-Header.h
│ │ └── Runner.entitlements
├── lib
│ ├── customization
│ │ ├── config_options.dart
│ │ ├── main_customization_screen.dart
│ │ ├── oauth_result_screen.dart
│ │ └── result_screen.dart
│ ├── main.dart
│ └── non_tc_screen.dart
├── pubspec.yaml
└── test
│ └── widget_test.dart
├── images
├── main.jpg
├── main_customization_screen.jpg
└── truecaller_logo.png
├── ios
├── .gitignore
├── Assets
│ └── .gitkeep
├── Classes
│ ├── Constants.swift
│ ├── Extensions.swift
│ ├── SwiftTruecallerSdkPlugin.swift
│ ├── TruecallerSdkPlugin.h
│ └── TruecallerSdkPlugin.m
└── truecaller_sdk.podspec
├── lib
├── src
│ ├── scope_options.dart
│ ├── truecaller.dart
│ └── truecaller_callback.dart
└── truecaller_sdk.dart
├── pubspec.yaml
└── test
└── truecaller_sdk_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter/Dart/Pub related
2 | .DS_Store
3 | .dart_tool/
4 | .idea/
5 | .packages
6 | .pub/
7 | build/
8 | pubspec.lock
9 | truecaller_sdk.iml
10 |
11 | # example
12 | **/truecaller_sdk_example.iml
13 | **/.dart_tool
14 | **/.idea
15 | **/build
16 | **/.flutter-plugins
17 | **/.flutter-plugins-dependencies
18 | **/pubspec.lock
19 |
20 |
21 | # Android related
22 | **/android/**/gradle-wrapper.jar
23 | **/android/.gradle
24 | **/android/gradlew
25 | **/android/gradlew.bat
26 | **/android/local.properties
27 | **/android/truecaller_sdk_example_android.iml
28 | **/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
29 |
30 | # iOS/XCode related
31 | **/ios/**/*.mode1v3
32 | **/ios/**/*.mode2v3
33 | **/ios/**/*.moved-aside
34 | **/ios/**/*.pbxuser
35 | **/ios/**/*.perspectivev3
36 | **/ios/**/*sync/
37 | **/ios/**/.sconsign.dblite
38 | **/ios/**/.tags*
39 | **/ios/**/.vagrant/
40 | **/ios/**/DerivedData/
41 | **/ios/**/Icon?
42 | **/ios/**/Pods/
43 | **/ios/**/.symlinks/
44 | **/ios/**/profile
45 | **/ios/**/xcuserdata
46 | **/ios/.generated/
47 | **/ios/Flutter/App.framework
48 | **/ios/Flutter/Flutter.framework
49 | **/ios/Flutter/Flutter.podspec
50 | **/ios/Flutter/Generated.xcconfig
51 | **/ios/Flutter/app.flx
52 | **/ios/Flutter/app.zip
53 | **/ios/Flutter/flutter_assets/
54 | **/ios/Flutter/flutter_export_environment.sh
55 | **/ios/ServiceDefinitions.json
56 | **/ios/Runner/GeneratedPluginRegistrant.*
57 |
58 | # Exceptions to above rules.
59 | !**/ios/**/default.mode1v3
60 | !**/ios/**/default.mode2v3
61 | !**/ios/**/default.pbxuser
62 | !**/ios/**/default.perspectivev3
63 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 8af6b2f038c1172e61d418869363a28dffec3cb4
8 | channel: stable
9 |
10 | project_type: plugin
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 1.0.0
2 |
3 | #### Breaking change
4 |
5 | * Flutter plugin supporting OAuth flow and manual verification flow.
6 | * Based on Truecaller's OAuth SDK for Android version [3.0.0](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0)
7 |
8 | ## 0.1.2
9 |
10 | * Updated Flutter channel to stable version 3.3.0
11 | * Updated Android Gradle Plugin to 7.2.2 and Kotlin to 1.7.0
12 | * Fixed a bug related to type mismatch
13 |
14 | ## 0.1.1
15 |
16 | * Flutter plugin for Truecaller SDK based on Truecaller's Android SDK 2.7.0
17 | * TruecallerSdk.requestVerification() would now throw a PlatformException in case an invalid number is supplied to it.
18 |
19 | ## 0.1.0
20 |
21 | * Migrated the plugin and example to support null safety
22 |
23 | ## 0.0.4
24 |
25 | * Flutter plugin for Truecaller SDK based on Truecaller's Android SDK 2.6.0
26 | * More optimisations, bug fixes and support for targetSdkVersion 30
27 |
28 | ## 0.0.3
29 |
30 | * Flutter plugin for Truecaller SDK based on Truecaller's Android SDK 2.5.0
31 | * A new error with code = 15 has been added to handle a rare device specific ActivityNotFound Exception
32 | * Enhanced the plugin to automatically clear the resources taken up by SDK when its no longer needed to save memory
33 | * Updated name validations to handle common scenarios during `non-truecaller verification` flow.
34 | The first name and last name values to be passed need to follow below mentioned rules :
35 | - The strings need to contains at least 1 alphabet, and cannot be completely comprised of numbers or special characters
36 | - String length should be less than 128 characters
37 | - First name is a mandatory field, last name can be empty (but non-nullable)
38 | * Time out exceptions have been removed for OTP and Missed Call from `non-truecaller verification` flow. Use TTL value returned by the stream callback to
39 | handle the time out logic at your own end which can be retrieved from `TruecallerUserCallback.ttl` when `TruecallerSdkCallback.result` equals
40 | `TruecallerSdkCallbackResult.missedCallInitiated` or `TruecallerSdkCallbackResult.otpInitiated`. This means that as soon as you initiate the number
41 | verification flow by OTP or Missed call, you will receive a TTL value which you can use appropriately to show a countdown timer and once it expires you
42 | need to restart the verification process.
43 |
44 | ## 0.0.2
45 |
46 | * Flutter plugin for Truecaller SDK based on Truecaller's Android SDK 2.4.0
47 | * Only supports Android at the moment
48 | * Supports verification of both Truecaller and Non-Truecaller users
49 | * TTL is now exposed to partners when OTP or Missed Call is initiated so that partners are aware of time left to complete the user verification and can take
50 | an appropriate action once TTL expires.
51 | * Optional nullable Error is passed in case of **`TruecallerSdkCallbackResult.verification`** which can be used to determine user action which led to initiating
52 | manual verification like whether the user pressed on the `footer CTA` on the verification screen OR the `system back button`.
53 |
54 | ## 0.0.1
55 |
56 | * Flutter plugin for Truecaller SDK based on Truecaller's Android SDK 2.3.0
57 | * Only supports Android at the moment
58 | * Only supports verification of Truecaller users at the moment
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2015-present, True Software Scandinavia AB. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # truecaller_sdk
2 |
3 |
4 |
5 |
6 |
7 | Flutter plugin that uses [Truecaller's OAuth SDK for Android](https://docs.truecaller.com/truecaller-sdk/) based on OAuth 2.0 which is the industry-standard protocol for authorization.
8 |
9 | For more details, please refer [here](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/implementing-user-flow-for-your-app)
10 |
11 | ## Steps to integrate
12 |
13 | ### 1. Update `pubspec.yaml`:
14 | Include the latest truecaller_sdk in your `pubspec.yaml`
15 | ```yaml
16 | dependencies:
17 | ...
18 | truecaller_sdk: ^1.0.0
19 | ...
20 | ```
21 | ### 2. Generate Client Id and add it to `AndroidManifest.xml`:
22 | * [Register](https://sdk-console-noneu.truecaller.com/) to create your business account and manage OAuth projects .
23 | * Refer to the [official documentation](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/integration-steps/generating-client-id) for
24 | generating client id.
25 | * Open your [AndroidManifest.xml](/example/android/app/src/main/AndroidManifest.xml) under /android module and add a `meta-data` element to the `application`
26 | element with your client id:
27 | ```xml
28 |
29 | ...
30 |
31 | ..
32 |
33 |
34 | ...
35 |
36 | ```
37 |
38 | ### 3. Make changes to `MainActivity.kt`:
39 | * Head to the [MainActivity.kt](/example/android/app/src/main/kotlin/com/example/truecaller_sdk_example/MainActivity.kt) under /android module
40 | * SDK requires the use of a `FragmentActivity` as opposed to `Activity`, so extend your `MainActivity.kt` with `FlutterFragmentActivity`.
41 | * Override the two functions `configureFlutterEngine(flutterEngine: FlutterEngine)` and `getBackgroundMode()` in your `MainActivity.kt`:
42 | ```kotlin
43 | class MainActivity: FlutterFragmentActivity() {
44 | override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
45 | GeneratedPluginRegistrant.registerWith(flutterEngine)
46 | }
47 |
48 | override fun getBackgroundMode(): FlutterActivityLaunchConfigs.BackgroundMode {
49 | return FlutterActivityLaunchConfigs.BackgroundMode.transparent
50 | }
51 | }
52 | ```
53 | * Update `launchMode` of `MainActivity.kt` to `singleTask` in `AndroidManifest.xml` :
54 | ```xml
55 |
56 | ...
57 |
59 | ..
60 | ...
61 |
62 | ```
63 |
64 | ### 4. Add required Permissions to `AndroidManifest.xml`:
65 | Permissions are mandatory only if you are initializing the SDK with `TcSdkOptions.OPTION_VERIFY_ALL_USERS` in order to verify the users manually.
66 |
67 | For Android 8 and above :
68 | ```xml
69 |
70 |
71 |
72 | ```
73 |
74 | For Android 7 and below :
75 | ```xml
76 |
77 |
78 |
79 | ```
80 |
81 | These permissions are required for the SDK to be able to automatically detect the drop call and complete the verification flow.
82 |
83 | To read more about different scenarios for user verifications, [click here](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/scenarios-for-all-user-verifications-truecaller-and-non-truecaller-users).
84 |
85 | ## Example 1 (to verify only Truecaller users having Truecaller app on their device)
86 |
87 | ```dart
88 |
89 | //Import package
90 | import 'package:truecaller_sdk/truecaller_sdk.dart';
91 |
92 | //Step 1: Initialize the SDK with OPTION_VERIFY_ONLY_TC_USERS
93 | TcSdk.initializeSDK(sdkOption: TcSdkOptions.OPTION_VERIFY_ONLY_TC_USERS);
94 |
95 | //Step 2: Check if SDK is usable on that device, otherwise fall back to any other login alternative
96 | bool isUsable = await TcSdk.isOAuthFlowUsable;
97 |
98 | //Step 3: If isUsable is true, then do the following before you can invoke the OAuth consent screen -
99 | //3.1: Set a unique OAuth state and store that state in your session so that you can match it with the state received from the authorization server to prevent
100 | //any request forgery attacks.
101 | //3.2: Set the OAuth scopes that you'd want to request from the user. You can either ask all of them together or a subset of it.
102 | //3.3: Generate a random code verifier either yourself or using the SDK method as shown below. Store the code verifier in the current session since it would
103 | //be required later to generate the access token.
104 | //3.4: Generate code challenge using the code verifier from the previous step
105 | //3.5 Set the code challenge
106 | //3.6 Finally, after setting all of the above, invoke the consent screen by calling getAuthorizationCode
107 | TcSdk.isOAuthFlowUsable.then((isOAuthFlowUsable) {
108 | if (isOAuthFlowUsable) {
109 | oAuthState = "some_unique_uuid" //store the state to use later
110 | TcSdk.setOAuthState(oAuthState); //3.1
111 | TcSdk.setOAuthScopes(['profile', 'phone', 'openid']); //3.2
112 | TcSdk.generateRandomCodeVerifier.then((codeVerifier) { //3.3
113 | TcSdk.generateCodeChallenge(codeVerifier).then((codeChallenge) { //3.4
114 | if (codeChallenge != null) {
115 | this.codeVerifier = codeVerifier; //store the code verifier to use later
116 | TcSdk.setCodeChallenge(codeChallenge); //3.5
117 | TcSdk.getAuthorizationCode; //3.6
118 | } else {
119 | print("***Code challenge NULL. Device not supported***");
120 | }
121 | });
122 | });
123 | } else {
124 | print("***Not usable***");
125 | }
126 | }
127 |
128 | //Step 4: Be informed about the TcSdk.getAuthorizationCode callback result(success, failure, verification)
129 | StreamSubscription streamSubscription = TcSdk.streamCallbackData.listen((tcSdkCallback) {
130 | switch (tcSdkCallback.result) {
131 | case TcSdkCallbackResult.success:
132 | TcOAuthData tcOAuthData = tcSdkCallback.tcOAuthData!;
133 | String authorizationCode = tcOAuthData.authorizationCode; //use this along with codeVerifier generated in step 3.3 to generate an access token
134 | String stateReceivedFromServer = tcOAuthData.state; //match it with what you set in step 3.1
135 | List scopesGranted = tcOAuthData.scopesGranted; //list of scopes granted by the user
136 | break;
137 | case TcSdkCallbackResult.failure:
138 | //Handle the failure
139 | int errorCode = tcSdkCallback.error!.code;
140 | String message = tcSdkCallback.error!.message;
141 | break;
142 | case TcSdkCallbackResult.verification:
143 | // won't receive this callback if initializing SDK with sdkOption as TcSdkOptions.OPTION_VERIFY_ONLY_TC_USERS
144 | print("Verification Required!!");
145 | break;
146 | default:
147 | print("Invalid result");
148 | }
149 | });
150 |
151 | //Step 5: Dispose streamSubscription
152 | @override
153 | void dispose() {
154 | streamSubscription?.cancel();
155 | super.dispose();
156 | }
157 | ```
158 |
159 | //Step 4a
160 | Using the “code verifier” from step 3.3, and the “authorization code” received in success callback of step 4, you need to make a network call to
161 | Truecaller’s backend so as to [fetch the access token](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/integration-steps/integrating-with-your-backend/fetching-user-token)
162 |
163 | //Step 4b
164 | Make a network call to [fetch the userInfo](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/integration-steps/integrating-with-your-backend/fetching-user-profile) using access token from step 4a. The response would be corresponding to the scopes granted by the user.
165 |
166 | ## Example 2 (to verify both Truecaller users (Example 1) and non-Truecaller users via manual verification)
167 |
168 | ```dart
169 |
170 | //Import package
171 | import 'package:truecaller_sdk/truecaller_sdk.dart';
172 |
173 | //Step 1: Initialize the SDK with SDK_OPTION_WITH_OTP
174 | TcSdk.initializeSDK(sdkOption: TcSdkOptions.OPTION_VERIFY_ALL_USERS);
175 |
176 | //Follow steps 2 and 3 from Example 1
177 |
178 | //Step 4: Be informed about the TcSdk.getAuthorizationCode callback result(success, failure, verification)
179 | StreamSubscription streamSubscription = TcSdk.streamCallbackData.listen((tcSdkCallback) {
180 | switch (tcSdkCallback.result) {
181 | case TcSdkCallbackResult.success:
182 | TcOAuthData tcOAuthData = tcSdkCallback.tcOAuthData!;
183 | String authorizationCode = tcOAuthData.authorizationCode; // use this along with codeVerifier generated in step 3.3 to generate an access token
184 | String stateReceivedFromServer = tcOAuthData.state; // match it with what you set in step 3.1
185 | List scopesGranted = tcOAuthData.scopesGranted;
186 | break;
187 | case TcSdkCallbackResult.failure:
188 | //Handle the failure
189 | int errorCode = tcSdkCallback.error!.code;
190 | String message = tcSdkCallback.error!.message;
191 | break;
192 | case TcSdkCallbackResult.verification:
193 | //If the callback comes here, it indicates that user has to be manually verified, so follow step 5
194 | //You'd receive nullable error which can be used to determine user action that led to manual verification
195 | int errorCode = tcSdkCallback.error!.code;
196 | String message = tcSdkCallback.error!.message;
197 | print("Verification Required!!");
198 | break;
199 | default:
200 | print("Invalid result");
201 | }
202 | });
203 |
204 | //Step 5: Initiate manual verification by asking user for his number only if you receive callback result as
205 | //TcSdkCallbackResult.verification in the previous step.
206 | //Please ensure proper validations are in place so as to send a valid phone number string to the below method,
207 | //otherwise an exception would be thrown.
208 | //Also, request the required permissions from the user and ensure they are granted before calling this method.
209 | TcSdk.requestVerification(phoneNumber: "PHONE_NUMBER");
210 |
211 | //Step 6: Be informed about the TcSdk.requestVerification callback result via [streamCallbackData] stream
212 | //result could be either of (missedCallInitiated, missedCallReceived, otpInitiated, otpReceived,
213 | //verifiedBefore, verificationComplete, exception)
214 | StreamSubscription streamSubscription = TcSdk.streamCallbackData.listen((tcSdkCallback) {
215 | switch (tcSdkCallback.result) {
216 | case TcSdkCallbackResult.missedCallInitiated:
217 | //Number Verification would happen via Missed call, so you can show a loader till you receive the call
218 | //You'd also receive ttl (in seconds) that determines time left to complete the user verification
219 | //Once TTL expires, you need to start from step 5. So you can either ask the user to input another number
220 | //or you can also auto-retry the verification on the same number by giving a retry button
221 | String? ttl = tcSdkCallback.ttl;
222 | //You'd also receive a request nonce whose value would be same as the State that you set in step 3.1
223 | String requestNonce = tcSdkCallback.requestNonce;
224 | break;
225 | case TcSdkCallbackResult.missedCallReceived:
226 | //Missed call received and now you can complete the verification as mentioned in step 7a
227 | break;
228 | case TcSdkCallbackResult.otpInitiated:
229 | //Number Verification would happen via OTP
230 | //You'd also receive ttl (in seconds) that determines time left to complete the user verification
231 | //Once TTL expires, you need to start from step 5. So you can either ask the user to input another number
232 | //or you can also auto-retry the verification on the same number by giving a retry button
233 | String? ttl = tcSdkCallback.ttl;
234 | //You'd also receive a request nonce whose value would be same as the State that you set in step 3.1
235 | String requestNonce = tcSdkCallback.requestNonce;
236 | break;
237 | case TcSdkCallbackResult.otpReceived:
238 | //OTP received and now you can complete the verification as mentioned in step 7b
239 | //If SMS Retriever hashcode is configured on Truecaller's developer dashboard, get the OTP from callback
240 | String? otp = tcSdkCallback.otp;
241 | break;
242 | case TcSdkCallbackResult.verificationComplete:
243 | //Number verification has been completed successfully and you can get the accessToken from callback
244 | String? token = tcSdkCallback.accessToken;
245 | //You'd also receive a request nonce whose value would be same as the State that you set in step 3.1
246 | String requestNonce = tcSdkCallback.requestNonce;
247 | break;
248 | case TcSdkCallbackResult.verifiedBefore:
249 | //Number has already been verified before, hence no need to verify. Retrieve the Profile data from callback
250 | String firstName = tcSdkCallback.profile!.firstName;
251 | String? lastName = tcSdkCallback.profile!.lastName;
252 | String phNo = tcSdkCallback.profile!.phoneNumber;
253 | String? token = tcSdkCallback.profile!.accessToken;
254 | //You'd also receive a request nonce whose value would be same as the State that you set in step 3.1
255 | String requestNonce = tcSdkCallback.profile!.requestNonce;
256 | break;
257 | case TcSdkCallbackResult.exception:
258 | //Handle the exception
259 | int exceptionCode = tcSdkCallback.exception!.code;
260 | String exceptionMsg = tcSdkCallback.exception!.message;
261 | break;
262 | default:
263 | print("Invalid result");
264 | }
265 | });
266 |
267 | //Step 7: Complete user verification
268 | //7a: If Missed call has been received successfully, i.e. if you received callback result as
269 | // TcSdkCallbackResult.missedCallReceived in the previous step call this method with user's name
270 | TcSdk.verifyMissedCall(firstName: "FIRST_NAME", lastName: "LAST_NAME");
271 |
272 | //7b: If OTP has been initiated, show user an input OTP screen where they can enter the OTP.
273 | //If the OTP is received on the same device, and you've configured the SMS Retriever, you can prefill the OTP which
274 | //you'd receive if the callback result is TcSdkCallbackResult.otpReceived, and call this method with user's name
275 | //Otherwise, if OTP is not auto-read or if the OTP is received on any other device, call this method with the user's name
276 | //and OTP entered by the user.
277 | TcSdk.verifyOtp(firstName: "FIRST_NAME", lastName: "LAST_NAME", otp: "OTP");
278 |
279 | //Step 7: Dispose streamSubscription
280 | @override
281 | void dispose() {
282 | streamSubscription?.cancel();
283 | super.dispose();
284 | }
285 | ```
286 |
287 | As mentioned in Step 6 above, when `TcSdkCallbackResult` equals `TcSdkCallbackResult.missedCallInitiated` or `TcSdkCallbackResult.otpInitiated`, you will receive an additional parameter for the time to live i.e TTL (in seconds) which is passed as String extra and can be retrieved from
288 | the callback using `tcSdkCallback.ttl`. This value determines amount of time left to complete the user verification. You can use this value to show
289 | a waiting message to your user before they can retry for another attempt i.e fresh verification for same number cannot be re-initiated till the TTL expires.
290 | Once the TTL expires, you need to start the verification process again from step 5.
291 |
292 | ##### NOTE #####
293 | * For details on different kinds of errorCodes, refer [here](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/integration-steps/handling-error-scenarios).
294 | * For details on different kinds of exceptions, refer [here](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/integration-steps/non-truecaller-user-verification/trueexception).
295 | * For details on Server Side Response Validation, refer [here](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/integration-steps/non-truecaller-user-verification/server-side-validation).
296 | * For sample implementations, head over to [example](example) module.
297 |
298 | ## Customization Options
299 |
300 | ### Language
301 | To customise the consent screen in any of the supported Indian languages, add the following line before calling `TcSdk.getAuthorizationCode`:
302 | ```dart
303 | /// initialize the SDK and check isUsable first before calling this method
304 | /// Default value is "en" i.e English
305 | TcSdk.setLocale("hi") // this sets the language to Hindi
306 | ```
307 |
308 | ### Consent screen UI
309 | You can customize the consent screen UI using the options available in class `TcSdkOptions` under `scope_options.dart` and pass them while initializing the SDK.
310 |
311 | ```dart
312 | /// [sdkOption] determines whether you want to use the SDK for verifying -
313 | /// 1. [TcSdkOptions.OPTION_VERIFY_ONLY_TC_USERS] i.e only Truecaller users
314 | /// 2. [TcSdkOptions.OPTION_VERIFY_ALL_USERS] i.e both Truecaller and Non-Truecaller users
315 | /// [consentHeadingOption] determines the heading of the consent screen.
316 | /// [ctaText] determines prefix text in login/primary button
317 | /// [footerType] determines the footer button/secondary button text.
318 | /// [buttonShapeOption] to set login button shape
319 | /// [buttonColor] to set login button color
320 | /// [buttonTextColor] to set login button text color
321 | static initializeSDK(
322 | {required int sdkOption,
323 | int consentHeadingOption = TcSdkOptions.SDK_CONSENT_HEADING_LOG_IN_TO,
324 | int footerType = TcSdkOptions.FOOTER_TYPE_ANOTHER_MOBILE_NO,
325 | int ctaText = TcSdkOptions.CTA_TEXT_PROCEED,
326 | int buttonShapeOption = TcSdkOptions.BUTTON_SHAPE_ROUNDED,
327 | int? buttonColor,
328 | int? buttonTextColor})
329 | ```
330 |
331 | By default, `initializeSDK()` has default argument values for all the arguments except the `sdkOption` which is a required argument, so if you
332 | don't pass any explicit values to the other arguments, this method will initialize the SDK with default values as above.
333 |
334 | ##### Note
335 | For list of supported locales and details on different kinds of customizations, refer [here](https://docs.truecaller.com/truecaller-sdk/android/oauth-sdk-3.0/integration-steps/customisation)
336 |
337 | ##### Support
338 | For any technical/flow related questions, please feel free to reach out via our [support channel](https://developer.truecaller.com/support) for a fast and dedicated response.
339 |
340 | ## License
341 |
342 | [`truecaller_sdk` is MIT-licensed](LICENSE).
343 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | group 'com.truecallersdk'
32 | version '1.0-SNAPSHOT'
33 |
34 | buildscript {
35 | ext.kotlin_version = '1.8.22'
36 | repositories {
37 | google()
38 | mavenCentral()
39 | }
40 |
41 | dependencies {
42 | classpath 'com.android.tools.build:gradle:7.4.2'
43 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
44 | }
45 | }
46 |
47 | rootProject.allprojects {
48 | repositories {
49 | google()
50 | mavenCentral()
51 | }
52 | }
53 |
54 | apply plugin: 'com.android.library'
55 | apply plugin: 'kotlin-android'
56 |
57 | def sdkVariant = "flutter"
58 | def sdkVariantVersion = "1.0.0"
59 |
60 | android {
61 | compileSdkVersion 28
62 |
63 | sourceSets {
64 | main.java.srcDirs += 'src/main/kotlin'
65 | }
66 | defaultConfig {
67 | minSdkVersion 22
68 | resValue("string", "sdk_variant", "${sdkVariant}")
69 | resValue("string", "sdk_variant_version", "${sdkVariantVersion}")
70 | }
71 | lintOptions {
72 | disable 'InvalidPackage'
73 | }
74 | }
75 |
76 | dependencies {
77 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
78 | implementation 'com.truecaller.android.sdk:truecaller-sdk:3.0.0'
79 | }
80 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | #
4 | # Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | #
6 | # Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | #
8 | # In accordance with the Truecaller SDK Agreement available
9 | # here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | # accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | # limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | # Truecaller SDK Product in object code form only, solely for the purpose of using
13 | # the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | #
15 | # THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | # WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | # SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | # EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | # OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | # OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | # POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | # PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | #
30 | org.gradle.jvmargs=-Xmx1536M
31 | android.useAndroidX=true
32 | android.enableJetifier=true
33 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #
2 | # TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | #
4 | # Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | #
6 | # Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | #
8 | # In accordance with the Truecaller SDK Agreement available
9 | # here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | # accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | # limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | # Truecaller SDK Product in object code form only, solely for the purpose of using
13 | # the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | #
15 | # THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | # WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | # SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | # EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | # OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | # OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | # POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | # PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | #
30 |
31 | distributionBase=GRADLE_USER_HOME
32 | distributionPath=wrapper/dists
33 | zipStoreBase=GRADLE_USER_HOME
34 | zipStorePath=wrapper/dists
35 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
36 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | rootProject.name = 'truecaller_sdk'
32 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/com/truecallersdk/Constants.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | package com.truecallersdk
32 |
33 | import androidx.annotation.Keep
34 |
35 | class Constants {
36 | companion object {
37 | //scope options
38 | const val SDK_OPTION = "sdkOption";
39 | const val CONSENT_HEADING_OPTION = "consentHeadingOption";
40 | const val LOGIN_TEXT_PRE = "loginTextPrefix";
41 | const val CTA_TEXT_PRE = "ctaText";
42 | const val FOOTER_TYPE = "footerType";
43 | const val BTN_SHAPE = "buttonShapeOption";
44 | const val BTN_CLR = "buttonColor";
45 | const val BTN_TXT_CLR = "buttonTextColor";
46 | const val LOCALE = "locale";
47 |
48 | //oauth customization
49 | const val SCOPES = "scopes";
50 | const val OAUTH_STATE = "oAuthState";
51 | const val CODE_VERIFIER = "codeVerifier";
52 | const val CODE_CHALLENGE = "codeChallenge";
53 |
54 | //callback data
55 | const val RESULT = "result";
56 | const val DATA = "data";
57 |
58 | //tc callback
59 | const val SUCCESS = "success"
60 | const val FAILURE = "failure"
61 | const val VERIFICATION = "verification"
62 |
63 | //non-tc callback
64 | const val MISSED_CALL_INITIATED = "missedCallInitiated"
65 | const val MISSED_CALL_RECEIVED = "missedCallReceived"
66 | const val OTP_INITIATED = "otpInitiated"
67 | const val OTP_RECEIVED = "otpReceived"
68 | const val VERIFIED_BEFORE = "verifiedBefore"
69 | const val VERIFICATION_COMPLETE = "verificationComplete"
70 | const val EXCEPTION = "exception"
71 |
72 | //non-tc values
73 | const val PH_NO = "ph"
74 | const val COUNTRY_ISO = "ci"
75 | const val FIRST_NAME = "fname"
76 | const val LAST_NAME = "lname"
77 | const val OTP = "otp"
78 | }
79 | }
80 |
81 | @Keep
82 | data class CallbackData(
83 | val otp: String? = null,
84 | val ttl: String? = null,
85 | val accessToken: String? = null,
86 | val requestNonce: String? = null,
87 | val profile: String? = null,
88 | )
--------------------------------------------------------------------------------
/android/src/main/kotlin/com/truecallersdk/TruecallerSdkPlugin.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | package com.truecallersdk
32 |
33 | import android.app.Activity
34 | import android.content.Intent
35 | import androidx.annotation.NonNull
36 | import androidx.fragment.app.FragmentActivity
37 | import com.google.gson.Gson
38 | import com.truecaller.android.sdk.common.VerificationCallback
39 | import com.truecaller.android.sdk.common.VerificationDataBundle
40 | import com.truecaller.android.sdk.common.TrueException
41 | import com.truecaller.android.sdk.common.models.TrueProfile
42 | import com.truecaller.android.sdk.oAuth.CodeVerifierUtil
43 | import com.truecaller.android.sdk.oAuth.TcOAuthCallback
44 | import com.truecaller.android.sdk.oAuth.TcOAuthData
45 | import com.truecaller.android.sdk.oAuth.TcOAuthError
46 | import com.truecaller.android.sdk.oAuth.TcSdk
47 | import com.truecaller.android.sdk.oAuth.TcSdkOptions
48 | import io.flutter.embedding.engine.plugins.FlutterPlugin
49 | import io.flutter.embedding.engine.plugins.activity.ActivityAware
50 | import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
51 | import io.flutter.plugin.common.BinaryMessenger
52 | import io.flutter.plugin.common.EventChannel
53 | import io.flutter.plugin.common.MethodCall
54 | import io.flutter.plugin.common.MethodChannel
55 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler
56 | import io.flutter.plugin.common.MethodChannel.Result
57 | import io.flutter.plugin.common.PluginRegistry
58 | import io.flutter.plugin.common.PluginRegistry.Registrar
59 | import java.util.Locale
60 |
61 | const val INITIALIZE_SDK = "initializeSDK"
62 | const val IS_OAUTH_FLOW_USABLE = "isOAuthFlowUsable"
63 | const val SET_LOCALE = "setLocale"
64 | const val GENERATE_RANDOM_CODE_VERIFIER = "generateRandomCodeVerifier"
65 | const val GENERATE_CODE_CHALLENGE = "generateCodeChallenge"
66 | const val SET_CODE_CHALLENGE = "setCodeChallenge"
67 | const val SET_OAUTH_SCOPES = "setOAuthScopes"
68 | const val SET_OAUTH_STATE = "setOAuthState"
69 | const val GET_AUTHORIZATION_CODE = "getAuthorizationCode"
70 | const val REQUEST_VERIFICATION = "requestVerification"
71 | const val VERIFY_OTP = "verifyOtp"
72 | const val VERIFY_MISSED_CALL = "verifyMissedCall"
73 | const val TC_METHOD_CHANNEL = "tc_method_channel"
74 | const val TC_EVENT_CHANNEL = "tc_event_channel"
75 |
76 | /** TruecallerSdkPlugin */
77 | public class TruecallerSdkPlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler,
78 | ActivityAware, PluginRegistry.ActivityResultListener {
79 |
80 | /** The MethodChannel that will the communication between Flutter and native Android
81 | * This local reference serves to register the plugin with the Flutter Engine and unregister it
82 | * when the Flutter Engine is detached from the Activity
83 | **/
84 | private var methodChannel: MethodChannel? = null
85 | private var eventChannel: EventChannel? = null
86 | private var eventSink: EventChannel.EventSink? = null
87 | private var activity: Activity? = null
88 | private val gson = Gson()
89 |
90 | override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
91 | onAttachedToEngine(flutterPluginBinding.binaryMessenger)
92 | }
93 |
94 | /**This static function is optional and equivalent to onAttachedToEngine. It supports the old
95 | * pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
96 | * plugin registration via this function while apps migrate to use the new Android APIs
97 | * post-flutter-1.12 via https:flutter.dev/go/android-project-migration.
98 | * It is encouraged to share logic between onAttachedToEngine and registerWith to keep
99 | * them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
100 | * depending on the user's project. onAttachedToEngine or registerWith must both be defined
101 | * in the same class.
102 | **/
103 | companion object {
104 | @JvmStatic
105 | fun registerWith(registrar: Registrar) {
106 | val truecallerSdkPlugin = TruecallerSdkPlugin()
107 | truecallerSdkPlugin.activity = registrar.activity()
108 | truecallerSdkPlugin.onAttachedToEngine(registrar.messenger())
109 | }
110 | }
111 |
112 | private fun onAttachedToEngine(messenger: BinaryMessenger) {
113 | methodChannel = MethodChannel(messenger, TC_METHOD_CHANNEL)
114 | methodChannel?.setMethodCallHandler(this)
115 | eventChannel = EventChannel(messenger, TC_EVENT_CHANNEL)
116 | eventChannel?.setStreamHandler(this)
117 | }
118 |
119 | override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
120 | when (call.method) {
121 | INITIALIZE_SDK -> {
122 | getTcSdkOptions(call)?.let { TcSdk.init(it) } ?: result.error("UNAVAILABLE", "Activity not available.", null)
123 | }
124 |
125 | IS_OAUTH_FLOW_USABLE -> {
126 | result.success(TcSdk.getInstance() != null && TcSdk.getInstance().isOAuthFlowUsable)
127 | }
128 |
129 | SET_LOCALE -> {
130 | call.argument(Constants.LOCALE)?.let {
131 | TcSdk.getInstance().setLocale(Locale(it))
132 | }
133 | }
134 |
135 | GENERATE_RANDOM_CODE_VERIFIER -> {
136 | result.success(CodeVerifierUtil.generateRandomCodeVerifier())
137 | }
138 |
139 | GENERATE_CODE_CHALLENGE -> {
140 | call.argument(Constants.CODE_VERIFIER)?.let {
141 | result.success(CodeVerifierUtil.getCodeChallenge(it))
142 | }
143 | }
144 |
145 | SET_CODE_CHALLENGE -> {
146 | call.argument(Constants.CODE_CHALLENGE)?.let {
147 | TcSdk.getInstance().setCodeChallenge(it)
148 | }
149 | }
150 |
151 | SET_OAUTH_SCOPES -> {
152 | call.argument>(Constants.SCOPES)?.let {
153 | TcSdk.getInstance().setOAuthScopes(it.toTypedArray())
154 | }
155 | }
156 |
157 | SET_OAUTH_STATE -> {
158 | call.argument(Constants.OAUTH_STATE)?.let {
159 | TcSdk.getInstance().setOAuthState(it)
160 | }
161 | }
162 |
163 | GET_AUTHORIZATION_CODE -> {
164 | activity?.let { TcSdk.getInstance().getAuthorizationCode(it as FragmentActivity) } ?: result.error(
165 | "UNAVAILABLE",
166 | "Activity not available.",
167 | null
168 | )
169 | }
170 |
171 | REQUEST_VERIFICATION -> {
172 | val phoneNumber = call.argument(Constants.PH_NO)?.takeUnless(String::isBlank)
173 | ?: return result.error("Invalid phone", "Can't be null or empty", null)
174 | val countryISO = call.argument(Constants.COUNTRY_ISO) ?: "IN"
175 | activity?.let {
176 | try {
177 | TcSdk.getInstance()
178 | .requestVerification(countryISO, phoneNumber, verificationCallback, it as FragmentActivity)
179 | } catch (e: RuntimeException) {
180 | result.error(e.message ?: "UNAVAILABLE", e.message ?: "UNAVAILABLE", null)
181 | }
182 | }
183 | ?: result.error("UNAVAILABLE", "Activity not available.", null)
184 | }
185 |
186 | VERIFY_OTP -> {
187 | val firstName = call.argument(Constants.FIRST_NAME)?.takeUnless(String::isBlank)
188 | ?: return result.error("Invalid name", "Can't be null or empty", null)
189 | val lastName = call.argument(Constants.LAST_NAME) ?: ""
190 | val trueProfile = TrueProfile.Builder(firstName, lastName).build()
191 | val otp = call.argument(Constants.OTP)?.takeUnless(String::isBlank)
192 | ?: return result.error("Invalid otp", "Can't be null or empty", null)
193 | TcSdk.getInstance().verifyOtp(
194 | trueProfile,
195 | otp,
196 | verificationCallback
197 | )
198 | }
199 |
200 | VERIFY_MISSED_CALL -> {
201 | val firstName = call.argument(Constants.FIRST_NAME)?.takeUnless(String::isBlank)
202 | ?: return result.error("Invalid name", "Can't be null or empty", null)
203 | val lastName = call.argument(Constants.LAST_NAME) ?: ""
204 | val trueProfile = TrueProfile.Builder(firstName, lastName).build()
205 | TcSdk.getInstance().verifyMissedCall(
206 | trueProfile,
207 | verificationCallback
208 | )
209 | }
210 |
211 | else -> {
212 | result.notImplemented()
213 | }
214 | }
215 | }
216 |
217 | private fun getTcSdkOptions(call: MethodCall): TcSdkOptions? {
218 | return activity?.let {
219 | TcSdkOptions.Builder(it, oAuthCallback)
220 | .sdkOptions(call.argument(Constants.SDK_OPTION) ?: TcSdkOptions.OPTION_VERIFY_ONLY_TC_USERS)
221 | .consentHeadingOption(call.argument(Constants.CONSENT_HEADING_OPTION) ?: TcSdkOptions.SDK_CONSENT_HEADING_LOG_IN_TO)
222 | .loginTextPrefix(call.argument(Constants.LOGIN_TEXT_PRE) ?: TcSdkOptions.LOGIN_TEXT_PREFIX_TO_GET_STARTED)
223 | .footerType(call.argument(Constants.FOOTER_TYPE) ?: TcSdkOptions.FOOTER_TYPE_ANOTHER_MOBILE_NO)
224 | .ctaText(call.argument(Constants.CTA_TEXT_PRE) ?: TcSdkOptions.CTA_TEXT_PROCEED)
225 | .buttonShapeOptions(call.argument(Constants.BTN_SHAPE) ?: TcSdkOptions.BUTTON_SHAPE_ROUNDED)
226 | .buttonColor(call.argument(Constants.BTN_CLR)?.toInt() ?: 0)
227 | .buttonTextColor(call.argument(Constants.BTN_TXT_CLR)?.toInt() ?: 0)
228 | .build()
229 | }
230 | }
231 |
232 | private val oAuthCallback: TcOAuthCallback = object : TcOAuthCallback {
233 | override fun onSuccess(tcOAuthData: TcOAuthData) {
234 | eventSink?.success(
235 | mapOf(
236 | Constants.RESULT to Constants.SUCCESS,
237 | Constants.DATA to gson.toJson(tcOAuthData)
238 | )
239 | )
240 | }
241 |
242 | override fun onFailure(tcOAuthError: TcOAuthError) {
243 | eventSink?.success(
244 | mapOf(
245 | Constants.RESULT to Constants.FAILURE,
246 | Constants.DATA to gson.toJson(tcOAuthError)
247 | )
248 | )
249 | }
250 |
251 | override fun onVerificationRequired(tcOAuthError: TcOAuthError?) {
252 | eventSink?.success(
253 | mapOf(
254 | Constants.RESULT to Constants.VERIFICATION,
255 | Constants.DATA to gson.toJson(tcOAuthError)
256 | )
257 | )
258 | }
259 | }
260 |
261 | private val verificationCallback: VerificationCallback = object : VerificationCallback {
262 | override fun onRequestSuccess(requestCode: Int, bundle: VerificationDataBundle?) {
263 | when (requestCode) {
264 | VerificationCallback.TYPE_MISSED_CALL_INITIATED -> {
265 | eventSink?.success(
266 | mapOf(
267 | Constants.RESULT to Constants.MISSED_CALL_INITIATED,
268 | Constants.DATA to gson.toJson(
269 | CallbackData(
270 | ttl = bundle?.getString(VerificationDataBundle.KEY_TTL),
271 | requestNonce = bundle?.getString(VerificationDataBundle.KEY_REQUEST_NONCE)
272 | )
273 | )
274 | )
275 | )
276 | }
277 |
278 | VerificationCallback.TYPE_MISSED_CALL_RECEIVED -> {
279 | eventSink?.success(
280 | mapOf(
281 | Constants.RESULT to Constants.MISSED_CALL_RECEIVED
282 | )
283 | )
284 | }
285 |
286 | VerificationCallback.TYPE_OTP_INITIATED -> {
287 | eventSink?.success(
288 | mapOf(
289 | Constants.RESULT to Constants.OTP_INITIATED,
290 | Constants.DATA to gson.toJson(
291 | CallbackData(
292 | ttl = bundle?.getString(VerificationDataBundle.KEY_TTL),
293 | requestNonce = bundle?.getString(VerificationDataBundle.KEY_REQUEST_NONCE)
294 | )
295 | )
296 | )
297 | )
298 | }
299 |
300 | VerificationCallback.TYPE_OTP_RECEIVED -> {
301 | eventSink?.success(
302 | mapOf(
303 | Constants.RESULT to Constants.OTP_RECEIVED,
304 | Constants.DATA to gson.toJson(
305 | CallbackData(
306 | otp = bundle?.getString(VerificationDataBundle.KEY_OTP)
307 | )
308 | )
309 | )
310 | )
311 | }
312 |
313 | VerificationCallback.TYPE_PROFILE_VERIFIED_BEFORE -> {
314 | eventSink?.success(
315 | mapOf(
316 | Constants.RESULT to Constants.VERIFIED_BEFORE,
317 | Constants.DATA to gson.toJson(
318 | CallbackData(
319 | profile = gson.toJson(bundle?.profile)
320 | )
321 | )
322 | )
323 | )
324 | }
325 |
326 | else -> {
327 | eventSink?.success(
328 | mapOf(
329 | Constants.RESULT to Constants.VERIFICATION_COMPLETE,
330 | Constants.DATA to gson.toJson(
331 | CallbackData(
332 | accessToken = bundle?.getString(VerificationDataBundle.KEY_ACCESS_TOKEN),
333 | requestNonce = bundle?.getString(VerificationDataBundle.KEY_REQUEST_NONCE)
334 | )
335 | )
336 | )
337 | )
338 | }
339 | }
340 | }
341 |
342 | override fun onRequestFailure(callbackType: Int, trueException: TrueException) {
343 | eventSink?.success(
344 | mapOf(
345 | Constants.RESULT to Constants.EXCEPTION,
346 | Constants.DATA to gson.toJson(trueException)
347 | )
348 | )
349 | }
350 | }
351 |
352 | override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink?) {
353 | this.eventSink = eventSink
354 | }
355 |
356 | override fun onCancel(arguments: Any?) {
357 | eventSink = null
358 | }
359 |
360 | override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
361 | cleanUp()
362 | }
363 |
364 | override fun onAttachedToActivity(binding: ActivityPluginBinding) {
365 | this.activity = binding.activity
366 | binding.addActivityResultListener(this)
367 | }
368 |
369 | override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
370 | this.activity = binding.activity
371 | binding.addActivityResultListener(this)
372 | }
373 |
374 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
375 | return if (requestCode == TcSdk.SHARE_PROFILE_REQUEST_CODE) {
376 | TcSdk.getInstance().onActivityResultObtained(activity as FragmentActivity, requestCode, resultCode, data)
377 | } else false
378 | }
379 |
380 | override fun onDetachedFromActivity() {
381 | cleanUp()
382 | }
383 |
384 | override fun onDetachedFromActivityForConfigChanges() {
385 | cleanUp()
386 | }
387 |
388 | private fun cleanUp() {
389 | TcSdk.clear()
390 | activity = null
391 | methodChannel?.setMethodCallHandler(null)
392 | methodChannel = null
393 | eventChannel?.setStreamHandler(null)
394 | eventChannel = null
395 | eventSink = null
396 | }
397 | }
398 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Exceptions to above rules.
43 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
44 |
--------------------------------------------------------------------------------
/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 8af6b2f038c1172e61d418869363a28dffec3cb4
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # truecaller_sdk_example
2 |
3 | Demonstrates how to use the `truecaller_sdk` plugin.
4 |
5 | You can find 2 example implementations under [example/lib](lib) directory
6 |
7 | 1. [main.dart](https://github.com/truecaller/flutter-sdk/blob/master/example/lib/main.dart) - a very basic, crude implementation of
8 | `truecaller_sdk` plugin which would look like this -
9 |
10 |
11 |
12 | To run this file, just execute the following command after navigating to `/example` directory -
13 |
14 | ```flutter run --target=lib/main.dart```
15 |
16 |
17 | 2. [main_customization_screen.dart](https://github.com/truecaller/flutter-sdk/blob/master/example/lib/customization/main_customization_screen.dart) - sample implementation that shows different customization options available for `truecaller_sdk` plugin which would look like this -
18 |
19 |
20 |
21 | To run this file, just execute the following command after navigating to `/example` directory -
22 |
23 | ```flutter run --target=lib/customization/main_customization_screen.dart```
24 |
25 |
26 | ##### Note : If you run these examples and proceed with user verification, SDK would give you error code 3 which indicates an incorrect app key. So you need to replace the partnerKey in [AndroidManifest.xml](android/app/src/main/AndroidManifest.xml) with your own app key as mentioned in [step 2](/README.md) of `Steps to integrate` section.
27 |
28 |
29 | ## License
30 |
31 | [MIT-licensed](../LICENSE).
32 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | def localProperties = new Properties()
32 | def localPropertiesFile = rootProject.file('local.properties')
33 | if (localPropertiesFile.exists()) {
34 | localPropertiesFile.withReader('UTF-8') { reader ->
35 | localProperties.load(reader)
36 | }
37 | }
38 |
39 | def flutterRoot = localProperties.getProperty('flutter.sdk')
40 | if (flutterRoot == null) {
41 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
42 | }
43 |
44 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
45 | if (flutterVersionCode == null) {
46 | flutterVersionCode = '1'
47 | }
48 |
49 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
50 | if (flutterVersionName == null) {
51 | flutterVersionName = '1.0'
52 | }
53 |
54 | apply plugin: 'com.android.application'
55 | apply plugin: 'kotlin-android'
56 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
57 |
58 | android {
59 | compileSdkVersion 33
60 |
61 | sourceSets {
62 | main.java.srcDirs += 'src/main/kotlin'
63 | }
64 |
65 | defaultConfig {
66 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
67 | applicationId "com.example.truecaller_sdk_example"
68 | minSdkVersion 22
69 | targetSdkVersion 30
70 | versionCode flutterVersionCode.toInteger()
71 | versionName flutterVersionName
72 | }
73 |
74 | buildTypes {
75 | release {
76 | // TODO: Add your own signing config for the release build.
77 | // Signing with the debug keys for now, so `flutter run --release` works.
78 | signingConfig signingConfigs.debug
79 | }
80 | }
81 | lint {
82 | disable 'InvalidPackage'
83 | }
84 | }
85 |
86 | flutter {
87 | source '../..'
88 | }
89 |
90 | dependencies {
91 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
92 | }
93 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
30 |
31 |
33 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
30 |
31 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
44 |
51 |
52 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
65 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/truecaller_sdk_example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | package com.example.truecaller_sdk_example
32 |
33 | import io.flutter.embedding.android.FlutterActivityLaunchConfigs
34 | import io.flutter.embedding.android.FlutterFragmentActivity
35 | import io.flutter.embedding.engine.FlutterEngine
36 | import io.flutter.plugins.GeneratedPluginRegistrant
37 |
38 | class MainActivity : FlutterFragmentActivity() {
39 | override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
40 | GeneratedPluginRegistrant.registerWith(flutterEngine)
41 | }
42 |
43 | override fun getBackgroundMode(): FlutterActivityLaunchConfigs.BackgroundMode {
44 | return FlutterActivityLaunchConfigs.BackgroundMode.transparent
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
41 |
42 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 |
38 |
44 |
47 |
48 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
30 |
31 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | buildscript {
32 | ext.kotlin_version = '1.8.22'
33 | repositories {
34 | google()
35 | mavenCentral()
36 | }
37 |
38 | dependencies {
39 | classpath 'com.android.tools.build:gradle:7.4.2'
40 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
41 | }
42 | }
43 |
44 | allprojects {
45 | repositories {
46 | google()
47 | mavenCentral()
48 | }
49 | }
50 |
51 | rootProject.buildDir = '../build'
52 | subprojects {
53 | project.buildDir = "${rootProject.buildDir}/${project.name}"
54 | }
55 | subprojects {
56 | project.evaluationDependsOn(':app')
57 | }
58 |
59 | tasks.register("clean", Delete) {
60 | delete rootProject.buildDir
61 | }
62 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | #
4 | # Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | #
6 | # Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | #
8 | # In accordance with the Truecaller SDK Agreement available
9 | # here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | # accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | # limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | # Truecaller SDK Product in object code form only, solely for the purpose of using
13 | # the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | #
15 | # THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | # WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | # SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | # EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | # OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | # INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | # ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | # OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | # POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | # PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | #
30 | org.gradle.jvmargs=-Xmx1536M
31 | android.useAndroidX=true
32 | android.enableJetifier=true
33 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Aug 03 12:58:09 IST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
7 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | include ':app'
6 |
7 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
8 | def properties = new Properties()
9 |
10 | assert localPropertiesFile.exists()
11 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
12 |
13 | def flutterSdkPath = properties.getProperty("flutter.sdk")
14 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
15 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
16 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 9.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Flutter (1.0.0)
3 | - truecaller_sdk (0.0.1):
4 | - Flutter
5 | - TrueSDK
6 | - TrueSDK (0.1.8)
7 |
8 | DEPENDENCIES:
9 | - Flutter (from `Flutter`)
10 | - truecaller_sdk (from `.symlinks/plugins/truecaller_sdk/ios`)
11 |
12 | SPEC REPOS:
13 | trunk:
14 | - TrueSDK
15 |
16 | EXTERNAL SOURCES:
17 | Flutter:
18 | :path: Flutter
19 | truecaller_sdk:
20 | :path: ".symlinks/plugins/truecaller_sdk/ios"
21 |
22 | SPEC CHECKSUMS:
23 | Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
24 | truecaller_sdk: 08d7553ccf979fe1bdc512261edac15c087176d7
25 | TrueSDK: 6845b0387144212913ec8fd851f4a57998c1ea21
26 |
27 | PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
28 |
29 | COCOAPODS: 1.11.2
30 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 | import truecaller_sdk
4 | import TrueSDK
5 |
6 | @UIApplicationMain
7 | @objc class AppDelegate: FlutterAppDelegate {
8 | override func application(
9 | _ application: UIApplication,
10 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
11 | ) -> Bool {
12 | GeneratedPluginRegistrant.register(with: self)
13 |
14 | TCTrueSDK.sharedManager().setup(withAppKey: "I7ViZ490028736bba408881687123b4cec49f",
15 | appLink: "https://si9f1dc18a1d0041efa219162d27d1c865.truecallerdevs.com")
16 |
17 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | truecaller_sdk_example
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleURLTypes
24 |
25 |
26 | CFBundleTypeRole
27 | Editor
28 | CFBundleURLSchemes
29 |
30 | truecallersdk-I7ViZ490028736bba408881687123b4cec49f
31 |
32 |
33 |
34 | CFBundleVersion
35 | $(FLUTTER_BUILD_NUMBER)
36 | LSApplicationQueriesSchemes
37 |
38 | truesdk
39 |
40 | LSRequiresIPhoneOS
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIMainStoryboardFile
45 | Main
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UISupportedInterfaceOrientations~ipad
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationPortraitUpsideDown
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 | UIViewControllerBasedStatusBarAppearance
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.associated-domains
6 |
7 | applinks:si9f1dc18a1d0041efa219162d27d1c865.truecallerdevs.com
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/lib/customization/config_options.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | import 'package:flutter/material.dart';
32 | import 'package:truecaller_sdk/truecaller_sdk.dart';
33 |
34 | class HeadingOption {
35 | static List getHeadingOptions() {
36 | return [
37 | "Login",
38 | "Signup",
39 | "Signin",
40 | "Verify",
41 | "Register",
42 | "Get Started",
43 | "Proceed with",
44 | "Verify with",
45 | "Verify profile with",
46 | "Verify your profile with",
47 | "Verify phone number with",
48 | "Verify your number with",
49 | "Continue with",
50 | "Complete order with",
51 | "Place order with",
52 | "Complete booking with",
53 | "Checkout with",
54 | "Manage details with",
55 | "Manage your details with",
56 | "Login to %s with one tap",
57 | "Subscribe to",
58 | "Get updates from",
59 | "Continue reading on",
60 | "Get new updates from",
61 | "Login/Signup with"
62 | ];
63 | }
64 | }
65 |
66 | class FooterOption {
67 | String name;
68 |
69 | FooterOption(this.name);
70 |
71 | static Map getFooterOptionsMap() {
72 | return {
73 | TcSdkOptions.FOOTER_TYPE_ANOTHER_MOBILE_NO: "Use Another Number",
74 | TcSdkOptions.FOOTER_TYPE_ANOTHER_METHOD: "Use Another Method",
75 | TcSdkOptions.FOOTER_TYPE_MANUALLY: "Enter Details Manually",
76 | TcSdkOptions.FOOTER_TYPE_LATER: "I'll do later",
77 | TcSdkOptions.FOOTER_TYPE_SKIP: "Skip",
78 | };
79 | }
80 | }
81 |
82 | class ConfigOptions {
83 | static Map getColorList() {
84 | return {
85 | "green": Colors.green.value,
86 | "white": Colors.white.value,
87 | "red": Colors.red.value,
88 | "blue": Colors.blue.value,
89 | "black": Colors.black.value,
90 | "grey": Colors.grey.value,
91 | "cyan": Colors.cyan.value,
92 | "brown": Colors.brown.value,
93 | "yellow": Colors.yellow.value,
94 | "lime": Colors.lime.value,
95 | "purple": Colors.purple.value,
96 | "pink": Colors.pink.value,
97 | "deepOrange": Colors.deepOrange.value,
98 | "indigo": Colors.indigo.value,
99 | "teal": Colors.teal.value,
100 | };
101 | }
102 |
103 | static List getCtaPrefixOptions() {
104 | return [
105 | "Proceed",
106 | "Continue",
107 | "Accept",
108 | "Confirm",
109 | "Use %s",
110 | "Continue with %s",
111 | "Proceed with %s"
112 | ];
113 | }
114 | }
115 |
116 | class AccessTokenHelper {
117 | final TcOAuthData tcOAuthData;
118 | final String codeVerifier;
119 |
120 | AccessTokenHelper(this.tcOAuthData, this.codeVerifier);
121 | }
122 |
--------------------------------------------------------------------------------
/example/lib/customization/main_customization_screen.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | import 'dart:async';
32 |
33 | import 'package:flutter/material.dart';
34 | import 'package:truecaller_sdk/truecaller_sdk.dart';
35 | import 'package:truecaller_sdk_example/customization/oauth_result_screen.dart';
36 | import 'package:truecaller_sdk_example/non_tc_screen.dart';
37 | import 'package:uuid/uuid.dart';
38 |
39 | import 'config_options.dart';
40 |
41 | // This screen shows different customization options available in Truecaller SDK
42 |
43 | void main() {
44 | runApp(OptionsConfiguration());
45 | }
46 |
47 | class OptionsConfiguration extends StatefulWidget {
48 | @override
49 | _OptionsConfigurationState createState() => _OptionsConfigurationState();
50 | }
51 |
52 | class _OptionsConfigurationState extends State {
53 | @override
54 | Widget build(BuildContext context) {
55 | return MaterialApp(
56 | title: "TC SDK Demo",
57 | debugShowCheckedModeBanner: false,
58 | home: HomePage());
59 | }
60 | }
61 |
62 | class HomePage extends StatefulWidget {
63 | @override
64 | _HomePageState createState() => _HomePageState();
65 | }
66 |
67 | class _HomePageState extends State {
68 | late int selectedFooter;
69 | late bool rectangularBtn, verifyAllUsers;
70 | late String? codeVerifier;
71 | List> colorMenuItemList = [];
72 | List> ctaPrefixMenuItemList = [];
73 | List> headingMenuItemList = [];
74 | late int ctaColor, ctaTextColor;
75 | late int ctaPrefixOption, headingOption;
76 | final TextEditingController localeController = TextEditingController();
77 | late StreamSubscription? streamSubscription;
78 |
79 | @override
80 | void initState() {
81 | super.initState();
82 | createStreamBuilder();
83 | selectedFooter = FooterOption.getFooterOptionsMap().keys.first;
84 | rectangularBtn = false;
85 | verifyAllUsers = false;
86 | ctaColor = Colors.blue.value;
87 | ctaTextColor = Colors.white.value;
88 | ctaPrefixOption = 0;
89 | headingOption = 0;
90 |
91 | for (String key in ConfigOptions.getColorList().keys) {
92 | colorMenuItemList.add(DropdownMenuItem(
93 | value: ConfigOptions.getColorList()[key],
94 | child: Text("$key"),
95 | ));
96 | }
97 |
98 | for (int i = 0; i < ConfigOptions.getCtaPrefixOptions().length; i++) {
99 | ctaPrefixMenuItemList.add(DropdownMenuItem(
100 | value: i,
101 | child: Text("${ConfigOptions.getCtaPrefixOptions()[i]}"),
102 | ));
103 | }
104 |
105 | for (int i = 0; i < HeadingOption.getHeadingOptions().length; i++) {
106 | headingMenuItemList.add(DropdownMenuItem(
107 | value: i,
108 | child: Text("${HeadingOption.getHeadingOptions()[i]}"),
109 | ));
110 | }
111 | }
112 |
113 | List createRadioListFooterOptions() {
114 | List widgets = [];
115 | for (int key in FooterOption.getFooterOptionsMap().keys) {
116 | widgets.add(
117 | RadioListTile(
118 | value: key,
119 | groupValue: selectedFooter,
120 | title: Text("${FooterOption.getFooterOptionsMap()[key]}"),
121 | onChanged: (dynamic currentOption) {
122 | setSelectedFooter(currentOption);
123 | },
124 | selected: selectedFooter == key,
125 | activeColor: Colors.green,
126 | ),
127 | );
128 | }
129 | return widgets;
130 | }
131 |
132 | setSelectedFooter(int option) {
133 | setState(() {
134 | selectedFooter = option;
135 | });
136 | }
137 |
138 | @override
139 | Widget build(BuildContext context) {
140 | return Scaffold(
141 | appBar: AppBar(
142 | title: Text("Configure SDK options"),
143 | ),
144 | body: SingleChildScrollView(
145 | child: Padding(
146 | padding: const EdgeInsets.all(16.0),
147 | child: Container(
148 | child: Column(
149 | children: [
150 | Text(
151 | "Customization Options",
152 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
153 | ),
154 | Column(
155 | children: createConfigOptions(),
156 | ),
157 | Divider(
158 | color: Colors.transparent,
159 | height: 20.0,
160 | ),
161 | Text(
162 | "Footer Options",
163 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
164 | ),
165 | Divider(
166 | color: Colors.transparent,
167 | height: 20.0,
168 | ),
169 | Column(
170 | children: createRadioListFooterOptions(),
171 | ),
172 | Padding(
173 | padding: const EdgeInsets.only(
174 | left: 16.0, right: 16.0, top: 10.0, bottom: 10.0),
175 | child: TextField(
176 | controller: localeController,
177 | maxLength: 2,
178 | style: TextStyle(
179 | color: Colors.green,
180 | ),
181 | decoration: InputDecoration(
182 | labelText: "Enter Locale",
183 | labelStyle:
184 | TextStyle(color: Colors.black, fontSize: 16.0),
185 | hintText:
186 | "Example: en(default), hi, kn, ta, te, mr, etc.",
187 | hintStyle: TextStyle(
188 | fontStyle: FontStyle.italic,
189 | color: Colors.green,
190 | fontSize: 14.0)),
191 | ),
192 | ),
193 | SwitchListTile(
194 | title: Text("Verify all users"),
195 | value: verifyAllUsers,
196 | onChanged: (value) {
197 | setState(() {
198 | verifyAllUsers = value;
199 | });
200 | },
201 | selected: verifyAllUsers,
202 | activeColor: Colors.green,
203 | ),
204 | Divider(
205 | color: Colors.transparent,
206 | height: 20.0,
207 | ),
208 | MaterialButton(
209 | height: 45.0,
210 | child: Text(
211 | "LET'S GO",
212 | style: TextStyle(
213 | color: Colors.white,
214 | ),
215 | ),
216 | color: Colors.blue,
217 | onPressed: () {
218 | initializeSdk();
219 | },
220 | )
221 | ],
222 | ),
223 | ),
224 | ),
225 | ),
226 | );
227 | }
228 |
229 | createConfigOptions() {
230 | return [
231 | Divider(
232 | color: Colors.transparent,
233 | height: 20.0,
234 | ),
235 | SwitchListTile(
236 | title: Text("Rectangular Button"),
237 | value: rectangularBtn,
238 | onChanged: (value) {
239 | setState(() {
240 | rectangularBtn = value;
241 | });
242 | },
243 | selected: rectangularBtn,
244 | activeColor: Colors.green,
245 | ),
246 | Divider(
247 | color: Colors.transparent,
248 | height: 10.0,
249 | ),
250 | Padding(
251 | padding: const EdgeInsets.only(left: 16.0, right: 16.0),
252 | child: DropdownButtonFormField(
253 | decoration: InputDecoration(
254 | labelText: "CTA color",
255 | labelStyle: TextStyle(color: Colors.black, fontSize: 16.0),
256 | ),
257 | style: TextStyle(color: Colors.green),
258 | value: ctaColor,
259 | isExpanded: true,
260 | items: colorMenuItemList,
261 | onChanged: (value) {
262 | setState(() {
263 | ctaColor = value!;
264 | });
265 | }),
266 | ),
267 | Divider(
268 | color: Colors.transparent,
269 | height: 10.0,
270 | ),
271 | Padding(
272 | padding: const EdgeInsets.only(left: 16.0, right: 16.0),
273 | child: DropdownButtonFormField(
274 | decoration: InputDecoration(
275 | labelText: "CTA text color",
276 | labelStyle: TextStyle(color: Colors.black, fontSize: 16.0),
277 | ),
278 | style: TextStyle(color: Colors.green),
279 | value: ctaTextColor,
280 | isExpanded: true,
281 | items: colorMenuItemList,
282 | onChanged: (value) {
283 | setState(() {
284 | ctaTextColor = value!;
285 | });
286 | }),
287 | ),
288 | Divider(
289 | color: Colors.transparent,
290 | height: 10.0,
291 | ),
292 | Padding(
293 | padding: const EdgeInsets.only(left: 16.0, right: 16.0),
294 | child: DropdownButtonFormField(
295 | decoration: InputDecoration(
296 | labelText: "CTA Prefix",
297 | labelStyle: TextStyle(color: Colors.black, fontSize: 16.0),
298 | ),
299 | style: TextStyle(color: Colors.green),
300 | value: ctaPrefixOption,
301 | isExpanded: true,
302 | items: ctaPrefixMenuItemList,
303 | onChanged: (value) {
304 | setState(() {
305 | ctaPrefixOption = value!;
306 | });
307 | }),
308 | ),
309 | Divider(
310 | color: Colors.transparent,
311 | height: 10.0,
312 | ),
313 | Padding(
314 | padding: const EdgeInsets.only(left: 16.0, right: 16.0),
315 | child: DropdownButtonFormField(
316 | decoration: InputDecoration(
317 | labelText: "Heading options",
318 | labelStyle: TextStyle(color: Colors.black, fontSize: 16.0),
319 | ),
320 | style: TextStyle(color: Colors.green),
321 | value: headingOption,
322 | isExpanded: true,
323 | items: headingMenuItemList,
324 | onChanged: (value) {
325 | setState(() {
326 | headingOption = value!;
327 | });
328 | }),
329 | ),
330 | Divider(
331 | color: Colors.transparent,
332 | height: 10.0,
333 | ),
334 | ];
335 | }
336 |
337 | void initializeSdk() {
338 | _hideKeyboard();
339 | TcSdk.initializeSDK(
340 | sdkOption: verifyAllUsers
341 | ? TcSdkOptions.OPTION_VERIFY_ALL_USERS
342 | : TcSdkOptions.OPTION_VERIFY_ONLY_TC_USERS,
343 | consentHeadingOption: headingOption,
344 | footerType: selectedFooter,
345 | ctaText: ctaPrefixOption,
346 | buttonShapeOption: rectangularBtn
347 | ? TcSdkOptions.BUTTON_SHAPE_RECTANGLE
348 | : TcSdkOptions.BUTTON_SHAPE_ROUNDED,
349 | buttonColor: ctaColor,
350 | buttonTextColor: ctaTextColor);
351 |
352 | TcSdk.isOAuthFlowUsable.then((isOAuthFlowUsable) {
353 | if (isOAuthFlowUsable) {
354 | TcSdk.setOAuthState(Uuid().v1());
355 | TcSdk.setOAuthScopes(['profile', 'phone', 'openid', 'offline_access']);
356 | if (localeController.text.isNotEmpty) {
357 | TcSdk.setLocale(localeController.text);
358 | }
359 | TcSdk.generateRandomCodeVerifier.then((codeVerifier) {
360 | TcSdk.generateCodeChallenge(codeVerifier).then((codeChallenge) {
361 | if (codeChallenge != null) {
362 | this.codeVerifier = codeVerifier;
363 | TcSdk.setCodeChallenge(codeChallenge);
364 | TcSdk.getAuthorizationCode;
365 | } else {
366 | final snackBar = SnackBar(content: Text("Device not supported"));
367 | ScaffoldMessenger.of(context).showSnackBar(snackBar);
368 | print("***Code challenge NULL***");
369 | }
370 | });
371 | });
372 | } else {
373 | print("****Not usable****");
374 | }
375 | });
376 | }
377 |
378 | void createStreamBuilder() {
379 | streamSubscription =
380 | TcSdk.streamCallbackData.listen((truecallerSdkCallback) {
381 | switch (truecallerSdkCallback.result) {
382 | case TcSdkCallbackResult.success:
383 | Navigator.push(
384 | context,
385 | MaterialPageRoute(
386 | builder: (context) => OAuthResultScreen(),
387 | settings: RouteSettings(
388 | arguments: AccessTokenHelper(
389 | truecallerSdkCallback.tcOAuthData!, codeVerifier!),
390 | ),
391 | ));
392 | break;
393 | case TcSdkCallbackResult.failure:
394 | final snackBar = SnackBar(
395 | content: Text("${truecallerSdkCallback.error!.code} : "
396 | "${truecallerSdkCallback.error!.message}"));
397 | ScaffoldMessenger.of(context).showSnackBar(snackBar);
398 | break;
399 | case TcSdkCallbackResult.verification:
400 | Navigator.push(
401 | context,
402 | MaterialPageRoute(
403 | builder: (context) => NonTcVerification(),
404 | ));
405 | break;
406 | default:
407 | print("Invalid result");
408 | }
409 | });
410 | }
411 |
412 | _hideKeyboard() {
413 | FocusManager.instance.primaryFocus!.unfocus();
414 | }
415 |
416 | @override
417 | void dispose() {
418 | localeController.dispose();
419 | streamSubscription?.cancel();
420 | super.dispose();
421 | }
422 | }
423 |
--------------------------------------------------------------------------------
/example/lib/customization/oauth_result_screen.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | import 'package:dio/dio.dart';
32 | import 'package:flutter/material.dart';
33 |
34 | import 'config_options.dart';
35 |
36 | class OAuthResultScreen extends StatefulWidget {
37 | @override
38 | State createState() {
39 | return _MyAppState();
40 | }
41 | }
42 |
43 | class _MyAppState extends State {
44 | late final Dio dio = Dio();
45 | late String accessToken = "";
46 | late String accessTokenResponse = "";
47 | late String userInfoResponse = "";
48 |
49 | @override
50 | Widget build(BuildContext context) {
51 | final accessTokenHelper =
52 | ModalRoute.of(context)!.settings.arguments as AccessTokenHelper;
53 | return MaterialApp(
54 | home: Scaffold(
55 | appBar: AppBar(
56 | title: const Text('OAuth Result'),
57 | ),
58 | body: SingleChildScrollView(
59 | child: Container(
60 | child: Padding(
61 | padding: const EdgeInsets.all(16.0),
62 | child: Column(
63 | children: [
64 | SelectableText(
65 | "Auth Code: ${accessTokenHelper.tcOAuthData.authorizationCode}",
66 | style: TextStyle(fontSize: 14.0),
67 | textAlign: TextAlign.center,
68 | ),
69 | Divider(
70 | color: Colors.transparent,
71 | height: 20.0,
72 | ),
73 | SelectableText(
74 | "OAuth State: ${accessTokenHelper.tcOAuthData.state}",
75 | style: TextStyle(fontSize: 14.0),
76 | textAlign: TextAlign.left,
77 | ),
78 | Divider(
79 | color: Colors.transparent,
80 | height: 20.0,
81 | ),
82 | SelectableText(
83 | "Scopes granted: ${accessTokenHelper.tcOAuthData.scopesGranted}",
84 | style: TextStyle(fontSize: 14.0),
85 | textAlign: TextAlign.left,
86 | ),
87 | Divider(
88 | color: Colors.transparent,
89 | height: 20.0,
90 | ),
91 | MaterialButton(
92 | height: 45.0,
93 | child: Text(
94 | "Fetch Access Token",
95 | style: TextStyle(
96 | color: Colors.white,
97 | ),
98 | ),
99 | color: Colors.blue,
100 | onPressed: () {
101 | fetchAccessToken(accessTokenHelper);
102 | },
103 | ),
104 | Divider(
105 | color: Colors.transparent,
106 | height: 20.0,
107 | ),
108 | SelectableText(
109 | accessTokenResponse.isEmpty
110 | ? ""
111 | : "Access Token Response: $accessTokenResponse",
112 | style: TextStyle(fontSize: 12.0),
113 | textAlign: TextAlign.left,
114 | ),
115 | Divider(
116 | color: Colors.transparent,
117 | height: 20.0,
118 | ),
119 | Visibility(
120 | visible: accessToken.isNotEmpty,
121 | child: MaterialButton(
122 | height: 45.0,
123 | child: Text(
124 | "Fetch User Info",
125 | style: TextStyle(
126 | color: Colors.white,
127 | ),
128 | ),
129 | color: Colors.blue,
130 | onPressed: () {
131 | fetchUserInfo();
132 | },
133 | ),
134 | ),
135 | Divider(
136 | color: Colors.transparent,
137 | height: 20.0,
138 | ),
139 | SelectableText(
140 | userInfoResponse.isEmpty
141 | ? ""
142 | : "User Info Response: $userInfoResponse",
143 | style: TextStyle(fontSize: 14.0),
144 | textAlign: TextAlign.left,
145 | ),
146 | Divider(
147 | color: Colors.transparent,
148 | height: 20.0,
149 | ),
150 | ],
151 | ),
152 | ),
153 | ),
154 | ),
155 | ));
156 | }
157 |
158 | void fetchAccessToken(AccessTokenHelper accessTokenHelper) async {
159 | try {
160 | Response response;
161 | response =
162 | await dio.post('https://oauth-account-noneu.truecaller.com/v1/token',
163 | data: {
164 | 'grant_type': 'authorization_code',
165 | 'client_id': '1si1lk7rbbo_mtg29mw5yczekv2ripbbnwnaozhpz6o',
166 | 'code': '${accessTokenHelper.tcOAuthData.authorizationCode}',
167 | 'code_verifier': '${accessTokenHelper.codeVerifier}'
168 | },
169 | options: Options(contentType: Headers.formUrlEncodedContentType));
170 | if (response.statusCode == 200 && response.data != null) {
171 | Map result = response.data;
172 | accessToken = result['access_token'];
173 | setState(() {
174 | for (final e in result.entries) {
175 | accessTokenResponse =
176 | accessTokenResponse + "\n\n" + ('${e.key} = ${e.value}');
177 | }
178 | });
179 | }
180 | } on DioException catch (e) {
181 | print(e.toString());
182 | setState(() {
183 | accessTokenResponse = e.toString();
184 | });
185 | }
186 | }
187 |
188 | void fetchUserInfo() async {
189 | try {
190 | userInfoResponse = "";
191 | Response response;
192 | response = await dio.get(
193 | 'https://oauth-account-noneu.truecaller.com/v1/userinfo',
194 | options: Options(headers: {"Authorization": "Bearer $accessToken"}));
195 | if (response.statusCode == 200 && response.data != null) {
196 | Map result = response.data;
197 | setState(() {
198 | for (final e in result.entries) {
199 | userInfoResponse =
200 | userInfoResponse + "\n\n" + ('${e.key} = ${e.value}');
201 | }
202 | });
203 | }
204 | } on DioException catch (e) {
205 | print(e.toString());
206 | setState(() {
207 | userInfoResponse = e.toString();
208 | });
209 | }
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/example/lib/customization/result_screen.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | import 'package:flutter/material.dart';
32 |
33 | class ResultScreen extends StatelessWidget {
34 | final String result;
35 |
36 | ResultScreen(this.result);
37 |
38 | @override
39 | Widget build(BuildContext context) {
40 | return Scaffold(
41 | appBar: AppBar(
42 | title: Text("Result Page"),
43 | ),
44 | body: Center(
45 | child: Text(
46 | "$result!",
47 | style: TextStyle(fontSize: 20.0, letterSpacing: 5.0),
48 | ),
49 | ),
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | import 'package:flutter/material.dart';
32 | import 'package:truecaller_sdk/truecaller_sdk.dart';
33 | import 'package:truecaller_sdk_example/non_tc_screen.dart';
34 | import 'package:uuid/uuid.dart';
35 |
36 | import 'customization/config_options.dart';
37 | import 'customization/oauth_result_screen.dart';
38 |
39 | void main() {
40 | runApp(MyApp());
41 | }
42 |
43 | class MyApp extends StatefulWidget {
44 | @override
45 | _MyAppState createState() => _MyAppState();
46 | }
47 |
48 | class _MyAppState extends State {
49 | late Stream? _stream;
50 | late String? codeVerifier;
51 |
52 | @override
53 | void initState() {
54 | super.initState();
55 | _stream = TcSdk.streamCallbackData;
56 | }
57 |
58 | @override
59 | Widget build(BuildContext context) {
60 | return MaterialApp(
61 | home: Scaffold(
62 | appBar: AppBar(
63 | title: const Text('Truecaller SDK example'),
64 | ),
65 | body: Center(
66 | child: Column(
67 | mainAxisSize: MainAxisSize.max,
68 | mainAxisAlignment: MainAxisAlignment.center,
69 | children: [
70 | MaterialButton(
71 | onPressed: () {
72 | TcSdk.initializeSDK(
73 | sdkOption: TcSdkOptions.OPTION_VERIFY_ALL_USERS);
74 | TcSdk.isOAuthFlowUsable.then((isOAuthFlowUsable) {
75 | if (isOAuthFlowUsable) {
76 | TcSdk.setOAuthState(Uuid().v1());
77 | TcSdk.setOAuthScopes(
78 | ['profile', 'phone', 'openid', 'offline_access']);
79 | TcSdk.generateRandomCodeVerifier.then((codeVerifier) {
80 | TcSdk.generateCodeChallenge(codeVerifier)
81 | .then((codeChallenge) {
82 | if (codeChallenge != null) {
83 | this.codeVerifier = codeVerifier;
84 | TcSdk.setCodeChallenge(codeChallenge);
85 | TcSdk.getAuthorizationCode;
86 | } else {
87 | final snackBar = SnackBar(
88 | content: Text("Device not supported"));
89 | ScaffoldMessenger.of(context)
90 | .showSnackBar(snackBar);
91 | print("***Code challenge NULL***");
92 | }
93 | });
94 | });
95 | } else {
96 | final snackBar = SnackBar(content: Text("Not Usable"));
97 | ScaffoldMessenger.of(context).showSnackBar(snackBar);
98 | print("***Not usable***");
99 | }
100 | });
101 | },
102 | child: Text(
103 | "Initialize SDK & Get Authorization Code",
104 | style: TextStyle(color: Colors.white),
105 | ),
106 | color: Colors.blue,
107 | ),
108 | Divider(
109 | color: Colors.transparent,
110 | height: 20.0,
111 | ),
112 | StreamBuilder(
113 | stream: _stream,
114 | builder: (context, snapshot) {
115 | if (snapshot.hasData) {
116 | switch (snapshot.data!.result) {
117 | case TcSdkCallbackResult.success:
118 | return MaterialButton(
119 | color: Colors.green,
120 | child: Text(
121 | "Go to OAuth Result",
122 | style: TextStyle(color: Colors.white),
123 | ),
124 | onPressed: () {
125 | Navigator.push(
126 | context,
127 | MaterialPageRoute(
128 | builder: (context) =>
129 | OAuthResultScreen(),
130 | settings: RouteSettings(
131 | arguments: AccessTokenHelper(
132 | snapshot.data!.tcOAuthData!,
133 | codeVerifier!),
134 | ),
135 | ));
136 | });
137 | case TcSdkCallbackResult.failure:
138 | return Text(
139 | "${snapshot.data!.error!.code} : ${snapshot.data!.error!.message}");
140 | case TcSdkCallbackResult.verification:
141 | return Column(
142 | children: [
143 | Text("Verification Required : "
144 | "${snapshot.data!.error != null ? snapshot.data!.error!.code : ""}"),
145 | MaterialButton(
146 | color: Colors.green,
147 | onPressed: () {
148 | Navigator.push(
149 | context,
150 | MaterialPageRoute(
151 | builder: (context) =>
152 | NonTcVerification()));
153 | },
154 | child: Text(
155 | "Do manual verification",
156 | style: TextStyle(color: Colors.white),
157 | ),
158 | )
159 | ],
160 | );
161 | default:
162 | return Text("Invalid result");
163 | }
164 | } else
165 | return Text("");
166 | }),
167 | ],
168 | ),
169 | )),
170 | );
171 | }
172 |
173 | @override
174 | void dispose() {
175 | _stream = null;
176 | super.dispose();
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/example/lib/non_tc_screen.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | import 'dart:async';
32 |
33 | import 'package:flutter/material.dart';
34 | import 'package:flutter/services.dart';
35 | import 'package:permission_handler/permission_handler.dart';
36 | import 'package:truecaller_sdk/truecaller_sdk.dart';
37 |
38 | import 'customization/result_screen.dart';
39 |
40 | void main() {
41 | runApp(NonTcVerification());
42 | }
43 |
44 | class NonTcVerification extends StatefulWidget {
45 | @override
46 | _NonTcVerificationState createState() => _NonTcVerificationState();
47 | }
48 |
49 | class _NonTcVerificationState extends State {
50 | @override
51 | Widget build(BuildContext context) {
52 | return HomePage();
53 | }
54 | }
55 |
56 | class HomePage extends StatefulWidget {
57 | @override
58 | _HomePageState createState() => _HomePageState();
59 | }
60 |
61 | class _HomePageState extends State {
62 | bool invalidNumber = false;
63 | bool invalidFName = false;
64 | bool invalidOtp = false;
65 | bool showProgressBar = false;
66 | TextEditingController phoneController = TextEditingController();
67 | TextEditingController fNameController = TextEditingController();
68 | TextEditingController lNameController = TextEditingController();
69 | TextEditingController otpController = TextEditingController();
70 | late StreamSubscription? streamSubscription;
71 | TcSdkCallbackResult? tempResult;
72 | Timer? _timer;
73 | int? _ttl;
74 |
75 | @override
76 | void initState() {
77 | super.initState();
78 | createStreamBuilder();
79 | }
80 |
81 | bool showInputNumberView() {
82 | return tempResult == null;
83 | }
84 |
85 | bool showInputNameView() {
86 | return tempResult != null &&
87 | (tempResult == TcSdkCallbackResult.missedCallReceived ||
88 | showInputOtpView());
89 | }
90 |
91 | bool showInputOtpView() {
92 | return tempResult != null &&
93 | ((tempResult == TcSdkCallbackResult.otpInitiated) ||
94 | (tempResult == TcSdkCallbackResult.otpReceived));
95 | }
96 |
97 | bool showRetryTextView() {
98 | return _ttl != null && !showInputNumberView();
99 | }
100 |
101 | @override
102 | Widget build(BuildContext context) {
103 | final double width = MediaQuery.of(context).size.width;
104 | const double fontSize = 18.0;
105 | return Scaffold(
106 | appBar: AppBar(
107 | title: Text("Verify User Manually"),
108 | ),
109 | body: Padding(
110 | padding: EdgeInsets.all(20.0),
111 | child: Column(
112 | mainAxisAlignment: MainAxisAlignment.center,
113 | children: [
114 | Visibility(
115 | visible: showProgressBar,
116 | child: CircularProgressIndicator(
117 | strokeWidth: 6.0,
118 | backgroundColor: Colors.grey,
119 | valueColor: AlwaysStoppedAnimation(Colors.green),
120 | ),
121 | ),
122 | Visibility(
123 | visible: showInputNumberView(),
124 | child: TextField(
125 | controller: phoneController,
126 | maxLength: 10,
127 | keyboardType: TextInputType.number,
128 | inputFormatters: [FilteringTextInputFormatter.digitsOnly],
129 | style: TextStyle(color: Colors.green, fontSize: fontSize),
130 | decoration: InputDecoration(
131 | prefixText: "+91",
132 | prefixStyle:
133 | TextStyle(color: Colors.lightGreen, fontSize: fontSize),
134 | labelText: "Enter Phone number",
135 | labelStyle:
136 | TextStyle(color: Colors.black, fontSize: fontSize),
137 | hintText: "99999-99999",
138 | errorText: invalidNumber
139 | ? "Mobile Number must be of 10 digits"
140 | : null,
141 | hintStyle: TextStyle(
142 | fontStyle: FontStyle.italic,
143 | color: Colors.grey,
144 | fontSize: fontSize),
145 | ),
146 | ),
147 | ),
148 | Divider(
149 | color: Colors.transparent,
150 | height: 20.0,
151 | ),
152 | Visibility(
153 | visible: showInputNameView(),
154 | child: TextField(
155 | controller: fNameController,
156 | keyboardType: TextInputType.text,
157 | style: TextStyle(color: Colors.green, fontSize: fontSize),
158 | decoration: InputDecoration(
159 | prefixStyle:
160 | TextStyle(color: Colors.lightGreen, fontSize: fontSize),
161 | labelText: "Enter First Name",
162 | labelStyle:
163 | TextStyle(color: Colors.black, fontSize: fontSize),
164 | hintText: "John",
165 | errorText: invalidFName
166 | ? "Invalid first name. Enter min 2 characters"
167 | : null,
168 | hintStyle: TextStyle(
169 | fontStyle: FontStyle.italic,
170 | color: Colors.grey,
171 | fontSize: fontSize),
172 | ),
173 | ),
174 | ),
175 | Divider(
176 | color: Colors.transparent,
177 | height: 20.0,
178 | ),
179 | Visibility(
180 | visible: showInputNameView(),
181 | child: TextField(
182 | controller: lNameController,
183 | keyboardType: TextInputType.text,
184 | style: TextStyle(color: Colors.green, fontSize: fontSize),
185 | decoration: InputDecoration(
186 | prefixStyle:
187 | TextStyle(color: Colors.lightGreen, fontSize: fontSize),
188 | labelText: "Enter Last Name",
189 | labelStyle:
190 | TextStyle(color: Colors.black, fontSize: fontSize),
191 | hintText: "Doe",
192 | hintStyle: TextStyle(
193 | fontStyle: FontStyle.italic,
194 | color: Colors.grey,
195 | fontSize: fontSize),
196 | ),
197 | ),
198 | ),
199 | Divider(
200 | color: Colors.transparent,
201 | height: 20.0,
202 | ),
203 | Visibility(
204 | visible: showInputOtpView(),
205 | child: TextField(
206 | controller: otpController,
207 | maxLength: 6,
208 | keyboardType: TextInputType.number,
209 | inputFormatters: [FilteringTextInputFormatter.digitsOnly],
210 | style: TextStyle(color: Colors.green, fontSize: fontSize),
211 | decoration: InputDecoration(
212 | labelText: "Enter OTP",
213 | labelStyle:
214 | TextStyle(color: Colors.black, fontSize: fontSize),
215 | hintText: "123-456",
216 | errorText: invalidOtp ? "OTP must be 6 digits" : null,
217 | hintStyle: TextStyle(
218 | fontStyle: FontStyle.italic,
219 | color: Colors.grey,
220 | fontSize: fontSize),
221 | ),
222 | ),
223 | ),
224 | Divider(
225 | color: Colors.transparent,
226 | height: 20.0,
227 | ),
228 | Visibility(
229 | visible: showInputNumberView() ||
230 | showInputNameView() ||
231 | showInputOtpView(),
232 | child: MaterialButton(
233 | minWidth: width - 50.0,
234 | height: 45.0,
235 | onPressed: () => onProceedClick(),
236 | child: Text("Proceed",
237 | style: TextStyle(
238 | color: Colors.white,
239 | )),
240 | color: Colors.blue,
241 | ),
242 | ),
243 | Divider(
244 | color: Colors.transparent,
245 | height: 30.0,
246 | ),
247 | Visibility(
248 | visible: showRetryTextView(),
249 | child: _ttl == 0
250 | ? TextButton(
251 | child: Text(
252 | "verification timed out, retry again",
253 | style: TextStyle(
254 | decoration: TextDecoration.underline,
255 | color: Colors.blue),
256 | ),
257 | onPressed: () => setState(() => tempResult = null))
258 | : Text("Retry again in $_ttl seconds"),
259 | ),
260 | ],
261 | ),
262 | ),
263 | );
264 | }
265 |
266 | void startCountdownTimer(int ttl) {
267 | _ttl = ttl;
268 | const oneSec = const Duration(seconds: 1);
269 | _timer = new Timer.periodic(
270 | oneSec,
271 | (Timer timer) => setState(
272 | () {
273 | if (_ttl! < 1) {
274 | timer.cancel();
275 | showProgressBar = false;
276 | } else {
277 | _ttl = _ttl! - 1;
278 | }
279 | },
280 | ),
281 | );
282 | }
283 |
284 | void createStreamBuilder() {
285 | streamSubscription =
286 | TcSdk.streamCallbackData.listen((truecallerUserCallback) {
287 | // make sure you're changing state only after number has been entered. there could be case
288 | // where user initiated missed call, pressed back, and came to this screen again after
289 | // which the call was received and hence it would directly open input name screen.
290 | if (phoneController.text.length == 10) {
291 | setState(() {
292 | if (truecallerUserCallback.result != TcSdkCallbackResult.exception) {
293 | tempResult = truecallerUserCallback.result;
294 | }
295 | showProgressBar =
296 | tempResult == TcSdkCallbackResult.missedCallInitiated;
297 | if (tempResult == TcSdkCallbackResult.otpReceived) {
298 | otpController.text = truecallerUserCallback.otp!;
299 | }
300 | });
301 | }
302 |
303 | switch (truecallerUserCallback.result) {
304 | case TcSdkCallbackResult.missedCallInitiated:
305 | startCountdownTimer(
306 | double.parse(truecallerUserCallback.ttl!).floor());
307 | showSnackBar(
308 | "Missed call Initiated with TTL : ${truecallerUserCallback.ttl} && "
309 | "requestNonce = ${truecallerUserCallback.requestNonce}");
310 | break;
311 | case TcSdkCallbackResult.missedCallReceived:
312 | showSnackBar("Missed call Received");
313 | break;
314 | case TcSdkCallbackResult.otpInitiated:
315 | startCountdownTimer(
316 | double.parse(truecallerUserCallback.ttl!).floor());
317 | showSnackBar(
318 | "OTP Initiated with TTL : ${truecallerUserCallback.ttl} && "
319 | "requestNonce = ${truecallerUserCallback.requestNonce}");
320 | break;
321 | case TcSdkCallbackResult.otpReceived:
322 | showSnackBar("OTP Received : ${truecallerUserCallback.otp}");
323 | break;
324 | case TcSdkCallbackResult.verificationComplete:
325 | showSnackBar(
326 | "Verification Completed : ${truecallerUserCallback.accessToken} && "
327 | "requestNonce = ${truecallerUserCallback.requestNonce}");
328 | _navigateToResult(fNameController.text);
329 | break;
330 | case TcSdkCallbackResult.verifiedBefore:
331 | showSnackBar(
332 | "Verified Before : ${truecallerUserCallback.profile!.accessToken} && "
333 | "requestNonce = ${truecallerUserCallback.profile!.requestNonce}");
334 | _navigateToResult(truecallerUserCallback.profile!.firstName);
335 | break;
336 | case TcSdkCallbackResult.exception:
337 | showSnackBar("Exception : ${truecallerUserCallback.exception!.code}, "
338 | "${truecallerUserCallback.exception!.message}");
339 | break;
340 | default:
341 | print(tempResult.toString());
342 | break;
343 | }
344 | });
345 | }
346 |
347 | void showSnackBar(String message) {
348 | final snackBar = SnackBar(content: Text(message));
349 | ScaffoldMessenger.of(context).showSnackBar(snackBar);
350 | }
351 |
352 | _navigateToResult(String firstName) {
353 | Navigator.pushReplacement(
354 | context,
355 | MaterialPageRoute(
356 | builder: (context) => ResultScreen(firstName),
357 | ));
358 | }
359 |
360 | Future onProceedClick() async {
361 | if (showInputNumberView() && validateNumber()) {
362 | try {
363 | if (await Permission.phone.request().isGranted) {
364 | await TcSdk.requestVerification(phoneNumber: phoneController.text);
365 | setProgressBarToActive();
366 | } else if (await Permission.phone.isPermanentlyDenied) {
367 | openAppSettings();
368 | } else {
369 | showSnackBar("Please grant all the permissions to proceed");
370 | }
371 | } on PlatformException catch (exception) {
372 | showSnackBar(exception.message.toString());
373 | } catch (exception) {
374 | showSnackBar(exception.toString());
375 | }
376 | } else if (tempResult == TcSdkCallbackResult.missedCallReceived &&
377 | validateName()) {
378 | setProgressBarToActive();
379 | TcSdk.verifyMissedCall(
380 | firstName: fNameController.text, lastName: lNameController.text);
381 | } else if ((tempResult == TcSdkCallbackResult.otpInitiated ||
382 | tempResult == TcSdkCallbackResult.otpReceived) &&
383 | validateName() &&
384 | validateOtp()) {
385 | setProgressBarToActive();
386 | TcSdk.verifyOtp(
387 | firstName: fNameController.text,
388 | lastName: lNameController.text,
389 | otp: otpController.text);
390 | }
391 | }
392 |
393 | void setProgressBarToActive() {
394 | setState(() {
395 | showProgressBar = true;
396 | });
397 | }
398 |
399 | bool validateNumber() {
400 | String phoneNumber = phoneController.text;
401 | setState(() {
402 | phoneNumber.length != 10 ? invalidNumber = true : invalidNumber = false;
403 | });
404 | return !invalidNumber;
405 | }
406 |
407 | bool validateOtp() {
408 | String otp = otpController.text;
409 | setState(() {
410 | otp.length != 6 ? invalidOtp = true : invalidOtp = false;
411 | });
412 | return !invalidOtp;
413 | }
414 |
415 | bool validateName() {
416 | String fName = fNameController.text;
417 | setState(() {
418 | fName.length < 2 ? invalidFName = true : invalidFName = false;
419 | });
420 | return !invalidFName;
421 | }
422 |
423 | @override
424 | void dispose() {
425 | phoneController.dispose();
426 | fNameController.dispose();
427 | lNameController.dispose();
428 | otpController.dispose();
429 | streamSubscription?.cancel();
430 | _timer?.cancel();
431 | super.dispose();
432 | }
433 | }
434 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: truecaller_sdk_example
2 | description: Demonstrates how to use the truecaller_sdk plugin.
3 |
4 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
5 |
6 | environment:
7 | sdk: '>=2.12.0 <3.0.0'
8 |
9 | dependencies:
10 | dio: ^5.3.2
11 | permission_handler: ^11.0.1
12 | uuid: ^4.1.0
13 | flutter:
14 | sdk: flutter
15 |
16 | truecaller_sdk:
17 | # When depending on this package from a real application you should use:
18 | # truecaller_sdk: ^x.y.z
19 | # See https://dart.dev/tools/pub/dependencies#version-constraints
20 | # The example app is bundled with the plugin so we use a path dependency on
21 | # the parent directory to use the current plugin's version.
22 | path: ../
23 |
24 | dev_dependencies:
25 | flutter_test:
26 | sdk: flutter
27 |
28 | flutter:
29 | uses-material-design: true
30 |
--------------------------------------------------------------------------------
/example/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | // This is a basic Flutter widget test.
32 | //
33 | // To perform an interaction with a widget in your test, use the WidgetTester
34 | // utility that Flutter provides. For example, you can send tap and scroll
35 | // gestures. You can also use WidgetTester to find child widgets in the widget
36 | // tree, read text, and verify that the values of widget properties are correct.
37 |
38 | import 'package:flutter/material.dart';
39 | import 'package:flutter_test/flutter_test.dart';
40 | import 'package:truecaller_sdk_example/main.dart';
41 |
42 | void main() {
43 | testWidgets('Verify Platform version', (WidgetTester tester) async {
44 | // Build our app and trigger a frame.
45 | await tester.pumpWidget(MyApp());
46 |
47 | // Verify that platform version is retrieved.
48 | expect(
49 | find.byWidgetPredicate(
50 | (Widget widget) =>
51 | widget is Text && widget.data!.startsWith('Running on:'),
52 | ),
53 | findsOneWidget,
54 | );
55 | });
56 | }
57 |
--------------------------------------------------------------------------------
/images/main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/images/main.jpg
--------------------------------------------------------------------------------
/images/main_customization_screen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/images/main_customization_screen.jpg
--------------------------------------------------------------------------------
/images/truecaller_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/images/truecaller_logo.png
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/Generated.xcconfig
37 | /Flutter/flutter_export_environment.sh
--------------------------------------------------------------------------------
/ios/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/truecaller/flutter-sdk/77c6bce3bca56028295e6987f843e7d4ff5bbda9/ios/Assets/.gitkeep
--------------------------------------------------------------------------------
/ios/Classes/Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Constants.swift
3 | // truecaller_sdk
4 | //
5 | // Created by Sreedeepkesav M S on 02/03/22.
6 | //
7 |
8 | import Foundation
9 |
10 | struct Constants {
11 | struct ChannelNames {
12 | static let methodChannel = "tc_method_channel"
13 | static let eventChannel = "tc_event_channel"
14 | }
15 |
16 | struct String {
17 | static let data = "data"
18 | static let result = "result"
19 | static let success = "success"
20 | static let failure = "failure"
21 | }
22 |
23 | struct Error {
24 | static let methodNotImplemented = "Method not implemented"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ios/Classes/Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Extensions.swift
3 | // truecaller_sdk
4 | //
5 | // Created by Sreedeepkesav M S on 02/03/22.
6 | //
7 |
8 | import Foundation
9 | import TrueSDK
10 |
11 | extension TCTrueProfileResponse {
12 | var toDict: [String: AnyHashable] {
13 | var dict = [String: AnyHashable]()
14 | dict["payload"] = payload
15 | dict["signature"] = signature
16 | dict["signatureAlgorithm"] = signatureAlgorithm
17 | dict["requestNonce"] = requestNonce
18 | return dict
19 | }
20 | }
21 |
22 | extension TCTrueProfile {
23 | var toDict: [String: AnyHashable] {
24 | var dict = [String: AnyHashable]()
25 | dict["firstName"] = firstName
26 | dict["lastName"] = lastName
27 | dict["isVerified"] = isVerified
28 | dict["isAmbassador"] = isAmbassador
29 | dict["phoneNumber"] = phoneNumber
30 | dict["countryCode"] = countryCode
31 | dict["street"] = street
32 | dict["city"] = city
33 | dict["facebookID"] = facebookID
34 | dict["twitterID"] = twitterID
35 | dict["email"] = email
36 | dict["url"] = url
37 | dict["avatarURL"] = avatarURL
38 | dict["jobTitle"] = jobTitle
39 | dict["companyName"] = companyName
40 | dict["requestTime"] = requestTime
41 | dict["genderValue"] = gender.rawValue
42 | return dict
43 | }
44 | }
45 |
46 | extension TCError {
47 | var toDict: [String: AnyHashable] {
48 | var dict = [String: AnyHashable]()
49 | dict["code"] = getCode()
50 | dict["message"] = description
51 | return dict
52 | }
53 | }
54 |
55 | extension Dictionary {
56 | var tojsonString: String? {
57 | guard let data = try? JSONSerialization.data(withJSONObject: self) else {
58 | return nil
59 | }
60 |
61 | return String(data: data, encoding: .utf8)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ios/Classes/SwiftTruecallerSdkPlugin.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import TrueSDK
4 |
5 | private enum MethodCalls: String {
6 | case initiateSDK
7 | case isUsable
8 | case setDarkTheme
9 | case setLocale
10 | case getProfile
11 | case requestVerification
12 | case verifyOtp
13 | case verifyMissedCall
14 | }
15 |
16 | public class SwiftTruecallerSdkPlugin: NSObject,
17 | FlutterPlugin {
18 | private var mainChannel: FlutterMethodChannel?
19 | private var eventChannel: FlutterEventChannel?
20 | private var eventSink: FlutterEventSink?
21 |
22 | private var trueSdk = TCTrueSDK.sharedManager()
23 |
24 | public static func register(with registrar: FlutterPluginRegistrar) {
25 | _ = SwiftTruecallerSdkPlugin(with: registrar)
26 | }
27 |
28 | private var trueProfileResponse: TCTrueProfileResponse?
29 |
30 | init(with registrar: FlutterPluginRegistrar) {
31 | super.init()
32 |
33 | addMainChannel(registrar: registrar)
34 | addEventChannel(registrar: registrar)
35 | registrar.addApplicationDelegate(self)
36 | }
37 |
38 | private func addMainChannel(registrar: FlutterPluginRegistrar) {
39 | mainChannel = FlutterMethodChannel(name: Constants.ChannelNames.methodChannel,
40 | binaryMessenger: registrar.messenger())
41 | guard let mainChannel = mainChannel else {
42 | return
43 | }
44 | registrar.addMethodCallDelegate(self, channel: mainChannel)
45 | }
46 |
47 | private func addEventChannel(registrar: FlutterPluginRegistrar) {
48 | eventChannel = FlutterEventChannel(name: Constants.ChannelNames.eventChannel,
49 | binaryMessenger: registrar.messenger())
50 | guard let eventChannel = eventChannel else {
51 | return
52 | }
53 | eventChannel.setStreamHandler(self)
54 | }
55 |
56 | public func handle(_ call: FlutterMethodCall,
57 | result: @escaping FlutterResult) {
58 | let method = MethodCalls(rawValue: call.method)
59 | switch method {
60 | case .initiateSDK:
61 | trueSdk.delegate = self
62 | result(true)
63 | case .isUsable:
64 | result(trueSdk.isSupported())
65 | case .setDarkTheme,
66 | .setLocale,
67 | .requestVerification,
68 | .verifyOtp,
69 | .verifyMissedCall:
70 | result(Constants.Error.methodNotImplemented)
71 | case .getProfile:
72 | trueSdk.requestTrueProfile()
73 | case .none:
74 | result(Constants.Error.methodNotImplemented)
75 | }
76 | }
77 | }
78 |
79 | // MARK: - App delegate methods -
80 |
81 | extension SwiftTruecallerSdkPlugin {
82 | public func application(_ application: UIApplication,
83 | continue userActivity: NSUserActivity,
84 | restorationHandler: @escaping ([Any]) -> Void) -> Bool {
85 | return TCTrueSDK.sharedManager().application(application,
86 | continue: userActivity,
87 | restorationHandler: restorationHandler as? ([Any]?) -> Void)
88 | }
89 |
90 | public func application(_ app: UIApplication,
91 | open url: URL,
92 | options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
93 | return TCTrueSDK.sharedManager().continue(withUrlScheme: url)
94 | }
95 | }
96 |
97 | // MARK: - FlutterStreamHandler -
98 |
99 | extension SwiftTruecallerSdkPlugin: FlutterStreamHandler {
100 | public func onListen(withArguments arguments: Any?,
101 | eventSink events: @escaping FlutterEventSink) -> FlutterError? {
102 | self.eventSink = events
103 | return nil
104 | }
105 |
106 | public func onCancel(withArguments arguments: Any?) -> FlutterError? {
107 | self.eventSink = nil
108 | return nil
109 | }
110 | }
111 |
112 | // MARK: - TCTrueSDKDelegate -
113 |
114 | extension SwiftTruecallerSdkPlugin: TCTrueSDKDelegate {
115 | public func didReceive(_ profile: TCTrueProfile) {
116 | var map = [String: Any]()
117 | map[Constants.String.result] = Constants.String.success
118 | var data = profile.toDict
119 | if let response = trueProfileResponse {
120 | data = data.merging(response.toDict) { $1 }
121 | trueProfileResponse = nil
122 | }
123 | map[Constants.String.data] = data.tojsonString
124 | eventSink?(map)
125 | }
126 |
127 | public func didReceive(_ profileResponse: TCTrueProfileResponse) {
128 | trueProfileResponse = profileResponse
129 | }
130 |
131 | public func didFailToReceiveTrueProfileWithError(_ error: TCError) {
132 | var map = [String: Any]()
133 | map[Constants.String.result] = Constants.String.failure
134 | map[Constants.String.data] = error.toDict.tojsonString
135 | trueProfileResponse = nil
136 | eventSink?(error)
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/ios/Classes/TruecallerSdkPlugin.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface TruecallerSdkPlugin : NSObject
4 | @end
5 |
--------------------------------------------------------------------------------
/ios/Classes/TruecallerSdkPlugin.m:
--------------------------------------------------------------------------------
1 | #import "TruecallerSdkPlugin.h"
2 | #if __has_include()
3 | #import
4 | #else
5 | // Support project import fallback if the generated compatibility header
6 | // is not copied when this plugin is created as a library.
7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
8 | #import "truecaller_sdk-Swift.h"
9 | #endif
10 |
11 | @implementation TruecallerSdkPlugin
12 | + (void)registerWithRegistrar:(NSObject*)registrar {
13 | [SwiftTruecallerSdkPlugin registerWithRegistrar:registrar];
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/ios/truecaller_sdk.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint truecaller_sdk.podspec' to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'truecaller_sdk'
7 | s.version = '0.0.1'
8 | s.summary = 'A Flutter plugin that uses Truecaller Android SDK for signing in with Phone numbers'
9 | s.description = <<-DESC
10 | A Flutter plugin that uses Truecaller Android SDK for signing in with Phone numbers
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 | s.source = { :path => '.' }
16 | s.source_files = 'Classes/**/*'
17 | s.dependency 'Flutter'
18 | s.dependency 'TrueSDK'
19 | s.platform = :ios, '9.0'
20 |
21 | # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
22 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
23 | s.swift_version = '5.0'
24 | end
25 |
--------------------------------------------------------------------------------
/lib/src/scope_options.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | /// scope options that are used to customize the consent screen UI
32 | class TcSdkOptions {
33 | /// secondary cta text options
34 | static const int FOOTER_TYPE_SKIP = 1;
35 | static const int FOOTER_TYPE_ANOTHER_MOBILE_NO = 2;
36 | static const int FOOTER_TYPE_ANOTHER_METHOD = 4;
37 | static const int FOOTER_TYPE_MANUALLY = 8;
38 | static const int FOOTER_TYPE_LATER = 16;
39 |
40 | /// sdk options
41 | static const int OPTION_VERIFY_ONLY_TC_USERS = 32;
42 | static const int OPTION_VERIFY_ALL_USERS = 64;
43 |
44 | /// button shape options
45 | static const int BUTTON_SHAPE_ROUNDED = 128;
46 | static const int BUTTON_SHAPE_RECTANGLE = 256;
47 |
48 | /// heading options
49 | static const int SDK_CONSENT_HEADING_LOG_IN_TO = 0;
50 | static const int SDK_CONSENT_HEADING_SIGN_UP_WITH = 1;
51 | static const int SDK_CONSENT_HEADING_SIGN_IN_TO = 2;
52 | static const int SDK_CONSENT_HEADING_VERIFY_NUMBER_WITH = 3;
53 | static const int SDK_CONSENT_HEADING_REGISTER_WITH = 4;
54 | static const int SDK_CONSENT_HEADING_GET_STARTED_WITH = 5;
55 | static const int SDK_CONSENT_HEADING_PROCEED_WITH = 6;
56 | static const int SDK_CONSENT_HEADING_VERIFY_WITH = 7;
57 | static const int SDK_CONSENT_HEADING_VERIFY_PROFILE_WITH = 8;
58 | static const int SDK_CONSENT_HEADING_VERIFY_YOUR_PROFILE_WITH = 9;
59 | static const int SDK_CONSENT_HEADING_VERIFY_PHONE_NO_WITH = 10;
60 | static const int SDK_CONSENT_HEADING_VERIFY_YOUR_NO_WITH = 11;
61 | static const int SDK_CONSENT_HEADING_CONTINUE_WITH = 12;
62 | static const int SDK_CONSENT_HEADING_COMPLETE_ORDER_WITH = 13;
63 | static const int SDK_CONSENT_HEADING_PLACE_ORDER_WITH = 14;
64 | static const int SDK_CONSENT_HEADING_COMPLETE_BOOKING_WITH = 15;
65 | static const int SDK_CONSENT_HEADING_CHECKOUT_WITH = 16;
66 | static const int SDK_CONSENT_HEADING_MANAGE_DETAILS_WITH = 17;
67 | static const int SDK_CONSENT_HEADING_MANAGE_YOUR_DETAILS_WITH = 18;
68 | static const int SDK_CONSENT_HEADING_LOGIN_TO_WITH_ONE_TAP = 19;
69 | static const int SDK_CONSENT_HEADING_SUBSCRIBE_TO = 20;
70 | static const int SDK_CONSENT_HEADING_GET_UPDATES_FROM = 21;
71 | static const int SDK_CONSENT_HEADING_CONTINUE_READING_ON = 22;
72 | static const int SDK_CONSENT_HEADING_GET_NEW_UPDATES_FROM = 23;
73 | static const int SDK_CONSENT_HEADING_LOGIN_SIGNUP_WITH = 24;
74 |
75 | /// login text prefix options
76 | static const int LOGIN_TEXT_PREFIX_TO_GET_STARTED = 0;
77 | static const int LOGIN_TEXT_PREFIX_TO_CONTINUE = 1;
78 | static const int LOGIN_TEXT_PREFIX_TO_PLACE_ORDER = 2;
79 | static const int LOGIN_TEXT_PREFIX_TO_COMPLETE_YOUR_PURCHASE = 3;
80 | static const int LOGIN_TEXT_PREFIX_TO_CHECKOUT = 4;
81 | static const int LOGIN_TEXT_PREFIX_TO_COMPLETE_YOUR_BOOKING = 5;
82 | static const int LOGIN_TEXT_PREFIX_TO_PROCEED_WITH_YOUR_BOOKING = 6;
83 | static const int LOGIN_TEXT_PREFIX_TO_CONTINUE_WITH_YOUR_BOOKING = 7;
84 | static const int LOGIN_TEXT_PREFIX_TO_GET_DETAILS = 8;
85 | static const int LOGIN_TEXT_PREFIX_TO_VIEW_MORE = 9;
86 | static const int LOGIN_TEXT_PREFIX_TO_CONTINUE_READING = 10;
87 | static const int LOGIN_TEXT_PREFIX_TO_PROCEED = 11;
88 | static const int LOGIN_TEXT_PREFIX_FOR_NEW_UPDATES = 12;
89 | static const int LOGIN_TEXT_PREFIX_TO_GET_UPDATES = 13;
90 | static const int LOGIN_TEXT_PREFIX_TO_SUBSCRIBE = 14;
91 | static const int LOGIN_TEXT_PREFIX_TO_SUBSCRIBE_AND_GET_UPDATES = 15;
92 |
93 | /// primary cta text prefix options
94 | static const int CTA_TEXT_PROCEED = 0;
95 | static const int CTA_TEXT_CONTINUE = 1;
96 | static const int CTA_TEXT_ACCEPT = 2;
97 | static const int CTA_TEXT_CONFIRM = 3;
98 | static const int CTA_TEXT_USE = 4;
99 | static const int CTA_TEXT_CONTINUE_WITH = 5;
100 | static const int CTA_TEXT_PROCEED_WITH = 6;
101 | }
102 |
--------------------------------------------------------------------------------
/lib/src/truecaller.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | import 'dart:collection';
32 | import 'dart:convert';
33 |
34 | import 'package:flutter/services.dart';
35 |
36 | import 'scope_options.dart';
37 | import 'truecaller_callback.dart';
38 |
39 | class TcSdk {
40 | static const MethodChannel _methodChannel =
41 | const MethodChannel('tc_method_channel');
42 | static const EventChannel _eventChannel =
43 | const EventChannel('tc_event_channel');
44 | static Stream? _callbackStream;
45 |
46 | /// This method has to be called before anything else. It initializes the SDK with the
47 | /// customizable options which are all optional and have default values as set below in the method
48 | ///
49 | /// [sdkOption] determines whether you want to use the SDK for verifying -
50 | /// 1. [TcSdkOptions.OPTION_VERIFY_ONLY_TC_USERS] i.e only Truecaller users
51 | /// 2. [TcSdkOptions.OPTION_VERIFY_ALL_USERS] i.e both Truecaller and Non-Truecaller users
52 | ///
53 | /// [consentHeadingOption] determines the heading of the consent screen.
54 | /// [ctaText] determines prefix text in login/primary button
55 | /// [footerType] determines the footer button/secondary button text.
56 | /// [buttonShapeOption] to set login button shape
57 | /// [buttonColor] to set login button color
58 | /// [buttonTextColor] to set login button text color
59 | static initializeSDK(
60 | {required int sdkOption,
61 | int consentHeadingOption = TcSdkOptions.SDK_CONSENT_HEADING_LOG_IN_TO,
62 | int footerType = TcSdkOptions.FOOTER_TYPE_ANOTHER_MOBILE_NO,
63 | int ctaText = TcSdkOptions.CTA_TEXT_PROCEED,
64 | int buttonShapeOption = TcSdkOptions.BUTTON_SHAPE_ROUNDED,
65 | int? buttonColor,
66 | int? buttonTextColor}) async =>
67 | await _methodChannel.invokeMethod('initializeSDK', {
68 | "sdkOption": sdkOption,
69 | "consentHeadingOption": consentHeadingOption,
70 | "footerType": footerType,
71 | "ctaText": ctaText,
72 | "buttonShapeOption": buttonShapeOption,
73 | "buttonColor": buttonColor,
74 | "buttonTextColor": buttonTextColor,
75 | });
76 |
77 | /// Once you initialise the Truecaller SDK using the [initializeSDK] method, and if you are using
78 | /// the SDK for verification of only Truecaller users ( by setting the sdkOptions scope as
79 | /// [TcSdkOptions.OPTION_VERIFY_ONLY_TC_USERS], you can check if the Truecaller app is
80 | /// present on the user's device and whether the user has a valid account state or not and
81 | /// whether the OAuth flow is supported or not using the following method
82 | static Future get isOAuthFlowUsable async =>
83 | _methodChannel.invokeMethod('isOAuthFlowUsable');
84 |
85 | /// After checking [isUsable], you can invoke Truecaller's OAuth consent screen dialog
86 | /// in your app flow by calling the following method
87 | /// The result will be returned asynchronously via [streamCallbackData] stream
88 | static get getAuthorizationCode async =>
89 | await _methodChannel.invokeMethod('getAuthorizationCode');
90 |
91 | /// Once you call [getAuthorizationCode], you can listen to this stream to determine the result of the
92 | /// action taken by the user.
93 | /// [TcSdkCallbackResult.success] means the result is successful and you can now fetch
94 | /// the user's access token using the authorization code from [TcSdkCallback.tcOAuthData]
95 | /// [TcSdkCallbackResult.failure] means the result is failure and you can now fetch
96 | /// the result of failure from [TcSdkCallback.error]
97 | /// [TcSdkCallbackResult.verification] will be returned only when using
98 | /// [TcSdkOptions.OPTION_VERIFY_ALL_USERS] which indicates to verify the user manually
99 | static Stream get streamCallbackData {
100 | if (_callbackStream == null) {
101 | _callbackStream =
102 | _eventChannel.receiveBroadcastStream().map((value) {
103 | TcSdkCallback callback = new TcSdkCallback();
104 | var resultHashMap = HashMap.from(value);
105 | final String? result = resultHashMap["result"];
106 | switch (result.enumValue()) {
107 | case TcSdkCallbackResult.success:
108 | callback.result = TcSdkCallbackResult.success;
109 | _insertOAuthData(callback, resultHashMap["data"]!);
110 | break;
111 | case TcSdkCallbackResult.failure:
112 | callback.result = TcSdkCallbackResult.failure;
113 | _insertError(callback, resultHashMap["data"]);
114 | break;
115 | case TcSdkCallbackResult.verification:
116 | callback.result = TcSdkCallbackResult.verification;
117 | _insertError(callback, resultHashMap["data"]);
118 | break;
119 | case TcSdkCallbackResult.missedCallInitiated:
120 | callback.result = TcSdkCallbackResult.missedCallInitiated;
121 | CallbackData data = _insertData(callback, resultHashMap["data"]!);
122 | callback.ttl = data.ttl;
123 | callback.requestNonce = data.requestNonce;
124 | break;
125 | case TcSdkCallbackResult.missedCallReceived:
126 | callback.result = TcSdkCallbackResult.missedCallReceived;
127 | break;
128 | case TcSdkCallbackResult.otpInitiated:
129 | callback.result = TcSdkCallbackResult.otpInitiated;
130 | CallbackData data = _insertData(callback, resultHashMap["data"]!);
131 | callback.ttl = data.ttl;
132 | callback.requestNonce = data.requestNonce;
133 | break;
134 | case TcSdkCallbackResult.otpReceived:
135 | callback.result = TcSdkCallbackResult.otpReceived;
136 | CallbackData data = _insertData(callback, resultHashMap["data"]!);
137 | callback.otp = data.otp;
138 | break;
139 | case TcSdkCallbackResult.verifiedBefore:
140 | callback.result = TcSdkCallbackResult.verifiedBefore;
141 | CallbackData data = _insertData(callback, resultHashMap["data"]!);
142 | _insertProfile(callback, data.profile!);
143 | break;
144 | case TcSdkCallbackResult.verificationComplete:
145 | callback.result = TcSdkCallbackResult.verificationComplete;
146 | CallbackData data = _insertData(callback, resultHashMap["data"]!);
147 | callback.accessToken = data.accessToken;
148 | callback.requestNonce = data.requestNonce;
149 | break;
150 | case TcSdkCallbackResult.exception:
151 | callback.result = TcSdkCallbackResult.exception;
152 | Map exceptionMap = jsonDecode(resultHashMap["data"]!);
153 | TruecallerException exception = TruecallerException.fromJson(
154 | exceptionMap as Map);
155 | callback.exception = exception;
156 | break;
157 | default:
158 | throw PlatformException(
159 | code: "1010",
160 | message: "${resultHashMap["result"]} is not a valid result");
161 | }
162 | return callback;
163 | });
164 | }
165 | return _callbackStream!;
166 | }
167 |
168 | static CallbackData _insertData(TcSdkCallback callback, String data) {
169 | Map dataMap = jsonDecode(data);
170 | return CallbackData.fromJson(dataMap as Map);
171 | }
172 |
173 | static _insertOAuthData(TcSdkCallback callback, String data) {
174 | Map oAuthDataMap = jsonDecode(data);
175 | TcOAuthData tcOAuthData =
176 | TcOAuthData.fromJson(oAuthDataMap as Map);
177 | callback.tcOAuthData = tcOAuthData;
178 | }
179 |
180 | static _insertProfile(TcSdkCallback callback, String data) {
181 | Map profileMap = jsonDecode(data);
182 | TruecallerUserProfile profile =
183 | TruecallerUserProfile.fromJson(profileMap as Map);
184 | callback.profile = profile;
185 | }
186 |
187 | static _insertError(TcSdkCallback callback, String? data) {
188 | // onVerificationRequired has nullable error, hence null check
189 | if (data != null &&
190 | data.trim().isNotEmpty &&
191 | data.trim().toLowerCase() != "null") {
192 | Map errorMap = jsonDecode(data);
193 | TcOAuthError tcOAuthError =
194 | TcOAuthError.fromJson(errorMap as Map);
195 | callback.error = tcOAuthError;
196 | }
197 | }
198 |
199 | /// This utility method generates a random code verifier string using SecureRandom as the
200 | /// source of entropy with 64 as the default entropy quantity.
201 | /// You can either generate your own code verifier or use this utility method to generate one
202 | /// for you.
203 | /// NOTE: Store the code verifier in the current session since it would be required later
204 | /// to generate the access token.
205 | static Future get generateRandomCodeVerifier async =>
206 | _methodChannel.invokeMethod('generateRandomCodeVerifier');
207 |
208 | /// This utility method produces a code challenge from the supplied code verifier[codeVerifier]
209 | /// using SHA-256 as the challenge method and Base64 as encoding if the system supports it.
210 | /// NOTE: All Android devices should ideally support SHA-256 and Base64, but in rare case if
211 | /// the doesn't, then this method would return null meaning that you can’t proceed further.
212 | /// Please ensure to have a null safe check for such cases.
213 | static Future generateCodeChallenge(String codeVerifier) async =>
214 | _methodChannel.invokeMethod(
215 | 'generateCodeChallenge', {"codeVerifier": codeVerifier});
216 |
217 | /// Set your own code challenge or use the utility method [generateRandomCodeVerifier] to generate
218 | /// one for you and set it via [codeChallenge] to this method
219 | /// Set it before calling [getAuthorizationCode]
220 | static setCodeChallenge(String codeChallenge) async => await _methodChannel
221 | .invokeMethod('setCodeChallenge', {"codeChallenge": codeChallenge});
222 |
223 | /// Set the list of scopes to be requested using [scopes].
224 | /// Set it before calling [getAuthorizationCode]
225 | static setOAuthScopes(List scopes) async =>
226 | await _methodChannel.invokeMethod('setOAuthScopes', {"scopes": scopes});
227 |
228 | /// Set a unique state parameter [oAuthState] & store it in the current session to use it later in the
229 | /// onSuccess() callback method of the [TcOAuthCallback] to match if the state received from the
230 | /// authorization server is the same as set here to prevent request forgery attacks.
231 | /// Set it before calling [getAuthorizationCode]
232 | static setOAuthState(String oAuthState) async => await _methodChannel
233 | .invokeMethod('setOAuthState', {"oAuthState": oAuthState});
234 |
235 | /// Customise the consent screen dialog in any of the supported Indian languages by supplying
236 | /// [locale] to the method.
237 | /// NOTE: Default value is en
238 | /// Set it before calling [getAuthorizationCode]
239 | static setLocale(String locale) async =>
240 | await _methodChannel.invokeMethod('setLocale', {"locale": locale});
241 |
242 | /// This method will initiate manual verification of [phoneNumber] asynchronously for Indian
243 | /// numbers only so that's why default countryISO is set to "IN".
244 | /// The result will be returned asynchronously via [streamCallbackData] stream
245 | /// Check [TcSdkCallbackResult] to understand the different verifications states.
246 | /// This method may lead to verification with a SMS Code (OTP) or verification with a CALL,
247 | /// or if the user is already verified on the device, will get the call back as
248 | /// [TcSdkCallbackResult.verifiedBefore] in [streamCallbackData]
249 | static requestVerification(
250 | {required String phoneNumber, String countryISO = "IN"}) async =>
251 | await _methodChannel.invokeMethod(
252 | 'requestVerification', {"ph": phoneNumber, "ci": countryISO});
253 |
254 | /// Call this method after [requestVerification] to complete the verification if the number has
255 | /// to be verified with a missed call.
256 | /// i.e call this method only when you receive [TcSdkCallbackResult.missedCallReceived]
257 | /// in [streamCallbackData].
258 | /// To complete verification, it is mandatory to pass [firstName] and [lastName] of the user
259 | static verifyMissedCall(
260 | {required String firstName, required String lastName}) async =>
261 | await _methodChannel.invokeMethod(
262 | 'verifyMissedCall', {"fname": firstName, "lname": lastName});
263 |
264 | /// Call this method after [requestVerification] to complete the verification if the number has
265 | /// to be verified with an OTP.
266 | /// i.e call this method when you receive either [TcSdkCallbackResult.otpInitiated] or
267 | /// [TcSdkCallbackResult.otpReceived] in [streamCallbackData].
268 | /// To complete verification, it is mandatory to pass [firstName] and [lastName] of the user
269 | /// with the [otp] code received over SMS
270 | static verifyOtp(
271 | {required String firstName,
272 | required String lastName,
273 | required String otp}) async =>
274 | await _methodChannel.invokeMethod(
275 | 'verifyOtp', {"fname": firstName, "lname": lastName, "otp": otp});
276 | }
277 |
--------------------------------------------------------------------------------
/lib/src/truecaller_callback.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | /// callback stream that gets returned from [TcSdk.streamCallbackData]
32 | class TcSdkCallback {
33 | late TcSdkCallbackResult result;
34 |
35 | //for tc-flow
36 |
37 | /// received when [result] equals [TcSdkCallbackResult.success]
38 | TcOAuthData? tcOAuthData;
39 |
40 | /// received when [result] equals [TcSdkCallbackResult.failure] or
41 | /// [result] equals [TcSdkCallbackResult.verification]
42 | /// It indicates reason why Truecaller user verification failed
43 | TcOAuthError? error;
44 |
45 | //for non-tc flow
46 |
47 | /// received when [result] equals [TcSdkCallbackResult.verifiedBefore]
48 | TruecallerUserProfile? profile;
49 |
50 | /// received when [result] equals [TcSdkCallbackResult.otpReceived]
51 | String? otp;
52 |
53 | /// received when [result] equals [TcSdkCallbackResult.verificationComplete]
54 | /// It can be used for server-side response validation
55 | String? accessToken;
56 |
57 | /// TTL(in sec) received when [result] equals either [TcSdkCallbackResult.otpInitiated]
58 | /// or [result] equals [TcSdkCallbackResult.missedCallInitiated]
59 | /// It indicates time left to complete the user verification process
60 | String? ttl;
61 |
62 | /// Request Nonce received when [result] equals either [TcSdkCallbackResult.otpInitiated]
63 | /// or [TcSdkCallbackResult.missedCallInitiated]
64 | /// or [TcSdkCallbackResult.verificationComplete]
65 | /// It can be used to verify whether the custom request identifier (if set) during SDK
66 | /// initialization is same as this one received in response which essentially assures a
67 | /// correlation between the request and the response
68 | String? requestNonce;
69 |
70 | /// received when [result] equals [TcSdkCallbackResult.exception]
71 | /// It indicates reason why non-truecaller user verification failed
72 | TruecallerException? exception;
73 | }
74 |
75 | /// enum with callback results that corresponds to the [TcSdkCallback.result]
76 | enum TcSdkCallbackResult {
77 | //tc user callback results
78 | success,
79 | failure,
80 | verification,
81 |
82 | //non-tc user callback results
83 | missedCallInitiated,
84 | missedCallReceived,
85 | otpInitiated,
86 | otpReceived,
87 | verifiedBefore,
88 | verificationComplete,
89 | exception
90 | }
91 |
92 | /// extension method that converts String to corresponding enum value
93 | extension EnumParser on String? {
94 | TcSdkCallbackResult? enumValue() {
95 | return TcSdkCallbackResult.values.firstWhere((element) =>
96 | element.toString().split(".")[1].toLowerCase() == this!.toLowerCase());
97 | }
98 | }
99 |
100 | /// OAuth data that corresponds to [TcSdkCallback.tcOAuthData]
101 | class TcOAuthData {
102 | late String authorizationCode;
103 | late String state;
104 | late List scopesGranted;
105 |
106 | /// get the [TcOAuthData] values from Json
107 | TcOAuthData.fromJson(Map map) {
108 | authorizationCode = map['authorizationCode'];
109 | state = map['state'];
110 | scopesGranted = map['scopesGranted'];
111 | }
112 | }
113 |
114 | /// user profile that corresponds to [TcSdkCallback.profile]
115 | class TruecallerUserProfile {
116 | String firstName;
117 | String? lastName;
118 | String phoneNumber;
119 | String? gender;
120 | String? street;
121 | String? city;
122 | String? zipcode;
123 | String? countryCode;
124 | String? facebookId;
125 | String? twitterId;
126 | String? email;
127 | String? url;
128 | String? avatarUrl;
129 | bool? isTrueName;
130 | bool? isAmbassador;
131 | String? companyName;
132 | String? jobTitle;
133 | String? payload;
134 | String? signature;
135 | String? signatureAlgorithm;
136 | String? requestNonce;
137 | bool? isSimChanged;
138 | String? verificationMode;
139 | int? verificationTimestamp;
140 | String? userLocale;
141 | String? accessToken;
142 |
143 | /// get the [TruecallerUserProfile] values from Json
144 | TruecallerUserProfile.fromJson(Map map)
145 | : firstName = map['firstName'],
146 | lastName = map['lastName'],
147 | phoneNumber = map['phoneNumber'],
148 | gender = map['gender'],
149 | street = map['street'],
150 | city = map['city'],
151 | zipcode = map['zipcode'],
152 | countryCode = map['countryCode'],
153 | facebookId = map['facebookId'],
154 | twitterId = map['twitterId'],
155 | email = map['email'],
156 | url = map['url'],
157 | avatarUrl = map['avatarUrl'],
158 | isTrueName = map['isTrueName'],
159 | isAmbassador = map['isAmbassador'],
160 | companyName = map['companyName'],
161 | jobTitle = map['jobTitle'],
162 | payload = map['payload'],
163 | signature = map['signature'],
164 | signatureAlgorithm = map['signatureAlgorithm'],
165 | requestNonce = map['requestNonce'],
166 | isSimChanged = map['isSimChanged'],
167 | verificationMode = map['verificationMode'],
168 | verificationTimestamp = map['verificationTimestamp'],
169 | userLocale = map['userLocale'],
170 | accessToken = map['accessToken'];
171 | }
172 |
173 | /// error that corresponds to [TcSdkCallback.error]
174 | class TcOAuthError {
175 | late int code;
176 | late String? message;
177 |
178 | /// get the [TruecallerError] values from Json
179 | TcOAuthError.fromJson(Map map) {
180 | code = map['errorCode'];
181 | message = map['errorMessage'];
182 | }
183 | }
184 |
185 | /// exception that corresponds to [TcSdkCallback.exception]
186 | class TruecallerException {
187 | late int code;
188 | late String message;
189 |
190 | /// get the [TruecallerException] values from Json
191 | TruecallerException.fromJson(Map map) {
192 | code = map['mExceptionType'];
193 | message = map['mExceptionMessage'];
194 | }
195 |
196 | @override
197 | String toString() {
198 | return "$code : $message";
199 | }
200 | }
201 |
202 | class CallbackData {
203 | late String? otp;
204 | late String? ttl;
205 | late String? accessToken;
206 | late String? requestNonce;
207 | late String? profile;
208 |
209 | CallbackData.fromJson(Map map) {
210 | otp = map['otp'];
211 | ttl = map['ttl'];
212 | accessToken = map['accessToken'];
213 | requestNonce = map['requestNonce'];
214 | profile = map['profile'];
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/lib/truecaller_sdk.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | export 'src/scope_options.dart';
32 | export 'src/truecaller.dart';
33 | export 'src/truecaller_callback.dart';
34 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: truecaller_sdk
2 | description: Flutter plugin that uses Truecaller's OAuth SDK for Android based on OAuth 2.0 which is the industry-standard protocol for authorization.
3 | version: 1.0.0
4 | homepage: https://github.com/truecaller/flutter-sdk
5 |
6 | environment:
7 | sdk: '>=2.12.0 <3.0.0'
8 | flutter: ">=2.0.0"
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 |
14 | dev_dependencies:
15 | flutter_test:
16 | sdk: flutter
17 |
18 | # The following section is specific to Flutter.
19 | flutter:
20 | # This section identifies this Flutter project as a plugin project.
21 | # The 'pluginClass' and Android 'package' identifiers should not ordinarily
22 | # be modified. They are used by the tooling to maintain consistency when
23 | # adding or updating assets for this project.
24 | plugin:
25 | platforms:
26 | android:
27 | package: com.truecallersdk
28 | pluginClass: TruecallerSdkPlugin
--------------------------------------------------------------------------------
/test/truecaller_sdk_test.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * TRUECALLER SDK COPYRIGHT, TRADEMARK AND LICENSE NOTICE
3 | *
4 | * Copyright © 2015-Present, True Software Scandinavia AB. All rights reserved.
5 | *
6 | * Truecaller and Truecaller SDK are registered trademark of True Software Scandinavia AB.
7 | *
8 | * In accordance with the Truecaller SDK Agreement available
9 | * here (https://developer.truecaller.com/Truecaller-sdk-product-license-agreement-RoW.pdf)
10 | * accepted and agreed between You and Your respective Truecaller entity, You are granted a
11 | * limited, non-exclusive, non-sublicensable, non-transferable, royalty-free, license to use the
12 | * Truecaller SDK Product in object code form only, solely for the purpose of using
13 | * the Truecaller SDK Product with the applications and APIs provided by Truecaller.
14 | *
15 | * THE TRUECALLER SDK PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDER AND AUTHOR “AS IS”,
16 | * WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED
17 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
18 | * SOFTWARE QUALITY,PERFORMANCE,DATA ACCURACY AND NON-INFRINGEMENT. IN NO
19 | * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR
21 | * OTHER LIABILITY INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | * INTERRUPTION: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | * ARISING IN ANY WAY OUT OF THE USE OF THE TRUECALLER SDK PRODUCT OR THE USE
26 | * OR OTHER DEALINGS IN THE TRUECALLER SDK PRODUCT, EVEN IF ADVISED OF THE
27 | * POSSIBILITY OF SUCH DAMAGE. AS A RESULT, BY INTEGRATING THE TRUECALLER SDK
28 | * PRODUCT YOU ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND PERFORMANCE.
29 | */
30 |
31 | import 'package:flutter/services.dart';
32 | import 'package:flutter_test/flutter_test.dart';
33 |
34 | void main() {
35 | const MethodChannel channel = MethodChannel('tc_method_channel');
36 |
37 | TestWidgetsFlutterBinding.ensureInitialized();
38 |
39 | setUp(() {
40 | TestWidgetsFlutterBinding.instance.defaultBinaryMessenger
41 | .setMockMethodCallHandler(channel, (MethodCall methodCall) async {
42 | return '42';
43 | });
44 | });
45 |
46 | tearDown(() {
47 | TestWidgetsFlutterBinding.instance.defaultBinaryMessenger
48 | .setMockMethodCallHandler(channel, null);
49 | });
50 |
51 | /*test('getPlatformVersion', () async {
52 | expect(await TruecallerSdk.platformVersion, '42');
53 | });*/
54 | }
55 |
--------------------------------------------------------------------------------