diff --git a/packages/analytics/amplify_analytics_pinpoint/.metadata b/packages/analytics/amplify_analytics_pinpoint/.metadata new file mode 100644 index 0000000000..c519b0887d --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + channel: stable + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + - platform: android + create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + - platform: ios + create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + - platform: linux + create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + - platform: macos + create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + - platform: web + create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + - platform: windows + create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/analytics/amplify_analytics_pinpoint/Makefile b/packages/analytics/amplify_analytics_pinpoint/Makefile new file mode 100644 index 0000000000..ab34e2e8cb --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/Makefile @@ -0,0 +1,4 @@ +.PHONY: pigeons +pigeons: + flutter pub run pigeon --input pigeons/pigeon_config_android.dart + flutter format --fix lib/src/legacy_native_data_provider/pigeon_legacy_data_provider.android.g.dart \ No newline at end of file diff --git a/packages/analytics/amplify_analytics_pinpoint/analysis_options.yaml b/packages/analytics/amplify_analytics_pinpoint/analysis_options.yaml index eb7b6bab52..a806cb6753 100644 --- a/packages/analytics/amplify_analytics_pinpoint/analysis_options.yaml +++ b/packages/analytics/amplify_analytics_pinpoint/analysis_options.yaml @@ -1,5 +1,7 @@ include: package:amplify_lints/library.yaml -analyzer: +analyzer: errors: - implementation_imports: error #TODO(equartey): Remove when lint is enforced project-wide + implementation_imports: error #TODO(equartey): Remove when lint is enforced project-wide + exclude: + - "**/*.g.dart" diff --git a/packages/analytics/amplify_analytics_pinpoint/android/.gitignore b/packages/analytics/amplify_analytics_pinpoint/android/.gitignore new file mode 100644 index 0000000000..26659750ab --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures \ No newline at end of file diff --git a/packages/analytics/amplify_analytics_pinpoint/android/build.gradle b/packages/analytics/amplify_analytics_pinpoint/android/build.gradle new file mode 100644 index 0000000000..ff76d95f44 --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/android/build.gradle @@ -0,0 +1,51 @@ +group 'com.amazonaws.amplify.amplify_analytics_pinpoint.amplify_analytics_pinpoint' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion 33 + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + minSdkVersion 23 + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} + diff --git a/packages/analytics/amplify_analytics_pinpoint/android/settings.gradle b/packages/analytics/amplify_analytics_pinpoint/android/settings.gradle new file mode 100644 index 0000000000..828ffda158 --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'amplify_analytics_pinpoint' diff --git a/packages/analytics/amplify_analytics_pinpoint/android/src/main/AndroidManifest.xml b/packages/analytics/amplify_analytics_pinpoint/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..178b72183e --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/packages/analytics/amplify_analytics_pinpoint/android/src/main/java/com/amazonaws/amplify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/Messages.java b/packages/analytics/amplify_analytics_pinpoint/android/src/main/java/com/amazonaws/amplify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/Messages.java new file mode 100644 index 0000000000..cebacf407c --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/android/src/main/java/com/amazonaws/amplify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/Messages.java @@ -0,0 +1,85 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// Autogenerated from Pigeon (v4.2.14), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package com.amazonaws.amplify.amplify_analytics_pinpoint.amplify_analytics_pinpoint; + +import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import io.flutter.plugin.common.BasicMessageChannel; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MessageCodec; +import io.flutter.plugin.common.StandardMessageCodec; +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.HashMap; + +/** Generated class from Pigeon. */ +@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"}) +public class Messages { + + public interface Result { + void success(T result); + void error(Throwable error); + } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface PigeonLegacyDataProvider { + void getEndpointId(@NonNull String pinpointAppId, Result result); + + /** The codec used by PigeonLegacyDataProvider. */ + static MessageCodec getCodec() { + return new StandardMessageCodec(); } + /**Sets up an instance of `PigeonLegacyDataProvider` to handle messages through the `binaryMessenger`. */ + static void setup(BinaryMessenger binaryMessenger, PigeonLegacyDataProvider api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.PigeonLegacyDataProvider.getEndpointId", getCodec()); + if (api != null) { + channel.setMessageHandler((message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + try { + ArrayList args = (ArrayList)message; + assert args != null; + String pinpointAppIdArg = (String)args.get(0); + if (pinpointAppIdArg == null) { + throw new NullPointerException("pinpointAppIdArg unexpectedly null."); + } + Result resultCallback = new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.getEndpointId(pinpointAppIdArg, resultCallback); + } + catch (Error | RuntimeException exception) { + ArrayList wrappedError = wrapError(exception); + reply.reply(wrappedError); + } + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + @NonNull private static ArrayList wrapError(@NonNull Throwable exception) { + ArrayList errorList = new ArrayList<>(3); + errorList.add(exception.toString()); + errorList.add(exception.getClass().getSimpleName()); + errorList.add("Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + return errorList; + } +} diff --git a/packages/analytics/amplify_analytics_pinpoint/android/src/main/kotlin/com/amazonaws/amplify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt b/packages/analytics/amplify_analytics_pinpoint/android/src/main/kotlin/com/amazonaws/amplify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt new file mode 100644 index 0000000000..a08ca3570d --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/android/src/main/kotlin/com/amazonaws/amplify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt @@ -0,0 +1,43 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.amplify.amplify_analytics_pinpoint.amplify_analytics_pinpoint + +import android.content.Context +import android.content.SharedPreferences +import androidx.annotation.NonNull +import io.flutter.embedding.engine.plugins.FlutterPlugin + +class AmplifyAnalyticsPinpointPlugin: FlutterPlugin, Messages.PigeonLegacyDataProvider { + + private var context: Context? = null + private var sharedPrefs: SharedPreferences? = null + + companion object { + private const val PINPOINT_SHARED_PREFS_SUFFIX = "515d6767-01b7-49e5-8273-c8d11b0f331d" + private const val UNIQUE_ID_KEY = "UniqueId"; + } + + override fun onAttachedToEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + context = binding.applicationContext + Messages.PigeonLegacyDataProvider.setup(binding.binaryMessenger, this) + } + + override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + Messages.PigeonLegacyDataProvider.setup(binding.binaryMessenger, null) + context = null + } + + override fun getEndpointId(pinpointAppId: String, result: Messages.Result){ + if (context == null) { + result.error(Exception("Application context is null")) + return + } + sharedPrefs = sharedPrefs ?: context!!.getSharedPreferences( + "${pinpointAppId}$PINPOINT_SHARED_PREFS_SUFFIX", + Context.MODE_PRIVATE + ) + result.success(sharedPrefs!!.getString(UNIQUE_ID_KEY, null)) + } + +} \ No newline at end of file diff --git a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/auto_session_tracking_test.dart b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/auto_session_tracking_test.dart index f64b23d2f4..28e112ad3b 100644 --- a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/auto_session_tracking_test.dart +++ b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/auto_session_tracking_test.dart @@ -1,15 +1,5 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// A copy of the License is located at -// -// http://aws.amazon.com/apache2.0 -// -// or in the "license" file accompanying this file. This file is distributed -// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -// express or implied. See the License for the specific language governing -// permissions and limitations under the License. +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 import 'dart:async'; diff --git a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/enable_disable_test.dart b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/enable_disable_test.dart index e4a256e194..9b2ac910fa 100644 --- a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/enable_disable_test.dart +++ b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/enable_disable_test.dart @@ -1,15 +1,5 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// A copy of the License is located at -// -// http://aws.amazon.com/apache2.0 -// -// or in the "license" file accompanying this file. This file is distributed -// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -// express or implied. See the License for the specific language governing -// permissions and limitations under the License. +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 import 'dart:async'; diff --git a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/identify_user_test.dart b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/identify_user_test.dart index 19d6bcdcc2..4216809e43 100644 --- a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/identify_user_test.dart +++ b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/identify_user_test.dart @@ -1,15 +1,5 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// A copy of the License is located at -// -// http://aws.amazon.com/apache2.0 -// -// or in the "license" file accompanying this file. This file is distributed -// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -// express or implied. See the License for the specific language governing -// permissions and limitations under the License. +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 import 'dart:async'; diff --git a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/mock_key_value_store.dart b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/mock_key_value_store.dart index 16f736acd8..a1ab009bc6 100644 --- a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/mock_key_value_store.dart +++ b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/mock_key_value_store.dart @@ -1,16 +1,5 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 import 'dart:async'; diff --git a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/mock_lifecycle_provider.dart b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/mock_lifecycle_provider.dart index f7f64d2d73..cd2ca677e5 100644 --- a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/mock_lifecycle_provider.dart +++ b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/mock_lifecycle_provider.dart @@ -1,15 +1,5 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// A copy of the License is located at -// -// http://aws.amazon.com/apache2.0 -// -// or in the "license" file accompanying this file. This file is distributed -// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -// express or implied. See the License for the specific language governing -// permissions and limitations under the License. +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 import 'package:amplify_analytics_pinpoint/amplify_analytics_pinpoint.dart'; diff --git a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/test_event.dart b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/test_event.dart index 3461dc567f..05127786d8 100644 --- a/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/test_event.dart +++ b/packages/analytics/amplify_analytics_pinpoint/example/integration_test/utils/test_event.dart @@ -1,16 +1,5 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 import 'package:amplify_analytics_pinpoint_dart/src/sdk/pinpoint.dart' show EndpointResponse; diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/amplify_analytics_pinpoint.dart b/packages/analytics/amplify_analytics_pinpoint/lib/amplify_analytics_pinpoint.dart index 24f7571f13..50f3035e14 100644 --- a/packages/analytics/amplify_analytics_pinpoint/lib/amplify_analytics_pinpoint.dart +++ b/packages/analytics/amplify_analytics_pinpoint/lib/amplify_analytics_pinpoint.dart @@ -6,10 +6,7 @@ library amplify_analytics_pinpoint; /// Overridable Flutter injected dependencies export 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart' - show - AppLifecycleProvider, - CachedEventsPathProvider, - DeviceContextInfoProvider; + show AppLifecycleProvider; /// Category Implementation export 'src/analytics_plugin_impl.dart'; diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/analytics_plugin_impl.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/analytics_plugin_impl.dart index 536a55094e..22519638ae 100644 --- a/packages/analytics/amplify_analytics_pinpoint/lib/src/analytics_plugin_impl.dart +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/analytics_plugin_impl.dart @@ -4,6 +4,7 @@ import 'package:amplify_analytics_pinpoint/src/device_context_info_provider/flutter_device_context_info_provider.dart'; import 'package:amplify_analytics_pinpoint/src/flutter_app_lifecycle_provider.dart'; import 'package:amplify_analytics_pinpoint/src/flutter_path_provider/flutter_path_provider.dart'; +import 'package:amplify_analytics_pinpoint/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart'; import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; import 'package:amplify_db_common/amplify_db_common.dart' as db_common; import 'package:amplify_secure_storage/amplify_secure_storage.dart'; @@ -16,9 +17,7 @@ class AmplifyAnalyticsPinpoint extends AmplifyAnalyticsPinpointDart { /// {@macro amplify_analytics_pinpoint.analytics_plugin_impl} AmplifyAnalyticsPinpoint({ @visibleForTesting SecureStorageInterface? endpointInfoStore, - @visibleForTesting CachedEventsPathProvider? pathProvider, @visibleForTesting AppLifecycleProvider? appLifecycleProvider, - @visibleForTesting DeviceContextInfoProvider? deviceContextInfoProvider, }) : super( endpointInfoStore: endpointInfoStore ?? AmplifySecureStorage( @@ -26,11 +25,11 @@ class AmplifyAnalyticsPinpoint extends AmplifyAnalyticsPinpointDart { scope: 'analyticsPinpoint', ), ), - pathProvider: pathProvider ?? FlutterPathProvider(), + pathProvider: FlutterPathProvider(), appLifecycleProvider: appLifecycleProvider ?? FlutterAppLifecycleProvider(), - deviceContextInfoProvider: deviceContextInfoProvider ?? - const FlutterDeviceContextInfoProvider(), + deviceContextInfoProvider: const FlutterDeviceContextInfoProvider(), + legacyNativeDataProvider: FlutterLegacyNativeDataProvider(), dbConnectFunction: db_common.connect, ); } diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider.dart index 3c9a363beb..f60aa28c0a 100644 --- a/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider.dart +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider.dart @@ -7,6 +7,10 @@ /// Multi platform class that provides storage location path /// Requires Flutter specific dependencies + +/// {@template amplify_analytics_pinpoint.flutter_path_provider} +/// Provides device storage location +/// {@endtemplate} export 'flutter_path_provider_stub.dart' if (dart.library.html) 'flutter_path_provider_html.dart' if (dart.library.io) 'flutter_path_provider_io.dart'; diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_html.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_html.dart index 620508d086..15d0475d67 100644 --- a/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_html.dart +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_html.dart @@ -3,7 +3,7 @@ import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; -/// {@template amplify_analytics_pinpoint.flutter_path_provider} +/// {@macro amplify_analytics_pinpoint.flutter_path_provider} class FlutterPathProvider extends CachedEventsPathProvider { @override Future getApplicationSupportPath() async { diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_io.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_io.dart index f1cfa06f3f..60c7699b58 100644 --- a/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_io.dart +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_io.dart @@ -4,7 +4,7 @@ import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; import 'package:path_provider/path_provider.dart'; -/// {@template amplify_analytics_pinpoint.flutter_path_provider} +/// {@macro amplify_analytics_pinpoint.flutter_path_provider} class FlutterPathProvider extends CachedEventsPathProvider { @override Future getApplicationSupportPath() async { diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_stub.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_stub.dart index f37bca2fea..a8ec5db5be 100644 --- a/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_stub.dart +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/flutter_path_provider/flutter_path_provider_stub.dart @@ -3,7 +3,7 @@ import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; -// ignore: public_member_api_docs +/// {@macro amplify_analytics_pinpoint.flutter_path_provider} class FlutterPathProvider extends CachedEventsPathProvider { @override Future getApplicationSupportPath() async { diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.android.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.android.dart new file mode 100644 index 0000000000..886cf036de --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.android.dart @@ -0,0 +1,20 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:async'; + +import 'package:amplify_analytics_pinpoint/src/legacy_native_data_provider/pigeon_legacy_data_provider.android.g.dart'; +import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; + +/// {@macro amplify_analytics_pinpoint.flutter_legacy_native_data_provider} +class DataProviderAndroid implements LegacyNativeDataProvider { + /// {@macro amplify_analytics_pinpoint.flutter_legacy_native_data_provider} + DataProviderAndroid() : _pigeonDataProvider = PigeonLegacyDataProvider(); + + final PigeonLegacyDataProvider _pigeonDataProvider; + + @override + Future getEndpointId(String pinpointAppId) { + return _pigeonDataProvider.getEndpointId(pinpointAppId); + } +} diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.ios.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.ios.dart new file mode 100644 index 0000000000..91deed2e92 --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.ios.dart @@ -0,0 +1,27 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:async'; + +import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; +import 'package:amplify_secure_storage/amplify_secure_storage.dart'; + +/// {@macro amplify_analytics_pinpoint.flutter_legacy_native_data_provider} +class DataProviderIos implements LegacyNativeDataProvider { + /// {@macro amplify_analytics_pinpoint.flutter_legacy_native_data_provider} + DataProviderIos() + : _keyValueStore = AmplifySecureStorage( + config: AmplifySecureStorageConfig.byNamespace(namespace: _context), + ); + + static const _context = 'com.amazonaws.AWSPinpointContext'; + static const _key = 'com.amazonaws.AWSPinpointContextKeychainUniqueIdKey'; + + final AmplifySecureStorage _keyValueStore; + + @override + Future getEndpointId(String pinpointAppId) async { + final endpointId = await _keyValueStore.read(key: _key); + return endpointId; + } +} diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart new file mode 100644 index 0000000000..aca9bc90ea --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart @@ -0,0 +1,40 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:async'; +import 'dart:io' show Platform; + +import 'package:amplify_analytics_pinpoint/src/legacy_native_data_provider/data_provider.android.dart'; +import 'package:amplify_analytics_pinpoint/src/legacy_native_data_provider/data_provider.ios.dart'; +import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; +import 'package:aws_common/aws_common.dart'; + +/// {@template amplify_analytics_pinpoint.flutter_legacy_native_data_provider} +/// Provides legacy data stored by Amplify Analytics iOS and Android. +/// {@endtemplate} +class FlutterLegacyNativeDataProvider implements LegacyNativeDataProvider { + /// {@macro amplify_analytics_pinpoint.flutter_legacy_native_data_provider} + factory FlutterLegacyNativeDataProvider() { + if (zIsWeb || !(Platform.isIOS || Platform.isAndroid)) { + return const FlutterLegacyNativeDataProvider._(); + } + + final LegacyNativeDataProvider provider; + if (Platform.isIOS) { + provider = DataProviderIos(); + } else { + provider = DataProviderAndroid(); + } + + return FlutterLegacyNativeDataProvider._(provider); + } + + const FlutterLegacyNativeDataProvider._([this._nativeDataProvider]); + + final LegacyNativeDataProvider? _nativeDataProvider; + + @override + Future getEndpointId(String pinpointAppId) async { + return _nativeDataProvider?.getEndpointId(pinpointAppId); + } +} diff --git a/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/pigeon_legacy_data_provider.android.g.dart b/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/pigeon_legacy_data_provider.android.g.dart new file mode 100644 index 0000000000..cfaa5bdc4f --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/pigeon_legacy_data_provider.android.g.dart @@ -0,0 +1,43 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// Autogenerated from Pigeon (v4.2.14), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +class PigeonLegacyDataProvider { + /// Constructor for [PigeonLegacyDataProvider]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + PigeonLegacyDataProvider({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + Future getEndpointId(String arg_pinpointAppId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PigeonLegacyDataProvider.getEndpointId', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_pinpointAppId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return (replyList[0] as String?); + } + } +} diff --git a/packages/analytics/amplify_analytics_pinpoint/pigeons/copyright.txt b/packages/analytics/amplify_analytics_pinpoint/pigeons/copyright.txt new file mode 100644 index 0000000000..478e610532 --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/pigeons/copyright.txt @@ -0,0 +1,2 @@ +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 \ No newline at end of file diff --git a/packages/analytics/amplify_analytics_pinpoint/pigeons/pigeon_config_android.dart b/packages/analytics/amplify_analytics_pinpoint/pigeons/pigeon_config_android.dart new file mode 100644 index 0000000000..f7cc9baf58 --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint/pigeons/pigeon_config_android.dart @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// To regenerate, run `make pigeons`. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: + 'lib/src/legacy_native_data_provider/pigeon_legacy_data_provider.android.g.dart', + javaOut: + 'android/src/main/java/com/amazonaws/amplify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/Messages.java', + javaOptions: JavaOptions( + className: 'Messages', + package: + 'com.amazonaws.amplify.amplify_analytics_pinpoint.amplify_analytics_pinpoint', + ), + copyrightHeader: 'pigeons/copyright.txt', + ), +) +@HostApi() +abstract class PigeonLegacyDataProvider { + @async + String? getEndpointId(String pinpointAppId); +} diff --git a/packages/analytics/amplify_analytics_pinpoint/pubspec.yaml b/packages/analytics/amplify_analytics_pinpoint/pubspec.yaml index dffb496ece..f210db8dab 100644 --- a/packages/analytics/amplify_analytics_pinpoint/pubspec.yaml +++ b/packages/analytics/amplify_analytics_pinpoint/pubspec.yaml @@ -35,3 +35,11 @@ dev_dependencies: amplify_lints: ^2.0.0 flutter_test: sdk: flutter + pigeon: ^4.2.5 + +flutter: + plugin: + platforms: + android: + package: com.amazonaws.amplify.amplify_analytics_pinpoint.amplify_analytics_pinpoint + pluginClass: AmplifyAnalyticsPinpointPlugin diff --git a/packages/analytics/amplify_analytics_pinpoint_dart/lib/amplify_analytics_pinpoint_dart.dart b/packages/analytics/amplify_analytics_pinpoint_dart/lib/amplify_analytics_pinpoint_dart.dart index e0adf2d728..8114db7a27 100644 --- a/packages/analytics/amplify_analytics_pinpoint_dart/lib/amplify_analytics_pinpoint_dart.dart +++ b/packages/analytics/amplify_analytics_pinpoint_dart/lib/amplify_analytics_pinpoint_dart.dart @@ -9,3 +9,4 @@ export 'src/analytics_plugin_impl.dart'; export 'src/impl/flutter_provider_interfaces/app_lifecycle_provider.dart'; export 'src/impl/flutter_provider_interfaces/cached_events_path_provider.dart'; export 'src/impl/flutter_provider_interfaces/device_context_info_provider.dart'; +export 'src/impl/flutter_provider_interfaces/legacy_native_data_provider.dart'; diff --git a/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart b/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart index 1283037702..b228d7006a 100644 --- a/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart +++ b/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_client.dart'; import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_global_fields_manager.dart'; +import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_store_keys.dart'; import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/event_client/event_client.dart'; import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/event_client/event_storage_adapter.dart'; import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/event_creator/event_creator.dart'; @@ -18,7 +19,6 @@ import 'package:amplify_core/amplify_core.dart'; import 'package:amplify_db_common_dart/amplify_db_common_dart.dart'; import 'package:amplify_secure_storage_dart/amplify_secure_storage_dart.dart'; import 'package:meta/meta.dart'; -import 'package:uuid/uuid.dart'; /// The Analytics Pinpoint session start event type. @visibleForTesting @@ -41,6 +41,7 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface { CachedEventsPathProvider? pathProvider, AppLifecycleProvider? appLifecycleProvider, DeviceContextInfoProvider? deviceContextInfoProvider, + LegacyNativeDataProvider? legacyNativeDataProvider, required Connect dbConnectFunction, }) : _endpointInfoStore = endpointInfoStore ?? AmplifySecureStorageWorker( @@ -51,6 +52,7 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface { _pathProvider = pathProvider, _appLifecycleProvider = appLifecycleProvider, _deviceContextInfoProvider = deviceContextInfoProvider, + _legacyNativeDataProvider = legacyNativeDataProvider, _dbConnectFunction = dbConnectFunction; void _ensureConfigured() { @@ -88,6 +90,7 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface { final CachedEventsPathProvider? _pathProvider; final AppLifecycleProvider? _appLifecycleProvider; final DeviceContextInfoProvider? _deviceContextInfoProvider; + final LegacyNativeDataProvider? _legacyNativeDataProvider; final Connect _dbConnectFunction; static final _logger = AmplifyLogger.category(Category.analytics); @@ -137,16 +140,9 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface { deviceContextInfo: deviceContextInfo, ); - // Retrieve Unique ID - final savedFixedEndpointId = - await _endpointInfoStore.read(key: endpointIdStorageKey); - final fixedEndpointId = savedFixedEndpointId ?? const Uuid().v1(); - if (savedFixedEndpointId == null) { - await _endpointInfoStore.write( - key: endpointIdStorageKey, - value: fixedEndpointId, - ); - } + final fixedEndpointId = await retrieveEndpointId( + pinpointAppId: appId, + ); final endpoint = PublicEndpoint( effectiveDate: DateTime.now().toUtc().toIso8601String(), @@ -323,4 +319,49 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface { await _eventClient.close(); await _eventStorageAdapter.close(); } + + /// Retrieve the stored pinpoint endpoint id + @visibleForTesting + Future retrieveEndpointId({ + required String pinpointAppId, + }) async { + // Retrieve Unique ID + final endpointInformationVersion = + await _endpointInfoStore.read(key: EndpointStoreKey.version.name); + + String? fixedEndpointId; + if (endpointInformationVersion == null) { + final legacyEndpointId = + await _legacyNativeDataProvider?.getEndpointId(pinpointAppId); + // Migrate legacy data if it is non-null + if (legacyEndpointId != null) { + fixedEndpointId = legacyEndpointId; + await _endpointInfoStore.write( + key: endpointIdStorageKey, + value: legacyEndpointId, + ); + } + // Update the version to prevent future legacy data migrations. + await _endpointInfoStore.write( + key: EndpointStoreKey.version.name, + value: EndpointStoreVersion.v1.name, + ); + } + + // Read the existing ID. + fixedEndpointId ??= await _endpointInfoStore.read( + key: endpointIdStorageKey, + ); + + // Generate a new ID if one does not exist. + if (fixedEndpointId == null) { + fixedEndpointId = uuid(); + await _endpointInfoStore.write( + key: endpointIdStorageKey, + value: fixedEndpointId, + ); + } + + return fixedEndpointId; + } } diff --git a/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/impl/analytics_client/endpoint_client/endpoint_store_keys.dart b/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/impl/analytics_client/endpoint_client/endpoint_store_keys.dart new file mode 100644 index 0000000000..6c02cfd39c --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/impl/analytics_client/endpoint_client/endpoint_store_keys.dart @@ -0,0 +1,14 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/// Keys used to store info about the endpoint version store. +enum EndpointStoreKey { + /// The current version of the endpoint version store + version, +} + +/// The endpoint store version. +enum EndpointStoreVersion { + /// The initial implementation of endpoint version store in Amplify Flutter Analytics. + v1, +} diff --git a/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/impl/flutter_provider_interfaces/legacy_native_data_provider.dart b/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/impl/flutter_provider_interfaces/legacy_native_data_provider.dart new file mode 100644 index 0000000000..9fb9e4717c --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/impl/flutter_provider_interfaces/legacy_native_data_provider.dart @@ -0,0 +1,10 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:async'; + +/// {@template amplify_analytics_pinpoint.flutter_legacy_native_data_provider} +abstract class LegacyNativeDataProvider { + /// Get stored Pinpoint Endpoint Id + Future getEndpointId(String pinpointAppId); +} diff --git a/packages/analytics/amplify_analytics_pinpoint_dart/pubspec.yaml b/packages/analytics/amplify_analytics_pinpoint_dart/pubspec.yaml index 5a9bf9e2f2..dd7a1d1faa 100644 --- a/packages/analytics/amplify_analytics_pinpoint_dart/pubspec.yaml +++ b/packages/analytics/amplify_analytics_pinpoint_dart/pubspec.yaml @@ -32,6 +32,7 @@ dev_dependencies: build_version: ^2.0.0 built_value_generator: 8.4.2 drift_dev: ^2.2.0+1 + mocktail: ^0.3.0 test: ^1.16.0 # TODO - use cipher libraries for encrypted cached Analytics Events diff --git a/packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart b/packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart new file mode 100644 index 0000000000..7bd9f4ba0d --- /dev/null +++ b/packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart @@ -0,0 +1,139 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:async'; +import 'dart:io'; + +import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'; +import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_store_keys.dart'; +import 'package:amplify_core/amplify_core.dart'; +import 'package:amplify_secure_storage_dart/amplify_secure_storage_dart.dart'; +import 'package:drift/drift.dart' show LazyDatabase; +import 'package:drift/native.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; + +void main() { + group('Analytics Legacy Native Data Tests', () { + late MockLegacyNativeDataProvider legacyDataProvider; + late MockSecureStorage store; + + const appId = 'appId'; + const legacyEndpointId = 'legacy-endpointId'; + + setUp(() { + legacyDataProvider = MockLegacyNativeDataProvider(); + store = MockSecureStorage(); + }); + + test('First app load, no legacy data, writes proper values', () async { + when(() => legacyDataProvider.getEndpointId(appId)) + .thenAnswer((_) async => null); + + final analyticsPlugin = AmplifyAnalyticsPinpointDart( + endpointInfoStore: store, + legacyNativeDataProvider: legacyDataProvider, + dbConnectFunction: ({required String name, FutureOr? path}) { + return _openConnection(); + }, + ); + await analyticsPlugin.retrieveEndpointId(pinpointAppId: appId); + + final storeVersion = await store.read( + key: EndpointStoreKey.version.name, + ); + expect(storeVersion, EndpointStoreVersion.v1.name); + + final migratedEndpointId = await store.read( + key: AmplifyAnalyticsPinpointDart.endpointIdStorageKey, + ); + expect(migratedEndpointId, isNotNull); + + verify(() => legacyDataProvider.getEndpointId(appId)).called(1); + }); + + test('First app load, legacy data, writes proper values', () async { + when(() => legacyDataProvider.getEndpointId(appId)) + .thenAnswer((_) => Future.value(legacyEndpointId)); + + final analyticsPlugin = AmplifyAnalyticsPinpointDart( + endpointInfoStore: store, + legacyNativeDataProvider: legacyDataProvider, + dbConnectFunction: ({required String name, FutureOr? path}) { + return _openConnection(); + }, + ); + await analyticsPlugin.retrieveEndpointId(pinpointAppId: appId); + + final storeVersion = await store.read( + key: EndpointStoreKey.version.name, + ); + expect(storeVersion, EndpointStoreVersion.v1.name); + + final migratedEndpointId = await store.read( + key: AmplifyAnalyticsPinpointDart.endpointIdStorageKey, + ); + expect(migratedEndpointId, legacyEndpointId); + + verify(() => legacyDataProvider.getEndpointId(appId)).called(1); + }); + + test('Second app load, legacy data is ignored', () async { + when(() => legacyDataProvider.getEndpointId(appId)) + .thenAnswer((_) => Future.value(legacyEndpointId)); + + final endpointId = uuid(); + store.seedData({ + EndpointStoreKey.version.name: EndpointStoreVersion.v1.name, + AmplifyAnalyticsPinpointDart.endpointIdStorageKey: endpointId + }); + + final analyticsPlugin = AmplifyAnalyticsPinpointDart( + endpointInfoStore: store, + legacyNativeDataProvider: legacyDataProvider, + dbConnectFunction: ({required String name, FutureOr? path}) { + return _openConnection(); + }, + ); + await analyticsPlugin.retrieveEndpointId(pinpointAppId: appId); + + final migratedEndpointId = await store.read( + key: AmplifyAnalyticsPinpointDart.endpointIdStorageKey, + ); + expect(migratedEndpointId, endpointId); + + verifyNever(() => legacyDataProvider.getEndpointId(any())); + }); + }); +} + +LazyDatabase _openConnection() { + // the LazyDatabase util lets us find the right location for the file async. + return LazyDatabase(() async { + final file = File('db.sqlite'); + return NativeDatabase.createInBackground(file); + }); +} + +class MockLegacyNativeDataProvider extends Mock + implements LegacyNativeDataProvider {} + +class MockSecureStorage extends Mock implements SecureStorageInterface { + MockSecureStorage(); + + final Map _data = {}; + + void seedData(Map data) { + _data.addAll(data); + } + + @override + FutureOr read({required String key}) { + return _data[key]; + } + + @override + FutureOr write({required String key, required String value}) { + _data[key] = value; + } +}