位置: 编程技术 - 正文

1、BluetoothChat之BluetoothChat.java

编辑:rootadmin

推荐整理分享1、BluetoothChat之BluetoothChat.java,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

参考:

Activity 。

BluetoothChat:

主界面,

显示聊天信息BluetoothChatService:

里面有3个主要线程类:

AcceptThread:蓝牙服务端socket监听线程.。

ConnectThread:蓝牙socket连接线程。

ConnectedThread:连接后的通信线程DeviceListActivity:

蓝牙扫描选择界面,负责传回选择连接的设备BluetoothChat:

定义了很多常量,用于处理消息和请求:

1、BluetoothChat的成员变量

其中Debugging部分则将用于我们在调试程序时通过log打印日志用,其他部分我们都加入了注释,需要说明的是BluetoothChatService ,它是我们自己定义的一个用来管理蓝牙的端口监听,链接,管理聊天的程序,后面我们会介绍。在这里需要说明一点,这些代码都出自google的员工之手,大家在学习时,可以借鉴很多代码编写的技巧和风&#;,这都将对我们有非常大的帮助。

2、onCreate()1、main及自定义title布局&#;&#;

1、onCreate函数中对窗口进行了设置,窗口风&#;设置为自定义风&#;,并且指定了自定义title布局为custom_title.xml

[html] view plaincopy// Set up the window layout requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.main); getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);

1、该布局将title设置为一个相对布局RelativeLayout,其中包含了两个TextView,一个在左边一个在右边,分别用于显示应用程序的标题title和当前的蓝牙配对链接名称,如下图所示。

其中左边显示为应用程序名称"BluetoothChat",右边显示一个connected:scort,则表示当前配对成功正在进行聊天的链接名称

2、整个聊天界面的布局在main.xml中实现:采用一个线性布局LinearLayout,其中包含了另一个ListView(用于显示聊天的对话信息)和另外一个线性布局来实现一个发送信息的窗口,发送消息发送框有一个输入框和一个发送按钮构成。整个界面如下图所示。

2、设置自定义title布局

我们就需要对界面进行一些设置,如下代码将用来设置我们自定义的标题title需要显示的内容:

[html] view plaincopy1.// 设置自定义title布局 2.  mTitle = (TextView) findViewById(R.id.title_left_text); 3.  mTitle.setText(R.string.app_name); 4.  mTitle = (TextView) findViewById(R.id.title_right_text);

左边的TextView被设置为显示应用程序名称,右边的则需要我们在链接之后在设置更新,目前则显示没有链接字样,所以这里我们暂不设置

3、蓝牙适配器BluetoothAdapter

进一步就需要获取本地蓝牙适配器BluetoothAdapter了,因为对于有关蓝牙的任何操作都需要首先获得该蓝牙适配器,获取代码非常简单,如下

getDefaultAdapter()函数用于获取本地蓝牙适配器,然后检测是否为null,如果为null则表示没有蓝牙设备的支持,将通过toast告知用户。

onStart()

在onStart()函数中,我们将检测蓝牙是否被打开,如果没有打开,则请求打开,否则就可以设置一些聊天信息的准备工作,代码如下

3、控件

一个显示连接到某个设备的TextView,

一个用于显示对话的ListView,

一个用于输入聊天内容的EditText,

一个发送按钮Button

1、 在EditText注册一个监听器(另外)

实现了软键盘按回车return键发送消息(一般我们在EditText里按return键是换行)

[html] view plaincopy.// 用于监听EditText的一个return键事件 .private TextView.OnEditorActionListener mWriteListener = . new TextView.OnEditorActionListener() { . public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { . // If the action is a key-up event on the return key, send the message . if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) { . String message = view.getText().toString(); . sendMessage(message); . } . if(D) Log.i(TAG, "END onEditorAction"); . return true; . } .};

1、BluetoothChat之BluetoothChat.java

得到本地 BluetoothAdapter 设备,检查是否支持。

onStart() 中检查是否启用蓝牙,并请求启用,然后执行 setupChat() 。

setupChat() 中先对界面中的控件进行初始化增加点击监听器等,然创建 BluetoothChatService 对象,该对象在整个应用过程中存在,并执行蓝牙连接建立、消息发送接受等实际的行为。

首先,程序启动进入BluetoothChat,在onCreate函数中对窗口进行了设置,代码如下:

// 设置窗口布局   requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);   setContentView(R.layout.main);   getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title); [java] view plaincopy// 设置窗口布局   requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);   setContentView(R.layout.main);   getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);

  这里可以看到将窗口风&#;设置为自定义风&#;了,并且指定了自定义title布局为custom_title,其定义代码如下:

view plaincopy to clipboardprint?<RelativeLayout xmlns:android="   android:layout_width="match_parent"   android:layout_height="match_parent"   android:gravity="center_vertical"   >   <TextView android:id="@&#;id/title_left_text"   android:layout_alignParentLeft="true"   android:ellipsize="end"   android:singleLine="true"   style="?android:attr/windowTitleStyle"   android:layout_width="wrap_content"   android:layout_height="match_parent"   android:layout_weight="1"   />   <TextView android:id="@&#;id/title_right_text"   android:layout_alignParentRight="true"   android:ellipsize="end"   android:singleLine="true"   android:layout_width="wrap_content"   android:layout_height="match_parent"   android:textColor="#fff"   android:layout_weight="1"   />   </RelativeLayout> [java] view plaincopy<RelativeLayout xmlns:android="   android:layout_width="match_parent"   android:layout_height="match_parent"   android:gravity="center_vertical"   >   <TextView android:id="@&#;id/title_left_text"   android:layout_alignParentLeft="true"   android:ellipsize="end"   android:singleLine="true"   style="?android:attr/windowTitleStyle"   android:layout_width="wrap_content"   android:layout_height="match_parent"   android:layout_weight="1"   />   <TextView android:id="@&#;id/title_right_text"   android:layout_alignParentRight="true"   android:ellipsize="end"   android:singleLine="true"   android:layout_width="wrap_content"   android:layout_height="match_parent"   android:textColor="#fff"   android:layout_weight="1"   />   </RelativeLayout>

  该布局将title设置为一个相对布局RelativeLayout,其中包含了两个TextView,一个在左边一个在右边,分别用于显示应用程序的标题title和当前的蓝牙配对链接名称,如下图所示。

  其中左边显示为应用程序名称"BluetoothChat",右边显示一个connected:scort则表示当前配对成功正在进行聊天的链接名称。整个聊天界面的布局在main.xml中实现,代码如下:

view plaincopy to clipboardprint?<LinearLayout xmlns:android="   android:orientation="vertical"   android:layout_width="match_parent"   android:layout_height="match_parent"   >   <!-- 显示设备列表 -->   <ListView android:id="@&#;id/in"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:stackFromBottom="true"   android:transcriptMode="alwaysScroll"   android:layout_weight="1"   />   <!-- 显示发送消息的编辑框 -->   <LinearLayout   android:orientation="horizontal"   android:layout_width="match_parent"   android:layout_height="wrap_content"   >   <EditText android:id="@&#;id/edit_text_out"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:layout_weight="1"   android:layout_gravity="bottom"   />   <Button android:id="@&#;id/button_send"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:text="@string/send"   />   </LinearLayout>   </LinearLayout> [java] view plaincopy<LinearLayout xmlns:android="   android:orientation="vertical"   android:layout_width="match_parent"   android:layout_height="match_parent"   >   <!-- 显示设备列表 -->   <ListView android:id="@&#;id/in"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:stackFromBottom="true"   android:transcriptMode="alwaysScroll"   android:layout_weight="1"   />   <!-- 显示发送消息的编辑框 -->   <LinearLayout   android:orientation="horizontal"   android:layout_width="match_parent"   android:layout_height="wrap_content"   >   <EditText android:id="@&#;id/edit_text_out"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:layout_weight="1"   android:layout_gravity="bottom"   />   <Button android:id="@&#;id/button_send"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:text="@string/send"   />   </LinearLayout>   </LinearLayout>

  整个界面的布局将是一个线性布局LinearLayout,其中包含了另一个ListView(用于显示聊天的对话信息)和另外一个线性布局来实现一个发送信息的窗口,发送消息发送框有一个输入框和一个发送按钮构成。整个界面如下图所示。

  布局好界面,下面我们需要进入编码状态,首先看BluetoothChat所要那些成员变量,如下代码所示:

view plaincopy to clipboardprint?public class BluetoothChatextends Activity {   // Debugging   private static final String TAG ="BluetoothChat";   private staticfinalboolean D =true;   //从BluetoothChatService Handler发送的消息类型   public staticfinalint MESSAGE_STATE_CHANGE =1;   public staticfinalint MESSAGE_READ =2;   public staticfinalint MESSAGE_WRITE =3;   public staticfinalint MESSAGE_DEVICE_NAME =4;   public staticfinalint MESSAGE_TOAST =5;   // 从BluetoothChatService Handler接收消息时使用的键名(键-&#;模型)   public staticfinal String DEVICE_NAME ="device_name";   public staticfinal String TOAST ="toast";   // Intent请求代码(请求链接,请求可见)   private staticfinalint REQUEST_CONNECT_DEVICE =1;   private static finalint REQUEST_ENABLE_BT =2;   // Layout Views   private TextView mTitle;   private ListView mConversationView;   private EditText mOutEditText;   private Button mSendButton;   // 链接的设备的名称   private String mConnectedDeviceName =null;   // Array adapter for the conversation thread   private ArrayAdapter<String> mConversationArrayAdapter;   // 将要发送出去的字符串   private StringBuffer mOutStringBuffer;   // 本地蓝牙适配器   private BluetoothAdapter mBluetoothAdapter =null;   // 聊天服务的对象   private BluetoothChatService mChatService =null;   //...... [java] view plaincopypublic class BluetoothChat extends Activity {   // Debugging   private static final String TAG = "BluetoothChat";   private static final boolean D = true;   //从BluetoothChatService Handler发送的消息类型   public static final int MESSAGE_STATE_CHANGE = 1;   public static final int MESSAGE_READ = 2;   public static final int MESSAGE_WRITE = 3;   public static final int MESSAGE_DEVICE_NAME = 4;   public static final int MESSAGE_TOAST = 5;   // 从BluetoothChatService Handler接收消息时使用的键名(键-&#;模型)   public static final String DEVICE_NAME = "device_name";   public static final String TOAST = "toast";   // Intent请求代码(请求链接,请求可见)   private static final int REQUEST_CONNECT_DEVICE = 1;   private static final int REQUEST_ENABLE_BT = 2;   // Layout Views   private TextView mTitle;   private ListView mConversationView;   private EditText mOutEditText;   private Button mSendButton;   // 链接的设备的名称   private String mConnectedDeviceName = null;   // Array adapter for the conversation thread   private ArrayAdapter<String> mConversationArrayAdapter;   // 将要发送出去的字符串   private StringBuffer mOutStringBuffer;   // 本地蓝牙适配器   private BluetoothAdapter mBluetoothAdapter = null;   // 聊天服务的对象   private BluetoothChatService mChatService = null;   //......

  其中Debugging部分则将用于我们在调试程序时通过log打印日志用,其他部分我们都加入了注释,需要说明的是BluetoothChatService ,它是我们自己定义的一个用来管理蓝牙的端口监听,链接,管理聊天的程序,后面我们会介绍。在这里需要说明一点,这些代码都出自google的员工之手,大家在学习时,可以借鉴很多代码编写的技巧和风&#;,这都将对我们有非常大的帮助。  然后,我们就需要对界面进行一些设置,如下代码将用来设置我们自定义的标题title需要显示的内容:

view plaincopy to clipboardprint?// 设置自定义title布局   mTitle = (TextView) findViewById(R.id.title_left_text);   mTitle.setText(R.string.app_name);   mTitle = (TextView) findViewById(R.id.title_right_text); [java] view plaincopy// 设置自定义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了,因为对于有关蓝牙的任何操作都需要首先获得该蓝牙适配器,获取代码非常简单,如下:

view plaincopy to clipboardprint?// 得到一个本地蓝牙适配器   mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();   // 如果适配器为null,则不支持蓝牙   if (mBluetoothAdapter ==null) {   Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();   finish();   return;   }   getDefaultAdapter()函数用于获取本地蓝牙适配器,然后检测是否为null,如果为null则表示没有蓝牙设备的支持,将通过toast告知用户。   在onStart()函数中,我们将检测蓝牙是否被打开,如果没有打开,则请求打开,否则就可以设置一些聊天信息的准备工作,代码如下:   @Override   public void onStart() {   super.onStart();   if(D) Log.e(TAG,"&#;&#; ON START &#;&#;");   // 如果蓝牙没有打开,则请求打开   // setupChat() will then be called during onActivityResult   if (!mBluetoothAdapter.isEnabled()) {   Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);   startActivityForResult(enableIntent, REQUEST_ENABLE_BT);   // 否则,设置聊天会话   } else {   if (mChatService == null) setupChat();   }   } [java] view plaincopy// 得到一个本地蓝牙适配器   mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();   // 如果适配器为null,则不支持蓝牙   if (mBluetoothAdapter == null) {   Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();   finish();   return;   }   getDefaultAdapter()函数用于获取本地蓝牙适配器,然后检测是否为null,如果为null则表示没有蓝牙设备的支持,将通过toast告知用户。   在onStart()函数中,我们将检测蓝牙是否被打开,如果没有打开,则请求打开,否则就可以设置一些聊天信息的准备工作,代码如下:   @Override   public void onStart() {   super.onStart();   if(D) Log.e(TAG, "&#;&#; ON START &#;&#;");   // 如果蓝牙没有打开,则请求打开   // setupChat() will then be called during onActivityResult   if (!mBluetoothAdapter.isEnabled()) {   Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);   startActivityForResult(enableIntent, REQUEST_ENABLE_BT);   // 否则,设置聊天会话   } else {   if (mChatService == null) setupChat();   }   }

onStart()函数_检测蓝牙

  如果蓝牙没有打开,我们则通过BluetoothAdapter.ACTION_REQUEST_ENABLE来请求打开蓝牙,REQUEST_ENABLE_BT则是我们自己定义的用于请求打开蓝牙的Intent代码,最后当我们调用startActivityForResult来执行请求时,就会在onActivityResult函数中得到一个反馈,如果当前蓝牙已经打开,那么就可以调用setupChat函数来准备蓝牙聊天相关的工作,稍后分析该函数的具体实现。  下面我们分析一下请求打开蓝牙之后,在onActivityResult 中得到的反馈信息,我们传递了REQUEST_ENABLE_BT代码作为请求蓝牙打开的命令,因此在onActivityResult 中,需要会得到一个请求代码为REQUEST_ENABLE_B的消息,对于其处理如下代码所示:

view plaincopy to clipboardprint?case REQUEST_ENABLE_BT:   // 在请求打开蓝牙时返回的代码   if (resultCode == Activity.RESULT_OK) {   // 蓝牙已经打开,所以设置一个聊天会话   setupChat();   } else {   // 请求打开蓝牙出错   Log.d(TAG, "BT not enabled");   Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();   finish();   } [java] view plaincopycase REQUEST_ENABLE_BT:   // 在请求打开蓝牙时返回的代码   if (resultCode == Activity.RESULT_OK) {   // 蓝牙已经打开,所以设置一个聊天会话   setupChat();   } else {   // 请求打开蓝牙出错   Log.d(TAG, "BT not enabled");   Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();   finish();   }

  在请求时,如果返回代码为Activity.RESULT_OK,则表示请求打开蓝牙成功,那么我们就可以和上面的操作进度一样,调用setupChat来设置蓝牙聊天相关信息,如果返回其他代码,则表示请求打开蓝牙失败,这时我们同样通过一个Toast来告诉用户,同时也需要调用finish()函数来结束应用程序。  

setupChat设置

如果打开蓝牙无误,那么下面我们开始进入setupChat的设置,其代码实现如下:

view plaincopy to clipboardprint?private void setupChat() {   Log.d(TAG, "setupChat()");   // 初始化对话进程   mConversationArrayAdapter = new ArrayAdapter<String>(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(new OnClickListener() {   public void onClick(View v) {   // 取得TextView中的内容来发送消息   TextView view = (TextView) findViewById(R.id.edit_text_out);   String message = view.getText().toString();   sendMessage(message);   }   });   // 初始化BluetoothChatService并执行蓝牙连接   mChatService = new BluetoothChatService(this, mHandler);   // 初始化将要发出的消息的字符串   mOutStringBuffer = new StringBuffer("");   } [java] view plaincopyprivate void setupChat() {   Log.d(TAG, "setupChat()");   // 初始化对话进程   mConversationArrayAdapter = new ArrayAdapter<String>(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(new OnClickListener() {   public void onClick(View v) {   // 取得TextView中的内容来发送消息   TextView view = (TextView) findViewById(R.id.edit_text_out);   String message = view.getText().toString();   sendMessage(message);   }   });   // 初始化BluetoothChatService并执行蓝牙连接   mChatService = new BluetoothChatService(this, mHandler);   // 初始化将要发出的消息的字符串   mOutStringBuffer = new StringBuffer("");   }

  首先构建一个对话进程mConversationArrayAdapter,然后从xml中取得用于显示对话信息的列表mConversationView,最后将列表的数据来源Adapter设置为mConversationArrayAdapter,这里我们可以看到mConversationArrayAdapter所指定的资源为message.xml,其定义实现如下:

view plaincopy to clipboardprint?<TextView xmlns:android="   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:textSize="sp"   android:padding="5dp"   /> [java] view plaincopy<TextView xmlns:android="   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:textSize="sp"   android:padding="5dp"   />

  很简单,就包含了一个TextView用来显示对话内容即可,这里设置了文字标签的尺寸大小textSize和padding属性。  然后我们取得了编辑框mOutEditText,用于输入聊天内容的输入框,并对其设置了一个事件监听mWriteListener,其监听函数的实现如下:

view plaincopy to clipboardprint?// The action listener for the EditText widget, to listen for the return key   private TextView.OnEditorActionListener mWriteListener =   new TextView.OnEditorActionListener() {   public boolean onEditorAction(TextView view,int actionId, KeyEvent event) {   // 按下回车键并且是按键弹起的事件时发送消息   if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {   String message = view.getText().toString();   sendMessage(message);   }   if(D) Log.i(TAG, "END onEditorAction");   return true;   }   }; [java] view plaincopy// The action listener for the EditText widget, to listen for the return key   private TextView.OnEditorActionListener mWriteListener =   new TextView.OnEditorActionListener() {   public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {   // 按下回车键并且是按键弹起的事件时发送消息   if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {   String message = view.getText().toString();   sendMessage(message);   }   if(D) Log.i(TAG, "END onEditorAction");   return true;   }   };

  首先在其监听中实现了onEditorAction函数,我们通过判断其参数actionId来确定事件触发的动作,其中的"EditorInfo.IME_NULL"在Ophone中表示回车键消息,然后再加上KeyEvent.ACTION_UP,则表示当用户按下回车键并弹起时才触发消息的处理,处理过程也很简单,将输入框中内容取出到变量message中,然后调用sendMessage函数来发送一条消息,具体的发送细节,我们稍后分析。

setupChat函数_发送消息

  在setupChat函数中,我们还对发送消息的按钮进行的初始化,同样为其设置了事件监听(setOnClickListener),监听的内容则也是取得输入框中的信息,然后调用sendMessage函数来发送消息,和用户按回车键来发送消息一样。  最后一个重要的操作就是初始化了BluetoothChatService对象mChatService用来管理蓝牙的链接,聊天的操作,并且设置了其Handler对象mHandler来负责数据的交换和线程之间的通信。另外还准备了一个空的字符串对象mOutStringBuffer,用于当我们在发送消息之后,对输入框的清理。

应用菜单用option_menu.xml

  该应用程序除了这些界面的布局之外,我们还为其设置了一个菜单,菜单包括了"扫描设备"和"使设备可见(能够被其他设备所搜索到)",创建菜单的方式有很多种,这里gogole的员工,比较喜欢和推崇使用option_menu.xml布局(将界面和逻辑分开),所以我们首先看一下对于该应用程序通过xml所定义的菜单布局,代码如下:

view plaincopy to clipboardprint?<menu xmlns:android="    <!-- 扫描菜单 -->   <item android:id="@&#;id/scan"   android:icon="@android:drawable/ic_menu_search"   android:title="@string/connect" />   <!-- 可见操作 -->   <item android:id="@&#;id/discoverable"   android:icon="@android:drawable/ic_menu_mylocation"   android:title="@string/discoverable" />   </menu> [java] view plaincopy<menu xmlns:android="    <!-- 扫描菜单 -->   <item android:id="@&#;id/scan"   android:icon="@android:drawable/ic_menu_search"   android:title="@string/connect" />   <!-- 可见操作 -->   <item android:id="@&#;id/discoverable"   android:icon="@android:drawable/ic_menu_mylocation"   android:title="@string/discoverable" />   </menu>

onOptionsItemSelected函数、onCreateOptionsMenu函数_菜单的处理与装载

  这样的定义的确非常的清晰,我们可以随意向这个Menu中添加菜单选项(itme),这里就定义了上面我们所说的两个菜单。然后再程序中通过onCreateOptionsMenu函数中来装载该菜单布局,遂于菜单的点击可以通过onOptionsItemSelected函数的不同参数来辨别,下面是该应用程序中对菜单选项的处理和装载菜单布局:

view plaincopy to clipboardprint?//创建一个菜单   @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:   // 启动DeviceListActivity查看设备并扫描   Intent serverIntent = new Intent(this, DeviceListActivity.class);   startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);   return true;   case R.id.discoverable:   // 确保设备处于可见状态   ensureDiscoverable();   return true;   }   return false;   } [java] view plaincopy//创建一个菜单   @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:   // 启动DeviceListActivity查看设备并扫描   Intent serverIntent = new Intent(this, DeviceListActivity.class);   startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);   return true;   case R.id.discoverable:   // 确保设备处于可见状态   ensureDiscoverable();   return true;   }   return false;   }

  装载菜单布局的时候使用了MenuInflater对象,整个过程很简单,大家可以参考上面的代码实现,在处理菜单事件的时候,通过item.getItemId()我们可以得到当前选择的菜单项的ID,首先是扫描设备(R.id.scan),这里我们有启动了另外一个Activity来专门处理扫描设备DeviceListActivity,如果扫描之后我们将通过startActivityForResult函数来请求链接该设备,

onActivityResult函数_扫描反馈信息

同样我们也会在onActivityResult函数中收到一个反馈信息,命令代码为REQUEST_CONNECT_DEVICE,如果反馈的请求代码为Activity.RESULT_OK,则表示扫描成功(扫描过程我们稍后介绍),那么下面就可以开始准备链接了,实现代码如下:

view plaincopy to clipboardprint?case REQUEST_CONNECT_DEVICE:   // 当DeviceListActivity返回设备连接   if (resultCode == Activity.RESULT_OK) {   // 从Intent中得到设备的MAC地址   String address = data.getExtras()   .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);   // 得到蓝牙设备对象   BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);   // 尝试连接这个设备   mChatService.connect(device);   }   break; [java] view plaincopycase REQUEST_CONNECT_DEVICE:   // 当DeviceListActivity返回设备连接   if (resultCode == Activity.RESULT_OK) {   // 从Intent中得到设备的MAC地址   String address = data.getExtras()   .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);   // 得到蓝牙设备对象   BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);   // 尝试连接这个设备   mChatService.connect(device);   }   break;

  首先我们可以通过DeviceListActivity.EXTRA_DEVICE_ADDRESS来取得设备的Mac地址,然后通过Mac地址使用蓝牙适配器mBluetoothAdapter的getRemoteDevice函数来查找到该地址的设备BluetoothDevice,查询到之后我们可以通过mChatService对象的connect来链接该设备。

ensureDiscoverable函数_使设备处于可见状态

  上面我们说的是扫描蓝牙设备并链接的过程,一般蓝牙设备在打开之后都需要设置可见状态,下面我们来看一下另一个菜单选项的实现,用于使设备处于可见状态,其菜单项的ID为R.id.discoverable,具体实现过程则位于ensureDiscoverable函数中,其实现如下代码:

view plaincopy to clipboardprint?private void ensureDiscoverable() {   if(D) Log.d(TAG, "ensure discoverable");   //判断扫描模式是否为既可被发现又可以被连接   if (mBluetoothAdapter.getScanMode() !=   BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {    //请求可见状态   Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);   //添加附加属性,可见状态的时间   discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,);   startActivity(discoverableIntent);   }   } [java] view plaincopyprivate void ensureDiscoverable() {   if(D) Log.d(TAG, "ensure discoverable");   //判断扫描模式是否为既可被发现又可以被连接   if (mBluetoothAdapter.getScanMode() !=   BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {    //请求可见状态   Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);   //添加附加属性,可见状态的时间   discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, );   startActivity(discoverableIntent);   }   }

  这里首先通过mBluetoothAdapter.getScanMode()函数取得该蓝牙的扫描模式,然后通过BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE设置可见属性,在这里我们加入一个附加属性BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,用来设置可见状态的时间,表示在指定的时间中蓝牙处于可见状态,设置好之后通过startActivity来执行即可。

onResume()函数_端口监听

  这里忧一个需要注意的问题,在链接某个设备之前,我们需要开启一个端口监听,该应用程序将其放在onResume()函数中来处理了,代码如下:

view plaincopy to clipboardprint?@Override   public synchronizedvoid onResume() {   super.onResume();   if(D) Log.e(TAG, "&#; ON RESUME &#;");   // Performing this check in onResume() covers the case in which BT was   // not enabled during onStart(), so we were paused to enable it...   // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.   if (mChatService !=null) {   // 如果当前状态为STATE_NONE,则需要开启蓝牙聊天服务   if (mChatService.getState() == BluetoothChatService.STATE_NONE) {   // 开始一个蓝牙聊天服务   mChatService.start();   }   }   } [java] view plaincopy@Override   public synchronized void onResume() {   super.onResume();   if(D) Log.e(TAG, "&#; ON RESUME &#;");   // Performing this check in onResume() covers the case in which BT was   // not enabled during onStart(), so we were paused to enable it...   // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.   if (mChatService != null) {   // 如果当前状态为STATE_NONE,则需要开启蓝牙聊天服务   if (mChatService.getState() == BluetoothChatService.STATE_NONE) {   // 开始一个蓝牙聊天服务   mChatService.start();   }   }   }

  首先检测mChatService是否被初始化,然后检测其状态是否为STATE_NONE,STATE_NONE表示初始化之后处于等待的状态,当我们在setupChat函数中初始时,其实就已经将其状态设置为STATE_NONE了(该操作是在BluetoothChatService的构造函数中处理的),所以这里就可以通过一个start函数来启动一个进程即可,实际上就是启动了一个端口监听进程,当有设备连接时,该监听进程结束,然后转向链接进程,链接之后同样又将转换到一个聊天管理进程,对于这些链接过程和通信模块看来只有下一篇文章介绍了.

  总结  本文试图完成一个蓝牙聊天程序的分析和实现,但是我发现只要涉及网络通信模块的程序分析过程都比较复杂,可能是因为分析太细的原因,并没有分析完该程序,因此,下一篇文章我们继续分析,同时下一篇要介绍的也是最核心的内容,网络通信过程,希望能得到大家的支持。!

2、BluetoothChat之扫描设备DeviceListActivity.java 参考引用:

3、BluetoothChat之BluetoothChatService.java 参考:

关于 update ADT plug-in 的错误 关于updateADTplug-in的错误0EclipsereportsrenderinglibrarymorerecentthanADTplug-in.PleaseupdateADTplug-inOnanewAndroidSDKinstallation,theEclipseGraphicalLayoutisblank,ratherthanshowingtherendering

标签: 1、BluetoothChat之BluetoothChat.java

本文链接地址:https://www.jiuchutong.com/biancheng/385110.html 转载请保留说明!

上一篇:android studio 安装教程——基于1.2.1.1(androidstudio安装gradle不成功)

下一篇:2、BluetoothChat之扫描设备DeviceListActivity.java

  • 金融保险业税目
  • 小汽车折旧年限的最新规定2023
  • 个税返还款要交增值税吗
  • 年末未分配利润怎么处理
  • 投资款算什么会计科目
  • 空调属于电子设备还是电气设备
  • 发票没作废写上作废了怎么办
  • 非居民企业股权转让所得税
  • 工伤医疗费用个人社保卡支付找谁报销
  • 英国租金收入所得税
  • 退休工资缴纳个人所得税税率表
  • 价税合计是什么会计科目
  • 建筑行业增值税税率是多少
  • 国家税务总局13号文
  • 业务招待费怎么调整应纳税所得额
  • 已确认为坏账的应收账款,并不意味着企业放弃了
  • 拿回费用票普票忘记入账怎么办?
  • win10更新补丁怎么关闭
  • 企业纳税申报的流程
  • 疫情期间企业贷款利率多少
  • 如何在 Windows 11 上打开 APK 文件
  • php字符串函数有哪些
  • 不征税收入有哪些条件
  • PHP:Memcached::decrementByKey()的用法_Memcached类
  • PHP:curl_multi_info_read()的用法_cURL函数
  • PHP:class_implements()的用法_spl函数
  • 离职补偿金如何缴纳个人所得税?
  • ipcservice.dll是什么?
  • php教程100
  • php提供了________和___________两种复合数据类型
  • 广告费用属于损失吗
  • 大沙丘上的日落图片
  • 债务重组收益的计算
  • 总部资产减值测试例题
  • linux用mv文件移动指定文件
  • js工厂模式创建对象
  • 非公司员工可以举报公司不交社保吗
  • 企业应收是什么意思
  • 待核销基建支出并入哪个科目
  • 企业所得税汇算清缴扣除标准2023
  • 加计抵减四项服务是什么?
  • 公司名下的车怎么交税
  • 计提年终奖的会计分录
  • 支付工程款的会计科目怎么写
  • 将自产产品用于建造厂房
  • 进口税 增值税
  • 递延所得税资产和负债怎么计算
  • 会计六大类会计科目
  • mysql恢复备份文件
  • 以公允价值计量计入其他综合收益
  • 固定资产后续计量包括哪些内容
  • 印花税记入哪个费用
  • 企业征收所得税会计分录
  • 商业地产收税
  • 疫情防控重点保障物资生产企业可以按月
  • 邮寄快递费用计算
  • 小规模纳税人增值税专用发票税率
  • 河道工程修建维护管理费何时开始停征?
  • 出资注意事项有哪些内容
  • 委托加工物资贷方
  • 资产负债表中负债的排列依据是
  • 总公司是一般纳税人分公司是什么
  • ubuntu怎样
  • 联想lenovo thinkpad c13 yoga
  • putty怎么连接linux
  • dllhost应用程序异常
  • win7装win8系统教程
  • androidtime
  • flash 3 utility
  • bootstrap基础教程
  • jquery生成div
  • 控制程序的先后顺序是怎样的
  • js创建对象的三种方式
  • 从零开始学什么好
  • [置顶]bilinovel
  • python微信公众号开发教程
  • js数组entries
  • python文件与异常答案
  • 3.5车船税2400还是3000
  • 怎样在网上申报税务流程
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设