我正在尝试创建一个允许将字符串从一部Android手机发送到另一部手机的应用。下面提供了此代码。但是,它不起作用,因为我不断从pairDevice()部分下的try catch代码中获取异常。有谁知道为什么我会得到这个?
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.ParcelUuid;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
InputStream inStream;
OutputStream outputStream;
private static final int REQUEST_ENABLE_BT = 1;
public void pairDevice() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
Object[] devices = pairedDevices.toArray();
BluetoothDevice device = (BluetoothDevice) devices[0];
ParcelUuid[] uuid = device.getUuids();
try {
BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid[0].getUuid());
socket.connect();
Toast.makeText(this, "Socket connected", Toast.LENGTH_LONG).show();
outputStream = socket.getOutputStream();
inStream = socket.getInputStream();
} catch (IOException e) {
Toast.makeText(this, "Exception found", Toast.LENGTH_LONG).show();
}
}
}
public void SendMessage(View v) {
EditText outMessage = (EditText) findViewById(R.id.editText);
try {
if (outputStream != null)
outputStream.write(outMessage.toString().getBytes());
TextView displayMessage = (TextView) findViewById(R.id.textView);
Scanner s = new Scanner(inStream).useDelimiter("\\A");
displayMessage.setText(s.hasNext() ? s.next() : "");
} catch (IOException e) {/*Do nothing*/}
Toast.makeText(this,"No output stream", Toast.LENGTH_LONG).show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pairDevice();
}
}
答案 0 :(得分:3)
我对您的应用进行了一些更改: -
首先,我将负责创建蓝牙连接的代码转移到ConnectThread
。
2)添加AcceptThread
负责监听传入连接,并ConnectedThread
维护BTConnection,发送数据,以及
分别通过输入/输出流接收输入数据。
3)创建2个按钮以启动ConnectThread和AcceptThread。
注意:确保两台设备都配对,并确保设备与您配对 试图连接到列表的顶部(或只是删除所有 来自两个设备的配对设备仅配对设备 你想要连接)。此外,您必须启动AcceptThread 在ConnectThread之前
<强> MAINACTIVITY.JAVA 强>
public class MainActivity extends AppCompatActivity {
private static final UUID MY_UUID_INSECURE =
UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
private static final int REQUEST_ENABLE_BT = 1;
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private BluetoothDevice mmDevice;
private UUID deviceUUID;
ConnectedThread mConnectedThread;
private Handler handler;
String TAG = "MainActivity";
EditText send_data;
TextView view_data;
StringBuilder messages;
public void pairDevice(View v) {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
Log.e("MAinActivity", "" + pairedDevices.size() );
if (pairedDevices.size() > 0) {
Object[] devices = pairedDevices.toArray();
BluetoothDevice device = (BluetoothDevice) devices[0];
//ParcelUuid[] uuid = device.getUuids();
Log.e("MAinActivity", "" + device );
//Log.e("MAinActivity", "" + uuid)
ConnectThread connect = new ConnectThread(device,MY_UUID_INSECURE);
connect.start();
}
}
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
public ConnectThread(BluetoothDevice device, UUID uuid) {
Log.d(TAG, "ConnectThread: started.");
mmDevice = device;
deviceUUID = uuid;
}
public void run(){
BluetoothSocket tmp = null;
Log.i(TAG, "RUN mConnectThread ");
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: "
+MY_UUID_INSECURE );
tmp = mmDevice.createRfcommSocketToServiceRecord(MY_UUID_INSECURE);
} catch (IOException e) {
Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage());
}
mmSocket = tmp;
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
Log.d(TAG, "run: Closed Socket.");
} catch (IOException e1) {
Log.e(TAG, "mConnectThread: run: Unable to close connection in socket " + e1.getMessage());
}
Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE );
}
//will talk about this in the 3rd video
connected(mmSocket);
}
public void cancel() {
try {
Log.d(TAG, "cancel: Closing Client Socket.");
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage());
}
}
}
private void connected(BluetoothSocket mmSocket) {
Log.d(TAG, "connected: Starting.");
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "ConnectedThread: Starting.");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = mmSocket.getInputStream();
tmpOut = mmSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run(){
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
// Read from the InputStream
try {
bytes = mmInStream.read(buffer);
final String incomingMessage = new String(buffer, 0, bytes);
Log.d(TAG, "InputStream: " + incomingMessage);
runOnUiThread(new Runnable() {
@Override
public void run() {
view_data.setText(incomingMessage);
}
});
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
break;
}
}
}
public void write(byte[] bytes) {
String text = new String(bytes, Charset.defaultCharset());
Log.d(TAG, "write: Writing to outputstream: " + text);
try {
mmOutStream.write(bytes);
} catch (IOException e) {
Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
public void SendMessage(View v) {
byte[] bytes = send_data.getText().toString().getBytes(Charset.defaultCharset());
mConnectedThread.write(bytes);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
send_data =(EditText) findViewById(R.id.editText);
view_data = (TextView) findViewById(R.id.textView);
if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
public void Start_Server(View view) {
AcceptThread accept = new AcceptThread();
accept.start();
}
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp = null ;
// Create a new listening server socket
try{
tmp = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("appname", MY_UUID_INSECURE);
Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE);
}catch (IOException e){
Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
}
mmServerSocket = tmp;
}
public void run(){
Log.d(TAG, "run: AcceptThread Running.");
BluetoothSocket socket = null;
try{
// This is a blocking call and will only return on a
// successful connection or an exception
Log.d(TAG, "run: RFCOM server socket start.....");
socket = mmServerSocket.accept();
Log.d(TAG, "run: RFCOM server socket accepted connection.");
}catch (IOException e){
Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
}
//talk about this is in the 3rd
if(socket != null){
connected(socket);
}
Log.i(TAG, "END mAcceptThread ");
}
public void cancel() {
Log.d(TAG, "cancel: Canceling AcceptThread.");
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage() );
}
}
}
<强> activity_main.xml中强>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hpi5.bluethoothshot.MainActivity"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/textView"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="58dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="153dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:onClick="SendMessage"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="22dp"
app:layout_constraintTop_toBottomOf="@+id/editText"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Server"
android:onClick="Start_Server"
android:layout_marginEnd="53dp"
tools:layout_constraintRight_creator="1"
tools:layout_constraintBottom_creator="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginBottom="84dp" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ConnectionREq"
android:onClick="pairDevice"
android:layout_marginStart="34dp"
tools:layout_constraintTop_creator="1"
tools:layout_constraintBottom_creator="1"
app:layout_constraintBottom_toBottomOf="@+id/button2"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/button2"
android:layout_marginLeft="30dp"
app:layout_constraintVertical_bias="0.0" />
</android.support.constraint.ConstraintLayout>
答案 1 :(得分:2)
异常描述肯定有帮助,但我99%确定系统阻止你在UI线程内执行套接字连接代码 - 所以你需要创建一个新线程,将套接字创建和套接字连接代码移动到该线程最后,创建一个回调,它将指示侦听器已执行连接或失败。
请注意,android会阻止你在UI线程中进行与网络相关的耗时操作的大部分尝试,因为它会让UI变得如此懒散; - )
答案 2 :(得分:2)
两个主要问题 -
1)connect()
是一个阻塞调用,您应该始终在与主活动(UI)线程分开的线程中执行此连接过程。你是在主线程上这样做的。
注意:您应该始终调用cancelDiscovery()来确保 在调用connect()之前,设备未执行设备发现。 如果正在进行发现,则尝试连接尝试 显着放缓,而且更有可能失败。
2)如果您在第二台设备上使用相同的代码(以便您可以发送或接收数据),那么我看不到对accept()
的任何呼叫。 accept()
侦听连接请求。
同样,accept()
调用是一个阻塞调用,它不应该在主活动UI线程中执行,这样您的应用程序仍然可以响应其他用户交互。
接受传入连接的服务器组件的简化线程:
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket
// because mmServerSocket is final.
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code.
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) {
Log.e(TAG, "Socket's listen() method failed", e);
}
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned.
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "Socket's accept() method failed", e);
break;
}
if (socket != null) {
// A connection was accepted. Perform work associated with
// the connection in a separate thread.
manageMyConnectedSocket(socket);
mmServerSocket.close();
break;
}
}
}
// Closes the connect socket and causes the thread to finish.
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
}
Android文档 - BLUETOOTH