Skip to content

Commit a2ab4dc

Browse files
committed
Add logic for Analytics parameters with maps
1 parent 2437818 commit a2ab4dc

File tree

3 files changed

+157
-38
lines changed

3 files changed

+157
-38
lines changed

analytics/src/analytics_android.cc

Lines changed: 90 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,93 @@ void AddToBundle(JNIEnv* env, jobject bundle, const char* key, int64_t value) {
355355
env->DeleteLocalRef(key_string);
356356
}
357357

358+
void AddArrayListToBundle(JNIEnv* env, jobject bundle, const char* key, jobject arraylist) {
359+
jstring key_string = env->NewStringUTF(key);
360+
env->CallVoidMethod(bundle, util::bundle::GetMethodId(util::bundle::kPutParcelableArrayList),
361+
key_string, arraylist);
362+
util::CheckAndClearJniExceptions(env);
363+
env->DeleteLocalRef(key_string);
364+
}
365+
366+
void AddBundleToBundle(JNIEnv* env, jobject bundle, const char* key, jobject inner_bundle) {
367+
jstring key_string = env->NewStringUTF(key);
368+
env->CallVoidMethod(bundle, util::bundle::GetMethodId(util::bundle::kPutBundle),
369+
key_string, inner_bundle);
370+
util::CheckAndClearJniExceptions(env);
371+
env->DeleteLocalRef(key_string);
372+
}
373+
374+
jobject MapToBundle(JNIEnv* env, const std::map<Variant, Variant>& map);
375+
376+
jobject VectorToArrayList(JNIEnv* env, const std::vector<Variant>& vector) {
377+
jobject arraylist =
378+
env->NewObject(util::array_list::GetClass(),
379+
util::array_list::GetMethodId(util::array_list::kConstructor));
380+
381+
for (const Variant& element : vector) {
382+
if (element.is_map()) {
383+
jobject bundle = MapToBundle(env, element.map());
384+
env->CallBooleanMethod(arraylist, util::array_list::GetMethodId(util::array_list::kAdd),
385+
bundle);
386+
env->DeleteLocalRef(bundle);
387+
} else {
388+
LogError("VectorToArrayList: Unsupported type (%s) within vector.",
389+
Variant::TypeName(element.type()));
390+
}
391+
}
392+
return arraylist;
393+
}
394+
395+
bool AddVariantToBundle(JNIEnv* env, jobject bundle, const char* key, const Variant& value) {
396+
if (value.is_int64()) {
397+
AddToBundle(env, bundle, key, value.int64_value());
398+
} else if (value.is_double()) {
399+
AddToBundle(env, bundle, key,
400+
value.double_value());
401+
} else if (value.is_string()) {
402+
AddToBundle(env, bundle, key,
403+
value.string_value());
404+
} else if (value.is_bool()) {
405+
// Just use integer 0 or 1.
406+
AddToBundle(env, bundle, key,
407+
value.bool_value() ? static_cast<int64_t>(1L)
408+
: static_cast<int64_t>(0L));
409+
} else if (value.is_null()) {
410+
// Just use integer 0 for null.
411+
AddToBundle(env, bundle, key, static_cast<int64_t>(0L));
412+
} else if (value.is_vector()) {
413+
jobject arraylist = VectorToArrayList(env, value.vector());
414+
AddArrayListToBundle(env, bundle, key, arraylist);
415+
env->DeleteLocalRef(arraylist);
416+
} else if (value.is_map()) {
417+
jobject inner_bundle = MapToBundle(env, value.map());
418+
AddBundleToBundle(env, bundle, key, inner_bundle);
419+
env->DeleteLocalRef(inner_bundle);
420+
} else {
421+
// A Variant type that couldn't be handled was passed in.
422+
return false;
423+
}
424+
return true;
425+
}
426+
427+
jobject MapToBundle(JNIEnv* env, const std::map<Variant, Variant>& map) {
428+
jobject bundle =
429+
env->NewObject(util::bundle::GetClass(),
430+
util::bundle::GetMethodId(util::bundle::kConstructor));
431+
for (const auto& pair : map) {
432+
// Only add elements that use a string key
433+
if (!pair.first.is_string()) {
434+
continue;
435+
}
436+
if (!AddVariantToBundle(env, bundle, pair.first.string_value(), pair.second)) {
437+
LogError("MapToBundle: Unsupported type (%s) within map with key %s.",
438+
Variant::TypeName(pair.second.type()), pair.first.string_value());
439+
}
440+
util::CheckAndClearJniExceptions(env);
441+
}
442+
return bundle;
443+
}
444+
358445
// Log an event with one string parameter.
359446
void LogEvent(const char* name, const char* parameter_name,
360447
const char* parameter_value) {
@@ -404,27 +491,11 @@ void LogEvent(const char* name, const Parameter* parameters,
404491
LogEvent(env, name, [env, parameters, number_of_parameters](jobject bundle) {
405492
for (size_t i = 0; i < number_of_parameters; ++i) {
406493
const Parameter& parameter = parameters[i];
407-
if (parameter.value.is_int64()) {
408-
AddToBundle(env, bundle, parameter.name, parameter.value.int64_value());
409-
} else if (parameter.value.is_double()) {
410-
AddToBundle(env, bundle, parameter.name,
411-
parameter.value.double_value());
412-
} else if (parameter.value.is_string()) {
413-
AddToBundle(env, bundle, parameter.name,
414-
parameter.value.string_value());
415-
} else if (parameter.value.is_bool()) {
416-
// Just use integer 0 or 1.
417-
AddToBundle(env, bundle, parameter.name,
418-
parameter.value.bool_value() ? static_cast<int64_t>(1L)
419-
: static_cast<int64_t>(0L));
420-
} else if (parameter.value.is_null()) {
421-
// Just use integer 0 for null.
422-
AddToBundle(env, bundle, parameter.name, static_cast<int64_t>(0L));
423-
} else {
424-
// Vector or Map were passed in.
494+
if (!AddVariantToBundle(env, bundle, parameter.name, parameter.value)) {
495+
// A Variant type that couldn't be handled was passed in.
425496
LogError(
426497
"LogEvent(%s): %s is not a valid parameter value type. "
427-
"Container types are not allowed. No event was logged.",
498+
"No event was logged.",
428499
parameter.name, Variant::TypeName(parameter.value.type()));
429500
}
430501
}

analytics/src/analytics_ios.mm

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,67 @@ void LogEvent(const char* name) {
231231
[FIRAnalytics logEventWithName:@(name) parameters:@{}];
232232
}
233233

234+
NSDictionary* MapToDictionary(const std::map<Variant, Variant>& map);
235+
236+
NSArray* VectorToArray(const std::vector<Variant>& vector) {
237+
NSMutableArray* array = [NSMutableArray arrayWithCapacity:vector.size()];
238+
for (const Variant& element : vector) {
239+
if (element.is_map()) {
240+
NSDictionary* dict = MapToDictionary(element.map());
241+
[array addObject:dict];
242+
} else {
243+
LogError("VectorToArray: Unsupported type (%s) within vector.",
244+
Variant::TypeName(element.type()));
245+
}
246+
}
247+
return array;
248+
}
249+
250+
bool AddVariantToDictionary(NSMutableDictionary* dict, NSString* key, const Variant& value) {
251+
if (value.is_int64()) {
252+
[dict setObject:[NSNumber numberWithLongLong:value.int64_value()]
253+
forKey:key];
254+
} else if (value.is_double()) {
255+
[dict setObject:[NSNumber numberWithDouble:value.double_value()]
256+
forKey:key];
257+
} else if (value.is_string()) {
258+
[dict setObject:SafeString(value.string_value()) forKey:key];
259+
} else if (value.is_bool()) {
260+
// Just use integer 0 or 1.
261+
[dict setObject:[NSNumber numberWithLongLong:value.bool_value() ? 1 : 0]
262+
forKey:key];
263+
} else if (value.is_null()) {
264+
// Just use integer 0 for null.
265+
[dict setObject:[NSNumber numberWithLongLong:0] forKey:key];
266+
} else if (value.is_vector()) {
267+
NSArray* array = VectorToArray(value.vector());
268+
[dict setObject:array forKey:key];
269+
} else if (value.is_map()) {
270+
NSDictionary* inner_dict = MapToDictionary(value.map());
271+
[dict setObject:inner_dict forKey:key];
272+
} else {
273+
// A Variant type that couldn't be handled was passed in.
274+
return false;
275+
}
276+
return true;
277+
}
278+
279+
NSDictionary* MapToDictionary(const std::map<Variant, Variant>& map) {
280+
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:map.size()];
281+
for (const auto& pair : map) {
282+
// Only add elements that use a string key
283+
if (!pair.first.is_string()) {
284+
continue;
285+
}
286+
NSString* key = SafeString(pair.first.string_value());
287+
const Variant& value = pair.second;
288+
if (!AddVariantToDictionary(dict, key, value)) {
289+
LogError("MapToDictionary: Unsupported type (%s) within map with key %s.",
290+
Variant::TypeName(value.type()), key);
291+
}
292+
}
293+
}
294+
234295
// Log an event with associated parameters.
235296
void LogEvent(const char* name, const Parameter* parameters, size_t number_of_parameters) {
236297
FIREBASE_ASSERT_RETURN_VOID(internal::IsInitialized());
@@ -239,25 +300,10 @@ void LogEvent(const char* name, const Parameter* parameters, size_t number_of_pa
239300
for (size_t i = 0; i < number_of_parameters; ++i) {
240301
const Parameter& parameter = parameters[i];
241302
NSString* parameter_name = SafeString(parameter.name);
242-
if (parameter.value.is_int64()) {
243-
[parameters_dict setObject:[NSNumber numberWithLongLong:parameter.value.int64_value()]
244-
forKey:parameter_name];
245-
} else if (parameter.value.is_double()) {
246-
[parameters_dict setObject:[NSNumber numberWithDouble:parameter.value.double_value()]
247-
forKey:parameter_name];
248-
} else if (parameter.value.is_string()) {
249-
[parameters_dict setObject:SafeString(parameter.value.string_value()) forKey:parameter_name];
250-
} else if (parameter.value.is_bool()) {
251-
// Just use integer 0 or 1.
252-
[parameters_dict setObject:[NSNumber numberWithLongLong:parameter.value.bool_value() ? 1 : 0]
253-
forKey:parameter_name];
254-
} else if (parameter.value.is_null()) {
255-
// Just use integer 0 for null.
256-
[parameters_dict setObject:[NSNumber numberWithLongLong:0] forKey:parameter_name];
257-
} else {
258-
// Vector or Map were passed in.
303+
if (!AddVariantToDictionary(parameters_dict, parameter_name, parameter.value)){
304+
// A Variant type that couldn't be handled was passed in.
259305
LogError("LogEvent(%s): %s is not a valid parameter value type. "
260-
"Container types are not allowed. No event was logged.",
306+
"No event was logged.",
261307
parameter.name, Variant::TypeName(parameter.value.type()));
262308
}
263309
}

app/src/util_android.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,9 @@ METHOD_LOOKUP_DECLARATION(activity, ACTIVITY_METHODS)
498498
X(PutFloat, "putFloat", "(Ljava/lang/String;F)V"), \
499499
X(PutLong, "putLong", "(Ljava/lang/String;J)V"), \
500500
X(PutString, "putString", "(Ljava/lang/String;Ljava/lang/String;)V"), \
501-
X(PutBundle, "putBundle", "(Ljava/lang/String;Landroid/os/Bundle;)V")
501+
X(PutBundle, "putBundle", "(Ljava/lang/String;Landroid/os/Bundle;)V"),\
502+
X(PutParcelableArrayList, "putParcelableArrayList", \
503+
"(Ljava/lang/String;Ljava/util/ArrayList;)V")
502504
// clang-format on
503505
METHOD_LOOKUP_DECLARATION(bundle, BUNDLE_METHODS)
504506

0 commit comments

Comments
 (0)