zoukankan      html  css  js  c++  java
  • Android 基于蓝牙的方向控制器

    最近开发了一个蓝牙控制器App,用手机远程控制小球的运动。

    包含了一些基础知识:多线程使用,页面UI数据更新,按钮事件,选择项功能,蓝牙功能(蓝牙打开,蓝牙搜索,蓝牙连接,蓝牙命令发送,蓝牙命令接收)。

    开发环境为:Android Studio+Java,蓝牙模块HC-06(自发自收模式)。

    实现代码

    主Activity代码:

      1 package com.example.cxk.lightballcontroller;
      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
    ";
    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
    ";
    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
    ";
    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
    ";
    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

  • 相关阅读:
    记sql语句
    thinkPHP小记
    php操作目录和文件
    ubuntu搭配lamp
    phpStorm实用快捷键
    在wamp中www的文件夹(项目)打不开解决办法
    php正则表达式
    远程桌面,出现身份验证错误,要求的函数不正确,这可能是由于CredSSP加密Oracle修正
    discuz增加中文验证码
    react webpack 环境配置
  • 原文地址:https://www.cnblogs.com/cv-pr/p/4709188.html
Copyright © 2011-2022 走看看