Android蓝牙聊天示例应用程序使用.doc_第1页
Android蓝牙聊天示例应用程序使用.doc_第2页
Android蓝牙聊天示例应用程序使用.doc_第3页
Android蓝牙聊天示例应用程序使用.doc_第4页
Android蓝牙聊天示例应用程序使用.doc_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

本文我们将通过学习Android的蓝牙聊天示例应用程序来介绍蓝牙开发包的使用,该示例程序完整的包含了蓝牙开发的各个部分,将实现两个设备通过蓝牙进行连接并聊天。AndroidManifest.xml前面我们说过,在使用蓝牙API时就需要开启某些权限,同时我们还可以从AndroidManifest.xml文件中找到应用程序启动时所进入的界面Activity等信息,因此下面我们首先打开AndroidManifest.xml文件,代码如下:复制到剪贴板Java代码1. 首先minSdkVersion用于说明该应用程序所需要使用的最小SDK版本,这里设置为6,也就是说最小需要使用android1.6版本的sdk,同时Ophone则需要使用oms2.0版本,然后打开了BLUETOOTH和BLUETOOTH_ADMIN两个蓝牙操作相关的权限,最后看到了两个Activity的声明,他们分别是BluetoothChat(默认主Activity)和DeviceListActivity(显示设备列表),其中DeviceListActivity风格被定义为一个对话框风格,下面我们将分析该程序的每个细节。BluetoothChat首先,程序启动进入BluetoothChat,在onCreate函数中对窗口进行了设置,代码如下:复制到剪贴板Java代码1. /设置窗口布局requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);setContentView(R.layout.main);getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.custom_title); 这里可以看到将窗口风格设置为自定义风格了,并且指定了自定义title布局为custom_title,其定义代码如下:复制到剪贴板Java代码1. 该布局将title设置为一个相对布局RelativeLayout,其中包含了两个TextView,一个在左边一个在右边,分别用于显示应用程序的标题title和当前的蓝牙配对链接名称,如下图所示。其中左边显示为应用程序名称BluetoothChat,右边显示一个connected:scort则表示当前配对成功正在进行聊天的链接名称。整个聊天界面的布局在main.xml中实现,代码如下:复制到剪贴板Java代码1. 整个界面的布局将是一个线性布局LinearLayout,其中包含了另一个ListView(用于显示聊天的对话信息)和另外一个线性布局来实现一个发送信息的窗口,发送消息发送框有一个输入框和一个发送按钮构成。整个界面如下图所示。布局好界面,下面我们需要进入编码状态,首先看BluetoothChat所要那些成员变量,如下代码所示:复制到剪贴板Java代码1. publicclassBluetoothChatextendsActivity/DebuggingprivatestaticfinalStringTAG=BluetoothChat;privatestaticfinalbooleanD=true;/从BluetoothChatServiceHandler发送的消息类型publicstaticfinalintMESSAGE_STATE_CHANGE=1;publicstaticfinalintMESSAGE_READ=2;publicstaticfinalintMESSAGE_WRITE=3;publicstaticfinalintMESSAGE_DEVICE_NAME=4;publicstaticfinalintMESSAGE_TOAST=5;/从BluetoothChatServiceHandler接收消息时使用的键名(键-值模型)publicstaticfinalStringDEVICE_NAME=device_name;publicstaticfinalStringTOAST=toast;/Intent请求代码(请求链接,请求可见)privatestaticfinalintREQUEST_CONNECT_DEVICE=1;privatestaticfinalintREQUEST_ENABLE_BT=2;/LayoutViewsprivateTextViewmTitle;privateListViewmConversationView;privateEditTextmOutEditText;privateButtonmSendButton;/链接的设备的名称privateStringmConnectedDeviceName=null;/ArrayadapterfortheconversationthreadprivateArrayAdaptermConversationArrayAdapter;/将要发送出去的字符串privateStringBuffermOutStringBuffer;/本地蓝牙适配器privateBluetoothAdaptermBluetoothAdapter=null;/聊天服务的对象privateBluetoothChatServicemChatService=null;/. 其中Debugging部分则将用于我们在调试程序时通过log打印日志用,其他部分我们都加入了注释,需要说明的是BluetoothChatService ,它是我们自己定义的一个用来管理蓝牙的端口监听,链接,管理聊天的程序,后面我们会介绍。在这里需要说明一点,这些代码都出自google的员工之手,大家在学习时,可以借鉴很多代码编写的技巧和风格,这都将对我们有非常大的帮助。然后,我们就需要对界面进行一些设置,如下代码将用来设置我们自定义的标题title需要显示的内容:复制到剪贴板Java代码1. /设置自定义title布局mTitle=(TextView)findViewById(R.id.title_left_text);mTitle.setText(R.string.app_name);mTitle=(TextView)findViewById(R.id.title_right_text);左边的TextView被设置为显示应用程序名称,右边的则需要我们在链接之后在设置更新,目前则显示没有链接字样,所以这里我们暂不设置,进一步就需要获取本地蓝牙适配器BluetoothAdapter了,因为对于有关蓝牙的任何操作都需要首先获得该蓝牙适配器,获取代码非常简单,如下:复制到剪贴板Java代码1. /得到一个本地蓝牙适配器mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();/如果适配器为null,则不支持蓝牙if(mBluetoothAdapter=null)Toast.makeText(this,Bluetoothisnotavailable,Toast.LENGTH_LONG).show();finish();return;getDefaultAdapter()函数用于获取本地蓝牙适配器,然后检测是否为null,如果为null则表示没有蓝牙设备的支持,将通过toast告知用户。在onStart()函数中,我们将检测蓝牙是否被打开,如果没有打开,则请求打开,否则就可以设置一些聊天信息的准备工作,代码如下:OverridepublicvoidonStart()super.onStart();if(D)Log.e(TAG,+ONSTART+);/如果蓝牙没有打开,则请求打开/setupChat()willthenbecalledduringonActivityResultif(!mBluetoothAdapter.isEnabled()IntentenableIntent=newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableIntent,REQUEST_ENABLE_BT);/否则,设置聊天会话elseif(mChatService=null)setupChat();如果蓝牙没有打开,我们则通过BluetoothAdapter.ACTION_REQUEST_ENABLE来请求打开蓝牙,REQUEST_ENABLE_BT则是我们自己定义的用于请求打开蓝牙的Intent代码,最后当我们调用startActivityForResult来执行请求时,就会在onActivityResult函数中得到一个反馈,如果当前蓝牙已经打开,那么就可以调用setupChat函数来准备蓝牙聊天相关的工作,稍后分析该函数的具体实现。下面我们分析一下请求打开蓝牙之后,在onActivityResult 中得到的反馈信息,我们传递了REQUEST_ENABLE_BT代码作为请求蓝牙打开的命令,因此在onActivityResult 中,需要会得到一个请求代码为REQUEST_ENABLE_B的消息,对于其处理如下代码所示:复制到剪贴板Java代码1. caseREQUEST_ENABLE_BT:/在请求打开蓝牙时返回的代码 2. if(resultCode=Activity.RESULT_OK) 3. /蓝牙已经打开,所以设置一个聊天会话 4. setupChat(); 5. else 6. /请求打开蓝牙出错 7. Log.d(TAG,BTnotenabled); 8. Toast.makeText(this,R.string.bt_not_enabled_leaving,Toast.LENGTH_SHORT).show(); 9. finish(); 10. 在请求时,如果返回代码为Activity.RESULT_OK,则表示请求打开蓝牙成功,那么我们就可以和上面的操作进度一样,调用setupChat来设置蓝牙聊天相关信息,如果返回其他代码,则表示请求打开蓝牙失败,这时我们同样通过一个Toast来告诉用户,同时也需要调用finish()函数来结束应用程序。如果打开蓝牙无误,那么下面我们开始进入setupChat的设置,其代码实现如下:复制到剪贴板Java代码1. privatevoidsetupChat()Log.d(TAG,setupChat();/初始化对话进程mConversationArrayAdapter=newArrayAdapter(this,R.layout.message);/初始化对话显示列表mConversationView=(ListView)findViewById(R.id.in);/设置话显示列表源mConversationView.setAdapter(mConversationArrayAdapter);/初始化编辑框,并设置一个监听,用于处理按回车键发送消息mOutEditText=(EditText)findViewById(R.id.edit_text_out);mOutEditText.setOnEditorActionListener(mWriteListener);/初始化发送按钮,并设置事件监听mSendButton=(Button)findViewById(R.id.button_send);mSendButton.setOnClickListener(newOnClickListener()publicvoidonClick(Viewv)/取得TextView中的内容来发送消息TextViewview=(TextView)findViewById(R.id.edit_text_out);Stringmessage=view.getText().toString();sendMessage(message););/初始化BluetoothChatService并执行蓝牙连接mChatService=newBluetoothChatService(this,mHandler);/初始化将要发出的消息的字符串mOutStringBuffer=newStringBuffer(); 首先构建一个对话进程mConversationArrayAdapter,然后从xml中取得用于显示对话信息的列表mConversationView,最后将列表的数据来源Adapter设置为mConversationArrayAdapter,这里我们可以看到mConversationArrayAdapter所指定的资源为message.xml,其定义实现如下:复制到剪贴板Java代码1. 很简单,就包含了一个TextView用来显示对话内容即可,这里设置了文字标签的尺寸大小textSize和padding属性。然后我们取得了编辑框mOutEditText,用于输入聊天内容的输入框,并对其设置了一个事件监听mWriteListener,其监听函数的实现如下:复制到剪贴板Java代码1. /TheactionlistenerfortheEditTextwidget,tolistenforthereturnkeyprivateTextView.OnEditorActionListenermWriteListener=newTextView.OnEditorActionListener()publicbooleanonEditorAction(TextViewview,intactionId,KeyEventevent)/按下回车键并且是按键弹起的事件时发送消息if(actionId=EditorInfo.IME_NULL&event.getAction()=KeyEvent.ACTION_UP)Stringmessage=view.getText().toString();sendMessage(message);if(D)Log.i(TAG,ENDonEditorAction);returntrue; 首先在其监听中实现了onEditorAction函数,我们通过判断其参数actionId来确定事件触发的动作,其中的EditorInfo.IME_NULL在Ophone中表示回车键消息,然后再加上KeyEvent.ACTION_UP,则表示当用户按下回车键并弹起时才触发消息的处理,处理过程也很简单,将输入框中内容取出到变量message中,然后调用sendMessage函数来发送一条消息,具体的发送细节,我们稍后分析。在setupChat函数中,我们还对发送消息的按钮进行的初始化,同样为其设置了事件监听(setOnClickListener),监听的内容则也是取得输入框中的信息,然后调用sendMessage函数来发送消息,和用户按回车键来发送消息一样。最后一个重要的操作就是初始化了BluetoothChatService对象mChatService用来管理蓝牙的链接,聊天的操作,并且设置了其Handler对象mHandler来负责数据的交换和线程之间的通信。另外还准备了一个空的字符串对象mOutStringBuffer,用于当我们在发送消息之后,对输入框的清理。应用菜单该应用程序除了这些界面的布局之外,我们还为其设置了一个菜单,菜单包括了扫描设备和使设备可见(能够被其他设备所搜索到),创建菜单的方式有很多种,这里gogole的员工,比较喜欢和推崇使用xml布局(将界面和逻辑分开),所以我们首先看一下对于该应用程序通过xml所定义的菜单布局,代码如下:复制到剪贴板Java代码1. 这样的定义的确非常的清晰,我们可以随意向这个Menu中添加菜单选项(itme),这里就定义了上面我们所说的两个菜单。然后再程序中通过onCreateOptionsMenu函数中来装载该菜单布局,遂于菜单的点击可以通过onOptionsItemSelected函数的不同参数来辨别,下面是该应用程序中对菜单选项的处理和装载菜单布局:复制到剪贴板Java代码1. /创建一个菜单OverridepublicbooleanonCreateOptionsMenu(Menumenu)MenuInflaterinflater=getMenuInflater();inflater.inflate(R.menu.option_menu,menu);returntrue;/处理菜单事件OverridepublicbooleanonOptionsItemSelected(MenuItemitem)switch(item.getItemId()caseR.id.scan:/启动DeviceListActivity查看设备并扫描IntentserverIntent=newIntent(this,DeviceListActivity.class);startActivityForResult(serverIntent,REQUEST_CONNECT_DEVICE);returntrue;caseR.id.discoverable:/确保设备处于可见状态ensureDiscoverable();returntrue;returnfalse; 装载菜单布局的时候使用了MenuInflater对象,整个过程很简单,大家可以参考上面的代码实现,在处理菜单事件的时候,通过item.getItemId()我们可以得到当前选择的菜单项的ID,首先是扫描设备(R.id.scan),这里我们有启动了另外一个Activity来专门处理扫描设备DeviceListActivity,如果扫描之后我们将通过startActivityForResult函数来请求链接该设备,同样我们也会在onActivityResult函数中收到一个反馈信息,命令代码为REQUEST_CONNECT_DEVICE,如果反馈的请求代码为Activity.RESULT_OK,则表示扫描成功(扫描过程我们稍后介绍),那么下面就可以开始准备链接了,实现代码如下:复制到剪贴板Java代码1. caseREQUEST_CONNECT_DEVICE:/当DeviceListActivity返回设备连接if(resultCode=Activity.RESULT_OK)/从Intent中得到设备的MAC地址Stringaddress=data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);/得到蓝牙设备对象BluetoothDevicedevice=mBluetoothAdapter.getRemoteDevice(address);/尝试连接这个设备mChatService.connect(device);break;首先我们可以通过DeviceListActivity.EXTRA_DEVICE_ADDRESS来取得设备的Mac地址,然后通过Mac地址使用蓝牙适配器mBluetoothAdapter的getRemoteDevice函数来查找到该地址的设备BluetoothDevice,查询到之后我们可以通过mChatService对象的connect来链接该设备。上面我们说的是扫描蓝牙设备并链接的过程,一般蓝牙设备在打开之后都需要设置可见状态,下面我们来看一下另一个菜单选项的实现,用于使设备处于可见状态,其菜单项的ID为R.id.discoverable,具体实现过程则位于ensureDiscoverable函数中,其实现如下代码:复制到剪贴板Java代码1. privatevoidensureDiscoverable()if(D)Log.d(TAG,ensurediscoverable);/判断扫描模式是否为既可被发现又可以被连接if(mBluetoothAdapter.getScanMode()!=BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE)/请求可见状态IntentdiscoverableIntent=newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);/添加附加属性,可见状态的时间discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);startActivity(discoverableIntent);这里首先通过mBluetoothAdapter.getScanMode()函数取得该蓝牙的扫描模式,然后通过BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE设置可见属性,在这里我们加入一个附加属性BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,用来设置可见状态的时间,表示在指定的时间中蓝牙处于可见状态,设置好之后通过startActivity来执行即可。这里忧一个需要注意的问题,在链接某个设备之前,我们需要开启一个端口监听,该应用程序将其放在onResume()函数中来处理了,代码如下:复制到剪贴板Java代码1. OverridepublicsynchronizedvoidonResume()super.onResume();if(D)Log.e(TAG,+ONRESUME+);/PerformingthischeckinonResume()coversthecaseinwhichBTwas/notenabledduringonStart(),sowewerepausedtoenableit./onResume()willbecalledwhenACTION_REQUEST_ENABLEactivityreturns.if(mChatService!=null)/如果当前状态为STATE_NONE,则需要开启蓝牙聊天服务if(mChatService.getState()=BluetoothChatService.STATE_NONE)/开始一个蓝牙聊天服务mChatService.start(); 首先检测mChatService是否被初始化,然后检测其状态是否为STATE_NONE,STATE_NONE表示初始化之后处于等待的状态,当我们在setupChat函数中初始时,其实就已经将其状态设置为STATE_NONE了(该操作是在BluetoothChatService的构造函数中处理的),所以这里就可以通过一个start函数来启动一个进程即可,实际上就是启动了一个端口监听进程,当有设备连接时,该监听进程结束,然后转向链接进程,链接之后同样又将转换到一个聊天管理进程。本文主要包括以下两个部分的内容:其一,分析扫描设备部分DeviceListActivity,其二,分析具体的聊天过程的完整通信方案,包括端口监听、链接配对、消息发送和接收等,如果有对上一篇文章不太熟悉的,可以返回去在过一次,这样会有利于本文的理解。设备扫描(DeviceListActivity)在上一篇文章的介绍中,当用户点击了扫描按钮之后,则会执行如下代码:复制到剪贴板Java代码1. /启动DeviceListActivity查看设备并扫描IntentserverIntent=newIntent(this,DeviceListActivity.class);startActivityForResult(serverIntent,REQUEST_CONNECT_DEVICE); 该代码将跳转到DeviceListActivity进行设备的扫描,并且通过REQUEST_CONNECT_DEVICE来请求链接扫描到的设备。从AndroidManifest.xml文件中我们知道DeviceListActivity将为定义为一个对话框的风格,下图是该应用程序中,扫描蓝牙设备的截图。其中DeviceListActivity则为图中对话框部分,其界面的布局如下代码所示。复制到剪贴板Java代码1. 该布局整体由一个线性布局LinearLayout组成,其中包含了两个textview中来显示已经配对的设备和信扫描出来的设备(还没有经过配对)和两个ListView分别用于显示已经配对和没有配对的设备的相关信息。按钮则用于执行扫描过程用,整个结构很简单,下面我们开始分析如何编码实现了。同样开始之前,我们先确定该类中的变量的作用,定义如下:复制到剪贴板Java代码1. publicclassDeviceListActivityextendsActivity/DebuggingprivatestaticfinalStringTAG=DeviceListActivity;privatestaticfinalbooleanD=true;/ReturnIntentextrapublicstaticStringEXTRA_DEVICE_ADDRESS=device_address;/蓝牙适配器privateBluetoothAdaptermBtAdapter;/已经配对的蓝牙设备privateArrayAdaptermPairedDevicesArrayAdapter;/新的蓝牙设备privateArrayAdaptermNewDevicesArrayAdapter; 其中Debugging部分,同样用于调试,这里定义了一个EXTRA_DEVICE_ADDRESS,用于在通过Intent传递数据时的附加信息,即设备的地址,当扫描出来之后,返回到BluetoothChat中的onActivityResult函数的REQUEST_CONNECT_DEVICE命令,这是我们就需要通过DeviceListActivity.EXTRA_DEVICE_ADDRESS来取得该设备的Mac地址,因此当我们扫描完成之后在反馈扫描结果时就需要绑定设备地址作为EXTRA_DEVICE_ADDRESS的附加值,这和我们上一篇介绍的并不矛盾。另外其他几个变量则分别是本地蓝牙适配器、已经配对的蓝牙列表和扫描出来还没有配对的蓝牙设备列表,稍后我们可以看到对他们的使用。进入DeviceListActivity之后我们首先分析onCreate,首先通过如下代码对窗口进行了设置:复制到剪贴板Java代码1. /设置窗口requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);setContentView(R.layout.device_list);setResult(Activity.RESULT_CANCELED); 这里我们设置了窗口需要带一个进度条,当我们在扫描时就看有很容易的高速用户扫描进度。具体布局则设置为device_list.xml也是我们文本第一段代码的内容,接下来首先初始化扫描按钮,代码如下:复制到剪贴板Java代码1. /初始化扫描按钮ButtonscanButton=(Button)findViewById(R.id.button_scan);scanButton.setOnClickListener(newOnClickListener()publicvoidonClick(Viewv)doDiscovery();v.setVisibility(View.GONE);); 首先取得按钮对象,然后为其设置一个事件监听,当事件触发时就通过doDiscovery函数来执行扫描操作即可,具体扫描过程稍后分析。然后需要初始化用来显示设备的列表和数据源,使用如下代码即可:复制到剪贴板Java代码1. /初始化ArrayAdapter,一个是已经配对的设备,一个是新发现的设备mPairedDevicesArrayAdapter=newArrayAdapter(this,R.layout.device_name);mNewDevicesArrayAdapter=newArrayAdapter(this,R.layout.device_name);/检测并设置已配对的设备ListViewListViewpairedListView=(ListView)findViewById(R.id.paired_devices);pairedListView.setAdapter(mPairedDevicesArrayAdapter);pairedListView.setOnItemClickListener(mDeviceClickListener);/检查并设置行发现的蓝牙设备ListViewListViewnewDevicesListView=(ListView)findViewById(R.id.new_devices);newDevicesListView.setAdapter(mNewDevicesArrayAdapter);newDevicesListView.setOnItemClickListe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论