この問題は解決されました!ブラッド、デニス、ジャンキーに感謝します!あなたはヒーローです! :)
これが作業コードです。 Zeemoteに接続し、そこからデータを読み取ります。
publicクラスZeeTestはActivity { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView( R.layout.main); { for(int i = 0; i <3; i ++){ test(); } } catch(Exception e){ e.printStackTrace(); } } private boolean connected = false; private BluetoothSocket sock; private InputStream in; public void test()throws Exception { if(connected){ return; } BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter()。 getRemoteDevice( "00:1C:4D:02:A6:55"); メソッドm = zee.getClass ().getMethod( "createRfcommSocket"、 new Class [] {int.class}); sock =(BluetoothSoc ket)m.invoke(zee、Integer.valueOf(1)); Log.d( "ZeeTest"、 "++++ Connecting"); sock.connect(); Log.d( "ZeeTest"、 "++++ Connected"); in = sock.getInputStream(); byte [] buffer = new byte [50]; int read = 0; Log.d( "ZeeTest"、 "++++ Listening ..."); try { while(true ){ read = in.read(buffer); connected = true; StringBuilder buf = new StringBuilder(); for(int i = 0; i <読み取り; i ++){ int b = buffer [i]&0xff; if(b <0x10){ buf.append( "0"); } buf.append(Integer.toHexString(b))。append( ""); } Log.d( "ZeeTest"、 "++++ Read" +読み取り+ "バイト:" + buf.toString()); } } catch(IOException e){} Log.d( "ZeeTest"、 "+++ +完了:test() "); } @Override public void onDestroy(){ try { if(in!= null){ in.close(); } if(sock!= null){ sock.close(); } } catch(IOException e){ e.printStackTrace(); } super.onDestroy(); } }
2.0.1ファームウェアを実行しているMoto DroidからZeemote( http://zeemote.com/ )ゲーミングコントローラーに接続しようとしています。以下のテストアプリケーションはデバイスに接続します(LEDが点滅します)が、その後すぐに接続が切断されます。
以下に2つのテストアプリを貼り付けます。1つは実際に入力ストリームから読み取ろうとし、もう1つはそこに座って、5秒後にデバイスが切断されるのを待ちます。そして、はい、3番目のバージョンがあります:)最初にACL_CONNECTEDを待ってからソケットを開きますが、その動作には新しいものはありません。
背景情報:bluezツールを使用して、ラップトップからZeemoteに完全に接続できます(ログも添付されています)。ドロイドはがZeemoteと話すこともできることは確かです。なぜなら、市場の「Game Pro」はそれでうまく動作するからです(しかし、それはドライバーです)/serviceですので、おそらく低レベルのAPIを使用しますか?)。
他のすべてのデバイス(Moto HS815ヘッドセット、「sdp browse」が何も報告しない別のダムデバイスを含む)については、「adb bugreport」がZeemoteのUUIDもRFCOMMチャネルも報告しないことに気付きました。また、デバイスの起動時、Zeemoteの優先度は0です(他の優先度は100+です)。
私はここでかなり途方に暮れているので、私はアイデアを使い果たしたので、どんな助けも大歓迎です(あなたが知らない場合でもthe答え:))
ありがとう、マックス
このアプリは、実際にデバイスから読み取ろうとします。
publicクラスZeeTestはActivity { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView( R.layout.main); try { test(); } catch(IOException e){ e.printStackTrace(); } } private BluetoothSocket sock; private InputStream in; public void test()throws IOException { BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter()。 getRemoteDevice( "00:1C:4D:02:A6:55"); sock = zee.createRfcommSocketToServiceRecord( UUID.fromString( "8e1f0cf7-508f-4875-b62c-fbb67fd34812")); Log.d( "ZeeTest"、 "++++ Connecting"); sock.connect(); Log.d( "ZeeTest"、 "++++ Connected"); in = sock.getInputStream(); byte [] buffer = new byte [1]; int bytes = 0; int x = 0; Log.d( "ZeeTest"、 "++++ Listening ... "); while(x <2){ x ++; try { bytes = in.read(buffer); Log.d( "ZeeTest"、 "++++ Read" + bytes + "bytes"); } catch(IOException e){ e.printStackTrace(); try {Thread.sleep(100); } catch(InterruptedException ie){} } } Log.d( "ZeeTest"、 "++++ Done:test()"); } @Override public void onDestroy(){ try { if(in!= null){ in.close() ; } if(sock!= null){ sock.close(); } } catch(IOException e){ e.printStackTrace(); } super.onDestroy(); } }
04-19 22:27:01.147:DEBUG/ZeeTest(8619):++++ Connecting 04-19 22:27:04.085:INFO/usbd(1062):process_usb_uevent_message() :buffer = add @/devices/virtual/bluetooth/hci0/hci0:1 04-19 22:27:04.085:INFO/usbd(1062):main():call select(...) 04-19 22:27:04.327:ERROR/BluetoothEventLoop.cpp(4029):event_filter:受信信号org.bluez.Device:PropertyChanged from /org/bluez/4121/hci0/dev_00_1C_4D_02_A6_55 04 -19 22:27:04.491:VERBOSE/BluetoothEventRedirector(7499):Android.bleutooth.device.action.UUID 04-19 22:27:04.905:DEBUG/ZeeTest(8619):++++を受信しました接続済み 04-19 22:27:04.905:DEBUG/ZeeTest(8619):++++ Listening ... 04-19 22:27:05.538:WARN/System.err( 8619):Java.io.IOException:ソフトウェアにより接続が中断されました 04-19 22:27:05.600:WARN/System.err(8619):at Android.bluetooth.BluetoothSocket.readNative(Native Method) ... 04-19 22:27:05.717:WARN/System.err(8619):Java.io.IOException:Software原因conne ction abort 04-19 22:27:05.717:WARN/System.err(8619):at Android.bluetooth.BluetoothSocket.readNative(Native Method) ... 04-19 22:27:05.819:DEBUG/ZeeTest(8619):++++完了:test() 04-19 22:27:07.155:VERBOSE/BluetoothEventRedirector(7499):Android.bleutoothを受信しました.device.action.UUID 04-19 22:27:09.077:INFO/usbd(1062):process_usb_uevent_message():buffer = remove @/devices/virtual/bluetooth/hci0/hci0:1 04-19 22:27:09.085:INFO/usbd(1062):main():call select(...) 04-19 22:27:09.139:ERROR/BluetoothEventLoop.cpp(4029 ):event_filter:受信したシグナルorg.bluez.Device:PropertyChanged from /org/bluez/4121/hci0/dev_00_1C_4D_02_A6_55
このテストは接続して待機します-自動切断の問題を表示するのに役立ちます。
publicクラスZeeTestはActivity { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView( R.layout.main); getApplicationContext()。registerReceiver(receiver、 new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)); getApplicationContext()。registerReceiver(receiver、 new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); try { BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter()。 getRemoteDevice( "00:1C:4D:02:A6: 55 "); sock = zee.createRfcommSocketToServiceRecord( UUID.fromString(" 8e1f0cf7-508f-4875-b62c-fbb67fd34812 ")); ログ。 d( "ZeeTest"、 "++++ Connecting"); sock.connect(); Log.d( "ZeeTest"、 "+++ +接続 "); } catch(IOException e){ e.printStackTrace(); } } private static final LogBroadcastReceiver receiver = new LogBroadcastReceiver(); public static class LogBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context、Intent intent){ Log.d( "ZeeReceiver"、intent.toString()); Bundle extras = intent.getExtras(); for(String k:extras.keySet()){ Log.d( "ZeeReceiver"、 "Extra:" + extras.get(k).toString()); } } } private BluetoothSocket sock; @Override public void onDestroy(){ getApplicationContext()。unregisterReceiver(receiver); if(sock! = null){ try { sock.close(); } catch(IOException e){ e.printStackTrace(); } } super.onDestroy(); } }
04-19 22:06:34.944:DEBUG/ZeeTest(7986):++++ Connecting 04-19 22:06:38.202:INFO/usbd(1062):process_usb_uevent_message() :buffer = add @/devices/virtual/bluetooth/hci0/hci0:1 04-19 22:06:38.202:INFO/usbd(1062):main():call select(...) 04-19 22:06:38.217:ERROR/BluetoothEventLoop.cpp(4029):event_filter:受信信号org.bluez.Device:PropertyChanged from /org/bluez/4121/hci0/dev_00_1C_4D_02_A6_55 04 -19 22:06:38.428:VERBOSE/BluetoothEventRedirector(7499):Android.bleutooth.device.action.UUID 04-19 22:06:38.968:DEBUG/ZeeTest(7986):++++を受信しましたConnected 04-19 22:06:39.061:DEBUG/ZeeReceiver(7986):Intent {act = Android.bluetooth.device.action.ACL_CONNECTED(has extras)} 04-19 22: 06:39.108:DEBUG/ZeeReceiver(7986):Extra:00:1C:4D:02:A6:55 04-19 22:06:39.538:INFO/ActivityManager(4029):Displayed activity zee.test /.ZeeTest:5178ミリ秒(合計5178ミリ秒) 04-19 22:06:41.014:VERBOSE/BluetoothEventRedirector(7499): Android.bleutooth.device.action.UUID 04-19 22:06:43.038:INFO/usbd(1062):process_usb_uevent_message():buffer = remove @/devices/virtual/bluetooth/hci0/hci0: 1 04-19 22:06:43.038:INFO/usbd(1062):main():call select(...) 04-19 22:06:43.069:ERROR/BluetoothEventLoop .cpp(4029):event_filter:受信信号org.bluez.Device:PropertyChanged from /org/bluez/4121/hci0/dev_00_1C_4D_02_A6_55 04-19 22:06:43.124:DEBUG/ZeeReceiver(7986):Intent {act = Android.bluetooth.device.action.ACL_DISCONNECTED(エクストラあり)} 04-19 22:06:43.124:DEBUG/ZeeReceiver(7986):エクストラ:00:1C:4D:02:A6: 55
$ sdptool browse Inquiring ... Browsing 00:1C:4D:02:A6:55 ... $ sdptool records 00:1C:4D:02:A6:55 サービス名:Zeemote Service RecHandle:0x10015 サービスクラスIDリスト: UUID 128:8e1f0cf7-508f -4875-b62c-fbb67fd34812 プロトコル記述子リスト: "L2CAP"(0x0100) "RFCOMM"(0x0003) チャネル:1 言語ベース属性リスト: code_ISO639:0x656e エンコーディング:0x6a base_offset:0x100 $ rfcomm connect/dev/tty10 00:1C: 4D:02:A6:55 チャネル1の/ dev/rfcomm0を00:1C:4D:02:A6:55に接続しました CTRL-Cを押してハングアップ #rfcomm show /dev/tty10 rfcomm0:00:1F:3A:E4:C8:40-> 00:1C:4D:02:A6:55チャネル1接続[reuse-dlc release- on-hup tty-attached] #cat /dev/tty10 (nothing here) #hcidump HCIスニファー-Bluetoothパケットアナライザーバージョン1.42 デバイス:hci0 snap_len:1028フィルター:0xf fffffff <HCIコマンド:接続の作成(0x01 | 0x0005)plen 13 > HCIイベント:コマンドステータス(0x0f)plen 4 > HCIイベント:接続完了(0x03)plen 11 <HCIコマンド:リモートサポート機能の読み取り(0x01 | 0x001b)plen 2 > HCIイベント:リモートサポート機能の読み取り(0x0b)plen 11 <ACLデータ:ハンドル11 flags 0x02 dlen 10 L2CAP(s):情報要求:タイプ2 > HCIイベント:コマンドステータス(0x0f)plen 4 > HCIイベント:ページスキャン繰り返しモードの変更( 0x20)plen 7 > HCIイベント:最大スロット変更(0x1b)plen 3 <HCIコマンド:リモート名要求(0x01 | 0x0019)plen 10 > HCIイベント:コマンドステータス(0x0f)plen 4 > ACLデータ:ハンドル11フラグ0x02 dlen 16 L2CAP(s):情報rsp:タイプ2結果0 拡張機能マスク0x0000 <ACLデータ:ハンドル11フラグ0x02 dlen 12 L2CAP:接続要求:psm 3 scid 0x0040 > HCIイベント:完了パケット数(0x13)plen 5 > ACLデータ:handl e 11フラグ0x02 dlen 16 L2CAP:接続rsp:dcid 0x04fb scid 0x0040結果1ステータス2 接続保留中-承認保留中 > HCIイベント:リモート名要求完了(0x07)plen 255 > ACLデータ:ハンドル11フラグ0x02 dlen 16 L2CAP(s):Connect rsp:dcid 0x04fb scid 0x0040 result 0 status 0 Connection successful <ACLデータ:ハンドル11フラグ0x02 dlen 16 L2CAP(s):構成要求:dcid 0x04fbフラグ0x00 clen 4 MTU 1013 (イベントは、 bluez)
-既知のデバイス- 00:19:A1:2D:16:EAボンディング(0)LG U830 00001105-0000 -1000-8000-00805f9b34fb RFCOMMチャネル= 17 00:1C:4D:02:A6:55結合(0)Zeemote JS1 00:0B:2E:6E:6F:00結合( 0)Motorola HS815 00001108-0000-1000-8000-00805f9b34fb RFCOMM channel = 1 0000111e-0000-1000-8000-00805f9b34fb RFCOMM channel = 2 00:1F:3A :E4:C8:40結合(0)BRCM BT4X 00001105-0000-1000-8000-00805f9b34fb RFCOMMチャネル= 9 00:18:42:EC:E2:99結合(0) N95 00001105-0000-1000-8000-00805f9b34fb RFCOMMチャネル= 9
04-18 21:55:10.382:VERBOSE/BluetoothEventRedirector(1985):Android.bluetooth.adapter.action.STATE_CHANGED 04-18 21:55:10.421:DEBUG/BT HSHFP( 1237):ロードされた優先度00:19:A1:2D:16:EA = 100 04-18 21:55:10.428:DEBUG/BT HSHFP(1237):ロードされた優先度00:1C:4D:02: A6:55 = 0 04-18 21:55:10.444:DEBUG/BT HSHFP(1237):ロードされた優先度00:0B:2E:6E:6F:00 = 101 04-18 21:55:10.749:DEBUG/BT HSHFP(1237):ロードされた優先度00:1F:3A:E4:C8:40 = 100 04-18 21:55:10.780:DEBUG/BT HSHFP(1237) :ロードされた優先度00:18:42:EC:E2:99 = 100
RfcommSocketを作成するためのコードを変更してみてください。
sock = zee.createRfcommSocketToServiceRecord(
UUID.fromString("8e1f0cf7-508f-4875-b62c-fbb67fd34812"));
このコードの場合:
Method m = zee.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
sock = (BluetoothSocket) m.invoke(device, 1);
また、このm.invoke(device、1)の範囲1〜3の引数値を変更してください。接続が接続されるが、読み取りを試みると中断される場合は、ループ内でメソッドtest()を再度呼び出します。簡単です:
for(int i=0;i<3;i++){ if(!testDone) test(); }
私が書いたコードと[Android-beginners]のコードをマージしました。Re:XCaffeinatedによるBluetooth上のシリアル] 1 と上記の投稿。
可能な限りシンプルなBluetoothプログラムを作成する。
このコードの主な追加点は、connect()
によってスローされる例外の処理を改善することです。
「@todo」を検索して、ニーズに合わせてカスタマイズします。
これで時間を節約できることを願っています!
package com.xxx; // @todo Change to your package.
import Java.io.IOException;
import Java.io.OutputStream;
import Java.lang.reflect.InvocationTargetException;
import Java.lang.reflect.Method;
import Android.app.Activity;
import Android.bluetooth.BluetoothAdapter;
import Android.bluetooth.BluetoothDevice;
import Android.bluetooth.BluetoothSocket;
import Android.os.Bundle;
import Android.util.Log;
/**
* This is the simplest bluetooth program. It sends one message to one bluetooth
* device. The message and the bluetooth hardware id for the device are hard
* coded. <br>
* <br>
* It does <b>not</b> receive any data. It does not do any thread processing. <br>
* <br>
*
* This application will be useful to communicate with a bluetooth hardware
* device such as a bar code reader, Lego Mindstorm, a PC with a com port
* application, a PC with a terminal program with 'listening' to a com port, a
* second Android device with a terminal program such as <a href=
* "http://www.tec-it.com/en/software/data-acquisition/getblue/Android-smartphone/Default.aspx"
* >GetBlue</a>. It is not a full Android bluetooth application but more a proof
* of concept that the bluetooth works.
*
* <br>
* <br>
*
* This code should cut and paste into the <a
* href="http://developer.Android.com/resources/tutorials/hello-world.html>
* 'HelloAndroid' example</a>. It does not use any screen io.
*
* Add to your Android Manifest.xml file: <uses-permission
* Android:name="Android.permission.BLUETOOTH" /> <uses-permission
* Android:name="Android.permission.BLUETOOTH_ADMIN" />
*
* For a proper bluetooth example with threading and receiving data see: <a
* href=
* "http://developer.Android.com/resources/samples/BluetoothChat/index.html"
* >http://developer.Android.com/resources/samples/BluetoothChat/index.html</a>
*
* @see <a
* href="http://developer.Android.com/guide/topics/wireless/bluetooth.html">
* http://developer.Android.com/guide/topics/wireless/bluetooth.html</a>
*
*/
public class BlueToothTesterActivity extends Activity {
/** The BluetoothAdapter is the gateway to all bluetooth functions **/
protected BluetoothAdapter bluetoothAdapter = null;
/** We will write our message to the socket **/
protected BluetoothSocket socket = null;
/** The Bluetooth is an external device, which will receive our message **/
BluetoothDevice blueToothDevice = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Grab the BlueToothAdapter. The first line of most bluetooth programs.
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// if the BluetoothAdapter.getDefaultAdapter(); returns null then the
// device does not have bluetooth hardware. Currently the emulator
// does not support bluetooth so this will this condition will be true.
// i.e. This code only runs on a hardware device an not on the emulator.
if (bluetoothAdapter == null) {
Log.e(this.toString(), "Bluetooth Not Available.");
return;
}
// This will find the remote device given the bluetooth hardware
// address.
// @todo: Change the address to the your device address
blueToothDevice = bluetoothAdapter.getRemoteDevice("00:00:00:00:00:00");
for (Integer port = 1; port <= 3; port++) {
simpleComm(Integer.valueOf(port));
}
}
protected void simpleComm(Integer port) {
// byte [] inputBytes = null;
// The documents tell us to cancel the discovery process.
bluetoothAdapter.cancelDiscovery();
Log.d(this.toString(), "Port = " + port);
try {
// This is a hack to access "createRfcommSocket which is does not
// have public access in the current api.
// Note: BlueToothDevice.createRfcommSocketToServiceRecord (UUID
// uuid) does not work in this type of application. .
Method m = blueToothDevice.getClass().getMethod(
"createRfcommSocket", new Class[] { int.class });
socket = (BluetoothSocket) m.invoke(blueToothDevice, port);
// debug check to ensure socket was set.
assert (socket != null) : "Socket is Null";
// attempt to connect to device
socket.connect();
try {
Log.d(this.toString(),
"************ CONNECTION SUCCEES! *************");
// Grab the outputStream. This stream will send bytes to the
// external/second device. i.e it will sent it out.
// Note: this is a Java.io.OutputStream which is used in several
// types of Java programs such as file io, so you may be
// familiar with it.
OutputStream outputStream = socket.getOutputStream();
// Create the String to send to the second device.
// Most devices require a '\r' or '\n' or both at the end of the
// string.
// @todo set your message
String message = "Data from Android and tester program!\r";
// Convert the message to bytes and blast it through the
// bluetooth
// to the second device. You may want to use:
// public byte[] getBytes (Charset charset) for proper String to
// byte conversion.
outputStream.write(message.getBytes());
} finally {
// close the socket and we are done.
socket.close();
}
// IOExcecption is thrown if connect fails.
} catch (IOException ex) {
Log.e(this.toString(), "IOException " + ex.getMessage());
// NoSuchMethodException IllegalAccessException
// InvocationTargetException
// are reflection exceptions.
} catch (NoSuchMethodException ex) {
Log.e(this.toString(), "NoSuchMethodException " + ex.getMessage());
} catch (IllegalAccessException ex) {
Log.e(this.toString(), "IllegalAccessException " + ex.getMessage());
} catch (InvocationTargetException ex) {
Log.e(this.toString(),
"InvocationTargetException " + ex.getMessage());
}
}
}
私が正しく理解している場合、アプリはデバイスからのデータをまったく見ることができませんか?
1つの小さなこと:ハイフンなしでUUIDを試してください。私のRFCOMMアプリでは、実際にはUUIDを長整数定数として定義しています。
また、test()メソッドの記述方法により、test()が接続を確立し、スレッドを定義し、開始してすぐに戻るように指示していると信じられます。言い換えると、スレッドは、test()メソッドの一部であるが、test()が終了すると変数も参照するスレッドの外部から変数を参照しています。
要するに、スレッドの外でテストしてみて、最初にそこで動作するようにします。これを行う簡単な方法の1つは、thread.start()の代わりにThread.run()を使用することです。 .run()はフォアグラウンドで実行します(したがって、test()をブロックするため、スレッドが終了する前に戻りません)。
長期的なソリューションでは、Bluetooth変数をグローバル変数またはメンバー変数として定義して、スコープから外れないようにし、スレッドで常に使用できるようにすることができます。
上記のコードは、Samsung Galaxy tab 2 4.0.4では機能しませんでした。 BTSocket.connectは、正しいピンが入力された場合でも、常にBluetoothペアリングダイアログを起動して失敗しました。 「createRfcommSocket」から「createInsecureRfcommSocket」に変更することで問題が解決しました。これが役立つことを願って、私はこの問題に3時間以上苦労しました。
よく知られているUUID:00001101-0000-1000-8000-00805F9B34FBを試してください