MTK平台Android Gsensor数据校准与数据获取

http://blog.csdn.net/morixinguan/article/details/76850600

上节,写WIFI MAC地址的时候我们已经知道,MTKAndroid系统的Gsensor校准的数据其实也是存储在NVRAM中的,Gsensor隶属于传感器系统架构。

 

接下来我们来看下Gsensor校准的基准图像:

那么如何来校准Gsensor的X,Y,Z三个方向呢?我们可以参考MTK提供的工厂测试factroymode的代码:

位置在:vendor\mediatek\proprietary\factory\src\test\ftm_gs_cali.c  ftm_gsensor.c

ftm_gs_cali.c就是校准的源码,我们可以打开来看看它具体的实现原理:

在ftm_gs_cali.c的static void*gs_cali_update_iv_thread(void *priv)这个函数中,我们可以看到如何校准Gsensor数值的过程:

static void *gs_cali_update_iv_thread(void *priv)
{
	struct gsc_data *dat = (struct gsc_data *)priv;
	struct gsc_priv *gsc = &dat->gsc;
	struct itemview *iv = dat->iv;
	int err = 0, len = 0;
	char *status;
	HwmData cali;
	static int op = -1;
	int  max_retry = 3, retry_period = 100, retry=0;
    unsigned int flags = 1;

	LOGD(TAG "%s: Start\n", __FUNCTION__);
	//打开gsensor
	err = gsensor_open(&(gsc->fd));
	if(err)
	{
		memset(dat->info, 0x00, sizeof(dat->info));
		sprintf(dat->info, uistr_info_sensor_init_fail);
		iv->redraw(iv);
		GSCLOGE("gs_cali_open() err = %d(%s)\n", err, dat->info);
		pthread_exit(NULL);
		return NULL;
	}
/** Enable G-sensor **/
//使能Gsensor,让它开始工作
    while ((err = ioctl(gsc->fd, GSENSOR_IOCTL_INIT, &flags)) && (retry ++ < max_retry))
    usleep(retry_period*1000);
    if (err) {
        LOGD("enable g-sensor fail: %s", strerror(errno));
        return -1;
	}

	while(1)
	{

		if(dat->exit_thd)
		{
			break;
		}

		pthread_mutex_lock(&dat->gsc.evtmutex);
		if(op != dat->gsc.pending_op)
		{
			op = dat->gsc.pending_op;
			GSCLOGD("op: %d\n", dat->gsc.pending_op);
		}
		pthread_mutex_unlock(&dat->gsc.evtmutex);
		err = 0;

		if(op == GS_OP_CLEAR)
		{
			memset(&dat->gsc.cali_nvram, 0x00, sizeof(dat->gsc.cali_nvram));
			memset(&dat->gsc.cali_drv, 0x00, sizeof(dat->gsc.cali_drv));
			err = gsensor_rst_cali(gsc->fd);
			if(err)
			{
				GSCLOGE("rst calibration: %d\n", err);
			}
			else if((err = gsensor_write_nvram(&dat->gsc.cali_nvram)) != 0)
			{
				GSCLOGE("write nvram: %d\n", err);
			}

			if(err)
			{
				snprintf(dat->gsc.status, sizeof(dat->gsc.status), uistr_info_sensor_cali_fail);
				//dat->mod->test_result = FTM_TEST_FAIL;
			}
			else
			{
				snprintf(dat->gsc.status, sizeof(dat->gsc.status), uistr_info_sensor_cali_ok);
				//dat->mod->test_result = FTM_TEST_PASS;
			}

			gsc->bUpToDate = false;
			pthread_mutex_lock(&dat->gsc.evtmutex);
			dat->gsc.pending_op = GS_OP_NONE;
			pthread_mutex_unlock(&dat->gsc.evtmutex);
		}
		else if(op == GS_OP_CALI_PRE)
		{
			err = 0;
			/*by-pass*/
			snprintf(dat->gsc.status, sizeof(dat->gsc.status), uistr_info_sensor_cali_ongoing);
			pthread_mutex_lock(&dat->gsc.evtmutex);
			dat->gsc.pending_op = GS_OP_CALI;
			pthread_mutex_unlock(&dat->gsc.evtmutex);
		}
		else if(op == GS_OP_CALI)
		{
			if(!dat->gsc.cali_delay || !dat->gsc.cali_num || !dat->gsc.cali_tolerance)
			{
				GSCLOGE("ignore calibration: %d %d %d\n", dat->gsc.cali_delay, dat->gsc.cali_num, dat->gsc.cali_tolerance);
			}
			//执行校准的动作
			else if((err = gsensor_calibration(gsc->fd, dat->gsc.cali_delay, dat->gsc.cali_num,
			                          dat->gsc.cali_tolerance, 0, &cali)) != 0)
			{
				GSCLOGE("calibrate acc: %d\n", err);
			}
			//设置校准cali,让校准的数据开始生效
			else if((err = gsensor_set_cali(gsc->fd, &cali)) != 0)
			{
				GSCLOGE("set calibration fail: (%s) %d\n", strerror(errno), err);
			}
			else if((err = gsensor_get_cali(gsc->fd, &cali)) != 0)
			{
				GSCLOGE("get calibration fail: (%s) %d\n", strerror(errno), err);
			}
			//将校准的数据写入到nvram中去
			else if((err = gsensor_write_nvram(&cali)) != 0)
			{
				GSCLOGE("write nvram fail: (%s) %d\n", strerror(errno), err);
			}
			else
			{
				dat->gsc.cali_delay = dat->gsc.cali_num = dat->gsc.cali_tolerance = 0;
				dat->gsc.bUpToDate = false;
			}

			if(err)
			{
				len = snprintf(dat->gsc.status, sizeof(dat->gsc.status), uistr_info_sensor_cali_fail);
				dat->mod->test_result = FTM_TEST_FAIL;
			}
			else
			{
				len = snprintf(dat->gsc.status, sizeof(dat->gsc.status), uistr_info_sensor_cali_ok);
				dat->mod->test_result = FTM_TEST_PASS;
			}

			pthread_mutex_lock(&dat->gsc.evtmutex);
			dat->gsc.pending_op = GS_OP_NONE;
			pthread_mutex_unlock(&dat->gsc.evtmutex);
		}

		err = gs_cali_update_info(gsc);
		if(err)
		{
			GSCLOGE("gs_cali_update_info() = (%s), %d\n", strerror(errno), err);
			break;
		} 

		len = 0;
		len += snprintf(dat->info+len, sizeof(dat->info)-len, "R: %+7.4f %+7.4f %+7.4f\n", gsc->dat.x, gsc->dat.y, gsc->dat.z);
		len += snprintf(dat->info+len, sizeof(dat->info)-len, "D: %+7.4f %+7.4f %+7.4f\n", gsc->cali_drv.x, gsc->cali_drv.y, gsc->cali_drv.z);
		len += snprintf(dat->info+len, sizeof(dat->info)-len, "N: %+7.4f %+7.4f %+7.4f\n", gsc->cali_nvram.x, gsc->cali_nvram.y, gsc->cali_nvram.z);
		len += snprintf(dat->info+len, sizeof(dat->info)-len, "%s\n", gsc->status);

		iv->set_text(iv, &dat->text);
		iv->redraw(iv);
	}
	//关闭gsensor
	gs_cali_close(gsc);
	LOGD(TAG "%s: Exit\n", __FUNCTION__);
	pthread_exit(NULL);

	return NULL;
}

这段代码虽然很多,但我们可以找出校准Gsensor的核心流程主要如下:

(1)    打开Gsensor

(2)    使能Gsensor

(3)    执行校准的动作

(4)    设置校准的Cail,让校准的数据生效

(5)    将校准得到的数据写入到nvram中

(6)    关闭Gsensor

核心流程我们已经清楚了,那么接下来如何来写这个程序呢?我们要弄明白,这些函数上哪个文件里去找这是第一步:

通过grep命令搜索相关函数,最终确定,这些函数的头文件在:

./pskyed/libs/em_emmc_comm/libhwm/include/libhwm.h这里,在这个头文件中有相关的函数可以给我们使用:

extern int gsensor_calibration(int fd, int period, int count, int tolerance, int trace, HwmData *cali);
extern int gsensor_write_nvram(HwmData *dat);
extern int gsensor_read_nvram(HwmData *dat);
extern int gsensor_rst_cali(int fd);
extern int gsensor_set_cali(int fd, HwmData *dat);
extern int gsensor_get_cali(int fd, HwmData *dat);
extern int gsensor_read(int fd, HwmData *dat);
extern int gsensor_init(int fd);
extern int gsensor_close(int fd);
extern int gsensor_open(int *fd);
extern int gyroscope_calibration(int fd, int period, int count, int tolerance, int trace, HwmData *cali);
extern int gyroscope_write_nvram(HwmData *dat);
extern int gyroscope_read_nvram(HwmData *dat);
extern int gyroscope_rst_cali(int fd);
extern int gyroscope_set_cali(int fd, HwmData *dat);
extern int gyroscope_get_cali(int fd, HwmData *dat);
extern int gyroscope_read(int fd, HwmData *dat);
extern int gyroscope_close(int fd);
extern int gyroscope_open(int *fd);
extern int gyroscope_init(int fd);

那么这些函数的源码在哪里呢?源码是没有的,因为MTK厂商将这部分代码给封装成了so动态库文件,所以,我们需要找到这个头文件对应的so文件,这样我们才能使用这个头文件,调用到so动态库中的函数。

通过搜索得知,这个so动态库文件在以下路径:

./pskyed/libs/em_emmc_comm/libhwm/libhwm.so

知道这些以后,下面我们就可以写一个简单的程序来验证这个过程了,这个留给读者自己去测试,接口我已经写好了,我的项目源码不便于公开,请读者自己拿去修改验证,流程是一样的,接口没有改过,至于想实现什么样的效果请读者自己去尝试添加,移植我的程序进行修改。

下面实现这个校准程序:

gs_cali.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/mount.h>
#include <sys/statfs.h>
#include <sys/reboot.h>
#include <dirent.h>
#include <linux/input.h>
#include <math.h>
#include <dirent.h>
#include <ctype.h>
#include <errno.h>
#include <linux/hwmsensor.h>
#include <linux/sensors_io.h>
#include "Keypad.h"
#include "libhwm.h"

#define GSENSOR_NAME  "/dev/gsensor"
#define OPEN_FILE_FAIR -1
#define OPEN_SUCCESS 0
#define RETURE_SUCCESS 0
#define ENABLED_SUCCESS 0
#define GSENSOR_CALIBRATION_SUCCESS 0
#define ENABLED_FAIR -2
#define CALIBRATION_FAIR -3
#define SET_CALIBRATION_FAIR -4
#define WRITE_NVRAM_FAIR  -5 

int gs_fd ; 

//打开gsensor
int gs_open(char *gs_name) ;
//关闭gsensor
int gs_close(int fd) ;
//gsensor开始工作
int gs_enable(unsigned int command) ;
//校准gsensor
int gs_calibration(unsigned int cali_delay ,unsigned int cali_num ,unsigned int cali_tolerance) ;

int main(void)
{
	int gs_ret = 0 ;
	int  cali_delay = 50;
int  cali_num = 20;
//这里的20表示把校准的数值做20次平均
//如果想要更精确,也可以做40次平均计算
    int  cali_tolerance = 20 ; //40
	//打开gsensor
	gs_ret = gs_open(GSENSOR_NAME);
	if(gs_ret != 0){
		printf("gs open fair!\n") ;
		return -1 ;
	}
	//使能gsensor
	gs_ret = gs_enable(GSENSOR_IOCTL_INIT);
	if(gs_ret != 0){
		printf("gs enable fair!\n") ;
		return -2 ;
	}
	//校准---->包括:执行校准的动作、设置校准数值、将校准数值写入nvram
	gs_ret = gs_calibration(cali_delay,cali_num,cali_tolerance);
	if(gs_ret != 0){
		printf("gs_calibration fair!\n") ;
		return -3 ;
	}
	//关闭gsensor
	gs_ret = gs_close(gs_fd);
	if(gs_ret != 0){
		printf("gs_close fair!\n");
		return -4 ;
	}
	printf("runexec call gsensorCalibrate end\n");
    return 0 ;
}

//1、open
int gs_open(char *gs_name)
{
	gs_fd = open(gs_name,O_RDONLY) ;
	if(gs_fd < 0)
	{
		printf("open gsensor dev fair!\n") ;
		return OPEN_FILE_FAIR ;
	}
	printf("gsensor open success!\n");
	return OPEN_SUCCESS ;
}

//2、enable gsensor
int gs_enable(unsigned int command)
{
	int err = 0;
	unsigned int flags = 1;
	int  max_retry = 3, retry_period = 100, retry=0;
	while ((err = ioctl(gs_fd, command, &flags)) && (retry ++ < max_retry)) ;
	usleep(retry_period*1000);
    if (err) {
        printf("enable g-sensor fail: %s", strerror(errno));
        return ENABLED_FAIR;
	}
	printf("enable gsensor success!\n");
	return ENABLED_SUCCESS ;
}
//3、校准
int gs_calibration(unsigned int cali_delay ,unsigned int cali_num ,unsigned cali_tolerance)
{
	int  err ;
	int flag = 0;
	HwmData dat; //dat.x  dat.y  dat.z
	HwmData cali;
	HwmData cali_nvram;
	while(1)
	{
		//执行校准的动作
		err = gsensor_calibration(gs_fd , cali_delay , cali_num , cali_tolerance , 0 , &cali);
		if(err != 0)
		{
			printf("calibrate acc: %d\n", err);
			return CALIBRATION_FAIR ;
		}
		//设置校准cali,让校准数据生效
		err = gsensor_set_cali(gs_fd,&cali) ;
		if(err != 0)
		{
			printf("set calibration fail: (%s) %d\n", strerror(errno), err);
			return SET_CALIBRATION_FAIR ;
		}
		//将校准数据写入nvram中
		err = gsensor_write_nvram(&cali) ;
		if(err != 0)
		{
			printf ("write nvram fail: (%s) %d\n", strerror(errno), err);
			return WRITE_NVRAM_FAIR ;
		}
		flag = 1 ;
		if(flag == 1)
		{
			printf("Gsensor calibrate success!\n") ;
			break ;
		}
	}
	return GSENSOR_CALIBRATION_SUCCESS ;
}

//关闭
int gs_close(int fd)
{
	close(fd) ;
	return 0 ;
}

然后写一个简单的Android.mk

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES += libcutils libutils   libhwm
LOCAL_STATIC_LIBRARIES += libz libstdc++
LOCAL_SRC_FILES:= \
	gs_cali.c 

LOCAL_MODULE:= gsensor_calibrate
include $(BUILD_EXECUTABLE)

将.c和Android.mk一并放在external下的一个自己定义的文件夹中,比如gs_cali文件夹,然后最后编译会在out目录下生成gsensor_calibrate这个二进制文件。

特别需要注意一点:使用这种方法进行校准后,需要将gsensor驱动的自动校准功能屏蔽,具体屏蔽方法还需要分析驱动源代码。

但这仅仅只是校准数值而已,如何把校准完的数值读出来呢?参考ftm_gsensor.c这个文件源代码,最终得知是通过打开/dev/gsensor这个节点,然后通过总线访问机制获取:

/sys/bus/platform/drivers/gsensor/sensordata这个文件存放的数据。

读取Gsensor的x,y,z的数据的方法可以参考static int gsensor_read(struct acc_priv *acc)这个函数的实现方法,但它的方法和我的是有区别的,MTK中实现的gsensor_read方法是读取从驱动中读取已经转化成十进制的数据,而我读取的是原始数据十六进制,所以必须要做进制转换,我们可以来看下这个函数:

static int gsensor_read(struct acc_priv *acc)
{
	static char buf[128];
	int x, y, z, err;

	if(acc->fd == -1)
	{
		FTGLOGE("invalid file descriptor\n");
		err = -EINVAL;
	}
	else if((acc->support_selftest == 1) && (!acc->selftest) && (err = gsensor_selftest(acc, 10, 20)))
	{
		FTGLOGE("selftest fail: %s(%d)\n", strerror(errno), errno);
	}
	else
	{
		//使用GSENSOR_IOCTL_READ_SENSORDATA命令获取sensor的数据,并存储在buf里
		err = ioctl(acc->fd, GSENSOR_IOCTL_READ_SENSORDATA, buf);
		if(err)
		{
			FTGLOGE("read data fail: %s(%d)\n", strerror(errno), errno);
		}
		//从buf中将x,y,z三个值取出来
		else if(3 != sscanf(buf, "%x %x %x", &x, &y, &z))
		{
			FTGLOGE("read format fail: %s(%d)\n", strerror(errno), errno);
		}
		else
		{
			//除以1000,并转成浮点数
			acc->evt.x = (float)(x)/1000;
			acc->evt.y = (float)(y)/1000;
			acc->evt.z = (float)(z)/1000;
			err = 0;
			gsensor_statistic(acc);
			//返回gsensor数据
			//add sensor data to struct sp_ata_data for PC side
			return_data.gsensor.g_sensor_x = acc->evt.x;
			return_data.gsensor.g_sensor_y = acc->evt.y;
			return_data.gsensor.g_sensor_z = acc->evt.z;
			return_data.gsensor.accuracy = 3;

		}
	}
	return err;
}

预知详情,可以去分析factory工厂测试的源码,看看具体实现,这里就简单的一笔带过了。

当然我们也可以采用:./pskyed/libs/em_emmc_comm/libhwm/include/libhwm.h这里面的读取gsensor数据的接口,如果要用就需要在Android.mk中包含相关的动态库。

使用adb进入Android根文件系统,此时,通过cat命令可以得知/sys/bus/platform/drivers/gsensor/sensordata这个文件存放的数据并不是字符串,而是十六进制数据,以下是机器平放在桌子上读取的x,y,z的数值:

Sensordata文件的数值:    算法转换:

-------------------------------------------------------------------------------------------------------------------------------

X:0000                                    转十进制(float)0/1000    =  0

Y:0072                                    转十进制(float)114/ 1000  = 0.114

Z:264f                                    转十进制(float)9807/ 1000 = 9.807

-------------------------------------------------------------------------------------------------------------------------------

x,y,z数值的校准范围是(0,0,9.8),以上数值说明机器校准后的数值是正确的,误差比较小。

在Window上用Notepad++打开这个文件看到里面的数据如下。



使用Winhex查看sensordata这个文件



以下是我实现的方法:

//Gsensor读取

//这个文件存放的数据不是字符串,而是十六进制数据,所以必须做进制转换,然后才能转成浮点数

#define	GSENSOR_NAME "/sys/bus/platform/drivers/gsensor/sensordata"
//存储gsensor节点数据的结构体
struct gsensor_info
{
	//x,y,z坐标值
	char x[10] ;
	char y[10] ;
	char z[10] ;
};
int Hex_to_dec(const char* str)  ;
static int check_flag ;
int Gsensor_Test()
{
	struct gsensor_info g ;
	char ln[80];//用于存取读出数据的数组
	FILE *f;
	int i,n;
	char *p;
	int x,y,z ;
	float x1,y1,z1 ;
	int xv = 0 , yv = 0 , zv = 0 ;
	while(1)
	{
		f=fopen(GSENSOR_NAME,"r");//打开txt文件
		if(NULL==f){
			printf("Can not open file sensordata!\n");//判断是否可以打开文件
			return 1;
		}
		i=0;
		while (1)
		{
		   //从文件中读取一行数据
		   if (NULL==fgets(ln,80,f))
				break;
		   p = ln ;
		   sscanf(p,"%s%s%s",g.x,g.y,g.z);
		   i++;
		}
		//存储的数据是十六进制,需要做数据转换
		x = Hex_to_dec(g.x);
		y = Hex_to_dec(g.y);
		z = Hex_to_dec(g.z);
		x1 = (float)x / 1000 ;
		y1 = (float)y / 1000 ;
		z1 = (float)z / 1000 ;
		printf("x: %4.2f   y:%4.2f  z:%4.2f\n",x1,y1,z1);
		break ;
	}
	return 0 ;
	while_r:
	while(1);
}
//16进制转10进制算法实现
int Hex_to_dec(const char* str)
{
    int value;  

    if (! str)
    {
        return 0;
    }
    value = 0;
    while (1)
    {
        if ((*str >= '0') && (*str <= '9'))
        {
            value = value*16 + (*str - '0');
        }
        else if ((*str >= 'A') && (*str <= 'F'))
        {
            value = value*16 + (*str - 'A') + 10;
        }
        else if ((*str >= 'a') && (*str <= 'f'))
        {
            value = value*16 + (*str - 'a') + 10;
        }
        else
        {
            break;
        }
        str++;
    }
    return value;
}
时间: 2024-11-02 14:21:16

MTK平台Android Gsensor数据校准与数据获取的相关文章

控制- android 的按键背光驱动 MTK平台

问题描述 android 的按键背光驱动 MTK平台 (MTK ) 关于android 按键背光的设置button-backlight 用GPIO电平来控制的话,这个结构体 cust_mt65xx_ledcust_led_list的对应行要怎么写?

android l版本-MTK平台,Android L版本,第三方输入法设为默认输入法的问题

问题描述 MTK平台,Android L版本,第三方输入法设为默认输入法的问题 按照FAQ上面的方法是在InputMethodManagerService.java中的systemRunning()方法中给perInstalledImeName赋值完整的第三方输入法包名ID,或者在system.prog文件中添加ro.mtk_default_ime的属性, String preInstalledImeName = SystemProperties.get("ro.mtk_default_ime&

Android平台中实现数据存储的5种方式_Android

本文介绍Android中的5种数据存储方式,具体内容如下   数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是:  1 使用SharedPreferences存储数据  2 文件存储数据  3 SQLite数据库存储数据  4 使用ContentProvider存储数据  5 网络存储数据   下面将为大家一一详细介绍.   第一种:使用SharedPreferences存储数据  SharedPreferences是Android平台上一个轻量级

各大市场研究公司针对Android和iOS两大平台发布的数据

回答了有关这两个平台竞争现状的各种问题.以下为文章全文:谁将在移动平台大战中胜出,苹果iOS还是谷歌Andorid?这已经成为博客圈最热门的科技话题之一.每出现一点新消息,都会引发大量的讨论.通常而言,博客在报道新闻时都会号称Android击败了iOS,或iOS击败了Android.不过,单独关注任何一项数据都是不明智的.如果你真正关注的是这两大移动操作系统的表现,而不是发布耸人听闻的消息,或是过于主观的判断,你肯定应该考虑众多数据.这也正是本文的目的.我在文中汇总了大量报告,专注于相对较新的内

Android保存数据

Android保存数据的方式,每种存储方式都各有不同,有如下四种: 1.Shared Preferences:主要用于保存程序的系统配置信息.用来存储"key-values paires".一般用于保存程序启动时设定的信息,以便在程序下一次启动时继续保留前一次设定的信息. 2.Files:用文件的形式保存信息.可以通过对文件的读写来获取或保存相关信息. 3.SQLite:用数据库的形式保存信息.SQLite是一个开源的数据库 系统. 4.NetWork:将数据保存于网络. 1. Pre

源码-做安卓驱动工程师 选用 全志平台 还是 MTK平台 ?哪个好?

问题描述 做安卓驱动工程师 选用 全志平台 还是 MTK平台 ?哪个好? MTK平台: mtk公司已经把Android源码优化了,把相关的驱动代码放到 mediatek 目录下, 主要修改相关的驱动就行,这样工程师跟内核的交互就少了,久而久之就不太熟悉 平台设备驱动等等: 全志平台: 我还没深入了解过. 有哪位大神对这两个平台比较了解, 做安卓驱动工程师 , 选择那款平台深入比较好? 解决方案 MTK挺好啊,高通平台也不错,全志平台没用过. 不过你做 android驱动工程师,如果不是 要做 平

我的Android进阶之旅------&amp;gt;Android实现数据存储技术

本文介绍Android中的5种数据存储方式. 数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 4 使用ContentProvider存储数据 5 网络存储数据 下面将为大家一一详细介绍. 第一种: 使用SharedPreferences存储数据 SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置

[lcm] MTK平台移植屏幕lcd过程要点

下拉项目和编译 参考吴庆亚添加LCM驱动 编译生成对应数据 为87工模添加lcm节点信息 TP fl10802 LCM himax_852xES 从单屏到多屏兼容 下拉项目和编译 [W5900] $ git clone ssh://172.16.16.15:29418/mtk_repository/MTK6580_WEG_L1_MP6.V2.19 $ git checkout -b MMI_W5900 origin/MMI_W5900 $ git pull $ source build/envs

Android开发笔记之Android中数据的存储方式(一)_Android

对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会有很大的促进作用. 总体的来讲,数据存储方式有三种:一个是文件,一个是数据库,另一个则是网络.其中文件和数据库可能用的稍多一些,文件用起来较为方便,程序可以自己定义格式:数据库用起稍烦锁一些,但它有它的优点,比如在海量数据时性能优越,有查询功能,可以加密,可以加锁,可以跨应用,跨平台等等:网络,则用于比较重要的事情,比如科研,勘探,航空等实时采集到的数据需要马上通过网络传输到数据处理中心进行存储并进行处理,有实时性的需求等.