我一直在询问有关我的Android项目的问题,该项目会不断地实时绘制蓝牙数据。
基本上我已经完成的工作是通过拼凑一些开源代码Blueterm和OrientationSensorExample
来创建我的应用的第一个版本有人建议我添加一个线程,一个处理程序,一个服务,或使用异步任务,或AIDL等。但我不知道如何使用这些,并希望得到解释。
以下是我开始使用的Blueterm开源代码的说明(参见上面的链接)。 Blueterm基本上是一个通过蓝牙进行通信的终端仿真器程序。它由几项活动组成,Blueterm是最重要的。它发现,配对并连接支持SPP / RfComm的远程蓝牙设备。连接后,我可以使用Blueterm配置远程设备,通过发送命令打开采样,更改要采样的通道数(到一个通道),更改为传入数据的格式(我喜欢逗号分隔数据)等< / p>
以下是我开始使用的OrientationSensorExample开源代码的说明(参见上面的链接)。它基本上是AnroidPlot库的一个示例应用程序。 OrientationSensor活动实现SensorEventListener。这包括重写onSenorChanged(),每当获取新的方向传感器数据时调用它,并重绘图形。
将这两个开源项目(Blueterm和OrientationSensorExample)拼凑成一个应用程序(Blueterm),这里描述了整个应用程序(Blueterm)的工作原理。当我启动Blueterm时,整个屏幕模拟一个漂亮的蓝色终端。从选项菜单中我发现,配对,连接和配置远程蓝牙设备,如上所述。配置好远程设备后,再次进入选项菜单,选择“绘图数据”,启动绘图活动。终端模拟器消失了,Plot活动中出现了一个很好的滚动实时图。
据我所知,有一个后台线程调用update()方法,如下所示:
/**
* Look for new input from the ptty, send it to the terminal emulator.
*/
private void update() {
int bytesAvailable = mByteQueue.getBytesAvailable();
int bytesToRead = Math.min(bytesAvailable, mReceiveBuffer.length);
try {
int bytesRead = mByteQueue.read(mReceiveBuffer, 0, bytesToRead);
append(mReceiveBuffer, 0, bytesRead);
//VTR use existing handler that calls update() to get data into plotting activity
Plot.plotData(mReceiveBuffer, 0, bytesRead);
} catch (InterruptedException e) {
//VTR OMG their swallowing this exception
}
}
在update()方法中,我发现调用我的Plot.plotData()方法并将其传递给传递给append()方法的相同日期来绘制数据很方便。注意:这仅在plotData()是静态方法时有效。没有人能够解释原因。
无论如何,plotData()是一个静态方法,以下是它和它的辅助方法现在的样子:
private static StringBuffer strData = new StringBuffer("");
public static void plotData(byte[] buffer, int base, int length) {
Log.i("Entering: ", "plotData()");
/*
byte[] buffer = (byte[]) msg.obj;
int base = msg.arg1;
int length = msg.arg2;
*/
for (int i = 0; i < length; i++) {
byte b = buffer[base + i];
try {
if (true) {
char printableB = (char) b;
if (b < 32 || b > 126) {
printableB = ' ';
}
Log.w("Log_plotData", "'" + Character.toString(printableB)
+ "' (" + Integer.toString(b) + ")");
strData.append(Character.toString(printableB));
if (b == 10)
{
Log.i("End of line: ", "processBlueData()");
Log.i("strData", strData.toString());
splitData(strData);
strData = new StringBuffer("");
}
}
} catch (Exception e) {
Log.e("Log_plotData_exception", "Exception while processing character "
+ Integer.toString(i) + " code "
+ Integer.toString(b), e);
}
}
Log.i("Leaving: ", "plotData()");
}
private static void splitData(StringBuffer strBuf) {
String strDash = strBuf.toString().trim();
String[] strDashSplit = strDash.split("-");
for (int ndx = 0; ndx < strDashSplit.length; ndx++)
{
if (strDashSplit[ndx].length() > 0)
Log.i("strDashSplit", ndx + ":" + strDashSplit[ndx]);
String strComma = strDashSplit[ndx].trim();
String[] strCommaSplit = strComma.split(",");
for (int mdx = 0; mdx < strCommaSplit.length; mdx++)
{
if (strCommaSplit[mdx].length() > 0)
Log.i("strCommaSplit", mdx + ":" + strCommaSplit[mdx]);
if (mdx == 1)
{
int raw = Integer.parseInt(strCommaSplit[1],16);
Log.i("raw", Integer.toString(raw));
float rawFloat = raw;
Log.i("rawFloat", Float.toString(rawFloat));
float ratio = (float) (rawFloat/65535.0);
Log.i("ratio", Float.toString(ratio));
float voltage = (float) (5.0*ratio);
Log.i("voltage", Float.toString(voltage));
nowPlotData(voltage);
}
}
}
}
public static void nowPlotData(float data) {
// get rid the oldest sample in history:
if (plotHistory.size() > HISTORY_SIZE) {
plotHistory.removeFirst();
}
// add the latest history sample:
plotHistory.addLast(data);
// update the plot with the updated history Lists:
plotHistorySeries.setModel(plotHistory, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
//VTR null pointer exception?
if (plotHistoryPlot == null)
Log.i("aprHistoryPlot", "null pointer exception");
// redraw the Plots:
plotHistoryPlot.redraw();
}
如果强烈建议plotData()不是静态方法,我应该做其他事情,请在这里解释一下。谢谢!
答案 0 :(得分:2)
这可能是一个更适合Code Review的问题,而不是在这里。也许你可以重新拟定在那里发布它,或者修改它以便在这里重新发布它。
此外,回答:“有人建议我添加一个线程,一个处理程序,一个服务,或使用异步任务,或AIDL等。但我不知道如何使用任何这些,并希望解释。“,最好的建议是将你链接到一本关于android的书,例如:http://commonsware.com/Android/。第35章和第36章涉及服务,第20章涉及线程。你永远不会得到像这里章节那样完整的答案。