Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ interface FirebaseAnalyticsHostApi {
fun getAppInstanceId(callback: (Result<String?>) -> Unit)
fun getSessionId(callback: (Result<Long?>) -> Unit)
fun initiateOnDeviceConversionMeasurement(arguments: Map<String, String?>, callback: (Result<Unit>) -> Unit)
fun logTransaction(transactionId: String, callback: (Result<Unit>) -> Unit)

companion object {
/** The codec used by FirebaseAnalyticsHostApi. */
Expand Down Expand Up @@ -363,6 +364,25 @@ interface FirebaseAnalyticsHostApi {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val transactionIdArg = args[0] as String
api.logTransaction(transactionIdArg) { result: Result<Unit> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(GeneratedAndroidFirebaseAnalyticsPigeonUtils.wrapError(error))
} else {
reply.reply(GeneratedAndroidFirebaseAnalyticsPigeonUtils.wrapResult(null))
}
}
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ protocol FirebaseAnalyticsHostApi {
func getSessionId(completion: @escaping (Result<Int64?, Error>) -> Void)
func initiateOnDeviceConversionMeasurement(arguments: [String: String?],
completion: @escaping (Result<Void, Error>) -> Void)
func logTransaction(transactionId: String, completion: @escaping (Result<Void, Error>) -> Void)
}

/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
Expand Down Expand Up @@ -459,5 +460,26 @@ class FirebaseAnalyticsHostApiSetup {
} else {
initiateOnDeviceConversionMeasurementChannel.setMessageHandler(nil)
}
let logTransactionChannel = FlutterBasicMessageChannel(
name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction\(channelSuffix)",
binaryMessenger: binaryMessenger,
codec: codec
)
if let api {
logTransactionChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let transactionIdArg = args[0] as! String
api.logTransaction(transactionId: transactionIdArg) { result in
switch result {
case .success:
reply(wrapResult(nil))
case let .failure(error):
reply(wrapError(error))
}
}
}
} else {
logTransactionChannel.setMessageHandler(nil)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import firebase_core_shared
#endif
import FirebaseAnalytics
import StoreKit

let kFLTFirebaseAnalyticsName = "name"
let kFLTFirebaseAnalyticsValue = "value"
Expand All @@ -28,6 +29,8 @@ let kFLTFirebaseAnalyticsUserId = "userId"

let FLTFirebaseAnalyticsChannelName = "plugins.flutter.io/firebase_analytics"

extension FlutterError: Error {}

public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, FlutterPlugin,
FirebaseAnalyticsHostApi {
public static func register(with registrar: any FlutterPluginRegistrar) {
Expand Down Expand Up @@ -142,6 +145,79 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt
completion(.success(()))
}

func logTransaction(transactionId: String,
completion: @escaping (Result<Void, any Error>) -> Void) {
#if os(macOS)
if #available(macOS 12.0, *) {
logTransactionWithStoreKit(transactionId: transactionId, completion: completion)
} else {
completion(.failure(FlutterError(
code: "firebase_analytics",
message: "logTransaction() is only supported on macOS 12.0 or newer",
details: nil
)))
}
#else
if #available(iOS 15.0, *) {
logTransactionWithStoreKit(transactionId: transactionId, completion: completion)
} else {
completion(.failure(FlutterError(
code: "firebase_analytics",
message: "logTransaction() is only supported on iOS 15.0 or newer",
details: nil
)))
}
#endif
}

#if os(macOS)
@available(macOS 12.0, *)
#else
@available(iOS 15.0, *)
#endif
private func logTransactionWithStoreKit(transactionId: String,
completion: @escaping (Result<Void, any Error>) -> Void) {
Task {
do {
guard let id = UInt64(transactionId) else {
completion(.failure(FlutterError(
code: "firebase_analytics",
message: "Invalid transactionId",
details: nil
)))
return
}

var foundTransaction: Transaction?
for await result in Transaction.all {
switch result {
case let .verified(transaction):
if transaction.id == id {
foundTransaction = transaction
break
}
case .unverified:
continue
}
}

guard let transaction = foundTransaction else {
completion(.failure(FlutterError(
code: "firebase_analytics",
message: "Transaction not found",
details: nil
)))
return
}

Analytics.logTransaction(transaction)
completion(.success(()))
} catch {
completion(.failure(error))
}
}
}

public func didReinitializeFirebaseCore(_ completion: @escaping () -> Void) {
completion()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,23 @@ class FirebaseAnalytics extends FirebasePluginPlatform {
);
}

/// Logs verified in-app purchase events in Google Analytics for Firebase
/// after a purchase is successful.
///
/// Only available on iOS.
///
/// You can obtain the [transactionId] from the
/// [in_app_purchase](https://pub.dev/packages/in_app_purchase) package.
Future<void> logTransaction(String transactionId) async {
if (defaultTargetPlatform != TargetPlatform.iOS &&
defaultTargetPlatform != TargetPlatform.macOS) {
throw UnimplementedError(
'logTransaction() is only supported on iOS and macOS.',
);
}
return _delegate.logTransaction(transactionId: transactionId);
}

/// Sets the duration of inactivity that terminates the current session.
///
/// The default value is 1800000 milliseconds (30 minutes).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,45 @@ void FirebaseAnalyticsHostApi::SetUp(
channel.SetMessageHandler(nullptr);
}
}
{
BasicMessageChannel<> channel(
binary_messenger,
"dev.flutter.pigeon.firebase_analytics_platform_interface."
"FirebaseAnalyticsHostApi.logTransaction" +
prepended_suffix,
&GetCodec());
if (api != nullptr) {
channel.SetMessageHandler(
[api](const EncodableValue& message,
const flutter::MessageReply<EncodableValue>& reply) {
try {
const auto& args = std::get<EncodableList>(message);
const auto& encodable_transaction_id_arg = args.at(0);
if (encodable_transaction_id_arg.IsNull()) {
reply(WrapError("transaction_id_arg unexpectedly null."));
return;
}
const auto& transaction_id_arg =
std::get<std::string>(encodable_transaction_id_arg);
api->LogTransaction(
transaction_id_arg,
[reply](std::optional<FlutterError>&& output) {
if (output.has_value()) {
reply(WrapError(output.value()));
return;
}
EncodableList wrapped;
wrapped.push_back(EncodableValue());
reply(EncodableValue(std::move(wrapped)));
});
} catch (const std::exception& exception) {
reply(WrapError(exception.what()));
}
});
} else {
channel.SetMessageHandler(nullptr);
}
}
}

EncodableValue FirebaseAnalyticsHostApi::WrapError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ class FirebaseAnalyticsHostApi {
virtual void InitiateOnDeviceConversionMeasurement(
const flutter::EncodableMap& arguments,
std::function<void(std::optional<FlutterError> reply)> result) = 0;
virtual void LogTransaction(
const std::string& transaction_id,
std::function<void(std::optional<FlutterError> reply)> result) = 0;

// The codec used by FirebaseAnalyticsHostApi.
static const flutter::StandardMessageCodec& GetCodec();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,15 @@ class MethodChannelFirebaseAnalytics extends FirebaseAnalyticsPlatform {
convertPlatformException(e, s);
}
}

@override
Future<void> logTransaction({
required String transactionId,
}) {
try {
return _api.logTransaction(transactionId);
} catch (e, s) {
convertPlatformException(e, s);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -416,4 +416,30 @@ class FirebaseAnalyticsHostApi {
return;
}
}

Future<void> logTransaction(String transactionId) async {
final String pigeonVar_channelName =
'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel =
BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[transactionId]);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,10 @@ abstract class FirebaseAnalyticsPlatform extends PlatformInterface {
'initiateOnDeviceConversionMeasurement() is not implemented',
);
}

Future<void> logTransaction({
required String transactionId,
}) {
throw UnimplementedError('logTransaction() is not implemented');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,7 @@ abstract class FirebaseAnalyticsHostApi {

@async
void initiateOnDeviceConversionMeasurement(Map<String, String?> arguments);

@async
void logTransaction(String transactionId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ abstract class TestFirebaseAnalyticsHostApi {
Future<void> initiateOnDeviceConversionMeasurement(
Map<String, String?> arguments);

Future<void> logTransaction(String transactionId);

static void setUp(
TestFirebaseAnalyticsHostApi? api, {
BinaryMessenger? binaryMessenger,
Expand Down Expand Up @@ -409,5 +411,37 @@ abstract class TestFirebaseAnalyticsHostApi {
});
}
}
{
final BasicMessageChannel<
Object?> pigeonVar_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
_testBinaryMessengerBinding!.defaultBinaryMessenger
.setMockDecodedMessageHandler<Object?>(pigeonVar_channel, null);
} else {
_testBinaryMessengerBinding!.defaultBinaryMessenger
.setMockDecodedMessageHandler<Object?>(pigeonVar_channel,
(Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_transactionId = (args[0] as String?);
assert(arg_transactionId != null,
'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction was null, expected non-null String.');
try {
await api.logTransaction(arg_transactionId!);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
}
}
Loading
Loading