在android L上测试反馈使用WebApp时会出现如下crash:
```bash
F/libc ( 7555): Fatal signal 6 (SIGABRT) in tid 12577 (RenderThread)

I/DEBUG ( 182): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

I/DEBUG ( 182): Build fingerprint: 'google/hammerhead/hammerhead:L/LPV79/1236599:user/release-keys'

I/DEBUG ( 182): Revision: '11'

I/DEBUG ( 182): pid: 7555, tid: 12577, name: RenderThread >>> com.eg.android.AlipayGphone <<<

I/DEBUG ( 182): signal 6 (SIGABRT), code 0 (SI_USER), fault addr --------
```
后来研究发现:

https://code.google.com/p/android-developer-preview/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary&groupby=&sort=&id=950

上有人报告同一问题。

LPV79这个build为developer preview version.存在一些问题。

后来在正式版本中验证同一问题,不可复现。

方法如下:

在自定义的WebChromeClient中实现如下方法(主要是为了保证不同android版本上的兼容性):

```java
public void openFileChooser(final ValueCallback uploadMsg)
public void openFileChooser(ValueCallback uploadMsg, String acceptType)
public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture)
```
并配置proguard保证其不被混淆掉。

在openFileChooser中使用如下Intent调用系统文件浏览器:

```java
private Intent createDefaultOpenableIntent(final Context ctx) {
// Create and return a chooser with the default OPENABLE
// actions including the camera, camcorder and sound
// recorder where available.
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");

Intent chooser = createChooserIntent(ctx, createCameraIntent(), createCamcorderIntent(),
createSoundRecorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT, i);
return chooser;
}

```
然后:

```java

startActivityForResult()

```
在主Activity的onActivityResult()中

调用ValueCallback对象的onReceiveValue()方法中将选择文件的Uri传回。

但是问题还是来了,这样做了之后在4.4系统上WebView不会回调openFileChooser方法导致没法显示出选择文件的Activity。

另外对于选择文件的应用也不能假定所有的Android系统上都有。

所以终极解决方案就是拥有自主可控的WebView。

PostgrepSQL 9.4开始支持了jsonb数据类型,从而支持了一部分nosql特性。今天使用了下,简要记录下:

记得在pgadmin中验证下postgresql的版本号:

```sql

SELECT version();

```
确认是9.4以上。

确认之后可以在SQL终端继续感受下:

```sql
SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json;
```
创建一个jsonb类型的字段:

```sql

CREATE TABLE mobile_analysis
(id serial PRIMARY KEY,
datadoc jsonb,
create_at TIMESTAMP WITH TIME ZONE default current_timestamp);

```
其中datadoc是我想存为json格式的字段的名称,为了支持后续的检索,为其创建索引:

```sql

CREATE INDEX idx_mobile_analysis ON mobile_analysis USING gin (datadoc jsonb_path_ops);

```
其中的jsonb_path_ops是为了支持对jsonb字段的值进行检索,条件过滤(比如包含有特定的key-value对的记录)所必需的。

插入一条测试数据:

```sql

INSERT INTO mobile_analysis(datadoc)
VALUES ('{"a": 1, "b":2, "d": "string_val"}');

```
通过包含条件查询之:

```sql

SELECT * FROM mobile_analysis WHERE datadoc @> '{"a":1}'

```
更多的关于json/jsonb类型的函数和操作符的资料请见这里。

有的同学在使用 git 时会不小心本地分支merge了远端的公共分支(通过 git pull ),我找了篇文章帮助大家学会 pull 的时候直接 rebase

[http://gitready.com/advanced/2009/02/11/pull-with-rebase.html](http://gitready.com/advanced/2009/02/11/pull-with-rebase.html)

其实很简单,对应的命令行是:

```bash
git pull --rebase  
```

由于 merge 提交会湮灭掉一些原始 commit 导致 rebase 时带来混乱,同时 merge 提交的 commit message 本身没有什么额外有价值的信息,我个人关于 merge 提交的经验是:

>如果你的角色是scm,代码集成者,多个分支隔离开发很长时间之后的合并建议使用merge;每天持续开发中的数量不多的提交都最好使用rebase,这样可以让提交记录尽量保持线性和整洁,进而方便代码的集成和追踪。

![](/uploads/2016_01_21_01.png)

尽管现在诞生的高级语言里边有了什么STM,协程,绿程的概念,但写代码总会遇到现实(商业级平台都不会用很新的东西)的多线程的问题。

比如有时候你需要同步的获取在另一个线程执行的代码的结果,在android里这种场景下ConditionVariable就非常好用了。

```java
if (Looper.myLooper() != Looper.getMainLooper()) {

final ConditionVariable completed = new ConditionVariable(); // 构造一个条件变量

view.runOnUiThread(new Runnable() {

@Override
public void run() {
try {
doSomeThingInUiThread(); // 将期望在另外线程做的事post出去
} finally { // finally很重要,防止运行时异常远跳转将ConditionVariable忘了open
completed.open(); // 事情办完了,notify到另外线程
}
}
});
completed.block(TIMEOUT_WAIT_UI); // 等着另外线程做的事完成,同时支持设置超时
} else {
doSomeThingInUiThread();
}
```

当然了以上是很简单的一个场景,使用ConditionVariable非常方便且够用。对于复杂的多线程之间的协同还是使用标准的条件变量结合lock + while 循环检查。

在一些新语言中有非常丰富的并发编程原语(future, delay, promise),特别是协程让我们用代码自主的确定代码流之间的协作关系而不是被动的作为OS调度器的奴隶,来支撑一些并行需求。