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, "--- 销毁 ---"); } }
这代码写的真是又臭又长
代码太多就封装函数,不要用匿名函数了,看上去乱糟糟的,翻起来特别费劲,问题还找不到你关键代码在哪,全混在一起
粗略翻了一下,怎么到处建立输出流,没有输入流吗