标签:
最近开发了一个蓝牙控制器App,用手机远程控制小球的运动。
开发环境为:Android Studio
实现代码
主Activity代码:
1 package com.example.wei.mybluetooth; 2 3 import android.app.Activity; 4 import android.bluetooth.BluetoothAdapter; 5 import android.bluetooth.BluetoothDevice; 6 import android.bluetooth.BluetoothSocket; 7 import android.content.BroadcastReceiver; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.content.IntentFilter; 11 import android.os.Bundle; 12 import android.os.Handler; 13 import android.os.Message; 14 import android.view.Menu; 15 import android.view.MenuItem; 16 import android.view.View; 17 import android.widget.AdapterView; 18 import android.widget.ArrayAdapter; 19 import android.widget.Button; 20 import android.widget.CompoundButton; 21 import android.widget.EditText; 22 import android.widget.Spinner; 23 import android.widget.Switch; 24 import android.widget.TextView; 25 import android.widget.Toast; 26 import java.io.IOException; 27 import java.io.InputStream; 28 import java.io.OutputStream; 29 import java.lang.ref.WeakReference; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.Set; 33 import java.util.UUID; 34 35 public class MainActivity extends Activity { 36 37 private Switch bluetoothSwitch; 38 private Button bluetoothSearch; 39 private Spinner bluetoothList; 40 private Button bluetoothConnect; 41 private TextView recvData; 42 private EditText sendData; 43 private Button bluetoothSend; 44 45 private Button upSend; 46 private Button leftSend; 47 private Button downSend; 48 private Button rightSend; 49 50 private BluetoothAdapter bluetoothAdapter; 51 private List<String> list = new ArrayList<String>(); 52 private ArrayAdapter<String> adapter; 53 private String strMacAddress; 54 private boolean booleanConnect = false; 55 private ConnectedThread connectedThread; 56 private MyHandler myHandler = new MyHandler(this); 57 58 @Override 59 protected void onCreate(Bundle savedInstanceState) { 60 super.onCreate(savedInstanceState); 61 setContentView(R.layout.activity_main); 62 63 bluetoothSwitch = (Switch) findViewById(R.id.swtch); 64 bluetoothSearch = (Button) findViewById(R.id.search); 65 bluetoothList = (Spinner) findViewById(R.id.list); 66 bluetoothConnect = (Button) findViewById(R.id.connect); 67 recvData = (TextView) findViewById(R.id.recvdata); 68 sendData = (EditText) findViewById(R.id.senddata); 69 bluetoothSend = (Button) findViewById(R.id.send); 70 71 upSend = (Button)findViewById(R.id.BtnUp); 72 leftSend = (Button)findViewById(R.id.BtnLeft); 73 downSend = (Button)findViewById(R.id.BtnDown); 74 rightSend = (Button)findViewById(R.id.BtnRight); 75 76 bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 77 if(bluetoothAdapter == null){ 78 //表明此手机不支持蓝牙 79 Toast.makeText(MainActivity.this, "未发现蓝牙设备", Toast.LENGTH_SHORT).show(); 80 return; 81 } 82 83 if (bluetoothAdapter.isEnabled()) { 84 bluetoothSwitch.setChecked(true); 85 } 86 87 adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, list); 88 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 89 bluetoothList.setAdapter(adapter); 90 91 bluetoothList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 92 @Override 93 public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 94 strMacAddress = adapter.getItem(i); 95 adapterView.setVisibility(View.VISIBLE); 96 } 97 98 @Override 99 public void onNothingSelected(AdapterView<?> adapterView) { 100 101 } 102 }); 103 104 bluetoothSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 105 @Override 106 public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 107 if (b) { 108 if (!bluetoothAdapter.isEnabled()) { //蓝牙未开启,则开启蓝牙 109 Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 110 startActivity(enableIntent); 111 } else { 112 Toast.makeText(MainActivity.this, "蓝牙已开启", Toast.LENGTH_SHORT).show(); 113 } 114 } else { 115 bluetoothAdapter.disable(); 116 Toast.makeText(MainActivity.this, "蓝牙已关闭", Toast.LENGTH_SHORT).show(); 117 } 118 } 119 }); 120 121 122 bluetoothSearch.setOnClickListener(new View.OnClickListener() { 123 @Override 124 public void onClick(View view) { 125 if (bluetoothAdapter == null) { 126 Toast.makeText(MainActivity.this, "未发现蓝牙设备", Toast.LENGTH_SHORT).show(); 127 return; 128 } else if (!bluetoothAdapter.isEnabled()) { 129 Toast.makeText(MainActivity.this, "蓝牙设备未开启", Toast.LENGTH_SHORT).show(); 130 } 131 132 Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); 133 if (pairedDevices.size() > 0) { 134 for (BluetoothDevice device : pairedDevices) { 135 adapter.remove(device.getAddress()); 136 adapter.add(device.getAddress()); 137 } 138 } else { 139 //注册,当一个设备被发现时调用mReceive 140 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 141 registerReceiver(mReceiver, filter); 142 } 143 } 144 }); 145 146 147 bluetoothConnect.setOnClickListener(new View.OnClickListener() { 148 @Override 149 public void onClick(View view) { 150 if (strMacAddress == null) { 151 Toast.makeText(MainActivity.this, "请先搜索设备", Toast.LENGTH_SHORT).show(); 152 } else { 153 BluetoothDevice device = bluetoothAdapter.getRemoteDevice(strMacAddress); 154 ConnectThread connectThread = new ConnectThread(device); 155 connectThread.start(); 156 } 157 } 158 }); 159 160 161 bluetoothSend.setOnClickListener(new View.OnClickListener() { 162 @Override 163 public void onClick(View view) { 164 if (booleanConnect == false) { 165 Toast.makeText(MainActivity.this, "请先连接设备", Toast.LENGTH_SHORT).show(); 166 } else { 167 String strSendData = new String(sendData.getText().toString()); 168 connectedThread.write(strSendData.getBytes()); 169 sendData.setText(""); 170 } 171 } 172 }); 173 174 upSend.setOnClickListener(new View.OnClickListener() { 175 @Override 176 public void onClick(View view) { 177 if (booleanConnect == false) { 178 Toast.makeText(MainActivity.this, "请先连接设备", Toast.LENGTH_SHORT).show(); 179 } else { 180 String str = "ONA\n"; 181 String strSendData = new String(str); 182 connectedThread.write(strSendData.getBytes()); 183 sendData.setText(""); 184 } 185 } 186 }); 187 188 downSend.setOnClickListener(new View.OnClickListener() { 189 @Override 190 public void onClick(View view) { 191 if (booleanConnect == false) { 192 Toast.makeText(MainActivity.this, "请先连接设备", Toast.LENGTH_SHORT).show(); 193 } else { 194 String str = "ONB\n"; 195 String strSendData = new String(str); 196 connectedThread.write(strSendData.getBytes()); 197 sendData.setText(""); 198 } 199 } 200 }); 201 202 leftSend.setOnClickListener(new View.OnClickListener() { 203 @Override 204 public void onClick(View view) { 205 if (booleanConnect == false) { 206 Toast.makeText(MainActivity.this, "请先连接设备", Toast.LENGTH_SHORT).show(); 207 } else { 208 String str = "ONC\n"; 209 String strSendData = new String(str); 210 connectedThread.write(strSendData.getBytes()); 211 sendData.setText(""); 212 } 213 } 214 }); 215 216 rightSend.setOnClickListener(new View.OnClickListener() { 217 @Override 218 public void onClick(View view) { 219 if (booleanConnect == false) { 220 Toast.makeText(MainActivity.this, "请先连接设备", Toast.LENGTH_SHORT).show(); 221 } else { 222 String str = "OND\n"; 223 String strSendData = new String(str); 224 connectedThread.write(strSendData.getBytes()); 225 sendData.setText(""); 226 } 227 } 228 }); 229 } 230 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 231 232 private static class MyHandler extends Handler { 233 WeakReference<MainActivity> mActivity; 234 235 MyHandler(MainActivity activity) { 236 mActivity = new WeakReference<MainActivity>(activity); 237 } 238 239 @Override 240 public void handleMessage(Message msg) { 241 MainActivity theActivity = mActivity.get(); 242 243 theActivity.recvData.append(msg.obj.toString()); 244 } 245 } 246 247 @Override 248 protected void onDestroy() { 249 if (connectedThread != null) { 250 connectedThread.cancel(); 251 } 252 super.onDestroy(); 253 } 254 255 256 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 257 @Override 258 public void onReceive(Context context, Intent intent) { 259 String action = intent.getAction(); 260 if(BluetoothDevice.ACTION_FOUND.equals(action)){ 261 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 262 // 已经配对的则跳过 263 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { 264 adapter.add(device.getAddress()); 265 } 266 }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //搜索结束 267 if (adapter.getCount() == 0) { 268 Toast.makeText(MainActivity.this, "没有搜索到设备", Toast.LENGTH_SHORT).show(); 269 } 270 } 271 } 272 }; 273 274 275 276 private class ConnectThread extends Thread{ 277 private BluetoothSocket mmsocket; 278 private BluetoothDevice mmdevice; 279 280 public ConnectThread(BluetoothDevice device){ 281 mmdevice = device; 282 BluetoothSocket tmp = null; 283 try { 284 tmp = mmdevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); 285 } catch (IOException e) { 286 287 } 288 mmsocket = tmp; 289 } 290 291 public void run(){ 292 bluetoothAdapter.cancelDiscovery(); //取消设备查找 293 try { 294 mmsocket.connect(); 295 } catch (IOException e) { 296 try { 297 mmsocket.close(); 298 } catch (IOException e1) { 299 300 } 301 //连接失败 302 return; 303 } 304 305 306 booleanConnect = true; 307 //新建一个数据交换线程 308 connectedThread = new ConnectedThread(mmsocket); 309 connectedThread.start(); 310 } 311 312 public void cancel() { 313 try { 314 mmsocket.close(); 315 } catch (IOException e) { 316 317 } 318 } 319 } 320 321 322 private class ConnectedThread extends Thread{ 323 private BluetoothSocket mmsocket; 324 private InputStream inStream; 325 private OutputStream outStream; 326 327 public ConnectedThread(BluetoothSocket socket){ 328 329 mmsocket = socket; 330 try { 331 //获得输入输出流 332 inStream = mmsocket.getInputStream(); 333 outStream = mmsocket.getOutputStream(); 334 } catch (IOException e) { 335 336 } 337 } 338 339 public void run(){ 340 byte[] buff = new byte[1]; 341 int len = 0; 342 //读数据需不断监听,写不需要 343 while(true){ 344 try { 345 len = inStream.read(buff); 346 //把读取到的数据发送给UI进行显示 347 String strBuffer = new String(buff); 348 349 Message toMain = myHandler.obtainMessage(); 350 toMain.obj = strBuffer; 351 myHandler.sendMessage(toMain); 352 } catch (IOException e) { 353 354 break; 355 } 356 } 357 } 358 359 public void write(byte[] buffer) { 360 try { 361 outStream.write(buffer); 362 } catch (IOException e) { 363 364 } 365 } 366 367 public void cancel() { 368 try { 369 mmsocket.close(); 370 } catch (IOException e) { 371 372 } 373 } 374 } 375 376 377 @Override 378 public boolean onCreateOptionsMenu(Menu menu) { 379 // Inflate the menu; this adds items to the action bar if it is present. 380 getMenuInflater().inflate(R.menu.menu_main, menu); 381 return true; 382 } 383 384 @Override 385 public boolean onOptionsItemSelected(MenuItem item) { 386 // Handle action bar item clicks here. The action bar will 387 // automatically handle clicks on the Home/Up button, so long 388 // as you specify a parent activity in AndroidManifest.xml. 389 int id = item.getItemId(); 390 391 //noinspection SimplifiableIfStatement 392 if (id == R.id.action_settings) { 393 super.finish(); 394 return true; 395 } 396 397 return super.onOptionsItemSelected(item); 398 } 399 }
界面代码:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 android:paddingBottom="@dimen/activity_vertical_margin" 10 tools:context=".MainActivity" 11 android:weightSum="1"> 12 13 <Switch 14 android:id="@+id/swtch" 15 android:textOn="@string/open" 16 android:textOff="@string/close" 17 android:layout_width="wrap_content" 18 android:layout_height="48dp" 19 android:layout_gravity="center_horizontal" /> 20 21 <LinearLayout 22 android:layout_width="fill_parent" 23 android:layout_height="wrap_content" 24 android:orientation="horizontal" 25 android:weightSum="1"> 26 27 <Button 28 android:id="@+id/search" 29 android:text="@string/search" 30 android:layout_width="wrap_content" 31 android:layout_height="37dp" 32 android:background="#ff9ed7ff" /> 33 34 <Spinner 35 android:id="@+id/list" 36 android:layout_width="162dp" 37 android:layout_height="48dp" 38 android:layout_weight="1.17" /> 39 40 <Button 41 android:id="@+id/connect" 42 android:text="@string/connect" 43 android:layout_width="93dp" 44 android:layout_height="38dp" 45 android:background="#ff9ed7ff" /> 46 </LinearLayout> 47 48 <LinearLayout 49 android:layout_width="fill_parent" 50 android:layout_height="wrap_content" 51 android:orientation="horizontal"> 52 53 </LinearLayout> 54 55 <RelativeLayout 56 android:layout_width="350dp" 57 android:layout_height="112dp" 58 android:layout_gravity="center_horizontal" 59 android:id="@+id/DirectionPanel"> 60 61 <Button 62 android:layout_width="wrap_content" 63 android:layout_height="wrap_content" 64 android:text="@string/up" 65 android:id="@+id/BtnUp" 66 android:layout_above="@+id/BtnRight" 67 android:layout_centerHorizontal="true" 68 android:background="#ffd0e2ff" /> 69 70 <Button 71 android:layout_width="wrap_content" 72 android:layout_height="wrap_content" 73 android:text="@string/left" 74 android:id="@+id/BtnLeft" 75 android:layout_alignParentBottom="true" 76 android:layout_toLeftOf="@+id/BtnUp" 77 android:background="#ffd0e2ff" /> 78 79 <Button 80 android:layout_width="wrap_content" 81 android:layout_height="wrap_content" 82 android:text="@string/right" 83 android:id="@+id/BtnRight" 84 android:layout_alignTop="@+id/BtnLeft" 85 android:layout_toRightOf="@+id/BtnUp" 86 android:background="#ffd0e2ff" /> 87 </RelativeLayout> 88 89 <Button 90 android:layout_width="wrap_content" 91 android:layout_height="wrap_content" 92 android:text="@string/down" 93 android:id="@+id/BtnDown" 94 android:layout_alignParentBottom="true" 95 android:layout_centerHorizontal="true" 96 android:layout_gravity="center_horizontal" 97 android:background="#ffd0e2ff" /> 98 99 <EditText 100 android:id="@+id/senddata" 101 android:layout_width="356dp" 102 android:layout_height="wrap_content" 103 android:layout_weight="0.18" /> 104 105 <Button 106 android:id="@+id/send" 107 android:text="@string/send" 108 android:layout_width="84dp" 109 android:layout_height="33dp" 110 android:background="#ff9ed7ff" 111 android:layout_gravity="right" /> 112 113 <TextView 114 android:text="@string/recv" 115 android:layout_width="wrap_content" 116 android:layout_height="wrap_content" /> 117 118 <ScrollView 119 android:layout_width="match_parent" 120 android:layout_height="66dp" 121 android:id="@+id/scrollView" 122 android:layout_weight="0.82" 123 android:background="#ffc8c8c8"> 124 125 <TextView 126 android:id="@+id/recvdata" 127 android:layout_width="fill_parent" 128 android:layout_height="wrap_content" 129 android:layout_weight="0.99" 130 android:background="#ffc8c8c8" /> 131 </ScrollView> 132 133 134 </LinearLayout>
实现的效果
实现工程代码:蓝牙控制器
参考资料:
http://www.pudn.com/downloads691/sourcecode/comm/android/detail2784484.html
标签:
原文地址:http://www.cnblogs.com/cv-pr/p/4709188.html