一直先想做一个遥控车,正好放假了,所以这些日子有时间,然后就搜集资料,找到一个博客,忘记是哪个了博主写的了,然后就试这写一下,
做完后一运行就是就Bug ,就是当终端蓝牙开启的时候,打开这个软件时,Android 顿时弹出来个大的ANR ,然后我改了改,没这种毛病了,然后又添了一些,比如当在蓝牙关闭的状态上打开软件,软件自动会打开蓝牙。
挺好玩的的。
一共分两个Activityu第一个是搜索蓝牙进行配对操作,第二个就是发送cdm了。
我用的是Android Studio写的所以不必担心添加权限的问题,如果你是用Eclipse写的那么一定不要忘了添加这两条权限:
android:name="android.permission.BLUETOOTH"/>
android:name="android.permission.BLUETOOTH_ADMIN"/>
在打开、关闭搜索,配对中主要是用到了两个类:BlueToothAdapter,和 BlueToothSocket这两个类。
里面有一个UUID也不知道是什么东西查API解释是UUID是128位的不可变表示全局惟一标识符(UUID)。什么魔鬼??望指教。
看代码吧。
package com.example.hejingzhou.newbuledemo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.*;
import android.os.Process;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.Toast;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private Switch aSwitch;
private Button buttonVisible,buttonSearch,buttonExit;
private ListView listView;
private Handler handler;
private BluetoothAdapter bluetoothAdapter;
static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
private UUID uuid;
private List listDevice = new ArrayList<>();
private ArrayAdapter adapterDevice;
private static BluetoothSocket socket;
public static BluetoothSocket bluetoothSocket;
private static AcceptThread acceptThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById();
OnClick();
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
InitBlueTooth();
}
/************************************************************************************************************/
private void OnClick() {
//Switch开关
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked == true) {
if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
return;
} else if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
bluetoothAdapter.enable();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
Toast.makeText(MainActivity.this, "蓝牙已打开", Toast.LENGTH_SHORT).show();
}
/***********修改修改**********/
try {
acceptThread = new AcceptThread();
handler = new Handler() {
public void handle(Message message) {
switch (message.what) {
case 0:
acceptThread.start();
}
}
};
} catch (Exception e) {
Toast.makeText(MainActivity.this, "服务监听出错", Toast.LENGTH_SHORT).show();
}
}
} else if (isChecked = false) {
bluetoothAdapter.disable();
if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF)
Toast.makeText(MainActivity.this, "蓝牙已关闭", Toast.LENGTH_SHORT).show();
}
}
});
//可见性Button
buttonVisible.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
});
//搜索设备
buttonSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setTitle("本机蓝牙地址" + bluetoothAdapter.getAddress());
listDevice.clear();
bluetoothAdapter.startDiscovery();//启动搜索其他蓝牙设备
}
});
//退出Button
buttonExit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(bluetoothSocket != null)
{
try {
bluetoothSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
MainActivity.this.finish();
}
}
});
}
/************************************************************************************************************/
private void InitBlueTooth() {
Toast.makeText(MainActivity.this,"正在初始化软件,请稍等...",Toast.LENGTH_SHORT).show();
/*if(bluetoothAdapter == null)
{
Toast.makeText(MainActivity.this,"您的蓝牙不可用,请查验您的手机是否具有此功能",Toast.LENGTH_LONG).show();
return;
}
else
{*/
if(bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF)
{
aSwitch.setChecked(false);
bluetoothAdapter.enable();
if(bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON)
{
Toast.makeText(MainActivity.this,"成功帮您打开蓝牙",Toast.LENGTH_LONG).show();
}else
{
Toast.makeText(MainActivity.this,"打开蓝牙失败,请手动打开您的蓝牙",Toast.LENGTH_LONG).show();
}
}else if(bluetoothAdapter.getState() == bluetoothAdapter.STATE_ON)
{
acceptThread = new AcceptThread();
handler = new Handler()
{
public void handleMessage(Message msg)
{
switch (msg.what)
{
case 0:
acceptThread.start();
break;
}
}
};
}
//注册Receiver蓝牙设备的相关结果
//IntentFilter结构化的描述意图值匹配。IntentFilter可以匹配操作、类别和数据(通过其类型、计划和/或路径)的意图。它还包括一个“优先级”值用于订单多个匹配过滤器。
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//广播操作:指示远程设备上的键状态的改变
intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);//广播操作:指示本地适配器的蓝牙扫描模式已经改变。
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//广播操作:当地蓝牙适配器的状态已更改。
registerReceiver(serachDevices,intentFilter);
// }
}
/**************************************************************************************************************/
private void findViewById() {
aSwitch = (Switch)findViewById(R.id.switchOpenAndClose);
buttonVisible = (Button)findViewById(R.id.buttonVisible);
buttonSearch = (Button)findViewById(R.id.buttonSeraveDevice);
buttonExit = (Button)findViewById(R.id.buttonExit);
listView = (ListView)findViewById(R.id.listViewShow);
adapterDevice = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1,listDevice);
listView.setAdapter(adapterDevice);
listView.setOnItemClickListener(new ItemClickEvent());//设置ListView 的单击监听
}
/*************************************************************************************************************/
class AcceptThread extends Thread
{
private final BluetoothServerSocket serverSocket;//蓝牙服务套接口
public AcceptThread()
{
BluetoothServerSocket BTServerSocket = null;
try {
Method listenMethod = bluetoothAdapter.getClass().getMethod("listenUsingRfcommOn",new Class[]{int.class});
BTServerSocket = (BluetoothServerSocket)listenMethod.invoke(bluetoothAdapter,Integer.valueOf(1));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
serverSocket = BTServerSocket;
}
public void run()
{
while (true)
{
try {
socket = serverSocket.accept();
Log.e("MainActivity","socket = serverSocket.accept();错误");
} catch (IOException e) {
break;
}
if(socket != null)
{
manageConnectedSocket();
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
Message message = new Message();
message.what = 0;
handler.sendMessage(message);
}
public void cancel()
{
try {
serverSocket.close();
} catch (IOException e) {
Log.e("MainActivity","注销错误");
}
}
}
/*************************************************************************************************************/
class ItemClickEvent implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
String str = listDevice.get(position);
String[] values = str.split("\\|");
String address = values[1];
Log.i("address",values[1]);
uuid = UUID.fromString(SPP_UUID);
Log.i("uuid",uuid.toString());
BluetoothDevice BtDev = bluetoothAdapter.getRemoteDevice(address);//getRemoteDevice获取BluetoothDevice对象从给定的蓝牙硬件地址
Log.i("获取的蓝牙硬件对象"," "+BtDev);
Method method;
try {
method = BtDev.getClass().getMethod("createRfcommSocket",new Class[]{int.class});
bluetoothSocket = (BluetoothSocket) method.invoke(BtDev,Integer.valueOf(1));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
bluetoothAdapter.cancelDiscovery();//对蓝牙进行信号注销
try {
bluetoothSocket.connect();//蓝牙配对
Toast.makeText(MainActivity.this,"连接成功进入控制界面",Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.setClass(MainActivity.this, SendMessageActivity.class);
startActivity(intent);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this,"连接失败",Toast.LENGTH_SHORT).show();
}
}
}
/*************************************************************************************************************/
/**
* 基类代码,将收到发送的意图sendBroadcast()。
*/
private BroadcastReceiver serachDevices = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Bundle bundle = intent.getExtras();
Object[] listName = bundle.keySet().toArray();
//显示收到的消息及细节
for(int i = 0;i < listName.length;i++)
{
String keyName = listName[i].toString();
Log.i(keyName,String.valueOf(bundle.get(keyName)));
}
if(BluetoothDevice.ACTION_FOUND.equals(action))
{
BluetoothDevice BTDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String str = BTDevice.getName()+"|"+BTDevice.getAddress();
if(listDevice.indexOf(str) == -1)//indexOf检索字符串,如果为null返回-1
{
listDevice.add(str);
}
adapterDevice.notifyDataSetChanged();//每次改变刷新一下自己
}
}
};
/*************************************************************************************************************/
@Override
protected void onDestroy() {
this.unregisterReceiver(serachDevices);
super.onDestroy();
android.os.Process.killProcess(Process.myPid());//杀死Pid
acceptThread.cancel();
acceptThread.destroy();
}
/*************************************************************************************************************/
private void manageConnectedSocket()
{
bluetoothSocket = socket;
Intent newActivity = new Intent();
newActivity.setClass(MainActivity.this,SendMessageActivity.class);
startActivity(newActivity);
}
}
package com.example.hejingzhou.newbuledemo;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.logging.Handler;
public class SendMessageActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
private RadioGroup radioGroup;
private RadioButton radioPc, radioMo;
private ToggleButton TB1, TB2, TB3, TB4;
private EditText EtReceive, EtSend;
private Button BtSend, BtBack, BtClose;
private android.os.Handler handler;
private String encodeType = "GBK";
private boolean isRecording = false;
private OutputStream outputStream = null;
private ConnectedThread connectedThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_send_message);
findViewById();
StartThread();
onClickListener();
}
private void onClickListener() {
BtClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
MainActivity.bluetoothSocket.close();//关闭蓝牙接口
connectedThread.Stop();
setTitle("蓝牙连接断开");
} catch (IOException e) {
e.printStackTrace();
}
}
});
BtBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SendMessageActivity.this.finish();
}
});
TB1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (TB1.isChecked() == false) {
sendMessage("11");
} else if (TB1.isChecked() == true) {
sendMessage("10");
}
}
});
TB2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (TB2.isChecked() == false) {
sendMessage("21");
} else if (TB2.isChecked() == true) {
sendMessage("20");
}
}
});
TB3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (TB3.isChecked() == false) {
sendMessage("31");
} else if (TB3.isChecked() == true) {
sendMessage("30");
}
}
});
TB4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (TB4.isChecked() == false) {
sendMessage("41");
} else if (TB4.isChecked() == true) {
sendMessage("40");
}
}
});
BtSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String infoSend = EtSend.getText().toString();
sendMessage(infoSend);
setTitle("发送成功");
}
});
}
public void sendMessage(String str) {
try {
outputStream = MainActivity.bluetoothSocket.getOutputStream();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "输出流失败", Toast.LENGTH_SHORT);
}
byte[] msgBuffer = null;
try {
msgBuffer = str.getBytes(encodeType);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
Log.e("decode 错误","编码异常",e);
}
try {
outputStream.write(msgBuffer);
setTitle("成功发送命令");
Log.i("成功发送命令"," "+str);
} catch (IOException e) {
Toast.makeText(getApplicationContext(),"发送命令失败",Toast.LENGTH_SHORT);
}
}
/*public static void setEditTextEnable(TextView view,Boolean able){
// view.setTextColor(R.color.read_only_color); //设置只读时的文字颜色
if (view instanceof android.widget.EditText){
view.setCursorVisible(able); //设置输入框中的光标不可见
view.setFocusable(able); //无焦点
view.setFocusableInTouchMode(able); //触摸时也得不到焦点
}
}*/
@Override
protected void onDestroy() {
try {
MainActivity.bluetoothSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
super.onDestroy();
}
private void StartThread() {
connectedThread = new ConnectedThread();
handler = new MyHandler();
connectedThread.Start();
}
private void findViewById() {
radioGroup = (RadioGroup) findViewById(R.id.radioGroup);
radioPc = (RadioButton) findViewById(R.id.radioPC);
radioMo = (RadioButton) findViewById(R.id.radioMobile);
TB1 = (ToggleButton) findViewById(R.id.toggleButton);
TB2 = (ToggleButton) findViewById(R.id.toggleButton2);
TB3 = (ToggleButton) findViewById(R.id.toggleButton3);
TB4 = (ToggleButton) findViewById(R.id.toggleButton4);
EtReceive = (EditText)findViewById(R.id.editTextreceive);
EtSend = (EditText)findViewById(R.id.editTextsend);
BtSend = (Button)findViewById(R.id.buttonsend);
BtBack = (Button)findViewById(R.id.buttonback);
BtClose = (Button)findViewById(R.id.buttonclose);
}
//单选按钮
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId)
{
case R.id.radioPC:
encodeType = "GBK";
break;
case R.id.radioMobile:
encodeType = "UTF-1";
break;
default:
break;
}
}
/**
* 连接线程
*/
class ConnectedThread extends Thread
{
private InputStream inputStream = null;
private long wait;
private Thread thread;
public ConnectedThread()
{
isRecording = false;
this.wait = 50;
thread = new Thread(new ReadRunnable());
}
public void Stop()
{
isRecording = false;
}
public void Start()
{
isRecording = true;
State state = thread.getState();
if(state == State.NEW)
{
thread.start();
}else thread.resume();
}
private class ReadRunnable implements Runnable
{
@Override
public void run() {
while(isRecording)
{
try {
inputStream = MainActivity.bluetoothSocket.getInputStream();
} catch (IOException e) {
Toast.makeText(getApplicationContext(),"创建input流失败",Toast.LENGTH_SHORT).show();
}
int length =20;
byte[] temp = new byte[length];//创建一个byte数组进行获取
if(inputStream != null)
{
try {
int len = inputStream.read(temp,0,length-1);
if(len > 0)
{
byte[] bluetoothbuff = new byte[len];
System.arraycopy(temp,0,bluetoothbuff,0,bluetoothbuff.length);
String readStr = new String(bluetoothbuff,encodeType);
handler.obtainMessage(01,len,-1,readStr).sendToTarget();
}
Thread.sleep(wait);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
handler.sendEmptyMessage(00);
}
}
}
}
}
}
private class MyHandler extends android.os.Handler
{
@Override
public void dispatchMessage(Message msg) {
switch (msg.what)
{
case 00:
isRecording = false;
EtReceive.setText("");
EtSend.setHint("soclet连接已关闭");
break;
case 01:
String info = (String)msg.obj;
EtReceive.append(info);
break;
default:
break;
}
}
}
}