Android静态方法可以很好地实时绘制背景线程数据,但这是一个好的解决方案吗?
我一直在问一系列关于我的Android项目的问题,该项目持续实时绘制蓝牙数据。我在提问方面做得不是很好 所以我需要做的是编辑这个问题,清理它,添加重要的细节,最重要的是,我需要添加相关代码部分的代码片段,特别是我已经黑客攻击过的部分,并提供关于这些代码部分的解释。这样,我可能会得到我的问题/顾虑的答案,即:我当前的解决方案是否可行?当我添加新功能时,它会持续吗 基本上,我已经做的是通过拼凑一些开放源代码和代码来创建我的应用程序的第一个版本 有人建议我添加一个线程、一个处理程序、一个服务,或者使用异步任务或AIDL等等。但是我决定不想修改或替换现有的解决方案,除非我真的应该这样做。我主要想知道它是否足够好,可以向前发展,并扩展它以添加其他功能 顺便说一下,我之前提到的蓝牙数据就是蓝牙数据:它是从远程蓝牙设备以每秒2到10个采样的速率接收的16位数据。我的应用程序基本上是一个数据采集系统,它采集/接收蓝牙数据并绘制数据 下面是我开始使用的Blueterm开源代码的描述(参见上面的链接)。Blueterm基本上是一个通过蓝牙进行通信的终端仿真器程序。它包括几个活动,其中Blueterm是最重要的。它发现、配对并连接支持SPP/RfComm的远程蓝牙设备。连接后,我可以使用Blueterm通过发送命令来配置远程设备,以打开采样、更改要采样的通道数(更改为一个通道)、更改输入数据的格式(我喜欢逗号分隔的数据)等 下面是我开始使用的OrientionSensoreSample开放源代码的描述(参见上面的链接)。它基本上是AnroidPlot库的一个示例应用程序。方向传感器活动实现SensorEventListener。这包括覆盖onSenorChanged(),在获取新的方向传感器数据时调用该函数,并重新绘制图形 在将这两个开源项目(Blueterm和OrientionSensoreSample)拼凑成一个应用程序(Blueterm)之后,下面是对整个应用程序(Blueterm)工作方式的描述。当我启动Blueterm时,整个屏幕模拟一个漂亮的蓝色终端。从“选项”菜单中,我发现、配对、连接和配置远程蓝牙设备,如上所述。配置远程设备后,我再次进入选项菜单并选择“绘图数据”,启动绘图活动。终端模拟器消失了,plot活动中的一个漂亮的滚动实时绘图显示出来 我是这样做的。在OnOptions ItemSelected()中,我添加了一个案例来启动绘图活动,如下所示:Android静态方法可以很好地实时绘制背景线程数据,但这是一个好的解决方案吗?,android,multithreading,static,android-activity,real-time,Android,Multithreading,Static,Android Activity,Real Time,我一直在问一系列关于我的Android项目的问题,该项目持续实时绘制蓝牙数据。我在提问方面做得不是很好 所以我需要做的是编辑这个问题,清理它,添加重要的细节,最重要的是,我需要添加相关代码部分的代码片段,特别是我已经黑客攻击过的部分,并提供关于这些代码部分的解释。这样,我可能会得到我的问题/顾虑的答案,即:我当前的解决方案是否可行?当我添加新功能时,它会持续吗 基本上,我已经做的是通过拼凑一些开放源代码和代码来创建我的应用程序的第一个版本 有人建议我添加一个线程、一个处理程序、一个服务,或者使用
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.connect:
if (getConnectionState() == BluetoothSerialService.STATE_NONE) {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
else
if (getConnectionState() == BluetoothSerialService.STATE_CONNECTED) {
mSerialService.stop();
mSerialService.start();
}
return true;
case R.id.preferences:
doPreferences();
return true;
case R.id.menu_special_keys:
doDocumentKeys();
return true;
case R.id.plot_data:
doPlotData();
return true;
}
return false;
}
private void doPlotData() {
Intent plot_data = new Intent(this, com.vtrandal.bluesentry.Plot.class);
startActivity(plot_data);
}
/**
* 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
//OrientationSensor orientationSensor = new OrientationSensor();
Plot.plotData(mReceiveBuffer, 0, bytesRead);
} catch (InterruptedException e) {
//VTR OMG their swallowing this exception
}
}
然后在bluetooth后台线程中,我添加了一个对update()的调用,以调用plotData(),如下所示:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.connect:
if (getConnectionState() == BluetoothSerialService.STATE_NONE) {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
else
if (getConnectionState() == BluetoothSerialService.STATE_CONNECTED) {
mSerialService.stop();
mSerialService.start();
}
return true;
case R.id.preferences:
doPreferences();
return true;
case R.id.menu_special_keys:
doDocumentKeys();
return true;
case R.id.plot_data:
doPlotData();
return true;
}
return false;
}
private void doPlotData() {
Intent plot_data = new Intent(this, com.vtrandal.bluesentry.Plot.class);
startActivity(plot_data);
}
/**
* 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
//OrientationSensor orientationSensor = new OrientationSensor();
Plot.plotData(mReceiveBuffer, 0, bytesRead);
} catch (InterruptedException e) {
//VTR OMG their swallowing this exception
}
}
然后在Plot活动中,我基本上清理了房间,删除了“implements SensorEventListener”和一些相关的方法和变量,并编写了plotData(),以便如上所示调用。以下是plotData()及其辅助方法splitData()和nowPlotData()当前的外观:
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();
}
private static StringBuffer strData=new StringBuffer(“”);
公共静态无效绘图数据(字节[]缓冲区,整数基,整数长度){
Log.i(“输入:”,“plotData()”;
/*
字节[]缓冲区=(字节[])msg.obj;
int base=msg.arg1;
int length=msg.arg2;
*/
for(int i=0;i126){
可打印B=“”;
}
Log.w(“Log_plotData”,“'”+Character.toString(可打印B)
+“(“+Integer.toString(b)+”);
追加(Character.toString(printableB));
如果(b==10)
{
Log.i(“行尾:”,“processBlueData()”;
Log.i(“strData”,strData.toString());
splitData(strData);
strData=新的StringBuffer(“”);
}
}
}捕获(例外e){
Log.e(“Log\u plotData\u异常”,“处理字符时异常”
+整数.toString(i)+“代码”
+整数。toString(b,e);
}
}
Log.i(“离开:,“plotData()”);
}
私有静态void splitData(StringBuffer strBuf){
字符串strDash=strBuf.toString().trim();
字符串[]strDashSplit=strDash.split(“-”);
对于(int ndx=0;ndx0)
Log.i(“strDashSplit”,ndx+:“+strDashSplit[ndx]);
字符串strComma=strDashSplit[ndx].trim();
字符串[]strCommaSplit=strComma.split(“,”);
for(int-mdx=0;mdx0)
Log.i(“strCommaSplit”,mdx+:“+strCommaSplit[mdx]);
如果(mdx==1)
{
int raw=Integer.parseInt(strCommaSplit[1],16);
Log.i(“raw”,Integer.toString(raw));
float-rawFloat=raw;
Log.i(“rawFloat”,Float.toString(rawFloat));
浮动比率=(浮动)(原始浮动/65535.0);
Log.i(“比率”,Float.toString(比率));
浮动电压=(浮动)(5.0*比率);
Log.i(“电压”,Float.toString(电压));
数据(电压);
}
}
}
}
公共静态无效数据