10

Bluetooth 経由で RFCOMM を介してカスタム デバイスと通信するアプリケーションがあります。通信コードは、BluetoothTalk サンプル プロジェクトに基づいています。以前は、Galaxy S3、Galaxy S2、Galaxy Note、Nexus 7 のいずれでも問題なく動作していました。

最近、Nexus 7 が Android 4.2 にアップグレードされて以来、問題は次のように発生します。

  1. アプリを使用して初めて接続をセットアップするとき、つまり、デバイスの電源を入れてアプリを起動したばかりの場合、問題なく、正常にデータを取得できます。

  2. その後、通信を停止して再起動しようとすると、「java.io.IOException: bt socket closed, read return: -1」というエラーで通信が失敗します。それ以降、何度再接続しようとしても、常に失敗します。

  3. 再度動作させる唯一の方法は、カスタム デバイスとアプリを再起動してから接続しようとすると、通信が正常になることです。しかし、いったん通信を停止して再開すると、失敗し続けます。

Android 4.2 を搭載した Nexus 4 を借りましたが、問題は解決しません。

私たちのデバイスの主な価値は Bluetooth RFCOMM アプリケーションに依存しているため、これは非常に面倒です。Android 4.2 の BT に関するドキュメントを再確認しましたが、大きな変更は見られませんでした。4.2 を実行していないすべての Android デバイスで動作するため、自分の側のコードにはかなりの自信があります。

ヒントや提案をいただければ幸いです。デバイスは 12 月の初めにデモを行う必要があり、この問題に早急に対処したいと考えています。

編集: 4.2.1 がリリースされましたが、問題はまだ解決されていません。少なくとも、それが機能しており、すぐに修正されるかどうかについて、確認を得ることができますか?

4

8 に答える 8

6

これはあまり役に立ちませんが、Google が 4.2 でまったく新しい Bluetooth スタックを導入したことに注意してください。

これは良いことです。ユーザーおよび開発者としての私の経験では、Bluez (古いコンボ) を搭載した Android は確実に機能することはありませんでした。

私が言えることは、新しいスタックでバグまたは癖に遭遇したように聞こえるということだけです。新しいスタックにも問題があると聞いて残念です。

デモに関しては、Google がすべての Nexus デバイスのファームウェア イメージを公開しており (https://developers.google.com/android/nexus/images)、それらをデバイスにフラッシュするのはかなり簡単であることに注意してください。

したがって、バグ レポートを提出してから、デバイスを 4.1.2 にフラッシュすることをお勧めします。

于 2012-11-20T00:39:00.393 に答える
1

私のテストでもそれは起こりました。ConnectionLost メソッドを参照する必要がある BluetoothChat サンプル コードです。失われた接続の数を保持する変数があるかどうかは覚えていませんが、自分で追加できます。connectionLost メソッドで、失われた接続の数が事前定義された数 (私の場合は 3) よりも少ないかどうかをテストします。その場合は、mHandler (トースト) を使用して UI にメッセージを送信し、connect(device) を再度呼び出します。そうでない場合 (接続が 3 回以上失われた場合)、stop() メソッドを呼び出します。

また、次のように ConnectThread でソケットを開いていることを確認してください。

    public ConnectThread(BluetoothDevice device, boolean isSecure) {
        mmDevice = device;
        BluetoothSocket tmp = null;
        mSocketType = isSecure ? "Secure" : "Insecure";
        // Get a BluetoothSocket for a connection with the given BluetoothDevice
        if (isSecure) {
            // reflection is better to use
            Method m = null;
            try {
                Log.d(TAG, "create reflection");
                m = device.getClass().getMethod("createRfcommSocket",new Class[] { int.class });
                } catch (NoSuchMethodException e1) {
                e1.printStackTrace();
            }
            try {
                tmp = (BluetoothSocket) m.invoke(device, 1);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            mmSocketFallBack = tmp;
        } else {
            Log.d(TAG, "create insecure");
            try {
                tmp = device
                        .createInsecureRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        mmSocket = mmSocketFallBack;
    }

connectionLost は次のようになります。

public void connectionLost() {
    init = false;
    Log.d(TAG, "connectionLost -> " + mConnectionLostCount);
    mConnectionLostCount++;
  if (mConnectionLostCount < 3) {
    // Send a reconnect message back to the Activity
        Message msg = mHandler.obtainMessage(cBluetooth.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(WebAppInterface.TOAST, "Connection lost. Reconnecting...");
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        connect(mSavedDevice,true);     
    } else {
    mConnectionLostCount = 0;
    Message msg = mHandler.obtainMessage(cBluetooth.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString(WebAppInterface.TOAST,"Device connection was lost!");
    msg.setData(bundle);
    mHandler.sendMessage(msg);
    cBluetooth.this.stop();
    }
}

あなたのケースに合わせて調整していただければ幸いです。このリンクも確認できます。とても役に立ちました。

  1. リモコンの例
  2. 接続切断ソリューション
  3. ヒントになる Bluetooth サービスの例
于 2013-10-15T11:42:33.343 に答える
1

同様の問題があり、この問題のデバッグに時間を費やしました。私は Android 4.3 を実行していますが、BluetoothChat サンプル コードに必要な唯一の基本的な変更は次の設定であることがわかりました。

MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

HC-05 Bluetooth モジュールに接続しようとしていますが、この UUID で示される SPP プロファイルを使用していると思います。次のコード行を使用して、デバイスの UUID を照会できます。

UUID uuid = device.getUuids()[0].getUuid();

UUID を確認し、接続しているデバイスのタイプに基づいて、意味のあるプロファイルと一致するかどうかを確認します。

MY_UUID_SECURE = uuid;

UUID は、接続先に応じて、異なるタイプのデバイス プロファイルを示している場合があります。適切な UUID を使用して、AcceptThread コードを実行し、問題なく BluetoothServerSocket としてリッスンすることができました。これが役立つことを願っていますが、私は Android と Bluetooth の開発に比較的慣れていないため、私の仮定が間違っている場合は修正してください。

于 2014-01-12T02:35:36.290 に答える
0

Nexus 4 でも同じ問題が発生しました。

私の場合、問題は SDP サービス検出プロトコルにあると思います。デバイスとサーバーは、特定のサービスに対して同じ UUID を使用する必要があります。

アプリケーションで SPP (シリアル ポート プロトコル) を使用しています。そこで、UUID を BluetoothChat のサンプル コードにある "fa87c0d0-afac-11de-8a39-0800200c9a66" から SPP "00001101-0000-1000-8000-00805F9B34FB" に変更します。今は大丈夫です。

そして、BluetoothChatService.start() で acceptThread のリッスン コードを無効にします。もっと簡潔に。それが役立つことを願っています。

于 2013-07-03T09:08:15.840 に答える
0

同様の問題が発生しました。ビルド ターゲットとして 17 を使用して 4.2 SDK でビルドすることにより、それらのいくつかを修正しました。

于 2013-01-04T12:56:45.380 に答える
0

4.2.2 でも同じ経験があります。

しかし、リソース (ソケットおよび/またはストリーム) を適切にクリーニングせずにアプリケーションが停止または強制終了された後にのみ、Bluetooth スタックが誤動作し始めることがわかりました。その前に、アプリを適切に閉じると、正常に動作します。

たとえば、ソケットを閉じてからアプリを強制終了すると、アプリを起動して正常に再接続できます。以前にソケットを閉じずにアプリケーションを強制終了すると、デバイスを再起動して再び機能させる必要があります。

そのため、新しい Android bluetooth スタックには、暗黙的なクリーニング メカニズムにバグがあるようです。アプリケーションが落ちると、Android は開いている Bluetooth リソースを消去する必要がありますが、これは発生していません。

私の Bluetooth 管理コードは Application サブクラスにあります。アプリケーションの破棄をフックしてクリーニングを行う方法はありません-または私にはわかりません。

任意の提案をいただければ幸いです

編集:

私はかなり厄介な回避策を作りました。

単一のリモート サービスを含む別のアプリケーションを作成しました。すべての通信コード (ソケットとストリームのオープン、読み取り、書き込み、クローズ) をこのリモート サービスに移動しました。その後、メイン アプリケーションがクラッシュまたは強制終了されても、サービスは引き続き実行されます。アプリケーションを再度起動すると、接続はまだ確立されています。Bluetooth 入力ストリームから読み取られたバイトは、標準のサービス メッセージングを介してメイン アプリケーションに転送されます。私の場合、非常に少量のデータを転送するので、これは問題ありません。

それでも、サービスを含むアプリケーションが強制終了されると、同じ混乱が発生します。

于 2013-10-21T22:23:08.523 に答える
0

私は同じ問題に直面しています。これは私のために働く:

try {
    Thread.sleep(1000); 
}
catch(Exception e3)
{
    Toast.makeText(getApplicationContext(), "wa ni sud sa thread sleep!", Toast.LENGTH_SHORT).show();
}
btSocket.close();
于 2015-01-06T05:59:18.183 に答える