copy别人的代码,报错socket closed,这个嵌套字到底要在那个步骤关闭呀?
2022-09-16 10:13:07.902 8816-8816/com.example.stm_car1 E/THINBTCLIENT: +++ 创建成功 +++
2022-09-16 10:13:07.907 8816-8816/com.example.stm_car1 E/THINBTCLIENT: +++ 创建完成,获得本地蓝牙适配器+++
2022-09-16 10:13:07.909 8816-8816/com.example.stm_car1 E/THINBTCLIENT: ++ 启动 ++
2022-09-16 10:13:07.910 8816-8816/com.example.stm_car1 E/THINBTCLIENT: + ON RESUME +
2022-09-16 10:13:07.910 8816-8816/com.example.stm_car1 E/THINBTCLIENT: + 正在尝试连接客户端 +
2022-09-16 10:13:07.910 8816-8816/com.example.stm_car1 E/THINBTCLIENT: MAC获取成功
2022-09-16 10:13:07.910 8816-8816/com.example.stm_car1 E/THINBTCLIENT: UUID获取成功
2022-09-16 10:14:07.914 8816-8816/com.example.stm_car1 E/THINBTCLIENT: 在on Resume中关闭流!
2022-09-16 10:14:24.086 8816-8816/com.example.stm_car1 E/THINBTCLIENT: 指令B写入失败!
java.io.IOException: socket closed
at android.net.LocalSocketImpl$SocketOutputStream.write(LocalSocketImpl.java:142)
at android.bluetooth.BluetoothSocket.write(BluetoothSocket.java:585)
at android.bluetooth.BluetoothOutputStream.write(BluetoothOutputStream.java:76)
at java.io.OutputStream.write(OutputStream.java:75)
at com.example.stm_car1.MainActivity$2.onTouch(MainActivity.java:160)
at android.view.View.dispatchTouchEvent(View.java:14305)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)
at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:488)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1871)
at android.app.Activity.dispatchTouchEvent(Activity.java:4125)
at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:446)
at android.view.View.dispatchPointerEvent(View.java:14568)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6016)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5819)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5310)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5485)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5542)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8080)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8031)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7992)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8203)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:220)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loop(Looper.java:183)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2022-09-16 10:14:24.197 8816-8816/com.example.stm_car1 E/THINBTCLIENT: 指令b写入失败!
java.io.IOException: socket closed
at android.net.LocalSocketImpl$SocketOutputStream.write(LocalSocketImpl.java:142)
at android.bluetooth.BluetoothSocket.write(BluetoothSocket.java:585)
at android.bluetooth.BluetoothOutputStream.write(BluetoothOutputStream.java:76)
at java.io.OutputStream.write(OutputStream.java:75)
at com.example.stm_car1.MainActivity$2.onTouch(MainActivity.java:179)
at android.view.View.dispatchTouchEvent(View.java:14305)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:488)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1871)
at android.app.Activity.dispatchTouchEvent(Activity.java:4125)
at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:446)
at android.view.View.dispatchPointerEvent(View.java:14568)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6016)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5819)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5310)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5485)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5542)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8080)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8031)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7992)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8203)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:220)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loop(Looper.java:183)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
用代码块功能插入代码,请勿粘贴截图
package com.example.stm_car1;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
public class MainActivity extends Activity {
private static final String TAG = "THINBTCLIENT";
private static final boolean G = true;
// 蓝牙适配器
private BluetoothAdapter mBluetoothAdapter = null;
// 手机蓝牙与蓝牙模块之间的socket嵌套字
private BluetoothSocket btSocket = null;
// 发送指令的输出流
private OutputStream outStream = null;
// 按键
Button mButtonF;
Button mButtonB;
Button mButtonL;
Button mButtonR;
Button mButtonS;
// UUIOD
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// MAC地址
private static final String address = "98:DA:E0:01:0B:4E";
/**
* 预加载 activity
*
* @param savedInstanceState
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 前进
*/
// 初始化按键
mButtonF = (Button) findViewById(R.id.btnF);
// 注册一个回调,当触摸事件被发送到这个视图时调用。
mButtonF.setOnTouchListener(new Button.OnTouchListener() {
// view 视图对象
// 对象,用于报告移动(鼠标、笔、手指、轨迹球)事件。运动事件可以保存绝对或相对运动和其他数据,这取决于设备的类型。
public boolean onTouch(View v, MotionEvent event) {
// 字符串变量
String message;
// 字节数组
byte[] msgBuffer;
// 整型变量 接受
// getAction()返回正在执行的操作的类型。考虑使用getactionmask和getActionIndex来检索单独的屏蔽动作和指针索引。
int action = event.getAction();
switch (action) {
// 按下前进按钮
case MotionEvent.ACTION_DOWN:
try {
// 通过socket 得到输出流
outStream = btSocket.getOutputStream();
// outStream.close();
Log.i(TAG, "输出流创建成功!");
} catch (IOException e) {
Log.e(TAG, " 输出流创建失败!", e);
}
// 上位机与下位机约定的指令A表示按下前进
message = "A";
// 因为outputStream 只能传输字节,所以要把字符串指令编程字节流
msgBuffer = message.getBytes();
try {
//将指令写入输出流中。也就是写入socket中
outStream.write(msgBuffer);
// outStream.close();
Log.i(TAG, "(指令A)输出流写入成功");
} catch (IOException e) {
Log.e(TAG, "(指令A)输出流写入失败.", e);
}
break;
// 松开了前进按钮,与前面类似,只是指令不同。
case MotionEvent.ACTION_UP:
try {
// 通过Socket得到输出流
outStream = btSocket.getOutputStream();
//outStream.close();
Log.i(TAG, "输出流创建成功!");
} catch (IOException e) {
Log.e(TAG, "输出流创建失败!.", e);
}
// 上位机与下位机约定的指令a表示松开前进
message = "a";
// 将字符转换为字节
msgBuffer = message.getBytes();
try {
// 将指令写入输出流,也就是写入socket中
outStream.write(msgBuffer);
//outStream.close();
Log.i(TAG, "写入成功!");
} catch (IOException e) {
Log.e(TAG, "写入失败!.", e);
}
break;
}
return false;
}
});
/**
* 后退 逻辑同上
*/
// 初始化后退按键
mButtonB = (Button) findViewById(R.id.btnB);
// 注册一个回调,当触摸事件被发送到这个视图时调用。
mButtonB.setOnTouchListener(new Button.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
String message;
byte[] msgBuffer;
int action = event.getAction();
switch (action) {
// 按下后退按键
case MotionEvent.ACTION_DOWN:
try {
outStream = btSocket.getOutputStream();
//outStream.close();
Log.i(TAG, "文件创建成功!");
} catch (IOException e) {
Log.e(TAG, "文件创建失败!", e);
}
// 约定B为按下后退
message = "B";
msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
//outStream.close();
Log.i(TAG, "指令B写入成功!");
} catch (IOException e) {
Log.e(TAG, "指令B写入失败!", e);
}
break;
// 松开后退按键
case MotionEvent.ACTION_UP:
try {
outStream = btSocket.getOutputStream();
Log.i(TAG, "文件创建成功");
// outStream.close();
} catch (IOException e) {
Log.e(TAG, "文件创建失败!", e);
}
message = "b";
msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
Log.i(TAG, "指令b写入成功!");
// outStream.close();
} catch (IOException e) {
Log.e(TAG, "指令b写入失败!", e);
}
break;
}
return false;
}
});
/**
* 左转
*/
// 初始化左转按键
mButtonL = (Button) findViewById(R.id.btnL);
// 注册一个回调,当触摸事件被发送到这个视图时被调用
mButtonL.setOnTouchListener(new Button.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
String message;
byte[] msgBuffer;
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
try {
outStream = btSocket.getOutputStream();
outStream.close();
Log.i(TAG, "左转按下----输出流创建成功!");
} catch (IOException e) {
Log.e(TAG, "左转按下----输出流创建失败!.", e);
}
message = "C";
msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
outStream.close();
Log.i(TAG, "指令C写入成功!");
} catch (IOException e) {
Log.e(TAG, "指令C写入失败!", e);
}
break;
// 松开左转
case MotionEvent.ACTION_UP:
try {
outStream = btSocket.getOutputStream();
outStream.close();
Log.i(TAG, "松开左转----输出流创建成功");
} catch (IOException e) {
Log.e(TAG, "松开左转----输出流创建失败!.", e);
}
message = "c";
msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
outStream.close();
Log.i(TAG, "指令c写入成功");
} catch (IOException e) {
Log.e(TAG, "指令c写入异常!.", e);
}
break;
}
return false;
}
});
/**
*右转
* */
mButtonR = (Button) findViewById(R.id.btnR);
mButtonR.setOnTouchListener(new Button.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
String message;
byte[] msgBuffer;
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
try {
outStream = btSocket.getOutputStream();
outStream.close();
Log.i(TAG, "输出流创建成功!");
} catch (IOException e) {
Log.e(TAG, "输出流创建失败!", e);
}
message = "D";
msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
outStream.close();
Log.i(TAG, "指令D写入成功!");
} catch (IOException e) {
Log.e(TAG, "指令写入异常", e);
}
break;
case MotionEvent.ACTION_UP:
try {
outStream = btSocket.getOutputStream();
outStream.close();
Log.i(TAG, "输出流创建成功!");
} catch (IOException e) {
Log.e(TAG, "输出流创建失败!", e);
}
message = "d";
msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
outStream.close();
Log.i(TAG, "指令d写入成功!");
} catch (IOException e) {
Log.e(TAG, "指令d写入失败!", e);
}
break;
}
return false;
}
});
/**
* 停止按键
*/
mButtonS = (Button) findViewById(R.id.btnS);
mButtonS.setOnTouchListener(new Button.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
try {
// 如果try块级代码出现问题则,执行catch块代码抛出异常!!!
outStream = btSocket.getOutputStream();
//outStream.close();
Log.i(TAG, "输出流创建成功!");
} catch (IOException e) {
Log.e(TAG, "输出流创建失败!", e);
}
String message = "0";
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
// outStream.close();
Log.i(TAG, "写入成功");
} catch (IOException e) {
Log.e(TAG, "写入失败!", e);
}
return false;
}
});
if (G) Log.e(TAG, "+++ 创建成功 +++");
// 获取本地蓝牙适配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 为null
if (mBluetoothAdapter == null) {
Toast.makeText(this, "蓝牙不可用!", Toast.LENGTH_LONG).show();
// 当您的活动完成并应该关闭时调用此函数。
finish();
return;
}
if (!mBluetoothAdapter.isEnabled()) {
Toast.makeText(this, "请开启蓝牙并重新运行此程序!", Toast.LENGTH_LONG).show();
finish();
return;
}
if (G) Log.e(TAG, "+++ 创建完成,获得本地蓝牙适配器+++");
}
/**
* activity界面被显示出来的时候执行的,用户可见。
*
* 是onStop()用户再切换回这个activity就会调用onRestart()而后调用onStart()。
*
* activity在上面,但没有将它完全覆盖,用户可以看到部分activity但不能与交互。
*/
@Override
public void onStart() {
super.onStart();
if (G) Log.e(TAG, "++ 启动 ++");
}
/**
* 这通常是您的活动开始与用户交互的一个提示,这是一个很好的指示,表明该活动已处于活动状态并准备好接收输入。这有时也可能是一个过渡状态到另一个静止状态。
* 当该activity与用户能进行交互时被执行,用户可以获得activity的焦点,能够与用户交互。
*
* onResume():是onPause()是当前的acitivty被暂停了,比如被另一个透明或者Dialog样式的Activity覆盖了,之后dialog取消,activity回到可交互状态,调用onResume()。
*
* activity在下面,用户不能交互。
*/
@Override
public void onResume() {
super.onResume();
if (G) {
Log.e(TAG, "+ ON RESUME +");
Log.e(TAG, "+ 正在尝试连接客户端 +");
}
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if(mBluetoothAdapter.getRemoteDevice(address)!=null) {
Log.e(TAG, "MAC获取成功");
}else{
Log.e(TAG,"MAC获取失败");
}
try {
// btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
Log.e(TAG, "UUID获取成功");
} catch (IOException e) {
Log.e(TAG, "与客户端连接失败!", e);
}
//因为发现是蓝牙适配器的重量级过程,
// 所以在尝试使用BluetoothSocket.connect()连接到远程设备之前,
// 应该始终调用此方法。发现不由Activity管理,而是作为系统服务运行,因此应用程序应该总是调用取消发现,即使它没有直接请求发现,只是为了确保。
mBluetoothAdapter.cancelDiscovery();
try {
btSocket.connect();
Log.e(TAG, "提示:蓝牙连接已建立,数据传输链路已打开。");
} catch (IOException e) {
try {
btSocket.close();
Log.e(TAG,"在on Resume中关闭流!");
} catch (IOException e2) {
Log.e(TAG, "无法在连接失败时关闭套接字!", e2);
}
}
/*
// 创建一个数据流,同服务器通信。
if (G) Log.e(TAG, "提示:请服务器稍句话!");
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "输出流创建失败!", e);
}
String message = "1";
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
} catch (IOException e) {
Log.e(TAG, "写入异常!", e);
}
*/
}
@Override
public void onPause() {
super.onPause();
if (G) Log.e(TAG, "暂停!");
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
Log.e(TAG, "无法刷新输出流!", e);
}
}
try {
btSocket.close();
Log.e(TAG,"在onPause中关闭流!");
} catch (IOException e2) {
Log.e(TAG, "无法关闭嵌套字", e2);
}
}
/**
* /**
* * 一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被杀掉
* */
@Override
public void onStop() {
super.onStop();
if (G) Log.e(TAG, "停止");
}
/**
* 销毁
*/
@Override
public void onDestroy() {
super.onDestroy();
if (G) Log.e(TAG, "--- 销毁 ---");
}
}