2572人阅读 评论(4) 收藏 举报 Android NTFS exFAT 自动挂载 源代码

目录(?)[+]

Android 不支持 NTFS 和 exFAT 格式的文件系统,但是 Linux 已经有相应的开源代码了,因此只需将其移植到 Android 上即可。

这里需要下载两份代码,分别是 ntfs-3g 和 exfat。下载地址ntfs-3gexfat。

由于 Android 并没有使用完整的 glibc 库,因此需要对源代码进行修改以使代码能被顺利地编译。


代码与编译好的文件都可以在 CSDN 资源里下载:

CyanogenMod10 ntfs 与 exfat 自动挂载支持


一、修改 ntfs-3g 代码

关于 ntfs-3g 代码的修改,可以参考 CSDN 上的这篇文章:ntfs-3g移植到android4.0.3方法总结。这里就不在重复叙述了。


二、修改 exfat 代码

exfat 也是使用了 fuse,但代码量很小。需要修改的地方不多:

1、fuse/main.c 文件

大约位于 264 行的fuse_exfat_statfs 函数,将参数中的 statvfs 改为 statfs,并将其代码中的sfs->f_namemax 改为sfs->f_namelen

[cpp] view plain copy
  1. sfs->f_favail=sfs->f_bfree>>ef.sb->spc_bits;
  2. sfs->f_ffree=sfs->f_bavail;
改为

[cpp] view plain copy
  1. sfs->f_ffree=sfs->f_bfree>>ef.sb->spc_bits;

2、libexfat/io.c

大约位于 255 行的exfat_seek 函数,将里面的 lseek 函数改为 lseek64;

大约位于 283 行的exfat_pread 函数,将里面的 pread 函数改为 pread64;

大约位于 295 行的exfat_pwrite 函数,将里面的 pwrite 函数改为 pwrite64。

3、将所有代码文件中的 off_t 类型全部换为 off64_t 类型

Android 的编译器编译出来的 off_t 类型是4字节的,只有改为 off64_t 才是8字节的。不改的话无法挂载超过 4G 的 SD 卡或 U 盘。


三、提取文件,编写 Android.mk 文件

这里我将所有的项目都放在了和 vold 同级的 system 目录下

1、libfuse

由于 ntfs-3g 和 exfat 都使用了 fuse,因此他们可以共享这个库。

在 system 目录新建 libfuse 文件夹,并建立子文件夹 src 和 include。将 ntfs-3g 中 libfuse-lite 中的所有文件复制到 libfuse/src 目录中,将 ntfs-3g 中 include/fuse-lite 中的所有文件复制到 libfuse/include 目录中,将 ntfs-3g 中的 config.h 复制到 libfuse 目录。

修改 libfuse/src/helper.c,在最后添加如下代码(exfat 需要):

[cpp] view plain copy
  1. intfuse_daemonize(intforeground)
  2. {
  3. intres;
  4. if(!foreground){
  5. res=daemon(0,0);
  6. if(res==-1){
  7. perror("fuse:failedtodaemonizeprogram\n");
  8. return-1;
  9. }
  10. }
  11. return0;
  12. }

在 libfuse 目录编写 Android.mk:

[plain] view plain copy
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_SRC_FILES:=\
  4. src/fuse.c\
  5. src/fusermount.c\
  6. src/fuse_kern_chan.c\
  7. src/fuse_loop.c\
  8. src/fuse_lowlevel.c\
  9. src/fuse_opt.c\
  10. src/fuse_session.c\
  11. src/fuse_signals.c\
  12. src/helper.c\
  13. src/mount.c\
  14. src/mount_util.c
  15. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include
  16. LOCAL_CFLAGS:=-O2-g-W-Wall-D_LARGEFILE_SOURCE-D_FILE_OFFSET_BITS=64-DHAVE_CONFIG_H
  17. LOCAL_MODULE:=libfuse
  18. LOCAL_MODULE_TAGS:=eng
  19. LOCAL_SYSTEM_SHARED_LIBRARIES:=libclibcutils
  20. include$(BUILD_STATIC_LIBRARY)

2、ntfs-3g

则里只提取挂载 NTFS 分区的文件。

在 system 目录新建 ntfs-3g 文件夹,并建立子文件夹 include、libntfs-3g 和 src。将 ntfs-3g 中 include/ntfs-3g 中的所有文件复制到 ntfs-3g/include 目录中,将 ntfs-3g 中 libntfs-3g 中的所有文件复制到 ntfs-3g/libntfs-3g 目录中,将 ntfs-3g 中 src 目录中的 ntfs-3g.c ntfs-3g_common.c ntfs-3g_common.h 复制到 ntfs-3g/src 目录中,将 ntfs-3g 中的 config.h 复制到 ntfs-3g 目录。

在 ntfs-3g 目录中编写 Android.mk:

[plain] view plain copy
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_SRC_FILES:=\
  4. libntfs-3g/acls.clibntfs-3g/attrib.clibntfs-3g/attrlist.c\
  5. libntfs-3g/bitmap.clibntfs-3g/bootsect.clibntfs-3g/cache.c\
  6. libntfs-3g/collate.clibntfs-3g/compat.clibntfs-3g/compress.c\
  7. libntfs-3g/debug.clibntfs-3g/device.clibntfs-3g/dir.c\
  8. libntfs-3g/efs.clibntfs-3g/index.clibntfs-3g/inode.c\
  9. libntfs-3g/lcnalloc.clibntfs-3g/logfile.clibntfs-3g/logging.c\
  10. libntfs-3g/mft.clibntfs-3g/misc.clibntfs-3g/mst.c\
  11. libntfs-3g/object_id.clibntfs-3g/realpath.clibntfs-3g/reparse.c\
  12. libntfs-3g/runlist.clibntfs-3g/security.clibntfs-3g/unistr.c\
  13. libntfs-3g/unix_io.clibntfs-3g/volume.c
  14. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/includesystem/libfuse/include
  15. LOCAL_CFLAGS:=-O2-g-W-Wall-D_LARGEFILE_SOURCE-D_FILE_OFFSET_BITS=64-DHAVE_CONFIG_H
  16. LOCAL_MODULE:=libntfs-3g
  17. LOCAL_MODULE_TAGS:=eng
  18. LOCAL_SYSTEM_SHARED_LIBRARIES:=libclibcutils
  19. include$(BUILD_STATIC_LIBRARY)
  20. include$(CLEAR_VARS)
  21. LOCAL_SRC_FILES:=\
  22. src/ntfs-3g.csrc/ntfs-3g_common.c
  23. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include$(LOCAL_PATH)/srcsystem/libfuse/include
  24. LOCAL_CFLAGS:=-O2-g-W-Wall-D_LARGEFILE_SOURCE-D_FILE_OFFSET_BITS=64-DHAVE_CONFIG_H
  25. LOCAL_MODULE:=ntfs-3g
  26. LOCAL_MODULE_TAGS:=eng
  27. LOCAL_SYSTEM_SHARED_LIBRARIES:=libc
  28. LOCAL_STATIC_LIBRARIES:=libfuselibntfs-3g
  29. include$(BUILD_EXECUTABLE)

3、ntfsfix

这个是用来在挂载 NTFS 分区前检查错误的。

在 system 目录下建立 ntfsfix 目录,并建立子目录 src。将 ntfs-3g 中 ntfsprogs 中的 ntfsfix.c sd.c sd.h utils.c utils.h 复制到 ntfsfix/src 目录,将 ntfs-3g 中的 config.h 复制到 ntfsfix 目录。

在 ntfsfix 目录下建立 Android.mk:

[plain] view plain copy
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_SRC_FILES:=\
  4. src/ntfsfix.c\
  5. src/utils.c\
  6. src/sd.c
  7. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/srcsystem/ntfs-3g/include
  8. LOCAL_CFLAGS:=-O2-g-W-Wall-D_LARGEFILE_SOURCE-D_FILE_OFFSET_BITS=64-DHAVE_CONFIG_H
  9. LOCAL_MODULE:=ntfsfix
  10. LOCAL_MODULE_TAGS:=eng
  11. LOCAL_SYSTEM_SHARED_LIBRARIES:=libc
  12. LOCAL_STATIC_LIBRARIES:=libntfs-3glibfuse
  13. include$(BUILD_EXECUTABLE)

4、mkntfs

这个是用来格式化分区为 NTFS 格式的。

在 system 目录下建立 mkntfs 目录,并建立子目录 src。将 ntfs-3g 中 ntfsprogs 中的 attrdef.c attrdef.h boot.c boot.h mkntfs.c sd.c sd.h utils.c utils.h 复制到 mkntfs/src 目录,将 ntfs-3g 中的 config.h 复制到 mkntfs 目录。

在 mkntfs 目录下建立 Android.mk:

[plain] view plain copy
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_SRC_FILES:=\
  4. src/attrdef.c\
  5. src/boot.c\
  6. src/utils.c\
  7. src/mkntfs.c\
  8. src/sd.c
  9. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/srcsystem/ntfs-3g/include
  10. LOCAL_CFLAGS:=-O2-g-W-Wall-D_LARGEFILE_SOURCE-D_FILE_OFFSET_BITS=64-DHAVE_CONFIG_H
  11. LOCAL_MODULE:=mkntfs
  12. LOCAL_MODULE_TAGS:=eng
  13. LOCAL_SYSTEM_SHARED_LIBRARIES:=libc
  14. LOCAL_STATIC_LIBRARIES:=libntfs-3glibfuse
  15. include$(BUILD_EXECUTABLE)

5、exfat

这里只提取挂载 exFAT 分区所需的文件。

在 system 目录下建立 exfat 目录。将 exfat 源代码中的 fuse 和 libexfat 文件夹复制到 exfat 目录中。

建立 Android.mk:

[plain] view plain copy
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_SRC_FILES:=\
  4. libexfat/cluster.clibexfat/io.clibexfat/log.c\
  5. libexfat/lookup.clibexfat/mount.clibexfat/node.c\
  6. libexfat/time.clibexfat/utf.clibexfat/utils.c
  7. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/libexfatsystem/libfuse/include
  8. LOCAL_CFLAGS:=-O2-g-W-Wall-D_LARGEFILE_SOURCE-D_FILE_OFFSET_BITS=64-UUSE_UBLIO
  9. LOCAL_MODULE:=libexfat
  10. LOCAL_MODULE_TAGS:=eng
  11. LOCAL_SYSTEM_SHARED_LIBRARIES:=libclibcutils
  12. include$(BUILD_STATIC_LIBRARY)
  13. include$(CLEAR_VARS)
  14. LOCAL_SRC_FILES:=\
  15. fuse/main.c
  16. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/libexfatsystem/libfuse/include
  17. LOCAL_CFLAGS:=-O2-g-W-Wall-D_LARGEFILE_SOURCE-D_FILE_OFFSET_BITS=64-DUSE_UBLIO
  18. LOCAL_MODULE:=exfat
  19. LOCAL_MODULE_TAGS:=eng
  20. LOCAL_SYSTEM_SHARED_LIBRARIES:=libc
  21. LOCAL_STATIC_LIBRARIES:=libfuselibexfat
  22. include$(BUILD_EXECUTABLE)

6、exfatfsck

这个是用来在挂载 exFAT 分区前检查错误的。

在 system 目录建立 exfatfsck 目录,并将 exfat 源代码中 fsck/main.c 复制到 exfatfsck 目录中。

建立 Android.mk(这里只列出关键的两行):

[plain] view plain copy
  1. LOCAL_SRC_FILES:=\
  2. main.c
  3. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/srcsystem/exfat/libexfat

7、mkexfatfs

这个是用来格式化分区为 exFAT 格式的。

在 system 目录下建立 mkexfatfs 目录,并建立子目录 src。将 exfat 源代码中 mkfs 目录下的所有文件复制到 mkexfatfs/src 目录中。

建立 Android.mk(关键部分):

[plain] view plain copy
  1. LOCAL_SRC_FILES:=\
  2. src/cbm.c\
  3. src/fat.c\
  4. src/main.c\
  5. src/mkexfat.c\
  6. src/rootdir.c\
  7. src/uct.c\
  8. src/uctc.c\
  9. src/vbr.c
  10. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/srcsystem/exfat/libexfat


四、修改 vold 代码

CyanogenMod 的 vold 代码包含了 Ntfs.cpp 和 Ntfs.h,但是需要修改

1、修改 Ntfs.cpp

添加全局变量:

[cpp] view plain copy
  1. staticcharMOUNT_NTFS_PATH[]="/system/bin/ntfs-3g";
  2. staticcharMKNTFS_PATH[]="/system/bin/mkntfs";
  3. staticcharNTFSFIX_PATH[]="/system/bin/ntfsfix";

check 函数:

[cpp] view plain copy
  1. intNtfs::check(constchar*fsPath){
  2. boolrw=true;
  3. if(access(NTFSFIX_PATH,X_OK)){
  4. SLOGW("Skippingfschecks\n");
  5. return0;
  6. }
  7. intrc=-1;
  8. do{
  9. constchar*args[3];
  10. args[0]=NTFSFIX_PATH;
  11. args[1]=fsPath;
  12. args[2]=NULL;
  13. rc=logwrap(3,args,1);
  14. switch(rc){
  15. case0:
  16. SLOGI("NTFSFilesystemcheckcompletedOK.\n");
  17. return0;
  18. case1:
  19. SLOGI("NTFSFilesystemcheckfailed.\n");
  20. return0;
  21. default:
  22. SLOGE("NTFSFilesystemcheckfailed(unknownexitcode%d).\n",rc);
  23. errno=EIO;
  24. return-1;
  25. }
  26. }while(0);
  27. return0;
  28. }

doMount 函数:

[cpp] view plain copy
  1. intNtfs::doMount(constchar*fsPath,constchar*mountPoint,
  2. boolro,boolremount,boolexecutable,
  3. intownerUid,intownerGid,intpermMask,boolcreateLost){
  4. intrc;
  5. unsignedlongflags;
  6. charmountData[255];
  7. charoptions[255]={};
  8. constchar*args[6];
  9. flags=MS_NODEV|MS_NOSUID|MS_DIRSYNC;
  10. flags|=(executable?0:MS_NOEXEC);
  11. flags|=(ro?MS_RDONLY:0);
  12. flags|=(remount?MS_REMOUNT:0);
  13. //Testing/security,mountrouptonow
  14. flags|=MS_RDONLY;
  15. /*
  16. *Note:Thisisatemporaryhack.Ifthesamplingprofilerisenabled,
  17. *wemaketheSDcardworld-writablesoanyprocesscanwritesnapshots.
  18. *
  19. *TODO:Removethiscodeoncewehaveadropboxinsystem_server.
  20. */
  21. charvalue[PROPERTY_VALUE_MAX];
  22. property_get("persist.sampling_profiler",value,"");
  23. if(value[0]=='1'){
  24. SLOGW("TheSDcardisworld-writablebecausethe"
  25. "'persist.sampling_profiler'systempropertyissetto'1'.");
  26. permMask=0;
  27. }
  28. sprintf(mountData,
  29. "uid=%d,gid=%d,fmask=%o,dmask=%o",
  30. ownerUid,ownerGid,permMask,permMask);
  31. if(!remount){
  32. SLOGI("Tryingtousentfs-3gprogramtomount%s",fsPath);
  33. if(ro)
  34. snprintf(options,sizeof(options),"ro,%s",mountData);
  35. else
  36. snprintf(options,sizeof(options),"%s",mountData);
  37. args[0]=MOUNT_NTFS_PATH;
  38. args[1]="-o";
  39. args[2]=options;
  40. args[3]=fsPath;
  41. args[4]=mountPoint;
  42. args[5]=NULL;
  43. rc=logwrap(6,args,1);
  44. if(rc==0){
  45. SLOGI("ntfs-3gexecutedsuccessfully.");
  46. }else{
  47. SLOGE("Failedtoexecutentfs-3g.");
  48. }
  49. }else{
  50. rc=mount(fsPath,mountPoint,"fuseblk",flags,mountData);
  51. }
  52. if(rc&&errno==EROFS){
  53. SLOGE("%sappearstobeareadonlyfilesystem-retryingmountRO",fsPath);
  54. flags|=MS_RDONLY;
  55. if(!remount){
  56. SLOGI("Tryingtousentfs-3gprogramtomount%sasread-only",fsPath);
  57. snprintf(options,sizeof(options),"ro,%s",mountData);
  58. args[0]=MOUNT_NTFS_PATH;
  59. args[1]="-o";
  60. args[2]=options;
  61. args[3]=fsPath;
  62. args[4]=mountPoint;
  63. args[5]=NULL;
  64. rc=logwrap(6,args,1);
  65. if(rc==0){
  66. SLOGI("ntfs-3gexecutedsuccessfullyforread-only.");
  67. }else{
  68. SLOGE("Failedtoexecutentfs-3gforread-only.");
  69. }
  70. }else{
  71. rc=mount(fsPath,mountPoint,"fuseblk",flags,mountData);
  72. }
  73. }
  74. returnrc;
  75. }

format 函数:

[cpp] view plain copy
  1. intNtfs::format(constchar*fsPath,unsignedintnumSectors){
  2. constchar*args[5];
  3. charstrNumOfSectors[16]={};
  4. intrc;
  5. args[0]=MKNTFS_PATH;
  6. args[1]="-f";
  7. args[2]=fsPath;
  8. if(numSectors){
  9. snprintf(strNumOfSectors,sizeof(strNumOfSectors),"%u",numSectors);
  10. args[3]=strNumOfSectors;
  11. args[4]=NULL;
  12. rc=logwrap(5,args,1);
  13. }else{
  14. args[3]=NULL;
  15. rc=logwrap(4,args,1);
  16. }
  17. if(rc==0){
  18. SLOGI("FilesystemformattedOK");
  19. return0;
  20. }else{
  21. SLOGE("Formatfailed(unknownexitcode%d)",rc);
  22. errno=EIO;
  23. return-1;
  24. }
  25. return0;
  26. }

2、添加 ExFat.h 和 ExFat.cpp

这里请使用 Ntfs.h 和 Ntfs.cpp 作为模板。

关键代码:

[cpp] view plain copy
  1. staticcharMOUNT_EXFAT_PATH[]="/system/bin/exfat";
  2. staticcharMKFS_EXFAT_PATH[]="/system/bin/mkexfatfs";
  3. staticcharFSCK_EXFAT_PATH[]="/system/bin/exfatfsck";
  4. intExFat::check(constchar*fsPath){
  5. boolrw=true;
  6. if(access(FSCK_EXFAT_PATH,X_OK)){
  7. SLOGW("Skippingfschecks\n");
  8. return0;
  9. }
  10. intrc=-1;
  11. do{
  12. constchar*args[3];
  13. args[0]=FSCK_EXFAT_PATH;
  14. args[1]=fsPath;
  15. args[2]=NULL;
  16. rc=logwrap(3,args,1);
  17. switch(rc){
  18. case0:
  19. SLOGI("exFATFilesystemcheckcompletedOK.\n");
  20. return0;
  21. case1:
  22. SLOGI("exFATFilesystemcheckfailed.\n");
  23. return0;
  24. default:
  25. SLOGE("exFATFilesystemcheckfailed(unknownexitcode%d).\n",rc);
  26. errno=EIO;
  27. return-1;
  28. }
  29. }while(0);
  30. return0;
  31. }
  32. intExFat::doMount(constchar*fsPath,constchar*mountPoint,
  33. boolro,boolremount,boolexecutable,
  34. intownerUid,intownerGid,intpermMask,boolcreateLost){
  35. intrc;
  36. unsignedlongflags;
  37. charmountData[255];
  38. constchar*args[4];
  39. flags=MS_NODEV|MS_NOSUID|MS_DIRSYNC;
  40. flags|=(executable?0:MS_NOEXEC);
  41. flags|=(ro?MS_RDONLY:0);
  42. flags|=(remount?MS_REMOUNT:0);
  43. //Testing/security,mountrouptonow
  44. flags|=MS_RDONLY;
  45. sprintf(mountData,
  46. "uid=%d,gid=%d,fmask=%o,dmask=%o",
  47. ownerUid,ownerGid,permMask,permMask);
  48. if(!remount){
  49. SLOGI("Tryingtouseexfatprogramtomount%s",fsPath);
  50. args[0]=MOUNT_EXFAT_PATH;
  51. args[1]=fsPath;
  52. args[2]=mountPoint;
  53. args[3]=NULL;
  54. rc=logwrap(4,args,1);
  55. if(rc==0){
  56. SLOGI("exfatexecutedsuccessfully.");
  57. }else{
  58. SLOGE("Failedtoexecuteexfat.");
  59. }
  60. }else{
  61. rc=mount(fsPath,mountPoint,"fuseblk",flags,mountData);
  62. }
  63. returnrc;
  64. }
  65. intExFat::format(constchar*fsPath,unsignedintnumSectors){
  66. constchar*args[3];
  67. charstrNumOfSectors[16]={};
  68. intrc;
  69. args[0]=MKFS_EXFAT_PATH;
  70. args[1]=fsPath;
  71. args[2]=NULL;
  72. rc=logwrap(3,args,1);
  73. if(rc==0){
  74. SLOGI("FilesystemformattedOK");
  75. return0;
  76. }else{
  77. SLOGE("Formatfailed(unknownexitcode%d)",rc);
  78. errno=EIO;
  79. return-1;
  80. }
  81. return0;
  82. }

3、修改 Volume.cpp

添加#include "Ntfs.h"

找到Volume::mountVol() 函数

找到else if (strcmp(fstype, "ntfs") == 0) 部分,在后面添加以下代码:

[cpp] view plain copy
  1. if(Ntfs::check(devicePath)){
  2. errno=EIO;
  3. /*Badness-abortthemount*/
  4. SLOGE("%sfailedFSchecks(%s)",devicePath,strerror(errno));
  5. setState(Volume::State_Idle);
  6. free(fstype);
  7. return-1;
  8. }

找到和if (fstype != NULL) 对应的 else 块,在后面添加以下代码:

[cpp] view plain copy
  1. //CheckifthefilesystemisexFAT
  2. FILE*volf=fopen(devicePath,"rb");
  3. intbytesRead=0;
  4. if(volf){
  5. charfschar[5];
  6. //ReadthesignatureinthePBR
  7. fseek(volf,3,SEEK_SET);
  8. bytesRead=fread(fschar,1,5,volf);
  9. fclose(volf);
  10. if(bytesRead==5&&strcmp(fschar,"EXFAT")==0){
  11. if(ExFat::check(devicePath)){
  12. errno=EIO;
  13. /*Badness-abortthemount*/
  14. SLOGE("%sfailedFSchecks(%s)",devicePath,strerror(errno));
  15. setState(Volume::State_Idle);
  16. free(fstype);
  17. return-1;
  18. }
  19. if(ExFat::doMount(devicePath,"/mnt/secure/staging",false,false,false,
  20. AID_SYSTEM,gid,0702,true)){
  21. SLOGE("%sfailedtomountviaexFAT(%s)\n",devicePath,strerror(errno));
  22. continue;
  23. }else{
  24. gotomountSuccess;
  25. }
  26. }
  27. }

然后转到 if (fstype != NULL) 的 else 的末尾,在语句块之后,SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint()); 之前添加mountSuccess: 跳转标签。

4、修改 vold 的 Android.mk

天际common_src_files += ExFat.c


五、修改 build/target/product/base.mk

添加

[plain] view plain copy
  1. PRODUCT_PACKAGES+=\
  2. libfuse\
  3. ntfs-3g\
  4. exfat\
  5. mkntfs\
  6. ntfsfix\
  7. mkexfatfs\
  8. exfatfsck



六、编译

如果不出意外的话,编译之后就可以直接使用了。

更多相关文章

  1. android EditText设置不可写
  2. android 使用html5作布局文件: webview跟javascript交互
  3. android studio调试c/c++代码
  4. IM-A820L限制GSM,WCDMA上网的原理(其他泛泰机型可参考)7.13
  5. 锁屏界面
  6. android(NDK+JNI)---Eclipse+CDT+gdb调试android ndk程序
  7. Android(安卓)version and Linux Kernel version
  8. Android(安卓)闹钟管理类的使用
  9. Android学习篇之Menu的使用

随机推荐

  1. android各版本的sdk区别
  2. Android之内嵌PDF预览
  3. Android(安卓)Studio Rendering Problems
  4. Android上的SQLLite性能分析
  5. android中Animation的使用!
  6. 画出 Android 的大体架构图
  7. Android APK 签名比对
  8. Android无障碍服务( Accessibility Servi
  9. OOM----内存溢出或内存泄漏
  10. Android设计缺陷--无法通话录音