MainFest xml

<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2009 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.BluetoothChat" android:versionCode="1" android:versionName="1.0"> <uses-sdk minSdkVersion="6" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <!-- 获取权限BlueTooth--> <application android:label="@string/app_name" android:icon="@drawable/app_icon" > <activity android:name=".BluetoothChat" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".DeviceListActivity" android:label="@string/select_device" android:theme="@android:style/Theme.Dialog" android:configChanges="orientation|keyboardHidden" /> <!-- android:theme="@android:style/Theme.Dialog" 设置界面主题:弹出框主题 --> </application> </manifest>

/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.BluetoothChat; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.view.inputmethod.EditorInfo; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; /** * This is the main Activity that displays the current chat session. */ public class BluetoothChat extends Activity { // Debugging private static final String TAG = "BluetoothChat"; private static final boolean D = true; // Message types sent from the 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; // Key names received from the BluetoothChatService Handler public static final String DEVICE_NAME = "device_name"; public static final String TOAST = "toast"; // Intent request codes 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; // Name of the connected device private String mConnectedDeviceName = null; // Array adapter for the conversation thread private ArrayAdapter<String> mConversationArrayAdapter; // String buffer for outgoing messages private StringBuffer mOutStringBuffer; // Local Bluetooth adapter private BluetoothAdapter mBluetoothAdapter = null; // Member object for the chat services private BluetoothChatService mChatService = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(D) Log.e(TAG, "+++ ON CREATE +++"); // Set up the window layout 设置Activity的标题栏格式Window.FEATURE_CUSTOM_TITLE普通、Window.FEATURE_NO_TITLE无标题栏、Window.FEATURE_INDETERMINATE_PROGRESS进度条 requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.main); //设置标题栏的布局资源 getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title); // Set up the custom title mTitle = (TextView) findViewById(R.id.title_left_text); mTitle.setText(R.string.app_name); mTitle = (TextView) findViewById(R.id.title_right_text); // Get local Bluetooth adapter //从根本上讲,这是你的出发点,所有的蓝牙行动。一旦你的本地适配器,getBondedDevices()所有配对设备对象设置; //与startDiscovery()启动设备可被发现,或建立一个BluetoothServerSocket监听与listenUsingRfcommWithServiceRecord(字符串,UUID的)传入的连接请求。 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // If the adapter is null, then Bluetooth is not supported if (mBluetoothAdapter == null) { Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); finish(); return; } } @Override public void onStart() { super.onStart(); if(D) Log.e(TAG, "++ ON START ++"); // If BT is not on, request that it be enabled. // setupChat() will then be called during onActivityResult //判断蓝牙是否开启,否则请求开启 if (!mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); // Otherwise, setup the chat session } else { if (mChatService == null) setupChat(); } } @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) { // Only if the state is STATE_NONE, do we know that we haven't started already if (mChatService.getState() == BluetoothChatService.STATE_NONE) { //STATE_NONE及刚创建为启动状态,如果是从后台切换到前台应为STATE_LISTEN,无需再次启动 // Start the Bluetooth chat services mChatService.start(); } } } private void setupChat() { Log.d(TAG, "setupChat()"); // Initialize the array adapter for the conversation thread mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message); mConversationView = (ListView) findViewById(R.id.in); mConversationView.setAdapter(mConversationArrayAdapter); // Initialize the compose field with a listener for the return key mOutEditText = (EditText) findViewById(R.id.edit_text_out); mOutEditText.setOnEditorActionListener(mWriteListener);////注册编辑状态监听 // Initialize the send button with a listener that for click events mSendButton = (Button) findViewById(R.id.button_send); mSendButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { // Send a message using content of the edit text widget TextView view = (TextView) findViewById(R.id.edit_text_out); String message = view.getText().toString(); sendMessage(message); //点击发送则向蓝牙发送消息 } }); // Initialize the BluetoothChatService to perform bluetooth connections mChatService = new BluetoothChatService(this, mHandler); // Initialize the buffer for outgoing messages mOutStringBuffer = new StringBuffer(""); } @Override public synchronized void onPause() { super.onPause(); if(D) Log.e(TAG, "- ON PAUSE -"); } @Override public void onStop() { super.onStop(); if(D) Log.e(TAG, "-- ON STOP --"); } @Override public void onDestroy() { super.onDestroy(); // Stop the Bluetooth chat services if (mChatService != null) mChatService.stop(); //UI关闭时,蓝牙服务应也停止 if(D) Log.e(TAG, "--- ON DESTROY ---"); } private void ensureDiscoverable() { if(D) Log.d(TAG, "ensure discoverable"); if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { //如果蓝牙状态为不可被发现则请求开启为可被发现,时间300秒内 Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent); } } /** * Sends a message. * @param message A string of text to send. */ private void sendMessage(String message) { // Check that we're actually connected before trying anything if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) { Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show(); return; } // Check that there's actually something to send if (message.length() > 0) { // Get the message bytes and tell the BluetoothChatService to write byte[] send = message.getBytes(); mChatService.write(send); // Reset out string buffer to zero and clear the edit text field mOutStringBuffer.setLength(0); //mOutStringBuffer 一直未使用,何意? mOutEditText.setText(mOutStringBuffer);//清空编辑框 窃以为使用mOutEditText.setText("");即可 } } // 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 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; } }; // The Handler that gets information back from the BluetoothChatService //更新标题栏右边状态和读写状态的Handler private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_STATE_CHANGE: if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); switch (msg.arg1) { case BluetoothChatService.STATE_CONNECTED: mTitle.setText(R.string.title_connected_to); mTitle.append(mConnectedDeviceName); mConversationArrayAdapter.clear(); //清空消息 break; case BluetoothChatService.STATE_CONNECTING: mTitle.setText(R.string.title_connecting); break; case BluetoothChatService.STATE_LISTEN: case BluetoothChatService.STATE_NONE: mTitle.setText(R.string.title_not_connected); break; } break; case MESSAGE_WRITE: byte[] writeBuf = (byte[]) msg.obj; // construct a string from the buffer String writeMessage = new String(writeBuf); mConversationArrayAdapter.add("Me: " + writeMessage); break; case MESSAGE_READ: byte[] readBuf = (byte[]) msg.obj; // construct a string from the valid bytes in the buffer String readMessage = new String(readBuf, 0, msg.arg1); mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage); break; case MESSAGE_DEVICE_NAME: // save the connected device's name mConnectedDeviceName = msg.getData().getString(DEVICE_NAME); Toast.makeText(getApplicationContext(), "Connected to " + mConnectedDeviceName, Toast.LENGTH_SHORT).show(); break; case MESSAGE_TOAST: Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show(); break; } } }; public void onActivityResult(int requestCode, int resultCode, Intent data) { if(D) Log.d(TAG, "onActivityResult " + resultCode); switch (requestCode) { case REQUEST_CONNECT_DEVICE: // When DeviceListActivity returns with a device to connect if (resultCode == Activity.RESULT_OK) { // Get the device MAC address String address = data.getExtras() .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); // Get the BLuetoothDevice object if(address==null){ break; } //获取设备进行连接 BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); // Attempt to connect to the device mChatService.connect(device); } break; case REQUEST_ENABLE_BT: // When the request to enable Bluetooth returns if (resultCode == Activity.RESULT_OK) { // Bluetooth is now enabled, so set up a chat session //蓝牙开启成功,则继续初始化UI setupChat(); } else { // User did not enable Bluetooth or an error occured Log.d(TAG, "BT not enabled"); Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); finish(); } } } @Override public boolean onCreateOptionsMenu(Menu menu) { //从Menu资源中初始化Menu 返回true则弹出默认menu,false则不弹出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 //启动DeviceListActivity,并等待返回 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; } }

/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.BluetoothChat; import java.util.Set; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; /** * This Activity appears as a dialog. It lists any paired devices and * devices detected in the area after discovery. When a device is chosen * by the user, the MAC address of the device is sent back to the parent * Activity in the result Intent. */ public class DeviceListActivity extends Activity { // Debugging private static final String TAG = "DeviceListActivity"; private static final boolean D = true; // Return Intent extra public static String EXTRA_DEVICE_ADDRESS = "device_address"; // Member fields private BluetoothAdapter mBtAdapter; private ArrayAdapter<String> mPairedDevicesArrayAdapter; private ArrayAdapter<String> mNewDevicesArrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Setup the window requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.device_list); // Set result CANCELED incase the user backs out //先设置为Canceled 防止点击回退键时BluetoothChat认为是Result_OK状态 setResult(Activity.RESULT_CANCELED); // Initialize the button to perform device discovery Button scanButton = (Button) findViewById(R.id.button_scan); scanButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { doDiscovery(); v.setVisibility(View.GONE); } }); // Initialize array adapters. One for already paired devices and // one for newly discovered devices mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); // Find and set up the ListView for paired devices ListView pairedListView = (ListView) findViewById(R.id.paired_devices); pairedListView.setAdapter(mPairedDevicesArrayAdapter); pairedListView.setOnItemClickListener(mDeviceClickListener); // Find and set up the ListView for newly discovered devices ListView newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(mDeviceClickListener); // Register for broadcasts when a device is discovered 发现设备时监听过滤 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, filter); // Register for broadcasts when discovery has finished发现设备程序运行结束时监听过滤 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter); // Get the local Bluetooth adapter mBtAdapter = BluetoothAdapter.getDefaultAdapter(); // Get a set of currently paired devices 获取当前已经互联过的设备 Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices(); // If there are paired devices, add each one to the ArrayAdapter if (pairedDevices.size() > 0) { findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE); for (BluetoothDevice device : pairedDevices) { mPairedDevicesArrayAdapter.add(device.getName() + "/n" + device.getAddress()); } } else { String noDevices = getResources().getText(R.string.none_paired).toString(); mPairedDevicesArrayAdapter.add(noDevices); } } @Override protected void onDestroy() { super.onDestroy(); // Make sure we're not doing discovery anymore if (mBtAdapter != null) { mBtAdapter.cancelDiscovery(); //BluetoothAdapter 不受UI管理受系统管理,所以要即使cancelDiscovery } // Unregister broadcast listeners this.unregisterReceiver(mReceiver); //取消监听当UI销毁时 } /** * Start device discover with the BluetoothAdapter */ private void doDiscovery() { if (D) Log.d(TAG, "doDiscovery()"); // Indicate scanning in the title 设置标题加载loading条可见 setProgressBarIndeterminateVisibility(true); setTitle(R.string.scanning); //设置标题 // Turn on sub-title for new devices findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE); // If we're already discovering, stop it if (mBtAdapter.isDiscovering()) { mBtAdapter.cancelDiscovery(); } // Request discover from BluetoothAdapter mBtAdapter.startDiscovery(); } // 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 IP地址17位 String info = ((TextView) v).getText().toString(); String address = info.substring(info.length() - 17); // Create the result Intent and include the MAC address Intent intent = new Intent(); intent.putExtra(EXTRA_DEVICE_ADDRESS, address); // Set result and finish this Activity setResult(Activity.RESULT_OK, intent); finish(); } }; // The BroadcastReceiver that listens for discovered devices and // changes the title when discovery is finished private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // When discovery finds a device 搜索到设备 if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // If it's already paired, skip it, because it's been listed already if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mNewDevicesArrayAdapter.add(device.getName() + "/n" + device.getAddress()); } // When discovery is finished, change the Activity title } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setProgressBarIndeterminateVisibility(false);//搜索完毕,loading条不可见 setTitle(R.string.select_device); if (mNewDevicesArrayAdapter.getCount() == 0) { String noDevices = getResources().getText(R.string.none_found).toString(); mNewDevicesArrayAdapter.add(noDevices); } } } }; }

/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.BluetoothChat; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; /** * This class does all the work for setting up and managing Bluetooth * connections with other devices. It has a thread that listens for * incoming connections, a thread for connecting with a device, and a * thread for performing data transmissions when connected. */ public class BluetoothChatService { // Debugging private static final String TAG = "BluetoothChatService"; private static final boolean D = true; // Name for the SDP record when creating server socket private static final String NAME = "BluetoothChat"; // Unique UUID for this application private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"); // Member fields private final BluetoothAdapter mAdapter; private final Handler mHandler; private AcceptThread mAcceptThread; private ConnectThread mConnectThread; private ConnectedThread mConnectedThread; private int mState; // Constants that indicate the current connection state public static final int STATE_NONE = 0; // we're doing nothing public static final int STATE_LISTEN = 1; // now listening for incoming connections public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection public static final int STATE_CONNECTED = 3; // now connected to a remote device /** * Constructor. Prepares a new BluetoothChat session. * @param context The UI Activity Context * @param handler A Handler to send messages back to the UI Activity */ public BluetoothChatService(Context context, Handler handler) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mState = STATE_NONE; mHandler = handler; } /** * Set the current state of the chat connection * @param state An integer defining the current connection state */ private synchronized void setState(int state) { if (D) Log.d(TAG, "setState() " + mState + " -> " + state); mState = state; // Give the new state to the Handler so the UI Activity can update 更新状态,使用Handler向UI发送消息提示 mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); } /** * Return the current connection state. */ public synchronized int getState() { return mState; } /** * Start the chat service. Specifically start AcceptThread to begin a * session in listening (server) mode. Called by the Activity onResume() */ public synchronized void start() { if (D) Log.d(TAG, "start"); // Cancel any thread attempting to make a connection if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} // Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} // Start the thread to listen on a BluetoothServerSocket if (mAcceptThread == null) { mAcceptThread = new AcceptThread(); mAcceptThread.start(); } setState(STATE_LISTEN); } /** * Start the ConnectThread to initiate a connection to a remote device. * @param device The BluetoothDevice to connect */ public synchronized void connect(BluetoothDevice device) { if (D) Log.d(TAG, "connect to: " + device); // Cancel any thread attempting to make a connection if (mState == STATE_CONNECTING) { if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} } // Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} // Start the thread to connect with the given device 设置正在状态为正在连接 mConnectThread = new ConnectThread(device); mConnectThread.start(); setState(STATE_CONNECTING); } /** * Start the ConnectedThread to begin managing a Bluetooth connection * @param socket The BluetoothSocket on which the connection was made * @param device The BluetoothDevice that has been connected */ public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { if (D) Log.d(TAG, "connected"); // Cancel the thread that completed the connection if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} // Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} // Cancel the accept thread because we only want to connect to one device if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;} // Start the thread to manage the connection and perform transmissions mConnectedThread = new ConnectedThread(socket); mConnectedThread.start(); // Send the name of the connected device back to the UI Activity Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.DEVICE_NAME, device.getName()); msg.setData(bundle); mHandler.sendMessage(msg); setState(STATE_CONNECTED); } /** * Stop all threads */ public synchronized void stop() { if (D) Log.d(TAG, "stop"); if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;} setState(STATE_NONE); } /** * Write to the ConnectedThread in an unsynchronized manner * @param out The bytes to write * @see ConnectedThread#write(byte[]) */ public void write(byte[] out) { // Create temporary object ConnectedThread r; // Synchronize a copy of the ConnectedThread synchronized (this) { if (mState != STATE_CONNECTED) return; r = mConnectedThread; } // Perform the write unsynchronized r.write(out); } /** * Indicate that the connection attempt failed and notify the UI Activity. */ private void connectionFailed() { setState(STATE_LISTEN); // Send a failure message back to the Activity更新状态,使用Handler向UI发送消息提示 Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.TOAST, "Unable to connect device"); msg.setData(bundle); mHandler.sendMessage(msg); } /** * Indicate that the connection was lost and notify the UI Activity. */ private void connectionLost() { setState(STATE_LISTEN); // Send a failure message back to the Activity更新状态,使用Handler向UI发送消息提示 Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.TOAST, "Device connection was lost"); msg.setData(bundle); mHandler.sendMessage(msg); } /** * This thread runs while listening for incoming connections. It behaves * like a server-side client. It runs until a connection is accepted * (or until cancelled). */ private class AcceptThread extends Thread { // The local server socket private final BluetoothServerSocket mmServerSocket; public AcceptThread() { BluetoothServerSocket tmp = null; // Create a new listening server socket try { tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { Log.e(TAG, "listen() failed", e); } mmServerSocket = tmp; } public void run() { if (D) Log.d(TAG, "BEGIN mAcceptThread" + this); setName("AcceptThread"); BluetoothSocket socket = null; // Listen to the server socket if we're not connected 不断监听是否有蓝牙连接请求 while (mState != STATE_CONNECTED) { try { // This is a blocking call and will only return on a // successful connection or an exception socket = mmServerSocket.accept(); } catch (IOException e) { Log.e(TAG, "accept() failed", e); break; } // If a connection was accepted if (socket != null) { synchronized (BluetoothChatService.this) { switch (mState) { case STATE_LISTEN: case STATE_CONNECTING: // Situation normal. Start the connected thread. 当有连接请求且状态是正在连接时 connected(socket, socket.getRemoteDevice()); break; case STATE_NONE: case STATE_CONNECTED: // Either not ready or already connected. Terminate new socket. try { socket.close(); } catch (IOException e) { Log.e(TAG, "Could not close unwanted socket", e); } break; } } } } if (D) Log.i(TAG, "END mAcceptThread"); } public void cancel() { if (D) Log.d(TAG, "cancel " + this); try { mmServerSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of server failed", e); } } } /** * This thread runs while attempting to make an outgoing connection * with a device. It runs straight through; the connection either * succeeds or fails. */ private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { mmDevice = device; BluetoothSocket tmp = null; // Get a BluetoothSocket for a connection with the // given BluetoothDevice try { tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "create() failed", e); } mmSocket = tmp; } public void run() { Log.i(TAG, "BEGIN mConnectThread"); setName("ConnectThread"); // Always cancel discovery because it will slow down a connection mAdapter.cancelDiscovery(); // Make a connection to the BluetoothSocket try { // This is a blocking call and will only return on a // successful connection or an exception mmSocket.connect(); } catch (IOException e) { connectionFailed(); // Close the socket try { mmSocket.close(); } catch (IOException e2) { Log.e(TAG, "unable to close() socket during connection failure", e2); } // Start the service over to restart listening mode BluetoothChatService.this.start(); return; } // Reset the ConnectThread because we're done synchronized (BluetoothChatService.this) { mConnectThread = null; } // Start the connected thread connected(mmSocket, mmDevice); } public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of connect socket failed", e); } } } /** * This thread runs during a connection with a remote device. * It handles all incoming and outgoing transmissions. */ private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) { Log.d(TAG, "create ConnectedThread"); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the BluetoothSocket input and output streams try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "temp sockets not created", e); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { Log.i(TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[1024]; int bytes; // Keep listening to the InputStream while connected while (true) { try { // Read from the InputStream bytes = mmInStream.read(buffer); // Send the obtained bytes to the UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); } catch (IOException e) { Log.e(TAG, "disconnected", e); connectionLost(); break; } } } /** * Write to the connected OutStream. * @param buffer The bytes to write */ public void write(byte[] buffer) { try { mmOutStream.write(buffer); //向对方写数据 // Share the sent message back to the UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer) .sendToTarget(); } catch (IOException e) { Log.e(TAG, "Exception during write", e); } } public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of connect socket failed", e); } } } }

更多相关文章

  1. android中gridView中点击 item为选中状态
  2. android PreferenceActivity使用
  3. android checkBox 的选中和取消选中
  4. android 获取手机设备信息
  5. 短信拦截的解决方案 经典
  6. Android耳机按键监听
  7. Android中隐藏标题栏和状态栏
  8. Android(安卓)监听耳机外放设备
  9. android TelephonyManager

随机推荐

  1. 细说:AndroidStudio插件
  2. [android]android自动化测试六之命令行编
  3. 《完美解决系列》Android(安卓)Studio中
  4. Android:设计一个具有3个选项的菜单程序,
  5. xe5 android sample 中的 SimpleList 是
  6. Android-------Activity之间通信
  7. permission大全及场景的用法
  8. Android之回调函数
  9. Android在线修复bug框架AndFix调研
  10. Android实现步进式录像进度条