好的,我尝试了我可以找到的“一切”并阅读了我搜索的所有内容,问题很简单,但我无法理解问题所在。
我正在使用 NDK(CPP 中的本机代码)。
我有一个非常简单的 Activity,它有一个 OpenGL GLSurfaceView,其中完成了一些非常简单的渲染,在某些时候我希望能够用两个按钮打开一个简单的 AlertDialog。
现在我尝试了许多不同的方法,基本上都陷入了这样的想法:“一条消息被发布到一个 Java 线程,该线程只是轮询消息,然后当它收到一个消息时,它会使用 Handler 向运行的主 UI 线程发布一条消息创建 AlertDialog 的消息处理程序”。
我尝试了其他一些方法,包括通过向 GLSurfaceView 的 onTouchEvent() 函数内的 Handler 发布一条消息来做 - 用于测试 - “全部来自 Java”,如下面的代码片段所示:
@Override
public boolean onTouchEvent(MotionEvent e) {
/* code to get the events .. */
if ( maskedAction == MotionEvent.ACTION_DOWN && isUiOn == false)
{
isUiOn = true;
GilesTest2JNIActivity.theHandler.sendEmptyMessage(1);
}
return true;
}
接收消息的处理程序执行以下操作:
public class GilesTest2JNIActivity extends Activity {
GilesTest2JNIView mView;
public static AlertDialog mTextInputDialog;
private Context MyContext;
public static Handler theHandler;
public LayoutInflater mInflater = null;
public Handler mHandler;
@Override protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
Log.i ("Giles OnCreate ","creating appl.");
MyContext = this;
mInflater = (LayoutInflater) getSystemService(MyContext.LAYOUT_INFLATER_SERVICE);
mHandler = new Handler(){
public void handleMessage(Message msg){
AlertDialog.Builder builder = new AlertDialog.Builder(MyContext);
Log.i ("handler","builder");
builder.setView(mInflater.inflate(R.layout.dialog_signin, null));
builder.setTitle("User - Login");
builder.setMessage("Please enter your username and pwd");
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
GilesTest2JNILib.nativeSendInputText( "BBB", "AAA");
//dialog.dismiss();
mView.isUiOn = false; // signal this is OFF
}
} );
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
Log.w ("Keyboard","Kb is going away via CANCEL");
GilesTest2JNILib.nativeSendInputText( "**", "**" );
mView.isUiOn = false; // signal this is OFF
}
});
mTextInputDialog = builder.show();
mTextInputDialog.setCanceledOnTouchOutside(false);
mView.isUiOn = true; // signal this is ON
}
};
/* rest of onCreate() .. */
}
发生的事情是出现了 AlertDialog,一切似乎都正常,但几秒钟后一切都冻结了,没有错误消息,什么都没有,但即使 GLSurfaceView() 上的渲染也停止了,因为不再调用 .step(),一切只是冻结停止而不显示任何类型的错误消息,并且几乎永远停留在那里和/或偶尔进入“应用程序无响应”。
这种行为似乎发生在 Nexus 7 平板电脑上,但在另一台平板电脑上我没有发生,但在我第 4 次或第 5 次启动/关闭对话框之后。
我唯一设法理解的事情似乎在某些时候停止接收各种触摸和/或就像“没有窗口”和/或某些窗口消失了,我真的不知道发生了什么。
我正在重新添加一些经过广泛测试后才发现的信息。
在获得经典的基本 OpenGL 示例后,简单地绘制一个三角形并将所有代码放回其中的那个发现它一切正常,所以回到第一方并在我的代码上重新尝试相同的示例,我开始将 #ifdef 放入在我找到“崩溃点”之前,各个地方都可以删除代码片段。
一段时间后我发现了这一点,似乎原因根本不在那段代码中,而是与我在后台工作的音频有关。
这是一个非常简单的基于 OpenSL 的播放器和一个播放器对象,它在循环中连续播放一个循环缓冲区,其中混合了样本,似乎一切都归结为这段代码:
// at this point we can enqueue the current chunk for playing
theSize = AUDIO_DATA_CHUNK_SIZE*sizeof(SLint16);
#define DO_NOT_ENQUEUE 1
#ifndef DO_NOT_ENQUEUE
result = (*bq)->Enqueue(bq, (void*) curdata, theSize ); /* Size given in bytes. */
#endif
AUDIO_DATA_CHUNK_SIZE 是 128,这个东西被设计成循环播放一个循环缓冲区,其中混合了样本,它不断播放(采样率 11.025 Khz)。
如果我在 Alertdialog 启动时禁用播放声音,一切都会完美无缺。
不知道到底发生了什么,除非在某些时候你可以看到这种情况发生:
12-19 18:56:52.418: W/InputConnectionWrapper.ICC(303): Timed out waiting on IInputContextCallback
12-19 18:56:52.418: I/InputDispatcher(150): Dropped event because it is stale.
12-19 18:56:52.418: I/InputDispatcher(150): Dropped event because it is stale.
12-19 18:56:52.418: I/InputDispatcher(150): Dropped event because it is stale.
似乎在某种程度上,音频播放会干扰输入。