我的程序在活动运行代码中的 While 循环中运行。它每 100 毫秒左右读取一次 USB 数据。当该 USB 数据流中的一个字节设置时,我称之为 startVoiceRecognitionActivity():
private void startVoiceRecognitionActivity() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Voice recognition Demo...");
startActivityForResult(intent, REQUEST_CODE);
}
语音识别器运行良好,我的 USB 数据流 While 循环在语音识别器执行操作时继续运行。
但是,在 onActivityResult 执行后,我的 While 循环被终止。我需要留在这个while循环中,我该怎么做?
编辑:我一直在调试它,并将显示相关的当前代码。似乎 onActivityReturn 在程序崩溃之前以某种方式破坏了 USB。我已经编辑了我的 while 循环,以显示我在语音识别器调用后如何尝试重新建立 USB。
使用显示的代码,在运行调试的语音识别器调用之后,代码在没有断点的情况下中断。如果我从那里恢复代码执行,程序就会停止,就像我单击了 Terminate 按钮一样。这是我的计算机屏幕,当执行本身发生中断时,它似乎是一个 NullPointerException 问题,仍然超出我的知识库。希望有人能指出我正确的方向。
我开始相信您在下图中看到的线程 [<12> Thread-130](正在运行)是罪魁祸首。此线程出现在从语音识别器调用返回时。我想我需要确保在语音识别器调用后执行返回到原始线程,但我可能会离开这里吗?
或者更好(也许),有没有办法在我调用语音识别器时杀死原始线程 <11>?
哇,就是这样,或者至少我是这么认为的,我需要做的就是打破;在我启动语音识别器后退出 while 循环(我还必须在 USB 请求失败时退出 while 循环)。
而且,我不必在 runOnUiThread() 中启动语音识别器。
我认为这很有魅力,但我注意到暂停的线程在累积,最终程序停止执行语音识别器。我相信我会追查到这一点,但任何智慧之言都会有所帮助。
抱歉这么多细节,但我会将整个初学者的思考过程留给后面的人(除非你开始对此投反对票)。
PS 这是多么棒的调试环境啊!!!!
似乎挂起的线程是在我调试时创建的,还没有弄清楚它为什么停止工作,但可能是所有那些挂起的线程。我会弄清楚的。我无法复制该问题,并且我认为我确实已经找到了答案(上图),但我会等一会儿再将其发布为答案,以确保。
1/21 11:14 EST:还有 2 个问题
- 大约十分之一的语音识别调用会导致执行 onResume(),但 run() 在 onResume() 之后不会执行(另外 9 次 run() 在 onResume() 之后输入)。这会导致我的程序挂起,因为没有进入 while 循环。
- 每次用户使用系统的“返回”箭头使用另一个程序然后返回到我的程序时,就会出现另一个线程(带有自己的 while 循环)。实际上,这会创建我的程序的多个实例,并且是不可接受的。
而且,我又回到了在 runOnUiThread() 中启动语音识别器,我认为挂断更少。
美国东部时间 1 月 21 日下午 1:27:
再一次,我想我已经成功了。我已经调用了 100 次语音识别,间歇性地使用了其他程序,并且在我的调试窗口中仍然有相同数量的运行线程并且它没有挂断。
我所做的是,声明一个活动级别整数 exitloopnow。我在 onCreate、onStart 和 onResume 中将 exitloopnow 设置为 0。我在 onPause、onStop 和 onDestroy 中将 exitloopnow 设置为 1。在 run() while 循环中,如果 exitloopnow==1 则中断。
同样,如果这继续有效,我会将其设置为答案,除非有人提出更好的答案。
美国东部时间 1 月 21 日下午 2:00:
我想100次是不够的。我在它挂起的地方以调试模式捕捉到它。它似乎卡在下图所示的 .resquestWait() 上。
我在“不可用 [本机方法]”上找不到太多内容,所以我又被卡住了。如果我恢复代码执行并再次中断,它总是在他的行 (350) 上。
美国东部时间 1 月 22 日上午 9:20:
虽然代码挂在第 350 行,但我可以拔下 USB 电缆,然后将其重新插入,这确实会创建另一个工作线程,但这是不可取的。我还可以使用 Android 的后退按钮并通过在最近的应用程序中选择程序来获取另一个线程,这也是不可取的。
这是 onActivityResult():
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK)
{
// Populate the wordsList with the String values the recognition engine thought it heard
final ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
this.runOnUiThread(new Runnable() {
public void run() {
((TextView) findViewById(R.id.tvTitle)).setText(matches.get(0));
}
});
BusyV=0;
}
super.onActivityResult(requestCode, resultCode, data);
}
而当前的 While 循环:
@Override
public void run() {
while (true) {
request.queue(buffer, 64);
if (mConnection.requestWait() == request) {
if (buffer.get(7)==0) { //New Box (Yellow) button pressed now
this.runOnUiThread(new Runnable() {
public void run() {
((TextView) findViewById(R.id.tvSpine)).setText("Spine");
((TextView) findViewById(R.id.tvPage)).setText("Page");
((TextView) findViewById(R.id.tvThick)).setText("Thick");
}
});
if (CanRecog==1) {
if (BusyV!=1) {
BusyV=1;
this.runOnUiThread(new Runnable() {
public void run() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Voice recognition ...");
startActivityForResult(intent, REQUEST_CODE);
}
});
}
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
} else {
this.runOnUiThread(new Runnable() {
public void run() {
((TextView) findViewById(R.id.tvZnum)).setText("USB lost at "+ System.currentTimeMillis());
((TextView) findViewById(R.id.tvXnum)).setText(" ");
}
});
}
}
}
以及我尝试重新建立 USB 的代码(在 onResume 代码中,因为在语音识别 onActivityResult() 之后会自动调用 onResume:
@Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
Log.d(TAG, "intent: " + intent);
savetofile("1 intent: " + intent);
connectToUsb();
}
private void connectToUsb() {
if (amconnected==1) {
mConnection.close();
request.close();
} else {
setupusb();
}
amconnected=0;
while(amconnected==0) {
doconnect();
}
request.initialize(mConnection, mEndpointIntr);
}
private void setupusb() {
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
}
private void doconnect() {
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device1 = deviceIterator.next();
if (device1.getVendorId() == 1240 & device1.getProductId() == 63) {
mUsbManager.requestPermission(device1, mPermissionIntent);
setDevice(device1);
}
}
}
private void setDevice(UsbDevice device) {
Log.d(TAG, "setDevice " + device);
savetofile("2 setDevice " + device);
if (device.getInterfaceCount() != 1) {
Log.e(TAG, "could not find interface");
savetofile("3 could not find interface");
return;
}
UsbInterface intf = device.getInterface(0);
UsbEndpoint ep = intf.getEndpoint(0);
if (ep.getType() != UsbConstants.USB_ENDPOINT_XFER_INT) {
Log.e(TAG, "endpoint is not interrupt type");
savetofile("5 endpoint is not interrupt type");
return;
}
mEndpointIntr = ep;
if (device != null) {
UsbDeviceConnection connection = mUsbManager.openDevice(device);
if (connection != null && connection.claimInterface(intf, true)) {
Log.d(TAG, "open SUCCESS");
savetofile("6 open SUCCESS");
mConnection = connection;
Thread thread = new Thread(this);
thread.start();
amconnected=1;
} else {
Log.d(TAG, "open FAIL");
savetofile("7 open FAIL");
mConnection = null;
}
}
}
和我的清单:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="act.ProMeasure2D">
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk android:minSdkVersion="13" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:theme="@android:style/Theme.Black" android:label="ProMeasure2D">
<activity android:name="act.ProMeasure2D.ProMeasure2DActivity"
android:label="ProMeasure2D">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
</application>
和我的项目结构: