Android下NDK开发的动态库(.so,shared library)增加版本号信息

在Android下面开发,免不了要涉及到C/C++层的开发,这就会涉及到崩溃异常的处理问题。

随着程序的不断升级,更新,会出现多个版本的动态库同时在线上共存的问题,一旦出现崩溃日志,往往不能方便的知道到底是哪个版本出现的崩溃。

传统的Linux,可以通过编译时候指定版本号来处理,最后生成如“libc.so.6”这种形式的文件名,我们可以根据文件名来获得相应的版本信息。遗憾的是,这种命名方式,在Android上面是不支持的

目前的需求主要有三点:

  1. 不依赖文件名,查询到版本号

    版本号写在文件名中,是一个比较方便的方式,但是带来的问题却是,靠不住!文件名可以随意更改,往往传来传去,文件名中的信息就改得面目全非了。

  2. logcat的崩溃日志中能得到版本号

    系统自带的logcat会在进程崩溃的时候,打印出崩溃栈,但是信息非常的精简,只有当前的线程回退栈帧信息(backtrace)以及几个关键寄存器信息,往往不能准确提供有足够的信息。而如果想在客户的设备上面,拿到完整的core-dump信息,只能是呵呵一下了!

  3. C/C++层的版本号变动,不要改动JAVA层的代码

    一方面,如果我们把版本号写在动态库的名字里面,这样会造成每次动态库的升级,JAVA的调用代码都需要变动,小团队还好,大团队,完全不可想象。另一方面,如果是系统框架层的开发,更加悲催,一个文件名的改动,影响到一片,当然,软链接也是个不错的选择,但是这样,常用的APK开发又要折腾一番,免不了一堆的抱怨。

针对上面的需求,我们逐个来提供解决方案:

  • 不依赖文件名,查询到版本号

在任意的C/C++文件中增加如下代码

在Android.mk文件中增加

编译生成的".so"文件使用如下命令即可查询版本号信息:

解释:
上面的代码的目的,是要求GCC在一个名为".SO_VERSION"的段内,记录我们的版本号信息。“unused”属性用于告诉GCC,不要在编译的时候警告这个变量没有被任何代码引用过。
注意事项:
在定义变量"Version"的时候,不要使用"volatile"来修饰。这个关键字影响到了最后生成的段的"PROGBITS"标记位置,这个标记表明了最后加载到内存中的数据是否可修改(我们当然希望这个位置不可修改,如果可写,可能由于越界导致版本号的不准确)。

没有使用"volatile"修饰

使用"volatile"修饰

注意两者的不同,一个属性是"A",一个属性是"WA"。

  • logcat的崩溃日志中能得到版本号,并且C/C++层的版本号变动,不要改动JAVA层的代码

目前对于这个问题的解决方法,是设置代理So。具体操作方式如下(假定我们生成的".so"项目LOCAL_MODULE:=So):

1.修改原来项目中的"JNI_OnLoad","JNI_OnUnLoad"函数,重新命名为 "So_JNI_OnLoad","So_JNI_OnUnLoad" 其他代码不变,并且在"So-jni.h"中对这两个函数进行声明。

2.所有的JNI方法都通过 "JavaVM->RegisterNatives" 方法进行动态注册。

3.建立SoStub-jni.cpp,代码如下:

4.原工程的"LOCAL_MODULE"修改为"LOCAL_MODULE:=So_1_0_3"(版本号根据实际情况调整即可

5.修改Android.mk,增加如下内容

6.修改JAVA层的调用代码

为:

解释:

由于logcat打印的崩溃栈,信息极少,因此我们只能采取这种折中的办法,这样设置之后,崩溃栈中会打印出"libSo_1_0_3.so"这样的字样,我们就可以知道版本号了。

Android Studio(JAVA) 编译警告:使用了未经检查或不安全的操作

在编译Android Studio(JAVA)程序时发生了如下的警告:

使用了未经检查或不安全的操作
要了解详细信息,请使用 "-Xlint:unchecked" 重新编译。

  • 如何设置Android Stuido开启 "-Xlint:unchecked"

修改build.gradle

增加

修改后的如下:

  • 警告信息的处理例子

包含-Xlint:unchecked警告的代码

消除警告后的代码如下:

同样的方法适用于"-Xlint:deprecation"。

svnrdump dump 实现 SVN 库的远程导出

svnrdump dump 命令必须 在 SVN 1.7版本以上提供的用于远程dump SVN库的命令.

以导出libyuv的svn库为例:

可以在这里下载已经DUMP完成之后的版本。目前的版本号是1444。

恢复DUMP文件到Subversion工程,请参考 Could not open the requested SVN filesystem

Debian和OpenMediaVault在命令行下设置更新源

很多时候我们比较纠结的问题是,“该把哪个Debian镜像发布站点加入source.list文件?”。

Ubuntu的图形界面中有一个测试工具,命令行下面的Debian也有一个现成的程序:netselect

安装netselect

不带参数运行它时会显示它的帮助信息。运行它时加上以空格分隔的镜像主机列表,它会返回一个分值和列表中的一个主机名。这个分值通过评估ping time和hopsnumber(一个网络请求报文到达目标主机所经过的转发主机的个数)得出,它与镜像站点预计下载速度成反比(数值越小越好)。返回的主机名是主机列表中得分最低的那个(查看列表中所以主机的得分情况可使用-vv选项)。看出下的例子:

它表示,在netselect后列出的所有主机中,http://mirrors.163.com/debian/是下载速度最快的主机,其得分为5。

注意,最近163的服务器不知道发生了何种故障,导致各种更新失败,尽管测试的结果是163更快,但是我们建议还是使用阿里云的服务器。

把netselect找到的连接速度最快的镜像站点手工加入/etc/apt/sources.list文件.

最新版本的netselect软件包包含了netselect-apt脚本,它使上述操作自动完成。只需将发布目录树做为参数(默认为stable)输入,sources.list文件就会生成速度最快的main和non-US镜像站点列表,并保存在当前目录下

对于OpenMediaVault用户还是手工修改配置文件好了,主要是上面的工具生成的比较简略

Ubuntu 12.04 + Apache2.2.22搭建SPDY服务器

SPDY是Google开发的基于传输控制协议(TCP)的应用层协议,该协议规定在一个SPDY连接内可以有无限个并行请求,服务器可以主动向客户端发起通信向客户端推送数据,通过请求优化、预加载、压缩HTTP 来达到加速的目的。

对用记而言,SPDY是基于SSL加密,它可以让网络访问更安全,用户隐私更加得到保护。对站长而言,SPDY在降低连接数目的同时,还使服务器上每个客户端占用的资源减少,从释放出更多内存和CPU ,让网站的浏览速度提升不少。

SPDY协议已经被Chrome、Firefox、Opera、IE 11以上支持,用户在访问使用SPDY协议加载的网站几乎感觉不到与普通的Https页面访问有何不同,而SPDY带来的页面加载速度提升和服务器性能优化确是有十分重要意义的。

具体的操作步骤如下:

  • 启用Apache2的HTTPS支持

参考 UBUNTU 12.04 下 APACHE 2.2.22 开启 HTTPS

  • 下载Apache2的mod_spdy模块

官网:https://developers.google.com/speed/spdy/mod_spdy/
由于众所周知的原因,本站提供下载(2015-11-6版本)
mod_spdy 64-bit .deb (Debian/Ubuntu)
mod_spdy 32-bit .deb (Debian/Ubuntu)

  • 安装mod_spdy模块(本站是64位系统)

  • 重启Apache2

  • 验证

目前验证貌似没有起作用啊!目前最新的chrome已经没办法进行验证了,主要是由于HTTP/2已经发布,Google放弃了spdy,转而支持HTTP/2,还是静待新版本的HTTP/2吧。

  • 卸载

  • 参考链接

Linux Mint + Apache2.2搭建SSL/HTTPS/SPDY服务器
https://developers.google.com/speed/spdy/mod_spdy/

WordPress使用WP-PostViews实现网站上显示文章的浏览量

WordPress的使用很方便,但是文章的点击浏览量默认是没有的,本文介绍用WP-PostViews实现网站上显示文章的浏览量的功能。效果如下图所示:WP-PostViews_Settings

  • 安装WP-PostViews插件

在插件界面中安装WP-PostViews插件,并且启用插件。

  • 修改主题文件(Twenty Fourteen)

修改content.php,找到如下代码:

在后面添加:

修改后的结果如下:

  • 修改主题文件(Twenty Fifteen)

修改content.php,找到如下代码:

在后面添加:

修改后的结果如下:

LMbench 3.0移植到Android并测试内存带宽

LMbench是个可移植的,用于评价系统综合性能的多平台开源benchmark,能够测试包括文档读写、内存操作、进程创建销毁开销、网络等性能。通过以下步骤操作,即可将LMbench移植到Android上。

  • 下载LMbench源码

下载地址http://sourceforge.net/projects/lmbench/
也可在本站下载

  • 修改LMbench代码

1.解压缩到指定的目录,保证最终的目录如下:

├── lmbench3/

│        ├── jni/

│            ├── doc/

│            ├── result/

│            ├── scripts/

│            ├── src/

│            ├── ACKNOWLEDGEMENTS

│            ├── CHANGES

│            ├── COPYING

│            ├── COPYING-2

│            ├── hbench-REBUTTAL

│            ├── Makefile

│            ├── README

2.修改“src/bench.h”的38行,40行,注释掉“#include <rpc/rpc.h>”,“#include <rpc/types.h>”,然后添加如下定义

3.添加根目录下面Android.mk,jni/目录下面内容如下:

4.添加根目录下面Android.mk,jni/src目录下面内容如下:

  • 编译LMbench代码

编译完成后的文件存放在“lmbench3\libs\armeabi”目录下面。

  • 测试内存带宽

更详细的命令参数,参考bw_mem

  • 参考链接
  1. andlmbench
  2. lmbench
  3. Performance Measurement on ARM

Windows下VirtualBox直接使用物理硬盘作虚拟机磁盘

目前VirtualBox只能用命令行来建立磁盘才可以使用物理硬盘。

我们假定VirtualBox安装在“D:\Program Files\Oracle\VirtualBox”这个目录下面,要在“D:\Users\VirtualBox VMs\Ubuntu\”目录下面生成文件,则执行如下命令:

\\.\PhysicalDrive1 表示机器上的第二块硬盘,\\.\PhysicalDrive0是第一块,\\.\PhysicalDrive2是第三块,以此类推。

在Windows 的磁盘管理中能看到硬盘的分区路径。如下图所示:ComputerManger

然后新建虚拟机,选择"使用已有的虚拟硬盘文件",找到刚刚创建的 Ubuntu.vmdk 即可。

对于Windows 8.1/10系统,以上的命令需要以管理员启动命令行的方式下启动并执行,否则会报告找不到磁盘。另外启动Virtual Box的时候,同样需要以管理员的身份运行,否则会出现VERR_ACCESS_DENIED错误,如下图所示:

VERR_ACCESS_DENIED

Android Studio 1.4主工程中使用gradle:1.3.0生成包含NDK的APK没有包含非".so"后缀的文件

Android Studio 1.4主工程中使用gradle:1.3.0,编译NDK,其中生成两个文件,一个是.so的动态链接库,另一个是可执行程序,没有扩展名,在最后生成的APK中没有包含非".so"后缀的文件。这个问题纠结了好久,最后追踪到了Android Studio对应的Gradle代码文件中。发现在

文件中有一个变量

这个变量决定了最后的打包时候的过滤条件。

具体的代码如下图所示:ndk_build_not_include
最后的解决方案,就是把编译之后的文件重新命名成为“.so”。

这边的build.gradle的配置如下:

(其他配置参考Android Studio 1.2 开发JNI工程