我在 Android 应用程序中创建了一个蓝牙 Activity 类,它适用于所有蓝牙功能,例如:扫描、配对、连接、发送和接收数据。
真正的问题是当 Activity 被销毁时。蓝牙正在断开连接。
如何在整个应用程序中建立蓝牙连接。我想从其他 Activity 向蓝牙发送数据。
帮助我以一种简单的方式实现它?
public class BTActivity extends AppCompatActivity {
ArrayList<BluetoothDevice> devices = new ArrayList<>();
BluetoothAdapter mBluetoothAdapter;
BluetoothDevice mBluetoothDevice;
ArrayAdapter<BluetoothDevice> arrayAdapter;
ConnectThread c;
private static final String TAG = "MY_BT";
ListView lvPaired;
Button BluetoothOnOff, ScanBt, pairedlist, sendButton, btDisconnect, incrementBtn, decrementBtn;
EditText input_text;
TextView ConnectedTo;
FragmentManager fm = getSupportFragmentManager();
UUID BHANU_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bt);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
lvPaired = findViewById(R.id.btPairedLV);
pairedlist = findViewById(R.id.btPaired);
input_text = findViewById(R.id.user_input);
sendButton = findViewById(R.id.btnSend);
BluetoothOnOff = findViewById(R.id.offOn_bt);
ScanBt = findViewById(R.id.scan_bt);
ConnectedTo = findViewById(R.id.current_connected_bluetooth);
btDisconnect = findViewById(R.id.bt_disconnect);
incrementBtn = findViewById(R.id.incrementBtn);
decrementBtn = findViewById(R.id.decrementBtn);
onClickListener();
pairedList();
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(mReceiver, filter);
}
public void onClickListener(){
pairedlist.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (arrayAdapter != null){
arrayAdapter.clear();
}
pairedList();
}
});
lvPaired.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
BluetoothDevice device = (BluetoothDevice) parent.getItemAtPosition(position);
c = new ConnectThread(device, true);
c.start();
}
});
sendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String text = input_text.getText().toString();
c.sendData(text);
input_text.setText("");
}
});
BluetoothOnOff.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.enable();
BluetoothOnOff.setText("ON");
}else {
mBluetoothAdapter.disable();
BluetoothOnOff.setText("OFF");
}
}
});
ScanBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ScanFragment scanFragment = new ScanFragment();
scanFragment.show(fm,"ScanBT");
//ScanFragment scanFragment = new ScanFragment();
//scanFragment.show(fm,"Scan Fragment");
}
});
btDisconnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
c.cancel();
}
});
incrementBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
c.sendData("a");
}
});
decrementBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
c.sendData("b");
}
});
}
public void toast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
public void pairedList() {
//arrayAdapter.clear();
devices.addAll(mBluetoothAdapter.getBondedDevices());
arrayAdapter = new ArrayAdapter<BluetoothDevice>(this, android.R.layout.simple_list_item_1,android.R.id.text1, devices);
lvPaired.setAdapter(arrayAdapter);
arrayAdapter.notifyDataSetChanged();
}
BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
toast("connected");
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
ConnectedTo.setText(device.getName());
btDisconnect.setVisibility(View.VISIBLE);
//getActionBar().setSubtitle(device.getName());
Log.d("BT", "connected to");
} else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
toast("disconnected");
ConnectedTo.setText("None");
btDisconnect.setVisibility(View.INVISIBLE);
// getActionBar().setSubtitle("");
Log.d("BT", "disconnected");
}
}
};
public class ConnectThread extends Thread {
BluetoothDevice cDevice;
BluetoothSocket socket;
ConnectedThread ct;
ConnectThread(BluetoothDevice device, boolean insecureConnection) {
cDevice = device;
try {
if (insecureConnection) {
socket = device.createInsecureRfcommSocketToServiceRecord(BHANU_UUID);
} else {
socket = device.createRfcommSocketToServiceRecord(BHANU_UUID);
}
} catch (IOException e) {
e.getMessage();
}
}
public void run() {
mBluetoothAdapter.cancelDiscovery();
try {
Log.d("BT", "Socket ready to connect");
socket.connect();
Log.d("BT", "Socket connected");
// out = socket.getOutputStream();
// input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (final IOException e) {
e.getMessage();
}
ct = new ConnectedThread(socket);
//ct.write("Q-smart".getBytes());
/*try {
socket.close();
} catch (final IOException closeException) {
closeException.getMessage();
}*/
}
private void sendData(String message){
Log.d(TAG,message);
if (socket != null){
ct.write(message.getBytes());
}else {
toast("Please connect to bluetooth first");
}
}
public void cancel() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams; using temp objects because
// member streams are final.
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating input stream", e);
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating output stream", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
numBytes = mmInStream.read(mmBuffer);
// Send the obtained bytes to the UI activity.
/* Message readMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1,
mmBuffer);
readMsg.sendToTarget();*/
} catch (IOException e) {
Log.d(TAG, "Input stream was disconnected", e);
break;
}
}
}
// Call this from the main activity to send data to the remote device.
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
// Share the sent message with the UI activity.
/* Message writtenMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
writtenMsg.sendToTarget();*/
} catch (IOException e) {
Log.e(TAG, "Error occurred when sending data", e);
// Send a failure message back to the activity.
/* Message writeErrorMsg =
mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString("toast",
"Couldn't send data to the other device");
writeErrorMsg.setData(bundle);
mHandler.sendMessage(writeErrorMsg);*/
}
}
}
}
最佳答案
是的,我找到了一个在 Android 中运行蓝牙后台的可行解决方案。 以下是我在我的 Android 应用程序中使用的代码。
public class BluetoothServices extends Service {
private BluetoothAdapter mBluetoothAdapter;
public static final String B_DEVICE = "MY DEVICE";
public static final String B_UUID = "00001101-0000-1000-8000-00805f9b34fb";
// 00000000-0000-1000-8000-00805f9b34fb
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 ConnectBtThread mConnectThread;
private static ConnectedBtThread mConnectedThread;
private static Handler mHandler = null;
public static int mState = STATE_NONE;
public static String deviceName;
public static BluetoothDevice sDevice = null;
public Vector<Byte> packData = new Vector<>(2048);
//IBinder mIBinder = new LocalBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
//mHandler = getApplication().getHandler();
return mBinder;
}
public void toast(String mess){
Toast.makeText(this,mess,Toast.LENGTH_SHORT).show();
}
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
BluetoothServices getService() {
// Return this instance of LocalService so clients can call public methods
return BluetoothServices.this;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String deviceg = intent.getStringExtra("bluetooth_device");
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
connectToDevice(deviceg);
return START_STICKY;
}
private synchronized void connectToDevice(String macAddress){
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
if (mState == STATE_CONNECTING){
if (mConnectThread != null){
mConnectThread.cancel();
mConnectThread = null;
}
}
if (mConnectedThread != null){
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectThread = new ConnectBtThread(device);
toast("connecting");
mConnectThread.start();
setState(STATE_CONNECTING);
}
private void setState(int state){
mState = state;
if (mHandler != null){
// mHandler.obtainMessage();
}
}
public synchronized void stop(){
setState(STATE_NONE);
if (mConnectThread != null){
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null){
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mBluetoothAdapter != null){
mBluetoothAdapter.cancelDiscovery();
}
stopSelf();
}
public void sendData(String message){
if (mConnectedThread!= null){
mConnectedThread.write(message.getBytes());
toast("sent data");
}else {
Toast.makeText(BluetoothServices.this,"Failed to send data",Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean stopService(Intent name) {
setState(STATE_NONE);
if (mConnectThread != null){
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null){
mConnectedThread.cancel();
mConnectedThread = null;
}
mBluetoothAdapter.cancelDiscovery();
return super.stopService(name);
}
/*private synchronized void connected(BluetoothSocket mmSocket){
if (mConnectThread != null){
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null){
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectedThread = new ConnectedBtThread(mmSocket);
mConnectedThread.start();
setState(STATE_CONNECTED);
}*/
private class ConnectBtThread extends Thread{
private final BluetoothSocket mSocket;
private final BluetoothDevice mDevice;
public ConnectBtThread(BluetoothDevice device){
mDevice = device;
BluetoothSocket socket = null;
try {
socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(B_UUID));
} catch (IOException e) {
e.printStackTrace();
}
mSocket = socket;
}
@Override
public void run() {
mBluetoothAdapter.cancelDiscovery();
try {
mSocket.connect();
Log.d("service","connect thread run method (connected)");
SharedPreferences pre = getSharedPreferences("BT_NAME",0);
pre.edit().putString("bluetooth_connected",mDevice.getName()).apply();
} catch (IOException e) {
try {
mSocket.close();
Log.d("service","connect thread run method ( close function)");
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
//connected(mSocket);
mConnectedThread = new ConnectedBtThread(mSocket);
mConnectedThread.start();
}
public void cancel(){
try {
mSocket.close();
Log.d("service","connect thread cancel method");
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class ConnectedBtThread extends Thread{
private final BluetoothSocket cSocket;
private final InputStream inS;
private final OutputStream outS;
private byte[] buffer;
public ConnectedBtThread(BluetoothSocket socket){
cSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
inS = tmpIn;
outS = tmpOut;
}
@Override
public void run() {
buffer = new byte[1024];
int mByte;
try {
mByte= inS.read(buffer);
} catch (IOException e) {
e.printStackTrace();
}
Log.d("service","connected thread run method");
}
public void write(byte[] buff){
try {
outS.write(buff);
} catch (IOException e) {
e.printStackTrace();
}
}
private void cancel(){
try {
cSocket.close();
Log.d("service","connected thread cancel method");
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onDestroy() {
this.stop();
super.onDestroy();
}
}
关于android - 如何保持蓝牙连接后台?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49729452/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我有一大串格式化数据(例如JSON),我想使用Psychinruby同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解