私のプログラムは、アクティビティ実行コードのWhileループで動作します。100ms程度ごとに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を再確立しようとしている方法を示しました。
示されているコードでは、デバッグを実行して音声認識機能を呼び出した後、ブレークポイントなしでコードが中断されます。そこからコードの実行を再開すると、[終了]ボタンをクリックした場合と同じようにプログラムが停止します。これは、実行がそれ自体で中断したときの私のコンピューター画面です。これはNullPointerExceptionの問題であるように見えますが、これはまだ私の知識ベースから外れています。誰かが私を正しい方向に向けることができることを願っています。
下の画像にあるスレッド[<12>スレッド-130](実行中)が原因であると私は信じ始めています。このスレッドは、音声認識機能の呼び出しから戻ると表示されます。音声認識機能の呼び出し後に実行が元のスレッドに戻ることを確認する必要があると考えていますが、ここから離れることができますか?
または、さらに良いことに(多分)、音声認識機能を呼び出しているときに元のスレッド<11>を強制終了する方法はありますか?
うわー、それはそれでした、または少なくとも私はそう思った、私がする必要があるのは壊すことだけでした。音声認識機能を開始した後、whileループから抜け出しました(usbリクエストの失敗時にwhileループから抜け出す必要もあります)。
また、runOnUiThread()で音声認識機能を起動する必要はありません。
これは魅力のように機能すると思いましたが、中断されたスレッドが蓄積し、最終的にプログラムが音声認識機能の実行を停止することに気付きました。私はこれを追跡すると確信していますが、どんな知恵の言葉も役に立ちます。
非常に詳細に申し訳ありませんが、私は初心者の思考プロセス全体を次の人のために残しておきます(あなたがこれに反対票を投じ始めない限り)。
PSこれはなんと素晴らしいデバッグ環境です!!!!
中断されたスレッドはデバッグ中に作成されたようですが、なぜそれが機能しなくなったのかはわかりませんが、おそらくすべての中断されたスレッドです。私はそれを理解します。私はその問題を再現することができず、私は本当に答えを見つけたと思います(上記)が、念のため、これを答えとして投稿する前にしばらく待ちます。
1/21 11:14 EST:まだ2つの問題
-音声認識呼び出しの約10分の1でonResume()が実行されますが、onResume()の後にrun()は実行されません(他の9回はonResume()の後にrun()が入力されます)。これにより、whileループに入っていないため、プログラムがハングアップします。
-ユーザーがシステムの「戻る」矢印を使用して別のプログラムを使用してから自分のプログラムに戻るたびに、別のスレッド(独自のwhileループを持つ)が表示されます。事実上、これは私のプログラムの複数のインスタンスを作成し、受け入れられません。
そして、runOnUiThread()で音声認識機能を開始することに戻りました。これにより、ハングアップが少なくなると思います。
1/21 1:27 pm EST:
そしてもう一度、私はそれが機能していると思います。音声認識を100回呼び出し、他のプログラムを断続的に使用しましたが、デバッグウィンドウに同じ数のスレッドが実行されていて、ハングアップしていません。
私がしたことは、アクティビティレベルの整数exitloopnowを宣言することでした。onCreate、onStart、onResumeでexitloopnowを0に設定しました。onPause、onStop、onDestroyでexitloopnowを1に設定しました。run()whileループでは、exitloopnow==1の場合に中断します。
繰り返しますが、これが引き続き機能する場合は、誰かがより良いものを考え出さない限り、これを答えとして設定します。
1/21 2:00 pm EST:
100回では足りなかったと思います。ハングアップした時点でデバッグモードでキャッチしました。下の写真の.resquestWait()に貼り付いているようです。
「利用できない[ネイティブメソッド]」についてはあまり見つけることができないので、再び行き詰まります。コードの実行を再開して再度中断すると、常に彼の行(350)にあります。
1/22 9:20 am EST:
コードが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>
そして私のプロジェクト構造: