android - Flurry Android 事件不是通过 NDK 记录而是通过 java 记录

标签 android c++ android-ndk flurry

我正在尝试将 Flurry 集成到 NativeActivity(非基于 Java 的代码)Android 应用程序中,但没有取得任何成功。我已经设置了一个基于 Java 的姐妹 flurry 测试 Activity ,效果很好,但 native 调用似乎是那些没有通过的调用

在 list 文件中,我有以下权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
package com.myTest.flurry;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.flurry.android.FlurryAgent;

public class FlurryActivity extends Activity {

    //code has correct api key here
    private static final String appKey = "xxxxxxxxxxxxxxxxxxxx";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flurry);
        FlurryAgent.onStartSession(this, appKey);
        FlurryAgent.setLogEnabled(true);
        FlurryAgent.setLogLevel(Log.VERBOSE);
        FlurryAgent.setLogEvents(true);
        FlurryAgent.logEvent("Starting up!");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        FlurryAgent.onEndSession(this);
    }
}

这足以让事件显示在 flurry 网站上。但是,当通过我的 native 代码调用相同的函数时,事件不会显示

#include "flurry.h"
#include <jni.h>
#include <android/native_activity.h>
#include <android_native_app_glue.h>
#include "log.h"

JNIEnv *GetEnv(JavaVM *jvm);
void DetachEnv(JavaVM *jvm);

Flurry::Flurry()
    : state_(0) {
}

jclass Flurry::GetFlurryAgentClass(JNIEnv *env) {
  // Extract the FlurryAgent class
  jobject nativeActivity = state_->activity->clazz;
  jclass acl = env->GetObjectClass(nativeActivity);
  // Get the classloader
  jmethodID getClassLoader = env->GetMethodID(acl, "getClassLoader", "()Ljava/lang/ClassLoader;");
  jobject cls = env->CallObjectMethod(nativeActivity, getClassLoader);
  jclass classLoader = env->FindClass("java/lang/ClassLoader");
  // find the loadclass function
  jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
  // Run the loadClass function for the flurry agent
  jstring strClassName = env->NewStringUTF("com/flurry/android/FlurryAgent");
  const char *path = env->GetStringUTFChars(strClassName, 0);
  // The following line will crash the app because it can't find the class files
  jclass flurry_agent_class = (jclass)(env->CallObjectMethod(cls, findClass, strClassName));
  env->DeleteLocalRef(strClassName);
  if (env->ExceptionCheck() || flurry_agent_class == 0) {
    Log("Failed to load flurry class!");
    env->ExceptionDescribe();
    env->ExceptionClear();
    return 0;
  }
  return flurry_agent_class;
}

void Flurry::SetStateAndStartSession(android_app *state) {
  state_ = state;
  JNIEnv *env = GetEnv(state->activity->vm);
  jclass flurry_agent_class = GetFlurryAgentClass(env);
  if (flurry_agent_class == 0) {
    return;
  }
  // Start session
  jmethodID onStartSession_method = env->GetStaticMethodID(flurry_agent_class, "onStartSession", "(Landroid/content/Context;Ljava/lang/String;)V");
  if (onStartSession_method) {
    jstring api_key_string = env->NewStringUTF("xxxxxxxxxxxxxxxxxxxx");
    Log("Starting native flurry");
    env->CallStaticVoidMethod(flurry_agent_class, onStartSession_method, state->activity->clazz, api_key_string);
    env->DeleteLocalRef(api_key_string);
  }
  // Set logging
  jmethodID setLogEnabled_method = env->GetStaticMethodID(flurry_agent_class, "setLogEnabled", "(Z)V");
  if (setLogEnabled_method) {
    env->CallStaticVoidMethod(flurry_agent_class, setLogEnabled_method, JNI_TRUE);
  }
  // Set logging
  jmethodID setLogLevel_method = env->GetStaticMethodID(flurry_agent_class, "setLogLevel", "(I)V");
  if (setLogLevel_method) {
    env->CallStaticVoidMethod(flurry_agent_class, setLogLevel_method, 2);
  }
  // Set events logging 
  jmethodID setLogEvents_method = env->GetStaticMethodID(flurry_agent_class, "setLogEvents", "(Z)V");
  if (setLogEvents_method) {
    env->CallStaticVoidMethod(flurry_agent_class, setLogEvents_method, JNI_TRUE);
  }
  // Set https 
  jmethodID setUseHttps_method = env->GetStaticMethodID(flurry_agent_class, "setUseHttps", "(Z)V");
  if (setUseHttps_method) {
    env->CallStaticVoidMethod(flurry_agent_class, setUseHttps_method, JNI_TRUE);
  }
  // Send the event
  const char *eventname = "Native interface start";
  jmethodID logEvent_method = env->GetStaticMethodID(flurry_agent_class, "logEvent", "(Ljava/lang/String;)V");
  if (logEvent_method) {
    Log("Sending Flurry Event: %s", eventname);
    jstring event_name = env->NewStringUTF(eventname);
    env->CallStaticVoidMethod(flurry_agent_class, logEvent_method, state_->activity->clazz, event_name);
    env->DeleteLocalRef(event_name);
  }
  //LogEvent("Starting up native interface");
}

void Flurry::EndSession() {
  // End session
  JNIEnv *env = GetEnv(state_->activity->vm);
  jclass flurry_agent_class = GetFlurryAgentClass(env);
  if (flurry_agent_class == 0) {
    return;
  }
  jmethodID onEndSession_method = env->GetStaticMethodID(flurry_agent_class, "onEndSession", "(Landroid/content/Context;)V");
  if (onEndSession_method) {
    Log("Ending flurry");
    env->CallStaticVoidMethod(flurry_agent_class, onEndSession_method, state_->activity->clazz);
  }
}

flurry 调用的输出日志似乎与基于 java 的调用一致:

示例日志输出:

I/FlurryAgent(25878): Agent cache file doesn't exist.
I/MyApp(25878): Starting native flurry
I/MyApp(25878): Sending Flurry Event: Native interface start
D/FlurryAgent(25878): generating report
D/FlurryAgent(25878): Sending report to: https://data.flurry.com/aap.do
D/FlurryAgent(25878): Report successful
D/FlurryAgent(25878): Done sending initial agent report
D/FlurryAgent(25878): Ending session

我完全不知道为什么来自 Java 的事件会出现而 Native 调用和事件却没有出现。请帮忙?谢谢

最佳答案

看来您正在使用错误的参数调用 logEvent 方法:

env->CallStaticVoidMethod(flurry_agent_class, logEvent_method, state_->activity->clazz, event_name);

应该是

env->CallStaticVoidMethod(flurry_agent_class, logEvent_method, event_name);

因为 FlurryAgent.logEvent 方法只接受一个字符串,而不是上下文。

关于android - Flurry Android 事件不是通过 NDK 记录而是通过 java 记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16362135/

相关文章:

c++ - 为什么这个对 swap() 的调用模棱两可?

c++ - 如何从键盘读取 C++ 中可变数量的整数?

带有 Linux : "ndk-build" command not found 的 Android NDK

android - 无法同步 Gradle 项目 - Android Studio 2.2

android - 手势识别器和 AndEngine (Android)

android - 如何在横向显示 AutoCompleteTextView 建议

android - 保留 fragment 状态

c++ - OpenGL + 多摄像头

android - 将项目添加到 C++ native 中的 ArrayList 会使单击监听器上的 android 应用程序崩溃

java - Android Room - 返回过去 30 天(1 个月) - java