马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 blurred 于 2025-10-4 13:16 编辑
前言:
1.此方法由"我"单独提出,实现,测试
2.本方案在Ren'py-8.3.7能够实现效果,如果使用,请注意引擎版本
3.涉及到修改引擎的代码,所以请在事前把引擎目录下的rapt相关文件备份
3.学习操作门槛:需要一定的java小基础以及了解Android应用的相关特性
(包括但不限于一些基础的apk知识,apk的文件结构以及其rapt各个文件作用和内容)
4.你使用了这个方案来屏蔽安全键盘,可以在游戏名单标上“浅唱”,不标也没关系
5.此方案还是有风险,具体看文尾
(其实是只要是修改了源码的都存在风险)
本帖参考:
一个Renpy游戏打包apk资源加密方案 - 经验教程 -
RenPy中文空间一个Renpy安卓打包游戏通过安卓平台审核方案 - 经验教程 - RenPy中文空间
包索引 | API 参考 | Android 开发者 --- Package Index | API reference | Android Developers
压缩包:(懒得看帖子可以一键解压即可食用)(内置食用教程和餐具)
https://www.renpy.cn/forum.php?mod=attachment&aid=MTY2OHxhOGRjYjUzYnwxNzU5NjEzNDUxfDB8
效果预览:
(注意我没有自己关闭安全键盘)
方法思路、代码讲解和配置教程:
配置教程在压缩包里面有
在renpy中,我们打包安卓游戏的时候时常会出现:
“欸,为什么我在游戏里面的输入框在手机上一直调用安全键盘?”
“啊啊啊我想要输入中文”
当我们需要输入中文只能让玩家自己去设置关闭安全键盘,这十分的不方便,所以我们需要修改renpy中关于安卓构建部分的源码
通过对安卓的认识,我们可以快速了解到安卓构建的对于安卓系统接口在ranpyandroid中,当我们观察renpy关于安卓的5355个文件,可以简单地注意到:
位于renpyandroid\src\main\java\org\libsdl\app的SDLActivity.java处理了安卓
应用生命周期管理(创建、暂停、恢复、销毁) 输入事件处理(触摸、键盘、传感器) 窗口管理、全屏控制 剪贴板、消息框、URL打开等系统功能
那么,我们阅读到以下代码,可以发现这里处理了虚拟文本编辑器视图,专门处理软键盘输入和硬件键盘事件。
[RenPy] 纯文本查看 复制代码 class DummyEdit extends View implements View.OnKeyListener {
InputConnection ic;
public DummyEdit(Context context) {
super(context);
setFocusableInTouchMode(true);
setFocusable(true);
setOnKeyListener(this);
}
@Override
public boolean onCheckIsTextEditor() {
return true;
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
/*
* This handles the hardware keyboard input
*/
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLActivity.isTextInputEvent(event)) {
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
return true;
}
SDLActivity.onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
SDLActivity.onNativeKeyUp(keyCode);
return true;
}
return false;
}
//
@Override
public boolean onKeyPreIme (int keyCode, KeyEvent event) {
// As seen on StackOverflow: [url=http://stackoverflow.com/questions/7634346/keyboard-hide-event]http://stackoverflow.com/questions/7634346/keyboard-hide-event[/url]
// FIXME: Discussion at [url=http://bugzilla.libsdl.org/show_bug.cgi?id=1639]http://bugzilla.libsdl.org/show_bug.cgi?id=1639[/url]
// FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not
// FIXME: A more effective solution would be to assume our Layout to be RelativeLayout or LinearLayout
// FIXME: And determine the keyboard presence doing this: [url=http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android]http://stackoverflow.com/questio ... keyboard-in-android[/url]
// FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :)
if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) {
SDLActivity.onNativeKeyboardFocusLost();
}
}
return super.onKeyPreIme(keyCode, event);
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
ic = new SDLInputConnection(this, true);
outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
| EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;
return ic;
}
}
其中的InputConnection:用于与输入法编辑器(IME)通信的接口,源码中的TYPE_TEXT_VARIATION_VISIBLE_PASSWORD字样就是向系统说明输入类型为密码,从而触发安全输入法导致无法输入中文
[RenPy] 纯文本查看 复制代码 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
| EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;
那么,我们将它改为
[RenPy] 纯文本查看 复制代码 outAttrs.inputType = InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS |
InputType.TYPE_TEXT_VARIATION_NORMAL;
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI |
EditorInfo.IME_FLAG_NO_FULLSCREEN |
EditorInfo.IME_ACTION_DONE;
就可以实现将密码类型改为正常文本类型,从而使得系统不调用安全输入法,而食用正常的默认输入法
完整修改代码:(这里只贴出DummyEdit ,因为整个文件全部有2.4k行)
[RenPy] 纯文本查看 复制代码 class DummyEdit extends View implements View.OnKeyListener {
InputConnection ic;
public DummyEdit(Context context) {
super(context);
setFocusableInTouchMode(true);
setFocusable(true);
setOnKeyListener(this);
}
@Override
public boolean onCheckIsTextEditor() {
return true;
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
/*
* This handles the hardware keyboard input
*/
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLActivity.isTextInputEvent(event)) {
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
return true;
}
SDLActivity.onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
SDLActivity.onNativeKeyUp(keyCode);
return true;
}
return false;
}
//
@Override
public boolean onKeyPreIme (int keyCode, KeyEvent event) {
// As seen on StackOverflow: [url=http://stackoverflow.com/questions/7634346/keyboard-hide-event]http://stackoverflow.com/questions/7634346/keyboard-hide-event[/url]
// FIXME: Discussion at [url=http://bugzilla.libsdl.org/show_bug.cgi?id=1639]http://bugzilla.libsdl.org/show_bug.cgi?id=1639[/url]
// FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not
// FIXME: A more effective solution would be to assume our Layout to be RelativeLayout or LinearLayout
// FIXME: And determine the keyboard presence doing this: [url=http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android]http://stackoverflow.com/questio ... keyboard-in-android[/url]
// FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :)
if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) {
SDLActivity.onNativeKeyboardFocusLost();
}
}
return super.onKeyPreIme(keyCode, event);
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
ic = new SDLInputConnection(this, true);
outAttrs.inputType = InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS |
InputType.TYPE_TEXT_VARIATION_NORMAL;
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI |
EditorInfo.IME_FLAG_NO_FULLSCREEN |
EditorInfo.IME_ACTION_DONE;
return ic;
}
}
闲言:
1.在github中,pytom对于安全输入法的回复是
不可置否,确实可能存在这样的问题,所以对于我这个方案,仍然存在对于非ASCLL字符处理导致出错的问题,但是至少我目前没遇到
2.在花费了快一周的时间解决这个问题的探索过程中,我发现关于安卓部分,文档仍然有不少东西是没说的,例如系统广播,更多的传感器调用等,也有可能是这一部分并不是tom直接负责,总体上安卓部分的内容对于安卓系统的兼容做的还是挺不错,但其内容冗杂实在...我甚至能在这里面看到2010年的开源项目...
3.关于SDL和rapt,tom也在图中表示会在SDL3更新中解决这个问题,希望有更好的处理方案。
|