android

Android Studio中项目NDK原生部分整合方式

UPDATE 2016.11.14:
目前的新版Android Studio 2.2已经可以完美支持NDK原生代码整合,通过cmake以及lldb实现c/c++代码调试,并且支持代码补全等功能!

自从Android Studio出现以后,我就很少再使用Eclipse+ADT的组合做Android开发了,更快的反应速度和更人性化的操作方式以及智能感知方面等等的优势,确实体现出了Google最初宣传Android Studio时的大部分特点,不过这些种种优势目前还只是体现在Java应用开发部分,而对于需要用到C/C++的Android NDK开发时,目前还没有很好的支持,当然,参考目前Android Studio的版本迭代速度来看,这应该也只是时间问题,当初ADT刚出的时候也是问题多多,包括后来的CDT+NDK支持,最初也只是支持原生代码的编译生成so,过了很久很久的某次update才加入了原生代码的可视化调试功能(当时也是历尽万难才测试成功的,还只是很简单的混合ndk项目…)。

最近看到了ndk又更新到了r10b版本,而且又据说新版的Android Studio中已经加入了一些ndk支持,于是正好一次测试一下(Android Studio beta 0.8.14, android-ndk32-r10b-windows-x86_64):

Continue reading…

使用distcc分布式编译加速Android NDK原生项目编译生成

随着项目规模的增大,源代码文件增多,结构越来越复杂,导致项目编译链接速度变慢是一件让人非常头痛的事!

在Windows上我们用Visual Studio可以使用IncrediBuild (http://www.incredibuild.com/) 这个非常好用的分布式编译工具,配合其自带的VS Add-In可以很方便的将大型项目的编译工作负担分布到网络上的其它机器完成,极大的缩短了项目编译时间,提高工作效率!

不过遗憾的是IncrediBuild目前只支持Windows系统和VS等一些编译环境,对于Android, iOS等交叉编译的移动平台开发环境就无能为力了。

其实对于linux系OS上还是有可用的分布式编译解决方案的,就是接下来我要说的这个distcc,项目介绍请猛击这里:https://code.google.com/p/distcc/

Continue reading…

Android百度地图SDK文字覆盖物的换行和旋转中心点问题

百度地图的Android SDK中支持在地图上添加各种覆盖物,其中包括文字覆盖物TextOptions,但目前版本4.1.0中此功能不支持文字换行,且不可设置文字的中心点,导致如果想要和其它覆盖物混合使用时,如在图标上显示一些文字时,效果很不好,由于只能通过对文字覆盖物的经纬度坐标添加一定的偏移来实现,例如下面这样:

                        // 定位坐标偏移
                        point = new LatLng(lat+0.0001, lng);
                        OverlayOptions textOption = new TextOptions()
                                .bgColor(0xAAFFFF00)
                                .fontSize(24)
                                .fontColor(0xFFFF00FF)
                                .text("test "+formatter.format(date))
                                .position(point);
                        // 在地图上添加该文字对象并显示
                        mBaiduMap.addOverlay(textOption);

Continue reading…

百度鹰眼SDK Android版后台服务的重绑定问题

Android版百度鹰眼SDK(测试版本2.1.15)在开启定位追踪时会开启com.baidu.trace.LBSTraceService的服务来完成后台的定位和上传数据功能,此时如果应用主Activity退出(用户自行关闭,或者被系统kill等情况)时,则需要在重启时检测是否已经开启了追踪服务并可以正确停止服务。按照官方文档的说明,这种情况下应该先通过startTrace()重新进行后台服务的绑定,可以收到“onTraceCallback: 10006, 服务已开启”的结果回调,但我的实际测试结果则是,后台服务运行的情况下,应用重启startTrace()不会收到任何回调!同时又做了几种其它情况下的服务开启关闭测试,结果如下:
在应用不退出重启的情况下,不管是用同样的Trace对象,还是每次都创建同样参数的新Trace对象,都可以顺利连续开启、关闭追踪服务。而在重启应用的状态下,检测到服务正在运行后,用新创建的同样参数的Trace对象尝试startTrace时会出现收不到任何回调的情况,而如果先在应用管理器中手动停止后台服务再startTrace就没问题。
在应用重启的情况下,重新new一样参数的Trace对象,然后调用stopTrace,这样得到的回调结果是“onStopTraceFailed: 11002, 服务未开启”,但此时getRunningServices确实能够查到正在运行的后台服务。又试了通过stopService的方式直接请求停止com.baidu.trace.LBSTraceService服务,此时返回的是true,但getRunningServices依然可以检测到服务正在运行。
附上测试用的检测后台服务运行状态的方法:

    public boolean isTraceServiceRunning() {
        ActivityManager manager = (ActivityManager) getActivity().getSystemService(ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if ("com.baidu.trace.LBSTraceService".equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

最后,在联系了官方后,得到了问题的解决方法:
Continue reading…

对于Android NDK编译器ARM和Thumb模式的理解及Toolchain的切换clang编译器

以前在做Symbian的时候,曾经研究过ARM CPU的指令集问题,ARM处理器支持两套指令集,即ARM和Thumb。ARM为32位指令集而Thumb为16位指令集,理论上32位可以提供更快的执行速度但会生成更大的二进制执行文件,而16位的Thumb则恰恰相反,省地儿但慢,这也正是体现出了ARM对于嵌入式设备的专业性。对于我这种牺牲一切换速度的理念来说,当时就留下了ARM就比Thumb快的印象,以致于现在在做Android NDK原生开发时,也是优先用ARM指令集。(这个可以通过在Android.mk中加入LOCAL_ARM_MODE := arm控制,默认情况下NDK使用Thumb指令集)

但是最近在Xcode编译iOS项目时,注意到同为ARM处理器的苹果设备,使用的是Thumb指令集,而且好像还是某种新版本的Thumb指令集,小搜索了一下看到有人说这种armv7引入的叫做Thumb-2的指令集要比arm指令集更好!于是又重新搜索更新了一下大脑知识库…

Continue reading…

Android应用图标修改后真机显示不更新的问题及mipmap图标

问题大致就如标题描述的那样,应用图标修改后重新打包安装到设备上时并没有变化,当然,前提是已经排除了人为因素导致的res内图标文件替错等原因。许久以前,在Android的原始时期,1.6、2.2时代时,就曾经在HTC的Sense UI上遇到过类似问题,当时也没太在意,现在在OnePlus One上(CM12s系统)又遇到了同样的问题,决定彻查一下原因。
百度下发现MIUI等也有类似的问题,基本确定是Launcher对应用图标建立了缓存,最直接的破除缓存的方法就是修改应用的Package Name,换包名后重装图标就会显示正确,明显就是没有缓存的特征!然而,应用发布过后一般是不会更换包名的,所以这个方法实际应用意义不大,仅仅是确认了这个图标缓存的机制。
这之后又查到了一些解决方法,如删除 /data/system/customized_icons 路径下的响应图标(这个需要root,且在5.0上没有这个路径,估计是Pre Lollipop用的),再如杀掉Launcher的进程,强制其重启刷新缓存(这个貌似不科学,因为重启Launcher的话应该和重启系统性质是一样的,但是我试过重启机器后图标依然没有刷新,再有就是CM上也没找到明显的Launcher进程,只有个systemui看起来比较像,不过也不敢强制结束,怕玩坏啊,哈哈!),这之后又自己尝试了下别的可能作为缓存key的要素,如改VersionCode,改VersionName,同时改VersionCode和VersionName,改res下的图标文件名等,均无效!
Continue reading…

iOS Android平台下的wchar_t默认size问题

很久以前曾经被wchar的问题在iOS和Android上被坑过,这次是在参研一份有年头的代码时又遇到了宽字符的问题,当然,也是和wchar有关系的,就是这个wchar在各个系统平台下的sizeof问题,关键的是一段UTF-8转UTF-16的代码:

size_t Utf8ToUtf16(const char* src_, wchar_t* dest_, size_t destlen_, size_t srclen_ /*= 0*/) 
{
	if (srclen_ == 0)
		srclen_ = _utf_length(src_);
	size_t destcapacity = destlen_;
	for (size_t idx = 0; ((idx < srclen_) && (destcapacity > 0));)
	{
		wchar_t	cp;
		unsigned char	cu = src_[idx++];
		if (cu < 0x80)
			cp = (wchar_t)(cu);
		else if (cu < 0xE0)
		{
			cp = ((cu & 0x1F) << 6);
			cp |= (src_[idx++] & 0x3F);
		}
		else if (cu < 0xF0)
		{
			cp = ((cu & 0x0F) << 12);
			cp |= ((src_[idx++] & 0x3F) << 6);
			cp |= (src_[idx++] & 0x3F);
		}
		else
		{
			cp = L'?';
		}
		*dest_++ = cp;
		--destcapacity;
	}
	return destlen_ - destcapacity;
}

这段代码在win下可以正常将utf-8的char*转换为utf-16的char*,但在Android, iOS下却不能得到和win下一样的转换结果,刚发现这个问题时,以为又是当年遇到的wchar坑,宽字符函数不支持之类的,但是仔细看了下并没有用到什么字符串函数,转换部分也是自己实现的,最后在各平台调试器的帮助下找到了问题:
Continue reading…

Cocos2d-x 3.6中的registerScriptKeypadHandler在Android真机上无法响应back键的问题

Cocos2d-x 3.6中使用Lua脚本作为主要开发语言,基于新的mvc框架,根据查到的响应安卓真机设备的返回按键back的方法,registerScriptKeypadHandler为Node下的注册按键事件侦听方法,新的框架中对此还进行了一次封装,在LayerEx.lua中的onKeypad实现,完成后的按键侦听代码如下:

function MyView:onKeypad(event)  
    if event == "backClicked" then
        -- back clicked!
    end
end
-- ...
function MyView:onCreate()
    display.newLayer()
        :onTouch(handler(self, self.onTouch))
        :onKeypad(handler(self, self.onKeypad))
        :addTo(self)
end

在Windows模拟器上测试时可以看到键盘上的任意键按下时都会触发这个回调函数,但是参数均为nil,读了一下源码发现在CCLuaEngine.cpp中的回调原生代码实现如下:
Continue reading…

Android Studio创建Xposed模块项目时BridgeApi的正确添加方式

使用Android Studio创建的空项目作为Xposed Module App,对于Api Jar包的引用方式,一开始是按照傻瓜式Jar Lib的处理方式,复制XposedBridgeApi-54.jar到app/lib中,然后直接右键Add As Library,也就是在build.gradle中生成了

compile files(‘lib/XposedBridgeApi-54.jar’)

这样的代码,结果写完IXposedHookLoadPackage实现类,加入assets/xposed_init,修改manifest中的meta后打包安装,Xposed Installer中也顺利检测出了新安装的模块,开启后重启系统,再看Log中出现了:

java.lang.IllegalAccessError class ref in preverified class resolved to unexpected implementation

这样的异常提示,结果当然是hook的代码也没有正确执行,研究后发现原来是jar包的引入方式不对,不能以compile方式加入,而应以provided方式,具体如下:
Continue reading…

Android中ObjectAnimator为Activity、Fragment设置过渡动画效果的方法

在iOS应用开发过程中,视图切换时的过渡动画是一个不可缺少的部分,简单的在Storyboard中托几个VC后连接上segue就可以实现,并可以选择几种如push,popover之类的动画效果,复杂的可以通过编码实现自定义的酷炫过渡动画效果(Github上有许多开源项目可以参考)。

最近一直在参研Android L的UI新特性,看到了更多注重UX的设计理解(当然也包括许多酷炫的效果,如OverScroll的新EdgeEffect、大部分控件的触摸效果,Reveal Effect等),其实从4.0 ICS开始,Android UI部分就有了很大的改进,当然也包括本篇要记录的过渡动画效果。4.0之前的UI动画主要是以Animation框架实现的,而4.0后加入了新的ObjectAnimator框架(貌似是3.0就有了,不过3.x是在没有存在感…),可以提供更多的动画控制从而实现更多的动画效果,这里记录下ObjectAnimator XML动画资源用于Activity和Fragment切换过渡动画的基本方法。

Continue reading…