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最初是基于旧版本的CDTGalileo,相对会麻烦很多,而且不容易配置出正确的高亮着色和定义跳转。至于gdb的配置和使用是差不多的。请注意。另外,旧版本CDT可以使用GNU ARM的Ecllipse插件来简化配置操作。

(20150115补注)

注:从2014年12月8日开始google发布Android Studio 1.0并取消adt-bundle的下载(android studio取代adt成为官方IDE)

参考:http://www.36kr.com/t/217653

Eclipse安装链接(未测试):

https://dl-ssl.google.com/android/eclipse/

http://dl.google.com/android/eclipse/(未测试,https?)

https://dl.google.com/android/ADT-23.0.4.zip(单机版更新包,文件名不定)

安装方法参考第二十七条的注释

目录:

一、简单地编写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)

十、apk逆向工程

十一、adb使用摘要

十二、Android数据共享手段

十三、在App中运行原生可执行文件(elf格式)

十四、ListView的一些问题。

十五、用CDTIndigo SR2创建main入口c工程

十六、Error generating final archive: Debug Certificate expired on ...的错误(转)

十七、刷新avd列表(重启adb服务器)

十八、查看内存占用量(检查内存泄露)

十九、打开活动时关闭IME

二十、Eclipse ADT出现ADB server didn't ACK错误

二十一、 在eclipse中显示垃圾回收的状态栏

二十二、ADT的BufferOverflowException错误

二十三、在Chrome PC版中模拟移动设备

二十四、屏蔽nativeGetEnabledTags的logcat输出

二十五、getView被多次调用的问题

二十六:Eclipse或ADT在初始化时卡住:Refreshing /.org.eclipse.jdt.core.external.folders/.link0

二十七:使用ADT with Android 5.0 (ADT 23.0.2) 初始化出现加载错误(第二十七条已过时,勿参考)

二十八:Eclipse ADT初始化时卡死问题(但切换到新的workspace正常)

二十九:如何在无互联网的情况下用真机(Android手机)连接电脑的服务器端口(如8080端口)

三十:用Flash Builder 4.7开发Android的Air应用程序问题

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

一、简单地编写JNI及测试:

(注:更快的方法是使用Ant和Eclipse,

见官网的介绍

http://developer.android.com/sdk/ndk/overview.html

首先用

>..\..\ndk-build.cmd

生成libs\armeabi下的.so文件

然后原地创建Eclipse工程

In Eclipse:
Click File > New Android Project...
Select the Create project from existing source radio button.
Select any API level above Android 1.5.
In the Location field, click Browse... and select the <ndk-root>/samples/hello-jni directory.
Click Finish.

在创建Android工程的向导中有三项,第二项是从现存代码中创建(注意,必须按Browse按钮)

ADT会自动生成原来没有的许多工程文件。

不建议使用以下方法,因为从头再做一遍太麻烦了,而且容易出错!!!

1. 用bat文件设置JDK、Android SDK、ANT的路径,双击启动控制台。

@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)

> android create project --target 1 --name MyJNI --path ./MyJNI --activity MyJNIActivity --package com.example.myjni
> cd myjni
> ant
> ant debug
> android
(添加或检查已有AVD)
> start emualator -avd add2
> start adb logcat
(Ctrl+C退出)
> ant install
> adb shell pm list packages | find "myjni"
(看到package:com.example.myjni)
(打开模拟器,打开主菜单,选择MyJNIActivity,看到有一行文字
Hello World, MyJNIActivity

> ant uninstall
(关闭模拟器)

3. 加入JNI类,放入src\com\example\myjni目录中

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工具)

> mkdir libs
> mkdir libs\armeabi
> C:/cygwin/home/Administrator/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-gcc.exe --sysroot="C:/cygwin/home/Administrator/android-ndk-r5b" -I"C:/cygwin/home/Administrator/android-ndk-r5b/platforms/android-8/arch-arm/usr/include" -L"C:/cygwin/home/Administrator/android-ndk-r5b/platforms/android-8/arch-arm/usr/lib" -o libs\armeabi\libMyJNI.so -shared jni/MyJNI.c

注意:上面的--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的输出如下:

com.android.launcher2.Launcher }
D/dalvikvm( 117): GC_EXPLICIT freed 2501 objects / 136776 bytes in 251ms
W/InputManagerService( 58): Ignoring hideSoftInput of: com.android.internal.vi
ew.IInputMethodClient$Stub$Proxy@44ff2bd0
I/ActivityManager( 58): Starting activity: Intent { act=android.intent.action.
MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.myjni
/.MyJNIActivity }
I/ActivityManager( 58): Start proc com.example.myjni for activity com.example.
myjni/.MyJNIActivity: pid=262 uid=10037 gids={1015}
D/dalvikvm( 262): Trying to load lib /data/data/com.example.myjni/lib/libMyJNI.
so 0x44ede258
D/dalvikvm( 262): Added shared lib /data/data/com.example.myjni/lib/libMyJNI.so
0x44ede258
D/dalvikvm( 262): No JNI_OnLoad found in /data/data/com.example.myjni/lib/libMy
JNI.so 0x44ede258, skipping init
I/System.out( 262): result is 1
I/ActivityManager( 58): Displayed activity com.example.myjni/.MyJNIActivity: 2
033 ms (total 2033 ms)
D/dalvikvm( 119): GC_EXPLICIT freed 1177 objects / 85560 bytes in 95ms
D/dalvikvm( 171): GC_EXPLICIT freed 2990 objects / 179416 bytes in 105ms
D/dalvikvm( 195): GC_EXPLICIT freed 3071 objects / 178608 bytes in 103ms

可以看到:

* dalvikvm加载libMyJNI.so成功,

* 发现JNI_OnLoad不存在,自动跳过。

* System.out输出1,证明执行了MyJNI.mycall。

* .c文件内的printf没有产生任何输出。(不解,可能是.so编译过程有问题)

* 按后退键,然后重新启动活动,执行MyJNI.mycall。

* 按Home键,然后重新启动活动,不执行MyJNI.mycall。

10. 更多信息请参考官方的介绍或其它资料:

* http://developer.android.com/guide/practices/design/jni.html

* http://stackoverflow.com/questions/5123564/use-ant-build-xml-to-compile-jni-directory

* Android NDK的文档和示例。

11. 如果出现C/C++混合编译,请在公共使用的.h头文件的声明中添加extern "C"包裹(不管这个.h文件是用.c实现还是用.cpp实现),然后在.c(或.cpp文件)中使用。

#pragma once#ifdef __cplusplusextern "C" {#endifextern int affine();extern int convolution();#ifdef __cplusplus}#endif

也可参照用javah生成的.h头文件的写法。

由于.c和.cpp都生成.o文件,所以最后的链接过程和纯C(或纯C++)是相同的。在Makefile中只要写两行即可,例如:

...

.cpp.o:

${CXX} ${CXX_FLAGS} ${BOOST_INCLUDE_PATH} ${LIBJPEG_INCLUDE_PATH} -c $<

.c.o:

${CC} ${CC_FLAGS} ${BOOST_INCLUDE_PATH} ${LIBJPEG_INCLUDE_PATH} -c $<

...

libgil.so :libjpeg.a com_iteye_weimingtom_gil_GilJNI.o affine.o

${CXX} -shared -o $@ ${CXX_FLAGS} com_iteye_weimingtom_gil_GilJNI.o affine.o -lstdc++ -lc -lm ${LIBJPEG_LIB_PATH} -ljpeg

在编译.so时最好添加-lstdc++,以防止出现运行期引用缺失的情况(编译期正常,但运行期会出错)。用IDA可能无法检查,因为-lstdc++可能不是表示依赖于某个独立的.so文件(libstdc++.so)

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

20111025:

二、ndk-gdb的使用:(这里用官方提供的原生活动例子,所以需要Level 10的模拟器)

修改AndroidManifest.xml,添加可调试标签:

android:debuggable="true"

<?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并启动程序(程序未启动)

$ ../../ndk-gdb --adb=/cygdrive/D/java/android-sdk_r10-windows/android-sdk-windows/platform-tools/adb.exe --start

或,启动ndk-gdb并依附到程序(程序已启动)

$ ../../ndk-gdb --adb=/cygdrive/D/java/android-sdk_r10-windows/android-sdk-windows/platform-tools/adb.exe

启动会话后ndk-gdb会自动暂停程序,出现>提示符,输入

> l

查看主文件的内容(或直接用编辑器查看)

以选择合适的断点行号或函数名,然后用

> b <断点地址,行号或函数名>

添加断点,

然后输入

> c

继续执行程序。

当断点命中时,可以用

> bt

查看回溯堆栈信息,

或使用其它gdb指令查看当前的变量值。

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

三、在CDT上看NDK工程:( 最好使用CDT Indigo SR2部署工程,见第十五节)

1. 安装JRE(或JDK)以及CDT

JDK :

http://www.oracle.com/technetwork/java/javase/downloads/index.html

Eclipse IDE for C/C++ Developers :

http://www.eclipse.org/downloads/

2. 创建C Makefile工程

File->New->Project...->C/C++->C Project

->(cancel) Use default location :

不带空格,而且是新的子目录(需要自己添加)

->Makefile proejct->Empty->Cross GCC

3. 把工程的文本编码修改为UTF-8

Project->Properties->

Resource->Text file encoding->Other:

-> UTF-8

4. 取消cygwin构建工具的本地化(避免中文乱码)

Project->Properties->

C/C++ Build->Environment->Add... :

-> Name:LANG, Value:en_US.UTF-8

-> Name:PATH, Value:C:\cygwin\bin

(默认不会覆盖原有的环境变量,而是尾加,

所以需要按Edit把C:\cygwin\bin放到PATH的最前面,

避免编译时PATH查找到别的目录中)

5. 修改构建工具

Project->Properties->

C/C++ Build->Builder Settings

-> (cancel) Use default build command

-> Build command: bash -c /cygdrive/C/cygwin/home/Administrator/android-ndk-r5b/ndk-build

(根据实际路径设置ndk-build的cygdrive绝对路径)

6. 修改头文件自动检测命令

Project->Properties->

C/C++ Build->Discovery Options

-> Compiler invocation command

-> C:\cygwin\home\Administrator\android-ndk-r5b\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin\arm-linux-androideabi-gcc.exe

根据NDK工具链的实际位置进行修改。

重启CDT后,Project Explorer会出现Includes目录。

多次修改可能无法生效(CDT的自动检测有问题?)

由于检测数据放在<workspace>\.metadata\.plugins\org.eclipse.cdt.make.core目录下

如果要修改这个设置,可以删除此目录,

然后重启CDT,强制使其重新执行检测命令,

扫描新的头文件目录。

7. 测试make

Project->Clean...

输出内容如下:

bash -c /cygdrive/C/cygwin/home/Administrator/android-ndk-r5b/ndk-build clean

cygwin warning:

MS-DOS style path detected: D:\ugame_c\native_activity

Preferred POSIX equivalent is: /cygdrive/d/ugame_c/native_activity

CYGWIN environment variable option "nodosfilewarning" turns off this warning.

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...

进行编译,输出如下:

**** Clean-only build of configuration Default for project native_activity ****

bash -c /cygdrive/C/cygwin/home/Administrator/android-ndk-r5b/ndk-build clean
cygwin warning:
MS-DOS style path detected: D:\ugame_c\native_activity
Preferred POSIX equivalent is: /cygdrive/d/ugame_c/native_activity
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
Compile thumb : native-activity <= main.c
Compile thumb : android_native_app_glue <= android_native_app_glue.c
StaticLibrary : libandroid_native_app_glue.a
SharedLibrary : libnative-activity.so
Install : libnative-activity.so => libs/armeabi/libnative-activity.so

**** Build Finished ****

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_MODULE := gnustl_static

如果出现undefined reference to `std::__throw_bad_alloc()'错误

需要添加以下标志:

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目录下) 查看导入导出表和依赖库的方法有: (1) 用IDAPro查看导入导出表 用IDAPro打开,然后查看Import或Export视图(可以点击表格的标题栏排序名称) (2) 用readelf或nm或objdump搜索.so的导出函数(用c++filt可以转换C++函数名) $ arm-linux-androideabi-readelf -s libapplication.so | grep SDL_main 335: 0000c3cd 820 FUNC GLOBAL DEFAULT 7 SDL_main $ arm-linux-androideabi-nm -D libapplication.so | grep SDL_main 0000c3cc T SDL_main $ arm-linux-androideabi-objdump -T libapplication.so | grep SDL_main 0000c3cc g DF .text 00000334 SDL_main (3) 用readelf列出.so的依赖动态库 $ arm-linux-androideabi-readelf -d libapplication.so Dynamic section at offset 0x3a200 contains 32 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [libsdl.so] 0x00000001 (NEEDED) Shared library: [libsdl_mixer.so] 0x00000001 (NEEDED) Shared library: [libsdl_image.so] 0x00000001 (NEEDED) Shared library: [libsdl_ttf.so] 0x00000001 (NEEDED) Shared library: [libbz2.so] 0x00000001 (NEEDED) Shared library: [libmad.so] 0x00000001 (NEEDED) Shared library: [libtremor.so] 0x00000001 (NEEDED) Shared library: [libc.so] 0x00000001 (NEEDED) Shared library: [libstdc++.so] 0x00000001 (NEEDED) Shared library: [libm.so] 0x00000001 (NEEDED) Shared library: [libGLESv1_CM.so] 0x00000001 (NEEDED) Shared library: [libdl.so] 0x00000001 (NEEDED) Shared library: [liblog.so] 0x00000001 (NEEDED) Shared library: [libz.so] 0x0000000e (SONAME) Library soname: [libapplication.so] 0x00000010 (SYMBOLIC) 0x0 0x00000019 (INIT_ARRAY) 0x3b134 0x0000001b (INIT_ARRAYSZ) 8 (bytes) 0x00000004 (HASH) 0xd4 0x00000005 (STRTAB) 0x4910 0x00000006 (SYMTAB) 0x15d0 0x0000000a (STRSZ) 25486 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000003 (PLTGOT) 0x3b320 0x00000002 (PLTRELSZ) 984 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0xb8f8 0x00000011 (REL) 0xaca0 0x00000012 (RELSZ) 3160 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x6ffffffa (RELCOUNT) 383 0x00000000 (NULL) 0x0

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

九、用Flash Builder 3.5开发Android的Air应用程序(模拟器上运行)

(已过时,请参考第三十条生成不依赖于运行时的apk)

* 安装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

(20120706新增:)

7. 修改和查看权限

>adb shell chmod 777 /data/affine

>adb shell ls -l/data/affine

8. 同时执行多条命令(Windows下可以不用引号)

>adb shell cd /data; ./affine affine

9. 动态改变模拟器窗口大小

首先要知道目标模拟器的端口号(一般是5554,出现在窗口标题栏中)

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

> telnet localhost 5554

Android Console: type 'help' for a list of commands

OK

help

Android console command help:

help|h|? print a list of commands

event simulate hardware events

geo Geo-location commands

gsm GSM related commands

cdma CDMA related commands

kill kill the emulator instance

network manage network settings

power power related commands

quit|exit quit control session

redir manage port redirections

sms SMS related commands

avd control virtual device execution

window manage emulator window

qemu QEMU-specific commands

sensor manage emulator sensors

try 'help <command>' for command-specific help

OK

window scale 0.5

OK

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

详细见:

http://developer.android.com/tools/devices/emulator.html

也可以用类似的方法模拟电话来电,但不如ddms和Eclipse ADT方便

(ddms是图形界面的,较容易使用)

十二、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() (20150727补注:小心,用Intent方式不能传递太多的数据,有大小限制,超出限制会导致消息无法发送到目的对象)

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;}        });

十六、用CDTIndigo 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个下拉菜单)

我的输出信息是:

写道
**** Build of configuration Debug for project test ****

C:\cygwin\home\Administrator\android-ndk-r7b-windows\android-ndk-r7b\prebuilt\windows\bin\make clean all
rm -rf ./hello.o ./hello.d test
' '
'Building file: ../hello.c'
'Invoking: Cross GCC Compiler'
arm-linux-androideabi-gcc -I"C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/platforms/android-8/arch-arm/usr/include" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"hello.d" -MT"hello.d" -o "hello.o" "../hello.c"
'Finished building: ../hello.c'
' '
'Building target: test'
'Invoking: Cross GCC Linker'
arm-linux-androideabi-gcc -L"C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/platforms/android-8/arch-arm/usr/lib" --sysroot="C:/cygwin/home/Administrator/android-ndk-r7b-windows/android-ndk-r7b/platforms/android-8/arch-arm" -o "test" ./hello.o -llog
'Finished building target: test'
' '

**** Build Finished ****

(10) gdbserver运行:

关于adb forward,上传二进制文件,gdbserver的运行的方法同前,略。

写道 (以下命令可能不正确)
> start emulator -avd add2
> adb forward tcp:5039 tcp:5039
> adb shell
# mkdir /data/hello
> adb push test /data/hello
> adb shell
# cd /data/hello
# chmod 777 test
# gdbserver :5039 ./test

(11) gdb调试配置

Run->Debug Configurations

双击C/C++ Attach to Application添加一个配置

Main标签页设置

C/C++ Application: Debug\test

Project: test

Debugger标签页:

Debugger:

选择:

gdbserver

Debugger Options的Main页

GDB debugger:

填入:

C:\cygwin\home\Administrator\android-ndk-r7b-windows\android-ndk-r7b\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin\arm-linux-androideabi-gdb.exe

GDB command file:

填入:

gdbinit.txt

Debugger Options的connection页

Type: TCP

Host name or IP address: localhost

Port number: 5039

工程右键->New->File

创建gdbinit.txt文件,内容如下:

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

解决方法:

写道 解决方法:
进入C:\Documents and Settings\Administrator\.android 删除路径下的debug.keystore及 ddms.cfg。
(不同环境下的目录可能略有不同,可在eclipse中查找此路径:Window->Preferences->Android->Build下 Default debug keystore)
然后重新导入即可。

(20120616)

十七、刷新avd列表(重启adb服务器)

> adb kill-server

> adb start-server

十八、查看内存占用量(检查内存泄露)

> ddms

选择一个进程,

然后按左上角show heap updates按钮(在Eclipse中则为DDMS切面Devices视图中的update heap按钮)

然后切换到右面的VM Heap,按Cause GC开始监控堆大小的改变(数值自动更新)

注意:如果是程序是多进程的,只显示其中一个进程的堆大小。其它进程要选择另一行。

(20120729)

十九、打开活动时关闭IME

修改AndroidManifest.xml的<activity>标签属性

android:windowSoftInputMode="stateHidden"

(更正,应为:

android:windowSoftInputMode="stateHidden|stateAlwaysHidden"

(20121229)

二十、Eclipse ADT出现ADB server didn't ACK错误

解决方法见:

http://stackoverflow.com/questions/5703550/my-eclipse-adb-server-didnt-ack-failed-to-start-daemon

原因之一可能是5037端口被占用

> adb kill-server

* server not running *

> adb start-server

(无输出)

> adb nodaemon server

cannot bind 'tcp:5037'

> netstat -ao | find "5037"

TCP PC-201009231401:5037 pubstat.sandai.net:0 LISTENING 548

用cport查看5037端口的占用程序。

wandoujia_daemon.exe548TCP5037127.0.0.10.0.0.0Listening

原来是被豌豆荚占用,杀掉该进程即可。

20130822: (参考: http://www.iteye.com/topic/1131687
  1. tasklist/fi"pideq4792"
) 二十一、 在eclipse中显示垃圾回收的状态栏 Window->Preferences, General, 选中“Show heap status”即可; (参考自http://hi.baidu.com/liuhann/item/089d5d246bb319c8a5275aa0)

(20131113)

二十二、ADT的BufferOverflowException错误

http://stackoverflow.com/questions/19727915/android-dex-gives-a-bufferoverflowexception

可用方法之一:使用最新4.x的系统库

可用方法之二:删除自动添加的依赖库

(20140403)

二十三、在Chrome PC版中模拟移动设备

即,怎么用PC版的Chrome打开触屏版的网页。

参考:

http://www.oschina.net/news/46332/google-chrome-developer-tool-gets-device-emulator

注意,有些版本的Chrome是在F12的设置(在工具栏中有个齿轮图标)中,而有些版本则是在F12然后按ESC打开控制台(或者是工具栏上的“>三”图标),然后选择Emulation选择设备。通常需要同时更改User Agent和打开Emulate touch screen开关才可以看到触屏版的页面。

(20140604)

二十四、屏蔽nativeGetEnabledTags的logcat输出

Log message: ^(?!.*(nativeGetEnabledTags)).*$ Name: nativeGetEnabledTags

(20140717)

二十五、Adapter类的getView方法被多次调用的问题

http://blog.csdn.net/ksr12333/article/details/18407527

http://blog.csdn.net/junjieking/article/details/7490602

* GridView(相对于ListView而言)会在onResume之后多调用一次getView(0),可以根据情况忽略掉一些重复操作(实际上很难做忽略的判断,用parent.getChildCount() == position的判断方式并不正确)

* ListView和GridView在某些时候也会重复调用getView方法(例如切换到桌面再切换回应用程序),可以先判断赋值之前的值是否相同再赋值(例如,要赋值图片的引用是否和View的原有图片的引用相同,如果相同则不需要重复赋值)

(20141001)

二十六:Eclipse或ADT在初始化时卡住:Refreshing /.org.eclipse.jdt.core.external.folders/.link0

解决方法:删除文件和目录:

workspace/.metadata/.plugins/org.eclipse.jdt.core/.org.eclipse.jdt.core.external.folders/

参考:http://blog.csdn.net/forfight/article/details/7783684

写道 在workspace/.metadata/.plugins/org.eclipse.jdt.core/.org.eclipse.jdt.core.external.folders/ 目录下,查看.project文件
原因就处在这个<link>标签内部,这是一个link的source,当初为了查看代码方便就把eclipse添加了外部的源码文件夹(我也不知道咋描述了,反正就是这个意思)但是,后来貌似这个文件夹被我删除了……然后貌似就是因为这个样子 它就会一直刷啊刷啊
问过别人这个问题,貌似即使是不删除源码文件夹 它每次加载的时候也会很慢
反正现在启动的速度倒是快了 但是attached resource不见了 看代码又麻烦了……愁~

(20141108)

二十七:使用ADT with Android 5.0 (ADT 23.0.2) 初始化出现加载错误(已过时,勿参考)

(20150210:

以下内容已过时,

因为Google已经不再发布ADT-bundle的打包版,旧版本的ADT-bundle如果升级插件(或者不升级),然后再装5.x的SDK时会出现各种错误(可能是adt带的eclipse版本低的原因)

建议使用最新版eclipse(非ADT旧版本中的eclipse,去eclipse官网下,我用的是eclipse-java-luna-SR1-win32),和JDK7,在线安装ADT插件,详细方法参考官网

http://developer.android.com/tools/sdk/eclipse-adt.html

http://developer.android.com/sdk/installing/installing-adt.html

在线安装路径(输入到Help->Install New Software->Add->Location,Name随便填):

https://dl-ssl.google.com/android/eclipse/

http://dl.google.com/android/eclipse/

离线安装包(文件名可能会变)

https://dl.google.com/android/ADT-23.0.4.zip

或参考本文开头的补注

-------------------------以下内容已过时---------------------------

Parsing Data for android-21 failed

Unsupported major.minor version 51.0

解决方法:新版本ADT不支持JDK 6,需要安装JDK 7以上

参考:

http://stackoverflow.com/questions/26474298/android-parsing-data-for-android-21-failed

如果出现这样的错误,

parseSdkContent failed Could not initialize class android.graphics.Typeface

parseSdkContent failed java.lang.ExceptionInInitializerError

需要删除user目录(XP为C:\Documents and Settings\Administrator)中的.android目录,

和删除workspace目录(例如D:\Documents and Settings\Administrator\workspace)中的

.metadata目录(或者主菜单->切换工作目录到其他目录)

如果还报错,需要用android20的layoutlib.jar文件替换android21的layoutlib.jar

写道 1. Download the SDK platform for API 20 (4.4W)
2. Navigate to your sdk folder (should be like D:\EclipseWorkspace\adt-bundle-windows-x86_64-20140321\sdk)
3. Go to platforms folder -> android-21 folder -> data folder
4. rename layoutlib.jar (for backup purpose)
5. copy the same file (layoutlib.jar) from your android-20 folder to this folder
6. restart Eclipse

参考:

http://stackoverflow.com/questions/24636393/parsesdkcontent-failed-could-not-initialize-class-android-graphics-typeface

http://stackoverflow.com/questions/5019051/android-sdk-content-loader-failing-with-nullpointerexception/5883841#5883841

http://stackoverflow.com/questions/25065336/eclipse-parsesdkcontent-failed-error-not-recognizing-xml-files

http://stackoverflow.com/questions/24669350/parsesdkcontent-failed-could-not-initialize-class-android-graphics-typeface

-------------------------以上内容已过时---------------------------

(20140501)

二十八:Eclipse ADT初始化时卡死问题(但切换到新的workspace正常)

ADT有时候初始化会卡死在插件加载中,但切换到新的workspace是正常,

猜测可能是ADT插件报错了(参考workspace下的.log文件)

这时候可以尝试这样做

* 把sdk目录改名,例如改成_sdk(让eclipse找不到Android SDK的目录)

* 重启Eclipse,让初始化能成功完成

* 关闭所有工程(右键->close)

* 关闭Eclipse,把sdk目录改名为原有的,让ADT能找回目录

* 重启Eclipse,等初始化成功后,创建新的Android工程或打开一个旧有的工程(不要打开太多),看是否能加载SDK成功。

(20120520)

这个问题的另一个解决办法是删除workspace目录下\.metadata文件夹里的workbench.xmi文件

参考:

http://stackoverflow.com/questions/15372023/eclipse-will-not-start-and-i-havent-changed-anything

不过代价是IDE布局被重置。

(20150721)

二十九:如何在无互联网的情况下用真机(Android手机)连接电脑的服务器端口(如8080端口)

方法一:PC通过USB线共享网络给手机(前提:手机支持USB线上网功能,但部分手机和平板没有USB上网功能)

说明:测试可行,可以ping通,例如我的手机通过USB接入PC后,在adb shell下用netcfg查看IP是

usbnet0 UP 10.0.2.15/24,

然后用ping -c4 10.0.2.2可以ping到PC

手机不打开Wifi,但可以看到网速,可以在设置中看手机的IP(或通过netcfg命令),但PC的IP不能查看,应该是固定的10.0.2.2(原理不明)

如果是模拟器,相当于用这种方式(即使宿主机没有联网获得IP,在模拟器内也可以通过10.0.2.2访问宿主机的端口)

方法二:PC通过无线网卡的SoftAP模式共享网络给手机(前提:PC的USB无线网卡支持SoftAP模式)

说明:这种方法比较通用,我的水星无线网卡测试可行。

此时PC的无线网卡IP是192.168.0.1(相当于网关),手机的IP是192.168.0.*之类(需要打开Wifi)

方法三:手机通过wifi热点功能共享网络给PC(前提:PC有USB无线路由,手机支持wifi热点功能,但部分手机和平板没有热点功能)

说明:实际测试过好像有问题(PC可以连上,但获取不到IP,或者无法ping通)

此时手机的IP是192.168.0.1,PC的IP是192.168.0.*之类

(20150722)

三十:用Flash Builder 4.7开发Android的Air应用程序问题

主菜单->项目->导出发行版

根据向导生成证书,就可以导出apk,如果选择

”导出具有运行时绑定的应用程序“

则生成的apk不依赖于air for android运行时(即生成的apk文件变大,但不需要额外安装air的运行时apk)

不过有个问题,在某些设备上会报错:

http://stackoverflow.com/questions/14922761/android-adobe-air-crash-report-java-lang-unsatisfiedlinkerror

这是FB 4.7自带的runtime.apk有bug,因为它不是最新的版本

解决办法:

(1) 下载最新的labs版Flex SDK

Adobe Labs Downloads(这个比fb的air新,相当于最新的Air for android版)

http://labs.adobe.com/technologies/flashruntimes/air/

Download the AIR beta(下载页面)

AIR 19 SDK & Compiler Beta

AIR 19 SDK for Flex Developers

(两个SDK zip包均可)

http://labs.adobe.com/downloads/air.html

https://helpx.adobe.com/air/kb/archived-air-sdk-version.html

解压到某个目录,例如

E:\Program Files (x86)\Adobe\Adobe Flash Builder 4.7\sdks\air19_sdk_sa_win

用于第(3)步的adt.jar

(2) 在导出发行版的对话框中勾选

“保留bin-release-temp文件夹”

(这样生成的发行版swf文件和xml文件可以保留)

然后根据普通的方法主菜单->项目->导出发行版生成apk

(3)写一个bat文件,用命令行编译apk,例如(下面只是示例):

写道 @cd bin-release-temp
@java.exe -jar "E:\Program Files (x86)\Adobe\Adobe Flash Builder 4.7\sdks\air19_sdk_sa_win\lib\adt.jar" -package -target apk-captive-runtime -storetype pkcs12 -keystore "D:\Users\Administrator\Adobe Flash Builder 4.7\testflex2\testflex.p12" -storepass testflex testflex2.apk testflex2-app.xml testflex2.swf
@pause

这个命令行是根据“导出发行版”的向导对话框第2步“打包设置“右下角的”自定义启动“按钮里面的”显示命令“按钮的内容改写的,注意adt.jar所在目录是上面下载的zip解压出来的

(TODO)

更多相关文章

  1. APK签名
  2. 创建和使用library
  3. Android数据持久化之文件存储
  4. ffmpeg编译android 硬解码支持库 libstagefright(1)—— git-hub&n
  5. Android使用AOP
  6. Android(安卓)Lottie动画初探
  7. Android(安卓)APK升级代码编写心得
  8. Android:将AVD文件搬家(修改AVD路径)
  9. android利用FTP实现文件共享

随机推荐

  1. Android基础—WebView(网页视图)基本用法
  2. 关于Android使用Google Map Android API
  3. android UI小结(三)
  4. 全局共享变量(Android)
  5. SqliteDatabase
  6. Android开发之消息处理机制(二)——消息循
  7. 布局之六GridLayout,Space
  8. Android(安卓)nine-patch .9使用方法入门
  9. 敏捷个人手机应用iOS和Android公开注册
  10. android添加删除桌面快捷方式