安卓动态曲线的绘制

        我们在安卓开发中,有时会用到统计图表的功能,而曲线绘制是其中比较典型的一种,一般是利用给定的坐标点集和安卓自带的绘图模块进行绘制,直接得到的是一张完整的静态的曲线图。但有时,我们需要动态绘制一些曲线图,就像我们打开电脑的任务管理器,里面有一个CPU使用记录的动态变化的带网格的曲线图,对于这一类的曲线绘制,安卓SDK自带的绘图模块貌似就不那么好用了。

        在这里,我就利用Handler+timer机制和第三方开发包achartengine实现动态绘制安卓手机充放电曲线的应用。

        1、下载第三方开发包achartengine,也就是jar包,可以在网上找到下载源,我下载的是achartengine-1.1.0.jar

        2、在创建的应用工程文件中引入该jar包,以Eclipse为例方法是:在包资源管理器目录中右键单击已创建的项目名称——>构建路径——>配置构建路径——>Java构建路径——>库——>外部JAR,然后找到achartengine包的存放路径,找到achartengine-1.1.0.jar文件,点击打开即完成了该包的引用,这时会在项目目录下出现一个名为引用的库文件,里面就是我们刚才引入的jar包。

        3、接下来就可以按正常步骤开发该应用了,需要注意的是:需要在主类中引入jar中绘图需要的库文件,如下:             

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;

              同时需要在AndroidManifest.xml文件中加上语句:             

<application
                      android:icon="@drawable/ic_launcher"
                      android:label="@string/app_name" >
                      <activity android:name="org.achartengine.GraphicalActivity" />

        4、接下来需要定义一些绘图的变量和样式:             

 private XYSeries series;
              private XYMultipleSeriesDataset mDataset;
              private GraphicalView chart;
              private XYMultipleSeriesRenderer renderer;
              private Context context, context1;
              private int addX = -1, addY;
              int[] xv = new int[720];// X轴数组元素个数
              int[] yv = new int[720];// Y轴数组元素个数         
                  context = getApplicationContext();
              // 这里获得main界面上的布局,下面会把图表画在这个布局里面
              LinearLayout layout = (LinearLayout) findViewById(R.id.linearLayout1);
              // 这个类用来放置曲线上的所有点,是一个点的集合,根据这些点画出曲线
              series = new XYSeries(title);
              // 创建一个数据集的实例,这个数据集将被用来创建图表
              mDataset = new XYMultipleSeriesDataset();
              // 将点集添加到这个数据集中
              mDataset.addSeries(series);
              // 以下都是曲线的样式和属性等等的设置,renderer相当于一个用来给图表做渲染的句柄
              int color = Color.GREEN;
              PointStyle style = PointStyle.CIRCLE;
              renderer = buildRenderer(color, style, true);

              // 设置好图表的样式(横轴时间分钟值,纵轴电压毫伏值)
              setChartSettings(renderer, "X", "Y", 0, 240, 3400, 4400, Color.WHITE,Color.WHITE);
              // 生成图表
              chart = ChartFactory.getLineChartView(context, mDataset, renderer);
              // 将图表添加到布局中去
              layout.addView(chart, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

               protected XYMultipleSeriesRenderer buildRenderer(int color,PointStyle style, boolean fill)// 配置绘图属性
              {
              XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
              // 设置图表中曲线本身的样式,包括颜色、点的大小以及线的粗细等
              XYSeriesRenderer r = new XYSeriesRenderer();
              r.setColor(color);
              r.setPointStyle(style);
              r.setFillPoints(fill);
              r.setLineWidth((float) 1);// 线粗尺寸
              renderer.addSeriesRenderer(r);
              return renderer;
}

protected void setChartSettings(XYMultipleSeriesRenderer renderer,
String xTitle, String yTitle, double xMin, double xMax,
double yMin, double yMax, int axesColor, int labelsColor) {
// 有关对图表的渲染可参看api文档
renderer.setChartTitle(title);
renderer.setXTitle(xTitle);
renderer.setYTitle(yTitle);
renderer.setXAxisMin(xMin);
renderer.setXAxisMax(xMax);
renderer.setYAxisMin(yMin);
renderer.setYAxisMax(yMax);
renderer.setAxesColor(axesColor);
renderer.setLabelsColor(labelsColor);
renderer.setShowGrid(true);
renderer.setGridColor(Color.GREEN);// 曲线颜色
renderer.setXLabels(20);
renderer.setYLabels(10);
renderer.setChartTitle("时间/电压变化曲线图");// 图表名称
renderer.setXTitle("时间(min)");// 横坐标名称
renderer.setYTitle("电压(mv)");// 纵坐标名称
renderer.setYLabelsAlign(Align.RIGHT);
renderer.setPointSize((float) 1.5);// 设置点的大小
renderer.setShowLegend(false);
renderer.setPanEnabled(true, false);// 设置滑动,这边是横向可以滑动,纵向不可滑动
renderer.setZoomEnabled(true, false);// 设置缩放,横向可以,纵向不可以
// renderer.setZoomLimits(new double[] { 0, 720, 3400, 4400 });//设置缩放的范围
// renderer.setPanLimits(new double[] { -0.5, 720, 3400, 4400
// });//设置拉动的范围
}

     5、动态绘制的实现:动态绘制主要需要实现两方面的内容,一是更新绘图的方法、二是动态绘图时间任务的定义。

1)更新绘图方法:             

<strong>private void updateChart()// 更新绘图方法</strong>
{
// 设置好下一个需要增加的节点
addX = (int) (addX + 1);
addY = BatteryV;
// 移除数据集中旧的点集
mDataset.removeSeries(series);
// 判断当前点集中到底有多少点,因为屏幕总共只能容纳240个,所以当点数超过240时,长度永远是240
int length = series.getItemCount();
if (length > 720) {
length = 720;
}
// 将旧的点集中x和y的数值取出来放入backup中,并且将x的值加1,造成曲线向右平移的效果
for (int i = 0; i < length; i++) {
xv[i] = (int) series.getX(i);
yv[i] = (int) series.getY(i);
}
// 点集先清空,为了做成新的点集而准备
series.clear();
// 将新产生的点首先加入到点集中,然后在循环体中将坐标变换后的一系列点都重新加入到点集中
// 这里可以试验一下把顺序颠倒过来是什么效果,即先运行循环体,再添加新产生的点
series.add(addX, addY);
for (int k = 0; k < length; k++) {
series.add(xv[k], yv[k]);
}
// 在数据集中添加新的点集
mDataset.addSeries(series);
// 视图更新,没有这一步,曲线不会呈现动态
// 如果在非UI主线程中,需要调用postInvalidate(),具体参考api
chart.invalidate();
}

           2)时间任务定义:              

 handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 刷新图表
updateChart();// 电压变化曲线刷新
updateChart1();// 电量变化曲线刷新
super.handleMessage(msg);
}
};
task = new TimerTask()// 刷新绘图计时任务配置
{
@Override
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
timer.schedule(task, 0, 60000);// 以一分钟为时间间隔运行 

         再发一下完整的代码:

主类:

<span style="font-size:14px;">package com.cfzz.vcd;

import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
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 com.cfzz.vqcd.R;

//import com.cfzz.wy.R;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint.Align;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.view.View.OnClickListener;

public class VoltageChangeDraw extends Activity {

	// protected static final Activity Activity = null;
	private PowerManager.WakeLock wl;
	private Timer timer = new Timer();
	private long mExitTime = 0;
	private TimerTask task, task1;
	private Handler handler;
	private String title = "Signal Strength";
	private XYSeries series, series1;
	private XYMultipleSeriesDataset mDataset, mDataset1;
	private GraphicalView chart, chart1;
	private XYMultipleSeriesRenderer renderer, renderer1;
	private Context context, context1;
	private int addX = -1, addY;
	private int addX1 = -1, addY1;
	private Button button;
	int[] xv = new int[720];// X轴数组元素个数
	int[] yv = new int[720];// Y轴数组元素个数
	int[] xv1 = new int[720];// X轴数组元素个数
	int[] yv1 = new int[720];// Y轴数组元素个数
	public TextView TV;
	// ScreenShot screenShot = new ScreenShot();
	private int BatteryN; // 目前电量
	private int BatteryV; // 电池电压
	// private double BatteryT; //电池温度
	private String BatteryStatus; // 电池状态
	private String BatteryTemp; // 电池使用情况

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
				WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		setContentView(R.layout.main);
		this.button = (Button) this.findViewById(R.id.my_button);// 截图按键定义
		// 截图按键监听
		this.button.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				SimpleDateFormat sdf = new SimpleDateFormat(
						"yyyy-MM-dd_HH-mm-ss", Locale.US);// 日期格式名定义

				String fname = "/sdcard/" + sdf.format(new Date()) + ".png";// 存储路径及文件名定义

				View view = v.getRootView();

				view.setDrawingCacheEnabled(true);

				view.buildDrawingCache();

				Bitmap bitmap = view.getDrawingCache();

				if (bitmap != null) {
					System.out.println("bitmap got!");

					try {

						FileOutputStream out = new FileOutputStream(fname);

						bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);// 图片格式及质量输出

						System.out.println("file" + fname + "output done.");

					} catch (Exception e) {

						e.printStackTrace();

					}

				} else {
					System.out.println("bitmap is NULL!");
				}
			}
		});
		// MyTag可以随便写,可以写应用名称等
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		// 换成PowerManager.SCREEN_DIM_WAKE_LOCK会变暗)
		PowerManager.WakeLock wl = pm.newWakeLock(
				PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "MyTest");
		wl.acquire();// 开启屏幕常亮

		TV = (TextView) findViewById(R.id.TV);// 电池信息打印控件定义

		// 注册一个系统 BroadcastReceiver,作为访问电池计量之用,这个不能直接在AndroidManifest.xml中注册
		registerReceiver(mBatInfoReceiver, new IntentFilter(
				Intent.ACTION_BATTERY_CHANGED));

		context = getApplicationContext();
		context1 = getApplicationContext();// 图2
		// 这里获得main界面上的布局,下面会把图表画在这个布局里面
		LinearLayout layout = (LinearLayout) findViewById(R.id.linearLayout1);

		// 这个类用来放置曲线上的所有点,是一个点的集合,根据这些点画出曲线
		series = new XYSeries(title);
		series1 = new XYSeries(title);// 图2
		// 创建一个数据集的实例,这个数据集将被用来创建图表
		mDataset = new XYMultipleSeriesDataset();
		mDataset1 = new XYMultipleSeriesDataset();
		// 将点集添加到这个数据集中
		mDataset.addSeries(series);
		mDataset1.addSeries(series1);// 图2
		// 以下都是曲线的样式和属性等等的设置,renderer相当于一个用来给图表做渲染的句柄
		int color = Color.GREEN;
		int color1 = Color.RED;
		PointStyle style = PointStyle.CIRCLE;
		renderer = buildRenderer(color, style, true);
		renderer1 = buildRenderer(color1, style, true);// 图2

		// 设置好图表的样式(横轴时间分钟值,纵轴电压毫伏值)
		setChartSettings(renderer, "X", "Y", 0, 240, 3400, 4400, Color.WHITE,
				Color.WHITE);
		setChart1Settings(renderer1, "X", "Y", 0, 240, 0, 100, Color.WHITE,
				Color.WHITE);
		// 生成图表
		chart = ChartFactory.getLineChartView(context, mDataset, renderer);
		chart1 = ChartFactory.getLineChartView(context1, mDataset1, renderer1);// 图2
		</span><span style="font-size:12px;">// 将图表添加到布局中去,此处的纵向尺寸设置存在一些问题,当两张图都设置<span style="font-family: Arial, Helvetica, sans-serif;">WRAP_CONTENT</span>时,在实际界面上只显示第一张图,在这里可根据手                  // </span><span style="font-family: Arial, Helvetica, sans-serif;">机屏幕的大小设置具</span><span style="font-family: Arial, Helvetica, sans-serif;">体的数值(像素点个数),可以保证两张图都能显示在屏幕上
</span><span style="font-size:14px;">		layout.addView(chart, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
		layout.addView(chart1, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
		// layout.addView(chart, new LayoutParams(LayoutParams.FILL_PARENT,
		// 400));//525
		// layout.addView(chart1, new LayoutParams(LayoutParams.FILL_PARENT,
		// 400));//图2 525
		// 这里的Handler实例将配合下面的Timer实例,完成定时更新图表的功能
		handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				// 刷新图表
				updateChart();// 电压变化曲线刷新
				updateChart1();// 电量变化曲线刷新
				super.handleMessage(msg);

			}
		};

		task = new TimerTask()// 刷新绘图计时任务配置
		{
			@Override
			public void run() {
				Message message = new Message();
				message.what = 1;
				handler.sendMessage(message);
			}
		};
		timer.schedule(task, 0, 60000);// 以一分钟为时间间隔运行

		task1 = new TimerTask()// 保存绘图计时任务配置
		{
			@Override
			public void run() {
				if (BatteryStatus == "充满电"
						|| (BatteryStatus == "放电状态" && BatteryN == 1))// 充/放电完成条件设定
				{
					button.callOnClick();// 保存曲线图按键触发
					timer.cancel(); // 停止计时功能
				}
			}
		};
		timer.schedule(task1, 0, 10000);// 以十秒钟为时间间隔运行
	}

	@Override
	public void onDestroy() // 结束程序声明
	{
		button.callOnClick();// 保存曲线图按键触发
		// 当结束程序时关掉Timer
		timer.cancel();
		// wl.release();
		// wl = null;
		super.onDestroy();
	}

	protected XYMultipleSeriesRenderer buildRenderer(int color,
			PointStyle style, boolean fill)// 配置绘图属性
	{
		XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();

		// 设置图表中曲线本身的样式,包括颜色、点的大小以及线的粗细等
		XYSeriesRenderer r = new XYSeriesRenderer();
		r.setColor(color);
		r.setPointStyle(style);
		r.setFillPoints(fill);
		r.setLineWidth((float) 1);// 线粗尺寸
		renderer.addSeriesRenderer(r);

		return renderer;
	}

	// 图2
	protected XYMultipleSeriesRenderer buildRenderer1(int color1,
			PointStyle style, boolean fill)// 配置绘图属性
	{
		XYMultipleSeriesRenderer renderer1 = new XYMultipleSeriesRenderer();// 图2
		// 设置图表中曲线本身的样式,包括颜色、点的大小以及线的粗细等
		XYSeriesRenderer r = new XYSeriesRenderer();
		r.setColor(color1);
		r.setPointStyle(style);
		r.setFillPoints(fill);
		r.setLineWidth((float) 1);// 线粗尺寸
		renderer1.addSeriesRenderer(r);

		return renderer1;
	}

	protected void setChartSettings(XYMultipleSeriesRenderer renderer,
			String xTitle, String yTitle, double xMin, double xMax,
			double yMin, double yMax, int axesColor, int labelsColor) {
		// 有关对图表的渲染可参看api文档

		renderer.setChartTitle(title);
		renderer.setXTitle(xTitle);
		renderer.setYTitle(yTitle);
		renderer.setXAxisMin(xMin);
		renderer.setXAxisMax(xMax);
		renderer.setYAxisMin(yMin);
		renderer.setYAxisMax(yMax);
		renderer.setAxesColor(axesColor);
		renderer.setLabelsColor(labelsColor);
		renderer.setShowGrid(true);
		renderer.setGridColor(Color.GREEN);// 曲线颜色
		renderer.setXLabels(20);
		renderer.setYLabels(10);
		renderer.setChartTitle("时间/电压变化曲线图");// 图表名称
		renderer.setXTitle("时间(min)");// 横坐标名称
		renderer.setYTitle("电压(mv)");// 纵坐标名称
		renderer.setYLabelsAlign(Align.RIGHT);
		renderer.setPointSize((float) 1.5);// 设置点的大小
		renderer.setShowLegend(false);
		renderer.setPanEnabled(true, false);// 设置滑动,这边是横向可以滑动,纵向不可滑动
		renderer.setZoomEnabled(true, false);// 设置缩放,横向可以,纵向不可以
		// renderer.setZoomLimits(new double[] { 0, 720, 3400, 4400 });//设置缩放的范围
		// renderer.setPanLimits(new double[] { -0.5, 720, 3400, 4400
		// });//设置拉动的范围
	}

	// 图2
	protected void setChart1Settings(XYMultipleSeriesRenderer renderer1,
			String xTitle, String yTitle, double xMin, double xMax,
			double yMin, double yMax, int axesColor, int labelsColor) {
		// 有关对图表的渲染可参看api文档

		renderer1.setChartTitle(title);
		renderer1.setXTitle(xTitle);
		renderer1.setYTitle(yTitle);
		renderer1.setXAxisMin(xMin);
		renderer1.setXAxisMax(xMax);
		renderer1.setYAxisMin(yMin);
		renderer1.setYAxisMax(yMax);
		renderer1.setAxesColor(axesColor);
		renderer1.setLabelsColor(labelsColor);
		renderer1.setShowGrid(true);
		renderer1.setGridColor(Color.GREEN);// 曲线颜色
		renderer1.setXLabels(20);
		renderer1.setYLabels(10);
		renderer1.setChartTitle("时间/电量变化曲线图");// 图表名称
		renderer1.setXTitle("时间(min)");// 横坐标名称
		renderer1.setYTitle("电量(%)");// 纵坐标名称
		renderer1.setYLabelsAlign(Align.RIGHT);
		renderer1.setPointSize((float) 1.5);// 设置点的大小
		renderer1.setShowLegend(false);
		renderer1.setPanEnabled(true, false);// 设置滑动,这边是横向可以滑动,纵向不可滑动
		renderer1.setZoomEnabled(true, false);// 设置缩放,横向可以,纵向不可以
		// renderer1.setZoomLimits(new double[] { 0, 720, 0, 100 });//设置缩放的范围
		// renderer1.setPanLimits(new double[] { -0.5, 720, 0, 100 });//设置拉动的范围
	}

	private void updateChart()// 更新绘图方法
	{

		// 设置好下一个需要增加的节点
		addX = (int) (addX + 1);
		addY = BatteryV;
		// 移除数据集中旧的点集
		mDataset.removeSeries(series);
		// 判断当前点集中到底有多少点,因为屏幕总共只能容纳240个,所以当点数超过240时,长度永远是240
		int length = series.getItemCount();
		if (length > 720) {
			length = 720;
		}
		// 将旧的点集中x和y的数值取出来放入backup中,并且将x的值加1,造成曲线向右平移的效果
		for (int i = 0; i < length; i++) {
			xv[i] = (int) series.getX(i);
			yv[i] = (int) series.getY(i);
		}
		// 点集先清空,为了做成新的点集而准备
		series.clear();

		// 将新产生的点首先加入到点集中,然后在循环体中将坐标变换后的一系列点都重新加入到点集中
		// 这里可以试验一下把顺序颠倒过来是什么效果,即先运行循环体,再添加新产生的点
		series.add(addX, addY);
		for (int k = 0; k < length; k++) {
			series.add(xv[k], yv[k]);
		}
		// 在数据集中添加新的点集
		mDataset.addSeries(series);

		// 视图更新,没有这一步,曲线不会呈现动态
		// 如果在非UI主线程中,需要调用postInvalidate(),具体参考api
		chart.invalidate();
	}

	// 图2
	private void updateChart1()// 更新绘图方法
	{

		// 设置好下一个需要增加的节点
		addX1 = (int) (addX1 + 1);
		addY1 = BatteryN;
		// 移除数据集中旧的点集
		mDataset1.removeSeries(series1);
		// 判断当前点集中到底有多少点,因为屏幕总共只能容纳240个,所以当点数超过240时,长度永远是240
		int length1 = series1.getItemCount();
		if (length1 > 720) {
			length1 = 720;
		}
		// 将旧的点集中x和y的数值取出来放入backup中,并且将x的值加1,造成曲线向右平移的效果
		for (int j = 0; j < length1; j++) {
			xv1[j] = (int) series1.getX(j);
			yv1[j] = (int) series1.getY(j);
		}
		// 点集先清空,为了做成新的点集而准备
		series1.clear();

		// 将新产生的点首先加入到点集中,然后在循环体中将坐标变换后的一系列点都重新加入到点集中
		// 这里可以试验一下把顺序颠倒过来是什么效果,即先运行循环体,再添加新产生的点
		series1.add(addX1, addY1);
		for (int l = 0; l < length1; l++) {
			series1.add(xv1[l], yv1[l]);
		}
		// 在数据集中添加新的点集
		mDataset1.addSeries(series1);

		// 视图更新,没有这一步,曲线不会呈现动态
		// 如果在非UI主线程中,需要调用postInvalidate(),具体参考api
		chart1.invalidate();
	}

	/* 创建电池状态广播接收器 */
	public BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();

			// 如果捕捉到的action是ACTION_BATTERY_CHANGED, 就运行onBatteryInfoReceiver()

			if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
				BatteryN = intent.getIntExtra("level", 0); // 目前电量
				BatteryV = intent.getIntExtra("voltage", 0); // 电池电压
				// BatteryT = intent.getIntExtra("temperature", 0); //电池温度

				switch (intent.getIntExtra("status",
						BatteryManager.BATTERY_STATUS_UNKNOWN)) {
				case BatteryManager.BATTERY_STATUS_CHARGING:
					BatteryStatus = "充电状态";
					break;
				case BatteryManager.BATTERY_STATUS_DISCHARGING:
					BatteryStatus = "放电状态";
					break;
				case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
					BatteryStatus = "未充电";
					break;
				case BatteryManager.BATTERY_STATUS_FULL:
					BatteryStatus = "充满电";

					break;
				case BatteryManager.BATTERY_STATUS_UNKNOWN:
					BatteryStatus = "未知道状态";
					break;
				}

				switch (intent.getIntExtra("health",
						BatteryManager.BATTERY_HEALTH_UNKNOWN)) {
				case BatteryManager.BATTERY_HEALTH_UNKNOWN:
					BatteryTemp = "未知错误";
					break;
				case BatteryManager.BATTERY_HEALTH_GOOD:
					BatteryTemp = "状态良好";
					break;
				case BatteryManager.BATTERY_HEALTH_DEAD:
					BatteryTemp = "电池没有电";

					break;
				case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
					BatteryTemp = "电池电压过高";
					break;
				case BatteryManager.BATTERY_HEALTH_OVERHEAT:
					BatteryTemp = "电池过热";
					break;
				}
				TV.setText("目前电量为" + BatteryN + "% --- " + BatteryStatus + "\n"
						+ "电压为" + BatteryV + "mV ----- " + BatteryTemp);

			}
		}

	};

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)// 程序按返回键退出处理
	{
		switch (keyCode) {
		case KeyEvent.KEYCODE_BACK:
			// 双击退出
			// if (isStart == true){isStart = false;}//关闭前确认频闪是否关闭
			if ((System.currentTimeMillis() - mExitTime) > 2000) {
				Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
				mExitTime = System.currentTimeMillis();
			} else {
				// isStart = false;
				finish();
			}
			return true;

		default:
			break;
		}
		return super.onKeyDown(keyCode, event);
	}

}
</span>
布局文件:

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/linearLayout1"
    
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"
    android:layout_weight="1"
    >  
<!--  -->
<TextView  
    android:id = "@+id/TV" 
      
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content" 
    
    />     
<Button
  android:text="保存该曲线图"
  android:textSize="4pt"
  android:id="@+id/my_button"
  
  android:layout_width="fill_parent"
  android:layout_height="28dp"
  android:layout_alignBottom="@+id/TV">
  <!--android:layout_alignParentBottom="true"-->
  
</Button>
</LinearLayout>
AndroidManifest.xml配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cfzz.vcd"
    android:versionCode="1"
    android:versionName="1.0"> 
    
    <uses-sdk android:minSdkVersion="10" />
    <uses-permission android:name="android.permission.READ_FRAME_BUFFER"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity android:name="org.achartengine.GraphicalActivity" />
        <activity
            android:name="com.cfzz.vcd.VoltageChangeDraw"
            android:screenOrientation="portrait"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

        在该源码中,我们绘制了两条曲线,一条是电压变化曲线,另一条是电量变化曲线,并加一个保存手机屏幕的截图按钮和自动保存时间任务(也可手动保存),用来保存绘制的截图。

运行结果图(充电曲线图):



     

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彧侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值