From 19784a816e79838779775f724d487d3cd356b774 Mon Sep 17 00:00:00 2001 From: Bhanu Pratap Date: Thu, 6 Mar 2025 07:51:31 +0000 Subject: [PATCH 1/3] feat: Add CleverTap initialization support and example configuration --- .env.example | 4 ++ README.md | 38 ++++++++++++++++++- .../CleverTapApplication.java | 1 + .../DartToNativePlatformCommunicator.kt | 26 +++++++++++++ doc/Integrate-Android.md | 27 ++++++------- doc/Integrate-iOS.md | 13 ++++++- .../android/app/src/main/AndroidManifest.xml | 14 ------- example/ios/Runner/Info.plist | 6 --- example/lib/main.dart | 8 ++++ example/pubspec.yaml | 5 --- ios/Classes/CleverTapPlugin.m | 24 ++++++++++++ lib/clevertap_plugin.dart | 24 +++++++++++- 12 files changed, 147 insertions(+), 43 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..dfa2771d --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +CLEVERTAP_ACCOUNT_ID=your_account_id_here +CLEVERTAP_ACCOUNT_TOKEN=your_token_here +CLEVERTAP_ACCOUNT_REGION=your_region_here # Optional +CLEVERTAP_HANDSHAKE_DOMAIN=your_handshake_domain_here # Optional \ No newline at end of file diff --git a/README.md b/README.md index 0bf5fce9..67d373c1 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,43 @@ clevertap_plugin: 3.2.0 import 'package:clevertap_plugin/clevertap_plugin.dart'; ``` -See our [Technical Documentation for Android](doc/Integrate-Android.md) and [Technical Documentation for iOS](doc/Integrate-iOS.md) for instructions on integrating CleverTap into your Flutter app. +### Initialize CleverTap + +You can initialize CleverTap using either: + +1. Platform-specific configuration files (recommended): + - Follow the instructions in [Technical Documentation for Android](doc/Integrate-Android.md) and [Technical Documentation for iOS](doc/Integrate-iOS.md) + +2. Or using environment variables: + - Copy `.env.example` to `.env` in your project root: + ```bash + cp .env.example .env + ``` + - Update the `.env` file with your CleverTap credentials: + ``` + CLEVERTAP_ACCOUNT_ID=your_account_id_here + CLEVERTAP_ACCOUNT_TOKEN=your_token_here + CLEVERTAP_ACCOUNT_REGION=your_region_here # Optional + CLEVERTAP_HANDSHAKE_DOMAIN=your_domain_here # Optional + ``` + - ⚠️ Security Measures: + - Always add `.env` to your `.gitignore` to prevent committing sensitive credentials + - Never commit actual credentials to version control + - Use different credentials for development and production environments + - Regularly rotate your account tokens as a security best practice + - Restrict environment variable access to only necessary team members + +3. Or programmatically in your Flutter code: +```dart +await CleverTapPlugin.initialize( + accountId: 'YOUR_ACCOUNT_ID', + token: 'YOUR_ACCOUNT_TOKEN', + region: 'YOUR_REGION', // Optional + targetDomain: 'YOUR_DOMAIN' // Optional +); +``` + +See our [Technical Documentation for Android](doc/Integrate-Android.md) and [Technical Documentation for iOS](doc/Integrate-iOS.md) for complete instructions on integrating CleverTap into your Flutter app. ## πŸ“‘ Documentation & Example diff --git a/android/src/main/java/com/clevertap/clevertap_plugin/CleverTapApplication.java b/android/src/main/java/com/clevertap/clevertap_plugin/CleverTapApplication.java index 57224a4e..0b2bdefd 100644 --- a/android/src/main/java/com/clevertap/clevertap_plugin/CleverTapApplication.java +++ b/android/src/main/java/com/clevertap/clevertap_plugin/CleverTapApplication.java @@ -16,6 +16,7 @@ public class CleverTapApplication extends Application implements CTPushNotificat @Override public void onCreate() { + ActivityLifecycleCallback.register(this); // Register ActivityLifecycleCallback automatically super.onCreate(); CleverTapAPI cleverTapAPI = CleverTapAPI.getDefaultInstance(this); if (cleverTapAPI != null) { diff --git a/android/src/main/java/com/clevertap/clevertap_plugin/DartToNativePlatformCommunicator.kt b/android/src/main/java/com/clevertap/clevertap_plugin/DartToNativePlatformCommunicator.kt index 479c8d1b..c2bf91fe 100644 --- a/android/src/main/java/com/clevertap/clevertap_plugin/DartToNativePlatformCommunicator.kt +++ b/android/src/main/java/com/clevertap/clevertap_plugin/DartToNativePlatformCommunicator.kt @@ -75,6 +75,9 @@ class DartToNativePlatformCommunicator( result: MethodChannel.Result ) { when (call.method) { + "initialize" -> { + initializeCleverTap(call = call, result = result) + } "startEmission" -> { startEmission(call = call, result = result) } @@ -2088,6 +2091,29 @@ class DartToNativePlatformCommunicator( } +private fun initializeCleverTap(call: MethodCall, result: MethodChannel.Result) { + val accountId = call.argument("accountId") + val token = call.argument("token") + val region = call.argument("region") + + if (accountId == null || token == null) { + result.error(TAG, "accountId and token are required for initialization", null) + return + } + + try { + val configMap = CleverTapAPI.getDefaultInstance(context)?.config + configMap?.let { + it.accountId = accountId + it.accountToken = token + region?.let { reg -> it.accountRegion = reg } + } + result.success(null) + } catch (e: Exception) { + result.error(TAG, "Failed to initialize CleverTap: ${e.message}", null) + } +} + private fun interface TemplateContextAction { fun execute(context: CustomTemplateContext): Any? } \ No newline at end of file diff --git a/doc/Integrate-Android.md b/doc/Integrate-Android.md index 832d9461..a3ec21b2 100644 --- a/doc/Integrate-Android.md +++ b/doc/Integrate-Android.md @@ -49,19 +49,6 @@ apply plugin: 'com.google.gms.google-services' //skip if not using FCM ``` -- In your app's Android Application class add the following code. - - ```java - public class MyApplication extends Application { - @java.lang.Override - public void onCreate() { - ActivityLifecycleCallback.register(this); //<--- Add this before super.onCreate() - super.onCreate(); - } - } - - ``` - #### Note - To use Header & Footer InApp Notification Templates of CleverTap, change the class from which MainActivity is inherited from `FlutterActivity` to `FlutterFragmentActivity` @@ -90,8 +77,8 @@ ``` -- Add your CleverTap Account ID and Token to your `AndroidManifest.xml`, within the tags. - +- Add your CleverTap Account ID and Token either: + 1. In your `AndroidManifest.xml`, within the tags: ```xml + ``` + 2. Or through environment variables in a .env file and initialize in your code: + ```dart + await CleverTapPlugin.initialize( + accountId: 'YOUR_ACCOUNT_ID', + token: 'YOUR_ACCOUNT_TOKEN', + region: 'YOUR_REGION', // Optional + targetDomain: 'YOUR_DOMAIN' // Optional + ); + ``` - - - - - - ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) - CleverTapAccountID - CLEVERTAP_ACCOUNT_ID - CleverTapToken - CLEVERTAP_ACCOUNT_TOKEN - CleverTapRegion - CLEVERTAP_ACCOUNT_REGION CleverTapUseIFA LSRequiresIPhoneOS diff --git a/example/lib/main.dart b/example/lib/main.dart index 8a11855e..602f1628 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -73,6 +73,14 @@ void main() async { CleverTapPlugin.onKilledStateNotificationClicked( onKilledStateNotificationClickedHandler); + // Initialize CleverTap with your credentials (Optional) + await CleverTapPlugin.initialize( + accountId: 'YOUR_ACCOUNT_ID', + token: 'YOUR_ACCOUNT_TOKEN', + region: 'YOUR_REGION', // Optional + targetDomain: 'YOUR_DOMAIN' // Optional + ); + print("CleverTapPlugin main pre runapp"); Future.delayed(Duration(seconds: TEST_RUN_APP_DELAY), () { diff --git a/example/pubspec.yaml b/example/pubspec.yaml index fa2e2f89..ce043626 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -50,11 +50,6 @@ flutter: # the material Icons class. uses-material-design: true - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. diff --git a/ios/Classes/CleverTapPlugin.m b/ios/Classes/CleverTapPlugin.m index 15056606..702778ca 100644 --- a/ios/Classes/CleverTapPlugin.m +++ b/ios/Classes/CleverTapPlugin.m @@ -23,6 +23,30 @@ @interface CleverTapPlugin () initialize({ + required String accountId, + required String token, + String? region, + String? targetDomain, + }) async { + final initProps = { + 'accountId': accountId, + 'token': token, + 'region': region, + 'targetDomain': targetDomain, + }; + + if (kIsWeb) { + await _dartToNativeMethodChannel.invokeMethod('init', initProps); + } else { + await _dartToNativeMethodChannel.invokeMethod('initialize', initProps); + } + } + + /// Only for Web - Initialize clevertap sdk directly with parameters (legacy method) + @Deprecated('Use initialize() instead') static Future init(String accountId, [String? region, String? targetDomain, String? token]) async { if (!kIsWeb) { From 8c98228257d307fcfb7bd13cc3fe9198e6f47ea7 Mon Sep 17 00:00:00 2001 From: Bhanu Pratap Date: Thu, 6 Mar 2025 08:03:28 +0000 Subject: [PATCH 2/3] docs: Update README for improved clarity and security practices --- README.md | 83 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 67d373c1..12585c60 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

# CleverTap Flutter SDK @@ -8,23 +8,23 @@ -## πŸ‘‹ Introduction +## Introduction The CleverTap Flutter SDK for Mobile Customer Engagement and Analytics solutions. -For more information check out our [website](https://clevertap.com/ "CleverTap") and [documentation](https://developer.clevertap.com/docs/ "CleverTap Technical Documentation"). +For more information, check out our [website](https://clevertap.com/) and [documentation](https://developer.clevertap.com/docs/). To get started, sign up [here](https://clevertap.com/live-product-demo/). -## πŸš€ Installation and Quick Start +## Installation and Quick Start - To add the **CleverTap Flutter SDK** to your project, edit your project's `pubspec.yaml` file: ```yaml dependencies: -clevertap_plugin: 3.2.0 + clevertap_plugin: 3.2.0 ``` -- Run `flutter packages get` to install the SDK +- Run `flutter packages get` to install the SDK. - Now, in your Dart code, you can use: @@ -36,10 +36,10 @@ import 'package:clevertap_plugin/clevertap_plugin.dart'; You can initialize CleverTap using either: -1. Platform-specific configuration files (recommended): +1. **Platform-specific configuration files (recommended):** - Follow the instructions in [Technical Documentation for Android](doc/Integrate-Android.md) and [Technical Documentation for iOS](doc/Integrate-iOS.md) -2. Or using environment variables: +2. **Using environment variables:** - Copy `.env.example` to `.env` in your project root: ```bash cp .env.example .env @@ -51,41 +51,54 @@ You can initialize CleverTap using either: CLEVERTAP_ACCOUNT_REGION=your_region_here # Optional CLEVERTAP_HANDSHAKE_DOMAIN=your_domain_here # Optional ``` - - ⚠️ Security Measures: - - Always add `.env` to your `.gitignore` to prevent committing sensitive credentials - - Never commit actual credentials to version control - - Use different credentials for development and production environments - - Regularly rotate your account tokens as a security best practice - - Restrict environment variable access to only necessary team members - -3. Or programmatically in your Flutter code: -```dart -await CleverTapPlugin.initialize( - accountId: 'YOUR_ACCOUNT_ID', - token: 'YOUR_ACCOUNT_TOKEN', - region: 'YOUR_REGION', // Optional - targetDomain: 'YOUR_DOMAIN' // Optional -); -``` + +3. **Programmatically in your Flutter code:** + ```dart + await CleverTapPlugin.initialize( + accountId: 'YOUR_ACCOUNT_ID', + token: 'YOUR_ACCOUNT_TOKEN', + region: 'YOUR_REGION', // Optional + targetDomain: 'YOUR_DOMAIN' // Optional + ); + ``` See our [Technical Documentation for Android](doc/Integrate-Android.md) and [Technical Documentation for iOS](doc/Integrate-iOS.md) for complete instructions on integrating CleverTap into your Flutter app. -## πŸ“‘ Documentation & Example +## Security Measures -- Checkout our [CleverTap Flutter Usage documentation](doc/Usage.md) -- Checkout our [Example Dart project](./example) +To ensure secure handling of CleverTap credentials and sensitive data, follow these best practices: -## πŸ“² CleverTap Push Templates SDK (Available only for Android OS) -[(Back to top)](#-table-of-contents) +- **Environment Variable Management:** + - Always add `.env` to your `.gitignore` to prevent accidental commits of sensitive credentials. + - Never store production credentials in the source code or version control. + - Use separate credentials for development, staging, and production environments. -CleverTap Push Templates SDK helps you engage with your users using fancy push notification templates built specifically to work with [CleverTap](https://www.clevertap.com). -Find the integration steps for the CleverTap Push Templates SDK [here](https://github.com/CleverTap/clevertap-android-sdk/blob/master/docs/CTPUSHTEMPLATES.md) +- **Secure Credential Handling:** + - Utilize secret management tools such as AWS Secrets Manager, Google Secret Manager, or environment variable injection via CI/CD pipelines. + - Ensure access to credentials is restricted to authorized team members only. + - Regularly rotate API keys and tokens to minimize security risks. -## πŸ†• Changelog +- **CI/CD Pipeline Security:** + - Store secrets in a secure vault instead of hardcoding them in configuration files. + - Use least privilege access policies for CI/CD tools interacting with CleverTap. + - Monitor logs for unauthorized access attempts. -Refer to the [CleverTap Flutter SDK Change Log](./CHANGELOG.md). +By implementing these security practices, you can safeguard your application and user data. + +## Documentation & Example -## ❓Questions +- Checkout our [CleverTap Flutter Usage documentation](doc/Usage.md). +- Checkout our [Example Dart project](./example). + +## CleverTap Push Templates SDK (Available only for Android OS) + +CleverTap Push Templates SDK helps you engage with your users using dynamic push notification templates built specifically for [CleverTap](https://www.clevertap.com). +Find the integration steps for the CleverTap Push Templates SDK [here](https://github.com/CleverTap/clevertap-android-sdk/blob/master/docs/CTPUSHTEMPLATES.md). + +## Changelog + +Refer to the [CleverTap Flutter SDK Change Log](./CHANGELOG.md). - If you have questions or concerns, you can reach out to the CleverTap support team from the CleverTap Dashboard. +## Questions +If you have questions or concerns, you can reach out to the CleverTap support team from the CleverTap Dashboard. From 8bd9772336696f49e670dc995036b09253136c52 Mon Sep 17 00:00:00 2001 From: Bhanu Pratap Date: Thu, 6 Mar 2025 08:28:39 +0000 Subject: [PATCH 3/3] docs: Update README for image alt text and improve documentation clarity feat: Deprecate old initialization method in example and provide new usage instructions fix: Add targetDomain configuration in CleverTapPlugin --- README.md | 6 +++--- example/lib/main.dart | 11 ++++++++++- ios/Classes/CleverTapPlugin.m | 5 +++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 12585c60..1e5a4f1a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- + CleverTap Logo

# CleverTap Flutter SDK @@ -87,8 +87,8 @@ By implementing these security practices, you can safeguard your application and ## Documentation & Example -- Checkout our [CleverTap Flutter Usage documentation](doc/Usage.md). -- Checkout our [Example Dart project](./example). +- Check out our [CleverTap Flutter Usage documentation](doc/Usage.md). +- Check out our [Example Dart project](./example). ## CleverTap Push Templates SDK (Available only for Android OS) diff --git a/example/lib/main.dart b/example/lib/main.dart index 602f1628..1e66eb37 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -130,7 +130,16 @@ class _MyAppState extends State { }); CleverTapPlugin.setDebugLevel(3); if (kIsWeb) { - CleverTapPlugin.init("CLEVERTAP_ACCOUNT_ID", "CLEVERTAP_REGION", "CLEVERTAP_TARGET_DOMAIN"); + // @deprecated Use initialize() method instead. This method will be removed in a future release. + // @deprecated: Use CleverTapPlugin.initialize() instead. + // Example of new initialization: + // await CleverTapPlugin.initialize( + // accountId: "CLEVERTAP_ACCOUNT_ID", + // token: "YOUR_ACCOUNT_TOKEN", + // region: "CLEVERTAP_REGION", + // targetDomain: "CLEVERTAP_TARGET_DOMAIN" + // ); + CleverTapPlugin.init("CLEVERTAP_ACCOUNT_ID", "CLEVERTAP_REGION", "CLEVERTAP_TARGET_DOMAIN"); // deprecated CleverTapPlugin.setDebugLevel(3); CleverTapPlugin.addKVDataChangeListener((obj) { var kv = obj["kv"]; diff --git a/ios/Classes/CleverTapPlugin.m b/ios/Classes/CleverTapPlugin.m index 702778ca..773c552c 100644 --- a/ios/Classes/CleverTapPlugin.m +++ b/ios/Classes/CleverTapPlugin.m @@ -43,6 +43,11 @@ - (void)initializeWithConfig:(FlutterMethodCall *)call withResult:(FlutterResult instanceConfig.regionCode = region; } + NSString *targetDomain = config[@"targetDomain"]; + if (targetDomain) { + instanceConfig.domain = targetDomain; + } + [CleverTap instanceConfigWithConfig:instanceConfig]; result(nil); }