【发布时间】:2015-06-30 07:54:09
【问题描述】:
我的应用从加速度计读取数据并绘制实时图表。我在模拟器上运行它,它似乎工作正常,但在真正的 android 设备上运行时它响应非常缓慢,该设备是 Samsung GT-S6500 Android 2.3.6 (API 10) .
我的应用程序中有一个启动和停止按钮,两者在模拟器上似乎都可以正常工作,但是当应用程序在上面提到的设备上运行时,启动按钮运行正常,但实时图形移动非常缓慢并挂起停止按钮响应时间变得非常大。 有什么建议吗?
代码如下: MainActivity.java
package com.mycompany.falldetect;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import com.telerik.widget.chart.engine.databinding.DataPointBinding;
import com.telerik.widget.chart.visualization.cartesianChart.RadCartesianChartView;
import com.telerik.widget.chart.visualization.cartesianChart.axes.CategoricalAxis;
import com.telerik.widget.chart.visualization.cartesianChart.axes.LinearAxis;
import com.telerik.widget.chart.visualization.cartesianChart.series.categorical.LineSeries;
import static android.os.Environment.getExternalStorageDirectory;
public class MainActivity extends Activity implements SensorEventListener,
OnClickListener {
private SensorManager SensorManager;
private Sensor mAccelerometer;
private FileWriter writer;
private Button btnStart, btnStop;
private boolean started = false;
private Queue<Data> seismicActivityBuffer;
private List<Data> allSeismicActivity;
private ViewGroup chartContainer;
private RadCartesianChartView chart;
private int bufferSize;
String f = "";
int m = 0;
double prev_xyz = 9.0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = SensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
this.seismicActivityBuffer = new LinkedList<Data>();
this.allSeismicActivity = new ArrayList<Data>();
this.bufferSize = 100;
// Adding points to fill the screen at initial state.
for (int i = -this.bufferSize/1000; i < 0; i++) {
this.seismicActivityBuffer.add(new Data(i, 0, 0, 0));
}
this.chartContainer = (ViewGroup) findViewById(R.id.chart_container);
this.chart = createChart(this.seismicActivityBuffer);
this.chartContainer.addView(this.chart);
btnStart = (Button) findViewById(R.id.btnStart);
btnStop = (Button) findViewById(R.id.btnStop);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
btnStart.setEnabled(true);
btnStop.setEnabled(false);
}
public void onStartClick(View view) {
SensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
public void onStopClick(View view) {
SensorManager.unregisterListener(this);
}
protected void onResume() {
super.onResume();
this.SensorManager.registerListener(this, this.mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
}
protected void onPause() {
super.onPause();
if (started) {
SensorManager.unregisterListener(this);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (started) {
double x = event.values[0];
double y = event.values[1];
double z = event.values[2];
long timestamp = System.nanoTime();
Data point = new Data(timestamp, x, y, z);
//System.out.print("sesor: " + point.getTimestamp() + " " + point.getX() + " " + point.getY() + " " + point.getZ());
// double xyz = Math.round(Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)));
// String s=timestamp+" "+x+" "+y+" "+z+" "+xyz+" \n";
// f+=s;
if (this.seismicActivityBuffer.size() > this.bufferSize) {
this.seismicActivityBuffer.remove();
}
this.seismicActivityBuffer.add(point);
//this.allSeismicActivity.add(point);
this.chartContainer.removeAllViews();
this.chart = createChart(seismicActivityBuffer);
this.chartContainer.addView(chart);
/*if(xyz!=9 && xyz!=10){
String s=timestamp+" "+x+" "+y+" "+z+" "+xyz+" \n";
f+=s;
}*/
//System.out.println("xyz: "+xyz);
/*if(xyz <= 5){
m++;
prev_xyz=xyz;
}
if(Math.abs(prev_xyz-xyz) >= 10 ){
Toast.makeText(getBaseContext(),"FALL DETECTED!",Toast.LENGTH_LONG).show();
f+="FALL DETECTED!\n";
prev_xyz=9;
fall=true;
m=0;
}*/
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnStart:
btnStart.setEnabled(false);
btnStop.setEnabled(true);
// save prev data if available
started = true;
this.chart = createChart(this.allSeismicActivity);
this.chartContainer.addView(this.chart);
break;
case R.id.btnStop:
stop();
break;
default:
break;
}
}
private void stop() {
btnStart.setEnabled(true);
btnStop.setEnabled(false);
started = false;
SensorManager.unregisterListener(this);
chartContainer.removeAllViews();
//openChart();
//createExternalStorageFile(f);
}
private RadCartesianChartView createChart(Iterable<Data> dataPoints) {
RadCartesianChartView chart = new RadCartesianChartView(this);
// create category binding with the X coordinate of the accelerometer point
DataPointBinding categoryBinding = new DataPointBinding() {
@Override
public Object getValue(Object o) throws IllegalArgumentException {
return ((Data) o).getTimestamp();
}
};
// create value binding with the X coordinate of the accelerometer point
DataPointBinding valueBinding_x = new DataPointBinding() {
@Override
public Object getValue(Object o) throws IllegalArgumentException {
return ((Data) o).getX();
}
};
DataPointBinding valueBinding_y = new DataPointBinding() {
@Override
public Object getValue(Object o) throws IllegalArgumentException {
return ((Data) o).getY();
}
};
DataPointBinding valueBinding_z = new DataPointBinding() {
@Override
public Object getValue(Object o) throws IllegalArgumentException {
return ((Data) o).getZ();
}
};
LineSeries series = new LineSeries();
series.setCategoryBinding(categoryBinding);
series.setValueBinding(valueBinding_x);
chart.getSeries().add(series);
series.setData(dataPoints);
LineSeries series2 = new LineSeries();
series2.setCategoryBinding(categoryBinding);
series2.setValueBinding(valueBinding_y);
chart.getSeries().add(series2);
series2.setData(dataPoints);
LineSeries series3 = new LineSeries();
series3.setCategoryBinding(categoryBinding);
series3.setValueBinding(valueBinding_z);
chart.getSeries().add(series3);
series3.setData(dataPoints);
// feed the data to the chart
// configure the vertical axis
LinearAxis vAxis = new LinearAxis();
// The maximum value of the accelerometer is 20 and the minimum -20, so give a bonus 10 to the vertical axis.
vAxis.setMaximum(20);
vAxis.setMinimum(-20);
chart.setVerticalAxis(vAxis);
// configure the horizontal axis
CategoricalAxis hAxis = new CategoricalAxis();
hAxis.setShowLabels(false);
chart.setHorizontalAxis(hAxis);
return chart;
}
void createExternalStorageFile(String a) {
// Create a path where we will place our private file on external
// storage.
File file = new File(getExternalStorageDirectory(), "DemoFile.txt");
try {
// Very simple code to copy a picture from the application's
// resource into the external file. Note that this code does
// no error checking, and assumes the picture is small (does not
// try to copy it in chunks). Note that if external storage is
// not currently mounted this will silently fail.
OutputStream os = new FileOutputStream(file);
os.write(a.getBytes());
os.close();
} catch (IOException e) {
// Unable to create file, likely because external storage is
// not currently mounted.
Log.w("ExternalStorage", "Error writing " + file, e);
}
}
}
这里是 logcat:
07-01 12:15:06.778 3542-3542/?我/艺术:没有后期启用-Xcheck:jni(已经启用)
07-01 12:15:07.284 3542-3554/com.mycompany.falldetect I/art:后台部分并发标记扫描 GC 释放 137(46KB) AllocSpace 对象,0(0B) LOS 对象,43% 空闲,663KB /1175KB,暂停 2.495ms 共 156.875ms
07-01 12:15:07.302 3542-3554/com.mycompany.falldetect W/art:暂停所有线程耗时:17.061ms
07-01 12:15:08.583 3542-3542/com.mycompany.falldetect I/Choreographer: 跳过 120 帧!应用程序可能在其主线程上做了太多工作。
07-01 12:15:08.860 3542-3554/com.mycompany.falldetect I/art:后台粘性并发标记扫描 GC 释放 4193(196KB) AllocSpace 对象,0(0B) LOS 对象,23% 可用,896KB /1175KB,暂停 1.315ms 共 104.895ms
07-01 12:15:09.045 3542-3542/com.mycompany.falldetect I/Choreographer﹕跳过 35 帧!应用程序可能在其主线程上做了太多工作。
07-01 12:15:09.247 3542-3542/com.mycompany.falldetect D/gralloc_goldfish:没有检测到 GPU 仿真的模拟器。
07-01 12:15:09.358 3542-3542/com.mycompany.falldetect I/Choreographer﹕跳过 30 帧!应用程序可能在其主线程上做了太多工作。
07-01 12:15:09.426 3542-3554/com.mycompany.falldetect I/art:后台部分并发标记扫描 GC 释放 291(16KB) AllocSpace 对象,0(0B) LOS 对象,24% 空闲,3MB /5MB,暂停 1.233ms 共 153.762ms
07-01 12:15:09.739 3542-3549/com.mycompany.falldetect W/art:暂停所有线程耗时:19.010ms
07-01 12:15:13.154 3542-3542/com.mycompany.falldetect I/Choreographer﹕跳过 33 帧!应用程序可能在其主线程上做了太多工作。
07-01 12:15:13.516 3542-3542/com.mycompany.falldetect I/Choreographer﹕跳过 36 帧!应用程序可能在其主线程上做了太多工作。
07-01 12:15:13.901 3542-3542/com.mycompany.falldetect I/Choreographer: 跳过了 37 帧!应用程序可能在其主线程上做了太多工作。
07-01 12:15:20.126 3542-3549/com.mycompany.falldetect W/art: 暂停所有线程耗时:51.394ms
07-01 12:15:20.140 3542-3542/com.mycompany.falldetect I/Choreographer﹕跳过 38 帧!应用程序可能在其主线程上做了太多工作。
07-01 12:15:20.585 3542-3549/com.mycompany.falldetect W/art:暂停所有线程耗时:17.665ms
07-01 12:15:20.656 3542-3554/com.mycompany.falldetect I/art:后台粘性并发标记扫描 GC 释放 8627(235KB) AllocSpace 对象,0(0B) LOS 对象,0% 空闲,7MB /7MB,暂停 1.020ms 共 124.402ms
07-01 12:15:22.087 3542-3549/com.mycompany.falldetect W/art:暂停所有线程耗时:27.697ms
07-01 12:15:22.122 3542-3554/com.mycompany.falldetect W/art:暂停所有线程耗时:29.438ms
07-01 12:15:23.703 3542-3554/com.mycompany.falldetect W/art:暂停所有线程耗时:30.292ms
07-01 12:15:24.505 3542-3554/com.mycompany.falldetect I/art:后台部分并发标记扫描 GC 释放 1195(43KB) AllocSpace 对象,1(3MB) LOS 对象,25% 空闲,3MB /5MB,暂停 1.126ms 共 116.397ms
07-01 12:15:25.263 3542-3554/com.mycompany.falldetect W/art:暂停所有线程耗时:38.968ms
07-01 12:18:45.820 3542-3554/com.mycompany.falldetect I/art:后台部分并发标记扫描 GC 释放 1244(45KB) AllocSpace 对象,1(3MB) LOS 对象,25% 空闲,3MB /5MB,暂停 31.610ms 共 38.187ms
【问题讨论】:
-
您可能想在这个问题中添加一些可重现的代码。
-
不要费心在模拟器上测试它。模拟器没有真正的加速度计。确保您使用线程并且仅每秒轮询一次数据。如果这些解决方案都不起作用,edit 你的问题是在其中发布你的代码并发布你的 logcat。此外,请确保数据在累积时被删除/清理/汇总。
-
@StephanBranczyk 我已经添加了代码,我认为不需要 logcat,因为没有错误。
-
@StephanBranczyk 也添加了 logcat。请回复:)
-
@Henrik 已添加代码和 logcat。
标签: android graph real-time accelerometer