android多个蓝牙设备实现连接
这是主界面,分别跳动服务器界面和客户端界面
package com.hao.activity;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class GroupChatActivity extends Activity {
/** Called when the activity is first created. */
//我是服务器按钮
Button buttonServer;
//我是客户端按钮
Button buttonClient;
//当前类跳转到聊天界面时的一个标记,用来说明是从buttonServer或者buttonClient里面进入的
public static final int clientFlag = 1;
public static final int serverFlag = 2;
public static final String FROM = "from";
int pid =Build.VERSION.SDK_INT;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonClient = (Button) findViewById(R.id.client);
buttonClient.setOnClickListener(clickListener);
buttonServer = (Button) findViewById(R.id.server);
buttonServer.setOnClickListener(clickListener);
}
OnClickListener clickListener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = null;
switch (v.getId()) {
case R.id.client:
intent = new Intent(GroupChatActivity.this, ChatAClientActivity.class);
startActivity(intent);
break;
case R.id.server:
intent = new Intent(GroupChatActivity.this, ChatServerActivity.class);
startActivity(intent);
break;
default:
break;
}
}
};
/**
* 完全退出程序
*/
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
if(pid<=7)
{
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
activityManager.restartPackage(getPackageName());
}
else {
android.os.Process.killProcess(pid);
System.exit(0);
finish();
}
return true;
}
return super.onKeyDown(keyCode, event);
}
}
客户端界面
package com.hao.activity;
import com.hao.activity.server.Connection;
import com.hao.activity.server.Connection.OnConnectionLostListener;
import com.hao.activity.server.Connection.OnConnectionServiceReadyListener;
import com.hao.activity.server.Connection.OnMessageReceivedListener;
import android.app.Activity;
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.View;
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;
public class ChatAClientActivity extends Activity {
private Connection mConnection;
private ChatAClientActivity self;
private static final int SERVER_LIST_RESULT_CODE = 42;
// Layout Views
private TextView mTitle;
private ListView mConversationView;
private EditText mOutEditText;
private Button mSendButton;
String deviceString;
// Name of the connected device
private String mConnectedDeviceName = null;
// Array adapter for the conversation thread
private ArrayAdapter mConversationArrayAdapter;
private static final String MAC = "FB:DB:7F:D2:AA:B5";
// private static final String MAC ="D8:B3:77:9A:6A:9A";
/**
* 开启蓝牙服务器端的服务
*/
private OnConnectionServiceReadyListener serviceReadyListener = new OnConnectionServiceReadyListener() {
@Override
public void OnConnectionServiceReady() {
// TODO Auto-generated method stub
Intent serverListIntent = new Intent(self, ServerListActivity.class);
startActivityForResult(serverListIntent, SERVER_LIST_RESULT_CODE);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.clientchat);
self = this;
mConnection = new Connection(this, serviceReadyListener);
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
mConversationArrayAdapter = new ArrayAdapter(this,
R.layout.message);
mConversationView = (ListView) findViewById(R.id.in_client);
mConversationView.setAdapter(mConversationArrayAdapter);
// Initialize the compose field with a listener for the return key
mOutEditText = (EditText) findViewById(R.id.edit_text_out_client);
mOutEditText.setOnEditorActionListener(mWriteListener);
// Initialize the send button with a listener that for click events
mSendButton = (Button) findViewById(R.id.button_send_client);
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_client);
String message = view.getText().toString();
sendMessage(message);
}
});
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (mConnection != null) {
mConnection.shutdown();
}
mConversationArrayAdapter.clear();
}
// The action listener for the 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;
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ((resultCode == Activity.RESULT_OK)
&& (requestCode == SERVER_LIST_RESULT_CODE)) {
String device = data
.getStringExtra(ServerListActivity.EXTRA_SELECTED_ADDRESS);
Toast.makeText(getApplicationContext(), device, Toast.LENGTH_SHORT)
.show();
Log.i("dds", device);
int connectionStatus = mConnection.connect(device,
dataReceivedListener, disconnectedListener);
Log.w("connectionStatus", "" + connectionStatus);
if (connectionStatus != Connection.SUCCESS) {
Toast.makeText(self, "Unable to connect; please try again.", 1)
.show();
}
return;
}
}
protected void sendMessage(String message) {
// TODO Auto-generated method stub
if (message.length() > 0) {
mConnection.sendMessage(deviceString, message);
mConversationArrayAdapter.add("我" + message);
mConversationArrayAdapter.notifyDataSetChanged();
}
}
/**
* 接收到对方发送过来的消息
*/
private OnMessageReceivedListener dataReceivedListener = new OnMessageReceivedListener() {
@Override
public void OnMessageReceived(String device, String message) {
// TODO Auto-generated method stub
deviceString = device;
Message mMessage = new Message();
mMessage.obj = message;
handler.sendMessage(mMessage);
}
};
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
mConversationArrayAdapter.add("她" + msg.obj);
mConversationArrayAdapter.notifyDataSetChanged();
};
};
private OnConnectionLostListener disconnectedListener = new OnConnectionLostListener() {
@Override
public void OnConnectionLost(String device) {
// TODO Auto-generated method stub
deviceString = "";
}
};
}
//服务器界面
package com.hao.activity;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.hao.activity.server.Connection;
import com.hao.activity.server.Connection.OnConnectionLostListener;
import com.hao.activity.server.Connection.OnConnectionServiceReadyListener;
import com.hao.activity.server.Connection.OnIncomingConnectionListener;
import com.hao.activity.server.Connection.OnMaxConnectionsReachedListener;
import com.hao.activity.server.Connection.OnMessageReceivedListener;
import android.R.integer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
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;
public class ChatServerActivity extends Activity {
private Connection mConnection;
private ChatServerActivity self;
// 第一个发送的消息列表
private ListView mConversationView1;
// 第二个发送的消息列表
private ListView mConversationView2;
// 第一个发送消息的输入框
private EditText mOutEditText1;
// 第二个发送消息的输入框
private EditText mOutEditText2;
// 第一个发送消息的按钮
private Button mSendButton1;
// 第二个发送消息的按钮
private Button mSendButton2;
// 当前的蓝牙设备名称
String deviceString;
// Array adapter for the conversation thread
private ArrayAdapter mConversationArrayAdapter1;
private ArrayAdapter mConversationArrayAdapter2;
// 所有连接到的蓝牙设备
List devices = new ArrayList();
int status = -1;
String sendMessage = "Dstad";
// 发送消息
private static final int SENDMESSAGE = 2;
// 接收消息
private static final int RECEIVEMESSAGE = 3;
// 保存第一个蓝牙设备发过来的内容
File file1 = null;
// 保存第二个蓝牙设备发过来的内容
File file2 = null;
// 第一个蓝牙设备保存文件时对应的FileOutputStream
FileOutputStream fileOutputStream1 = null;
// 第二个蓝牙设备保存文件时对应的FileOutputStream
FileOutputStream fileOutputStream2 = null;
// 设置一个标记,用来控制写入文件操作
boolean writeFlag1 = true;
boolean writeFlag2 = true;
// 向文件写入线程1
Thread writeThread1;
//
Thread writeThread2;
/**
* 开启服务器端的服务
*/
private OnConnectionServiceReadyListener serviceReadyListener = new OnConnectionServiceReadyListener() {
@Override
public void OnConnectionServiceReady() {
// TODO Auto-generated method stub
mConnection.startServer(2, connectedListener,
maxConnectionsListener, dataReceivedListener,
disconnectedListener);
self.setTitle("MultiScreen: " + mConnection.getName() + "-"
+ mConnection.getAddress());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.serverchat);
self = this;
// 文件操作初始化
// 将文件保存到SD卡
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File sdCardDir = Environment.getExternalStorageDirectory();// 获取SDCard目录,2.2的时候为:/mnt/sdcard
// 2.1的时候为:/sdcard,所以使用静态方法得到路径会好一点。
file1 = new File(sdCardDir, "abc1.txt");
// FileOutputStream outStream;
try {
fileOutputStream1 = new FileOutputStream(file1);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
file2 = new File(sdCardDir, "abc2.txt");
// FileOutputStream outStream;
try {
fileOutputStream2 = new FileOutputStream(file2);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mConnection = new Connection(this, serviceReadyListener);
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
mConversationArrayAdapter1 = new ArrayAdapter(this,
R.layout.message);
mConversationView1 = (ListView) findViewById(R.id.in_server_1);
mConversationView1.setAdapter(mConversationArrayAdapter1);
// Initialize the compose field with a listener for the return key
mOutEditText1 = (EditText) findViewById(R.id.edit_text_out_server_1);
mOutEditText1.setOnEditorActionListener(mWriteListener);
mOutEditText1.setText(sendMessage);
// Initialize the send button with a listener that for click events
mSendButton1 = (Button) findViewById(R.id.button_send_server_1);
mSendButton1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String message = mOutEditText1.getText().toString();
deviceString = devices.get(0);
sendServerMessage(message);
}
});
mConversationArrayAdapter2 = new ArrayAdapter(this,
R.layout.message);
mConversationView2 = (ListView) findViewById(R.id.in_server_2);
mConversationView2.setAdapter(mConversationArrayAdapter2);
// Initialize the compose field with a listener for the return key
mOutEditText2 = (EditText) findViewById(R.id.edit_text_out_server_2);
mOutEditText2.setOnEditorActionListener(mWriteListener);
mOutEditText2.setText(sendMessage);
// Initialize the send button with a listener that for click events
mSendButton2 = (Button) findViewById(R.id.button_send_server_2);
mSendButton2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String message = mOutEditText2.getText().toString();
deviceString = devices.get(1);
sendServerMessage(message);
}
});
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (mConnection != null) {
mConnection.shutdown();
}
if (mConversationArrayAdapter2 != null) {
mConversationArrayAdapter2.clear();
mConversationArrayAdapter2 = null;
}
if (mConversationArrayAdapter1 != null) {
mConversationArrayAdapter1.clear();
mConversationArrayAdapter1 = null;
}
if (devices != null) {
devices.clear();
devices = null;
}
// 将其当前的蓝牙设备名称设为空
deviceString = null;
// 释放文件流
if (fileOutputStream1 != null) {
try {
fileOutputStream1.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fileOutputStream1 = null;
}
if (fileOutputStream2 != null) {
try {
fileOutputStream2.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fileOutputStream2 = null;
}
// 关闭写入线程
writeFlag1 = false;
writeFlag2 = false;
if (writeThread1 != null) {
writeThread1.stop();
}
}
private TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView view, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_NULL
&& event.getAction() == KeyEvent.ACTION_UP) {
String message = view.getText().toString();
if (view.getId() == R.id.edit_text_out_server_1) {
deviceString = devices.get(1);
}
if (view.getId() == R.id.edit_text_out_server_2) {
deviceString = devices.get(0);
}
sendServerMessage(message);
}
return true;
}
};
public void sendServerMessage(String message) {
// TODO Auto-generated method stub
if (message.length() > 0) {
mConnection.sendMessage(deviceString, message);
int id = devices.indexOf(deviceString);
if (id == 0) {
mConversationArrayAdapter1.add(message);
mConversationArrayAdapter1.notifyDataSetChanged();
} else if (id == 1) {
mConversationArrayAdapter2.add(message);
mConversationArrayAdapter2.notifyDataSetChanged();
}
}
}
private OnMessageReceivedListener dataReceivedListener = new OnMessageReceivedListener() {
@Override
public synchronized void OnMessageReceived(String device, String message) {
// TODO Auto-generated method stub
InputMessage inputMessage = new InputMessage();
inputMessage.device = device;
inputMessage.message = message;
inputMessage.type = RECEIVEMESSAGE;
Message mMessage = new Message();
mMessage.obj = inputMessage;
handler.sendMessage(mMessage);
}
};
// 接收到的消息
String message = null;
/**
* 对UI层进行更新
*/
Handler handler = new Handler() {
public synchronized void handleMessage(android.os.Message msg) {
InputMessage inputMessage = (InputMessage) msg.obj;
int type = inputMessage.type;
switch (type) {
case SENDMESSAGE:
String device = inputMessage.device;
Toast.makeText(getApplicationContext(), "连接到" + device,
Toast.LENGTH_SHORT).show();
break;
case RECEIVEMESSAGE:
message = inputMessage.message;
boolean flag = message.startsWith("aa");
if (flag) {
//writeFlag1 = inputMessage.falg;
// 在蓝牙保持连接的情况下进行以下操作
if (writeFlag1) {
mConversationArrayAdapter1.add("" + message);
mConversationArrayAdapter1.notifyDataSetChanged();
writeThread(writeThread1, fileOutputStream1, message);
/*writeThread1 = new Thread() {
public void run() {
// 将文件保存到SD卡
if (Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)) {
try {
fileOutputStream1.write(message
.getBytes());
fileOutputStream1
.write("\n".getBytes());
fileOutputStream1.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
};
writeThread1.start();*/
}
} else {
//writeFlag2 = inputMessage.falg;
// 在蓝牙保持连接的情况下进行以下操作
if (writeFlag2) {
mConversationArrayAdapter2.add("" + message);
mConversationArrayAdapter2.notifyDataSetChanged();
writeThread(writeThread2, fileOutputStream2, message);
/*writeThread2 = new Thread() {
public void run() {
// 将文件保存到SD卡
if (Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)) {
try {
fileOutputStream2.write(message
.getBytes());
fileOutputStream2
.write("\n".getBytes());
fileOutputStream2.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
};
writeThread2.start();*/
}
}
message = null;
break;
default:
break;
}
};
};
public void writeThread(Thread thread,FileOutputStream fileOutputStream, String messag)
{
final String mesaage1 = messag;
final FileOutputStream fileOutputStream22 = fileOutputStream;
thread = new Thread() {
public void run() {
// 将文件保存到SD卡
if (Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)) {
try {
fileOutputStream22.write(mesaage1
.getBytes());
fileOutputStream22
.write("\n".getBytes());
fileOutputStream22.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
};
thread.start();
}
private OnConnectionLostListener disconnectedListener = new OnConnectionLostListener() {
@Override
public void OnConnectionLost(String device) {
// 当连接断掉,就该将相应的往listview里面显示数据和向文件里面写入数据停止
/*int index = devices.indexOf(device);
if (index == 0) {
writeFlag1 = false;
InputMessage inputMessage = new InputMessage();
inputMessage.device = device;
inputMessage.falg = writeFlag1;
inputMessage.type = RECEIVEMESSAGE;
Message mMessage = new Message();
mMessage.obj = inputMessage;
handler.sendMessage(mMessage);
} else if (index == 1) {
writeFlag2 = false;
InputMessage inputMessage = new InputMessage();
inputMessage.device = device;
inputMessage.falg = writeFlag2;
inputMessage.type = RECEIVEMESSAGE;
Message mMessage = new Message();
mMessage.obj = inputMessage;
handler.sendMessage(mMessage);
}*/
// TODO Auto-generated method stub
deviceString = "";
}
};
private OnMaxConnectionsReachedListener maxConnectionsListener = new OnMaxConnectionsReachedListener() {
public void OnMaxConnectionsReached() {
Log.e("tag", "Max connections reached!");
}
};
/**
* 蓝牙连接成功后,发送过来连接到到地址
*/
private OnIncomingConnectionListener connectedListener = new OnIncomingConnectionListener() {
@Override
public synchronized void OnIncomingConnection(String device) {
// TODO Auto-generated method stub
if (devices.size() == 0) {
devices.add(device);
} else {
for (String str : devices) {
if (str.equals(device)) {
return;
} else {
devices.add(device);
}
}
}
InputMessage inputMessage = new InputMessage();
inputMessage.type = SENDMESSAGE;
inputMessage.device = device;
Message msg = new Message();
msg.obj = inputMessage;
handler.sendMessage(msg);
}
};
// int sum=0;
class InputMessage implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
// 接收或者发送的消息
String message;
// 蓝牙设备的地址
String device;
// 消息类型
int type;
// 消息的相关操作是否终止
boolean falg = true;
}
}
//搜索蓝牙设备
/*
* 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.hao.activity;
import android.app.Activity;
import android.app.ListActivity;
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.os.Parcelable;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
/**
* A simple list activity that displays Bluetooth devices that are in
* discoverable mode. This can be used as a gamelobby where players can see
* available servers and pick the one they wish to connect to.
*/
public class ServerListActivity extends ListActivity {
public static String EXTRA_SELECTED_ADDRESS = "btaddress";
private BluetoothAdapter myBt;
private ServerListActivity self;
private ArrayAdapter arrayAdapter;
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Parcelable btParcel = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
BluetoothDevice btDevice = (BluetoothDevice) btParcel;
arrayAdapter.add(btDevice.getName() + " - " + btDevice.getAddress());
// BluetoothDevice.pairRequest;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
self = this;
arrayAdapter = new ArrayAdapter(self, R.layout.text);
ListView lv = self.getListView();
lv.setAdapter(arrayAdapter);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView> arg0, View arg1, int arg2, long arg3) {
myBt.cancelDiscovery(); // Cancel BT discovery explicitly so
// that connections can go through
String btDeviceInfo = ((TextView) arg1).getText().toString();
String btHardwareAddress = btDeviceInfo.substring(btDeviceInfo.length() - 17);
Intent i = new Intent();
i.putExtra(EXTRA_SELECTED_ADDRESS, btHardwareAddress);
self.setResult(Activity.RESULT_OK, i);
finish();
}
});
myBt = BluetoothAdapter.getDefaultAdapter();
myBt.startDiscovery();
self.setResult(Activity.RESULT_CANCELED);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(myReceiver, filter);
}
@Override
protected void onPause() {
super.onPause();
this.unregisterReceiver(myReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (myBt != null) {
myBt.cancelDiscovery(); // Ensure that we don't leave discovery
}
}
}
//使本机蓝牙可见
/*
* 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.hao.activity;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.bluetooth.BluetoothAdapter;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.widget.Toast;
/**
* A simple activity that displays a prompt telling users to enable discoverable
* mode for Bluetooth.
*/
public class StartDiscoverableModeActivity extends Activity {
public static final int REQUEST_DISCOVERABLE_CODE = 42;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent i = new Intent();
i.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(i, REQUEST_DISCOVERABLE_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_DISCOVERABLE_CODE) {
if (resultCode < 0) {
showWarning();
} else {
Toast.makeText(this, "Discoverable mode enabled.", 1).show();
finish();
}
}
}
private void showWarning() {
Builder warningDialog = new Builder(this);
final Activity self = this;
warningDialog.setTitle(R.string.DISCOVERABLE_MODE_NOT_ENABLED);
warningDialog.setMessage(R.string.WARNING_MESSAGE);
warningDialog.setPositiveButton("Yes", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent i = new Intent();
i.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(i, REQUEST_DISCOVERABLE_CODE);
}
});
warningDialog.setNegativeButton("No", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(self, "Discoverable mode NOT enabled.", 1).show();
finish();
}
});
warningDialog.setCancelable(false);
warningDialog.show();
}
}
//连接
/*
* 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.hao.activity.server;
import com.hao.activity.IConnection;
import com.hao.activity.IConnectionCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
/**
* API for the Bluetooth Click, Link, Compete library. This library simplifies
* the process of establishing Bluetooth connections and sending data in a way
* that is geared towards multi-player games.
*/
public class Connection {
public static final String TAG = "net.clc.bt.Connection";
public static final int SUCCESS = 0;
public static final int FAILURE = 1;
public static final int MAX_SUPPORTED = 2;
public interface OnConnectionServiceReadyListener {
public void OnConnectionServiceReady();
}
public interface OnIncomingConnectionListener {
public void OnIncomingConnection(String device);
}
public interface OnMaxConnectionsReachedListener {
public void OnMaxConnectionsReached();
}
public interface OnMessageReceivedListener {
public void OnMessageReceived(String device, String message);
}
public interface OnConnectionLostListener {
public void OnConnectionLost(String device);
}
private OnConnectionServiceReadyListener mOnConnectionServiceReadyListener;
private OnIncomingConnectionListener mOnIncomingConnectionListener;
private OnMaxConnectionsReachedListener mOnMaxConnectionsReachedListener;
private OnMessageReceivedListener mOnMessageReceivedListener;
private OnConnectionLostListener mOnConnectionLostListener;
private ServiceConnection mServiceConnection;
private Context mContext;
private String mPackageName = "";
private boolean mStarted = false;
private final Object mStartLock = new Object();
private IConnection mIconnection;
private IConnectionCallback mIccb = new IConnectionCallback.Stub() {
public void incomingConnection(String device) throws RemoteException {
if (mOnIncomingConnectionListener != null) {
mOnIncomingConnectionListener.OnIncomingConnection(device);
}
}
public void connectionLost(String device) throws RemoteException {
if (mOnConnectionLostListener != null) {
mOnConnectionLostListener.OnConnectionLost(device);
}
}
public void maxConnectionsReached() throws RemoteException {
if (mOnMaxConnectionsReachedListener != null) {
mOnMaxConnectionsReachedListener.OnMaxConnectionsReached();
}
}
public void messageReceived(String device, String message)
throws RemoteException {
if (mOnMessageReceivedListener != null) {
mOnMessageReceivedListener.OnMessageReceived(device, message);
}
}
};
// TODO: Add a check to autodownload this service from Market if the user
// does not have it already.
public Connection(Context ctx, OnConnectionServiceReadyListener ocsrListener) {
mOnConnectionServiceReadyListener = ocsrListener;
mContext = ctx;
// mPackageName = ctx.getPackageName();
mPackageName = "SPP";
mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mStartLock) {
mIconnection = IConnection.Stub.asInterface(service);
mStarted = true;
if (mOnConnectionServiceReadyListener != null) {
mOnConnectionServiceReadyListener
.OnConnectionServiceReady();
}
}
}
public void onServiceDisconnected(ComponentName name) {
synchronized (mStartLock) {
try {
mStarted = false;
mIconnection.unregisterCallback(mPackageName);
mIconnection.shutdown(mPackageName);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in onServiceDisconnected",
e);
}
mIconnection = null;
}
}
};
// Intent intent = new
// Intent("com.google.intent.action.BT_ClickLinkCompete_SERVICE");
Intent intent = new Intent(mContext, ConnectionService.class);
// intent.addCategory("com.google.intent.category.BT_ClickLinkCompete");
mContext.bindService(intent, mServiceConnection,
Context.BIND_AUTO_CREATE);
}
public int startServer(final int maxConnections,
OnIncomingConnectionListener oicListener,
OnMaxConnectionsReachedListener omcrListener,
OnMessageReceivedListener omrListener,
OnConnectionLostListener oclListener) {
if (!mStarted) {
return Connection.FAILURE;
}
if (maxConnections > MAX_SUPPORTED) {
Log.e(TAG, "The maximum number of allowed connections is "
+ MAX_SUPPORTED);
return Connection.FAILURE;
}
mOnIncomingConnectionListener = oicListener;
mOnMaxConnectionsReachedListener = omcrListener;
mOnMessageReceivedListener = omrListener;
mOnConnectionLostListener = oclListener;
try {
int result = mIconnection.startServer(mPackageName, maxConnections);
mIconnection.registerCallback(mPackageName, mIccb);
return result;
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in startServer", e);
}
return Connection.FAILURE;
}
public int connect(String device, OnMessageReceivedListener omrListener,
OnConnectionLostListener oclListener) {
if (!mStarted) {
return Connection.FAILURE;
}
mOnMessageReceivedListener = omrListener;
mOnConnectionLostListener = oclListener;
try {
int result = mIconnection.connect(mPackageName, device);
mIconnection.registerCallback(mPackageName, mIccb);
return result;
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in connect", e);
}
return Connection.FAILURE;
}
public int sendMessage(String device, String message) {
if (!mStarted) {
return Connection.FAILURE;
}
try {
return mIconnection.sendMessage(mPackageName, device, message);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in sendMessage", e);
}
return Connection.FAILURE;
}
public String getConnections() {
if (!mStarted) {
return "";
}
try {
return mIconnection.getConnections(mPackageName);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in getConnections", e);
}
return "";
}
public int getVersioxn() {
if (!mStarted) {
return Connection.FAILURE;
}
try {
return mIconnection.getVersion();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in getVersion", e);
}
return Connection.FAILURE;
}
public String getAddress() {
if (!mStarted) {
return "";
}
try {
return mIconnection.getAddress();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in getAddress", e);
}
return "";
}
public String getName() {
if (!mStarted) {
return "";
}
try {
return mIconnection.getName();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in getVersion", e);
}
return "";
}
public void shutdown() {
try {
mStarted = false;
if (mIconnection != null) {
mIconnection.shutdown(mPackageName);
}
mContext.unbindService(mServiceConnection);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in shutdown", e);
}
}
}
//server
/*
* 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.hao.activity.server;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
import com.hao.activity.IConnection;
import com.hao.activity.IConnectionCallback;
import com.hao.activity.StartDiscoverableModeActivity;
import com.hao.activity.util.FetchData;
/**
* Service for simplifying the process of establishing Bluetooth connections and
* sending data in a way that is geared towards multi-player games.
*/
public class ConnectionService extends Service {
public static final String TAG = "net.clc.bt.ConnectionService";
private ArrayList mUuid;
private ConnectionService mSelf;
private String mApp; // Assume only one app can use this at a time; may
// change this later
FetchData fd = new FetchData();
private IConnectionCallback mCallback;
private ArrayList mBtDeviceAddresses;
private HashMap mBtSockets;
private HashMap mBtStreamWatcherThreads;
private BluetoothAdapter mBtAdapter;
public ConnectionService() {
mSelf = this;
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
mApp = "";
mBtSockets = new HashMap();
mBtDeviceAddresses = new ArrayList();
mBtStreamWatcherThreads = new HashMap();
mUuid = new ArrayList();
mUuid.add(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
mUuid.add(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
/*
* mUuid.add(UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666"));
* mUuid.add(UUID.fromString("503c7430-bc23-11de-8a39-0800200c9a66"));
* mUuid.add(UUID.fromString("503c7431-bc23-11de-8a39-0800200c9a66"));
* mUuid.add(UUID.fromString("503c7432-bc23-11de-8a39-0800200c9a66"));
* mUuid.add(UUID.fromString("503c7433-bc23-11de-8a39-0800200c9a66"));
* mUuid.add(UUID.fromString("503c7434-bc23-11de-8a39-0800200c9a66"));
* mUuid.add(UUID.fromString("503c7435-bc23-11de-8a39-0800200c9a66"));
*/
}
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
private class BtStreamWatcher implements Runnable {
private String address;
public BtStreamWatcher(String deviceAddress) {
address = deviceAddress;
}
public void run() {
BluetoothSocket bSock = mBtSockets.get(address);
try {
InputStream instream = bSock.getInputStream();
String message = "";
BufferedReader bufferedReader;
while (true) {
message = "";
if (instream.available() > 0) {
bufferedReader = new BufferedReader(
new InputStreamReader(instream));
if ((message = bufferedReader.readLine()) != null) {
Thread.sleep(0);
mCallback.messageReceived(address, message);
}
}
}
} catch (IOException e) {
Log
.i(
TAG,
"IOException in BtStreamWatcher - probably caused by normal disconnection",
e);
} catch (RemoteException e) {
Log
.e(
TAG,
"RemoteException in BtStreamWatcher while reading data",
e);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Getting out of the while loop means the connection is dead.
try {
mBtDeviceAddresses.remove(address);
mBtSockets.remove(address);
mBtStreamWatcherThreads.remove(address);
mCallback.connectionLost(address);
} catch (RemoteException e) {
Log
.e(
TAG,
"RemoteException in BtStreamWatcher while disconnecting",
e);
}
}
}
private class ConnectionWaiter implements Runnable {
private String srcApp;
private int maxConnections;
public ConnectionWaiter(String theApp, int connections) {
srcApp = theApp;
maxConnections = connections;
}
public void run() {
try {
for (int i = 0; i < Connection.MAX_SUPPORTED
&& maxConnections > 0; i++) {
BluetoothServerSocket myServerSocket = mBtAdapter
.listenUsingRfcommWithServiceRecord(srcApp, mUuid
.get(i));
BluetoothSocket myBSock = myServerSocket.accept();
myServerSocket.close(); // Close the socket now that the
// connection has been made.
String address = myBSock.getRemoteDevice().getAddress();
mBtSockets.put(address, myBSock);
mBtDeviceAddresses.add(address);
Thread mBtStreamWatcherThread = new Thread(
new BtStreamWatcher(address));
mBtStreamWatcherThread.start();
mBtStreamWatcherThreads
.put(address, mBtStreamWatcherThread);
maxConnections = maxConnections - 1;
if (mCallback != null) {
mCallback.incomingConnection(address);
}
}
if (mCallback != null) {
mCallback.maxConnectionsReached();
}
} catch (IOException e) {
Log.i(TAG, "IOException in ConnectionService:ConnectionWaiter",
e);
} catch (RemoteException e) {
Log
.e(
TAG,
"RemoteException in ConnectionService:ConnectionWaiter",
e);
}
}
}
private BluetoothSocket getConnectedSocket(BluetoothDevice myBtServer,
UUID uuidToTry) {
BluetoothSocket myBSock;
try {
myBSock = myBtServer.createRfcommSocketToServiceRecord(uuidToTry);
myBSock.connect();
return myBSock;
} catch (IOException e) {
Log.i(TAG, "IOException in getConnectedSocket", e);
}
return null;
}
private final IConnection.Stub mBinder = new IConnection.Stub() {
public int startServer(String srcApp, int maxConnections)
throws RemoteException {
if (mApp.length() > 0) {
return Connection.FAILURE;
}
mApp = srcApp;
(new Thread(new ConnectionWaiter(srcApp, maxConnections))).start();
Intent i = new Intent();
i.setClass(mSelf, StartDiscoverableModeActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
return Connection.SUCCESS;
}
public int connect(String srcApp, String device) throws RemoteException {
if (mApp.length() > 0) {
return Connection.FAILURE;
}
mApp = srcApp;
BluetoothDevice myBtServer = mBtAdapter.getRemoteDevice(device);
BluetoothSocket myBSock = null;
for (int i = 0; i < Connection.MAX_SUPPORTED && myBSock == null; i++) {
for (int j = 0; j < 3 && myBSock == null; j++) {
myBSock = getConnectedSocket(myBtServer, mUuid.get(i));
if (myBSock == null) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Log.e(TAG, "InterruptedException in connect", e);
}
}
}
}
if (myBSock == null) {
return Connection.FAILURE;
}
mBtSockets.put(device, myBSock);
mBtDeviceAddresses.add(device);
Thread mBtStreamWatcherThread = new Thread(new BtStreamWatcher(
device));
mBtStreamWatcherThread.start();
mBtStreamWatcherThreads.put(device, mBtStreamWatcherThread);
return Connection.SUCCESS;
}
public int broadcastMessage(String srcApp, String message)
throws RemoteException {
if (!mApp.equals(srcApp)) {
return Connection.FAILURE;
}
for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
sendMessage(srcApp, mBtDeviceAddresses.get(i), message);
}
return Connection.SUCCESS;
}
public String getConnections(String srcApp) throws RemoteException {
if (!mApp.equals(srcApp)) {
return "";
}
String connections = "";
for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
connections = connections + mBtDeviceAddresses.get(i) + ",";
}
return connections;
}
public int getVersion() throws RemoteException {
try {
PackageManager pm = mSelf.getPackageManager();
PackageInfo pInfo = pm
.getPackageInfo(mSelf.getPackageName(), 0);
return pInfo.versionCode;
} catch (NameNotFoundException e) {
Log.e(TAG, "NameNotFoundException in getVersion", e);
}
return 0;
}
public int registerCallback(String srcApp, IConnectionCallback cb)
throws RemoteException {
if (!mApp.equals(srcApp)) {
return Connection.FAILURE;
}
mCallback = cb;
return Connection.SUCCESS;
}
public int sendMessage(String srcApp, String destination, String message)
throws RemoteException {
if (!mApp.equals(srcApp)) {
return Connection.FAILURE;
}
try {
BluetoothSocket myBsock = mBtSockets.get(destination);
if (myBsock != null) {
OutputStream outStream = myBsock.getOutputStream();
byte[] stringAsBytes = (message + " ").getBytes();
stringAsBytes[stringAsBytes.length - 1] = 0; // Add a stop
// marker
outStream.write(stringAsBytes);
return Connection.SUCCESS;
}
} catch (IOException e) {
Log.i(TAG, "IOException in sendMessage - Dest:" + destination
+ ", Msg:" + message, e);
}
return Connection.FAILURE;
}
public void shutdown(String srcApp) throws RemoteException {
try {
for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
BluetoothSocket myBsock = mBtSockets.get(mBtDeviceAddresses
.get(i));
myBsock.close();
}
mBtSockets = new HashMap();
mBtStreamWatcherThreads = new HashMap();
mBtDeviceAddresses = new ArrayList();
mApp = "";
} catch (IOException e) {
Log.i(TAG, "IOException in shutdown", e);
}
}
public int unregisterCallback(String srcApp) throws RemoteException {
if (!mApp.equals(srcApp)) {
return Connection.FAILURE;
}
mCallback = null;
return Connection.SUCCESS;
}
public String getAddress() throws RemoteException {
return mBtAdapter.getAddress();
}
public String getName() throws RemoteException {
return mBtAdapter.getName();
}
};
}
//两个aidl文件
/*
* 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.
*/
/**
* AIDL for the Bluetooth Connect, Link, Compete Service
* IConnection.java is autogenerated from this
*/
package com.hao.activity;
// TODO: Ideally, we would import BluetoothDevice here
// and use that instead of just a String in the connect
// method for better type safety, but this is currently
// not possible yet.
import com.hao.activity.IConnectionCallback;
// Declare the interface.
interface IConnection {
String getAddress();
String getName();
int startServer(in String srcApp, in int maxConnections);
int connect(in String srcApp, in String device);
int sendMessage(in String srcApp, in String device, in String message);
int broadcastMessage(in String srcApp, in String message);
String getConnections(in String srcApp);
int getVersion();
int registerCallback(in String srcApp, IConnectionCallback cb);
int unregisterCallback(in String srcApp);
void shutdown(in String srcApp);
}
/*
* 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.
*/
/**
* AIDL for the Bluetooth Connect, Link, Compete Service
* IConnectionCallback.java is autogenerated from this
*/
package com.hao.activity;
// Declare the interface.
oneway interface IConnectionCallback {
void incomingConnection(String device);
void maxConnectionsReached();
void messageReceived(String device, String message);
void connectionLost(String device);
}