星期一, 十二月 30, 2013

星期四, 十二月 26, 2013

icu 52.1 for android window 下交叉编译 mingw-64/msys

00.下载android ndk http://developer.android.com/tools/sdk/ndk/index.html
01.下载安装MSys http://www.mingw.org/wiki/MSYS 1.01
02.下载gcc 3.8.1 w64版本,比官方版本修复了一些c++11bug,http://mingw-w64.sourceforge.net/
03.下载icu 代码52.1版本 http://site.icu-project.org/download/52#TOC-ICU4C-Download
04.展开icu代码到d:\icu
05.进入msys 环境
,使用export PATH将msys 1.0 bin目录和mingw bin目录加入到PATH里.
06.cd /d/icu;mkdir mingw;mkdir android;cd mingw
   这里主要是按照icu 目录下的README.html里的cross compile的步骤.
07. ../source/runConfigureICU MinGW ;#生成配置文件  然后执行make 开始编译
这里将自动在当前mingw目录下的bing子目录里生成后面需要的一些icu打包工具
  并生成mingw 下的icu相应的库,见本文后面详细的库名解释.所有的库在lib子目录里
在msys+mingw的编译是很顺利的,没有任何错误,麻烦就在于交叉编译。

08.cd ../android 准备使用交叉编译生成android下使用的库.
09. 准备生成编译icu的android ndk 独立工具链包执行
  比如:
  /d/android-ndk-r9b/build/tools/make-standalone-toolchain.sh --platform=android-9 --install-dir=/c/temp/my-toolchain -- toolchain=arm-linux-androideabi-4.8
如果是window 7/8 64 bit 需要加上 --system=windowx86_64
然后将export PATH将msys 1.0 bin目录和/c/temp/my-toolchain/bin及ndk 独立工具链目录下的arm-linux-androideabi/bin/
目录都放入到PATH变量中,在arm-linux-androideabi/bin/目录下有需要建库的ar.exe工具,所以必须加入到PATH变量里。
   export PATH=/d/msys/1.0/bin/:/d/androidgcc/bin/:/d/androidgcc/arm-linux-androideabi/bin/
用的是gcc 4.8.1 reversion 5版本。
10. ../source/configure --host=arm-linux-androideabi --target=arm-linux-androideabi --build=i686-pc-mingw32 --with-cross-build=/d/icu/mingw -enable-shared --disable-static

以下语法顺利生成静态链接库!!!()
$ sh ../source/configure --host=armv6-google-linux --enable-static --disable-shared -with-cross-build=/d/icu/mingw CC=a
rm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ AR=arm-linux-androideabi-ar
make 

再尝试只生成动态库,在data 目录下make出现许多问题,这个data模式只在尝试将data打包成动态库的方式的出现问题,
所以尝试用其他选项避开该问题。
$ sh ../source/configure --host=armv6-google-linux --enable-shared=yes --disable-static -with-cross-build=/d/icu/mingw CC=a
rm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ AR=arm-linux-androideabi-ar --with-data-packaging=archive

make
经过阅读 http://userguide.icu-project.org/icudata 可以看到这个data库并不是必须的,不影响常规的功能使用,如果是用
archive的方式,可以让数据和应用分类,更新该.dat数据文档,不需要重新编译icu的程序. 这样使用 --with-data-packaging=archive
最后生成的动态库如图,而字典.dat文件在/d/icu/android/data/out/icudt52l.dat ,可以将该文件和ICU程序一起发布
该文件比较巨大,可以在网站下下载定制的字典数据文件:http://apps.icu-project.org/datacustom/

可能的错误:
   注意,如果这里出现错误说不支持arm-linux-androideabi,需要下载补丁覆盖修改
     source目录config.sub和config.guess,然后再次执行该命令
需要下载支持android版本 config.sub
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD

以及config.guess source目录下
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
11.make开始编译,这里52.1版本编译data目录下的时候出现一些错误.
错误一:../../source/common/putil.cpp:133:22: fatal error: langinfo.h: No such file or directory
#include <langinfo.h>
从http://ftp.cc.uoc.gr/mirrors/OpenBSD/src/include/ 下载langinfo.h和nl_types.h 到/d/ic/source/common目录下,
再重新make clean;make.

错误二:
android/common: make 
rm -f ../lib/libicuuc.so.52 && ln -s libicuuc.so.52.1 ../lib/libicuuc.so.52
ln: creating symbolic link `../lib/libicuuc.so.52' to `libicuuc.so.52.1': No such file or directory
通过使用make -d 查询到规则是.o规则,最后在
D:\icu\source\config\mh-linux 中修改对应%.o的规则加上目录../lib修复该错误。
%.$(SO).$(SO_TARGET_VERSION_MAJOR): %.$(SO).$(SO_TARGET_VERSION)
     $(RM) $@ && ln -s ../lib/${<F} $@
%.$(SO): %.$(SO).$(SO_TARGET_VERSION_MAJOR)
     $(RM) $@ && ln -s ../lib/${*F}.$(SO).$(SO_TARGET_VERSION) $@

回到/d/icu/android 继续make 还会出现其他错误,但都可以通过提示反复修改mk-linx并继续make通过错误,
这是由于相对路径的错误造成的,具体原因可能是sed获取路径模式出现问题。

错误三:
android/data:
pkgdata: bash -c "arm-linux-androideabi-gcc -D_REENTRANT  -DU_HAVE_ELF_H=1 -DU_HAVE_ATOMIC=1  -DU_ATTRIBUTE_DEPRECATED=
-O2 -std=c99 -Wall -pedantic -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings   -c -I../../source/common -I
../common -DPIC -fPIC -o ./out/tmp/icudt52l_dat.o ./out/tmp/icudt52l_dat.s"
pkgdata: bash -c "arm-linux-androideabi-gcc -O2 -std=../lib/libicudata.lib -nodefaultlibs -nostdlib -o ../lib/icudata.so
.52 ./out/tmp/icudt52l_dat.o -Wl,-soname -Wl,icudata.so.52  -Wl,-Bsymbolic"
arm-linux-androideabi-gcc.exe: error: unrecognized command line option '-std=../lib/libicudata.lib'
-- return status = 1
Error generating library file. Failed command: arm-linux-androideabi-gcc -O2 -std=../lib/libicudata.lib -nodefaultlibs -
nostdlib -o ../lib/icudata.so.52 ./out/tmp/icudt52l_dat.o -Wl,-soname -Wl,icudata.so.52  -Wl,-Bsymbolic
Error generating assembly code for data.
很明显是 -std 后面的选项出现了错误
cd android\data ;make -d 查看是那个规则出现的错误
发现是D:\icu\source\tools\pkgdata\pkgdata.cpp  method pkg_checkFlag,代码逻辑错误:
1858行代码,将部分数据丢,Mingw 下不需要如此处理:
     #if U_PLATFORM == U_PF_CYGWIN
         uprv_memset(flag + position, 0, length - position);
     #endif

修正该错误后,依然不能通过,依然是无法发现:../lib/libicudata.lib

10.
首先要看README.html 

How To Cross Compile ICU 里有如何骄交叉编译的步骤

Here are some useful links regarding ICU and internationalization in general.
ICU, ICU4C & ICU4J Homepagehttp://icu-project.org/
FAQ - Frequently Asked Questions about ICUhttp://userguide.icu-project.org/icufaq
ICU User's Guidehttp://userguide.icu-project.org/
How To Use ICUhttp://userguide.icu-project.org/howtouseicu
Download ICU Releaseshttp://site.icu-project.org/download
ICU4C API Documentation Onlinehttp://icu-project.org/apiref/icu4c/
Online ICU Demoshttp://demo.icu-project.org/icu-bin/icudemos
Contacts and Bug Reports/Feature Requestshttp://site.icu-project.org/contacts

Library NameWindows FilenameLinux FilenameComment
Data LibraryicudtXYl.dlllibicudata.so.XY.ZData required by the Common and I18n libraries. There are many ways to package and customize this data, but by default this is all you need.
Common LibraryicuucXY.dlllibicuuc.so.XY.ZBase library required by all other ICU libraries.
Internationalization (i18n) LibraryicuinXY.dlllibicui18n.so.XY.ZA library that contains many locale based internationalization (i18n) functions.
Layout EngineiculeXY.dlllibicule.so.XY.ZAn optional engine for doing font layout.
Layout Extensions EngineiculxXY.dlllibiculx.so.XY.ZAn optional engine for doing font layout that uses parts of ICU.
ICU I/O (Unicode stdio) LibraryicuioXY.dlllibicuio.so.XY.ZAn optional library that provides a stdio like API with Unicode support.
Tool Utility LibraryicutuXY.dlllibicutu.so.XY.ZAn internal library that contains internal APIs that are only used by ICU's tools. If you do not use ICU's tools, you do not need this library.


参看README.html里有关cross complile的步骤:

Three initially-empty directories will be used in this example:
/icua copy of the ICU source
/buildAan empty directory, it will contain ICU built for A
(MacOSX in this case)
/buildBan empty directory, it will contain ICU built for B
(HaikuOS in this case)
  1. Check out or unpack the ICU source code into the /icu directory.You will have the directories /icu/source, etc.
  2. Build ICU in /buildA normally (using runConfigureICU or configure):
    cd /d/icu/mingw
    sh /d/icu/source/runConfigureICU MinGW
    gnumake
    
  3. Set PATH or other variables as needed, such as CPPFLAGS.
  4. Build ICU in /buildB
    Note: "--with-cross-build" takes an absolute path.
    cd /d/icu/android
    sh /d/icu/source/configure  --host=arm-linux-androideabi --with-cross-build=/d/icu/mingw
    gnumake
    
  5. Tests and testdata can be built with cd test;make

星期五, 十二月 20, 2013

android NDK 编译常用c开源库curl和sqlite

编译curl

1.安装msys 1.0
2.制作android独立编译工具链,这里是最新的android ndk r9b
$NDK/build/tools/make-standalone-toolchain.sh --platform=android-9 --toolchina=arm-linux-androideabi-4.8 --install-dir=/d/androidgcc
这里是安装到d:\androidgcc目录下

3.下载最新curl源代码http://curl.haxx.se/download.htm

4. 进入msys 环境
5.修改PATH环境变量
   export PATH=/d/androidgcc/bin
6.进入curl源代码目录比如C:\curl-7.33.0\
     cd /c/curl-7.33.0
7.运行配置命令,告知是跨平台编译通过--host
    ./configure --host=arm-linux-androideabi   如果一切正确,最后生成标准的配置文件
8.make 开始编译,最后生成的静态库及动态库 curl-7.33.0\lib\.libs 目录下.a为静态库,.so为动态库

如果要使用静态库编译独立的可执行文件,需要在编译包含curl 函数调用的源文件加上-DCURL_STATICLIB
window下需要加入 并在最后添加如下系统库:
  d:\curl-7.33.0\libcurl.a -lws2_32 -lwldap32

Android 需要在连接生成可执行文件的时候加上 -lz
否则出现:undefined reference to 'inflateEnd'  的错误。


编译sqlite 381

同理,安装msys 1.0 和制作android 独立编译工具链同上。
1.安装msys 1.0
2.制作android独立编译工具链,这里是最新的android ndk r9b
$NDK/build/tools/make-standalone-toolchain.sh --platform=android-9 --toolchina=arm-linux-androideabi-4.8 --install-dir=/d/androidgcc
这里是安装到d:\androidgcc目录下
3.下载最新sqlite 源代码:http://www.sqlite.org/download.html  Source Code 部分下载对应最新代码
  我使用的是3.8.1
  4.进入sqlite 源代码目录 cd /d/temp
  5.运行编译命令
     arm-linux-androideabi-gcc  sqlite3.c -fpic -shared -o libsqlite381.so
     得到动态库,如果想要静态库,请 加上-static 编译选项
6.测试是否成功代码,读取sqlite 版本号
   #include <stdio.h>
#include "sqlite3.h"
main()
{
printf("version is %s\n",sqlite3_libversion());
printf("sqlite3_sourceid is %s\n",sqlite3_sourceid());
}
然后编译成android 下执行文件:
arm-linux-androideabi-gcc getv.c   -o getv.android.exe    libsqlite381.so
准备传送到手机上测试:

D:\temp>adb push libsqlite381.so /sdcard/temp
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
2808 KB/s (853708 bytes in 0.296s)

D:\temp>adb push getv.android.exe /sdcard/temp
6 KB/s (6204 bytes in 1.000s)

D:\temp>adb shell
shell@maguro:/ $ su
su
root@maguro:/ # cd /system/tmp
cd /system/tmp
root@maguro:/system/tmp # cp /sdcard/temp/libsqlite381.so .
cp /sdcard/temp/libsqlite381.so .

root@maguro:/system/tmp # cp /sdcard/temp/getv.*.exe .
cp /sdcard/temp/getv.*.exe .
root@maguro:/system/tmp # chmod 755 getv.android.exe
chmod 755 getv.android.exe
root@maguro:/system/tmp # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/system/tmp
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/system/tmp
root@maguro:/system/tmp # ./getv.android.exe
./getv.android.exe
version is 3.8.1
sqlite3_sourceid is 2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a
240|root@maguro:/system/tmp # 
all is work!perfect
     

星期四, 十二月 19, 2013

改变javac的错误提示信息的语言。Change Javac Error Message Language

使用-J传递进去系统变量设置。
javac -J-Duser.language=en
chang error message to english.
改变错误信息为英语提示了。


星期三, 十二月 18, 2013

About c++ Excpetion处理

C++只所以被很多人鄙视,认为难学很大一部分是由于历史进化造成的。
C++作为super c,很多设计受到设计师的思维和编码习惯约束,典型的技术债
(technical debt).
和java那浑然天成的Exception 处理,c++的一场处理就是一个充满了设计师
个人经验思维局限和实验的大杂烩。
 很难想象,如果尝试用c++ ifstream open 一个不存在的文件错误,竟然没有
扔出异常,而是丑陋和另类的 good,bad fail,eof.
怎么不来一个stupid方法呢?
而且竟然没有完整的错误信息文字,只是丑陋的state.

如何偿还技术债,是c++重生的前提,我在c++11里,还没有看到整体的一种
规划和设计。


星期二, 十二月 17, 2013

string.find 和pcre regular match 那个快?

通过对比12万条的记录,查找同时包含2个子字符串的字符串行,
使用pcre需要7328 milliseconds
而调用2次 .find 时间是:2891 milliseconds

如果不是regular expression 写的不够聪明,就是regular 在简单查询上的确慢。

当然扩展性是regular 好了,只要将regular pattern string 传递函数即可。
字符串find 则需要编写非常复杂的代码表达简单的逻辑判断。

效率也基本是2~3倍的差距。几千行的数据比较,基本都在1秒内完成。


星期五, 十二月 13, 2013

C++ 11 迷茫的语言设计师们

刚刚看完c++11的激动过去了,再实际测试使用中,碰到了许多啼笑皆非的语言行为,
或者说实现和设计完全背离的行为。
C++11给出了很好的uniform initialization的方式。即花括号{}
auto i{10};非常优雅。
但是,且慢。
struct ABC_def
{
  string name;
  int tall{20};//给个默认的初始值吧。
}
然后
ABC_def test={"William",1000};
g++ 4.8.1 编译通不过了。
blabla:
error: could not convert '{"William",1000}' from '<brace-enclosed initializer list>' to 'BALL_DATA'
  BALL_DATA data=
{"William",1000};
 
What Hell?
Google !果然发现了有关聚合初始化的一些语言规范限制:
http://en.cppreference.com/w/cpp/language/aggregate_initialization
 
no brace-or-equal initializers for non-static members 非静态成员.不能有默认的值语法
 
 为什么语言规范里会有这么愚蠢的限制?且慢吐槽!先看看规范提交大师们的解释或者思路。
找了许久,只是看到一些讨论的帖子,完全没有找到一个理由解释这种限制的原因,
而且据说要在c++14里消掉这种限制............
 
C++ 的各位大神把一个语言规范弄成这样。。。惭愧吗?
 
 
 

规则表达开源库PCRE向Android下的移植步骤 window 下mingw64 gcc/g++ 4.8.1

pcre向Android下的移植 window 下mingw64 4.8.1

该编译需要在msys环境下运行,所以必须准备的环境是:
1.Android ndk (我使用的是android ndk r9b )
2.msys (http://www.mingw.org/wiki/MSYS)下载http://downloads.sourceforge.net/mingw/MSYS-1.0.11.exe。安装到d:\msys
3.下载 pcre 8.33包www.pcre.org
4.展开pcre 8.33 包pcre-8.33.zip 到d:\
 以下是步骤。

1.准备独立的android ndk toolchain,
D:\Android\android-ndk-r9b\build\tools\make-standalone-toolchain.bat --platform=android-9 --install-dir=d:\temp\my-toolchain --toolchain=arm-linux-androideabi-4.8
2.进入 msys shell 通过桌面快捷方式或者d:\msys\1.0\msys.bat都可以.
 运行mount 可以看到系统的各个盘被映射的方式 window d:盘 映射为  /d
3.将目录输入到PATH里
 export PATH=/d/temp/my-toolchina/bin:/d/msys/1.0/bin/
./configure --host=arm-linux-androideabi --prefix=G:/William_Wang/pcre-8.33 
--disable-shared --enable-newline-is-anycrlf --enable-utf8 --enable-unicode-properties
$ make #等待稍长时间后,在.libs目录下生成了.a静态库和.so后缀的动态库,由于--disable-shared禁止了动态库,所以只有.a的静态库了
$ make install 
此时在pcre-8.33目录下生成了android 命令行程序 pcretest
adb push pcretest /sdcard/temp/然后adb shell 进入超级用户后,如果手机已经root了,可以chmod 755 pcretest 权限后,直接运行。
即可。

PCRE configure 参数清单
 
 
 

    Build 8 bit pcre library ........ : yes --disable-pcre8
    Build 16 bit pcre library ....... : no --enable-pcre16
    Build 32 bit pcre library ....... : no --enable-pcre32
    Build C++ library ............... : yes --disable-cpp
    Enable JIT compiling support .... : no --enable-jit
    Enable UTF-8/16/32 support ...... : yes --enable-utf8
    Unicode properties .............. : yes --enable-unicode-properties
    Newline char/sequence ........... : anycrlf --enable-newline-is-anycrlf
    \R matches only ANYCRLF ......... : no --enable-bsr-anycrlf
    EBCDIC coding ................... : no   --enable-ebcdic
    EBCDIC code for NL .............. : n/a --enable-ebcdic-nl25
    Rebuild char tables ............. : no   --enable-rebuild-chartables
    Use stack recursion ............. : yes --disable-stack-for-recursion
    POSIX mem threshold ............. : 10 --with-posix-malloc-threshold=20
    Internal link size .............. : 2 --with-link-size=2
    Match limit ..................... : 10000000 --with-match-limit=10000000
    Match limit recursion ........... : MATCH_LIMIT --with-match-limit-recursion=10000
    Build shared libs ............... : no --disable-shared
    Build static libs ............... : yes --disable-static
    Use JIT in pcregrep ............. : no --disable-pcregrep-jit
    Buffer size for pcregrep ........ : 20480 --with-pcregrep-bufsize=20K
    Link pcregrep with libz ......... : no --enable-pcregrep-libz
    Link pcregrep with libbz2 ....... : no --enable-pcregrep-libbz2
    Link pcretest with libedit ...... : no --enable-pcretest-libedit
    Link pcretest with libreadline .. : no --enable-pcretest-libreadline
    Valgrind support ................ : no --enable-valgrind
    Code coverage ................... : no --enable-coverage
 
 Libraries (lib):
    libpcre16     (if 16-bit character support support is enabled)
    libpcre32     (if 32-bit character support support is enabled)
    libpcre       (if 8-bit support is enabled)
    libpcreposix  (if 8-bit support is enabled)
    libpcrecpp    (if 8-bit and C++ support is enabled)
The following table shows the different representations of a few characters in comparison:
Unicode code point
U+0041
U+00DF
U+6771
U+10400
Representative glyph
UTF-32 code units
00000041
000000DF
00006771
00010400
UTF-16 code units
0041
00DF
6771
D801DC00
UTF-8 code units
41
C39F
E69DB1
F0909080
参考个选项意义:
http://www.pcre.org/pcre.txt
 

星期五, 十二月 06, 2013

mingw for window gcc 4.8.1 有bug.不支持std::to_string

这个bug自2012年就被发现了,可是一直到现在都在www.ming.org的版本里没有更新。
通过stackflow的帖子,下载了mingw32 w64的版本,果然这个bug修复了。

http://mingw-w64.sourceforge.net/

看gnu,现在c++11在语法编译器g++和运行库libstdc++都已经完备支持了。但是还没有window下的版本释放。
据说到2014年的gcc 4.9系列将完全释出。

星期四, 十二月 05, 2013

c++11革命性特征,增加软件健壮性。

Java处理异常通过try
{}catch(Exception e)//或者catch(Throwable t)
{}可以处理所有的异常了。
c++早期虽然可以通过
try
{}catch(...){}
来处理所有的异常。但是无法得知是什么异常类型,只能给出自己定制的异常信息。

c++11 后,提供了std::current_exception()即可处理所有异常了,并明确异常信息。
当然为了提出这个一场信息,处理过程依然不够java优雅,
需要一个再次扔出异常指针的过程。
代码:
catch(...)
 {
         std::exception_ptr eptr= std::current_exception(); // capture
         handle_eptr(eptr);
     }

void handle_eptr(std::exception_ptr eptr) // passing by value is ok
{
    try {
        if (eptr != std::exception_ptr()) {
            std::rethrow_exception(eptr);
        }
    } catch(const std::exception& e) {
        std::cout << "Caught exception \"" << e.what() << "\"\n";
    }
}


星期一, 十一月 25, 2013

终于看完了C++11了。果然是革命一般。

感觉C++11在STL基本库的完善后,开发效率上应该不输于java了。

准备抽时间,来试试看看开发多线程,i18n,l10n,方面的coding效率。

现在还有了LLVM的方向,语言级别的大一统时代就要到来了?

星期二, 十月 15, 2013

如何得到Android自带的sqlite的版本?

代码getv.c:
#include <stdio.h>
#include "sqlite3.h"
main()
{
printf("version is %s\n",sqlite3_libversion());
printf("sqlite3_sourceid is %s\n",sqlite3_sourceid());
}
将Android设备/system/lib/libsqlite.so复制到本地编译链接的需要参考,或者自己编译新的版本.参看NDK编译sqlite共享库及命令行读取数据库程序

Androkd.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := getv
LOCAL_SRC_FILES :=  getv.c
LOCAL_LDLIBS := -L. -lsqlite
include $(BUILD_EXECUTABLE)
得到ibs\armeabi\getv执行文件,使用adb push复制到android设备上,chmod 755 getv 后,执行
即可:android 4.3自带的sqlite版本为:
version is 3.7.11
sqlite3_sourceid is 2012-03-20 11:35:50 00bb9c9ce4f465e6ac321ced2a9d0062dc364669

星期四, 十月 10, 2013

编译sqlite 用于Android NDK

2.在一个目录下sqlitendk 建立jni目录,将三个文件展开到该目录下,并新建一个空白的
  Android.mk文件,目录结构
d:\sqlitendk
|
├─jni
│      Android.mk
│      sqlite3.c
│      sqlite3.h
│      sqlite3ext.h


3.修改Android.mk包含如下内容:
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := sqlite3802
LOCAL_CFLAGS    := -Werror
LOCAL_SRC_FILES := sqlite3.c

include $(BUILD_SHARED_LIBRARY)


回到jni的上级目录,sqlitendk,运行%NDK_HOME%\ndk-build.cmd
编译开始,最后生成 d:\sqlitendk\libs\armeabi\libsqlite3802.so
├─libs
│  └─armeabi
│          libsqlite3802.so

在Android NDK c文件中包含 sqlite3.h 即可使用sqlite的全部功能了。
将编译好的libsqlite3802.so和sqlite 头文件 sqlite3.h复制到将要使用的
例子的jni目录下,并建立Android.mk文件,指明 libsqlite3802.so所在目录,
然后调用ndk-build或ndk-build.cmd编译即可生成db 运行文件,
需要将 db和libsqlite3802.so都是用adb push复制到手机上,并修改
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:libsqlite3802.so所在目录
然后修改db权限可执行,运行即可。

附件为一个读取android /data/data/目录下某个应用的数据库的例子。
 dbtype.h
#ifndef DBTYPE_H_INCLUDED
#define DBTYPE_H_INCLUDED
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"

#define DB_PATH "/data/data/home.sunose/databases/doubleball.db3"

#define MAX_REDBALL 33 //最大双色球红球

#define  MAX_BLUEBALL 16 //最大双色球篮球球
#define  REDBALL_NUMBER 6 //最多红球数目
#define STDCALL __stdcall

static char QUERY_DB[]="SELECT * FROM _DBHISTORY order by term asc";;
 

例子db.c
#include "dbtype.h"
#include <stdio.h>

    char *zErrMsg;
    int rc;
    int db_open;   
         char **records;//所有记录
     int nrow;
     int ncol;
     sqlite3 *db;
//pre declare    
     int query(char * sql);

int main()
{
char  result[1024*1024];//1M
char buf[80];
char number[16];
   
 printf("this is %d\n",MAX_REDBALL);
 printf("this is %s\n",DB_PATH);
 rc = sqlite3_open(DB_PATH, &db);
   if(rc!=SQLITE_OK)
    {
    printf("%s ",zErrMsg);
    }    
    query(QUERY_DB);
    int i=0,j=0;
for(i=1;i<=nrow;i++)//line,注意,recoreds包含了列名字
   {
       strcpy(buf,"[");
    for(j=0;j<ncol;j++)
   {
                     if(j==0 || j==1) //term and date time
                         {
                        sprintf(number,"'%s'",(records[i*ncol+j]));                           
                  strcat(buf,number);
                  }
                     if(j>1) //term and date time
                         {
                  sprintf(number,"'%02s'",(records[i*ncol+j]));
                  strcat(buf,number);
                  }
                  if(j<(ncol-1))
                   {
                       strcat(buf,",");
                }
   }
    strcat(buf,"],\n");           
  strcat (result,buf);                 
      }  
printf("%s",result);      
}
int query(char * sql)
{
zErrMsg=NULL;
        rc = sqlite3_get_table
        (
              db,              /* An open database */
              sql,       /* SQL to be executed */
              &records,       /* Result written to a char *[]  that this points to */
              &nrow,             /* Number of result rows written here */
              &ncol,          /* Number of result columns written here */
              &zErrMsg          /* Error msg written here */
              );
if(zErrMsg!=NULL)
{

  printf("%s",zErrMsg);
  zErrMsg=NULL;
}

        return rc;
}


Android.mk:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := db
LOCAL_SRC_FILES := db.c
LOCAL_LDLIBS := -LD:/test_Projects/testc/ -lsqlite3802
include $(BUILD_EXECUTABLE)

星期二, 九月 24, 2013

Android 命令行 dx转换格式出现 file not found

解决方法不要用相对路径,要用绝对路径。
dx默认将dx.bat或dx.sh所在目录作为主目录。语法类似如下

dx --dex --no-strict --output=c:\temp\cmd.jar c:\temp\testCMD.class

星期三, 九月 11, 2013

7zip lzma 移植到Android ndk

1) 下载LZMA-SDK源码包,下载地址:http://www.7-zip.org/sdk.html,当前最新版本是9.20,即lzma920.tar.bz2包;

2) 解压:把源码包的程序文件解压到文件夹:lzma920中;

3) 解压后,建议先查看下其中的说明文件:7zC.txt和lzma.txt两文件;

4) 进入目录:lzma920/C/Util/7z,可以看到其中有两个makefile文件:makefile和makefile.gcc,因为是在linux下,所以用makefile.gcc这个makefile文件;

5.lzma920目录下新建jni目录
将 lzma920\C\目录下所有c和.h文件复制到jni目录下,不包含util子目录
6.在jni目录下建立Android.mk文件,包含如下内容:
LOCAL_PATH:= $(call my-dir)
#LOCAL_CXX := $(CXX)
include $(CLEAR_VARS)

#LOCAL_C_INCLUDES :=
LOCAL_MODULE    :=  7zDec
LOCAL_CFLAGS    :=   -c -O2 -Wall  -flto -dM
LOCAL_SRC_FILES :=  7zAlloc.c \
7zBuf.c \
7zBuf2.c \
7zCrc.c \
7zDec.c \
7zIn.c \
7zFile.c \
7zStream.c \
7zCrcOpt.c \
CpuArch.c \
LzmaDec.c \
Lzma2Dec.c \
Bra.c \
Bra86.c \
Bcj2.c \
Ppmd7.c \
Ppmd7Dec.c


LOCAL_LDLIBS    := -llog
##LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

include $(BUILD_SHARED_LIBRARY)

在lzma920目录下执行ndk-build.cmd命令

此时出现一些类型没有定义错误,可以在types.h中加入如下申明,
重新编译即可.


Types.h

//port start
typedef void *PVOID,*LPVOID;
typedef void *HANDLE;
typedef unsigned long DWORD;
/*WINNT.H*/
typedef long LONG;
typedef unsigned short WORD;

typedef struct _LIST_ENTRY {
    struct _LIST_ENTRY *Flink;
    struct _LIST_ENTRY *Blink;
} LIST_ENTRY,*PLIST_ENTRY;
typedef struct _CRITICAL_SECTION_DEBUG {
    WORD Type;
    WORD CreatorBackTraceIndex;
    struct _CRITICAL_SECTION *CriticalSection;
    LIST_ENTRY ProcessLocksList;
    DWORD EntryCount;
    DWORD ContentionCount;
    DWORD Spare [2];
} CRITICAL_SECTION_DEBUG,*PCRITICAL_SECTION_DEBUG;

typedef struct _CRITICAL_SECTION {
    PCRITICAL_SECTION_DEBUG DebugInfo;
    LONG LockCount;
    LONG RecursionCount;
    HANDLE OwningThread;
    HANDLE LockSemaphore;
    DWORD SpinCount;
} CRITICAL_SECTION;

//port over

星期五, 九月 06, 2013

fastboot devices和adb devices

adb devices 可以列出设备,但是fastboot devices无法列出。
原因是工作原理不同。
adb devices和fastboot不能同时工作。
使用adb reboot bootloader 启动 手机后,出现android 系统提示的时候,
这个时候,使用fastboot devices就出现设备了,这个时候
就可以刷机了。
比如:
fastboot flash recovery openrecovery-twrp-2.6.1.0-maguro.img

星期四, 八月 15, 2013

巧妙在底部中间对齐.

     <div style="position: absolute; left: 50%;bottom: 0;">
        <div style="position: relative; left: -50%;font-size:24px;bottom: 0;">
          Version here!haha.
        </div>
    </div>

星期三, 八月 14, 2013

Gradle项目里调用ant的propertyFile task 用来制作build number

文件:buildnumber.gralde包含代码

task buildversionnumber << {

ant.propertyfile(file: "src/build.properties")
{
 entry(key: 'builder.date', type:'date',value: new Date(),pattern:'YYYY/MM/dd  HH:mm')
 entry(key: 'build.number', value: '1',operation:'+',type:'int')
 }
 }

src\build.properties 文件里包含内容:

build.number=455
builder.date=2013/08/14  15\:22
builder.author=William Wang

运行:
gradle -b bnumber.gradle buildversionnumber

即可看到builder.date和build.number如期改变了。

星期五, 八月 09, 2013

cordova 生成Android mobile的奇怪约束.否则会无法生成build.xml

C:\npm>cordova create HWLauncher  com.projectname projectname

 cordova create path id name的参数格式。

C:\npm>cd HWLauncher

C:\npm\HWLauncher>cordova platform add android
dir platforms\android,如果这个时候没有看到build.xml和AndroidManifest.xml
则说明出现了错误,注意红色的peojectname必须相同,但大小写不需要一致,
这个最后保存在www\config.xml里。如果这里不一致,则会出现不能生成build.xml的错误。


adb命令行下检查输出的错误log.

adb logcat Cordova:D DroidGap:D CordovaLog:D *:S
adb logcat CordovaLog:D *:S"

星期五, 八月 02, 2013

phonegap一些稀奇古怪的错误

npm 安装包到指定目录语法:

npm --prefix 路径即可

cordova -d platform add android安装出现如下错误的时候


Error: No platforms added to this project. Please use `cordova platform add <platform>`.

加上详细输出 -d 来看具体的错误,这个错误是由于
JAVA_HOME需要设置以及 path中加入可以找到 javac的路径即可。

如何使用不同的phonegap Adobe ID build不同的app

删除掉%HOME%\.cordova 目录即可重新提示输入新的用户名和密码了


星期四, 八月 01, 2013

PhoneGap 3.0 编译多平台HTML 5 Client 成功

Android key:

1.keytool -genkey -v -keystore android-release-key.keystore -alias key_android -keyalg RSA -keysize 2048 -validity 10000
2.进入build.phonegap.com 上传Android key。
3.进入目录上传代码:phonegap run android
   可以修改config.xml里面的app名字和修改..cordova 下的config.json相关配置字符串

4.进入build.phonegap.com 查看app,并为Android 选择key,key首先要解锁
5.选择key 文件,重新编译android app并下载

星期五, 七月 19, 2013

如何修改Android Studio 字体

Android Studio 字体默认读取JVM的默认字体。
在Window Xp下非常难看。

通过Android Stuido 菜单File/Setting..../搜索 font,建立自己的Scheme,确定保存即可

星期三, 七月 17, 2013

Gradle gui

gradle --gui 弹出GUI窗口。

星期五, 七月 05, 2013

Android Studio gradle plugin 帮助手册

Android Tools Project Site


这里比较全的包含了gradle task.

如何在build.gradle在最后打包的apk里加入JNI的库

如何生成jni库,不赘述,需要修改build.gradle加入如下语句即可:
 不过注意此脚本适合:'com.android.tools.build:gradle:0.4版本,其后的版本可能默认加入JNI打包的步骤:

tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->pkgTask.jniDir new File(buildDir, 'native-libs')

task copyNativeLibs(type: Copy) {
    println 'call copyNativeLibs'
    from fileTree(dir: 'libs', include: '**/*.so' )
    into 'build/native-libs'
}

build.gradle加入自己的签名文件。

如何生成签名文件不赘述。
build.gradle 加入如下语句即可:
android {
    compileSdkVersion 10
    buildToolsVersion "17.0.0"

    signingConfigs  {
        debug{
        storeFile = file("D:\\eclipse workspace\\dbball-cn\\dbball-cn\\release.keystore")
        keyAlias = "sunose"
        storePassword = "sunose"
        keyPassword = "sunose"
        }
        release{
            storeFile = file("D:\\eclipse workspace\\dbball-cn\\dbball-cn\\release.keystore")
            keyAlias = "sunose"
            storePassword = "sunose"
            keyPassword = "sunose"
        }
    }

注意如何发布运行测试的时候出现:INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES
错误,是由于以前的版本已经安装使用了不同签名,只要删除掉该app
从新发布即可。

Java Double Brace Initialization

常用语Java Collect类的初始化,因为Java没有提供简易的初始化Collect的方法。
Set<String> flavors = new HashSet<String>() {{      add("vanilla");      add("strawberry");      add("chocolate");      add("butter pecan");  }};

The first brace creates a new AnonymousInnerClass,
the second declares an instance initializer block that is run when the anonymous inner class is instantiated.

 add(new JPanel() {{  	setLayout(...);  	setBorder(...);  	add(new JLabel(...));  	add(new JSpinner(...));   }});

星期四, 七月 04, 2013

Android Studio操作说明:INSTALL_PARSE_FAILED_NO_CERTIFICATES

有两个生成最终app的模式:一个是testing/debuggging debug模式,
另外一个是release 模式,rease模式必须要自己签名。debug模式则声称
一个debug.store的签名用于调试。

生成自己的签名app在菜单build/generate signed APK....就可以了。

星期三, 七月 03, 2013

如何得到当前使用的Grovvy的版本。

2.0之后可以用如下方法:
println groovy.lang.GroovySystem.getVersion()

星期六, 六月 29, 2013

如何更新Android studio to 0.1.8

Help 菜单 Check for update...
在中国大陆 dl-sdk.appspot.com 这个地址被封闭了。
所以要不修改hosts或者使用VPN来更新

星期六, 六月 15, 2013

Android ListView如何避免全部选中情况下的背景变色问题?

选中一个Item然后向上或向下拖拉,则出现全部变白色背景问题,如图

纠正也很简单,只要在xml中的ListView中加入:
        android:cacheColorHint="@android:color/transparent"
即可。

星期四, 六月 13, 2013

如何用windump或者tcpdump得到http request url?

tcpdump或者 windump -i 1 -A -s 1492 dst port 80



星期三, 六月 12, 2013

如何从Eclipse ADT 转换到Google Android Studio

前提:
Google 推荐使用gradle代替maven 来管理项目。
1.所以,首先必须在Eclipse 里使用export然后在项目里选择
生成 gradle script 文件
 注意:必须用android sdk 更新SDK 到最新的22及以后才可以使用这个功能,
同样Eclipse ADT plugin 也必须在SDK 升级后,升级到最新的版本。

2.android studio 默认使用自己携带的Android SDK,所以,可能出现错误:


这个时候就要先修改Android Stuio默认使用的Android SDK.
从android快速启动UI里:
选择 Configure->Project Defaults-> Project Structure.在左面的面板里选择设置Android SDKs

星期三, 六月 05, 2013

ADT emulator-5554 disconnected! 错误纠正

在命令行使用adb kill-server,adb start-server即可
然后再Eclipse里打开 devices view,刷新即可看到emulator,
然后就可以run Android application 了。

而不是又重新开启一个新的emuluator.

星期五, 五月 17, 2013

星期三, 五月 08, 2013

如何使用adb shell 执行多个命令或者执行需要root权限的命令。

adb shell "dumpsys meminfo |grep tencent"

秘诀,必须用双引号将命令扩起来“
不同的命令用分号;隔开。
比如:
adb shell "ls  ;ps "

则顺序执行ls和ps -ef命令了。

星期一, 四月 29, 2013

download antrl 3.2

Open JPA

2.openjpa编译及enhance需要antlr,具体的版本可以example里例子里目录下查看build.properties里的antlr.version=3.2
3.下载antlr ,http://www.antlr.org/download.html,如果不是最新的版本,可以从 https://github.com/antlr/ 目录里寻找具体的版本下载,
你需要:antlr-runtime-3.2.jar和antlr-3.2.jar两个.jar文件。
4.修改build.properties,修改对应的openjpa和antlr lib目录。
5.修改build.xml 对应的ant 脚本 property指向具体的jpa lib和antlr lib
6.运行ant build.xml开始编译例子程序。




星期三, 四月 10, 2013

git for window 如何保存提交到code.google.com的用户名及密码

首先在window %HOME%变量制定的目录下建立_netrc文件,
注意是_netrc不是.netrc或者netrc.
可以在window cmd下使用echo %HOME%看到具体的目录。
_netrc文件里放入一下字符串即可:
machine code.google.com login yourRealEmail@gmail.com password  xxxxx

然后使用:
git add *
git commit -m "commit source code by....."
git push


星期二, 四月 09, 2013

如何在 window 下手动建立GIT project在code.google.com上

git init

 git add *

 git commit -m "initial project version"

 git remote add master https://code.google.com/p/myproject/

 git push master  --all

星期二, 四月 02, 2013

编写自己的Wrapper Class

   编写自己的Wrapper Class
A URL Connection to a Java ARchive (JAR) file or an entry in a JAR file.
The syntax of a JAR URL is:
jar:<url>!/{entry}

参考: java.net.JarURLConnection
http://java.sun.com/j2se/1.4.2/docs/api/java/net/JarURLConnection.html

目的:要解决在可执行Jar文件中使用包含在其他地方的Jar文件中的class.

初级方法:使用Java extension机制,通过编写启动脚本来解决问题:
  把第三方的Jar Library复制到{java home}\jre\lib\ext 目录下
或使用java ?Xbootclasspath 命令行参数:

    -Xbootclasspath:<directories and zip/jar files separated by ;>
                      set search path for bootstrap classes and resources
    -Xbootclasspath/a:<directories and zip/jar files separated by ;>
                      append to end of bootstrap class path
-Xbootclasspath/p:<directories and zip/jar files separated by ;>

大多数的Java 应用服务器都使用了制作启动脚本的方法.
例子: 脚本run.bat 可以参看Jboss Application的run.bat或run.sh脚本

中级方法: 利用Jar 扩展机制规范,通过制作安装包来解决问题.
   利用Jar包扩展(extension)机制通过Manifest Specification 来编写
参考: http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html
利用META-INF/MANIFEST.MF文件中的Class-Path:来指定需要引用的第三包,
将需要的第三方包放到在Class-Path:指定的目录下,然后把主程序jar包和第三包
制作安装包,在安装的时候按照目录结构安装。然后SystemClassLoader(sun.misc.Launcher)
自动加载

高级方法,编写自己的Container类或bootStrap Wrapper类.
思路:实现一个Custom ClassLoader-系统类java.开头的类让SysemClassLoader来载入,
  其他的类用CustomClassLoader读取给出的Jar Library 包来实现.
最终实现 Class.forName(String name)自动使用Custom ClassLoader来寻找和加载class.

这里需要介绍一些Java ClassLoader的一些限制的知识,ClassLoader的详细原理,可以参看
其他相关介绍.
Hack Java:
强行设置系统默认的ClassLoader,有作用吗?No
Field tclass = ClassLoader.class.getDeclaredField("scl");
tclass.setAccessible(true);
tclass.set(null,Mydefault);

JVM的 SystemClassLoader是 sun.misc.Luncher的实例,这里面包含native的本地方法,
其中工作算法不得而之,JVM唯一给我们留下的扩展机制就是改变ContextClassLoader来实现
JVM的ClassLoader委托模式(delegation mode).

  详细介绍:
Custom ClassLoader代码
/**
* Don't Reinvent wheel
* 使用 URLClassLoader 来载入Jar Library
*
*/

import java.io.InputStream;
import java.io.File;
import java.net.URLClassLoader;
import java.util.*;
import java.net.URL;

public class myClassLoaderByURL extends java.lang.ClassLoader
{
static java.net.URL _url=null;
static String libpath=null;
public static  myClassLoaderByURL defaultld=null;

public myClassLoaderByURL(String liburl,ClassLoader parent) throws Exception
{
     super(parent);
  if(!checkJar(liburl))
   {
  throw new java.lang.RuntimeException("Jar File "+liburl+" not exist");        
        }
     try
     {
     _url = new  URL("jar:file:/"+liburl+"!/");
}catch(Exception e)
{
     e.printStackTrace();
     }
}
protected  Class findClass(String name) throws ClassNotFoundException
{
Class speClass=null;
try
{
     speClass = getParent().loadClass(name );
     System.out.println("myClassLoaderByURL Msg: parent CLD find Class............"+name);
} catch( ClassNotFoundException cnfe )
   {
  try
  {
String rname = name;
rname = rname.replace ('.', '/') + ".class";//重要,必须还原为目录格式
  System.out.println("myClassLoaderByURL Msg: Option jar Lib:"+_url.toExternalForm());
  System.out.println("myClassLoaderByURL Msg: find class name:"+rname);
  URLClassLoader ucld = new URLClassLoader(new URL[]{_url},myClassLoaderByURL.class.getClassLoader());
  InputStream is = ucld.getResourceAsStream(rname);
if(is==null)
{
  throw new ClassNotFoundException(" Can't Find Specified Class:"+name);
}
int size=is.available();

byte[] b = new byte[size];
is.read(b,0,size);
is.close();
     speClass = defineClass(name,b,0,b.length);

}catch(Exception ioe)
{
     ioe.printStackTrace();
     throw new ClassNotFoundException();
}
}catch(Exception ce)
{
     ce.printStackTrace();
     throw new ClassNotFoundException();
}
System.out.println("myClassLoaderByURL Msg: ok,load success");

return speClass;
}

public Class loadClass( String pClassName, boolean pResolve ) throws ClassNotFoundException {
       System.out.println("myClassLoaderByURL Msg:loadClass(), resolve: " + pResolve );
       Class lClass = findLoadedClass( pClassName );
       lClass  = findClass( pClassName );


       //ResolveClass.
       try {
           if( pResolve ) {
               System.out.println("myClassLoaderByURL Msg:resolve class: " + lClass );
               resolveClass( lClass );
           }
       } catch (Error e) {
           e.printStackTrace();
           throw e;
       }
       return lClass;
   }
public Class loadClass( String pClassName) throws ClassNotFoundException
{
     Class t =loadClass(pClassName,true);
     return t;
}

private boolean checkJar(String jarfile)
{
     System.out.println("myClassLoaderByURL Msg: checkJar:"+jarfile);
     File jarf = new File(jarfile);
     try
     {
     System.out.println(jarf.getCanonicalFile());
}catch(Exception ee)
{
     }
     return jarf.exists();
}
}

编写自己的Boot Wrapper类:

import java.io.*;
import java.util.zip.*;
import java.util.jar.*;
import java.net.URLClassLoader;
import java.net.URL;
import java.lang.reflect.Method;

public class testClassLoaderByURL extends java.lang.Thread
{
static myClassLoaderByURL Mydefault;
static String JarLibraryPath="";
static String executedClass = "";
public static void main(String[] args) throws Exception
{
if(args.length <2)
{
     System.out.println("Syntax testClassLoaderByURL /path/xx.jar Executable class name(include main method");
     System.out.println("Example: java testClassLoaderByURL c:\\temp\\test.jar org.sun.go");
     System.exit(0);
}
JarLibraryPath=args[0];
executedClass = args[1];
//here can verified parameter

System.out.println("Jar is:"+JarLibraryPath+", Class is:"+executedClass);
System.out.println("Begin Load");
Mydefault = new myClassLoaderByURL(JarLibraryPath,testClassLoader.class.getClassLoader());
myClassLoaderByURL.defaultld = Mydefault;

      Thread.currentThread().setContextClassLoader(Mydefault);
     
         Class cls = Mydefault.loadClass(executedClass);//重要.
         Method main = cls.getMethod("main", new Class[]{String[].class});
         main.invoke(cls, new Object[]{args});


}
}