一个非常适合用于对用户进行第一次使用进行指导的库ShowcaseView,截图示例如下:

![showcase view 1](/uploads/2015-02-01-01.png)

![showcase view 2](/uploads/2015-02-01-02.png)

下面给出一个实例,需要瞄定一个特殊的View(id为R.id.answers),在其上显示一个ShowCaseView:

```java
new ShowcaseView.Builder(getActivity()).setTarget(new ActionItemTarget(getActivity(), R.id.answers))
//Here is where you supply the id of the action bar item you want to display
.setContentTitle("Title").setContentText("Description").hideOnTouchOutside().build();
```

项目主页位于:https://github.com/amlcurran/ShowcaseView,从其commit数和release数来看,应该非常靠谱。

接下来打算在项目中使用起来,后续补上使用感受。

android 5.0上WebView开始默认阻止Mixed Content,且不再接受第三方的cookie。所以为了你以往的WebApp里边的内容可以正常访问,需要使用WebSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW) 和CookieManager.setAcceptThirdPartyCookies({your_webview}, true) 来放开这一限制。

当然最好是让你的页面不再存在mixed content,不再依赖第三方cookie最为完美。

在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类型的函数和操作符的资料请见这里。