farewell 2014

前途是光明的,道路是曲折的 2014 发生了太多的事情,并不是平稳的一年,正如引用所说,今年可以概括为曲折与光明并存的一年。 工作 在广州找到的这家公司是一家创业型的公司,工作还是蛮有趣的,无奈由于公司和自身的原因,在年初就离开了公司。 在把私事做完后从新开始找工作。那时候大概是四到五月份。我发现在 51job 更新了简历后,差不多每天都有2到3个电话打过来说有兴趣给我面试机会,心想广州对于 Android 的人才还是很渴求的。除了被动接受面试邀请,也投了几家自己心仪的互联网公司。然后就是满满的面试日程了。 我所投的职位都给了我面试机会,感到有点幸运。对于 Android 的面试,一方面会问 JAVA 的熟悉程度,一方面会问 Android 的相关机制。当然了,作为技术面试,还会涉及到基础数据结构例如链表实现,多线程模型例如生产者和消费者,算法基础例如压缩算法的实现。 面试了两个星期,收获了不少 offer。除了一堆小公司,还有网易,YY,搜狐,翼支付等公司的。各公司给的薪金还可以,但是大部分都需要加班,这似乎是大环境。。最后经过综合考虑,选择了网易。 在网易工作非常愉快,除了工作,网易还有很多活动,例如每个月例行聚餐,公司对于节日的安排的小节目,不定期的培训,每天在健身室流汗。今年还去了一次珠海与澳门的旅游。 袋鼠国 在今年的第四季度,还在上班,接到老婆的一个电话,我们申请的袋鼠国的签证通过了,感觉是一个大大的 bonus 。接着我们就开始计划前往这个梦寐以求的国度了。虽然需要放弃国内的工作和离开家人一段时间,但是我是相信,前途还是光明的。 在去的路上。今年飞机事故蛮多的,幸好我们一切都顺利。 坐了十多个小时的飞机,踏入一个新的国度,开始,一切都是新奇。 过完年,还在适应期。开始学车和找工作了。 TODO 2015年一切都是未知,曲折,向上,要立足需要比之前更加努力。 下面是今年需要完成的事情,贴出来让各位监督。 考取 full license 找到专业工作 体重保持到 70kg

January 3, 2015

tmux

tmux 犹如 screen,用来在控制台里打开多个窗口,以达到减少打开控制台的数目和快速切换的目的。算是一个效率工具。 tmux 有很多快捷键,这些快捷键用来完成不同的操作,如能灵活运用,可以达到提高效率的目的。 Session Manager tmux里面的Session就像是一个工作台,每次打开tmux,其实就是打开一个 Session 。我们可以根据不同的使用场景来定义不同的 Session。例如我专门建立了一个叫做 blog 的 Session。用来做 blog 相关的工作(设置环境变量,打开文章,编译,上传等)。我主要用到如下命令来管理Session。 tmux new -s session_name 创建一个 Session 名字叫做 session_name tmux list-sessions (tmux ls) 列出当前有什么 Session 在后台 tmux attach -t session_name (tmux a -t session_name) 打开一个已经创建的叫做 session_name 的 Session。 tmux switch -t session_name 切换到session_name tmux detach (c-b d) 临时退出 Session。也就是退出了 tmux Windows 我们可以在 Session里面建立标签,也即是 Windows。每个 window 也有自己的名字。例如我在 blog 这个 Session 里面建立了两个 window 一个叫 serve 用来运行本地服务器,另一个叫 compile 用来编译 blog。我可以很方便的在两个 window 之间切换。其中相关的命令如下。...

December 1, 2014

why Android Studio use Gradle as its new Build System

Google 原来使用 Ant 作为它的构建系统。但在使用了 Android Studio 后却确定使用 Gradle。 新构建系统的要求 容易重建代码和资源 容易创建不同程序的变体,无论是要创建多个发布版本还是为同一个程序创建不同的属性 易于配置,扩展和定制构建流程 IDE集成 为什么是 Gradle gradle 是一个高级的构建系统,同时允许工具通过插件创建定制化构建逻辑。 下面是我们使用 Gradle 的一些原因: 使用 Domain Specific Language 来描述和控制构建逻辑 构建文件是基于 Groovy的,而且通过 DSL 支持装饰元素(例如 dependencies,configurations) 还可以使用代码来操作 DSL 元素来提供定制逻辑。 通过 Maven 和/或 Ivy 来管理依赖关系 非常灵活, 允许使用最佳实践但不强制使用唯一方式来完成事项。 插件可以提供其特定 DSL 和他们特定 的 API 给构建文件使用。 良好的 API 集成 版本要求 Gradle 1.10 或 1.11 或 1.12 + plugin 0.11.1 SDK 构建工具 19.0.0以上 基本工程 一个 Gradle 工程会在工程的根目录创建一个叫做 build.gradle 的文件 简单地构建文件 最简单的 Java 工程构建文件 build....

December 1, 2014

android 打印 stderr

mark android 默认的 stderr 没有重定向到 logcat ,如果想在 logcat 上打印本地程序的错误信息,可以输入下列命令。 adb shell stop adb shell setprop log.redirect-stdio true adb shell start

February 11, 2014

android-jni技术-回调

前面介绍了jni的基本概念和如何使用jni技术达到 Java 调用 C 的目的。 但是没有说 C 如何通过 jni 来调用 java 的方法,也就是如何实现回调。实现回调的作用很大,例如我们使用了 upnp 本地库,当库接收到消息便需要往 java 端传递。又例如使用了 C 实现了播放器,但是进度显示需要使用到 java。这些时候就需要用到回调了。 ##实现 先看看主要部分 :::java static void callback_handler(char *s) { int status; JNIEnv *env; bool isAttached = false; status = gJavaVM->GetEnv((void **) &env, JNI_VERSION_1_4); if(status < 0) { LOGE("callback_handler: failed to get JNI environment, " "assuming native thread"); status = gJavaVM->AttachCurrentThread(&env, NULL); if(status < 0) { LOGE("callback_handler: failed to attach " "current thread"); return; } isAttached = true; } /* Construct a Java string */ jstring js = env->NewStringUTF(s); jclass interfaceClass = env->GetObjectClass(gInterfaceObject); if(!...

February 8, 2014

bye 2013, hello 2014

It is the best of times.It is the worst of times 上面的话足够我概括这一年的经历了。 ##离家 之前的公司倒了,是留在本地工作装土豪,还是去外面当个屌丝?这个问题我犹豫了很久。最后还是选择了走出去,寻梦想,寻未来。虽然离家也不远。 ##工作 从一家创业公司到另一个创业公司,同样是做消费类电子,但是做的工作更加有挑战性了,这是比较满意的一点。 一直都想做些系统层和底层的工作愿望得到的实现。一样是围绕着 android 做工作,但是内容为 frameworks 和 linux kernel 了。 ##学习 学习围绕着两个主题进行,英语和计算机。 说说英语,这一年对于英语的学习热情一点也不高,虽然报了班,跑了几趟广外,但是这并不说明什么,最重要的是内功的修炼,是去记和背,去用英语思维思考,去听,说和写。很惭愧,没做好。 俗话说不x不知身体好,不赌不知时运高。同理,没做过编程都不知道要学习这么多东西。但是说到底,最核心的是思想,例如是否有面向对象的思想写出来的程序是不一样的。在我看来算法也算是思想的一种体现,简单的比如求 fibonacci 数列通项,用数组做和用递归做的时间差是几何级数的。 ##生活 买了部阅读神器 kindle 。阅读量倍增,而且涉及的范围也变广了。今年读了的书有 Android 系统源代码情景分析 人月神话 看见 动物农场 家 黄金时代 rework 嫌疑人x的献身 白夜行 写给大家看的设计书 今年最开心的一件事就是去旅行了,对于从没有出过国,坐过飞机的孩子真心是个突破(估计被很多人鄙视)。东南亚的小岛很漂亮,人们也很热情,同时看到很多华人在那边奋斗着。当然了,美食很多。 ##TODO 2014对于程序员真是充满了机会。只要潜心修炼,关注动态,勤于思考,敏捷执行,我们做的东西可以很多。 我要做的事也很多,要努力鞭策自己了。 英语 算法 linux编程 android 与 ios 以上是2014的基调,希望能买 macbook air 。一是移动需要,其次是程序员利器。 不管愿意不愿意,我们都要对 2013 说再见了。你好 2014。

January 1, 2014

ffmpeg教程二:屏幕显示

SDL and Video 显示图像的方法有很多,这里我们使用 SDL 。SDL 英文全称为 Simple Direct Layer 。是一个跨平台的多媒体库,也就是你可以在 windonws linuxe 和 mac 里面使用这个库。所谓的多媒体库,就是提供了图像显示,声音播放,和线程相关接口的库。在 linux 上安装这个库很简单,示例代码的 README 已经有写了。 SDL 提供了很多显示图片的方法,SDL显示图片是通过把数据显示在 YUV 层实现的。YUV 是显示原始数据的一种方法,类似于 RGB,通俗地说, Y 代表亮度系数, U 和 V 代表颜色系数。SDL的工作方式是把 YUV数据传进 YUV 层并显示。它接受4种 YUV 格式,但其中 YV12 是最快的。另一种格式叫 YUV420P 和 YV12 差不多,只是 U 和 V 调转了。420 的意思是每个样本的比例是 4:2:0 ,也就是每4个亮度分量共享一个颜色分量。这样可以节省带宽,而且人类对于颜色分量不太敏感,即使去掉几个也看不出差别。“P” 的意思是数据是 Y U V 在不同的数组中。ffmpeg 能够把图像转为 YUV420P, 其实很多视频已经使用这种格式存储图像,或者很容易就可以转为到这种格式。 现在如果想要显示图像,我们要把之前的代码中的 SaveFrame 函数替换掉。但是首先,我们先要知道怎么用 SDL 。 首先需要把库包含进来并初始化 SDL: :::c #include <SDL.h> #include <SDL_thread.h> if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); exit(1); } SDL_Init 告诉库我们先要用什么功能。SDL_GetError 显然是用来处理 debug 信息的函数。...

December 31, 2013

C++ 如何选用合适的容器

在 stackoverflow 里面掏到一张图,对选用容器有很好的指导作用,故贴在此。

December 17, 2013

rime输入法

在认识 rime 之前一直都在使用 ibus-pinyin 作为我的 linux 系统的输入法。而在 window 系统中用的是 某狗。 但是 某狗 好像变得越来越讨厌了。一会而弹出该换皮肤了,一会儿又弹出该换桌面背景了,最可恨的是还弹出什么某狗浏览器的广告。又在公司大战中发什么声明。只能说一句贵圈真乱。要不看在其输入法还比较好用的份上,早就把它删除了。 直到我找到了 rime ,这真是个神奇的输入法。支持 mac linux 和 windows 。不需要配置也可以用得很好,速度很快,准确率也很高。而且开源,没广告,可定制,简直是 geek 的理想输入法。我也忍不住为其背书。 若要下载,请点击前往 https://code.google.com/p/rimeime/ ###tips 在 linux 中的 gvim 调出 ibus 可能会出现 ibus 重新关闭导致输入法打不开的情况。这时可以点击 iBus 的 preferences ,把 Embed preedit text in application window 的勾去掉。

December 9, 2013

Android MVC Part7 State Pattern

这部分的内容是之前答应过之后再说的状态模式,这个模式在 TapController 用到。与 MVC 和 DAOs 不同的是,我不会把状态模式归为 android 程序架构必须实现的部分。然而,它的确非常有用。因为我在 TapController 中用它来处理消息,所以还是有必要说一下。 ##状态模式 在之前的系列中我没有提到它是怎样在 android 里工作的。但是在这部分,我们将会更深入一些来探讨它。状态模式是一个面向对象的模式,目的是可以动态切换对象的行为。还记得对象具有属性和行为吗?你会觉得这听起来像是策略模式?对,你说得没错。这里不同的地方就是模式的意图。状态模式是根据属性的不同而改变其行为的。客户端甚至不知道调用的对象已经发生转换。那么是怎么做到动态切换而接口不变的?我们需要把行为封装到对象内部,然后让他妈共享一套接口。接下来我们聊聊具体的例子,这个例子就是 Tap Counter 工程了。 我们要看的连个对象叫做 UnlockedState 和 LockedState。当 CounterVo 设置为被锁,这意味着我们不希望属性改变。例如,如果用户点击了增加按钮,如果状态是锁住得话,值将不会增加。但是如果不是锁住的状态,用户点击将会使值增加。这是基于 CounterVo.locked 的两种不同行为。 当 TapController.handleMessage 被触发,它就会把消息代理给其中一种状态。这里使用了 Controller.messageState 来确定用哪一种转台。让我们看看代码吧。 :::java @Override public boolean handleMessage(int what) { return messageState.handleMessage(what); } 这的确非常简单,但是 messageState 的状态是如何改变的呢? 两个状态之间是彼此知道对方的。当 UnLockedState 接到 MESSAGE_UPDATE_LOCK 这个消息时,它就会把 messageState 的引用改为 LockedState 。然后当 MESSAGE_UPDATE_LOCK 消息被 LockedState 处理时它会更细 messageState 的引用到 UnlockedState。我觉得我们看看代码会更好理解一些。 :::java package com.musselwhizzle.tapcounter.controllers; public class UnlockedState extends TapState { // ....

November 16, 2013