zoukankan      html  css  js  c++  java
  • android自带蓝牙例子详解

    相关参考网站:http://wenku.baidu.com/view/d901cc2d4b73f242336c5f87.html

                      

    http://wenku.baidu.com/view/518414b069dc5022aaea007b.html?from=rec&pos=2&weight=167&lastweight=111&count=5

    http://wenku.baidu.com/view/dec9bddd5022aaea998f0f7f.html

    测试蓝牙程序需要至少2个真机,然而Android 2.0以后才真正支持蓝牙设备编程。为了给这一讲配图,我要先去把HTC G4 刷一下机,经过2天的折腾,终于把G4刷到Android 2.2版本了…… 开始写本讲……

    image

    蓝牙是一种设备短距离无线通信技术,使用蓝牙你可以搜索并连接到附近的蓝牙设备,可以在两个已经进行过配对的蓝牙设备之间进行数据传输。

    本讲我们先使用Android SDK自带的例子蓝牙聊天程序BluetoothChat来做演示。源代码具体位置\android-sdk-windows\samples\android-8\BluetoothChat目录下。然后再自己实现一边这个蓝牙聊天程序。

    一、SDK自带例子,BluetoothChat 的运行演示

    这一次我们先看一下运行效果:准备两个真机 Milestone 和 HTC G4 Tattoo,分别安装好Bluetooth程序,
    先在 Milestone上点击 BluetoothChat 运行程序,

    image

    提示需要蓝牙使用权限

    image

    选择是,打开蓝牙,进入聊天界面,只是此时还未连接任何蓝牙设备。在HTC G4上进行同样的操作,也进入not connected 状态。

    image

    点击Menu按钮呼出菜单

    image

    点击 Make discoverable 菜单使,并在弹出的权限请求对话框中选择是,使手机可以被其它蓝牙设备发现,G4也做同样操作

    image

    然后选择connect a device,在弹出的对话框中选择 Scan for devices 查找设备,会发现 HTC Tattoo 设备

    image

    image

    image

    image

    全部选择匹配,然后就连接成功了。

    image

    image

    这样就可以聊天了……

    MainFest xml

    Xhtml代码 复制代码
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <!-- Copyright (C) 2009 The Android Open Source Project   
    3.      Licensed under the Apache License, Version 2.0 (the "License");   
    4.      you may not use this file except in compliance with the License.   
    5.      You may obtain a copy of the License at   
    6.           http://www.apache.org/licenses/LICENSE-2.0   
    7.      Unless required by applicable law or agreed to in writing, software   
    8.      distributed under the License is distributed on an "AS IS" BASIS,   
    9.      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   
    10.      See the License for the specific language governing permissions and   
    11.      limitations under the License.   
    12. -->  
    13. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    14.       package="com.example.android.BluetoothChat"  
    15.       android:versionCode="1"  
    16.       android:versionName="1.0">  
    17.     <uses-sdk minSdkVersion="6" />  
    18.     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />  
    19.     <uses-permission android:name="android.permission.BLUETOOTH" />  
    20.     <!-- 获取权限BlueTooth-->  
    21.     <application android:label="@string/app_name"  
    22.                  android:icon="@drawable/app_icon" >  
    23.         <activity android:name=".BluetoothChat"  
    24.                   android:label="@string/app_name"  
    25.                   android:configChanges="orientation|keyboardHidden">  
    26.             <intent-filter>  
    27.                 <action android:name="android.intent.action.MAIN" />  
    28.                 <category android:name="android.intent.category.LAUNCHER" />  
    29.             </intent-filter>  
    30.         </activity>  
    31.         <activity android:name=".DeviceListActivity"  
    32.                   android:label="@string/select_device"  
    33.                   android:theme="@android:style/Theme.Dialog"                 
    34.                   android:configChanges="orientation|keyboardHidden" />  
    35.                       <!-- android:theme="@android:style/Theme.Dialog" 设置界面主题:弹出框主题 -->  
    36.     </application>  
    37. </manifest>  

    Java代码 复制代码
    1. /*  
    2.  * Copyright (C) 2009 The Android Open Source Project  
    3.  *  
    4.  * Licensed under the Apache License, Version 2.0 (the "License");  
    5.  * you may not use this file except in compliance with the License.  
    6.  * You may obtain a copy of the License at  
    7.  *  
    8.  *      http://www.apache.org/licenses/LICENSE-2.0  
    9.  *  
    10.  * Unless required by applicable law or agreed to in writing, software  
    11.  * distributed under the License is distributed on an "AS IS" BASIS,  
    12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
    13.  * See the License for the specific language governing permissions and  
    14.  * limitations under the License.  
    15.  */  
    16. package com.example.android.BluetoothChat;   
    17. import android.app.Activity;   
    18. import android.bluetooth.BluetoothAdapter;   
    19. import android.bluetooth.BluetoothDevice;   
    20. import android.content.Intent;   
    21. import android.os.Bundle;   
    22. import android.os.Handler;   
    23. import android.os.Message;   
    24. import android.util.Log;   
    25. import android.view.KeyEvent;   
    26. import android.view.Menu;   
    27. import android.view.MenuInflater;   
    28. import android.view.MenuItem;   
    29. import android.view.View;   
    30. import android.view.Window;   
    31. import android.view.View.OnClickListener;   
    32. import android.view.inputmethod.EditorInfo;   
    33. import android.widget.ArrayAdapter;   
    34. import android.widget.Button;   
    35. import android.widget.EditText;   
    36. import android.widget.ListView;   
    37. import android.widget.TextView;   
    38. import android.widget.Toast;   
    39. /**  
    40.  * This is the main Activity that displays the current chat session.  
    41.  */  
    42. public class BluetoothChat extends Activity {   
    43.     // Debugging   
    44.     private static final String TAG = "BluetoothChat";   
    45.     private static final boolean D = true;   
    46.     // Message types sent from the BluetoothChatService Handler   
    47.     public static final int MESSAGE_STATE_CHANGE = 1;   
    48.     public static final int MESSAGE_READ = 2;   
    49.     public static final int MESSAGE_WRITE = 3;   
    50.     public static final int MESSAGE_DEVICE_NAME = 4;   
    51.     public static final int MESSAGE_TOAST = 5;   
    52.     // Key names received from the BluetoothChatService Handler   
    53.     public static final String DEVICE_NAME = "device_name";   
    54.     public static final String TOAST = "toast";   
    55.     // Intent request codes   
    56.     private static final int REQUEST_CONNECT_DEVICE = 1;   
    57.     private static final int REQUEST_ENABLE_BT = 2;   
    58.     // Layout Views   
    59.     private TextView mTitle;   
    60.     private ListView mConversationView;   
    61.     private EditText mOutEditText;   
    62.     private Button mSendButton;   
    63.     // Name of the connected device   
    64.     private String mConnectedDeviceName = null;   
    65.     // Array adapter for the conversation thread   
    66.     private ArrayAdapter<String> mConversationArrayAdapter;   
    67.     // String buffer for outgoing messages   
    68.     private StringBuffer mOutStringBuffer;   
    69.     // Local Bluetooth adapter   
    70.     private BluetoothAdapter mBluetoothAdapter = null;   
    71.     // Member object for the chat services   
    72.     private BluetoothChatService mChatService = null;   
    73.   
    74.     @Override  
    75.     public void onCreate(Bundle savedInstanceState) {   
    76.         super.onCreate(savedInstanceState);   
    77.         if(D) Log.e(TAG, "+++ ON CREATE +++");   
    78.         // Set up the window layout 设置Activity的标题栏格式Window.FEATURE_CUSTOM_TITLE普通、Window.FEATURE_NO_TITLE无标题栏、Window.FEATURE_INDETERMINATE_PROGRESS进度条   
    79.         requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);   
    80.         setContentView(R.layout.main);   
    81.         //设置标题栏的布局资源   
    82.         getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);   
    83.            
    84.         // Set up the custom title   
    85.         mTitle = (TextView) findViewById(R.id.title_left_text);   
    86.         mTitle.setText(R.string.app_name);   
    87.         mTitle = (TextView) findViewById(R.id.title_right_text);   
    88.         // Get local Bluetooth adapter   
    89.        //从根本上讲,这是你的出发点,所有的蓝牙行动。一旦你的本地适配器,getBondedDevices()所有配对设备对象设置;   
    90.         //与startDiscovery()启动设备可被发现,或建立一个BluetoothServerSocket监听与listenUsingRfcommWithServiceRecord(字符串,UUID的)传入的连接请求。   
    91.         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();   
    92.         // If the adapter is null, then Bluetooth is not supported   
    93.         if (mBluetoothAdapter == null) {   
    94.             Toast.makeText(this"Bluetooth is not available", Toast.LENGTH_LONG).show();   
    95.             finish();   
    96.             return;   
    97.         }   
    98.     }   
    99.     @Override  
    100.     public void onStart() {   
    101.         super.onStart();   
    102.         if(D) Log.e(TAG, "++ ON START ++");   
    103.         // If BT is not on, request that it be enabled.   
    104.         // setupChat() will then be called during onActivityResult   
    105.         //判断蓝牙是否开启,否则请求开启   
    106.         if (!mBluetoothAdapter.isEnabled()) {   
    107.             Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);   
    108.             startActivityForResult(enableIntent, REQUEST_ENABLE_BT);   
    109.         // Otherwise, setup the chat session   
    110.         } else {   
    111.             if (mChatService == null) setupChat();   
    112.         }   
    113.     }   
    114.     @Override  
    115.     public synchronized void onResume() {   
    116.         super.onResume();   
    117.         if(D) Log.e(TAG, "+ ON RESUME +");   
    118.         // Performing this check in onResume() covers the case in which BT was   
    119.         // not enabled during onStart(), so we were paused to enable it...   
    120.         // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.   
    121.         if (mChatService != null) {   
    122.             // Only if the state is STATE_NONE, do we know that we haven't started already   
    123.             if (mChatService.getState() == BluetoothChatService.STATE_NONE) { //STATE_NONE及刚创建为启动状态,如果是从后台切换到前台应为STATE_LISTEN,无需再次启动   
    124.               // Start the Bluetooth chat services    
    125.               mChatService.start();   
    126.             }   
    127.         }   
    128.     }   
    129.     private void setupChat() {   
    130.         Log.d(TAG, "setupChat()");   
    131.         // Initialize the array adapter for the conversation thread    
    132.         mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);   
    133.         mConversationView = (ListView) findViewById(R.id.in);   
    134.         mConversationView.setAdapter(mConversationArrayAdapter);   
    135.         // Initialize the compose field with a listener for the return key   
    136.         mOutEditText = (EditText) findViewById(R.id.edit_text_out);   
    137.         mOutEditText.setOnEditorActionListener(mWriteListener);////注册编辑状态监听   
    138.         // Initialize the send button with a listener that for click events   
    139.         mSendButton = (Button) findViewById(R.id.button_send);   
    140.         mSendButton.setOnClickListener(new OnClickListener() {   
    141.             public void onClick(View v) {   
    142.                 // Send a message using content of the edit text widget   
    143.                 TextView view = (TextView) findViewById(R.id.edit_text_out);   
    144.                 String message = view.getText().toString();   
    145.                 sendMessage(message); //点击发送则向蓝牙发送消息   
    146.             }   
    147.         });   
    148.         // Initialize the BluetoothChatService to perform bluetooth connections   
    149.         mChatService = new BluetoothChatService(this, mHandler);   
    150.         // Initialize the buffer for outgoing messages   
    151.         mOutStringBuffer = new StringBuffer("");   
    152.     }   
    153.     @Override  
    154.     public synchronized void onPause() {   
    155.         super.onPause();   
    156.         if(D) Log.e(TAG, "- ON PAUSE -");   
    157.     }   
    158.     @Override  
    159.     public void onStop() {   
    160.         super.onStop();   
    161.         if(D) Log.e(TAG, "-- ON STOP --");   
    162.     }   
    163.     @Override  
    164.     public void onDestroy() {   
    165.         super.onDestroy();   
    166.         // Stop the Bluetooth chat services   
    167.         if (mChatService != null) mChatService.stop(); //UI关闭时,蓝牙服务应也停止   
    168.         if(D) Log.e(TAG, "--- ON DESTROY ---");   
    169.     }   
    170.     private void ensureDiscoverable() {   
    171.         if(D) Log.d(TAG, "ensure discoverable");   
    172.         if (mBluetoothAdapter.getScanMode() !=   
    173.             BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { //如果蓝牙状态为不可被发现则请求开启为可被发现,时间300秒内   
    174.             Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);   
    175.             discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);   
    176.             startActivity(discoverableIntent);   
    177.         }   
    178.     }   
    179.     /**  
    180.      * Sends a message.  
    181.      * @param message  A string of text to send.  
    182.      */  
    183.     private void sendMessage(String message) {   
    184.         // Check that we're actually connected before trying anything   
    185.         if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {   
    186.             Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();   
    187.             return;   
    188.         }   
    189.         // Check that there's actually something to send   
    190.         if (message.length() > 0) {   
    191.             // Get the message bytes and tell the BluetoothChatService to write   
    192.             byte[] send = message.getBytes();   
    193.             mChatService.write(send);   
    194.             // Reset out string buffer to zero and clear the edit text field   
    195.             mOutStringBuffer.setLength(0); //mOutStringBuffer 一直未使用,何意?   
    196.             mOutEditText.setText(mOutStringBuffer);//清空编辑框 窃以为使用mOutEditText.setText("");即可   
    197.         }   
    198.     }   
    199.     // The action listener for the EditText widget, to listen for the return key   
    200.     private TextView.OnEditorActionListener mWriteListener =   
    201.         new TextView.OnEditorActionListener() {   
    202.         public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {   
    203.             // If the action is a key-up event on the return key, send the message    
    204.             //经测试应为点击回车键后放开时发送消息   
    205.             if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {   
    206.                 String message = view.getText().toString();   
    207.                 sendMessage(message);   
    208.             }   
    209.             if(D) Log.i(TAG, "END onEditorAction");   
    210.             return true;   
    211.         }   
    212.     };   
    213.     // The Handler that gets information back from the BluetoothChatService   
    214.     //更新标题栏右边状态和读写状态的Handler   
    215.     private final Handler mHandler = new Handler() {   
    216.         @Override  
    217.         public void handleMessage(Message msg) {   
    218.             switch (msg.what) {   
    219.             case MESSAGE_STATE_CHANGE:   
    220.                 if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);   
    221.                 switch (msg.arg1) {   
    222.                 case BluetoothChatService.STATE_CONNECTED:   
    223.                     mTitle.setText(R.string.title_connected_to);   
    224.                     mTitle.append(mConnectedDeviceName);   
    225.                     mConversationArrayAdapter.clear(); //清空消息   
    226.                     break;   
    227.                 case BluetoothChatService.STATE_CONNECTING:   
    228.                     mTitle.setText(R.string.title_connecting);   
    229.                     break;   
    230.                 case BluetoothChatService.STATE_LISTEN:   
    231.                 case BluetoothChatService.STATE_NONE:   
    232.                     mTitle.setText(R.string.title_not_connected);   
    233.                     break;   
    234.                 }   
    235.                 break;   
    236.             case MESSAGE_WRITE:   
    237.                 byte[] writeBuf = (byte[]) msg.obj;   
    238.                 // construct a string from the buffer   
    239.                 String writeMessage = new String(writeBuf);   
    240.                 mConversationArrayAdapter.add("Me:  " + writeMessage);   
    241.                 break;   
    242.             case MESSAGE_READ:   
    243.                 byte[] readBuf = (byte[]) msg.obj;   
    244.                 // construct a string from the valid bytes in the buffer   
    245.                 String readMessage = new String(readBuf, 0, msg.arg1);   
    246.                 mConversationArrayAdapter.add(mConnectedDeviceName+":  " + readMessage);   
    247.                 break;   
    248.             case MESSAGE_DEVICE_NAME:   
    249.                 // save the connected device's name   
    250.                 mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);   
    251.                 Toast.makeText(getApplicationContext(), "Connected to "  
    252.                                + mConnectedDeviceName, Toast.LENGTH_SHORT).show();   
    253.                 break;   
    254.             case MESSAGE_TOAST:   
    255.                 Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),   
    256.                                Toast.LENGTH_SHORT).show();   
    257.                 break;   
    258.             }   
    259.         }   
    260.     };   
    261.     public void onActivityResult(int requestCode, int resultCode, Intent data) {   
    262.         if(D) Log.d(TAG, "onActivityResult " + resultCode);   
    263.         switch (requestCode) {   
    264.         case REQUEST_CONNECT_DEVICE:   
    265.             // When DeviceListActivity returns with a device to connect   
    266.             if (resultCode == Activity.RESULT_OK) {   
    267.                 // Get the device MAC address   
    268.                 String address = data.getExtras()   
    269.                                      .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);   
    270.                 // Get the BLuetoothDevice object   
    271.                 if(address==null){   
    272.                     break;   
    273.                 }   
    274.                 //获取设备进行连接   
    275.                 BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);   
    276.                 // Attempt to connect to the device   
    277.                 mChatService.connect(device);   
    278.             }   
    279.             break;   
    280.         case REQUEST_ENABLE_BT:   
    281.             // When the request to enable Bluetooth returns   
    282.             if (resultCode == Activity.RESULT_OK) {   
    283.                 // Bluetooth is now enabled, so set up a chat session   
    284.                 //蓝牙开启成功,则继续初始化UI   
    285.                 setupChat();   
    286.             } else {   
    287.                 // User did not enable Bluetooth or an error occured   
    288.                 Log.d(TAG, "BT not enabled");   
    289.                 Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();   
    290.                 finish();   
    291.             }   
    292.         }   
    293.     }   
    294.     @Override  
    295.     public boolean onCreateOptionsMenu(Menu menu) {   
    296.         //从Menu资源中初始化Menu 返回true则弹出默认menu,false则不弹出Menu,须自定义   
    297.         MenuInflater inflater = getMenuInflater();   
    298.         inflater.inflate(R.menu.option_menu, menu);   
    299.         return true;    
    300.     }   
    301.     @Override  
    302.     public boolean onOptionsItemSelected(MenuItem item) {   
    303.         switch (item.getItemId()) {   
    304.         case R.id.scan:   
    305.             // Launch the DeviceListActivity to see devices and do scan   
    306.             //启动DeviceListActivity,并等待返回   
    307.             Intent serverIntent = new Intent(this, DeviceListActivity.class);   
    308.             startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);   
    309.             return true;   
    310.         case R.id.discoverable:   
    311.             // Ensure this device is discoverable by others   
    312.             ensureDiscoverable();   
    313.             return true;   
    314.         }   
    315.         return false;   
    316.     }   
    317. }  

    Java代码 复制代码
    1. /*  
    2.  * Copyright (C) 2009 The Android Open Source Project  
    3.  *  
    4.  * Licensed under the Apache License, Version 2.0 (the "License");  
    5.  * you may not use this file except in compliance with the License.  
    6.  * You may obtain a copy of the License at  
    7.  *  
    8.  *      http://www.apache.org/licenses/LICENSE-2.0  
    9.  *  
    10.  * Unless required by applicable law or agreed to in writing, software  
    11.  * distributed under the License is distributed on an "AS IS" BASIS,  
    12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
    13.  * See the License for the specific language governing permissions and  
    14.  * limitations under the License.  
    15.  */  
    16. package com.example.android.BluetoothChat;   
    17. import java.util.Set;   
    18. import android.app.Activity;   
    19. import android.bluetooth.BluetoothAdapter;   
    20. import android.bluetooth.BluetoothDevice;   
    21. import android.content.BroadcastReceiver;   
    22. import android.content.Context;   
    23. import android.content.Intent;   
    24. import android.content.IntentFilter;   
    25. import android.os.Bundle;   
    26. import android.util.Log;   
    27. import android.view.View;   
    28. import android.view.Window;   
    29. import android.view.View.OnClickListener;   
    30. import android.widget.AdapterView;   
    31. import android.widget.ArrayAdapter;   
    32. import android.widget.Button;   
    33. import android.widget.ListView;   
    34. import android.widget.TextView;   
    35. import android.widget.AdapterView.OnItemClickListener;   
    36. /**  
    37.  * This Activity appears as a dialog. It lists any paired devices and  
    38.  * devices detected in the area after discovery. When a device is chosen  
    39.  * by the user, the MAC address of the device is sent back to the parent  
    40.  * Activity in the result Intent.  
    41.  */  
    42. public class DeviceListActivity extends Activity {   
    43.     // Debugging   
    44.     private static final String TAG = "DeviceListActivity";   
    45.     private static final boolean D = true;   
    46.     // Return Intent extra   
    47.     public static String EXTRA_DEVICE_ADDRESS = "device_address";   
    48.     // Member fields   
    49.     private BluetoothAdapter mBtAdapter;   
    50.     private ArrayAdapter<String> mPairedDevicesArrayAdapter;   
    51.     private ArrayAdapter<String> mNewDevicesArrayAdapter;   
    52.     @Override  
    53.     protected void onCreate(Bundle savedInstanceState) {   
    54.         super.onCreate(savedInstanceState);   
    55.         // Setup the window   
    56.         requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);   
    57.         setContentView(R.layout.device_list);   
    58.         // Set result CANCELED incase the user backs out   
    59.         //先设置为Canceled 防止点击回退键时BluetoothChat认为是Result_OK状态   
    60.         setResult(Activity.RESULT_CANCELED);   
    61.         // Initialize the button to perform device discovery   
    62.         Button scanButton = (Button) findViewById(R.id.button_scan);   
    63.         scanButton.setOnClickListener(new OnClickListener() {   
    64.             public void onClick(View v) {   
    65.                 doDiscovery();   
    66.                 v.setVisibility(View.GONE);   
    67.             }   
    68.         });   
    69.         // Initialize array adapters. One for already paired devices and   
    70.         // one for newly discovered devices   
    71.         mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);   
    72.         mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);   
    73.         // Find and set up the ListView for paired devices   
    74.         ListView pairedListView = (ListView) findViewById(R.id.paired_devices);   
    75.         pairedListView.setAdapter(mPairedDevicesArrayAdapter);   
    76.         pairedListView.setOnItemClickListener(mDeviceClickListener);   
    77.         // Find and set up the ListView for newly discovered devices   
    78.         ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);   
    79.         newDevicesListView.setAdapter(mNewDevicesArrayAdapter);   
    80.         newDevicesListView.setOnItemClickListener(mDeviceClickListener);   
    81.         // Register for broadcasts when a device is discovered 发现设备时监听过滤   
    82.         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);   
    83.         this.registerReceiver(mReceiver, filter);   
    84.         // Register for broadcasts when discovery has finished发现设备程序运行结束时监听过滤   
    85.         filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);   
    86.         this.registerReceiver(mReceiver, filter);   
    87.         // Get the local Bluetooth adapter   
    88.         mBtAdapter = BluetoothAdapter.getDefaultAdapter();   
    89.         // Get a set of currently paired devices 获取当前已经互联过的设备   
    90.         Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();   
    91.         // If there are paired devices, add each one to the ArrayAdapter   
    92.         if (pairedDevices.size() > 0) {   
    93.             findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);    
    94.             for (BluetoothDevice device : pairedDevices) {   
    95.                 mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());   
    96.             }   
    97.         } else {   
    98.             String noDevices = getResources().getText(R.string.none_paired).toString();   
    99.             mPairedDevicesArrayAdapter.add(noDevices);   
    100.         }   
    101.     }   
    102.     @Override  
    103.     protected void onDestroy() {   
    104.         super.onDestroy();   
    105.         // Make sure we're not doing discovery anymore   
    106.         if (mBtAdapter != null) {   
    107.             mBtAdapter.cancelDiscovery(); //BluetoothAdapter 不受UI管理受系统管理,所以要即使cancelDiscovery   
    108.         }   
    109.         // Unregister broadcast listeners   
    110.         this.unregisterReceiver(mReceiver); //取消监听当UI销毁时   
    111.     }   
    112.     /**  
    113.      * Start device discover with the BluetoothAdapter  
    114.      */  
    115.     private void doDiscovery() {   
    116.         if (D) Log.d(TAG, "doDiscovery()");   
    117.         // Indicate scanning in the title 设置标题加载loading条可见   
    118.         setProgressBarIndeterminateVisibility(true);    
    119.         setTitle(R.string.scanning); //设置标题   
    120.         // Turn on sub-title for new devices   
    121.         findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);   
    122.         // If we're already discovering, stop it   
    123.         if (mBtAdapter.isDiscovering()) {   
    124.             mBtAdapter.cancelDiscovery();    
    125.         }   
    126.         // Request discover from BluetoothAdapter   
    127.         mBtAdapter.startDiscovery();   
    128.     }   
    129.     // The on-click listener for all devices in the ListViews 点击蓝牙列表的监听   
    130.     private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {   
    131.         public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {   
    132.             // Cancel discovery because it's costly and we're about to connect   
    133.             mBtAdapter.cancelDiscovery();    
    134.             // Get the device MAC address, which is the last 17 chars in the View IP地址17位   
    135.             String info = ((TextView) v).getText().toString();   
    136.             String address = info.substring(info.length() - 17);   
    137.             // Create the result Intent and include the MAC address   
    138.             Intent intent = new Intent();   
    139.             intent.putExtra(EXTRA_DEVICE_ADDRESS, address);   
    140.             // Set result and finish this Activity   
    141.             setResult(Activity.RESULT_OK, intent);   
    142.             finish();   
    143.         }   
    144.     };   
    145.     // The BroadcastReceiver that listens for discovered devices and   
    146.     // changes the title when discovery is finished   
    147.     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {   
    148.         @Override  
    149.         public void onReceive(Context context, Intent intent) {   
    150.             String action = intent.getAction();   
    151.             // When discovery finds a device 搜索到设备   
    152.             if (BluetoothDevice.ACTION_FOUND.equals(action)) {   
    153.                 // Get the BluetoothDevice object from the Intent   
    154.                 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);   
    155.                 // If it's already paired, skip it, because it's been listed already   
    156.                 if (device.getBondState() != BluetoothDevice.BOND_BONDED) {   
    157.                     mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());   
    158.                 }   
    159.             // When discovery is finished, change the Activity title   
    160.             } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {    
    161.                 setProgressBarIndeterminateVisibility(false);//搜索完毕,loading条不可见   
    162.                 setTitle(R.string.select_device);   
    163.                 if (mNewDevicesArrayAdapter.getCount() == 0) {   
    164.                     String noDevices = getResources().getText(R.string.none_found).toString();   
    165.                     mNewDevicesArrayAdapter.add(noDevices);   
    166.                 }   
    167.             }   
    168.         }   
    169.     };   
    170. }  

    Java代码 复制代码
    1. /*  
    2.  * Copyright (C) 2009 The Android Open Source Project  
    3.  *  
    4.  * Licensed under the Apache License, Version 2.0 (the "License");  
    5.  * you may not use this file except in compliance with the License.  
    6.  * You may obtain a copy of the License at  
    7.  *  
    8.  *      http://www.apache.org/licenses/LICENSE-2.0  
    9.  *  
    10.  * Unless required by applicable law or agreed to in writing, software  
    11.  * distributed under the License is distributed on an "AS IS" BASIS,  
    12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
    13.  * See the License for the specific language governing permissions and  
    14.  * limitations under the License.  
    15.  */  
    16. package com.example.android.BluetoothChat;   
    17. import java.io.IOException;   
    18. import java.io.InputStream;   
    19. import java.io.OutputStream;   
    20. import java.util.UUID;   
    21. import android.bluetooth.BluetoothAdapter;   
    22. import android.bluetooth.BluetoothDevice;   
    23. import android.bluetooth.BluetoothServerSocket;   
    24. import android.bluetooth.BluetoothSocket;   
    25. import android.content.Context;   
    26. import android.os.Bundle;   
    27. import android.os.Handler;   
    28. import android.os.Message;   
    29. import android.util.Log;   
    30. /**  
    31.  * This class does all the work for setting up and managing Bluetooth  
    32.  * connections with other devices. It has a thread that listens for  
    33.  * incoming connections, a thread for connecting with a device, and a  
    34.  * thread for performing data transmissions when connected.  
    35.  */  
    36. public class BluetoothChatService {   
    37.     // Debugging   
    38.     private static final String TAG = "BluetoothChatService";   
    39.     private static final boolean D = true;   
    40.     // Name for the SDP record when creating server socket   
    41.     private static final String NAME = "BluetoothChat";   
    42.     // Unique UUID for this application   
    43.     private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");   
    44.     // Member fields   
    45.     private final BluetoothAdapter mAdapter;   
    46.     private final Handler mHandler;   
    47.     private AcceptThread mAcceptThread;   
    48.     private ConnectThread mConnectThread;   
    49.     private ConnectedThread mConnectedThread;   
    50.     private int mState;   
    51.     // Constants that indicate the current connection state   
    52.     public static final int STATE_NONE = 0;       // we're doing nothing   
    53.     public static final int STATE_LISTEN = 1;     // now listening for incoming connections   
    54.     public static final int STATE_CONNECTING = 2// now initiating an outgoing connection   
    55.     public static final int STATE_CONNECTED = 3;  // now connected to a remote device   
    56.     /**  
    57.      * Constructor. Prepares a new BluetoothChat session.  
    58.      * @param context  The UI Activity Context  
    59.      * @param handler  A Handler to send messages back to the UI Activity  
    60.      */  
    61.     public BluetoothChatService(Context context, Handler handler) {   
    62.         mAdapter = BluetoothAdapter.getDefaultAdapter();   
    63.         mState = STATE_NONE;   
    64.         mHandler = handler;   
    65.     }   
    66.     /**  
    67.      * Set the current state of the chat connection  
    68.      * @param state  An integer defining the current connection state  
    69.      */  
    70.     private synchronized void setState(int state) {   
    71.         if (D) Log.d(TAG, "setState() " + mState + " -> " + state);   
    72.         mState = state;   
    73.         // Give the new state to the Handler so the UI Activity can update 更新状态,使用Handler向UI发送消息提示   
    74.         mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();   
    75.     }   
    76.     /**  
    77.      * Return the current connection state. */  
    78.     public synchronized int getState() {   
    79.         return mState;   
    80.     }   
    81.     /**  
    82.      * Start the chat service. Specifically start AcceptThread to begin a  
    83.      * session in listening (server) mode. Called by the Activity onResume() */  
    84.     public synchronized void start() {   
    85.         if (D) Log.d(TAG, "start");   
    86.         // Cancel any thread attempting to make a connection   
    87.         if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}   
    88.         // Cancel any thread currently running a connection   
    89.         if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}   
    90.         // Start the thread to listen on a BluetoothServerSocket   
    91.         if (mAcceptThread == null) {   
    92.             mAcceptThread = new AcceptThread();   
    93.             mAcceptThread.start();   
    94.         }   
    95.         setState(STATE_LISTEN);   
    96.     }   
    97.     /**  
    98.      * Start the ConnectThread to initiate a connection to a remote device.  
    99.      * @param device  The BluetoothDevice to connect  
    100.      */  
    101.     public synchronized void connect(BluetoothDevice device) {   
    102.         if (D) Log.d(TAG, "connect to: " + device);   
    103.         // Cancel any thread attempting to make a connection   
    104.         if (mState == STATE_CONNECTING) {   
    105.             if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}   
    106.         }   
    107.         // Cancel any thread currently running a connection   
    108.         if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}   
    109.         // Start the thread to connect with the given device 设置正在状态为正在连接   
    110.         mConnectThread = new ConnectThread(device);   
    111.         mConnectThread.start();   
    112.         setState(STATE_CONNECTING);   
    113.     }   
    114.     /**  
    115.      * Start the ConnectedThread to begin managing a Bluetooth connection  
    116.      * @param socket  The BluetoothSocket on which the connection was made  
    117.      * @param device  The BluetoothDevice that has been connected  
    118.      */  
    119.     public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {   
    120.         if (D) Log.d(TAG, "connected");   
    121.         // Cancel the thread that completed the connection   
    122.         if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}   
    123.         // Cancel any thread currently running a connection   
    124.         if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}   
    125.         // Cancel the accept thread because we only want to connect to one device   
    126.         if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}   
    127.         // Start the thread to manage the connection and perform transmissions   
    128.         mConnectedThread = new ConnectedThread(socket);   
    129.         mConnectedThread.start();   
    130.         // Send the name of the connected device back to the UI Activity   
    131.         Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);   
    132.         Bundle bundle = new Bundle();   
    133.         bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());   
    134.         msg.setData(bundle);   
    135.         mHandler.sendMessage(msg);   
    136.         setState(STATE_CONNECTED);   
    137.     }   
    138.     /**  
    139.      * Stop all threads  
    140.      */  
    141.     public synchronized void stop() {   
    142.         if (D) Log.d(TAG, "stop");   
    143.         if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}   
    144.         if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}   
    145.         if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}   
    146.         setState(STATE_NONE);   
    147.     }   
    148.     /**  
    149.      * Write to the ConnectedThread in an unsynchronized manner  
    150.      * @param out The bytes to write  
    151.      * @see ConnectedThread#write(byte[])  
    152.      */  
    153.     public void write(byte[] out) {   
    154.         // Create temporary object   
    155.         ConnectedThread r;   
    156.         // Synchronize a copy of the ConnectedThread   
    157.         synchronized (this) {   
    158.             if (mState != STATE_CONNECTED) return;   
    159.             r = mConnectedThread;   
    160.         }   
    161.         // Perform the write unsynchronized   
    162.         r.write(out);   
    163.     }   
    164.     /**  
    165.      * Indicate that the connection attempt failed and notify the UI Activity.  
    166.      */  
    167.     private void connectionFailed() {   
    168.         setState(STATE_LISTEN);   
    169.         // Send a failure message back to the Activity更新状态,使用Handler向UI发送消息提示   
    170.         Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);   
    171.         Bundle bundle = new Bundle();   
    172.         bundle.putString(BluetoothChat.TOAST, "Unable to connect device");   
    173.         msg.setData(bundle);   
    174.         mHandler.sendMessage(msg);   
    175.     }   
    176.     /**  
    177.      * Indicate that the connection was lost and notify the UI Activity.  
    178.      */  
    179.     private void connectionLost() {   
    180.         setState(STATE_LISTEN);   
    181.         // Send a failure message back to the Activity更新状态,使用Handler向UI发送消息提示   
    182.         Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);   
    183.         Bundle bundle = new Bundle();   
    184.         bundle.putString(BluetoothChat.TOAST, "Device connection was lost");   
    185.         msg.setData(bundle);   
    186.         mHandler.sendMessage(msg);   
    187.     }   
    188.     /**  
    189.      * This thread runs while listening for incoming connections. It behaves  
    190.      * like a server-side client. It runs until a connection is accepted  
    191.      * (or until cancelled).  
    192.      */  
    193.     private class AcceptThread extends Thread {   
    194.         // The local server socket   
    195.         private final BluetoothServerSocket mmServerSocket;   
    196.         public AcceptThread() {   
    197.             BluetoothServerSocket tmp = null;   
    198.             // Create a new listening server socket   
    199.             try {   
    200.                 tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);   
    201.             } catch (IOException e) {   
    202.                 Log.e(TAG, "listen() failed", e);   
    203.             }   
    204.             mmServerSocket = tmp;   
    205.         }   
    206.         public void run() {   
    207.             if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);   
    208.             setName("AcceptThread");   
    209.             BluetoothSocket socket = null;   
    210.             // Listen to the server socket if we're not connected 不断监听是否有蓝牙连接请求   
    211.             while (mState != STATE_CONNECTED) {    
    212.                 try {   
    213.                     // This is a blocking call and will only return on a   
    214.                     // successful connection or an exception   
    215.                     socket = mmServerSocket.accept();   
    216.                 } catch (IOException e) {   
    217.                     Log.e(TAG, "accept() failed", e);   
    218.                     break;   
    219.                 }   
    220.                 // If a connection was accepted   
    221.                 if (socket != null) {   
    222.                     synchronized (BluetoothChatService.this) {   
    223.                         switch (mState) {   
    224.                         case STATE_LISTEN:   
    225.                         case STATE_CONNECTING:   
    226.                             // Situation normal. Start the connected thread. 当有连接请求且状态是正在连接时   
    227.                             connected(socket, socket.getRemoteDevice());   
    228.                             break;   
    229.                         case STATE_NONE:   
    230.                         case STATE_CONNECTED:   
    231.                             // Either not ready or already connected. Terminate new socket.   
    232.                             try {   
    233.                                 socket.close();   
    234.                             } catch (IOException e) {   
    235.                                 Log.e(TAG, "Could not close unwanted socket", e);   
    236.                             }   
    237.                             break;   
    238.                         }   
    239.                     }   
    240.                 }   
    241.             }   
    242.             if (D) Log.i(TAG, "END mAcceptThread");   
    243.         }   
    244.         public void cancel() {   
    245.             if (D) Log.d(TAG, "cancel " + this);   
    246.             try {   
    247.                 mmServerSocket.close();   
    248.             } catch (IOException e) {   
    249.                 Log.e(TAG, "close() of server failed", e);   
    250.             }   
    251.         }   
    252.     }   
    253.   
    254.     /**  
    255.      * This thread runs while attempting to make an outgoing connection  
    256.      * with a device. It runs straight through; the connection either  
    257.      * succeeds or fails.  
    258.      */  
    259.     private class ConnectThread extends Thread {   
    260.         private final BluetoothSocket mmSocket;   
    261.         private final BluetoothDevice mmDevice;   
    262.         public ConnectThread(BluetoothDevice device) {   
    263.             mmDevice = device;   
    264.             BluetoothSocket tmp = null;   
    265.             // Get a BluetoothSocket for a connection with the   
    266.             // given BluetoothDevice   
    267.             try {   
    268.                 tmp = device.createRfcommSocketToServiceRecord(MY_UUID);   
    269.             } catch (IOException e) {   
    270.                 Log.e(TAG, "create() failed", e);   
    271.             }   
    272.             mmSocket = tmp;   
    273.         }   
    274.         public void run() {   
    275.             Log.i(TAG, "BEGIN mConnectThread");   
    276.             setName("ConnectThread");   
    277.             // Always cancel discovery because it will slow down a connection   
    278.             mAdapter.cancelDiscovery();   
    279.             // Make a connection to the BluetoothSocket   
    280.             try {   
    281.                 // This is a blocking call and will only return on a   
    282.                 // successful connection or an exception   
    283.                 mmSocket.connect();   
    284.             } catch (IOException e) {   
    285.                 connectionFailed();   
    286.                 // Close the socket   
    287.                 try {   
    288.                     mmSocket.close();   
    289.                 } catch (IOException e2) {   
    290.                     Log.e(TAG, "unable to close() socket during connection failure", e2);   
    291.                 }   
    292.                 // Start the service over to restart listening mode   
    293.                 BluetoothChatService.this.start();   
    294.                 return;   
    295.             }   
    296.             // Reset the ConnectThread because we're done   
    297.             synchronized (BluetoothChatService.this) {   
    298.                 mConnectThread = null;   
    299.             }   
    300.             // Start the connected thread   
    301.             connected(mmSocket, mmDevice);   
    302.         }   
    303.         public void cancel() {   
    304.             try {   
    305.                 mmSocket.close();   
    306.             } catch (IOException e) {   
    307.                 Log.e(TAG, "close() of connect socket failed", e);   
    308.             }   
    309.         }   
    310.     }   
    311.     /**  
    312.      * This thread runs during a connection with a remote device.  
    313.      * It handles all incoming and outgoing transmissions.  
    314.      */  
    315.     private class ConnectedThread extends Thread {   
    316.         private final BluetoothSocket mmSocket;   
    317.         private final InputStream mmInStream;   
    318.         private final OutputStream mmOutStream;   
    319.         public ConnectedThread(BluetoothSocket socket) {   
    320.             Log.d(TAG, "create ConnectedThread");   
    321.             mmSocket = socket;   
    322.             InputStream tmpIn = null;   
    323.             OutputStream tmpOut = null;   
    324.             // Get the BluetoothSocket input and output streams   
    325.             try {   
    326.                 tmpIn = socket.getInputStream();   
    327.                 tmpOut = socket.getOutputStream();   
    328.             } catch (IOException e) {   
    329.                 Log.e(TAG, "temp sockets not created", e);   
    330.             }   
    331.             mmInStream = tmpIn;   
    332.             mmOutStream = tmpOut;   
    333.         }   
    334.         public void run() {   
    335.             Log.i(TAG, "BEGIN mConnectedThread");   
    336.             byte[] buffer = new byte[1024];   
    337.             int bytes;   
    338.             // Keep listening to the InputStream while connected   
    339.             while (true) {   
    340.                 try {   
    341.                     // Read from the InputStream    
    342.                     bytes = mmInStream.read(buffer);   
    343.                     // Send the obtained bytes to the UI Activity   
    344.                     mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)   
    345.                             .sendToTarget();   
    346.                 } catch (IOException e) {   
    347.                     Log.e(TAG, "disconnected", e);   
    348.                     connectionLost();   
    349.                     break;   
    350.                 }   
    351.             }   
    352.         }   
    353.         /**  
    354.          * Write to the connected OutStream.  
    355.          * @param buffer  The bytes to write  
    356.          */  
    357.         public void write(byte[] buffer) {   
    358.             try {   
    359.                 mmOutStream.write(buffer); //向对方写数据   
    360.                 // Share the sent message back to the UI Activity   
    361.                 mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)   
    362.                         .sendToTarget();   
    363.             } catch (IOException e) {   
    364.                 Log.e(TAG, "Exception during write", e);   
    365.             }   
    366.         }   
    367.         public void cancel() {   
    368.             try {   
    369.                 mmSocket.close();   
    370.             } catch (IOException e) {   
    371.                 Log.e(TAG, "close() of connect socket failed", e);   
    372.             }   
    373.         }   
    374.     }   
    375. }  

    里面的难点就是BluetoothChatService.java这个类中几个线程的理解;

    ConnectThread这个线程就是连接socket的线程.如果断开就执行 BluetoothChatService.this.start();这段句代码来重新获取socket

    那么AcceptThread这个就很容易理解了.就是获取socket的线程.

    ConnectedThread这个线程就是一直运行着来接受输入输出数据的线程.当ConnectThread连接之后就开始执行他.

    其他的都比较好理解吧

  • 相关阅读:
    switch语句(上)(转载)
    MSIL实用指南-生成if...else...语句
    Docker 部署Jira8.1.0
    K8S从入门到放弃系列-(13)Kubernetes集群mertics-server部署
    K8S踩坑篇-master节点作为node节点加入集群
    K8S从入门到放弃系列-(12)Kubernetes集群Coredns部署
    K8S从入门到放弃系列-(11)kubernetes集群网络Calico部署
    K8S从入门到放弃系列-(10)kubernetes集群之kube-proxy部署
    K8S从入门到放弃系列-(9)kubernetes集群之kubelet部署
    K8S从入门到放弃系列-(8)kube-apiserver 高可用配置
  • 原文地址:https://www.cnblogs.com/qingblog/p/2553772.html
Copyright © 2011-2022 走看看