在Android中对SD卡进行扇区级读写

来源:互联网 发布:淘宝首页添加链接代码 编辑:程序博客网 时间:2024/04/30 07:56

最近想在安卓手机系统中,对SD卡进行扇区读取,以便进行一些内部操作。经过多次尝试,终于和同事一起解决了这个问题,把心得给大家一起分析下。

首先必须明确一个条件,那就是如果手机系统没有Root过的话,是绝对不可以对磁盘进行扇区级操作的。所以,第一步,请先Root了你的手机或者模拟器吧。

Java语言本身是无法访问磁盘扇区的。所以想借助于Java提供的类库进行操作,此路也不通。

在安卓手机中,所有的硬件设备都是存储于/dev/block目录里,在这个目录你可以看见mmcblk0,mmcblk0p1等等。其中mmcblk0指得是SD卡的本身,mmcblk0p1指的是SD卡的第一个分区所在的位置,熟悉磁盘分区的朋友应该明白这个意思,简单解释就是,磁盘的mbr通过mmcblk0进行访问,而磁盘第一个分区往往开始于第64个扇区,注意,64这个数值是不固定的。也可能是其他值,比如我的SD卡就是129扇区。这数值可以通过解析mbr中的dpt分区表进行得到。

综上可得:在手机中想对SD卡的扇区进行操作,需要完成以下几步:

1、手机Root

2、获得dev/block/mmcblk0dev/block/mmcblk0p1的访问权限。

3、在Linux系统中编写扇区访问,通过GCC将其进行编译成Java可用的动态链接库文件(linux中以so后缀名结尾)。

贴一个Linux下写的访问扇区的函数的C代码

int ret = 0;

JNIEXPORT jint JNICALL Java_com_android_counter_Counter_readsd 
(JNIEnv *env, jobject obj,  jstring sdname, jint sectorstart, jcharArray buffer)
{
   size_t sector_size = 0;
 int col;
 unsigned short *array; 
 unsigned char *buf;
// jboolean *buf;
 int i;
// int res;

/***********      jstring to char *     ***********/
 char* rtn = NULL;
 jclass clsstring = (*env)->FindClass(env,"java/lang/String");
 jstring strencode = (*env)->NewStringUTF(env,"utf-8");
 jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B");
 jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,sdname, mid, strencode);
 jsize alen = (*env)->GetArrayLength(env,barr);
 jbyte* ba = (*env)->GetByteArrayElements(env,barr, JNI_FALSE);
 if (alen > 0)
 {
 rtn = (char*)malloc(alen + 1);
 memcpy(rtn, ba, alen);
 rtn[alen] = 0;
 }
 (*env)->ReleaseByteArrayElements(env,barr, ba, 0);

 int fd = open(rtn,O_RDONLY);
        if (fd == -1)    
 {
               // printf("Open \"sdname \" failed. %s\n",strerror(errno));
                return errno;     
 }
 
// jchar * buf = (*env)->GetCharArrayElements(env,buffer,0);


 ioctl(fd, BLKSSZGET, &sector_size);
// buffer = (unsigned char*)malloc(sector_size);
 buf = (unsigned char*)malloc(sector_size);
 
 lseek(fd,sectorstart * sector_size ,SEEK_SET);

// ret = read(fd,buffer,(unsigned int)sector_size);
 ret = read(fd,buf,(unsigned int)sector_size);
 printf("%d",ret);
 printf("\n");
// jcharArray iarr = (*env)->NewCharArray(env, sector_size);

 (*env)->SetByteArrayRegion(env,buffer, 0, sector_size, buf);
 
 if (ret < 0)         
 {
                        printf("Read sectors failed. %s\n",strerror(errno)); 
   return errno;
    }
    
    close(fd);
 return ret;    
}

需要注意的是,这个函数将得到的扇区存储在了字符数组中,长度是512。可是Cchar的长度为1,字节,而Javachar的长度为2字节。入口参数又是char test[512],哎,因此,在linux下必须对所得到的字符将其解析为字节。解析函数如下:

   int i=0;

    byte[] filebuffer;
    byte[] b_temp=new byte[2];
    filebuffer= new byte[512];

 //将读取到的扇区转为字节.
    for (i=0;i<256;i++)
    {
     b_temp=charToByte(c_test[i]);
     filebuffer[2*i]=b_temp[0];
       filebuffer[2*i+1]=b_temp[1];
    }
    c_test[512]是从扇区得到的内容。

 

基本上从以上知识就可以得到扇区的内容了。程序的完整代码基于版权的关系,无法完整提供。也算是个需要此操作的朋友提供一个思路吧。

原创文章,转载请完整转载。

有什么问题可以QQ探讨。QQ:2484908

原创粉丝点击