Nitro's

Jul 25, 2014 - Comments - tech life

Java的位运算、移位运算

上个月在做蓝牙通讯协议实现时数据操作基本处于Byte级别,所以用到了大量的位运算,恰巧看到这篇简单而又容易遗忘的基础点,所以翻译一下,顺便熟悉熟悉。 Java的位运算和移位运算非常强大,它可以在bit级别上使用int、long、short、byte以及boolean类型的数据,而且相比其他运算方式,位运算和移位运算的速度要快很多。但是很多Java程序员却对此了解不多,尤其时那些没有接触过C、C++语言的程序员。当然对于在学习Java之前已经了解了C、C++的程序员来说就没有那么陌生了,因为这些运算基本与C类似。 在许多面试题中也会经常出现这种运算题目。这个实例代码主要时为了快速的了解Java的位运算符之间的不同,以及如何使用他们,其次我们也会介绍一下无符号移位和有符号的移位运算。 基础 在介绍位运算和移位运算之前,你必须区分二进制、位、字节和位运算。良好的二进制运算基础对理解位运算将大有裨益。 1)二进制数据只会有两种0、1两种位,这也是为什么叫做二进制位的原因。 2)二进制的算术运算 0 + 0 = 0 1 + 0 = 1 1 + 1 = 10 3)取反运算:会将0改为1、1改为0,它用~来表示 4)OR运算:如果任一操作数中有1返回1;如果操作数均为0则返回0 5)AND运算:如果操作数均为1返回1,否则返回0 6)XOR运算:如果两个操作数相同则返回0;否则返回1,比如1XOR1返回0,1XOR0返回1,0XOR1返回1,0XOR0返回0 7)Java中的整数类型都是有符号的,其中最高位表示正负,高位为1表示负数,高位为0表示正数。 8)Java中的负数用2的补码来表示。2的补码=1的补码+1,1的补码全为0

Jun 29, 2014 - Comments - dev tech

Android 读取classpath路径下的文件流&证书问题

今天在读取HTTPS证书时遇到的一个问题,src文件夹下的cer证书读取始终为空。 经过对APK包反编译发现cer证书竟然一直没有打包进去,怎么可能?!之前一直都很正常的。最后把问题聚焦在了Android Studio使用的Gradle编译环境上,因为之前Eclipse下的编译环境都可以将src文件夹下的XML、CER等文件一并打包进去,但是Gradle却不是这么做的。 由于刚刚切换到Android Studio,对Gradle编译系统还不是特别熟悉,从Intellij工程配置到Gradle编译配置没有发现对src下*.class以外文件的特殊配置,无奈只能选择其他方法。 解决方法: 将cer证书文件放在assets文件夹下,assets文件夹会被编译系统打包到APK包内,并且处于Root Path级别。 InputStream caInput = this.getClass().getClassLoader().getResourceAsStream("assets/d.com.cer"); 这样就可以读取到证书文件。 可能还有其他方式读取类似这种文件,比如通过context.getRaw().open(“”),但是这样在独立模块中会引入Activity的context,不符合模块解耦的原则,对代码复用不友好。 = 之前看到很多使用HTTPClient与API进行交互时默认信任所有证书,这样开发确实方便,但是却会大开安全之门。 Android 证书的导入没有公开的API,需要自己手动导入,像12306那种自己做证书No Zuo No Die的方式直接让很多小白感觉那是个冒牌网站。 关于Android导入证书的教程,移步Google Help

Mar 22, 2014 - Comments - tech translate

POP3协议 中文翻译

翻译:N2Hsu 校对:Nii Ma 3-基本流程: 首先,服务器启动POP3服务监听TCP 100端口; 当客户机要使用这个服务器上的POP3服务时,与POP3服务器建立一个TCP连接; 连接建立后,POP3服务器发送一条问候语; 客户机和POP3服务器就可以进行命令和响应的交互,直到连接关闭或终止。 POP3协议中的命令是一个不区分大小的关键字,后面可能会有一个或多个参数。所有的命令都以一对换行符结尾。关键字和参数都是可打印的ASCII字符。关键字和参数之间、参数与参数之间都用一个空格相隔。关键字为三个或四个字符。每一个参数的长度最长为40个字符。 POP3协议的响应包含一个状态指示码、一个关键字,后面可能会有一些额外的信息。所有的响应都以一对换行符结尾。每个响应的长度最长为512个字符(包含最后的换行符)。当前有两种状态指示码:正确响应(”+OK”)、错误响应(”-ERR”)。服务器必须发送大写的”+OK”和”-ERR”。 某些命令的响应可能会有多行。这种情况遵循如下约定:首先发送第一行和一个换行符,此后要发送的其他行都以一对换行符结尾。当所有的响应行发送完成以后,一个八进制的终止符(ASCII046,字符“.”)加一对换行符的结尾行会被发送出去。如果多行响应中的任意一行开始于终止符,此行就是预填充入终止符的响应行。所以说,多行响应是以五个八进制字符(一对换行符+终止符+一对换行符)结束的。当客户端解释多行响应时需要判断此行是否以终止符开头,如果是并且紧随其后的不是换行符那么此行的第一个字符(终止符)会被剥离;如果是并且后面是换行符,表示POP服务响应完成,包含终止符+换行符的这一行则不会包含在多行响应行中。 POP3的会话期间会经历几个状态。 一旦TCP连接建立,POP3服务器发送了握手信息,会话进入AUTHORIZATION状态。在这个状态中,客户端对POP3服务器发起身份验证。 一旦客户端验证通过后,服务器获取与客户端邮件相关的资源,这时会话进入TRANSACTION状态。在这个状态中,客户端可以对POP3服务器进行相关的操作。 当客户端键入QUIT命令后,会话进入UPDATE状态。在这个状态中,POP3服务器会释放在TRANSACTION状态期间的相关资源,回复goodbye,TCP连接随之关闭。 服务器必须对不可识别的、未实现的、语法错误的命令给出错误的状态指示。服务器必须对处于不合法状态的会话给出错误的状态指示。因为客户端没有统一的方法来区分服务器是否实现某个可选命令或者服务器是否能够执行某个命令。 POP3服务器可能会包含一个非活动自动退出的计时器。计时器的周期最少为10分钟。在计时器一个周期内服务器接收到来自客户端的任意命令时,自动退出计时器应该重新计时。当计时器超时后,会话不会进入UPDATE状态,服务器不会删除消息、不会给予客户端任何响应的关闭TCP连接。 4-AUTHORIZATION 状态 一旦对客户端的TCP连接被打开,POP3服务器就会发送一条问候语,这是一条正确的响应。例子如下: +OK POP3 server ready 此时会话处于AUTHORIZATION状态。客户端和服务器进行身份验证。在本文档中描述了两种认证机制,USERPASS命令和APOP命令。其他的认证机制在[RFC1734]中会有描述。虽然没有一种认证机制是POP3服务器必须支持的,但是它需要最少支持一种认证机制。 一旦服务器通过了客户端发起的某种认证,客户端就有权访问相应的邮箱,此时服务器会给邮箱加上独占访问锁,防止会话在进入UPDATE状态之前邮件被修改或者移除。如果独占锁成功获取,POP3服务器就会给予客户端正确响应的状态指示码,会话进入TRANSACTION状态,此时没有邮件被标记或者删除。如果邮箱由于某些原因无法打开(比如无法获得独占锁、客户端被拒绝访问相应邮箱、邮箱无法被解析),POP3发送错误响应的状态指示码(如果获取到了独占锁但服务器返回了错误响应的状态指示码,服务器必须释放这个锁,拒绝这个命令请求)。返回错误响应的状态指示码后,服务器可能会关闭连接。如果服务器没有关闭TCP连接,客户端可以重新发起认证命令或者发起QUIT命令断开连接。 POP3服务器打开邮箱后,会为每一封邮件指定一个编号,用八进制标记每封邮件的大小。邮箱中的第一封编号为“1”,第二封为“2”,以此类推,第N封邮件编号为N。在POP3的命令和响应中,所有的邮件编号和邮件大小都用BASE10编码(十进制)。 下面是一个AUTHORIZATION状态时QUIT命令的介绍: QUIT 参数:无 限制:无 正确的响应: +OK 例子: C: QUIT S: +OK dewey POP3 server signing off 5-TRANSACTION状态 一旦客户端通过了身份认证,POP3服务器对邮箱成功加锁并且已经打开,会话进入TRANSACTION状态。客户端就可以重复的执行以下的命令。最终客户端发起QUIT命令,会话进入UPDATE状态。 以下是在TRANSACTION状态时的POP3命令: STAT 参数:无 限制:只能在TRANSACTION状态时使用 解释: POP3服务器用一行信息来表明邮箱的信息,作为此命令的正确响应。这一行信息称为邮箱的“信息统计”。 为了简单解析起见,所有的POP3服务器都必须使用固定的格式来表示邮件概述信息。正确的响应由“+OK”、一个空格符、邮箱的邮件数量、一个空格符、八进制表示的邮箱大小组成。在这个版本的协议中,邮箱大小后面的信息不是必须的,因此对这个命令响应的最小实现应该是以一对换行符作为响应行的结束。对此命令响应的高级实现可能会包含额外的信息。 注意: 当前协议中强烈不建议对此命令响应实现其他的额外信息。 注意:被标记为删除的邮件不会被计入邮件总数中。 可能的响应: +OK nn mm 例子: C: STAT S: +OK 2 320 LIST [msg]

Jan 19, 2014 - Comments - dev internet

我们到底遇到了什么困难

最近手头的工作不是特别忙,临近年关了正好也做做总结。2013年的主要工作是一个移动互联网项目,其间还有一些零散的工作,比如现场实施、项目调研需求分析等等。从目前的情况来看,这个移动互联网项目如果是百分制,或许它还在四十五分的路上… 2012年10月份XX银行与我们正式接触,提出要做一个移动互联网方向的项目。此时的移动互联网概念正在整个业界蔓延,各大银行纷纷开始布局移动互联网,网银客户端终于有了iOS、Android版,微信也开始崭露头角,尤其是移动互联网公司越来越高的估值让每个人的心中不免骚动,都想在这一大潮中掘得一桶金。前景确实很美好,但在拿到需求说明书之后,也开始陷入了深深的思考。我们公司的主要方向就是金融行业,所以从业务角度考略完全没有问题,但之前的项目基本都是运行在内网环境下而且用户量极小,这与互联网项目相比不仅仅是开发语言、平台的差异,而是思维的转变与架构设计重建的问题。开发人员上,公司的主要开发人员是WEB方向,Android平台开发我一个人负责,UI/UE半把手凑合,iOS平台基础为0。虽然有这些困难需要解决,但是项目最终是签下来了。 项目初期目标是先出Android版和管理平台,后期看使用情况再考虑iOS、Windows Phone。就这样从13年1月份做到今天,算下来整整一年时间,但这个项目的主体开发还在继续,完整性测试还没通过。现在回头看这个项目各种滋味,如果从资金上说,项目验收通过,没完成的算是后期开发;如果从产品可用性和用户角度说,它是一个半成品。就像《精益创业》中提起的一句话,在一个项目失败之后我们常常总结到,虽然项目失败了但积累了教训。不管是成功还是失败,总结教训,不要再犯同样的错误。 需求定义、技术协调问题。 项目一开始是这样分工的:我负责Android平台App的开发和API接口定义,WEB管理后台和API实现由项目经理A负责。在UI初稿定型后,我准备提起测试一个API通讯接口,A直接发给我一堆AXIS2的客户端JAR包,还有一系列客户端代码让我把它导入到Android中,顿时我就一身冷汗,这是要做什么?之前的架构设计讨论过要使用HTTP/HTTPS通讯,架构图上也标明了,况且支持HTTP协议的API使用轻量级WS中完全可以实现,业界也都有成熟的模式可以借鉴,为什么突然跑出来一堆JAR包?后来和A讨论了一下才明白,原来之前做WEB开发时就是用的AXIS2 WS,所以A想直接复用后端代码,然后把Andoid App和HTML前端做类比,听到这里,我就开始反驳,还是要按照之前定好的HTTP协议通讯最好,AXIS这种重量级的WS不适合开发移动应用,如果用WS就选择Rest-ful 这种轻量级的,完全满足我们的要求。讨论之下没有结果,只好找技术总监来定夺,最终是走了折衷方案,抛弃AXIS2不采用Rest-ful,所有接口数据从一个Servlet接入。虽然这不是一个完美的方案,但总让我面对MB级的JAR长舒了一口气。此时还处于项目的初期阶段,万幸的是我一早提出测试接口,否则后面的路就越走越远了。还是那句话,一切按照文档来,尤其是API接口和交互类的设计,一定要双方约定好交互方式、通讯方式,早沟通早定义。由于之前没接触过移动项目,所以一味的照搬技术经验,容易导致误入歧途。 源代码管理工具的使用。 之前公司内部采用CVS来管理源代码,但是内部使用起来仅仅发挥了代码保存的作用,而且账号体系不完善,开发人员共用一个账号,时常出现文件丢失、冲突无法解决的问题,所以从这个项目开始我部署上SVN源代码管理,每人分配一个账号,各自解决冲突、严格代码审查。在使用初期团队内部抵触较大,整体使用效果不佳,一些开发人员还是按照CVS的思维推卸自己删除文件的责任,导致内部有些小冲突。直到前几天,在项目经理的要求下,将最新的Android源代码和文档资料又迁移回CVS管理平台。事实证明SVN在我们团队下是失败了。团队开发人员对工具的依赖性不想切换工具(此事的另外一条例证,Eclipse现在已经到4.3,但WEB开发人员来停留在3.2),对代码的责任不够强都导致了SVN无法继续使用的结果,容易但使用CVS问题依旧还会出现;开发过程没有代码审查,也导致众多Bug重生的问题。 项目需求的变更。 这或许是每个开发人员最头疼的一件事,做好的功能还要再回炉重造,微博上的吐槽也是不计其数。其实在项目开发过程中需求的变更是比较正常的事,但为什么还是那么多人吐槽呢,这其中也有项目经理或者产品经理的问题。本身App在开发前期已经定好了五大功能,而且UI也设计完工,突然技术总监找我说,AA不做了,现在抓紧换上BB,过几天需要演示,然后又需要做UI又需要砍掉代码重新来过。回头想想AA功能新颖,实现不复杂,产品突出点强,完全可以与类似产品做差异化竞争,换上的BB与其他功能略微重复,给人一种转来转去的感觉。最后又重新实现BB,花费大概半个月的时间。 为什么总是提需求? 这几天项目上银行甲方又提出来不少需求,现在负责对接的同事开始抱怨“为什么总是提出这多需求?”他们的需求合不合理?我们到底应该以怎么的思维理解这件事?这都是我们需要考虑的问题,首先从商务角度考虑,甲方现在提出要求是合情合理的,因为我们签的是开发运维合同,属于长期技术支持型的项目,不断修改在所难免;其次我们没有合理的安排后期进度,导致需求来一个改一个,到最后就变成一锅粥,怎么改都不合适。没有合理的开发计划和更新进程导致项目处于一种无序的状态。再者做传统软件项目的思维一时半会儿无法适应互联网模式下的“小步快跑”、快速迭代也是一大致命因素。 团队人员管理。 由于公司今年项目比较多,有硬件项目需要现场实施,老的软件项目需要维护,导致团队内部开发队伍不稳定,经常出现某个模块写完之后没人再配合,转而交给另外一个人再继续开发的情况。这个问题到现在维护阶段还存在。 前几天找老总,聊了聊关于这个项目,关于公司的发展,个中滋味吧! 项目算是告一段落,但开发的路还在继续,不管是经验还是教训都是满满的一笔财富。思维或许是最难以转变的东西,这也时刻告诉自己抱有好奇心,敢于尝试与冒险,更要不断地读书学习。

Jan 16, 2014 - Comments - project

嘟噜(Dulu)

嘟噜是一款针对新浪微博定制的客户端 优化的微博时间线,更加注重微博的重要性,不论它来自你的好友还是某个草根,你都可以无障碍的浏览阅读; 界面简洁清新,保留最核心的功能,去除冗繁复杂的交互操作,只为阅读每一条有价值的微博; 一键直达,发微博就要快,文字、图片、位置、表情、@某死党 统统都能搞定; 根据网络状况优化图片加载,想看就看; 支持Android 4.0以上; 更新: 2014-01-16 2.7.7 适配Android 4.4 增加Google Map、百度地图支持 重新设计微博发布器 增加超链接内部导航 增加图片缓存机制 修复个人关注数问题 修复导致崩溃的BUG

Jan 9, 2014 - Comments - tech repost

优化String StringBuffer

这篇文章主要介绍了一下String、StringBuffer对象在初始化和字符串连接时的优化,很不错。 This topic illustrates the performance improvement techniques in String and StringBuffer with the following sections: Overview of String and StringBuffer Better way of creating Strings Optimization by interning Strings Optimization techniques when Concatenating Strings Optimization by initializing StringBuffer Key Points Overview of String and StringBuffer Immutable objects cannot be modified once they are created. Mutable objects can be modified after their creation. String objects are immutable where as StringBuffer objects are mutable.

Dec 31, 2013 - Comments - life

写在2013

2014年还有几个小时就要来了,赶在这最后的几个小时总结一下自己的2013。 上幼儿园小学时,生活无忧无虑,小伙伴们在一块就是玩,在教室里本是学习但开小差那也是常有的事情,不用刻意记下今天是不是周末,因为每一天都是轻松而欢乐的; 后来上了中学大学,时间渐渐变成了用分来计算,6:30准时起床,8点整第一节课,22:30准时熄灯,此时的生活是规律的,按照规则来作息起居,偶尔的卧下而谈也会止于彼此的困意而息; 两年前换了一种生活方式,没有了鸣号的起床声,没有了小伙伴们挤在厕所门口等着Previous君蹲号出来一脸不舒服的样子,没有了三块五的肉夹馍,没有了鸡蛋灌饼来一个的吆喝,一切都变了,某个线程执行时间用微秒来衡量,双11准时开抢用秒来计算,还有一些十分诡异的公司早一秒没迟到后一脚扣掉200块钱,此时的生活用秒来定义。 2013,满满的31536000秒,惊喜、悲伤、挑战。 4.18—遇见你 紫色呢子大衣,红色包包,有点害羞腼腆,以至于坐下来了还有点紧张,就这样让我认识了你。刚过年那会儿,自己特别得瑟地默念了一遍:今年我24岁了,本命年,神马恋爱婚姻与我无关,因为按照老家习俗本命年不能结婚,今年终于可以安安静静地过完这一年了,哈哈。如果不是遇见你,或许我的2013也就这样平淡的度过。你的出现,犹如帕隆藏布江,平静出湖浪波涛,时间让我遇见你。时间见证一个开始,有你,惊喜的2013。 5.28—此日启程 吃过午饭,敲开经理室的门,后面敞开的就是这段新的旅程。一个月,2166公里,6个人,我们一起走过川藏线。从11年买第一辆山地车,梦想清单就写着这样一项:骑行川藏线。3月份和老板商量时间安排、周末准备物品、搜集资料、不间断的骑行训练,这一切就像是换个时空,离开这座城市,离开熟悉的人,踏上未知的旅途。因为怕家人担心,到拉萨的最后一天老爸才得知我走川藏线去了。 我们来自五湖四海,鞠哥四川,铨哥广东,胡主席、袁哥来自湖北,立哥河南,因为一个共同的梦想走到一起,肩并肩走完这段旅程,谢谢一路有你们,特别感谢大广州的铨哥,能让我遇见你,撞大运不说还让你成功打破不搭车的记录,哈哈! 还是那句话,梦不只是想,我们都做到了!挑战2013,一个梦想落地,我们笑到了最后。 7.01—笑还是哭 今天是从松多到拉萨的最后一程,大家的兴奋自不必说,一个月的旅程最后一点当然值得我们好好珍惜,路上骑的不是特别快,还是按照我们原有规则8点之前到就可以。由于鞠哥一直是打头阵,所以铨哥、胡主席还有我,就一直慢悠悠的骑着,途中路过一大片油菜花时,我们停下来买了个西瓜吃着休息一下,这时姐姐打来的电话犹如惊天雷把我对拉萨的期待一冲而散:奶奶快不行了!?当时脑子懵了,临走前还是好好的,怎么就不行了?!不敢相信这到底是不是真的?!手机信号时有时无,手机一直拿在手里生怕错过任何一个电话,但事实就是事实,无法挽回也无法欺骗自己,5月1号成了我和奶奶的最后一面。2013的悲伤,愿奶奶在天堂休息好~ 2013,24岁,时间又画了一个圈圈,把你我圈在里面变成回忆。 2014,25岁,即将画点成弧,借Q上一句话,唯有努力。

Dec 19, 2013 - Comments - dev tech

Android CSS 渐变 阴影

CSS中线性渐变的方向可以通过角度或关键字来指定,渐变中间色可以叠加多个。 语法: linear-gradient([[<angle> | to <side-or-corner> ],]?<color-stop>[,<color-stop>]+) 角度值表示:从0deg到360deg,0表示从下向上,90表示从左到右,顺时针方向旋转; 关键字表示:“to top”表示从下向上,“to right”表示从左向右; 第三个参数为起始颜色,后面第N个参数依次指定后续渐变颜色。 Android中线性渐变的方向只能通过android:angle属性来指定角度,渐变色最多为三个。 <gradient android:angle="0" android:endColor="#FEFEFE" android:centerColor="#435345" android:startColor="#EEEEEE" /> 其中Android线性渐变的角度与CSS的方向并不一致,0表示从左向右,90表示从下向上,逆时针方向旋转。

Dec 18, 2013 - Comments - dev tech

Android 读取媒体库文件 4.4

Nexus 4更新Android 4.4之后Doplus无法发送图片微博,今晚修复了这个问题,记录一下。 获取图片资源是通过Intent来调用媒体库。示例如下: Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivityForResult(intent, 0x01); Android4.4之前会默认调用Galley Provider选择图片,对应返回的URI是 content://media/external/images/media/65360**** Android4.4则会调用Document Provider选择图片,在Document Provider整合了最近查看、内部存储器、SD卡、下载内容等本地资源,以及第三方的图片资源读取Provider比如Galley、Photos(Google+独立出来的图片应用)、Drive、Dropbox、Box、SkyDrive等等。 本地资源通过Document Provider选择后返回的URI如下: content://com.android.providers.media.documents/document/image:65360 读取Document Provider的图片资源,需要做如下处理: String wholeID = DocumentsContract.getDocumentId(uri); //获得资源唯一ID String id = wholeID.split(":")[1]; //定义索引字段 String[] column = { MediaStore.Images.Media.DATA }; // String sel = MediaStore.Images.Media._ID + "=?"; Cursor cursor = getContentResolver(). query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null); int columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { //DATA字段就是本地资源的全路径 String filePath = cursor.

Dec 13, 2013 - Comments - dev tech

C# 调用动态链接库

C#调用动态链接库主要是通过DllImport来实现的. 在调用DLL的CS文件中引入using System.Runtime.InteropServices; 将DLL拷贝至工程目录bin下的Debug或者Release文件夹内; 声明调用函数,以打开磁卡读写器为例: /* 丛指定的端口打开磁卡读写机 */ [DllImport("HCE300_API.dll", EntryPoint = "HCE300_Open", CharSet = CharSet.Auto, SetLastError = true)] public static extern int init(int ComPort); DllImport 指定要动态调用的DLL位置名称 EntryPoint 指定DLL内部函数名 CharSet 说明内部数据返回编码 SetLastError 确定在函数返回前是否调用Win32的SetLastError 下面是对应于Dll函数的自定义函数声明,一定要保证参数列表一致。 如果再DllImport中指定ExactSpelling=true,函数名要与EntryPoint保持一致,指定为false,可以自定义函数名。 外部函数就可以直接通过init函数调用Dll内部的封装函数了。 注意: Dll函数的参数列表中如果有指针类型的参数,那么工程必须是非线程安全的。示例如下: byte[] data = new byte[301];//声明外部byte数组 fixed (byte* pData = data)//定义指针,指向外部数组,fixed 语句设置指向托管变量的指针 { byte* poiner = pData; int ret = SDK.read(poiner);//函数指针入口 string str = System.Text.Encoding.ASCII.GetString(data); }