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插件来简化配置操作。
(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的一些问题。
十五、用CDT Indigo 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应用程序问题
三十一:adb shell提示error: device unauthorized. Please check the confirmation dialog on your device,但不弹出授权对话框
三十二:用ADT调试程序,安装到模拟器时出现超时错误,提示Failed to install xxx.apk on device 'emulator-5554': timeout
----------------
一、简单地编写JNI及测试:
(注:更快的方法是使用Ant和Eclipse,
见官网的介绍
http://developer.android.com/sdk/ndk/overview.html
首先用
> ..\..\ndk-build.cmd
生成libs\armeabi下的.so文件
然后原地创建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)
> 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 __cplusplus extern "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 JNICALL Java_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\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的输出如下:
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 __cplusplus extern "C" { #endif extern 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并依附到程序(程序已启动)
启动会话后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...
进行编译,输出如下:
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-r5b CC := /cygdrive/C/cygwin/home/Administrator/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-gcc CC += --sysroot=$(NDK_HOME)/platforms/android-9/arch-arm RM := rm -rf CFLAGS := -g CFLAGS += -I $(NDK_HOME)/platforms/android-9/arch-arm/usr/include LIBS := -lm TARGET := hello OBJS := hello.o all : $(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 := libgl2jni LOCAL_CFLAGS := -Werror LOCAL_SRC_FILES := gl_code.cpp LOCAL_LDLIBS := -llog -lGLESv2 LOCAL_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 := true include $(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
中:
如果出现undefined reference to `std::__throw_bad_alloc()'错误
需要添加以下标志:
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
参见
--------------------------
七、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_cpp pause
上传和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 range
cout << "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_cpp
chmod 744 hello_cpp && ./hello_cpp
Hello, world!
size:1,capacity:1
size:1,capacity:3
V[0]:4
V[1]:0
june -> 30
hello, exception!
*/
------------------------------------------------
八、依赖库问题:
(20160119:从ndk-r9开始有个新的工具叫ndk-depends,可以判断依赖次序。
另外依赖是有次序的,如果system.loadlibrary调用的次序不对,也会造成UnsatisfiedLinkError错误)
E/AndroidRuntime(544): Caused by: java.lang.UnsatisfiedLinkError: Library XXX not found
------------------------------------------------
九、用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-release call adt.bat -package -target apk-emulator -storetype pkcs12 -keystore C:\Test\Test.p12 ..\Test.apk Test-app.xml Test.swf cd .. 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
方法有(性能和适用的数据类型不一样,根据情况选择):
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滚动的位置
//列表滚动
private OnScrollListener ScrollLis = new OnScrollListener() {
@Override
public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
}
@Override
public 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() {
@Override
public 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个下拉菜单)
我的输出信息是:
**** 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/test b 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
原来是被豌豆荚占用,杀掉该进程即可。
- tasklist /fi "pid eq 4792"
(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输出
(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
(20160119:大部分卡死情况可参考下面《二十八》的方法)
解决方法:删除文件和目录:
workspace/.metadata/.plugins/org.eclipse.jdt.core/.org.eclipse.jdt.core.external.folders/
参考:http://blog.csdn.net/forfight/article/details/7783684
原因就处在这个<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
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,例如(下面只是示例):
@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解压出来的
(20180208)如果出现dx错误
dx tool failed:Error:
需要在java.exe后面加上参数-Xms1024m
参考:
https://forum.starling-framework.org/topic/dx-tool-failederror-could-not-create-the-java-virtual-machine
(20150921)
三十一:adb shell提示error: device unauthorized. Please check the confirmation dialog on your device,但不弹出授权对话框
可能是因为设置了环境变量ANDROID_SDK_HOME,但是它没有指向正确的路径。
解决办法:修改环境变量ANDROID_SDK_HOME让它指向我的文档的根目录(参考AVD Manager界面上显示的路径值)
(20160210)
三十二:用ADT调试程序,安装到模拟器时出现超时错误,提示Failed to install xxx.apk on device 'emulator-5554': timeout
如果这种情况经常发生,可能是DDMS的超时时间设置得太短,修改Eclipse设置->Android->DDMS,把超时时间改大
In eclipse, you can increase the timeout. In Eclipse, Go to WINDOW-->Prefrences-->android-->DDMS>increase the timeout value. In my case it was 5000 & i incresed it to 10000 & it worked for me .
参考自:
http://stackoverflow.com/questions/4552435/failed-to-install-apk-on-device-emulator-5554-timeout
(20160902)
三十三、用adt打包apk发布版时显示“Conversion to Dalvik format failed with error 1”
解决方法,取消eclipse的自动编译(Project->Build Automatically把钩去掉),然后再打包
参考:
http://stackoverflow.com/questions/2680827/conversion-to-dalvik-format-failed-with-error-1-on-external-jar
(TODO)