編輯:關於Android編程
AChartEngine是一個很強大的圖表引擎,我在上學的時候就接觸過,並且利用它做了一個傳感器的應用,想想現在也很久遠了,今天就把這個app的源碼貼出來供其他人研究這款引擎。
app的效果如下:

github項目地址:https://github.com/AlexZhuo/SensorMonitor
此APP的主要特性如下:
1、支持手機傳感器數量探測,支持加速度,磁場,距離等傳感器數據的實時獲取
2、使用了一些github上的第三方控件來美化UI,
3、支持全屏顯示
4、通過舊版的xUtils 2實現了數據庫實時記錄
5、通過POI來將數據庫的數據導出為excel,方便以後分析。
AChartEngine根據事先准備好的數據進行繪圖,也就是說是一幀一幀的進行繪制,如果我們想動態生成波浪圖並讓坐標軸隨之移動其實也不難,只需要隔一段時間在舊數據上添加數據並刷新一下view即可。
想要在項目中使用這個圖標引擎,AChartEngine的jar包的下載地址:
http://repository-achartengine.forge.cloudbees.com/snapshot/org/achartengine/achartengine/1.2.0/
注意版本,以後說不定還會出新版。
下面把控制繪圖的代碼貼一下,原理其實不是很復雜,github上有全部app的代碼,如果你喜歡也可以在原來基礎上幫我完善一下(學生時代第一個上線項目,想想還有點小激動)。
import java.util.List;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint.Align;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.lidroid.xutils.DbUtils;
import com.lidroid.xutils.db.sqlite.Selector;
import com.lidroid.xutils.exception.DbException;
import com.situ.model.Accelerate_info;
public class AccelActivity extends Activity{
public SensorManager sensorManager;
public Sensor accelSensor ;
TextView xText ;
TextView yText ;
TextView zText ;
TextView sumText;
TextView danWei ;
TextView title;
private Vibrator vibrator;
SensorEventListener threeParamListener;
SensorEventListener oneParamListener;
SensorEventListener twoParamListener;
Handler avgHandler;
Thread avgThread;
int sensor_id = 0;
//圖表相關
private XYSeries series;
private XYMultipleSeriesDataset mDataset;
private GraphicalView chart;
private XYMultipleSeriesRenderer renderer;
private Context context;
private int yMax = 20;//y軸最大值,根據不同傳感器變化
private int xMax = 100;//一屏顯示測量次數
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_accel);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
avgHandler = new AveHandler();
//給控件實例化
if(xText==null){
findViews();
}
Intent intent = getIntent();
avgThread = new Thread(runnable);//定期更新平均值的線程啟動
avgThread.start();
//初始化各個監聽器
initListeners();
switch (wtd) {
case Sensor.TYPE_ACCELEROMETER:
title.setText("加速度傳感器");
danWei.setText("N/M^2");
accelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(threeParamListener, accelSensor, sensorManager.SENSOR_DELAY_UI);
yMax = 20;
sensor_id = 1;
break;
default:
break;
}
//初始化圖表
initChart("*0.5s", danWei.getText().toString(),0,xMax,0,yMax);
}
/**
* 抓取view中文本控件的函數
*/
private void findViews(){
xText = (TextView) findViewById(R.id.xAxis);
yText = (TextView) findViewById(R.id.yAxis);
zText = (TextView) findViewById(R.id.zAxis);
sumText = (TextView) findViewById(R.id.sum);
danWei = (TextView) findViewById(R.id.danWei);
title = (TextView) findViewById(R.id.title);
}
/**
* 初始化各類監聽器
*/
private void initListeners() {
threeParamListener = new SensorEventListener() {//有三個返回參數的監聽器
@Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
xText.setText(event.values[0]+"");
yText.setText(event.values[1]+"");
zText.setText(event.values[2]+"");
double sum = threeDimenToOne(event.values[0], event.values[1], event.values[2]);
giveAverage(sum);//將當前測量的結果寫入buffer,然後定期求buffer裡面的平均值,並顯示
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
}
/**
* 初始化圖表
*/
private void initChart(String xTitle,String yTitle,int minX,int maxX,int minY,int maxY){
//這裡獲得main界面上的布局,下面會把圖表畫在這個布局裡面
LinearLayout layout = (LinearLayout)findViewById(R.id.chart);
//這個類用來放置曲線上的所有點,是一個點的集合,根據這些點畫出曲線
series = new XYSeries("歷史曲線");
//創建一個數據集的實例,這個數據集將被用來創建圖表
mDataset = new XYMultipleSeriesDataset();
//將點集添加到這個數據集中
mDataset.addSeries(series);
//以下都是曲線的樣式和屬性等等的設置,renderer相當於一個用來給圖表做渲染的句柄
int lineColor = Color.BLACK;
PointStyle style = PointStyle.CIRCLE;
renderer = buildRenderer(lineColor, style, true);
//設置好圖表的樣式
setChartSettings(renderer, xTitle,yTitle,
minX, maxX, //x軸最小最大值
minY, maxY, //y軸最小最大值
Color.BLACK, //坐標軸顏色
Color.WHITE//標簽顏色
);
//生成圖表
chart = ChartFactory.getLineChartView(this, mDataset, renderer);
//將圖表添加到布局中去
layout.addView(chart, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if(threeParamListener!=null){
sensorManager.unregisterListener(threeParamListener);
}
if(oneParamListener!=null){
sensorManager.unregisterListener(oneParamListener);
}
if(avgThread!=null)
avgThread.interrupt();
DbUtils db = DbUtils.create(getApplicationContext());//xUtils框架
try {
List list = db.findAll(Selector.from(Accelerate_info.class).where("sensor", "=", sensor_id));//看看一共寫入了數據庫多少數據
System.out.println("數量是"+list.size());
} catch (DbException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 根據三個坐標向量求和向量的模
* @param x
* @param y
* @param z
* @return
*/
public static double threeDimenToOne(double x,double y,double z){
return Math.sqrt(x*x+y*y+z*z);
}
public int index = 0;//指示這段時間一共寫入了多少個數據
//在這裡可以設置緩沖區的長度,用於求平均數
double[] buffer = new double[500];//半秒鐘最多放500個數
public int INTERVAL = 500;//每半秒求一次平均值
public double AVERAGE = 0;//存儲平均值
/**
* 一個子線程,沒隔固定時間計算這段時間的平均值,並給textView賦值
*/
Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("線程已經啟動");
while(true){
try {
Thread.sleep(INTERVAL);//沒隔固定時間求平均數
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
avgThread = new Thread(runnable);
avgThread.start();
}
if(index!=0){
double sum = 0;
for (int i=0;i100){//如果超出了屏幕邊界,實現坐標軸自動移動的方法
renderer.setXAxisMin(addX-100);//顯示范圍為100
renderer.setXAxisMax(addX);
}
//重要:在數據集中添加新的點集
mDataset.addSeries(series);
//視圖更新,沒有這一步,曲線不會呈現動態
//如果在非UI主線程中,需要調用postInvalidate(),具體參考api
chart.invalidate();
}
}
Android學習筆記之應用單元測試實例分析
本文實例講述了Android學習筆記之應用單元測試。分享給大家供大家參考,具體如下:第一步:在AndroidManifest.xml中加入如下兩段代碼:<manif
android:Toolbar用法探析(二):內容顯示微調
原生的Toolbar基本的功能樣式已經在上節簡單的說了一下,但是當前的樣式並不滿足我們的需要,因此這一節主要探索一下Toolbar的一些內容上調整的方法,比如Title位
淺談Android自定義鎖屏頁
一、為什麼需要自定義鎖屏頁鎖屏作為一種黑白屏時代就存在的手機功能,至今仍發揮著巨大作用,特別是觸屏時代的到來,鎖屏的功用被發揮到了極致。多少人曾經在無聊的時候每隔幾分鐘劃
Android仿百度壁紙客戶端之搭建主框架(一)
這是個不錯的教程,自己學完了之後就拿出來分享了,本來想一個帖子寫完,但是發現這樣對自己寫博客的效率有點出入,為了讓大家看的舒服點,所以分開來寫,我們先開看下百度壁紙的客戶