想了想,还是把这个项目记录一下,刚接触Android不久,这个算是第二个Android项目吧!不废话了,还是开始叙述一下项目吧!整个项目涉及Android的Wifi、Bluetooth通信,这里只介绍蓝牙部分:

一边是Android手机,另一端是串口蓝牙模块,具体是在淘宝买的(参考网址:http://item.taobao.com/item.htm?id=12792736263),串口蓝牙与AVR(ATMEGA 1280)相连。Android手机通过蓝牙向ATMEGA 1280发送指令信息来控制机器人做出相应动作。

主界面截图如下:两个EditText输入两个马达的速度,后面两个按钮设置马达转动的方向,点击发送指令开始发送,同时在下面的TextView中显示所发送的指令。

android手机通过串口蓝牙透传模块与AVR单片机通信实例。。。蓝牙服务程序案例_第1张图片

界面布局比较简单,就不再贴代码了。解释一下指令格式:前四位为固定值“CMD:”;接下来四位为ACK发送成功一次,ACK累加1;接下来四位设置第一个马达,第一位设置方向,后三位为速度;最后四位就是第二个马达的设置。

Android要使用蓝牙,首先要在AndroidManifest.xml文件中进行如下配置:

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />

在AndroidManifest.xml里面注册Service
<service android:name=".BluetoothServe.BluetoothService" android:enabled="true"></service>


1、首先是主Activity,主界面如上图,点击菜单,可以扫描远端蓝牙设备,可以设置本机蓝牙可见性,代码如下:

package com.example.android.BluetoothChat;import java.io.IOException;import com.example.android.BluetoothServe.BluetoothService;import com.example.android.BluetoothServe.BluetoothData;import android.app.Activity;import android.app.AlertDialog;import android.app.Dialog;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothSocket;import android.content.ComponentName;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.view.Menu;import android.view.MenuInflater;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class BluetoothChat extends Activity {/** Called when the activity is first created. */private static final String TAG = "BlutoothTest";private static final boolean D = true ;private Button btF1,btF2,btW1,btW2,sendCMD;private TextView mTextView;private TextView commandview,ackview;private EditText edit1,edit2;private BluetoothAdapter myBluetoothAdapter = null;private BluetoothSocket btSocket = null;private static final int REQUEST_CONNECT_DEVICE = 1;private String BackACK = "ACK:";    private String speed1,speed2;private int left = 1,right=1;private static int count = 1;private BluetoothData bluetoothData;//此处用于启动蓝牙服务程序    private ServiceConnection connection=new ServiceConnection(){@Overridepublic void onServiceConnected(ComponentName arg0, IBinder service) {bluetoothData = (BluetoothData)service; }@Overridepublic void onServiceDisconnected(ComponentName arg0) {bluetoothData = null;}};    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);             //本地蓝牙启动         myBluetoothAdapter =BluetoothAdapter.getDefaultAdapter();        OpenBluetooth(myBluetoothAdapter);               try {       bindService(new Intent(BluetoothChat.this,BluetoothService.class),        connection, Context.BIND_AUTO_CREATE);} catch (Exception e) {// TODO: handle exception}               btF1 = (Button)findViewById(R.id.bt4);        btF2 = (Button)findViewById(R.id.bt5);        btW1 = (Button)findViewById(R.id.bt1);        btW2 = (Button)findViewById(R.id.bt2);        edit1 = (EditText) findViewById(R.id.edit1);        edit2 = (EditText) findViewById(R.id.edit2);        mTextView =(TextView) findViewById(R.id.mytext);        commandview = (TextView) findViewById(R.id.commandview);        sendCMD = (Button)findViewById(R.id.bt3);         ackview = (TextView) findViewById(R.id.ackview);                       btF1.setOnClickListener(new myButtonClickListener());        btF2.setOnClickListener(new myButtonClickListener());        btW1.setOnClickListener(new myButtonClickListener());              btW2.setOnClickListener(new myButtonClickListener());                sendCMD.setOnClickListener(new OnClickListener() {                       @Overridepublic void onClick(View v) {// TODO Auto-generated method stubString command = "CMD:"; try {     count = bluetoothData.getACK();} catch (Exception e) {// TODO: handle exception}speed1 = edit1.getText().toString();speed2 = edit2.getText().toString();command +=  bluetoothData.CreateCMD(speed1, speed2, String.valueOf(count), left, right);try {bluetoothData.SendMessage(command);//bluetoothData.getACK();} catch (Exception e) {// TODO: handle exception}commandview.setText(command);//count++;}});    }     private void OpenBluetooth(BluetoothAdapter myBluetoothAdapter){//本地蓝牙启动         if(myBluetoothAdapter == null)        {        Toast.makeText(this,"蓝牙不可用", Toast.LENGTH_LONG).show();        //finish();         return;        }        if(!myBluetoothAdapter.isEnabled())        {        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);        startActivity(enableIntent);        }}    class myButtonClickListener implements OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()){            case R.id.bt1: left=0;  mTextView.setText("马达一向后");   break;                                    case R.id.bt2: right=0;  mTextView.setText("马达二向后");  break;                        case R.id.bt4: left=1;  mTextView.setText("马达一向前");   break;                                     case R.id.bt5: right=1; mTextView.setText("马达二向前");   break;           default: break;}}}    @Overrideprotected void onStart() {// TODO Auto-generated method stubsuper.onStart();if(D){Log.e(TAG, "++ ON START ++");Log.e(TAG, "ABOUT TO ATTEMPT CLIENT CONNECT");}}    @Override   protected void onResume(){   super.onResume();     new Thread()   {   public void run()   {   try {   if(bluetoothData.getMessage() != null)       BackACK += bluetoothData.getMessage();   ackview.setText(BackACK);   } catch (Exception e) {   // TODO: handle exception   }   try {   sleep(1000);   } catch (InterruptedException e) {   // TODO Auto-generated catch block   e.printStackTrace();   }   }   }.start();   if(D){   Log.e(TAG, "++ ON RESUME ++");   }     }public void DisplayMessage(String str){   Toast.makeText(this, str, Toast.LENGTH_LONG).show();}        //创建对话框的方法   @Override protected Dialog onCreateDialog(int id) { // TODO Auto-generated method stub AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(BackACK)        .setCancelable(false)        .setPositiveButton("YES", new DialogInterface.OnClickListener() {  @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub //MyActivity.this.finish(); dialog.dismiss(); } });  AlertDialog alert = builder.create(); return alert; //return super.onCreateDialog(id); }@Overrideprotected void onPause() {  // TODO Auto-generated method stubsuper.onPause();if(D){Log.e(TAG, "++ ON PAUSE ++");}}@Overrideprotected void onStop() {// TODO Auto-generated method stubsuper.onStop();//count = 1;if(D){Log.e(TAG, "++ ON STOP ++");}}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubunbindService(connection);super.onDestroy();//count = 1;if (D){Log.e(TAG, "++ ON DESTROY ++");}try {if(btSocket != null)  btSocket.close();} catch (IOException e) {    Log.e(TAG, "Close failed");}}    @Override    public boolean onCreateOptionsMenu(Menu menu) {        MenuInflater inflater = getMenuInflater();        inflater.inflate(R.menu.option_menu, menu);        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        switch (item.getItemId()) {        case R.id.scan:            // Launch the DeviceListActivity to see devices and do scan            Intent serverIntent = new Intent(this, DeviceListActivity.class);            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);            return true;        case R.id.discoverable:            // Ensure this device is discoverable by others        ensureDiscoverable();            return true;        }        return false;    }   //设置本机蓝牙可见性    private void ensureDiscoverable() {        if(D) Log.d(TAG, "ensure discoverable");        if (myBluetoothAdapter.getScanMode() !=            BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);            startActivity(discoverableIntent);        }    }}

开始是将蓝牙服务程序作为主界面的一个进程,结果运行速度比较慢,由于程序一启动就进行蓝牙连接,所以主进程被阻塞,导致程序启动后过好一会才有反应,而且手机一旦锁屏后,蓝牙连接被断开,解锁后又重新进行 蓝牙连接,觉得很不方便,效率不高。所以把整个蓝牙的连接建立、蓝牙数据传送以及其他处理放到service里面,程序启动后,启动蓝牙服务程序一直处于后台运行,当要传递数据时直接调用service里面的服务即可。

2、下面是蓝牙服务程序

package com.example.bote.BluetoothServe;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.lang.reflect.Method;import java.util.UUID;import android.app.Service;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothSocket;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.util.Log;import android.widget.Toast;public class BluetoothService extends Service {private static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");private static String address = "00:12:08:21:06:01";//远端蓝牙地址private BluetoothAdapter myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();   //获取本地蓝牙信息private BluetoothDevice mDevice = myBluetoothAdapter.getRemoteDevice(address);  //获取远端蓝牙信息private BluetoothSocket btSocket = null;private InputStream inputStream = null;private OutputStream outputStream = null;private int temp = 0;private String CMD = null;private String BackACK = null;private static final String TAG = "BlutoothService";private int ACK=0;/*Binder类实现BluetoothData接口*/public class myIBinder extends Binder implements BluetoothData {BluetoothService getService() {return BluetoothService.this;}/*发送指令函数,参数为指令信息,发送成功返回true,否则返回false*/public boolean SendMessage(String str) {// TODO Auto-generated method stubbyte[] msgBuffer;msgBuffer = str.getBytes();try {if (btSocket != null) {outputStream = btSocket.getOutputStream();//打开输出流}} catch (IOException e) {Log.e(TAG, "ON Resume:output stream creation failed");}try {outputStream.write(msgBuffer);ACK++;             //发送成功后,ACK自动加一if(ACK>9999){ACK=0;}return true;} catch (IOException e) {// TODO: handle exceptionLog.e(TAG, "On Resume:Exception during write");DisplayMessage("发送失败!");}return false;}/*获取ACK信息并返回*/public String getMessage() {// TODO Auto-generated method stubif (BackACK != null) {return BackACK;}return null;}/*初始速度设置函数,向船发送指令,设置两个马达的初始速度,发送成功返回true,否则返回false*/public boolean Sendmessagelr(int left, int right) {// TODO Auto-generated method stubString string = null;string=CreateCMD(String.valueOf(left),String.valueOf(right),String.valueOf(ACK),1,1);SendMessage(string);return false;}/*生成指令函数,通过传递速度、ACK以及方向信息来生成一个指令 * 指令的前4位表示ACK,不足四位的前面补零 * 接下来4位为第一个马达信息,第一位表示方向,为0表示反转,为1表示正转,后三位为速度大小,不足3位的前面补零 * 最后4位为第二个马达信息,第一位表示方向,为0表示反转,为1表示正转,后三位为速度大小,不足3位的前面补零*/public String CreateCMD(String speed1, String speed2, String ACK,int left, int right) {// TODO Auto-generated method stubtemp = ACK.length();while (temp < 4){ACK='0'+ACK;temp++;}CMD = ACK;temp = speed1.length();while (temp < 3){speed1='0'+speed1;temp++;}CMD += (left+speed1);temp = speed2.length();while (temp < 3){speed2='0'+speed2;temp++;}CMD += (right+speed2);return CMD+'!';      }}private IBinder mBinder = new myIBinder();@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubSystem.out.println("onBind Service");return mBinder;}@Overridepublic void onCreate() {// TODO Auto-generated method stubSystem.out.println("onCreate Service");DisplayMessage("Bluetooth Service Start");DisplayMessage("正在尝试连接蓝牙设备" + mDevice + "请稍后···");/*将蓝牙连接建立过程放到新线程中*/new Thread() {public void run() {//如果本地蓝牙尚未开启,无法建立连接,必须等待蓝牙开启if (!myBluetoothAdapter.isEnabled()) {try {Log.e(TAG, "线程休眠");sleep(8000);  //线程睡眠,等待蓝牙开启} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}Log.e(TAG, "线程开始");try {btSocket = mDevice.createRfcommSocketToServiceRecord(myUUID); //创建socket通信} catch (IOException e) {// TODO Auto-generated catch blockDisplayMessage("创建套接字失败!");e.printStackTrace();}try {connectDevice();   //调用蓝牙连接函数来建立连接} catch (Exception e) {// TODO: handle exception}}}.start();super.onCreate();}@Overridepublic void onDestroy() {// TODO Auto-generated method stubSystem.out.println("onDestroy Service");super.onDestroy();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// TODO Auto-generated method stubLog.i("LocalService", "Received Start ID" + startId + ":" + intent);System.out.println("onStartCommand Service");return START_STICKY;}@Overridepublic void onStart(Intent intent, int startId) {// TODO Auto-generated method stubSystem.out.println("onStart Service");getMessageThread getMessage = new getMessageThread();getMessage.start();super.onStart(intent, startId);}@Overridepublic boolean onUnbind(Intent intent) {// TODO Auto-generated method stubSystem.out.println("onUnbind Service");return super.onUnbind(intent);}public void DisplayMessage(String str) {Toast.makeText(this, str, Toast.LENGTH_LONG).show(); //显示Toast信息}protected void connectDevice() {try {// 连接建立之前的先配对if (mDevice.getBondState() == BluetoothDevice.BOND_NONE) {Method creMethod = BluetoothDevice.class.getMethod("createBond");Log.e("TAG", "开始配对");creMethod.invoke(mDevice);} else {}} catch (Exception e) {// TODO: handle exceptionDisplayMessage("无法配对!");e.printStackTrace();}myBluetoothAdapter.cancelDiscovery();try {btSocket.connect();DisplayMessage("连接成功!");} catch (IOException e) {// TODO: handle exceptionDisplayMessage("连接失败!");try {btSocket.close();} catch (IOException e2) {// TODO: handle exceptionLog.e(TAG, "Cannot close connection when connection failed");}}}    //从蓝牙端获取信息类,这个方法不一定对或者并没有完善public class getMessageThread extends Thread {public void run() {if (btSocket != null) {try {inputStream = btSocket.getInputStream();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}try {BackACK = Integer.toString(inputStream.read());} catch (Exception e) {// TODO: handle exception}}}}


3、那Activity和Service如何传递数据呢?从service程序总可以看出,多了一个myIBinder类继承自Binder,并且实现接口BluethData,对了,就是通过这个接口来实现Activity与Service传递数据,接口定义如下:

/* * 蓝牙服务接口   * */package com.example.bote.BluetoothServe;public interface BluetoothData {/*发送指令函数,参数为指令信息,发送成功返回true,否则返回false*/public boolean SendMessage(String str);/*从蓝牙端获取信息函数,返回的信息为获取到的字符窜*/public String getMessage();/*初始速度设置函数,向船发送指令,设置两个马达的初始速度,发送成功返回true,否则返回false*/public boolean Sendmessagelr(int left, int right);/*生成指令函数,通过传递速度、ACK以及方向信息来生成一个指令*/public String CreateCMD(String speed1, String speed2, String ACK,int left, int right);}


4、如果这样直接制定远端蓝牙的地址建立连接,那么当要改变地址时,得手动修改源程序的蓝牙地址,这样显得不人性化,所以添加一个扫描蓝牙地址的功能。扫描程序没必要自己写,下面是Android自带的例子BluetoothChat里面的DeviceListActivity.java的内容,直接用就行,不过,有个地方需要修改一下,就是当点击扫描到的蓝牙地址时,需要重新启动蓝牙服务程序,直接调用service里面的OnStart()方法就行。修改如下:
// The on-click listener for all devices in the ListViews    private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {        public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {            // Cancel discovery because it's costly and we're about to connect            mBtAdapter.cancelDiscovery();            // Get the device MAC address, which is the last 17 chars in the View            String info = ((TextView) v).getText().toString();            String address = info.substring(info.length() - 17);            BluetoothService nService = new BluetoothService();                   // Create the result Intent and include the MAC address            Intent intent = new Intent();            intent.putExtra(EXTRA_DEVICE_ADDRESS, address);            nService.onStart(intent,1);  //启动蓝牙服务                       setResult(Activity.RESULT_OK, intent);            finish();        }    };

这是几个月前做的项目,现在来梳理,可能有些地方有问题。还有此处的重点是向单片机发送信息,并没有处理从单片机回送的信息,因此简化了蓝牙接收信息的过程,当然处理起来也不难,网上有很多教程。请多多指教~
   

更多相关文章

  1. Android 获取无线蓝牙MAC信息代码
  2. Android查看手机线程指令
  3. Android smali语言功能指令详细介绍
  4. Android实现蓝牙打印
  5. 根据文件名称修改安卓默认的蓝牙接收文件地址
  6. Android 中文API (65) ―― BluetoothClass[蓝牙]
  7. adb pm 指令介绍
  8. android bluetooth UUID蓝牙查询表
  9. Android 蓝牙(BLE)连接,发送,接收消息

随机推荐

  1. 包建强的培训课程(2):Android与设计模式
  2. Android(安卓)LOG机制的实现的详细解读
  3. Google Android开发精华教程
  4. Android(安卓)ADB over TCP/IP 及在Mini6
  5. 利用BLCR加快android的启动过程
  6. Android(安卓)面试 15 家大厂,这个问题是
  7. Android中获取当前位置信息
  8. Android(安卓)移植到C#
  9. Android开发指南-框架主题-资源和资产
  10. Android内存阀值修改--内存回收机制配置