@@ -355,6 +355,109 @@ void AddToBundle(JNIEnv* env, jobject bundle, const char* key, int64_t value) {
355355 env->DeleteLocalRef (key_string);
356356}
357357
358+ // Add an ArrayList to the given Bundle.
359+ void AddArrayListToBundle (JNIEnv* env, jobject bundle, const char * key,
360+ jobject arraylist) {
361+ jstring key_string = env->NewStringUTF (key);
362+ env->CallVoidMethod (
363+ bundle, util::bundle::GetMethodId (util::bundle::kPutParcelableArrayList ),
364+ key_string, arraylist);
365+ util::CheckAndClearJniExceptions (env);
366+ env->DeleteLocalRef (key_string);
367+ }
368+
369+ // Add a Bundle to the given Bundle.
370+ void AddBundleToBundle (JNIEnv* env, jobject bundle, const char * key,
371+ jobject inner_bundle) {
372+ jstring key_string = env->NewStringUTF (key);
373+ env->CallVoidMethod (bundle,
374+ util::bundle::GetMethodId (util::bundle::kPutBundle ),
375+ key_string, inner_bundle);
376+ util::CheckAndClearJniExceptions (env);
377+ env->DeleteLocalRef (key_string);
378+ }
379+
380+ // Declared here so that it can be used, defined below.
381+ jobject MapToBundle (JNIEnv* env, const std::map<Variant, Variant>& map);
382+
383+ // Converts the given vector into a Java ArrayList. It is up to the
384+ // caller to delete the local reference when done.
385+ jobject VectorOfMapsToArrayList (JNIEnv* env,
386+ const std::vector<Variant>& vector) {
387+ jobject arraylist = env->NewObject (
388+ util::array_list::GetClass (),
389+ util::array_list::GetMethodId (util::array_list::kConstructor ));
390+
391+ for (const Variant& element : vector) {
392+ if (element.is_map ()) {
393+ jobject bundle = MapToBundle (env, element.map ());
394+ env->CallBooleanMethod (
395+ arraylist, util::array_list::GetMethodId (util::array_list::kAdd ),
396+ bundle);
397+ util::CheckAndClearJniExceptions (env);
398+ env->DeleteLocalRef (bundle);
399+ } else {
400+ LogError (" VectorOfMapsToArrayList: Unsupported type (%s) within vector." ,
401+ Variant::TypeName (element.type ()));
402+ }
403+ }
404+ return arraylist;
405+ }
406+
407+ // Converts and adds the Variant to the given Bundle.
408+ bool AddVariantToBundle (JNIEnv* env, jobject bundle, const char * key,
409+ const Variant& value) {
410+ if (value.is_int64 ()) {
411+ AddToBundle (env, bundle, key, value.int64_value ());
412+ } else if (value.is_double ()) {
413+ AddToBundle (env, bundle, key, value.double_value ());
414+ } else if (value.is_string ()) {
415+ AddToBundle (env, bundle, key, value.string_value ());
416+ } else if (value.is_bool ()) {
417+ // Just use integer 0 or 1.
418+ AddToBundle (env, bundle, key,
419+ value.bool_value () ? static_cast <int64_t >(1L )
420+ : static_cast <int64_t >(0L ));
421+ } else if (value.is_null ()) {
422+ // Just use integer 0 for null.
423+ AddToBundle (env, bundle, key, static_cast <int64_t >(0L ));
424+ } else if (value.is_vector ()) {
425+ jobject arraylist = VectorOfMapsToArrayList (env, value.vector ());
426+ AddArrayListToBundle (env, bundle, key, arraylist);
427+ env->DeleteLocalRef (arraylist);
428+ } else if (value.is_map ()) {
429+ jobject inner_bundle = MapToBundle (env, value.map ());
430+ AddBundleToBundle (env, bundle, key, inner_bundle);
431+ env->DeleteLocalRef (inner_bundle);
432+ } else {
433+ // A Variant type that couldn't be handled was passed in.
434+ return false ;
435+ }
436+ return true ;
437+ }
438+
439+ // Converts the given map into a Java Bundle. It is up to the caller
440+ // to delete the local reference when done.
441+ jobject MapToBundle (JNIEnv* env, const std::map<Variant, Variant>& map) {
442+ jobject bundle =
443+ env->NewObject (util::bundle::GetClass (),
444+ util::bundle::GetMethodId (util::bundle::kConstructor ));
445+ for (const auto & pair : map) {
446+ // Only add elements that use a string key
447+ if (!pair.first .is_string ()) {
448+ continue ;
449+ }
450+ if (!AddVariantToBundle (env, bundle, pair.first .string_value (),
451+ pair.second )) {
452+ LogError (" MapToBundle: Unsupported type (%s) within map with key %s." ,
453+ Variant::TypeName (pair.second .type ()),
454+ pair.first .string_value ());
455+ }
456+ util::CheckAndClearJniExceptions (env);
457+ }
458+ return bundle;
459+ }
460+
358461// Log an event with one string parameter.
359462void LogEvent (const char * name, const char * parameter_name,
360463 const char * parameter_value) {
@@ -404,27 +507,11 @@ void LogEvent(const char* name, const Parameter* parameters,
404507 LogEvent (env, name, [env, parameters, number_of_parameters](jobject bundle) {
405508 for (size_t i = 0 ; i < number_of_parameters; ++i) {
406509 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.
510+ if (!AddVariantToBundle (env, bundle, parameter.name , parameter.value )) {
511+ // A Variant type that couldn't be handled was passed in.
425512 LogError (
426513 " LogEvent(%s): %s is not a valid parameter value type. "
427- " Container types are not allowed. No event was logged." ,
514+ " No event was logged." ,
428515 parameter.name , Variant::TypeName (parameter.value .type ()));
429516 }
430517 }
0 commit comments