Android NDK 回调到 Java Activity

3
我正在移植我的一个应用程序,因此大部分工作都在应用程序的本地部分完成,Java端只是用于我的UI。
目前我想要实现一个ProgressBar,它将显示本地线程操作的状态。UI由不同的Activity组成,我打算从这些Activity中显示ProgressBar。
问题是:我该怎么做?我有以下一些本地代码:
jclass clazz = emv->FindClass( "com/example/myapp/MainActivity" );

该代码返回clazz为空值。我意识到此时未显示MainActivity活动,而是我的SettingsActivity的一个实例,因此我试图相应更改上述代码行,但仍返回null。

无法从本地代码中调用FindClass()以检索Activity类吗?

最终我认为我需要做的是调用以下方法:

  public void ProgressUpdateFromNative( int i )
  {
    runOnUiThread( new Runnable()
    {
      @Override
      public void run()
      {
        DisplayProgressUpdate();
      }
    } );
  }

这是我的一个Activity中的方法。

jmethodID ProgressUpdateFromNative = env->GetMethodID( clazz, "ProgressUpdateFromNative", "(I)V");
env->CallObjectMethod( g_pObj, ProgressUpdateFromNative, 1 ) ;

我从onLoad() JNI调用中检索了JavaVM指针,并调用了JavaVM->AttachCurrentThread()以检索上述使用的env指针。

请问有人可以告诉我缺少什么 - 也就是为什么我从FindClass返回null类,或者如果我做错了,请给我提供不同的方向。我打算再研究一下Handler,但我认为我对它的理解还不够深入。

注意:我确实可以从Java UI轮询一些本地变量,但我更喜欢回调/事件处理的实现,而不是轮询。


你的本地代码在哪里调用了 FindClass() 方法? - HHK
@Hans Kratz:我有一个pthread正在处理从Java Activity发送到本地线程的消息。本地线程在循环中持续运行,并处理来自Java UI的任何消息。 - SparkyNZ
1个回答

2

我认为你得到了正确的答案。只是在翻阅我的 NDK Cookbook 时,我注意到 FindClass() 在 OnLoad() 函数中被调用了 MainActivity 上。我不知道 NewGlobalRef 是什么,但我会进行一些阅读和搜索。 - SparkyNZ
1
在JNI中对Java对象(如类)的引用通常只在获取它们的帧存在期间有效。为了延长其生命周期,您需要创建一个全局引用。请注意,这将防止您创建全局引用的对象被垃圾回收。这就是为什么通过DeleteGlobalRef删除引用在您完成后很重要的原因。对于普通对象。 - HHK
@Hand Kratz:谢谢你。所以,如果我要获取一个Activity的全局引用,这会是一件非常糟糕的事情,对吧?我的MainActivity始终保持不变,但如果设备旋转,则会重新创建它 - 所以我将得到2个Activity对象持久存在,对吗?即使只有一个Activity是有效和当前的。我之前想知道是否可能在每次(重新)创建Activity时通过某种方式向我的本地代码“注册”一个Activity? - SparkyNZ
1
当然可以通过JNI在你的activity的onResume()方法中调用本地方法来设置当前活动。在你的本机代码中,你可以删除旧的全局引用(如果不为空),并为新的活动创建一个新的全局引用。然而:我建议只从你的本机代码回调到一个静态方法,并在Java中进行所有进一步的处理。这样你就可以避免NewGlobalRef/DeleteGlobalRef这些东西,除了对你的jclass的引用。 - HHK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接