我有一个奇怪的问题。我已经失去了很多时间试图理解 并解决这个问题,但没有任何作用。
我有一个应用程序通过蓝牙连接与另一台设备通信 接收一些传感器数据。在这一点上,一切正常,我可以连接 到设备,接收和处理消息。
但昨天,我决定创建某种日志文件直接保存在 内部存储器从设备接收的数据,没有从我的应用程序进行任何转换。
要从设备接收数据,我有一个后台话题:
public class CommunicationThread extends Thread {
private static final UUID UUID_DEVICE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static final String TAG = CommunicationThread.class.getSimpleName();
private CommunicationListener mListener;
private boolean mRunning;
private BluetoothSocket mBluetoothSocket;
private InputStream mInputStream;
private OutputStream mOutputStream;
public interface CommunicationListener {
void onMessageReceived(String msg);
}
public CommunicationThread(
@NonNull BluetoothDevice device,
@Nullable CommunicationListener listener) throws IOException {
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID_DEVICE);
socket.connect();
this.mBluetoothSocket = socket;
this.mInputStream = socket.getInputStream();
this.mOutputStream = socket.getOutputStream();
this.mListener = listener;
}
@Override
public void run() {
mRunning = true;
byte[] bytes = new byte[1024];
int length;
while (mRunning) {
try {
Log.d(TAG, "Waiting for message");
// read the message (block until receive)
length = mInputStream.read(bytes);
String msg = new String(bytes, 0, length);
Log.d(TAG, "Message: " + msg);
// Message received, inform the listener
if (mListener != null)
mListener.onMessageReceived(msg);
} catch (Exception e) {
Log.e(TAG, "Error reading the message", e);
}
}
}
public void sendCommand(String msg) {
try {
mOutputStream.write((msg).getBytes());
} catch (Exception e) {
Log.e(TAG, "Error to send message", e);
}
}
public void stopCommunication() {
mRunning = false;
mListener = null;
try {
if (mBluetoothSocket != null) {
mBluetoothSocket.close();
}
if (mInputStream != null) {
mInputStream.close();
}
if (mOutputStream != null) {
mOutputStream.close();
}
} catch (IOException e) {
Log.e(TAG, "Error to stop communication", e);
}
}
}
这个线程运行得很好,当收到一条消息时,它会通知监听器, 我的Controller类。当消息传来时,我尝试做的第一件事就是保存它:
public class Controller implements CommunicationThread.CommunicationListener
...
@Override
public void onMessageReceived(final String msg) {
Log.d(TAG, "onMessageReceived(msg): " + msg);
mLogCreator.saveThis(msg);
....
}
}
这是LogCreator类:
public class LogCreator {
private static final String TAG = LogCreator.class.getSimpleName();
public static final String LOG_FILE_NAME = "log.txt";
private final Context mContext;
private volatile String mTempFullLog;
public LogCreator(Context context) {
mContext = context.getApplicationContext();
File dir = new File(mContext.getFilesDir(), "log_folder");
if (!dir.exists()) {
dir.mkdirs();
File file = new File(dir, LOG_FILE_NAME);
writeString(file, "");
Log.d(TAG, "empty file created");
}
}
public void saveThis(final String data) {
mTempFullLog += "\n" + data;
Log.d(TAG, "New log: " + data);
}
public void start() {
File dir = new File(mContext.getFilesDir(), "log_folder");
File file = new File(dir, LOG_FILE_NAME);
mTempFullLog = readString(file);
Log.d(TAG, "File: " + file);
Log.d(TAG, "Temp full log: " + mTempFullLog);
}
public void stop() {
File dir = new File(mContext.getFilesDir(), "log_folder");
File file = new File(dir, LOG_FILE_NAME);
writeString(file, mTempFullLog);
Log.d(TAG, "log saved: " + mTempFullLog);
}
}
LogCreator类已经初始化,它可以正常工作,因为 如果我稍后尝试阅读该文件,那么一切都在那里。
真正的问题如下:在此期间有很多对Log.d的调用 这个执行流程,这让我很容易理解所有的过程。 但是,日志只会打印在logcat中,直到此Log.d调用为止 CommunicationThread类:
Log.d(TAG, "Waiting for message);
收到消息后,所有代码都正常执行,但没有打印日志 logcat,我真的不知道为什么。
日志未打印:
CommunicationThread:
Log.d(TAG, "Message: " + msg);
控制器:
Log.d(TAG, "onMessageReceived(msg): " + msg);
LogCreator:
Log.d(TAG, "New log: " + data);
就像我说的那样,我知道一切都正常,因为日志 即使没有logcat打印,也会在内部存储器中创建文件。它花了我 几个小时才意识到问题只出现在日志中而不是真正存在 我的代码。
出于测试目的,如果我在LogCreator的saveThis方法中添加此代码, 它正常执行:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, data, Toast.LENGTH_SHORT).show();
}
});
这让我觉得一切都可能是线程问题,因为一开始 LogCreator的stop方法都是从主线程而不是CommunicationThread调用的,两种方法都打印了日志。因此,在onMessageReceived方法中 在Controller类中,我尝试了这个:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
mLogCreator.saveThis(msg);
}
});
但是,不幸的是,日志不会在logcat中打印出来。吐司还在 已执行,数据仍保存到文件中。
如果有人知道可能导致这种情况的原因,我真的很想知道,谢谢。
答案 0 :(得分:0)
我终于找到了解决方案。以下不起作用的原因对我来说并不清楚,IMO它应该被视为一个bug。
我在调试模式下编译应用程序并发现从设备收到的字符串有一个" \ r"最后。
示例:"15.50\r"
所以,出于一些奇怪的原因,如果我尝试这样做:
Log.d(TAG, "New log: " + data);
什么都没打印,我们根本没有收到任何警告。
但是,如果我这样做:
Log.d(TAG, "New log: " + data.replace("\r", ""));
数据位于: "15.50\r"
一切正常,logcat打印消息。