当前位置: 首页 > news >正文

Android Bluetooth 蓝牙通信

最近又搞到了蓝牙通信功能,重搞,走起(看成果,上代码)。

一、先看成果

二、上代码

1、蓝牙item:bluetooth_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="12dp"><TextViewandroid:id="@+id/tv_device_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="@android:color/black"android:textSize="16sp"android:textStyle="bold" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="4dp"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_device_address"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@color/black"android:textSize="12sp" /><TextViewandroid:id="@+id/tv_pair_state"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="12sp" /></LinearLayout></LinearLayout>

2、demo主Activityxml:activity_bluetooth_demo

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@mipmap/sdbei"android:orientation="vertical"><!-- 标题栏 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:background="@color/colorPrimary"android:gravity="center_vertical"android:paddingHorizontal="16dp"><Buttonandroid:id="@+id/isOut"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@null"android:text="退出"android:textColor="@android:color/white" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="16dp"android:text="蓝牙通信"android:textColor="@android:color/white"android:textSize="18sp" /></LinearLayout><!-- 设备列表区域 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="8dp"><ListViewandroid:id="@+id/device_list"android:layout_width="match_parent"android:layout_height="150dp"android:background="@android:color/white"android:divider="@color/color_EEEEEE"android:dividerHeight="1dp" /><!-- 接收消息提示 --><TextViewandroid:id="@+id/tv_received"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="8dp"android:text="接收消息区"android:textColor="@android:color/black" /></LinearLayout><!-- 聊天消息列表 --><ListViewandroid:id="@+id/chatListView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:divider="@null"android:padding="8dp" /><!-- 输入区域 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="8dp"android:gravity="center_vertical"android:orientation="horizontal"><EditTextandroid:id="@+id/et_message"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:hint="输入消息..."android:inputType="text"android:maxLines="3" /><Buttonandroid:id="@+id/btn_send"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="8dp"android:text="发送" /></LinearLayout><!-- 功能按钮区 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:orientation="horizontal"android:padding="16dp"><Buttonandroid:id="@+id/btn_scan"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="16dp"android:text="搜索蓝牙设备" /><Buttonandroid:id="@+id/btn_start_server"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="启动服务端" /></LinearLayout></LinearLayout>

3、BluetoothCallback 

public interface BluetoothCallback {// 设备发现回调void onDeviceFound(BluetoothDevice device);// 连接状态变化void onConnectionStateChanged(boolean isConnected, BluetoothDevice device);// 消息接收回调void onMessageReceived(String message);// 操作结果回调void onOperationResult(boolean success, String message);
}

4、BluetoothManager

public class BluetoothManager {private static final String TAG = "BluetoothManager";private static final String SERVICE_NAME = "GlobalBluetoothService";private static final UUID UUID_DEVICE = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");// 单例实例private static volatile BluetoothManager instance;private Context mContext;private BluetoothAdapter mBluetoothAdapter;private BluetoothSocket mClientSocket;private BluetoothServerSocket mServerSocket;private ConnectedThread mConnectedThread;private BluetoothCallback mCallback;private List<BluetoothDevice> mFoundDevices = new ArrayList<>();private boolean isConnected = false;private BluetoothDevice mConnectedDevice;// 权限请求码public static final int PERMISSION_REQUEST_BLE_S = 100;public static final int PERMISSION_REQUEST_BLE_LEGACY = 101;public static final int REQUEST_OPEN_BLUETOOTH = 0;// 广播接收器private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action == null) return;switch (action) {case BluetoothDevice.ACTION_FOUND:handleDeviceFound(intent);break;case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:if (mCallback != null) {mCallback.onOperationResult(true, "扫描完成,共发现" + mFoundDevices.size() + "台设备");}break;case BluetoothDevice.ACTION_BOND_STATE_CHANGED:handleBondStateChanged(intent);break;case BluetoothAdapter.ACTION_STATE_CHANGED:int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);if (state == BluetoothAdapter.STATE_OFF) {disconnect();if (mCallback != null) {mCallback.onConnectionStateChanged(false, null);}}break;}}};// 主线程Handlerprivate Handler mHandler = new Handler(Looper.getMainLooper());// 私有构造函数private BluetoothManager(Context context) {this.mContext = context.getApplicationContext();mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();registerReceiver();}// 单例获取方法public static BluetoothManager getInstance(Context context) {if (instance == null) {synchronized (BluetoothManager.class) {if (instance == null) {instance = new BluetoothManager(context);}}}return instance;}// 注册广播接收器private void registerReceiver() {IntentFilter filter = new IntentFilter();filter.addAction(BluetoothDevice.ACTION_FOUND);filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);mContext.registerReceiver(mBluetoothReceiver, filter);}// 设置回调public void setCallback(BluetoothCallback callback) {this.mCallback = callback;}// 检查设备是否支持蓝牙public boolean isBluetoothSupported() {return mBluetoothAdapter != null;}// 检查蓝牙是否开启public boolean isBluetoothEnabled() {return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled();}// 开启蓝牙@SuppressLint("MissingPermission")public boolean enableBluetooth() {if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {return mBluetoothAdapter.enable();}return true;}// 检查所有蓝牙权限public boolean checkAllPermissions() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {return ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED&& ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;} else {boolean hasBluetooth = ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED;boolean hasBluetoothAdmin = ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED;boolean hasLocation = ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {hasLocation &= ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;}return hasBluetooth && hasBluetoothAdmin && hasLocation;}}// 获取需要请求的权限列表public String[] getRequiredPermissions() {List<String> permissions = new ArrayList<>();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {permissions.add(Manifest.permission.BLUETOOTH_SCAN);permissions.add(Manifest.permission.BLUETOOTH_CONNECT);} else {permissions.add(Manifest.permission.BLUETOOTH);permissions.add(Manifest.permission.BLUETOOTH_ADMIN);permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);}}return permissions.toArray(new String[0]);}// 开始扫描设备@SuppressLint("MissingPermission")public void startScan() {if (!isBluetoothSupported()) {notifyOperationResult(false, "设备不支持蓝牙");return;}if (!isBluetoothEnabled()) {notifyOperationResult(false, "蓝牙未开启");return;}if (!checkAllPermissions()) {notifyOperationResult(false, "缺少蓝牙权限");return;}// 检查位置服务(Android 10及以下)if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q && !isLocationEnabled()) {notifyOperationResult(false, "请开启位置服务以搜索蓝牙设备");return;}// 清除之前的设备列表mFoundDevices.clear();// 如果正在扫描,先停止if (mBluetoothAdapter.isDiscovering()) {mBluetoothAdapter.cancelDiscovery();}// 开始扫描boolean started = mBluetoothAdapter.startDiscovery();if (started) {notifyOperationResult(true, "开始扫描设备...");// 30秒后自动停止扫描mHandler.postDelayed(() -> {if (mBluetoothAdapter.isDiscovering()) {stopScan();}}, 30000);} else {notifyOperationResult(false, "扫描启动失败");}}// 停止扫描@SuppressLint("MissingPermission")public void stopScan() {if (mBluetoothAdapter != null && mBluetoothAdapter.isDiscovering()) {mBluetoothAdapter.cancelDiscovery();notifyOperationResult(true, "扫描已停止");}}// 处理发现的设备@SuppressLint("MissingPermission")private void handleDeviceFound(Intent intent) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (device != null && !TextUtils.isEmpty(device.getAddress())) {// 避免重复添加boolean isExist = false;for (BluetoothDevice d : mFoundDevices) {if (TextUtils.equals(d.getAddress(), device.getAddress())) {isExist = true;break;}}if (!isExist) {mFoundDevices.add(device);if (mCallback != null) {mCallback.onDeviceFound(device);}}}}// 处理配对状态变化@SuppressLint("MissingPermission")private void handleBondStateChanged(Intent intent) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);if (bondState == BluetoothDevice.BOND_BONDED) {notifyOperationResult(true, "配对成功,正在连接...");connect(device); // 配对成功后自动连接} else if (bondState == BluetoothDevice.BOND_NONE) {notifyOperationResult(false, "配对已取消");}}// 连接设备@SuppressLint("MissingPermission")public void connect(BluetoothDevice device) {if (device == null) {notifyOperationResult(false, "设备不能为空");return;}// 停止扫描stopScan();// 如果已连接,先断开if (isConnected) {disconnect();}// 检查配对状态if (device.getBondState() != BluetoothDevice.BOND_BONDED) {notifyOperationResult(true, "正在与" + device.getName() + "配对...");pairDevice(device);} else {// 已配对,直接连接startClientConnect(device);}}// 配对设备private void pairDevice(BluetoothDevice device) {try {Method method = BluetoothDevice.class.getMethod("createBond");method.invoke(device);} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {Log.e(TAG, "配对失败: ", e);notifyOperationResult(false, "配对失败: " + e.getMessage());}}// 客户端连接@SuppressLint("MissingPermission")private void startClientConnect(BluetoothDevice device) {new Thread(() -> {try {closeSocket(mClientSocket);// 创建客户端SocketmClientSocket = device.createRfcommSocketToServiceRecord(UUID_DEVICE);Log.d(TAG, "开始连接设备: " + device.getName());mClientSocket.connect();// 连接成功if (mClientSocket.isConnected()) {mConnectedDevice = device;isConnected = true;mHandler.post(() -> {if (mCallback != null) {mCallback.onConnectionStateChanged(true, device);mCallback.onOperationResult(true, "已连接到: " + device.getName());}});// 启动通信线程mConnectedThread = new ConnectedThread(mClientSocket);mConnectedThread.start();} else {notifyOperationResult(false, "连接失败");}} catch (IOException e) {Log.e(TAG, "连接失败: ", e);notifyOperationResult(false, "连接失败: " + e.getMessage());closeSocket(mClientSocket);}}).start();}// 启动服务端监听@SuppressLint("MissingPermission")public void startServer() {new Thread(() -> {try {closeServerSocket();// 创建服务端SocketmServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(SERVICE_NAME, UUID_DEVICE);notifyOperationResult(true, "服务端启动,等待连接...");// 阻塞等待连接BluetoothSocket socket = mServerSocket.accept();if (socket != null && socket.isConnected()) {closeServerSocket();mClientSocket = socket;mConnectedDevice = socket.getRemoteDevice();isConnected = true;mHandler.post(() -> {if (mCallback != null) {mCallback.onConnectionStateChanged(true, mConnectedDevice);mCallback.onOperationResult(true, "已接受连接: " + mConnectedDevice.getName());}});// 启动通信线程mConnectedThread = new ConnectedThread(socket);mConnectedThread.start();}} catch (IOException e) {Log.e(TAG, "服务端启动失败: ", e);notifyOperationResult(false, "服务端启动失败: " + e.getMessage());closeServerSocket();}}).start();}// 发送消息public void sendMessage(String message) {if (!isConnected || mConnectedThread == null) {notifyOperationResult(false, "未连接到设备");return;}if (TextUtils.isEmpty(message)) {notifyOperationResult(false, "消息不能为空");return;}mConnectedThread.write(message);}// 断开连接public void disconnect() {if (!isConnected) return;isConnected = false;if (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}closeSocket(mClientSocket);closeServerSocket();mHandler.post(() -> {if (mCallback != null) {mCallback.onConnectionStateChanged(false, mConnectedDevice);mCallback.onOperationResult(true, "已断开连接");}mConnectedDevice = null;});}// 关闭Socketprivate void closeSocket(BluetoothSocket socket) {if (socket != null) {try {socket.close();} catch (IOException e) {Log.e(TAG, "关闭Socket失败: ", e);}}}// 关闭服务端Socketprivate void closeServerSocket() {if (mServerSocket != null) {try {mServerSocket.close();} catch (IOException e) {Log.e(TAG, "关闭服务端Socket失败: ", e);}mServerSocket = null;}}// 检查位置服务是否开启private boolean isLocationEnabled() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {android.location.LocationManager lm = (android.location.LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);return lm.isLocationEnabled();} else {int mode = Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.LOCATION_MODE,Settings.Secure.LOCATION_MODE_OFF);return mode != Settings.Secure.LOCATION_MODE_OFF;}}// 通知操作结果private void notifyOperationResult(boolean success, String message) {mHandler.post(() -> {if (mCallback != null) {mCallback.onOperationResult(success, message);}});}// 获取连接状态public boolean isConnected() {return isConnected;}// 获取已连接的设备public BluetoothDevice getConnectedDevice() {return mConnectedDevice;}// 数据通信线程private class ConnectedThread extends Thread {private final BluetoothSocket mmSocket;private final InputStream mmInStream;private final OutputStream mmOutStream;private final byte[] mmBuffer;public ConnectedThread(BluetoothSocket socket) {mmSocket = socket;InputStream tmpIn = null;OutputStream tmpOut = null;try {tmpIn = socket.getInputStream();tmpOut = socket.getOutputStream();} catch (IOException e) {Log.e(TAG, "获取流失败: ", e);}mmInStream = tmpIn;mmOutStream = tmpOut;mmBuffer = new byte[1024];}public void run() {int bytes; // 读取的字节数// 持续读取数据while (true) {try {if (mmInStream == null) break;bytes = mmInStream.read(mmBuffer);final String message = new String(mmBuffer, 0, bytes);// 发送到主线程mHandler.post(() -> {if (mCallback != null) {mCallback.onMessageReceived(message);}});} catch (IOException e) {Log.e(TAG, "读取数据失败: ", e);// 连接断开mHandler.post(() -> {disconnect();});break;}}}// 发送数据public void write(String message) {try {byte[] bytes = message.getBytes();mmOutStream.write(bytes);notifyOperationResult(true, "消息发送成功");} catch (IOException e) {Log.e(TAG, "发送数据失败: ", e);notifyOperationResult(false, "消息发送失败");}}// 取消连接public void cancel() {try {mmSocket.close();} catch (IOException e) {Log.e(TAG, "关闭连接失败: ", e);}}}// 释放资源public void destroy() {disconnect();try {mContext.unregisterReceiver(mBluetoothReceiver);} catch (IllegalArgumentException e) {Log.w(TAG, "广播接收器未注册");}mCallback = null;instance = null;}
}

5、在Activity中使用

public class BluetoothDemoActivity extends AppCompatActivity implements BluetoothCallback {private BluetoothManager bluetoothManager;private ListView deviceListView;private DeviceAdapter deviceAdapter;private List<BluetoothDeviceMessage> deviceList = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_bluetooth_demo);// 初始化蓝牙管理器bluetoothManager = BluetoothManager.getInstance(this);bluetoothManager.setCallback(this);// 初始化UIinitView();// 检查蓝牙状态checkBluetoothStatus();}private void initView() {deviceListView = findViewById(R.id.device_list);deviceAdapter = new DeviceAdapter(this, deviceList);deviceListView.setAdapter(deviceAdapter);deviceListView.setOnItemClickListener((parent, view, position, id) -> {
//            BluetoothDevice device = deviceList.get(position);BluetoothDevice device = ((BluetoothDeviceMessage) deviceList.get(position)).getDevice();bluetoothManager.connect(device);});// 扫描按钮findViewById(R.id.btn_scan).setOnClickListener(v -> {deviceList.clear();deviceAdapter.notifyDataSetChanged();bluetoothManager.startScan();});// 发送消息按钮findViewById(R.id.btn_send).setOnClickListener(v -> {String message = ((EditText) findViewById(R.id.et_message)).getText().toString();bluetoothManager.sendMessage(message);});// 开启服务端按钮findViewById(R.id.btn_start_server).setOnClickListener(v -> {bluetoothManager.startServer();});}@SuppressLint("MissingPermission")private void checkBluetoothStatus() {if (!bluetoothManager.isBluetoothSupported()) {Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();return;}if (!bluetoothManager.isBluetoothEnabled()) {// 请求开启蓝牙Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, BluetoothManager.REQUEST_OPEN_BLUETOOTH);} else {// 检查权限checkPermissions();}}private void checkPermissions() {if (!bluetoothManager.checkAllPermissions()) {ActivityCompat.requestPermissions(this,bluetoothManager.getRequiredPermissions(),Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ?BluetoothManager.PERMISSION_REQUEST_BLE_S :BluetoothManager.PERMISSION_REQUEST_BLE_LEGACY);}}@SuppressLint("MissingPermission")@Overridepublic void onDeviceFound(BluetoothDevice device) {BluetoothDeviceMessage deviceMsg = new BluetoothDeviceMessage(TextUtils.isEmpty(device.getName()) ? "未知设备" : device.getName(),device.getAddress());deviceMsg.setDevice(device);deviceMsg.setPaired(device.getBondState() == BluetoothDevice.BOND_BONDED);deviceList.add(deviceMsg);//        deviceList.add(device);deviceAdapter.notifyDataSetChanged();}@Overridepublic void onConnectionStateChanged(boolean isConnected, BluetoothDevice device) {@SuppressLint("MissingPermission") String status = isConnected ? "已连接到: " + (device != null ? device.getName() : "未知设备") : "连接已断开";Toast.makeText(this, status, Toast.LENGTH_SHORT).show();}@Overridepublic void onMessageReceived(String message) {// 处理接收到的消息runOnUiThread(() -> {TextView tvReceived = findViewById(R.id.tv_received);tvReceived.append("收到: " + message + "\n");});}@Overridepublic void onOperationResult(boolean success, String message) {Toast.makeText(this, message, Toast.LENGTH_SHORT).show();}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);boolean allGranted = true;for (int result : grantResults) {if (result != PackageManager.PERMISSION_GRANTED) {allGranted = false;break;}}if (!allGranted) {Toast.makeText(this, "缺少必要权限,无法使用蓝牙功能", Toast.LENGTH_SHORT).show();}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == BluetoothManager.REQUEST_OPEN_BLUETOOTH) {if (resultCode == RESULT_OK) {Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show();checkPermissions();} else {Toast.makeText(this, "请开启蓝牙以使用功能", Toast.LENGTH_SHORT).show();}}}@Overrideprotected void onDestroy() {super.onDestroy();bluetoothManager.disconnect();// 如果是全局使用,可以不调用destroy(),保持单例存在// bluetoothManager.destroy();}
}

6、打完收工,代码已全,撤退。。

不想复制,直接拖(下附下载地址):

https://download.csdn.net/download/m5157/92190699?spm=1001.2014.3001.5503

http://www.dtcms.com/a/520533.html

相关文章:

  • 简述一般网站开发方式广州三合一企业网站哪家好
  • 网站建设邀标函专业的外贸建站公司
  • C++ STL(标准模板库)深度解析:从基础到实践
  • 压缩与缓存调优实战指南:从0到1根治性能瓶颈(二)
  • Linux小课堂: SSH 配置文件详解之全局与局部 Config 文件的语义梳理与技术深化
  • 6-2〔O҉S҉C҉P҉ ◈ 研记〕❘ 客户端攻击▸利用WORD宏让客户端执行命令
  • 网站页面设计报价xampp做网站设置
  • 制作 网站 盈利怎么看网站到期时间
  • Qt6.10 | Qt Bluetooth 蓝牙
  • 网站自动化开发无极官方网站下载
  • 基于 docker compose 进行部署PandaWiki
  • 哪里建设网站设计服务
  • Python - 100天从新手到大师:第五十八天 Python中的并发编程(1-3)
  • C语言-动态内存分配
  • 多个PDF文档如何批量删除页眉处的多余信息
  • 网站服务器空间大小网站自适应宽度
  • 静态网站什么样做个简单的网站
  • EtherCAT转EtherNet/IP工业PLC网关:实现PLC与底层设备的无缝协同控制
  • 群晖边缘存储方案,让数据更近、更快、更安全
  • Python电力负荷预测:LSTM、GRU、DeepAR、XGBoost、Stacking、ARIMA结合多源数据融合与SHAP可解释性的研究
  • 做网站送的小程序有什么用多多进宝怎么推广赚钱
  • 做彩票类网站用什么服务器图片生成二维码软件
  • 机器学习(7)逻辑回归及其成本函数
  • 计算机视觉六大前沿创新方向
  • 加网络网站建设工作室医院网站规划方案
  • 流量型网站 cms西安网站建设高端
  • Oracle 19.29
  • Elasticsearch(ES)映射(Mapping)
  • 连锁餐饮行业ERP如何选择:为何Oracle NetSuite成为增长新引擎
  • 网站建设背景分析怎样重新运行wordpress