Quantcast
Channel: Sam的技术Blog
Viewing all 158 articles
Browse latest View live

OpenNI2 研究

$
0
0
作者:Sam (甄峰)  sam_code@hotmail.com

 
0. 背景介绍:
近期要研究ROS Xtion Driver. 在ROS系统下, Xtion Driver是openni2_camera, 它读取Xtion数据并将数据发布到各Topic供其它Node使用。但研究下来,其实openni2_camera仅仅是冰山露出海面的部分。它构建了类似Linux Driver 中的Device,Driver 概念,并使用Manager管理Device。看起来很清晰,但数据处理,Device具体处理等庞大的部分,其实并不在这个包内。二是另有玄机。现在就将这部分内容大概的理一下。
 
 
1. openni2_camera文件结构和组成研究:
这个Package是Asus Xtion and Primesense Devices的Driver。
下载并察看之。
 
分析组成结构:
文件组成和结构的分析,照例是看CMakefiles.txt
A:  首先生成一个动态库,名为:libopenni2_wrapper.so:
 
add_library(openni2_wrapper src/openni2_convert.cpp
   src/openni2_device.cpp
   src/openni2_device_info.cpp
   src/openni2_timer_filter.cpp
   src/openni2_frame_listener.cpp
   src/openni2_device_manager.cpp
   src/openni2_exception.cpp
   src/openni2_video_mode.cpp )
target_link_libraries(openni2_wrapper ${catkin_LIBRARIES} ${PC_OPENNI2_LIBRARIES} ${Boost_LIBRARIES} )
 
可以看到,它由src下的一些文件构成。同时,请注意,这个库依赖于${PC_OPENNI2_LIBRARIES}
它是谁呢?是/usr/lib/OpenNI2/Drivers中的各个库文件,这个库提供对设备的识别,操作,对数据的处理等大量的工作。
 
 
B:test_wrapper应用程序
add_executable(test_wrapper test/test_wrapper.cpp )
target_link_libraries(test_wrapper openni2_wrapper ${Boost_LIBRARIES})
这个程序用来尝试使用A库。由test/test_wrapper.cpp构成,并依赖于A 库。
 
 
C:生成主要的动态库:libopenni2_driver_lib.so:
add_library(openni2_driver_lib src/openni2_driver.cpp ) target_link_libraries(openni2_driver_lib openni2_wrapper ${catkin_LIBRARIES} ${Boost_LIBRARIES} ) add_dependencies(openni2_driver_lib ${PROJECT_NAME}_gencfg ${PROJECT_NAME}_generate_messages_cpp)
它原来于A库。
 
D:nodelet 库:
add_library(openni2_camera_nodelet ros/openni2_camera_nodelet.cpp )
target_link_libraries(openni2_camera_nodelet openni2_driver_lib ${catkin_LIBRARIES} ${Boost_LIBRARIES} )
add_dependencies(openni2_camera_nodelet ${PROJECT_NAME}_gencfg)
这个是为nodelet创建的库。 它依赖于C库,则间接依赖于A库。
 
 
E:node:
add_executable(openni2_camera_node ros/openni2_camera_node.cpp )
target_link_libraries(openni2_camera_node openni2_driver_lib ${catkin_LIBRARIES} ${Boost_LIBRARIES} )
add_dependencies(openni2_camera_node ${PROJECT_NAME}_gencfg ${PROJECT_NAME}_generate_messages_cpp)
与nodelet地位相同,但它是创建一个Node。利用Node发布Topic。
它依赖于C库,则间接依赖于A库。
 
 
F:list_devices, usb_reset应用程序:
比较简单的Linux程序,打开设备并设置。
 
 
2. libopenni2_wrapper.so 中各种概念(Manager, Device, Driver)的分析
 2.1: Manager:
class OpenNI2DeviceManager:它主要用来管理Device。对插入和拔出设备进行监听。随时维护正在插入设备的列表。并得到他们的信息。
 
在构造函数中,
A: 首先调用底层库的: openni::OpenNI::initialize()
B: device_listener_ = boost::make_shared(); 创建了OpenNI2DeviceListener class 的对象。并给出对象指针。
 
先着重谈谈OpenNI2DeviceListener 这个Class。
它是 public openni::OpenNI::DeviceConnectedListener,
                             public openni::OpenNI::DeviceDisconnectedListener,
                             public openni::OpenNI::DeviceStateChangedListener
的子class.
 
在OpenNI2DeviceListener 构造函数中,它把自己的对象加入监听队列:
openni::OpenNI::addDeviceConnectedListener(this);
    openni::OpenNI::addDeviceDisconnectedListener(this);
    openni::OpenNI::addDeviceStateChangedListener(this);
 
并获取已经连接的Device信息:
    openni::Array device_info_list;
    openni::OpenNI::enumerateDevices(&device_info_list);
 
    for (int i = 0; i < device_info_list.getSize(); ++i)
    {
      onDeviceConnected(&device_info_list[i]);
    }
 并把这些设备记录下来。
 
它主要用来监听设备的连接和断开。
 
device_manager.getDevice(uri);
则返回一个新创建的Device。
 
 
2.2:Driver;
在构造函数中。
1. 利用OpenNI2DeviceManager的static函数getSingelton()获取到Manager。
2. 在initDevice()中,利用Manager的getDevice()获取到当前Device。(此处会初始化Device)
3. advertiseROSTopics();
 
现在主要分析advertiseROSTopics()
 
 
 
 
 

 

毫米波雷达简介

$
0
0
作者: Sam (甄峰) sam_code@hotmail.com


毫米波实质上就是电磁波。毫米波的频段比较特殊,其频率高于无线电,低于可见光和红外线,频率大致范围是10GHz—200GHz。毫米波介于微波(Micro waves)和THz(1000GHz)之间,可以说是微波的一个子集。



在这个频段,毫米波相关的特性使其非常适合应用于车载领域。目前,比较常见的车载领域的毫米波雷达频段有三类。

其一是24—24.25GHz这个频段,目前大量应用于汽车的盲点监测、变道辅助。雷达安装在车辆的后保险杠内,用于监测车辆后方两侧的车道是否有车、可否进行变道。这个频段也有其缺点,首先是频率比较低,另外就是带宽(Bandwidth)比较窄,只有250MHz。

另一个频段就是77GHz,这个频段的频率比较高,国际上允许的带宽高达800MHz。这个频段的雷达性能要好于24GHz的雷达,所以主要用来装配在车辆的前保险杠上,探测与前车的距离以及前车的速度,实现的主要是紧急制动、自动跟车等主动安全领域的功能。

第三类应用频段就是79GHz—81GHz,这个频段最大的特点就是其带宽非常宽,要比77GHz的高出3倍以上,这也使其具备非常高的分辨率,可以达到5cm。这个分辨率在自动驾驶领域非常有价值,因为自动驾驶汽车要区分行人等诸多精细物体,对带宽的要求很高。

现在各个国家把24GHz划出来可以民用,77GHz划分给了汽车防撞雷达


在波长方面,24GHz毫米波的波长是1.25cm,而77GHz毫米波的波长大概是4mm,毫米波的波长要比光波的波长长1000倍以上,所以它对物体的穿透能力更强。

举个例子,我们通常看到的灰尘的直径大概在1um—100um之间,自然界的雨点的直径在0.5mm—4mm的范围内。所以波长与它们相等或者更长的电磁波可以轻易穿透这些障碍物,毫米波便拥有这样的能力。


全球主要有四大毫米波雷达供应商简称为ABCD,即Autoliv、Bosch、Continental和Delphi。

Autoliv以24GHz盲点、变道辅助雷达为主,主要客户是戴姆勒奔驰——其车辆基本标配了变道辅助,Autoliv的毫米波雷达出货量很大。

Bosch的毫米波雷达主要以77GHz为主,覆盖的面比较广,有长距(LRR)、中距(MRR)以及用于车后方的盲点雷达。Bosch的方案集成度非常高,输出的是对汽车的控制信号,其定制性很强,通常是与大型车企合作一个车型,共同推进项目。

Continental在毫米波雷达产品方面既有24GHz,也有77GHz,性能做得还不错,戴姆勒的77GHz毫米波雷达主要由Continental供应。

Delphi则是美国老牌企业,以77GHz毫米波雷达为主,采用较为传统的硬件方案,成本比较高,性能不俗。


毫米波雷达的特点:

对距离、速度和角度的探测

需要明确的一点是,毫米波雷达在测量目标的距离、速度和角度上展现的性能和其他传感器还是略有区别的。视觉传感器得到的是二维信息,没有深度信息,而毫米波雷达则是具备深度信息的,可以提供目标的距离;激光雷达对于速度并不敏感,而毫米波雷达则对速度非常敏感,可以直接获得目标的速度,因为毫米波雷达会有很明显的多普勒效应,通过检测其多普勒频移可将目标的速度提取出来。

毫米波雷达的分辨率:

毫米波雷达的分辨率。其定义是“雷达可以区分的两个物体的最近的距离”,比如,两个物体靠得很近,那么雷达可能会将其列为一个物体,如果分得开一些,雷达会看到两个物体。那么究竟离多远雷达能区分两个物体间的距离,这个就叫做雷达的分辨率。

分辨率的计算公式也很简单,就是光速/2倍的雷达带宽,所以对于24GHz和77GHz来说,可以直接算出其分辨率。前者是0.6m,后者则约为20cm。而3GHz带宽的毫米波雷达的分辨率可以做到5cm,非常适合自动驾驶的应用。


24GHz,带宽250M。

77GHz,带宽800M

79GHz—81GHz,带宽3000M 


与激光的区别:



毫米波和大多数微波雷达一样,有波束的概念,也就是发射出去的电磁波是一个锥状的波束,而不像激光是一条线。这是因为这个波段的天线,主要以电磁辐射,而不是光粒子发射为主要方法。这一点,雷达和超声是一样,这个波束的方式,导致它优缺点。优点,可靠,因为反射面大,缺点,就是分辨力不高。

毫米波雷达可以对目标进行有无检测、测距、测速以及方位测量。




 

OpenCV for Linux 编译中遇到的几个问题

$
0
0
作者:Sam (甄峰)  sam_code@hotmail.com

这几天需要编译Linux下几个特定版本(2.4.13)的OpenCV库。OpenCV各版本库已经编译多次,本想这是非常容易的事情了,可没想到竟然遇到一些问题。先把最后找到的经典方法记录如下:


0. Download OpenCV:
先使用:git clone https://github.com/opencv/opencv.git

#git branch -a 
master 
remotes/origin/2.4
remotes/origin/master
当前的分支是master.

#git describe
3.3.0-56-g89172c0
是3.3版本。但Sam需要2.4.xx版本。

切换:
#git checkout 2.4
#git describe
2.4.13-4-gf7d99f3

好,这个版本可以用了。

1. 编译:
先进入编译脚本目录:
cd platforms/scripts/
但里面没有i686版本脚本。所以Sam干脆增加一个脚本。仿照其它编译脚本。

cmake_linux_i686.sh

#!/bin/sh
cd `dirname $0`/..

mkdir -p build_linux_i686
cd build_linux_i686

cmake -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DBUILD_EXAMPLES=1 -DCMAKE_TOOLCHAIN_FILE=../linux/gnu.toolchain.cmake  $@ ../..


$cd platforms
$sh scripts/cmake_linux_i686.sh
$cd build_linux_i686
$make

编译完成。

下面再说说遇到的问题。



3. 第一次尝试中遇到的问题及解决方法
3.1: 下载:
http://www.opencv.org/releases.html
下载了opencv-2.4.13-3.zip
同样在platforms/scripts/ 下建立了cmake_linux_i686.sh
$cd platforms
$sh scripts/cmake_linux_i686.sh

CMake Warning at cmake/OpenCVPackaging.cmake:23 (message):
  CPACK_PACKAGE_VERSION does not match version provided by version.hpp
  header!
Call Stack (most recent call first):
  CMakeLists.txt:1106 (include)


分析:
查看cmake/OpenCVPackaging.cmake 23行内容:
  if (NOT "${OPENCV_VCSVERSION}" MATCHES "^${OPENCV_VERSION}.*")
    message(WARNING "CPACK_PACKAGE_VERSION does not match version provided by version.hpp header!")
  endif()

OPENCV_VCSVERSION是哪里来的呢? 查到是在CMakeLists.txt中。

if(GIT_EXECUTABLE)
  execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty --match "2.[0-9].[0-9]*"
    WORKING_DIRECTORY "${OpenCV_SOURCE_DIR}"
    OUTPUT_VARIABLE OPENCV_VCSVERSION
    RESULT_VARIABLE GIT_RESULT
    ERROR_QUIET
    OUTPUT_STRIP_TRAILING_WHITESPACE
  )
  if(NOT GIT_RESULT EQUAL 0)
    set(OPENCV_VCSVERSION "unknown")
  endif()
else()
  # We don't have git:
  set(OPENCV_VCSVERSION "unknown")
endif()

这段脚本告诉要使用git describe 得到版本。可想而知,OpenCV这次是zip形式download的。肯定没有.git文件。 所以OPENCV_VCSVERSION没有信息。 
所以Sam在这里加上:
set(OPENCV_VCSVERSION "2.4.13")
就可以正常了。

但实际做完发现,其实就是个Warring,不用理都没事。呵呵。



 

ROS 公用包学习解析 vision_opencv

$
0
0
作者: Sam  (甄峰)  sam_code@hotmail.com

0.vision_opencv简介:
这个stack是ROS的OpenCV Interface。这个stack包含两个Package。cv_bridge, image_geometry.
主要用来将sensor::Image (ROS)和cv::Mat(OpenCV)之间数据转换。


cv_bridge: ROS Message和OpenCV之间的桥接。
image_geometry: Collection of methods for dealing with image and pixel geometry

为了在ROS中使用OpenCV,主要使用cv_bridge Package. 



在Indigo和Jade,OpenCV2 作为官方版本存在。要使用它,必须增加dependency on opencv2并使用find_package() 在CMakeLists.txt. 


 find_package(OpenCV)
   include_directories(${OpenCV_INCLUDE_DIRS})
   target_link_libraries(my_awesome_library ${OpenCV_LIBRARIES})
也可以使用openCV3. 




1. 概念:
ROS中,image使用sensor_msga/Image Message 格式。CvBridge是一个ROS库,它提供一个接口在ROS和OpenCV之间 。

稍后研究。



class CvImage
{
public:
  std_msgs::Header header; //!< ROS header
  std::string encoding;    //!< Image encoding ("mono8", "bgr8", etc.)
  cv::Mat image;           //!< Image data for use with OpenCV

  typedef boost::shared_ptr Ptr;
  typedef boost::shared_ptr ConstPtr;















 

使用Android NDK编译器写Makefile研究

$
0
0

作者: Sam (甄峰)  sam_code@hotmail.com

 

0. 基础介绍:

Android推出NDK,是为了可以编译JNI和Native程序。它提供了一系列脚本:ndk-build, ndk-stack, ndk-dbg, ndk-which.  用来帮助用户编译,调试程序。

 

有了这些脚本,尤其是ndk-build, 它和Android.mk,  Application.mk结合,可以快速的产生需要的库或可执行程序。但他们也隐藏了很多信息。例如:编译器用的是哪个,使用什么编译选项,什么链接选项等。头文件使用哪些,库文件使用哪些。无从得知。

 

如果我们不想利用ndk-build系列脚本,而是想直接使用编译器,添加相关编译选项,理论上完全可以编译出Native库和可执行程序。 

 

但这样做,有什么意义呢?Sam工作中会遇到这样的需求:有些第三方库,采用Makefile或CMake编译。若要使用NDK脚本编译,需要重新了解编译思路,哪些源码生成那些库,哪些可执行程序依赖哪些库,然后根据这个写Android.mk.   这样做比较麻烦,尤其对比较庞大复杂的第三方库来说,就不是一个好办法。则可以直接使用NDK的编译器,添加必要的编译选项,修改Makefile或CMakefiles.txt,则可以简单的生成库了。

 

 

1. 寻找编译器:

首先要知道,不同版本的NDK, 所用到的编译器并不相同. Sam手头使用的是NDK-R9。就以它为例分析。

/opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/ 目录下,就是交叉编译器。

 

 

2. 编译选项的添加:

2.1: 头文件系列选项:

-MMD -MP -MF

说明:

-M : 生成文件依赖关系.  显示文件依赖什么头文件,头文件又依赖什么头文件. 仅仅显示依赖关系,不会真编译

-MM: 显示文件依赖关系,但不显示依赖的系统头文件。

-MMD:同-MM。 但存储在.d文件中

 

例子:

gcc -M main.cpp -I../Include
main.o: main.cpp /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/features.h /usr/include/sys/cdefs.h \
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 /usr/include/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-redhat-linux/4.8.3/include/stddef.h \
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 /usr/lib/gcc/x86_64-redhat-linux/4.8.3/include/stdarg.h \
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 /usr/include/unistd.h /usr/include/bits/posix_opt.h \
 /usr/include/bits/environments.h /usr/include/bits/confname.h \
 /usr/include/getopt.h ../Include/Input_Event.h

 

 gcc -M main.cpp -I../Include

main.o: main.cpp ../Include/Input_Event.h

 

 

 

gcc -MMD  main.cpp -I../Include -c

注意,-MMD与 -M  -MM 不同,它不会阻止编译。它会真正的编译下去。

 

-MP:

生成的依赖文件里面,依赖规则中的所有.h依赖项都会在该文件中生成一个伪目标,其不依赖任何其他依赖项。该伪规则将避免删除了对应的头文件而没有更新”Makefile”去匹配新的依赖关系而导致make出错的情况出现。 

 

 

-MF:指定依赖文件。

-MF /home/sam/work/Jeenon/Source/Input_Event_2_Tony/obj/local/armeabi-v7a/objs/Input_Event/Input_Event.o.d

 

感觉以上选项,是否加入意义不大,但为和NDK保持一致,还是加上, 但 -MF不准备加入了:

 

CXXFLAGS := -MMD -MP

 

2.2: fpic:

CXXFLAGS += -fpic

 

2.3:setion:

CXXFLAGS += -ffunction-sections

将每一个function建立一个新的Sections.

 

2.4: 为stack信息跟踪作准备:

CXXFLAGS += -funwind-tables -fstack-protector -no-canonical-prefixes

-funwind-tables:为GDB Stack dump做准备。

 -fstack-protector :选项能够检测出 stack smashing 问题,并在测到问题时通过 abort 方式触发 core dump

 

 

 2.5:指令集和浮点设置:

CXXFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16

 

2.6: 优化:

 CXXFLAGS += -O2

 

2.7:  define:

CXXFLAGS += -DNDEBUG -Dlinux -D_GLIBCXX_USE_WCHAR_T

 

2.8: 异常,RTTI,signed-char

CXXFLAGS += -fexceptions -frtti  -fsigned-char

 

 2.9: 头文件路径:

 CXXFLAGS += -I/opt/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.6/include

CXXFLAGS += -I/opt/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include

CXXFLAGS += -I/opt/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.6/include/backward

CXXFLAGS += -I./

CXXFLAGS += -I/opt/android-ndk-r9/platforms/android-8/arch-arm/usr/include

 

 2.10: 几个优化:

CXXFLAGS += -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300

 

2.11: PIE问题:

CXXFLAGS += -pie -fPIE

 

 3. 链接选项的添加:

LFLAGS += -shared -fpic

 

指定了-sysroot就是为编译时指定了逻辑目录。编译过程中需要引用的库,头文件,如果要到/usr/include目录下去找的情况下,则会在前面加上逻辑目录。
LFLAGS += --sysroot=/opt/android-ndk-r9/platforms/android-8/arch-arm

 


LFLAGS += -lgcc -no-canonical-prefixes -march=armv7-a

 

如果so里有未定义符号,这编译不通过

LFLAGS += -Wl,--fix-cortex-a8  -Wl,--no-undefined 

 

LFLAGS += -lc -lm
LFLAGS += -L/opt/android-ndk-r9/platforms/android-8/arch-arm/usr/lib

LFLAGS += /opt/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/libsupc++.a
LFLAGS += /opt/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/libgnustl_shared.so

 

 

这个结论还不对,下一步继续研究.




注:Android编译动态库时,会加入:

-Wl,-soname,libInput_Event.so



 

i2c_tools使用记录

$
0
0
作者: Sam (甄峰) sam_code@hotmail.com

最近又需要研究I2C Driver。在测试连线时,需要I2C工具。于是下载编译了I2C_Tools. 记录之。

1. download and Make:
$git clone git://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git
$make

可以看到,库文件被放在i2c-tools/lib, 可执行文件被放在i2c-tools/tools。

2. 使用:
2.1:察看I2C总线:
# ./i2cdetect -l                                         
i2c-0   i2c             Tegra I2C adapter                       I2C adapter
i2c-1   i2c             Tegra I2C adapter                       I2C adapter
i2c-2   i2c             Tegra I2C adapter                       I2C adapter
i2c-3   i2c             Tegra I2C adapter                       I2C adapter
i2c-4   i2c             Tegra I2C adapter                       I2C adapter
i2c-5   i2c             Tegra I2C adapter                       I2C adapter




 

Android APP开发环境安装-Linux

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

因为众所周知的原因,Android APP开发环境在国内安装很麻烦。 幸好有无数热心人提供了很多办法解决这个问题。现记录如下。

0. 不同形式的Android 开发环境。
首先介绍不同的Android 开发环境。
0.1. Eclipse + ADT  Plugin.
ADT plugin:eclipse里的一个插件,负责将eclipse与android sdk链接到一起,让eclipse可以调用adk的类库,虚拟机等功能
早期Google把Eclipse作为开发APP的IDE。它自己仅提供ADT  Plugin. 让Eclipse与Android SDK等联结在一起。Sam早期就这么做。
 但Eclipse在不断升级中, 不同版本ADT Plugin与之有兼容性问题。所以后期又推出其它解决方案。

0.2 . ADT bundle
为了解决ATD Plugin与Eclipse兼容性问题,Google推出了ADT Bundle. 它是由Google Android官方提供的集成式IDE,已经包含了Eclipse,你无需再去下载Eclipse,并且里面已集成了插件。

0.3:  Android  Studio
Eclipse是个开源软件,有一些固有的问题,对Android APP开发造成困扰。所以Goolge最终推出自己维护的IDE工具, 就是Android Studio。


1. 各种形式的Android 开发环境的安装
1.1:Eclipse + ADT Plugin:



1.2:ADT Bundle:



1.3: Android Studio:




 

Android Studio 简介和使用细节

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

在Android系统发布早期,Android APP官方IDE是Eclipse+ADT(Android Developer Tools). 但因为这个方案有兼容性和稳定性等各种问题。2014年,Google基于IntelliJ IDEA制作了Android Studio。并将其作为官方唯一提供全面支持的Android IDE。 它由Google开发并免费提供给Android 开发社区。 Eclipse+ADT不再进行开发。

1. 安装JDK:
要使用Android Studio IDE, 需要安装JDK。 JDK7和JDK8均可用于Android Studio。在Linux和Windows系统,安装后还需要设置环境变量。

例如:
export JAVA_HOME=/usr/java/jdk1.7.0_09/
export JAVA_BIN=/usr/java/jdk1.7.0_09/bin
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME JAVA_BIN PATH CLASSPATH


2. 察看Android SDK Manager:
File ->Setting ->Appearance & Behavior ->System Settings -> Android SDK.
或者Tools -> Android -> SDK Manager .
都可以进入 SDK Manager。在这里,可以选择下载的SDK Platform或SDK Tools。


3. Sample Code 下载:
https://github.com/googlesamples


4. Android Studio Project Window:
Android Project Window下,有多个不同的视图。常用的是 Android和Project, Package:

Android 视图通过类型来组织项目的资产文件。如在manifests中,可以看到AndroidManifest.xml文件。Java内可以看到Java Class。 res中放着各类资源。但这并不反映文件在磁盘上的实际位置。例如:AndroidManifest.xml文件,并不存在manifests目录。

Project视图:显示项目的实际目录结构。每个目录都是实际存在的。

Package视图:项目所用到的Package和Class视图。 


5.  app/src/build.gradle和根目录下build.gradle: 
app/src/build.gradle: 告知Android系统,MiniSDK是多少, 目标SDK是多少,还有其它信息。
根目录下build.gradle.

6. Java编程风格:
Android Studio中,可以设置Java编程风格。Java6和Java7编程风格稍有不同。有时使用了Java7的编程风格,编译也许会出错,这时就需要修改编程风格。

File -> Project Structure->app->Properties->Source Compatibility.  选择1.7 


7. Android编译工具
不同的工程需要不同版本的Android 编译工具。需要时可以方便的直接点击下载。

8. Gradle:
Gradle是一个构建工具。gradle是以Groovy语言为基础的。
当创建一个Android Studio项目时,它配置了两个Gradle脚本。

8.1:local.properties: 
在Android 视图中,Gradle Scripts 的local.properties中配置了Android SDK路径。当然,如同其它设置一样,这个选项也可以通过Android Studio 直接设置。File-> Project Structure ->SDK Location

8.2: Gradle.properties:


8.3: 两个Build.gradle:
根目录下的Build.gradle,叫项目文件。
app下的build.gradle, 存放buildToolsVersion, MiniSDK, TargetSDK. 一些以前Manifest.xml中的内容被写道这里。

当然,buildToolsVersion, MiniSDK,TargetSDK等指定的版本,需要被下载到本地。












 

Android NDK学习  NDK一些新特性

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

从2012年最初接触NDK到现在已经5年过去了,从最初的NDK R7到现在已经到达NDK R14.  它本身也发生了很多变化。 例如对C++支持程度。对64bit ARM的支持等。现有必要把这些新特性研究一下。

1. 32bit/64bit ARM平台支持:
在NDK R10的某个版本中,开始支持64bit ARM平台。那时它还是将64bit和32bit NDK分开提供的。
当前Google支持下载的NDK中,最低版本是NDK R10e. 这个版本之后,64bit和32bit采用同一套NDK,只使用编译选项的不同来支持目标代码编译为何种平台。


Instruction Set(s) Notes
armeabi ARMV5TE and later
Thumb-1
No hard float.
armeabi-v7a armeabi
Thumb-2
VFPv3-D16
other optional
Hard float when specified as armeabi-v7a-hard.
Incompatible with ARMv5, v6 devices.
arm64-v8a AArch-64
x86 x86 (IA-32)
MMX
SSE/2/3
SSSE3
No support for MOVBE or SSE4.
x86_64 x86-64
MMX
SSE/2/3
SSSE3
SSE4.1, 4.2
POPCNT

mips MIPS32r1 and later Hard float.
mips 64 MIPS64r6


可以看到,只要在Application.mk中,切换:

#APP_ABI := armeabi-v7a
APP_ABI := arm64-v8a
即可选择64Bit或32Bit。 在代码中,如何区分32Bit和64Bit,可以使用
#ifdef __aarch64__
printf("\nThis is 64bit\n");
#else
printf("\nThis is 32Bit\n");
#endif



2. Clang和GCC:
从NDK R10开始支持clang. 但GCC还作为缺省编译器。
在之后的版本中,clang成为缺省编译器。

clang: 
NDK_TOOLCHAIN_VERSION=clang
指出由clang编译。 

GCC:
#NDK_TOOLCHAIN_VERSION=clang
NDK_TOOLCHAIN_VERSION=4.9



注1:Clang:
Clang是一个C语言C++Objective-C、Objective-C++语言的轻量级编译器源代码发布于BSD协议下.
GCC采用GPLv3. 导致大量芯片厂商更愿意转投Clang+llvm.

注2:
GPLv3争议,Linus对它的评价:
GPL,是GNU General Public License的缩写,是GNU通用公共授权非正式的中文翻译。它并非由自由软件基金会所发表,亦非使用GNU通用公共授权的软件的法定发布条款─只有GNU通用公共授权英文原文的版本始具有此等效力。

嗯我喜歡版本 2 的那些理由,並且我仍然覺得版本 2 是一個非常棒的協議, 理由是:「我給你源代碼,你給我你對它的修改,我們就扯平了」 對吧?這是我用 GPL 版本 2 的理由,就是這麼簡單
然後版本 3 的擴展在某些方面讓我個人覺得非常不舒服,也就是說「我給你源代碼, 這意味着你必須服從我的一些規則,否則你不能把它用在你的設備上。」 對我來說,這是違反了版本 2 協議所追求的所有目的






 

CMake使用记录

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

最近尝试再次编译OpenCV4Android。因为Android SDK, NDK, Cmake版本问题,意料之中的遇到N多问题。分析和解决问题大都需要修改CMake file. 现记录一些信息如下。

0. CMake基本语法记录: 
0.1. CMake中的赋值:
  1. set(variable value1 value2 value3 ... valueN)
 调用这个命令后,variable变量将是一个列表,其中包含值"value1,value2,...valueN"。

  1. set(myvar "a" "b")
  2. message("${myvar}")
  3. message(${myvar})
此时,控制台中将分别打印出"a;b"和"ab"。这是因为,不带引号时,${myvar}是一个列表,包含了两个值,而message中相当于接收到了两个参数"a"、"b",因此输出"ab"。而带有引号时,引号中的内容整体将作为一个参数存在



0.2.  CMake中循环:
CMake中的循环有两种:foreach()...endforeach()和while()...endwhile()

cmake_minimum_required(VERSION 2.6)
#project (V4L2_Utils)

set(mylist "a" "b" c "d")
foreach(_var ${mylist})
     message("current var: ${_var}")
endforeach()  

#cmake ../ -G"Unix Makefiles"
结果:
current var: a
current var: b
current var: c
current var: d


还有一种比较实用的方法是:foreach(loop_var RANGE start stop [step])
cmake_minimum_required(VERSION 2.6)
#project (V4L2_Utils)

set(mylist "a" "b" c "d")
foreach(_var ${mylist})
     message("current var: ${_var}")
endforeach()   

set(result 0)
foreach(_var RANGE 0 100)
     math(EXPR result "${result}+${_var}")
endforeach()
message("from 0 plus to 100 is:${result}")

#cmake ../ -G"Unix Makefiles"
结果:
current var: a
current var: b
current var: c
current var: d
from 0 plus to 100 is: 5050



0.3.  CMake中使用Maco:

Start recording a macro for later invocation as a command.
开始记录一个宏,未来可以把它当作命令来调用:

macro(< name > [arg1 [arg2 [arg3 ...]]])
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
endmacro( < name >)

例:

macro(sum outvar)


     set(_args ${ARGN})

message("${ARGN}")


     list(LENGTH _args argLength)


     if(NOT argLength LESS 4)


         message(FATAL_ERROR "to much args!")


     endif()


     set(result 0)


     foreach(_var ${ARGN})


         math(EXPR result "${result}+${_var}")


     endforeach()


     set(${outvar} ${result})


endmacro()


sum(addResult 1 2 3)


message("Result is :${addResult}")

"${ARGN}"是CMake中的一个变量,指代宏中传入的多余参数因为我们这个宏sum中只定义了一个参数"outvar",其余需要求和的数字都是不定形式传入的,所以需要先将多余的参数传入一个单独的变量中



1. OpenCV4Android(OpenCV3.1)编译时遇到问题
1.0: 编译准备工作:
Sam要编译32bit和64bit两个版本,所以创建了两个不同的设置环境变量的脚本:
setenv_32bit, setenv_64bit.

setenv_32bit: 
export ANDROID_NDK=/opt/android-ndk-r14b/
export ANDROID_SDK=/home/sam/Android/Sdk/
export ANDROID_ABI=armeabi-v7a

export ANT_HOME=/usr/share/ant
export PATH=${PATH}:${ANT_HOME}/bin



setenv_64bit:
export ANDROID_NDK=/opt/android-ndk-r14b/
export ANDROID_SDK=/home/sam/Android/Sdk/
export ANDROID_ABI=arm64-v8a

export ANT_HOME=/usr/share/ant
export PATH=${PATH}:${ANT_HOME}/bin

开始编译:
$cd platforms
$sh scripts/cmake_android_arm.sh


1.1: 错误抓取和分析:
CMake Error at platforms/android/android.toolchain.cmake:812 (message):
  Specified Android native API level 'android-8' is not supported by your
  NDK/toolchain.
Call Stack (most recent call first):
  platforms/build_android_arm/CMakeFiles/3.9.1/CMakeSystem.cmake:6 (include)
  CMakeLists.txt:95 (project)

问题解析:
概念1:Android native API level:
在使用NDK编译时,需要指定系统头文件和库所在目录。而Android版本如此之多,要使用哪个版本的头文件和库,就是个问题。
在Application.mk中,可以使用:APP_PLATFORM=android-12 来指定系统头文件和系统库采用NDK/platforms/android-12/下的版本。
那Android native API level就指这个版本。
--sysroot=/opt/android-ndk-r14b/platforms/android-12/arch-arm

如在NDK R10e中,platforms目录包含从android-3到android-21.
在NDK R14中,platforms目录包含从android-9到android-24.

那如果指定的APP_PLATFORM不包含在NDK指定目录内呢?例如:
APP_PLATFORM=android-8, 但又使用NDK R14.  那系统头文件和库该使用哪个呢?
在NDK编译时,它会指定当前最新的版本:
--sysroot=/opt/android-ndk-r14b/platforms/android-24/arch-arm

那问题就清晰了, OpenCV  Cmake 认为我们指定了Android Native API为8。但NDK R14又不支持。
这就奇怪了,我们并没有指定Native API阿。看CMakefile


A:找到报错地点:
list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx )
if( __levelIdx EQUAL -1 )
 message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." )

利用list(FIND), 查找list--ANDROID_SUPPORTED_NATIVE_API_LEVELS中是否有${ANDROID_NATIVE_API_LEVEL},如果有,则返回index到 --levelIdx. 
显然,这个list中并没有。

那就需要看哪里得到两个值:
list: ANDROID_SUPPORTED_NATIVE_API_LEVELS
ANDROID_NATIVE_API_LEVEL


B: 找两个变量:
B1:list ANDROID_SUPPORTED_NATIVE_API_LEVELS:
__DETECT_NATIVE_API_LEVEL( 
ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" )
这个宏__DETECT_NATIVE_API_LEVEL()的功能是,从NDK/sysroot/usr/include/android/api-leve文件中,获取它所支持的api-level. 

B2: ANDROID_NATIVE_API_LEVEL:
__INIT_VARIABLE( 
ANDROID_NATIVE_API_LEVEL 
ENV_ANDROID_NATIVE_API_LEVEL 
ANDROID_API_LEVEL 
ENV_ANDROID_API_LEVEL 
ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL )

它最终是因为:set( ANDROID_DEFAULT_NDK_API_LEVEL 8 )
而被设置为8.
8: 不包含在9-26的list中,所以报错。

解决方法;
到这一步,解决方法就很明显了:
cmake -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DANDROID_NATIVE_API_LEVEL=14 -DCMAKE_TOOLCHAIN_FILE=../android/android.toolchain.cmake $@ ../..






GDB: 
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")



 

OpenCV4Android编译

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

又尝试完整编译OpenCV4Android (3.1), 因为开发平台(FC26-64bit), CMake(3.9.1), Android SDK 版本,NDK(ndk R14B)等都有变化,会遇到一些版本匹配问题。现记录如下。

编译方法,与之前的blog(http://blog.sina.com.cn/s/blog_602f87700102vdnw.html)一样。

A:先建立配置脚本:
32bit: 
export ANDROID_NDK=/opt/android-ndk-r14b/
export ANDROID_SDK=/home/sam/Android/Sdk
export ANDROID_ABI=armeabi-v7a

export ANT_HOME=/usr/share/ant
export PATH=${PATH}:${ANT_HOME}/bin

B:开始配置:
$source setenv_32bit
$cd platforms
$sh scripts/cmake_android_arm.sh

C: 开始编译:
$cd build_android_arm
$make 
或为了能看到更多编译细节,而使用:
$make VERBOSE=1

错误一:
会报错如下:
*************************************************************************
The "android" command is deprecated.
For manual SDK, AVD, and project management, please use Android Studio.
For command-line tools, use tools/bin/sdkmanager and tools/bin/avdmanager
*************************************************************************

因为新版本Android SDK中,Tools目录内,android命令已经废弃。 
从OpenCV 这端修改太麻烦。所以干脆把之前老版本的Android  SDK copy一份,并设置ANDROID_SDK指向这个目录:
export ANDROID_SDK=/home/sam/Android/android-sdk-linux

删除build_android_arm目录,重新来一次。


错误二:
/opt/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc -fPIC -fexceptions -frtti -fpic -Wno-psabi --sysroot=/opt/android-ndk-r14b/platforms/android-14/arch-arm -funwind-tables -finline-limit=64 -fsigned-char -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fdata-sections -ffunction-sections -Wa,--noexecstack    -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security  -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wno-narrowing -Wno-delete-non-virtual-dtor -fdiagnostics-show-option -fomit-frame-pointer -fvisibility=hidden -fvisibility-inlines-hidden -Wno-missing-declarations -mthumb -fomit-frame-pointer -fno-strict-aliasing -O3 -DNDEBUG  -DNDEBUG  -Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,-allow-shlib-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now  -shared -Wl,-soname, -o .build/libs/armeabi-v7a/libdetection_based_tracker.so CMakeFiles/detection_based_tracker.dir/jni/DetectionBasedTracker_jni.cpp.o  -L/home/sam/work/current/Research/OpenCV/opencv-3.1.0/platforms/build_android_arm/install/libs/armeabi-v7a -ldl -lm -llog ../../../lib/armeabi-v7a/libopencv_java3.so -ldl -lm -llog -ljnigraphics  "/opt/android-ndk-r14b/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/libgnustl_static.a" "/opt/android-ndk-r14b/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/libsupc++.a" -lm


/opt/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: fatal error: -soname: must take a non-empty argument

cmake3.2开始,就在NO_SONAME上与之前有所不同, 它的NO_SONAME property 缺省被Enable。但它会引发与
 

Linux Socket详解 <十一> socket收发缓冲区

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

socket在发送和接收时,根据不同的协议族和Type,会有不同类型的缓冲区。现研究如下。

1. TCP socket的接收和发送缓冲区
socket(AF_INET, SOCK_STREAM, 0);
每个TCP Socket在内核中都有一个发送缓冲区和一个接收缓冲区, TCP的全双工工作模式以及TCP的滑动窗口就是依赖这两个独立的buufer以及Buffer的填充状态。
对端发送过来数据,内核把数据缓存入接收缓冲区,应用程序一直没有调用read()读取的话,此数据会一直缓存在相应的socket的接收缓冲区。 若应用程序调用read(),会把接收缓冲区的数据读取用应用程序层的buffer.

应用程序调用write()或send()时,仅仅是把buffer中的数据copy到socket的发送缓冲区中。write()或send()返回时,data并不一定已经发送到对端了。

如果应用进程一直没有读取,buffer满了之后,发生的动作是:通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。

int rcvbuf = 0;
int sndbuf = 0;
socklen_t optlen;
int ret_opt = 0;
strcpy(buf, send_buf);

// 1. socket
iSocket_Server = socket(AF_INET, SOCK_STREAM, 0);
if(iSocket_Server == -1)
{
perror("socket()");
return -1;
}

// 1.4: Get socket send and receive buffer size
optlen = sizeof(sndbuf);
ret_opt = getsockopt(iSocket_Server, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen);
if(ret_opt == 0)
printf("\nSend buffer length: %d\n", sndbuf);

ret_opt = getsockopt(iSocket_Server, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &optlen);
if(ret_opt == 0)
printf("\nRecv buffer length: %d\n", rcvbuf);

获取的结果是:
Send Buffer length: 16384
Recv Buffer Length: 87380


但Sam疑惑的是,从TCP Socket一段发送,另一端不Read,为何竟然可以发送3579904byte???
这与Recv Buffer 大小并不相符。



2. UDP的接收缓冲区
每个UDP Socket都有一个接收缓冲区,没有发送缓冲区。有数据就直接发送,不管对方是否能够正确接收,也不管对端接收缓冲区是否已经满了。
UDP是没有流量控制的;快的发送者可以很容易地就淹没慢的接收者,导致接收方的UDP丢弃数据报。



 

Linux Socket详解<十二> Local Socket

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com



 

NDK升级遇到的一些问题汇总

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

之前每次升级NDK,均会遇到或大或小的问题,常见的问题有:NDK下的C库,C++库与Android设备内的库不匹配等。但这次从android-ndk-r10e 升级到android-ndk-r14b. 却遇到不少有特色的问题。记录如下:


1. 在Amlogic AArch64--S905X平台
Android版本:6.0.1
Kernel版本:3.14.29
这个平台虽然是64bit平台。但烧入的Image中,包含的库却是32bit.

使用NDK-r10e编译的C程序,C++程序,均可正常运行。
使用NDK-r14b编译的C程序。C++程序,32Bit下,clang/GCC编译的均正常运行。
使用NDK-r14b编译的C程序,C++程序, 64Bit下,均无法正常运行。(这也符合预期)


2. 在另一个Amlogic AArch64盒子--NEXBOX-A95X
Android版本:6.0.1
这个平台虽然是64bit平台。但烧入的Image中,包含的库却是32bit.

使用NDK-r10e编译的C程序,C++程序,均可正常运行。
使用NDK-r14b编译的C程序。C++程序,32Bit下,clang/GCC编译的均正常运行。
使用NDK-r14b编译的C程序,C++程序, 64Bit下,均无法正常运行。(这也符合预期)


3. Amlogic S905 32bit--中兴媚盒2:
使用NDK-r10e编译的C程序,C++程序,均可正常运行。
使用NDK-r14b编译的C程序。C++程序,32Bit下,clang/GCC编译的均正常运行。
使用NDK-r14b编译的C程序,C++程序, 64Bit下,均无法正常运行。(这也符合预期)


4. RK3288 32Bit:
Android版本:5.1.1
Kernel版本:3.10.0
使用NDK-r10e编译的C程序,C++程序,均可正常运行。
使用NDK-r14b编译的C程序。C++程序,32Bit下,clang/GCC编译的均正常运行。但只要是r14b编译的ELF(不管可执行程序还是动态库),均会在运行时报错如下:

WARNING: linker:   ./Test_NDK: unused DT Entry: type 0x6ffffffe arg 0xd3c
WARNING: linker:   ./Test_NDK: unused DT Entry: type 0x6fffffff arg 0x1
WARNING: linker:   libV4L2_utils.so: unused DT Entry: type ......
WARNING: linker:   libV4L2_utils.so:  unused DT Entry: type.....
WARNING: linker:   libgnustl_shared.so: unused DT Entry: type ......
WARNING: linker:   libgnustl_shared.so:  unused DT Entry: type.....

看到DT Entry, 感觉是ELF内的东西。可为何R14编译的东西,会在RK3288上报这个警告呢?


DT Entry: 用来在ELF文件头中描述Array Entry.
可执行程序和库会需要一些Dynamic Array Tags(DT). 但并不是所有的Entry是必需的,也有些已经不可用。 有哪些以及哪些DT Entry可用, 依赖于具体处理器和指令集。

所以:这个Warning的出现,原因是有DT Entry编译入了可执行程序或动态库,但Kernel却表示不支持。

导致的原因:
1. ARM Kernel交叉编译时,用到错误的Flags。 通常指不正确的处理器指令集。
2. ARM可执行程序或动态库使用了已经弃用的编译选项。

从Android 5.1(API 22)开始, Android Linker对VERNEED和VERNEEDNUM ELF dynamic section报警。
type 0x6ffffffe, type 0x6fffffff正是它俩。


察看那个API版本关心那些DT,可以看NDK/platfomrs/android-xx/arch-xxx/usr/include/linux/elf.h

察看某个可执行程序或动态库有哪些DT:
#readelf --dynamic  Test_NDK

可以看到,其中包含:
0x6ffffffe (VERNEED)  0xce8
0x6fffffff  (VERNEEDNUM) 1

就是他们导致警告。


 

Win7下Android开发环境安装

$
0
0
作者: Sam (甄峰)   sam_code@hotmail.com

之前Android App开发都是在Linux下,使用工具为Eclipse+ADT。 但Eclipse真是比较难用,且随着Google在2015年停止维护升级ADT。所以使用Android Studio也成了必由之路。 

这次选择在Windows平台开发APP,就选择使用Android Studio。

0.基础介绍:
Android Studio作为Google官方支持的Android开发工具,它依赖于JDK, Android SDK, NDK三种工具。

1:JDK安装:
1.1:下载地址:
JDK:http://www.oracle.com/technetwork/java/javase/downloads/jdk9-downloads-3848520.html
不同的Android版本对JDK有相应的要求。 如Android5.0默认使用jdk1.7编译。 Android7.0默认使用jdk1.8编译。
1.2: 
如果JDK为老版本,而SDK版本更新,则可能导致以下问题:
A. 创建项目后,浏览布局文件设计图时,报错:Android N requires the IDE to be running with Java 1.8 or later.
B. 项目编译失败,提示错误: com/android/dx/commmand/dexer/Main: unsupported major.minor version 52.0.
C: 运行App失败,提示错误:错哦马屁了SdkVersion‘android-24’ requires JDK 1.8 or later to compile.

1.3: 配置环境变量:
设置环境变量JAVA_HOME, CLASSPATH, PATH.




JAVA_HOME:
C:\Program Files\Java\jdk-9.0.4



CLASSPATH:
.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar



修改系统变量PATH:
在结尾处加:   ;%JAVA_HOME%\bin



验证:
java -version





2. Android SDK 安装
2.0: SDK 基础:
可以单独安装,也可以选择下载包含了SDK的Android Studio。比较推荐在Android Studio内安装。这样可以避免可能的兼容性问题和环境设置问题。
Android Studio附带安装SDK, 会安装在类似:C:\Users\Administrator\AppData\Local\Android\Sdk目录内。如果自己安装,也可以仿照此目录。

2.1:下载:
http://sdk.android-studio.org/

2.2: 设置环境变量:
不管自己安装还是Android Studio附带安装,都需要设置环境变量。
2.2.1: ANDROID_HOME:

C:\Users\Administrator\AppData\Local\Android\Sdk     



2.2.2: 添加内容到PATH:
;%ANDROID_HOME%\tools

2.2.3: SDK更新:
SDKManager.exe可以更新SDK。








3.  Android NDK 安装:
NDK是C/C++代码编译器。全称为:Native Development Kit。

3.1:下载NDK:
https://developer.android.google.cn/ndk/downloads/index.html
或:
http://tools.android-studio.org/


3.2:
把NDK放在类似:C:\Users\Administrator\AppData\Local\Android\android-ndk-r16b-windows-x86_64\android-ndk-r16b
目录下。

3.3:设置环境变量:
NDK_ROOT:
C:\Users\Administrator\AppData\Local\Android\android-ndk-r16b-windows-x86_64\android-ndk-r16b

PATH后加入:
;%NDK_ROOT%



4. Android Stuido安装:
在http://sdk.android-studio.org/ , 下载带有SDK的Android Studio版本。
安装,可以看到,带有SDK的版本会有SDK安装选项:



4.3:确保Android Studio设置中,JDK, SDK, NDK均正确
File -〉Project Structure-〉SDK Location:
中可以看到SDK, JDK,NDK路径。也可以修改之。



5. 安装SVN工具:
之前在Eclipse上开发时,对它如何与SVN结合起来有点头痛,但一直没有深究。 Android Studio自带了 SVN插件。它与SVN软件配合而实现SVN功能。 

5.1: 安装TortoiseSVN:
安装时需要选中command line client tools. 让命令行下也可以执行svn命令。 

5.2: 在Android Studio中配置 TortoiseSVN的命令行 工具
File->Setting->Version Control ->Subversion->user command line client.
给出svn路径。






 

AndroidStudioApp工程结构

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

Android Studio的App工程结构, 目录结构与 Eclipse+ADT的有一些不同。现学习如下。

1. Project和Module:
Android Studio的在创建项目时,有两个层级。一个是Project, 相当于workspace. 另一个是module, 可以对应App. 
一个Project中可以有多个Module. 相当于在一个workspace内,创建多个项目。

1.1: 创建Project:
File -> New -> New Project.  则创建Project,这个Project内,同时还包含一个Module。

1.2: 创建Module:
File -> New -> New Module。它则会在当前Project内创建一个新的Module. 
同一个Project内可以有多个Module。


2. Android工程结构: 
先创建一个Project,再在这个Project内多创建一个Module。此时, Project内有两个Module。
在结构图中可以看到, 该Project有三个目录, 一个是app, 一个是新建的module--Test_Game, 第三个是 Gradle Scripts.

每个Module目录下, 又有三个目录: 
A:manifests: 包含一个xml文件----AndroidManifest.xml, 是APP运行的配置文件。 
B: java: 下面有三个包名,第一个是存放Module的 Java源码。 其它两个则是用来存放测试用代码。 
C: res: 此Module的资源文件。

Gradle Scripts目录: 
主要用来存放工程的编译配置文件。主要包括: 
build.gradle: 此文件包括两类, 针对Project的, 针对Module的。每个Project都会对应一个build.gradle, 每个module也对应一个。用来描述App的编译规则。
proguard-rules.pro:
gradle.properties: 配置编译工程的命令行参数。
settings.gradle: 配置那些内容一起编译。 include ':app' , ':game_test1' . 想编译哪些Module, 就可以加入其中。
local.properties: 项目本地配置。 比如SDK路径,NDK路径。 



3. 编译配置文件--build.gradle:
前面说过: build.gradle分两类, 针对Project和针对Module的。
我们通常只关心针对Module的编译配置文件。 

具体看内容: 
android条目下, 分别包括编译 SDK版本号。 buildTools版本号。 
buildTypes条目下: 指定是否开启混淆功能。 

dependencies:



4. AndroidManifest.xml:
与Eclipse+ADT类似。








 

AndroidStudio下SVN的使用

$
0
0
作者:  Sam (甄峰)  sam_code@hotmail.com

先前使用Eclipse+ADT开发Android App.对如何将代码做版本控制, 一直是一知半解的。 通常的做法就是在Linux下使用SVN工具, 如RapidSVN把整个目录存储起来。 这显然不是个好办法。 所以在转到 Android Studio后。 记录下如何使用SVN工具。 


1. SVN工具的安装和设置: 
Android Studio自带SVN插件, 它与SVN软件配合而实现SVN功能。 
1.1: SVN工具的安装: 
 安装TortoiseSVN:
安装时需要选中command line client tools. 让命令行下也可以执行svn命令。
1.2: 在Android Studio中配置 TortoiseSVN的命令行 工具
File->Setting->Version Control ->Subversion->user command line client.
给出svn路径。

Win7下Android开发环境安装





2. Android Studio设置忽略文件
File -> Setting ->Version Control -> Ignored Files.
这里可以选择添加忽略文件。


可以看到, 添加的忽略文件有三种方式: 
1. 直接指定忽略文件。 
2. 指定忽略的文件夹。 
3. 指定忽略的文件类型和规则。

我们把需要忽略的加入如下: 




3.创建SVN项目并上传内容: 
VCS->Import into Version Control->Import into Subversion–>Import into Subversion弹窗中,点击+ –>创建一个新的仓库,填写svn服务器路径,选择上传的项目(Project而不是单个Moudle)


此时, SVN仓库就建立好了。通过RapidSVN,可以看到新建了一个仓库。

4.SVN与本地项目关联
之前只是创建了SVN仓库。 并未和本地项目关联起来。想要关联起来, 则需要重新check out.
VSC -> Checkout from Version Control -> Subversion




选中仓库。就可以checkout了。






 

Android App的构建过程和工具

$
0
0
摘抄 : Sam (甄峰)  sam_code@hotmail.com

此Blog大量摘抄网络内容。谢谢各位研究者分享。

1.  Android APP的构建: 
不管用Eclipse+ADT还是 Android Studio, 创建APP的过程相当简单, Build, Run,或创建有签名的APK,只需鼠标点击Menu即可。 这是因为构建工具已经在后台做了大量工作。

例如: 大量资源文件, 如Layout中的控件,如何构建成一个个实体,Java代码如何被编译,最终如何添加签名,如何生成APK。 这都是构建工具的工作。

一个APP被构建出的过程相当复杂,请看下图: 

1. 资源文件,如Layout,Values等都被aapt编译,并生成对象,最终在R文件中被引用。
2.
3. JVM字节码再被 dex工具 转化为dalvik字节码 (dex文件)
4. .dex文件,资源文件和其它不被编译的文件(assets)被打包成APK。
5. 添加签名(临时/正式)到APK。




2. 早起的构建工具----Ant和Maven:
早期的构建工具有: Apache Ant和 Maven.
2.1:Apache Ant:
Ant 2000年发布,很快成Java项目最流行的构建工具。
它的优点有: 
简单,易学,不需要特殊准备就可以上手。
基于过程编程 ,使得构建非常灵活 
支持插件。

不足支持: 
XML作为脚本配置,若项目较大,XML文件会变得非常大。 

2.2: Apache Maven
Maven发布与2004年, 为了解决Ant造成的问题。
它也使用XML作为构建配置的文件格式。且提供了从网路自动下载依赖的能力。
但 XML会变得太大,以致难以维护的问题还继续存在。 


3. Android 新构建工具Gradle:
在反思前两者的问题后,提出了DST(Domain Special Language, 领域专用语言)的概念。目标是设计一套能够解决特定领域问题的语言。 Gradle就是例子。

2012年,Gradle发布, 它的构建脚本不再使用XML, 而是使用基于Groovy的DSL进行书写。比Ant和Maven的 XML更加清晰,简洁。它灵活而强大,且支持自动下载依赖包。

2013年,成为Android Studio的 默认构建工具。

Groovy语言很容易学习: 
Groovy 代码非常易读,如果你学习过 Java,那么学习 Groovy 的曲线不会陡峭。 
如果你想构建自己的任务和插件,那么对 Groovy 有更深层次的理解尤为重要。 
不过因为 Groovy 是基于 Java 虚拟机的,所以你完全可以用 Java 或者其他基于 Java 虚拟机的语言来编写你的自定义插件。


4. Gradle的关键概念: 
Gradle中有两个关键的概念: 项目和任务。(Project and Module)
每次构建,需要先构建一个Project. 而一个Project,拥有一个或多个Module。
Project拥有一个build.gradle脚本。 每个Module也拥有一个build.gradle脚本。





 

AndroidStuidoGradle初探

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com


从2013年开始, Google就选中Gladle作为Android Studio的构建工具。 我们使用Android Studio开发, 必须对如何使用Gradle有所了解。 

1. Android Studio 项目中的4类Gradle文件: 
1.1: 属于Project的Gradle文件: build.gradle:
指定了使用的代码仓库,声明了使用的Android Gradle插件版本,在这里边主要是可以对整个项目进行配置,这些配置适用于该项目下的所有Module


buildscript {
repositories {   //仓库 
jcenter()      ////代码托管库:设置之后可以在项目中轻松引用jcenter上的开源项目
maven {     //maven仓库 
url 'https://maven.google.com/'
name 'Google'
}
}

dependencies {

classpath 'com.android.tools.build:gradle:3.0.1'     //声明gradle插件

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
jcenter()
google()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}


1.2: 各Module的build.gradle文件:
对于指定的Module进行具体的配置。主要分为三大块:apply plugin(声明了Gradle引入的插件),android(描述了该Android Module在构建过程中的配置参数等信息),dependencies(描述了构建过程中所有依赖的库)


apply plugin: 'com.android.application'

android {
compileSdkVersion 24    //编译版本。如果此处写24, 则SDK中必须下载了SDK 24
buildToolsVersion "27.0.3"   //编译工具版本。 需要下载对应版本 build-tools
defaultConfig {  
applicationId "com.zienon.gamemodsdk1"  //包名 
minSdkVersion 15      //最小版本号 
targetSdkVersion 24    //目标版本 
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false   //是否混淆 
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
testCompile 'junit:junit:4.12'
}


1.3. local.properties:
SDK和NDK的路径


1.4:settings.gradle:

include ':app', ':testsdk'
选择哪些Module被编译。

 

AndroidStuido使用记录

$
0
0
作者: Sam (甄峰)   sam_code@hotmail.com

在Android Studio使用中,常会遇到这样那样的问题。 有些与SDK版本有关, 有些与Build-tools版本有关, 还有些和Gradle或Gradle插件版本有关。 现把常见的问题记录如下: 

1: Gradle版本和Gradle插件版本: 
Error:(1, 1) A problem occurred evaluating project ':app'.
> Failed to apply plugin [id 'com.android.application']
   > Minimum supported Gradle version is 4.1. Current version is 2.14.1. If using the gradle wrapper, try editing the distributionUrl in E:\work\current\Android_Porject\EX07_151\gradle\wrapper\gradle-wrapper.properties to gradle-4.1-all.zip

要搞清Gradle版本问题,首先要知道一个概念,Gradle版本和Gradle插件版本。 
Android Stuido的Gradle插件版本和Gradle版本有个对应关系。若两者不匹配,就会出现以上问题。

1.0: Gradle:
Gradle是Android的构建工具。负责处理项目依赖,编译,打包,签名等操作。
它通过维护一个build.gradle的脚本对项目进行配置,再更具这个脚本对项目进行构建。

1.0.1:如何查看更新Gradle版本: 
查看和更新Gradle, 有两种方式: 
A: File -> Project Structure -> Project. 来指定Gradle版本。


B: 在gradle/wrapper/gradle-wrapper.properties中编辑 Gradle的引用地址。

#Thu Mar 29 18:21:21 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip


1.1:Gradle插件(Android Plugin for Gradle):
从名字上来说, 它是个Android插件,让Gradle可以运行。

1.1.1: 查看和更新Gradle插件: 
同样有两种方法: 
A: File -> Project Structure -> Project. 来指定Gradle版本。


B: Project的build.gradle中查看和修改: 

buildscript {

repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'


// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}


1.2:Gradle版本和Gradle插件版本的对应关系: 

Plugin version Required Gradle version
1.0.0 - 1.1.3 2.2.1 - 2.3
1.2.0 - 1.3.1 2.2.1 - 2.9
1.5.0 2.2.1 - 2.13
2.0.0 - 2.1.2 2.10 - 2.13
2.1.3 - 2.2.3 2.14.1+
2.3.0+ 3.3+
3.0.0+ 4.1+
3.1.0+ 4.4+

现在回到原始错误处。
 plugin [id 'com.android.application'] 插件的版本需要的最低Gradle是 Gradle version is 4.1. 但当前的Gradle版本却是Current version is 2.14.1。 所以建议我们修改gradle-wrapper.properties , 把内容变化为: gradle-4.1-all.zip
两种方法都可以看到问题所在。 









 
Viewing all 158 articles
Browse latest View live