蓝牙聊天
2016-07-17 21:12
211 查看
最近通过Google学习了两部设备之间通过蓝牙连接实现聊天的功能,以下为代码:
接下来是
接下来实现的是:
已配对列表和发现新设备的列表和开启300s蓝牙可被发现的功能
以下是一些布局文件
/** * BlueToothChat:开启蓝牙,300s可见,连接设备,线程UI处理,聊天设置,整个界面功能的实现 * @author micro * */ public class BlueToothChat extends Activity { //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; //设备名和TOAST public static final String DEVICE_NAME = "device_name"; public static final String TOAST = "toast"; //请求码 public static final int REQUEST_CONNECT_DEVICE = 2; public static final int REQUEST_ENABLE_BT = 3; //控件 private ListView mConversation; private EditText mEdit; private Button sendBtn; private String mConnectedServiceName; //设备名 private ArrayAdapter<String> mConversationAdapter; //聊天设配器 private StringBuffer mOutString ; //输出的信息 private BluetoothAdapter mBluetoothAdapter = null; //蓝牙适配器 private BlueToothChatService mBlueToothChatService = null; //服务端 @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //获取默认的蓝牙适配器 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if(mBluetoothAdapter==null){ Toast.makeText(getApplicationContext(), "此设备不支持蓝牙", Toast.LENGTH_SHORT).show(); this.finish(); //结束 return ; } } /** * 在onStart方法中开启蓝牙 */ @Override public void onStart(){ super.onStart(); //如果蓝牙没开,则开启蓝牙,开启后回调REQUEST_ENABLE_BT if(!mBluetoothAdapter.isEnabled()){ Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent,REQUEST_ENABLE_BT); }else{ if(mBlueToothChatService == null){ //设置聊天 setupChat(); } } } /** * 在onResume方法中开启服务端里的线程 */ @Override public void onResume(){ super.onResume(); //只有满足以下的两个条件之后我们才会开启 if(mBlueToothChatService!=null){ if(mBlueToothChatService.getState()==BlueToothChatService.STATE_NONE){ mBlueToothChatService.start(); } } } /** * 聊天设置,初始化及监听 */ private void setupChat() { // TODO Auto-generated method stub //初始化ListView mConversationAdapter = new ArrayAdapter<String>(this,R.layout.message); mConversation = (ListView)findViewById(R.id.chat_list); mConversation.setAdapter(mConversationAdapter); //发送按钮 sendBtn = (Button)findViewById(R.id.send_btn); sendBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub TextView mTextView = (TextView)findViewById(R.id.edit_text); String message = mTextView.getText().toString(); sendMessage(message); } }); //Edit监听 mEdit = (EditText)findViewById(R.id.edit_text); mEdit.setOnEditorActionListener(mWriteLisentner); //初始化 mBlueToothChatService = new BlueToothChatService(this,handler); mOutString = new StringBuffer(""); } //发送信息到Handler处理 private void sendMessage(String message) { // TODO Auto-generated method stub if(mBlueToothChatService.getState()!=BlueToothChatService.STATE_CONNECTED){ Toast.makeText(getApplicationContext(), R.string.not_connected, Toast.LENGTH_SHORT).show(); return ; } if(message.length()>0){ //在这里发送信息 byte[] send = message.getBytes(); mBlueToothChatService.write(send); //重置清空 mOutString.setLength(0); mEdit.setText(mOutString); } } /** * 监听编辑器的结果 */ private TextView.OnEditorActionListener mWriteLisentner = new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { // TODO Auto-generated method stub //如果结果为空,提示 if(actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP){ String message = view.getText().toString(); sendMessage(message); } return true; } }; //通过ActionBar显示 private final void setStatus(int resId){ final ActionBar actionBar = getActionBar(); actionBar.setSubtitle(resId); } public final void setStatus(CharSequence subTitle){ final ActionBar actionBar = getActionBar(); actionBar.setSubtitle(subTitle); } //handler处理机制 private Handler handler = new Handler(){ @Override public void handleMessage(Message msg){ switch(msg.what){ case MESSAGE_STATE_CHANGE: switch(msg.arg1){ case BlueToothChatService.STATE_CONNECTED: setStatus( "connected to "+mConnectedServiceName); mConversationAdapter.clear(); break; case BlueToothChatService.STATE_CONNECTING: setStatus(R.string.title_connecting); break; case BlueToothChatService.STATE_LISTEN: case BlueToothChatService.STATE_NONE: setStatus(R.string.title_not_connected); break; } break; case MESSAGE_WRITE: byte[] writebuf = (byte[]) msg.obj; String writemessage = new String(writebuf); mConversationAdapter.add("Me: "+writemessage); break; case MESSAGE_READ: byte[] readbuf = (byte[])msg.obj; String readmessage = new String(readbuf, 0, msg.arg1); mConversationAdapter.add(mConnectedServiceName+": "+readmessage); break; case MESSAGE_TOAST: //这个好像没用到 Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show(); break; case MESSAGE_DEVICE_NAME: //保存链接设备的名称 mConnectedServiceName = msg.getData().getString(DEVICE_NAME); Toast.makeText(getApplicationContext(), "connect to "+mConnectedServiceName, Toast.LENGTH_SHORT).show(); break; } } }; //请求码的处理 @Override public void onActivityResult(int requestCode,int resultCode,Intent data){ //通过请求码来判断是否与结果码一样,然后做处理 switch(requestCode){ //请求成功则链接设备 case REQUEST_CONNECT_DEVICE: if(resultCode == Activity.RESULT_OK){ connectDevice(data); } break; case REQUEST_ENABLE_BT: if(resultCode == Activity.RESULT_OK){ //设备可用,进入setupChat() setupChat(); }else{ Toast.makeText(getApplicationContext(), R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); finish(); } } } /** * 连接设备 * @param data */ public void connectDevice(Intent data) { // TODO Auto-generated method stub //获取Mac地址 String address = data.getExtras(). getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); //通过地址获取设备 BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); //然后连接 mBlueToothChatService.connect(device); } @Override public boolean onCreateOptionsMenu(Menu menu){ MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.option_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item){ Intent serverIntent =null; switch (item.getItemId()) { //扫描连接 case R.id.connect_scan: serverIntent = new Intent(this,DeviceListActivity.class); startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); return true; //可发现300s内 case R.id.discoverable: ensureDiscovery(); return true; } return false; } //设置300s可被发现 private void ensureDiscovery() { // TODO Auto-generated method stub 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); } } @Override public synchronized void onPause(){ super.onPause(); } @Override public void onStop(){ super.onStop(); } @Override public void onDestroy(){ super.onDestroy(); if(mBlueToothChatService!=null){ mBlueToothChatService.stop(); } } }
接下来是
/** * BlueToothChatService实现的线程开启,关闭,管理以及连接 * @author micro * */ public class BlueToothChatService { private static int mState; public static final String NAME = "BlueToothChat"; public static final UUID MY_UUID = UUID.fromString("0001101-0000-1000-8000-00805F9B34FB"); // private final Handler mHandler ; //三个线程 private ConnectThread mmConnectThread ; private ConnectedThread mmConnectedThread; private AcceptThread mmAcceptThread; //表示当前的连接状态 public static final int STATE_NONE = 0; public static final int STATE_LISTEN = 1; public static final int STATE_CONNECTING = 2; public static final int STATE_CONNECTED = 3; //蓝牙适配器 private BluetoothAdapter mAdapter; //构造器初始化 public BlueToothChatService(Context context, Handler handler) { // TODO Auto-generated constructor stub mAdapter = BluetoothAdapter.getDefaultAdapter(); mState = STATE_NONE; mHandler = handler; } //设置当前状态 public synchronized void setState(int state){ mState = state; //UI线程处理 mHandler.obtainMessage(BlueToothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); } /** * Return the current connection state. */ public synchronized int getState() { return mState; } /** * 开启AcceptThread线程 */ public synchronized void start() { // TODO Auto-generated method stub if(mmConnectedThread!=null){ mmConnectedThread.cancel(); mmConnectedThread = null; } if(mmConnectThread!=null){ mmConnectThread.cancel(); mmConnectThread=null; } //服务端线程开启 if(mmAcceptThread == null){ mmAcceptThread = new AcceptThread(); mmAcceptThread.start(); } //设置为监听状态 setState(STATE_LISTEN); } /** * 开启一个设备连接线程 * @param device */ public synchronized void connect(BluetoothDevice device) { // TODO Auto-generated method stub if(mState == STATE_CONNECTING){ if(mmConnectThread!=null){ mmConnectThread.cancel(); mmConnectThread = null; } } if(mmConnectedThread!=null){ mmConnectedThread.cancel(); mmConnectedThread = null; } //开启 mmConnectThread = new ConnectThread(device); mmConnectThread.start(); setState(STATE_CONNECTING); } /** * 开启一个已经连接的线程来管理蓝牙连接 * Start the ConnectedThread to begin managing a Bluetooth connection * @param socket * @param device * @param socketType */ public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType){ if(mmConnectedThread!=null){ mmConnectedThread.cancel(); mmConnectedThread = null; } if(mmConnectThread!=null){ mmConnectThread.cancel(); mmConnectThread = null; } if(mmAcceptThread!=null){ mmAcceptThread.cancel(); mmAcceptThread = null; } mmConnectedThread = new ConnectedThread(socket, socketType); mmConnectedThread.start(); // Send the name of the connected device back to the UI Activity Message message = mHandler.obtainMessage(BlueToothChat.MESSAGE_DEVICE_NAME); Bundle bundle = new Bundle(); bundle.putString(BlueToothChat.DEVICE_NAME, device.getName()); message.setData(bundle); mHandler.sendMessage(message); setState(STATE_CONNECTED); } /** * 停止所有的线程 */ public synchronized void stop() { // TODO Auto-generated method stub if(mmConnectedThread!=null){ mmConnectedThread.cancel(); mmConnectedThread = null; } if(mmConnectThread!=null){ mmConnectThread.cancel(); mmConnectThread = null; } if(mmAcceptThread!=null){ mmAcceptThread.cancel(); mmAcceptThread = 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 = mmConnectedThread; } // Perform the write unsynchronized //线程调用写入方法 r.write(out); } /** * failed处理 * @author micro * */ public void connectionFailed(){ Message msg = mHandler.obtainMessage(BlueToothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BlueToothChat.TOAST, "Device connection failed to connect"); msg.setData(bundle); mHandler.sendMessage(msg); //重启对Socket的监听线程,即服务端的线程 BlueToothChatService.this.start(); } /** * * @author micro * */ public void connectionLost(){ 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); //重启对Socket的监听线程,即服务端的线程 BlueToothChatService.this.start(); } //ServerSocket private class AcceptThread extends Thread{ private final BluetoothServerSocket serverSocket; private String socketType; public AcceptThread(){ BluetoothServerSocket temp =null; try { temp = mAdapter. listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (Exception e) { // TODO: handle exception Log.e("listen Thread", "failed to get the temp thread"); } serverSocket = temp; } @Override public void run(){ setName("AcceptThread" + socketType); BluetoothSocket socket = null; //如果设备没有连接 while(mState!=STATE_CONNECTED){ try { socket = serverSocket.accept(); Log.e("success", "success"); } catch (IOException e) { // TODO Auto-generated catch block Log.e("socket", "couldn't accept the socket sending"); break; } //如果Socket.accpt()成功 if(socket!=null){ //异步线程加载 synchronized (BlueToothChatService.this) { switch(mState){ case STATE_LISTEN: case STATE_CONNECTING: Log.e("connectting or Listen", "start"); connected(socket,socket.getRemoteDevice(),socketType); Log.e("connectting or Listen", "success"); break; //None或者连接上的时候关闭socket case STATE_NONE: case STATE_CONNECTED: try { socket.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } break; } } } } } public void cancel(){ try { serverSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //连接线程connectThread,用于连接 private class ConnectThread extends Thread{ private BluetoothSocket mmSocket; private BluetoothDevice mmDevice; private String mSocketTye; public ConnectThread(BluetoothDevice device){ mmDevice = device; BluetoothSocket temp = null; try { temp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } mmSocket = temp; } @Override public void run(){ setName("ConnectThread"+mSocketTye); //关闭扫描发现,否则会影响socket之间的连接 mAdapter.cancelDiscovery(); try { Log.e("mmSocket", "mmSocket.connect()"); mmSocket.connect(); Log.e("mmSocket", "mmSocket.connect success"); } catch (Exception e) { // TODO: handle exception try { mmSocket.close(); } catch (Exception e2) { // TODO: handle exception } //连接失败 connectionFailed(); return; } //重置 synchronized (BlueToothChatService.this) { mmConnectThread = null; } //已连接的线程Start the ConnectedThread to begin managing a Bluetooth connection connected(mmSocket,mmDevice,mSocketTye); } public void cancel(){ try { mmSocket.close(); } catch (Exception e) { // TODO: handle exception } } } //这是一个在两个设备之间进行数据交换的线程,前提是已经连接上 private class ConnectedThread extends Thread{ private BluetoothSocket mmSocket ; private InputStream mmInput ; private OutputStream mmOuput ; public ConnectedThread(BluetoothSocket socket,String socketType){ mmSocket = socket; InputStream tmpInput = null; OutputStream tmpOutput = null; try { tmpInput = socket.getInputStream(); tmpOutput = socket.getOutputStream(); } catch (Exception e) { // TODO: handle exception } mmInput = tmpInput; mmOuput = tmpOutput; } @Override public void run(){ byte[] buff = new byte[1024]; int bytes; while (true) { try { //读取 bytes = mmInput.read(buff); //发送到UI线程处理 mHandler.obtainMessage(BlueToothChat.MESSAGE_READ, bytes, -1, buff).sendToTarget(); } catch (IOException e) { // TODO Auto-generated catch block connectionLost(); BlueToothChatService.this.start(); break; } } } //写入 public void write(byte[] buff){ try { mmOuput.write(buff); mHandler.obtainMessage(BlueToothChat.MESSAGE_WRITE, -1, -1, buff).sendToTarget(); } catch (Exception e) { // TODO: handle exception } } public void cancel(){ try { mmSocket.close(); } catch (Exception e) { // TODO: handle exception } } } } /*关于客户端和服务端: 首先每一部设备都有服务线程和连接线程,当一部设备(A)对另一部设备(B)发起连接的时候,那么A将作为客户端,而B作为服务端,B的服务端线程的serverSocket将不断监听来自客户端的socket 即就是:socket = serverSocket.accept(); 这个实现之后,才能实现彼此的聊天数据线程的连接和交换*/
接下来实现的是:
已配对列表和发现新设备的列表和开启300s蓝牙可被发现的功能
/** * 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. * 这个活动将以dialog的形式显示,主要通过主题设置实现 * 包含的功能有:已配对的设备列表和发现的设备列表 * 当选择任何一个选项的时候,将返回一些信息给BlueToothChat * */ public class DeviceListActivity extends Activity { public static final String EXTRA_DEVICE_ADDRESS = "device_name"; //蓝牙必备 private BluetoothAdapter mBtAdapter; private ArrayAdapter<String> mPairDeviceArrayAdapter; //已配对的适配器 private ArrayAdapter<String> mNewDevicesArrayAdapter; //发现的新设备适配器 @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.device_list); Button scanBtn = (Button)findViewById(R.id.button_scan); scanBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //点击之后开始扫描发现,按钮隐藏不可见 // TODO Auto-generated method stub doDiscovery(); v.setVisibility(View.GONE); } }); //初始化适配器 mPairDeviceArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); ListView pairedList = (ListView)findViewById(R.id.paired_devices); ListView newList = (ListView)findViewById(R.id.new_devices); pairedList.setAdapter(mPairDeviceArrayAdapter); newList.setAdapter(mNewDevicesArrayAdapter); pairedList.setOnItemClickListener(mDeviceClickListener); newList.setOnItemClickListener(mDeviceClickListener); //注册广播及状态 IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(reciver, intentFilter); intentFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(reciver, intentFilter); // mBtAdapter = BluetoothAdapter.getDefaultAdapter(); Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices(); if(pairedDevices.size()>0){ findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE); for(BluetoothDevice device:pairedDevices){ mPairDeviceArrayAdapter.add(device.getName()+"\n"+device.getAddress()); } }else{ String noDevice = getResources().getText(R.string.none_paired).toString(); mPairDeviceArrayAdapter.add(noDevice); } } @Override public void onDestroy(){ super.onDestroy(); if(mBtAdapter!=null){ mBtAdapter.cancelDiscovery(); } this.unregisterReceiver(reciver); } private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) { // TODO Auto-generated method stub //停止扫描发现 mBtAdapter.cancelDiscovery(); //截取后面17位字符也就是Mac地址 String info = ((TextView)v).getText().toString(); String address = info.substring(info.length()-17); Intent intent = new Intent(); intent.putExtra(EXTRA_DEVICE_ADDRESS, address);//返回了一个地址 setResult(RESULT_OK, intent); finish();//关闭界面 } }; public void doDiscovery() { // TODO Auto-generated method stub setProgressBarVisibility(true); setTitle(R.string.scanning); findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE); if(mBtAdapter.isDiscovering()){ mBtAdapter.cancelDiscovery(); } mBtAdapter.startDiscovery(); //开始扫描发现 } // The BroadcastReceiver that listens for discovered devices and // changes the title when discovery is finished //通过广播对扫描的设备做处理 private final BroadcastReceiver reciver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub //获取当前的Action即就是其状态 String action = intent.getAction(); //same and then if(BluetoothDevice.ACTION_FOUND.equals(action)){ //获取设备对象 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //判断该设备是否已配对 if(device.getBondState()!=BluetoothDevice.BOND_BONDED){ mNewDevicesArrayAdapter.add(device.getName()+"\n"+device.getAddress()); } }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){ //扫描结束 setProgressBarVisibility(false); setTitle(R.string.select_device); if(mNewDevicesArrayAdapter.getCount()==0){ String noDevice = getResources().getText(R.string.none_found).toString(); mNewDevicesArrayAdapter.add(noDevice); } } } }; }
权限: <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH" />
以下是一些布局文件
device_list.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/title_paired_devices" android:layout_width="match_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="match_parent" android:layout_height="wrap_content" android:stackFromBottom="true" android:layout_weight="1" /> <TextView android:id="@+id/title_new_devices" android:layout_width="match_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="match_parent" android:layout_height="wrap_content" android:stackFromBottom="true" android:layout_weight="2" /> <Button android:id="@+id/button_scan" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/button_scan" /> </LinearLayout> device_name.xml: <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:padding="5dp" /> message.xml: <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:padding="5dp" /> main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/chat_list" android:layout_width="match_parent" android:layout_height="0dp" android:stackFromBottom="true" android:transcriptMode="alwaysScroll" android:layout_weight="1"> </ListView> <LinearLayout android:layout_gravity="bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/edit_text" android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" /> <Button android:id="@+id/send_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/send"/> </LinearLayout> </LinearLayout> strings.xml: <resources> <string name="app_name">BlueToothChat</string> <string name="send">Send</string> <string name="not_connected">You are not connected to a device</string> <string name="title_connecting">connecting...</string> <string name="title_not_connected">not connected</string> <string name="bt_not_enabled_leaving">Bluetooth was not enabled. Leaving Bluetooth Chat.</string> <!-- Options Menu --> <string name="connect">Connect a device</string> <string name="discoverable">Make discoverable</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> </resources> option_menu.xml: <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/connect_scan" android:icon="@android:drawable/ic_menu_search" android:title="@string/connect" android:showAsAction="ifRoom|withText" /> <item android:id="@+id/discoverable" android:icon="@android:drawable/ic_menu_mylocation" android:title="@string/discoverable" android:showAsAction="ifRoom|withText" /> </menu> AndroidManifest.xml的Apllication部分: <application android:allowBackup="true" android:icon="@drawable/app_icon" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".BlueToothChat" 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.Holo.Dialog" android:configChanges="orientation|keyboardHidden"></activity> </application>
相关文章推荐
- [原创]java局域网聊天系统
- C#线程间不能调用剪切板的解决方法
- C#线程同步的三类情景分析
- C#获取进程或线程相关信息的方法
- 简单对比C#程序中的单线程与多线程设计
- C#停止线程的方法
- C#子线程更新UI控件的方法实例总结
- C#线程队列用法实例分析
- C++使用CriticalSection实现线程同步实例
- 基于C++实现的线程休眠代码
- Windows系统中使用C#编写蓝牙通信程序的简单实例
- VB读取线程、句柄及写入内存的API代码实例
- Android聊天工具基于socket实现
- PHP+swoole实现简单多人在线聊天群发
- c#实现多线程局域网聊天系统
- C#网络编程基础之进程和线程详解
- C#通过Semaphore类控制线程队列的方法
- C#多线程处理多个队列数据的方法
- C#实现线程安全的简易日志记录方法