从C使用NDK ++更新的Andr​​oid UI [英] Using NDK from C++ updating Android UI

查看:200
本文介绍了从C使用NDK ++更新的Andr​​oid UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是直接关系到这个帖子: https://开头组.google.com /论坛/#!话题/ Android的NDK / 291sBdkITyI

My question is related directly to this post: https://groups.google.com/forum/#!topic/android-ndk/291sBdkITyI

基本上,我有写在C编译NDK的一个基本的Andr​​oid(活动)的应用程序++。我有需要的时候什么东西在C ++侧发生(例如说一个状态的改变)要更新一个TextView(在Java中)。我想从C ++调用Java和更新的TextView时的状态变化。

Basically, I have an application written in C++ compiled with the NDK with a basic Android (activity). I have a textview (in Java) that needs to be updated when something happens in the c++ side (say for example a state change). I would like to call Java from C++ and update the textview when the state changes.

在上面的链接,他们用code是(可能是伪code):

In the link above, the code they used was (probably pseudo code):

public class Example extends Activity{    

    Handler handler = new Handler() {

         @Override
         public void handleMessage(Message msg) {
             this.currentDownloadField.setText(""+ msg.what);
         }

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // whatever
    }   

    public static void sendMessage(int  id){ 
         handler.sendEmptyMessage(id); // just the what() is filled with the id
    }
}

和从C ++调用会

void sendMessage(char* buffer, int bufferlen) {
    JNIEnv *env = NULL;
    jmethodID mid = NULL;
    jbyteArray message;

    jint res = (jjvm->AttachCurrentThread(&jjvm, &env, NULL));

    if (res >= 0) {
        message = (*env)->NewByteArray(env, bufferlen);
        (*env)->SetByteArrayRegion(env, message, 0, bufferlen, (const jbyte *) ((BYTE*) buffer));
        mid = (*env)->GetStaticMethodID(env, jcls, "sendMessage", "([B)V");

        // Mid <= 0 ? Not found : OK
        if (mid > 0) {
        (*env)->CallStaticVoidMethod(env, jcls, mid, message);
        }
    }
}

问题是在使用活动处理程序从静态功能不起作用(因为它不是静态的)。如果是静态的,那么如何this.currentDownloadFieldGET引用?

The problem is using "handler" in the activity from a static function does not work (because it is not static). If it was static, then how does "this.currentDownloadField" get referenced?

我也尝试从C只调用公共职能++

I also tried just calling a public function from c++

public void update(String message) {
    Log.i("logging", "Hit here")
    mMyTextField.setText(message);
}

在C ++调用Java函数更新,日志命中(在logcat中),但TextView中不会更新。也许这是线程一个问题,但我不知道如何正确地更新文本框。

When C++ calls the Java function "update", the log hits (in logcat) but the textview does not update. Maybe it is an issue with threads but I have no idea how to update the textfield correctly.

另一种选择是轮询,并有Java调用C ++来读取一个变量(状态),但是这是乏味的,而不是良好的编程习惯。

The other option is to poll and have Java call C++ to read a variable (state) however that is tedious and not good programming practice.

任何建议,以解决呢?

先谢谢了。

推荐答案

您是对的,你必须调用 mMyTextField.setText()从UI线程。 Android的Java类提供多种方式来做到这一点,例如 View.post() Handler.post()或<一href=\"http://developer.android.com/reference/android/os/Handler.html#sendMessage(android.os.Message)\"相对=nofollow> Handler.sendMessage(),或<一个href=\"http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)\"相对=nofollow> Activity.runOnUiThread()。这些方法都不是的静态后,他们都需要一个现场的这个对象的工作。

You are right, you must call mMyTextField.setText() from UI thread. Android Java classes provide multiple ways to do it, e.g. View.post() or Handler.post() or Handler.sendMessage(), or Activity.runOnUiThread(). None of these methods is static, they all need a live this object to work.

有解决这一供您使用不同的方法。也许是微小到你的code会去如下:

There are different approaches to resolve this for your purpose. Probably the minimal change to your code will go as follows:

public class Example extends Activity {

    private static Handler staticHandler;
    private TextView currentDownloadField;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                this.currentDownloadField.setText(""+ msg.what);
            }
        }
        staticHandler = handler;
        setContentView(R.layout.main_view);
        currentDownloadField = (TextView)findViewById(R.id.download_field);
    }

    @Override
    protected void onDestroy() {
        staticHandler = null;
    }

    public static void sendMessage(int id) {
        staticHandler.sendEmptyMessage(id); // just the what() is filled with the id
    }
}

在上面的code,错误检查跳过简洁。

In the code above, error checking is skipped for brevity.

另外,你可以通过引用您的活动(或处理,或downloadFiled)C库,而是调用的 CallStaticVoidMethod()你会使用对象全球参考,并使用 CallVoidMethod(ENV,jactivityObj,中旬,消息)

Alternatively, you could pass the reference to your activity (or handler, or downloadFiled) to the C library, and instead of calling CallStaticVoidMethod() you would use the object global reference and use CallVoidMethod(env, jactivityObj, mid, message).

PS 我只是奇怪,你怎么指望你的系统,如果你发送一个 jbyteArray (在Java中工作,这是字节[] ),以期望一个回调方法 INT

PS I just wonder, how you expect you system to work if you send a jbyteArray (in Java, that's byte[]) to a callback method that expects int?

更新简单的code以上受的处理程序泄漏的,因此,如果你想重新使用它在生产中,请包括的静态内部类包装围绕处理器

Update The simple code above is subject to Handler Leak, thus if you want to reuse it in production, please include a static inner class wrapper around the Handler.

这篇关于从C使用NDK ++更新的Andr​​oid UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆