加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在C/C++中接收完整的android unicode输入

发布时间:2020-12-16 05:00:53 所属栏目:百科 来源:网络整理
导读:( Android,NDK,C,OpenGL ES) 我需要一种方法可靠地从(软)键盘接收文本输入. 解决方案可以通过Java使用NativeActivity子类或任何有效的方法. 最后我需要输入任何文本,所以我可以用OpenGL自己渲染它 一些背景: 到目前为止,我通过调用showSoftInput或hideSoftI
( Android,NDK,C,OpenGL ES)

我需要一种方法可靠地从(软)键盘接收文本输入.
解决方案可以通过Java使用NativeActivity子类或任何有效的方法.
最后我需要输入任何文本,所以我可以用OpenGL自己渲染它

一些背景:
到目前为止,我通过调用showSoftInput或hideSoftInputFromWindow来调用JNI来触发软键盘.这到目前为止从未失败过.
但是,问题是本机活动不会发送所有字符.特别是ASCII范围之外的一些unicode字符,或某些运动软键盘不起作用(AKeyEvent_getKeyCode)

以前可以获取一些其他unicode字符,以便检查KeyEvent.ACTION_MULTIPLE并读取一串字符.
但即使这样也不会再可靠.

到目前为止,我没有找到替代方法.
我尝试以编程方式添加EditText,但从未让它工作.即使尝试添加一个简单的Button也导致OpenGL视图不再被渲染.

在iOS上我通过隐藏编辑框来解决它,我只是激活它以使键盘显示.然后我会读出编辑框并使用字符串在OpenGL中渲染自己.

解决方法

我有同样的问题,我使用’Character’事件解决了它,我将事件与InputEvent分开处理.

问题是:AKeyEvent_getKeyCode不会返回某些软键事件的KeyCode,特别是按住键时扩展的“unicode / latin”字符.这可以防止方法@Shammi和@eozgonul工作,因为在Java端重建的KeyEvent没有足够的信息来获取unicode字符.

另一个问题是在触发dispatchKeyEvent事件之前,在C / Native端排出了InputQueue.这意味着KEYDOWN / KEYUP事件在Java代码可以处理事件之前全部触发. (它们不是交错的).

我的解决方案是通过重写dispatchKeyEvent并将字符发送到Queue< Integer>来捕获Java端的unicode字符. queueLastInputCharacter = new ConcurrentLinkedQueue< Integer>();

// [JAVA]
@Override
public boolean dispatchKeyEvent (KeyEvent event)
{
    int metaState = event.getMetaState(); 
    int unichar = event.getUnicodeChar(metaState);

    // We are queuing the Unicode version of the characters for
    // sending to the app during processEvents() call.

    // We Queue the KeyDown and ActionMultiple Event UnicodeCharacters
    if(event.getAction()==KeyEvent.ACTION_DOWN){
        if(unichar != 0){
            queueLastInputCharacter.offer(Integer.valueOf(unichar));
        }
        else{
            unichar = event.getUnicodeChar(); 

            if(unichar != 0){
                queueLastInputCharacter.offer(Integer.valueOf(unichar));
            }
            else if (event.getDisplayLabel() != 0){
                String aText = new String();
                aText = "";
                aText += event.getDisplayLabel();
                queueLastInputCharacter.offer(Integer.valueOf(Character.codePointAt(aText,0)));
            }
            else
                queueLastInputCharacter.offer(Integer.valueOf(0));
        }
    }
    else if(event.getAction()==KeyEvent.ACTION_MULTIPLE){
        unichar = (Character.codePointAt(event.getCharacters(),0));
        queueLastInputCharacter.offer(Integer.valueOf(unichar));
    }


    return super.dispatchKeyEvent(event);
}

并发队列将让线程一起玩得很好.

我有一个Java方法返回最后一个输入字符:

// [JAVA]
public int getLastUnicodeChar(){
    if(!queueLastInputCharacter.isEmpty())
        return queueLastInputCharacter.poll().intValue();
    return 0;
}

在我的looper代码结束时,我进行了额外的检查以查看队列是否保留了任何unicode字符:

// [C++]
int ident;
int events;
struct android_poll_source* source;

// If not rendering,we will block 250ms waiting for events.
// If animating,we loop until all events are read,then continue
// to draw the next frame of animation.
while ((ident = ALooper_pollAll(((nv_app_status_focused(_lpApp)) ? 1 : 250),NULL,&events,(void**)&source)) >= 0)
{
    // Process this event.
    if (source != NULL)
        source->process(_lpApp,source);

    // Check if we are exiting.  If so,dump out
    if (!nv_app_status_running(_lpApp))
        return;
}

static int modtime = 10; // let's not run on every call
if(--modtime == 0) {
    long uniChar = androidUnicodeCharFromKeyEvent();
    while (uniChar != 0) {
        KEvent kCharEvent; // Game engine event
        kCharEvent.ptkKey = K_VK_ERROR;
        kCharEvent.unicodeChar = uniChar;
        kCharEvent.character = uniChar;

        /* Send unicode char */
        kCharEvent.type = K_EVENT_UNICHAR;
        _lpPortableHandler(&kCharEvent);

        if (kCharEvent.character < 127) {
            /* Send ascii char for source compatibility as well */
            kCharEvent.type = K_EVENT_CHAR;
            _lpPortableHandler(&kCharEvent);
        }

        uniChar = androidUnicodeCharFromKeyEvent();
    }
    modtime = 10;
}

androidUnicodeCharFromKeyEvent函数与@Shammi的GetStringFromAInputEvent方法非常相似,只使用CallIntMethod来返回jint.

笔记
这确实需要修改引擎以处理与Key事件分开的字符事件. Android仍然有像AKEYCODE_BACK或AKEYCODE_ENTER这样的密钥代码,它们不是字符事件,仍然需要处理(并且可以在主输入循环器上处理).

编辑框,控制台等…可以修改期望用户输入的内容以接收构建字符串的单独字符事件.如果您在多个平台上工作,那么除了普通的键输入事件之外,您还需要生成这些新的字符事件.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读