android中基于蓝牙开发的demo

来源:互联网 发布:奇迹暖暖 知乎 编辑:程序博客网 时间:2024/05/18 00:33

今儿闲着无聊,重新浏览android中sdk重的sample中的demo,觉的BluetoothChat写的不错,就把它搬到这里,以方便查看和学习。

主显示界面activity:

/* * 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        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        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) {              // 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();        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) {            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);            mOutEditText.setText(mOutStringBuffer);        }    }    // 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    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                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                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) {        MenuInflater inflater = getMenuInflater();        inflater.inflate(R.menu.option_menu, menu);        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        switch (item.getItemId()) {        case R.id.scan:            // Launch the DeviceListActivity to see devices and do scan            Intent serverIntent = new Intent(this, DeviceListActivity.class);            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);            return true;        case R.id.discoverable:            // Ensure this device is discoverable by others            ensureDiscoverable();            return true;        }        return false;    }}

有关服务的类:

/* * 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        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        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        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);            }        }    }}

3.查询结果对话框:

/* * 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        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();        }        // Unregister broadcast listeners        this.unregisterReceiver(mReceiver);    }    /**     * Start device discover with the BluetoothAdapter     */    private void doDiscovery() {        if (D) Log.d(TAG, "doDiscovery()");        // Indicate scanning in the title        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            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);                setTitle(R.string.select_device);                if (mNewDevicesArrayAdapter.getCount() == 0) {                    String noDevices = getResources().getText(R.string.none_found).toString();                    mNewDevicesArrayAdapter.add(noDevices);                }            }        }    };}

Manifest.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" />    <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" />    </application></manifest>

String.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.--><resources>    <string name="app_name">Bluetooth Chat</string>    <!--  BluetoothChat -->    <string name="send">Send</string>    <string name="not_connected">You are not connected to a device</string>    <string name="bt_not_enabled_leaving">Bluetooth was not enabled. Leaving Bluetooth Chat.</string>    <string name="title_connecting">connecting...</string>    <string name="title_connected_to">connected: </string>    <string name="title_not_connected">not connected</string>    <!--  DeviceListActivity -->    <string name="scanning">scanning for devices...</string>    <string name="select_device">select a device to connect</string>    <string name="none_paired">No devices have been paired</string>    <string name="none_found">No devices found</string>    <string name="title_paired_devices">Paired Devices</string>    <string name="title_other_devices">Other Available Devices</string>    <string name="button_scan">Scan for devices</string>    <!-- Options Menu -->    <string name="connect">Connect a device</string>    <string name="discoverable">Make discoverable</string></resources>

option_menu.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.--><menu xmlns:android="http://schemas.android.com/apk/res/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>

Layout

message.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.--><TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:textSize="18sp"    android:padding="5dp"android:password="true"/>

main.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.--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    >    <ListView android:id="@+id/in"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:stackFromBottom="true"        android:transcriptMode="alwaysScroll"        android:layout_weight="1"    />    <LinearLayout        android:orientation="horizontal"        android:layout_width="fill_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>

custom_title.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.--><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_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="fill_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="fill_parent"        android:textColor="#fff"        android:layout_weight="1"     /></RelativeLayout>

device_list.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.--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    >    <TextView android:id="@+id/title_paired_devices"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="@string/title_paired_devices"        android:visibility="gone"        android:background="#666"        android:textColor="#fff"        android:paddingLeft="5dp"    />    <ListView android:id="@+id/paired_devices"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:stackFromBottom="true"        android:layout_weight="1"    />    <TextView android:id="@+id/title_new_devices"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="@string/title_other_devices"        android:visibility="gone"        android:background="#666"        android:textColor="#fff"        android:paddingLeft="5dp"    />    <ListView android:id="@+id/new_devices"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:stackFromBottom="true"        android:layout_weight="2"    />    <Button android:id="@+id/button_scan"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="@string/button_scan"    /></LinearLayout>

device_name.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.--><TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:textSize="18sp"    android:padding="5dp"/>



原创粉丝点击