Android Platform 3.0 SDK和Eclipse ADT安装记录二
Android Platform 3.0 SDK和Eclipse ADT安装记录二
?
(20120308补注)
注:从NDK r7开始引入了新的命令文件ndk-build.cmd,可以实现无cygwin的编译。使用它可以免除在Windows下手工写bat。但只适用于标准的JNI工程,如果要编译纯elf文件(main入口)仍然需要手工写Makefile或bat。下文中大多数都是基于NDK r5b的,可能已经过时,请留意。
?
(20120401补注)
注:从CDT Indigo SR2开始,CDT支持交叉编译的配置,下文中提到的CDT最初是基于旧版本的CDT?Galileo,相对会麻烦很多,而且不容易配置出正确的高亮着色和定义跳转。至于gdb的配置和使用是差不多的。请注意。另外,旧版本CDT可以使用GNU ARM的Ecllipse插件来简化配置操作。
?
目录:
一、简单地编写JNI及测试
二、ndk-gdb的使用
三、在CDT上看NDK工程(最好使用CDT Indigo SR2部署工程,见第十五节)
四、创建普通Android原生程序(main入口)
五、如何使用jdb调试android的java程序
六、利用Android NDK的Import Module功能导入C++的标准库(gnu-libstdc++)
七、main入口的c++程序编写(测试用)
八、依赖库问题
九、用Flash Builder 3.5开发Android的Air应用程序(模拟器上运行)
十、apk逆向工程
十一、adb使用摘要
十二、Android数据共享手段
十三、在App中运行原生可执行文件(elf格式)
十四、ListView的一些问题。
十五、用CDT?Indigo SR2创建main入口c工程
十六、Error generating final archive: Debug Certificate expired on ...的错误(转)
十七、刷新avd列表(重启adb服务器)
十八、查看内存占用量(检查内存泄露)
?
----------------
?
一、简单地编写JNI及测试:
?
(注:更快的方法是使用Ant和Eclipse,
见官网的介绍
http://developer.android.com/sdk/ndk/overview.html
?
首先用
>?..\..\ndk-build.cmd
生成libs\armeabi下的.so文件
然后原地创建Eclipse工程
?
@set PATH="C:\WINDOWS" @set PATH="C:\WINDOWS\system32";%PATH% @set PATH="D:\java\apache-ant-1.8.1\bin";%PATH% @set JAVA_HOME="D:\java\jdk1.6.0_20" @set PATH="D:\java\jdk1.6.0_20\bin";%PATH% @set PATH="D:\java\android-sdk_r10-windows\android-sdk-windows\platform-tools";%PATH% @set PATH="D:\java\android-sdk_r10-windows\android-sdk-windows\tools";%PATH% @cd /D "D:\java\android-sdk_r10-windows\android-sdk-windows\work" @cmd ??
?
2. 创建工程,并且测试(假设AVD的名称为add2)
?
package com.example.myjni;public class MyJNI {public static native int mycall(int x);} ?然后执行ant compile编译
?
4. 生成头文件,这里需要指定原生类class文件的根目录以及完整类名。
> javah -jni -classpath ./bin/classes -d jni com.example.myjni.MyJNI
输出文件为jni\com_example_myjni_MyJNI.h,内容如下:
?
?
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_myjni_MyJNI */#ifndef _Included_com_example_myjni_MyJNI#define _Included_com_example_myjni_MyJNI#ifdef __cplusplusextern "C" {#endif/* * Class: com_example_myjni_MyJNI * Method: mycall * Signature: (I)I */JNIEXPORT jint JNICALL Java_com_example_myjni_MyJNI_mycall (JNIEnv *, jclass, jint);#ifdef __cplusplus}#endif#endif?由于使用JNIEXPORT进行导出,
所以在编译.so文件时编译器会检查此函数是否被实现。
(如果编译器看到这个头文件的内容)
?
5. 实现JNI接口。
创建jni目录。
创建一个.c文件,内容如下:
?
?
#include "com_example_myjni_MyJNI.h"#include <stdio.h>jint JNICALLJava_com_example_myjni_MyJNI_mycall(JNIEnv *env, jclass cl, jint x){printf("hello, JNI, %d", x);return x + 1;}?6. 编译JNI的.so文件(需要下载NDK,使用其中的工具链命令行,这里尽量用命令行)
方便起见,我没有使用官方提供的ndk-build,而是直接使用工具链命令行(可能有问题)。
?
(请尽量使用ndk-build和ndk-build.cmd,以节约时间和保证生成.so的正确性,以下步骤只是因为NDK r7之前还没有出现ndk-build.cmd工具)
?
?
注意:上面的--sysroot应该是写错了,应该是类似这样才对
--sysroot=“C:/cygwin/home/Administrator/android-ndk-r5b/platforms/android-8/arch-arm”
见下面的Makefile。
?
输出文件名必须是lib前缀,.so后缀,而且必须输出到libs/armeabi目录下。
?
7. 在Activity中使用JNI,必须首先使用loadLibrary指定要加载的so文件名(不需要lib前缀和.so后缀)
?
?
package com.example.myjni;import android.app.Activity;import android.os.Bundle;public class MyJNIActivity extends Activity{ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); int result = MyJNI.mycall(0); System.out.println("result is " + result); } static { System.loadLibrary("MyJNI"); }}?8. 重新编译和打包apk
> ant clean debug
然后用7zip打开bin\MyJNI-debug.apk,查看libs\armeabi\libMyJNI.so是否被打包
?
9. 在模拟器内测试(方法同2),adb logcat的输出如下:
?
?
<?xml version="1.0" encoding="utf-8"?><!-- BEGIN_INCLUDE(manifest) --><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.native_activity" android:versionCode="1" android:versionName="1.0"> <!-- This is the platform API where NativeActivity was introduced. --> <uses-sdk android:minSdkVersion="10" /> <!-- This .apk has no Java code itself, so set hasCode to false. --> <application android:label="@string/app_name" android:hasCode="false" android:debuggable="true"> <!-- Our activity is the built-in NativeActivity framework class. This will take care of integrating with our NDK code. --> <activity android:name="android.app.NativeActivity" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden"> <!-- Tell NativeActivity the name of or .so --> <meta-data android:name="android.app.lib_name" android:value="native-activity" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest> <!-- END_INCLUDE(manifest) -->?
然后必须重新编译JNI工程(使用ndk-build clean all)和Android工程(使用ant clean debug)
如果缺少一个,都无法使用ndk-gdb调试
(官方NDK文档说可以在编译时使用
$NDK/ndk-build NDK_DEBUG=1
就不需要修改AndroidManifest.xml文件了
)
?
?
启动模拟器
> start emulator -avd <AVD名称>
?
启动ndk-gdb并启动程序(程序未启动)
?
?
? Consult the user's guide for more details about POSIX paths:
? ? http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
/cygdrive/C/cygwin/home/Administrator/android-ndk-r5b/build/core/build-local.mk:85: *** Android NDK: Aborting ? ?. ?Stop.
Android NDK: Could not find application project directory ! ? ?
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it. ? ?
说明ndk-build运行正常(因为目录中没有包含AndroidManifest.xml和JNI源代码)
8. 加入代码
复制示例代码
<NDK目录>/samples/native-activity
到Eclipse的工程树下
然后重新执行Project->Clean...
进行编译,输出如下:
?
?
Consult the user's guide for more details about POSIX paths:?
9. 纠正代码错误提示的问题
由于CDT的错误提示不依赖于编译过程(即编译通过,编辑器仍会显示错误)
需要手动指定NDK工具链的头文件目录:
Project->Properties->
C/C++ Build->Paths and Symbols->Includes->GNU C->Add...
-> C:\cygwin\home\Administrator\android-ndk-r5b\platforms\android-9\arch-arm\usr\include
-> C:\cygwin\home\Administrator\android-ndk-r5b\sources\android\native_app_glue
(需要根据实际目录添加)
确定后CDT会自动刷新工程,重新检查错误。
?
-------------------
?
?
?
四、创建普通Android原生程序(main入口):
?
方法类似上面创建原生活动的方法,不同的是:
1. Make命令改为
bash -c /cygdrive/C/cygwin/bin/make
2. 创建源文件文件
File->New->Source File
->Source file : hello.c
编辑内容如下:
?
?
#include <stdio.h>int main(int argc, char **argv) {printf("Hello, world!\n");return 0;}?3. 创建Makefile
File->New->Other->General->File
->File name: Makefile
编辑内容如下:(绝对路径根据实际修改)
?
?
NDK_HOME := C:/cygwin/home/Administrator/android-ndk-r5bCC := /cygdrive/C/cygwin/home/Administrator/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-gccCC += --sysroot=$(NDK_HOME)/platforms/android-9/arch-armRM := rm -rfCFLAGS := -gCFLAGS += -I $(NDK_HOME)/platforms/android-9/arch-arm/usr/includeLIBS := -lmTARGET := helloOBJS := hello.oall : $(TARGET)$(TARGET) : $(OBJS)$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)%.o : %.c$(CC) $(CFLAGS) -o $@ -c $<clean :$(RM) $(OBJS) $(TARGET)?
4. 重新编译
然后按Project->Clean...重新编译,左面工程树出现Binaries和Includes节点。
5. 上传到模拟器并测试
启动emulator后,
> adb shell
# mkdir /data/hellowolrd
# exit
(创建可写目录)
> adb push hello /data/helloworld
(把刚才编译的文件上传至模拟器)
> adb shell
# cd /data/helloworld
# ls
# chmod 744 hello
# ./hello
Hello, world!
# exit
6. 远程调试
gdbserver的用法如下:
# gdbserver --help
gdbserver --help
Usage: ?gdbserver COMM PROG [ARGS ...]
? ? ? ? gdbserver COMM --attach PID [--close-fd FD]
?
COMM may either be a tty device (for serial debugging), or
HOST:PORT to listen for a TCP connection.
?
Exiting
如果要执行远程调试,可以
> start adb shell?
# cd /data/helloworld
# gdbserver :5039 ./hello
gdbserver :5039 ./hello
Process ./hello created; pid = 293
Listening on port 5039
(此时gdbserver未被连接,所以被阻塞)
然后重定向端口(详细见gdb help)
? adb forward <local> <remote> - forward socket connections
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?forward specs are one of:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tcp:<port>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?localabstract:<unix domain socket name>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?localreserved:<unix domain socket name>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?localfilesystem:<unix domain socket name>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?dev:<character device name>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jdwp:<process pid> (remote only)
方法如下:
> adb forward tcp:5039 tcp:5039
这样模拟器的监听的模拟器端口5039,被重定向到宿主机的端口5039(只需要做一次)
然后启动本地的gdb
> C:\cygwin\home\Administrator\android-ndk-r5b\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin\arm-linux-androideabi-gdb.exe
进入gdb后
(gdb) file hello
(加载elf文件的调试信息)
(gdb) target remote localhost:5039
(连接到本机的5039端口)
(gdb) b main
(下断点)
(gdb) c
(继续)
Continuing.
Error while mapping shared library sections:
/system/bin/linker: No such file or directory.
Error while mapping shared library sections:
libc.so: No error.
Error while mapping shared library sections:
libm.so: No error.
?
Breakpoint 1, main (argc=1, argv=0xbe9c5cd4) at hello.c:4
4 ? ? ? ? ? ? ? printf("Hello, world!\n");
(断点命中,用其它gdb指令调试)
(gdb) printf "%s\n", argv[0]
./hello
(输出argv[0]的字符串值,当前为./hello)
(gdb) bt
#0 ?main (argc=1, argv=0xbe9c5cd4) at hello.c:4
(回溯堆栈)
(gdb) n
(步进,gdbserver的控制台出现如下输出:
gdb: Unable to get location for thread creation breakpoint: requested event is n
ot supported
Hello, world!
)
7. 在CDT中执行gdb
原理和上面用命令行调试一样,但断点的触发不能关联到编辑器(未解决)
设置方法是
启动gdbserver后
打开CDT的Run->Debug Configurations->双击新建C/C++ Attach to Application->Debugger
-> Debugger : gdbserver
-> Main -> GDB debugger : C:\cygwin\home\Administrator\android-ndk-r5b\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin\arm-linux-androideabi-gdb.exe
-> Connection -> Port Number : 5039
(设置好gdb绝对路径和端口号,按Apply和Debug)
Console视图会出现gdb的控制台(看右上角按钮Display Selected Console),可以输入相应的gdb命令。
不同于控制台调试,
1) gdb命令没有(gdb)提示符
2) gdb命令用绿色高亮显示
由于CDT的原因,断点触发时无法自动打开源文件。
?
---------------------------
?
?
五、如何使用jdb调试android的java程序
http://blog.csdn.net/dlmu2001/article/details/6946830
(未测试)
?
?
?
---------------------------
?
六、利用Android NDK的Import Module功能导入C++的标准库(gnu-libstdc++)
?
默认NDK不支持C++标准库,但提供Import Module功能
支持外挂的第三方移植库,
例如samples\native-activity就是在Android.mk中使用
LOCAL_STATIC_LIBRARIES := android_native_app_glue
和
$(call import-module,android/native_app_glue)
导入
$(NDK)/sources/android/native_app_glue
的第三方库
所以,可以用相同的方法导入
$(NDK)/sources/cxx-stl/gnu-libstdc++
?
例如:
?
# Copyright (C) 2009 The Android Open Source Project## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.#LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := libgl2jniLOCAL_CFLAGS := -WerrorLOCAL_SRC_FILES := gl_code.cpp LOCAL_LDLIBS := -llog -lGLESv2LOCAL_STATIC_LIBRARIES := gnustl_static# see http://stackoverflow.com/questions/7209971/ndk-build-undefined-reference-to-errors-when-statically-linking-to-libxml-a# 避免以下错误:# undefined reference to `std::__throw_bad_alloc()'LOCAL_ALLOW_UNDEFINED_SYMBOLS := trueinclude $(BUILD_SHARED_LIBRARY)$(call import-module,cxx-stl/gnu-libstdc++)
?
其中?
?
$(call import-module,cxx-stl/gnu-libstdc++)
表示导入
$(NDK)/sources/cxx-stl/gnu-libstdc++
的头文件和库文件
而
?
LOCAL_STATIC_LIBRARIES := gnustl_static
?
表示导入的模块名(必需)
模块名定义在
$(NDK)/sources/cxx-stl/gnu-libstdc++/Android.mk
中:
?
?
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true?
?
参见
http://stackoverflow.com/questions/7209971/ndk-build-undefined-reference-to-errors-when-statically-linking-to-libxml-a
?
--------------------------
?
七、main入口的c++程序编写(测试用)
?
假设有一个C++代码文件:
?
?
#include <iostream>using namespace std;int main(int argc, char *argv[]){cout << "Hello, world!" << endl;return 0;}?
编译用bat
?
?
C:/cygwin/home/Administrator/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-g++ --sysroot=C:/cygwin/home/Administrator/android-ndk-r5b/platforms/android-8/arch-arm -L"C:/cygwin/home/Administrator/android-ndk-r5b/sources/cxx-stl/gnu-libstdc++/libs/armeabi" -L"C:/cygwin/home/Administrator/android-ndk-r5b/platforms/android-8/arch-arm/usr/lib" -I"C:/cygwin/home/Administrator/android-ndk-r5b/platforms/android-8/arch-arm/usr/include" -I"C:/cygwin/home/Administrator/android-ndk-r5b/sources/cxx-stl/gnu-libstdc++/include" -I"C:/cygwin/home/Administrator/android-ndk-r5b/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include" hello.cpp -lc -lm -lstdc++ -o hello_cpppause?
上传和chmod 744的做法与前面关于c的hello,world程序编译步骤相同。
?
?
我测试过C++标准库中的vector,map,iostream和异常,代码如下(内附输出内容):
?
?
/*adb push hello_cpp /data/wmt*/#include <iostream>#include <vector>#include <map>using namespace std;int main(int argc, char *argv[]){cout << "Hello, world!" << endl;vector<int> V;V.insert(V.begin(), 3);V[0] = 4;V[1] = 5; //越界 out of rangecout << "size:" << V.size() << ",capacity:" << V.capacity() << endl;V.reserve(3);cout << "size:" << V.size() << ",capacity:" << V.capacity() << endl;cout << "V[0]:" << V[0] << endl;cout << "V[1]:" << V[1] << endl;map<const char*, int> months;months["january"] = 31;months["february"] = 28;months["march"] = 31;months["april"] = 30;months["may"] = 31;months["june"] = 30;months["july"] = 31;months["august"] = 31;months["september"] = 30;months["october"] = 31;months["november"] = 30;months["december"] = 31;cout << "june -> " << months["june"] << endl;try{throw "hello, exception!";} catch (const char *&str) {cout << str << endl;}return 0;}/*# chmod 744 hello_cpp && ./hello_cppchmod 744 hello_cpp && ./hello_cppHello, world!size:1,capacity:1size:1,capacity:3V[0]:4V[1]:0june -> 30hello, exception!*/?------------------------------------------------
八、依赖库问题:
?
E/AndroidRuntime(544): Caused by: java.lang.UnsatisfiedLinkError: Library XXX not found
这个错误有可能是因为它所依赖的动态库(.so)文件不存在,不一定是因为它自身不存在(开发环境的libs/armeabi目录下)------------------------------------------------
?
九、用Flash Builder 3.5开发Android的Air应用程序(模拟器上运行)
* 安装Flash Builder 3.5,创建一个Flex Mobile Project
* 右键->Export...->Flash Builder->Release Build
* 创建签名C:\Test\Test.p12文件,然后导出Test.apk
* 用adb install Test.apk安装,结果安装失败
Failure [INSTALL_FAILED_INVALID_APK]
(可能因为导出的apk使用了armeabi的.so不能装在模拟器上)
* 确保当前avd已经使用了sdcard(可以用edit按钮修改,但会丢失所有模拟器数据)
如果没有sdcard,后面运行air程序时会失败(adb logcat提示无法创建目录)。
* 用emulator -avd启动这个avd
* 用adb install(或adb install -s)安装C:\Program Files\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\runtimes\air\android\emulator\Runtime.apk
* 在Flex工程目录中写个bat文件,用adt创建自己的apk(指定目标为apk-emulator)
?
set path=C:\Program Files\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\bin;%path%cd bin-releasecall adt.bat -package -target apk-emulator -storetype pkcs12 -keystore C:\Test\Test.p12 ..\Test.apk Test-app.xml Test.swfcd ..pause
* 在模拟器内的settings中确保已经安装air(因为它不显示在启动器中)
* 用adb install重新安装生成的Test.apk
* 运行,成功
?
参考:
http://www.3amartstudio.com/blog/post/130.html
http://www.cnblogs.com/ginoz/archive/2011/01/26/1945074.html
http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-5d0f4f25128cc9cd0cb-7ffe.html
?
?
(20120527)
如果用真机调试,SDK中AIR运行时的安装包
C:\Program Files\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\runtimes\air\android\device\Runtime.apk
只包含armeabi-v7a的.so文件,可能需要自己替换成
C:\Program Files\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\runtimes\air\android\emulator\Runtime.apk
否则运行会出错。
?
------------------------------------------------
十、apk逆向工程 / android hack技术
?
(TODO)
参考:
http://chuancun.sakura.ne.jp/mt/mt-search.cgi?IncludeBlogs=2&search=source%20code
(链接失效)
?
如何用gdb找到Android so文件中的加密key
http://all-ipad.net/how-to-get-key-from-android-so-using-gdb/
?
?
-------------------------------------------------
十一、adb使用摘要
(2012/03/13)
?
摘自android-ui-utils的design-preview:
http://code.google.com/p/android-ui-utils/
?
1. 运行应用程序的某个Activity
$ adb shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n com.google.android.apps.proofer/.DesktopViewerActivity
?
2. 强制杀死应用程序
$ adb shell am force-stop com.google.android.apps.proofer
?
3. 卸载应用程序
$ adb uninstall com.google.android.apps.proofer
?
4. 安装apk到SD卡
$ adb install -r Proofer.apk
?
5. 重定向设备的监听端口到本机
$ adb forward tcp:<本地端口号如6800> tcp:<设备端口号如7800>
(Windows下测试)
> netstat -ano | find "6800"
> telnet localhost 6800
?
6. 搜索是否安装某个应用程序
$ adb shell pm list packages | grep com.google.android.apps.proofer
其它adb或android自带命令请参考:
http://en.androidwiki.com/wiki/ADB_Shell_Command_Reference
http://developer.android.com/guide/developing/tools/adb.html
?
?
十二、Android数据共享手段:
http://developer.android.com/resources/faq/framework.html
?
http://stackoverflow.com/questions/1636500/are-static-fields-in-activity-classes-guaranteed-to-outlive-a-create-destroy-cyc
?
http://stackoverflow.com/questions/2114312/android-persistent-state-with-global-variables-when-system-kills-activities
?
方法有(性能和适用的数据类型不一样,根据情况选择):
1.?Intent.putExtras()
2.?Preferences
3. 单例类getInstance()
?
?
class EvilSingleton{ private static EvilSingleton instance; //put your data as non static variables here public static EvilSingleton getInstance() { if(instance == null) instance = new EvilSingleton(); return instance; }}?4.?public static字段/方法
5.?Long键WeakReference对象值的HashMap,传递Long键给另一个活动
6. 文件
7. 内容提供者
8. SQLite DB
9. 覆盖Application类
?
?
public class MyApplication extends Application{ private String thing = null; public String getThing(){ return thing; } public void setThing( String thing ){ this.thing = thing; }}public class MyActivity extends Activity { private MyApplication app; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); app = ((MyApplication)getApplication()); String thing = app.getThing(); }}?
十三、在App中运行原生可执行文件(elf格式)
?
Run native executable in Android App
http://gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App
https://github.com/gimite/android-native-exe-demo
?
十四、ListView的一些问题
?
(1) ListView滚动时右侧快速滑块的启用方法
http://www.maxhis.info/archives/541
?
?
myListView.setFastScrollEnabled(true);
?
(2) 记录和恢复ListView滚动的位置
http://yes2.me/archives/567
?
?
//列表滚动private OnScrollListener ScrollLis = new OnScrollListener() {@Overridepublic void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if(scrollState==OnScrollListener.SCROLL_STATE_IDLE){ ListPos=list.getFirstVisiblePosition(); //ListPos记录当前可见的List顶端的一行的位置 }}};??
setOnScrollListener(ScrollLis);list.setSelection(ListPos);
?
十五、WebView的问题:
?
(1) JavaScript内定时器被触碰的输入事件阻塞
?
方法一:在JavaScript内解决。
参考:
http://www.html5rocks.com/en/mobile/touch/
?
?
clock();setInterval(clock, 1000);var touches = []document.body.addEventListener('touchmove', function(event) {event.preventDefault(); //关键在这一句console.log("touchmove");touches = event.touches;}, false);?上面的touches数组可以传递给clock(),作为拖动信息读取。
?
方法二:在Java内屏蔽ACTION_MOVE,不过js端无法得到touchmove事件信息。
?
?
setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_MOVE) {return true;}return false;} });?
?
?
十六、用CDT?Indigo SR2创建main入口c工程
?
配置步骤:
(0) CDT和NDK:
假设我的NDK目录是:
C:\cygwin\home\Administrator\android-ndk-r7b-windows\android-ndk-r7b\
CDT使用
Eclipse CDT Indigo Service Release 2(SR2支持创建交叉编译工程)
(1) 创建工程
Project name: test
File->New->C Project->
Executable->Cross-Compile Project->
Cross GCC
(2) 创建工程向导
Tool command prefix:?
arm-linux-androideabi-
Tool command path:
C:\cygwin\home\Administrator\android-ndk-r7b-windows\android-ndk-r7b\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin
(3) 字符集
右键工程(注:在Project Explorer视图中,下同)->Properties->Resource
Text file encoding
选择Other: UTF-8
(4) make命令目录
Properties->C/C++ Build->
取消勾选Use default build command
Build command:
填入:
C:\cygwin\home\Administrator\android-ndk-r7b-windows\android-ndk-r7b\prebuilt\windows\bin\make?
(5) gcc参数设置
Properties->C/C++ Build->Settings->
Tool Settings->Cross GCC Compiler->Includes->
Include paths (-I)
添加:(带引号)
"C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/platforms/android-8/arch-arm/usr/include"
Tool Settings->Cross GCC Linker->Libraries->
Libraries (-l)
添加:
log
Library search path (-L)
添加:(带引号)
"C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/platforms/android-8/arch-arm/usr/lib"
Tool Settings->Cross GCC Linker->Miscellaneous->
Linker flags
填入:(带引号)
--sysroot="C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/platforms/android-8/arch-arm"
(6) 检查是否头文件目录正确:
按OK退出Properties后目录下的Includes节点出现三个目录:
C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/platforms/android-8/arch-arm/usr/include
C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/lib/gcc/arm-linux-androideabi/4.4.3/include
C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/lib/gcc/arm-linux-androideabi/4.4.3/include-fixed
(7) 添加测试源文件
工程右键->New->Source File
Source file:填hello.c
Template:选择Default C source template
hello.c的内容如下:
?
?
/* * hello.c * * Created on: 2012-4-13 * Author: Administrator */#include <stdio.h>#include <android/log.h>#define TAG "HelloWorld"int main(int argc, char **argv) {printf("Hello, world!\n");__android_log_print(ANDROID_LOG_INFO, TAG, "Hello, world!\n");return 0;}??
(8) 开始编译:
工程右键->Build Project
弹出Build Project对话框,编译结束后消失。
出现Binaries节点和Debug目录
makefile文件生成在Debug目录下。
因为是调试版,所以Binaries节点中的"test - [arm/le]"可以展开
(9) 重新编译:
如果修改hello.c,但不编译,CDT仍然可以检查.c文件中的错误,
但Debug目录下的输出文件不会被修改。
重新编译可以有两种方法:
方法一、同(8),相当于执行make all
方法二、
Window->Show Views->Others->Make Target
打开Make Target视图
切换到test/Debug节点,然后按右上角加号按钮,
添加:clean all
然后双击clean all节点即可重新编译,
gcc编译器警告和错误信息输出在Problems视图中。
而make输出信息在Console视图的CDT Build Console中
(见视图右上角倒数第2个下拉菜单)
我的输出信息是:
?
?
?
'Finished building: ../hello.c'?
(10) gdbserver运行:
关于adb forward,上传二进制文件,gdbserver的运行的方法同前,略。
?
file Debug/testb main??
然后按Debug连接gdbserver调试。
如果成功,Console视图可以直接输入gdb指令(会显示为绿色,同前,略)。
暂时没有办法在编辑器中加断点,也没有办法关联地打开源文件。
十六、Error generating final archive: Debug Certificate expired on ...的错误(转)
?
see
http://www.cnblogs.com/yyangblog/archive/2011/01/07/1929657.html
?
解决方法:
?
?
?写道解决方法:?
?
?
(20120616)
十七、刷新avd列表(重启adb服务器)
> adb kill-server
> adb start-server
?
十八、查看内存占用量(检查内存泄露)
> ddms
选择一个进程,
然后按左上角show heap updates按钮(在Eclipse中则为DDMS切面Devices视图中的update heap按钮)
然后切换到右面的VM Heap,按Cause GC开始监控堆大小的改变(数值自动更新)
注意:如果是程序是多进程的,只显示其中一个进程的堆大小。其它进程要选择另一行。
?
?
(TODO)
?
?
?