Fork me on GitHub

Gradle的Properties 2014-07-23

问题背景

团队一起在开发一个Android项目,工程师有的使用Eclipse,有个使用Intellij IDEA,有的使用Android Studio。每个人安装的Android SDK build-tools可能都不一样,有的是19.0.3,有的是19.1.0,不同版本的build-tools对Gradle Plugin也有相应的要求,如19.0.3对应的是com.android.tools.build:gradle:0.10.+,19.1.0对应的是com.android.tools.build:gradle:0.12.+,下面是一个典型的build.gradle配置文件。

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.10.+'
    }
}

apply plugin: 'android-library'

android {
    compileSdkVersion 19
    buildToolsVersion 19.0.3

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
    }
}

Android异步编程 2014-06-29

Android的线程和内存模型

Android操作系统在boot后,会启动一个Zygote(受精卵)进程,Zygote进程负责创建大部分应用程序进程。Zygote进程启动加载核心程序库和数据结构到内存后会创建一个Dalvik虚拟机(DVM)进程--SystemServer,此进程会包含大部分的系统服务(包括管理Activity的服务ActivityManagerService),SystemServer初始化后,Zygote进程会侦听本地的socket端口, 等待进一步的指令。当新的app被启动时,Zygote会为这个app创建一个DVM—-直接fork出一个子进程,这种架构的好处是同时启动多个App时,多个App进程可以访问共享内存。

Android App的进程也是一个DVM,内部有许多线程在执行,比如,主UI线程(Main Thread),垃圾回收线程等。其中主UI线程负责执行我们写的应用代码。对于只做很少的I/O操作或耗时操作的App,单一线程开发模式问题不大,但是如果有大量IO或者CPU计算的任务,我们就必须在其他线程内完成了。

因为主UI线程需要根据硬件刷新率[^3]同步用户界面的重绘。手机应用体验流畅要求界面帧率[^3]达到每秒60,也就是说每16.67毫秒就需要重绘一帧,这意味着如果我们在主线程上执行的任务超过16毫秒,就会出现丢帧现象,也就是界面会开始变卡。。。

Android异步执行任务的方法有以下几种:

AsyncTask

AsyncTask是最常用的异步方法,功能结构设计的也很丰富,给使用者足够的控制,使用上主要是将异步执行的任务放在下面方法里。

提高Android开发效率的小贴士 2014-02-10

查看日志 adb logcat

下面命令将只显示错误日志,和所有Tag=mytag的调试日志,-C 会用不同颜色区分不同级别的日志,但只有Android 4.3以后才支持。

adb logcat [-C] *:E <mytag>:D

远程调试 adb over TCP

首先在手机或Pad上执行以下命令(要求root)

su
setprop service.adb.tcp.port 5555
stop adbd
start adbd

再执行下面命令则可以看到手机的网络地址

拷贝Android应用的数据 2013-11-27

有root权限

adb shell su -c cat /data/data/app.package.name/databases/application.sqlite | sed 's/\r$//' > application.sqlite

应用可调试的话

adb shell
run-as app.package.name \
cp /data/data/package.name/databases/application.sqlite /sdcard/
exit
adb pull /sdcard/application.sqlite ~/

使用备份方法

adb backup -f ~/data.ab -noapk app.package.name
dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -

在树莓派上使用Phantomjs自动登录微博 2013-07-21

使用过新浪开放平台的朋友都知道用户对小应用(用户数较少的)的授权Token很容易过期,自动续期要求授权过的用户在过期前重新打开授权页。如果你想实现一个自动备份自己微博的App,就不得每天(周)自己去访问授权页(想死的心都有了吧?)。这里介绍一种通过脚本自动登录微博获取最新oAuth token的方法(需要微博登录名和密码),合适自己玩。将脚本部署在树莓派上后,我再也不用每周都去登录一次授权页了,只是收到报警消息后(经常是帐号被冻结了)需要手动处理一下。

Phantomjs

Phantomjs 是一个开源的,没有界面可运行在命令行,跨平台,基于WebKit的全功能浏览器,可以用来做网站自动化测试。从源代码编译比较费时间,可以直接下载二进制版本,树莓派的版本在这里可下载。Phantomjs下载好了后就一个可执行文件,依赖非常少,我很喜欢这种方式。

代码

以下代码使用提供的微博用户名和密码登录,获得Token后还会打开微博首页看帐号是否被冻结了。

var page = require('webpage').create(),
    system = require('system'),
    fs = require('fs'),
    address;

var weibo_userid = system.args[1]
var weibo_passwd = system.args[2]

var startUrl = "https://api.weibo.com/oauth2/authorize?client_id=<your_app_key>&redirect_uri=<your_return_url>/&response_type=token";

var verify_weibo_freeze = false;

page.onResourceReceived = function (res,network) {
    if (res.stage == "end") {
        // console.log("\t<-" + res.url);
        if (res.url.indexOf("authorize?client_id")>0) {
            startUrl = res.url
        } 
        if (res.url.indexOf("?access_token")>0) {
            var pos1 = res.url.indexOf("access_token=")
            var pos2 = res.url.indexOf("&")
            var access_token = res.url.substring(pos1+"access_token=".length, pos2)
            console.log(weibo_userid + " login OK, access_token is: " + access_token)
            verify_weibo_freeze = true
        }
        if (verify_weibo_freeze && res.url != "http://weibo.com/" && res.url.indexOf("http://weibo.com/")>-1) {
            var pos1 = res.url.indexOf("/",8)
            var pos2 = res.url.indexOf("?")
            var weibo_name = res.url.substring(pos1+1,pos2)
            console.log(weibo_name+" status verified OK")
            phantom.exit();
        }
    }
};

page.onLoadFinished = function() {
    if (verify_weibo_freeze) {
        page.open("http://weibo.com/", function() {
            phantom.exit();
        })
    }
};

page.onConsoleMessage = function(msg) {
    console.log(msg);
};

page.open(startUrl, function(status) {
    if ( status === "success" ) {
        page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
            var offset = page.evaluate(function(a,b) {
                $("#userId").val(a)
                $("#passwd").val(b)
                if ($('.WB_btn_login').hasClass("formbtn_01")) {
                    // console.log("Found button!")
                    return $('.WB_btn_login').offset()
                }
                return undefined
            }, weibo_userid, weibo_passwd);
            page.sendEvent('click', offset.left + 1, offset.top + 1);
        });
    }
})

使用夏普GP2Y1010AU0F灰尘传感器检测空气质量 2013-07-21

夏普GP2Y1010AU0F灰尘传感器价格较便宜,能检测出室内空气中的灰尘和烟尘含量。另外还有韩国SYHITECH生产的DSM501A粉尘传感器也有类似功能。

检测原理

其原理如下图,传感器中心有个洞可以让空气自由流过,定向发射LED光,通过检测经过空气中灰尘折射过后的光线来判断灰尘的含量。

电路图

因为数据是通过pin 5的电压模拟信号输出的,而树莓派的引脚不支持模拟信号直接读取(需要增加数模转换芯片),所以先用Arduino来实验。

替换树莓派的U盘 2013-07-11

除了SD卡上的存储,树莓派还可以使用U盘来做存储,有时候我们可能需要替换已有的U盘为更大容量的。在Mac上可以采用下面的方法:

  1. 备份已有的U盘,把U盘从树莓派上拔下来插在Mac上,找出U盘对应的盘符(下例为/dev/disk2

    20:51:19 hugozhu-mac-mini ~ $ diskutil list
    /dev/disk0
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:      GUID_partition_scheme                        *500.1 GB   disk0
       1:                        EFI                         209.7 MB   disk0s1
       2:                  Apple_HFS Macintosh HD            499.2 GB   disk0s2
       3:                 Apple_Boot Recovery HD             650.0 MB   disk0s3
    /dev/disk2
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:     FDisk_partition_scheme                        *2.1 GB     disk2
    

    使用 dd 命令把U盘拷贝到raspberrypi.img

在Mac上使用Sublime 3写Go代码 2013-07-11

Sublime 是一个相当好用的文本编辑器,界面简洁,功能强大。最近Sublime 3 Beta 出来了, 体验了一下,发现启动速度比之前快了很多。

下载安装

下载地址: http://www.sublimetext.com/3

安装Package Control

Sublime 支持插件来丰富其功能,package control 本身也是一个插件,可以用来管理其他插件,所以我们要先安装Package Control,Sublime 3需要安装Pacakge Control Alpha.

cd "Library/Application Support/Sublime Text 3"
cd Packages/
git clone https://github.com/wbond/sublime_package_control.git "Package Control"
cd "Package Control"
git checkout python3

Java并发中正确使用volatile 2013-06-30

前几天并发编程群里有同学对volatile的用法提出了疑问,刚好我记得Twitter有关实时搜索的这个PPT对这个问题解释的很清晰并有一个实际的应用场景,于是周末把这个问题摘录了一些和并发相关的内容如下:

并发 - 定义

悲观锁 - Pressimistic locking

  1. 一个线性在执行一个操作时持有对一个资源的独占锁。(互斥)
  2. 一般用在冲突比较可能发生的场景下

乐观锁 - Optimistic locking

  1. 尝试采用原子操作,而不需要持有锁;冲突可被检测,如果发生冲突,具有相应的重试逻辑
  2. 通常用在冲突较少发生的场景下

非阻塞算法 - Non-blocking algorithm

  1. 算法确保对线程间竞争共享资源时候,不会因为互斥而使任一线程的执行无限延迟;

在Android上使用tcpdump 2013-06-24

tcpdump工具是分析网络协议和数据包的利器,也可以在Android上使用(需要root)。

首先在android上安装tcpdump

wget http://www.strazzere.com/android/tcpdump
adb push tcpdump /data/local/tmp/tcpdump
adb chmod 755 /data/local/tmp/tcpdump

然后使用root用户启动tcpdump,在android上进行相应的操作后,按ctrl+c中断

adb shell
shell@android:/ $ su
root@android:/ # /data/local/tmp/tcpdump -h                                    
tcpdump version 3.9.8
libpcap version 0.9.8
Usage: tcpdump [-aAdDeflLnNOpqRStuUvxX] [-c count] [ -C file_size ]
        [ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]
        [ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]
        [ -W filecount ] [ -y datalinktype ] [ -Z user ]
        [ expression ]
root@android:/ # /data/local/tmp/tcpdump -p -vv -s 0 w /sdcard/capture.pcap