Full Code of MrFuFuFu/RxFace for AI

master f8753b8d76d1 cached
53 files
114.0 KB
30.3k tokens
244 symbols
1 requests
Download .txt
Repository: MrFuFuFu/RxFace
Branch: master
Commit: f8753b8d76d1
Files: 53
Total size: 114.0 KB

Directory structure:
gitextract_nz7e2i3v/

├── .gitignore
├── .idea/
│   ├── .name
│   ├── compiler.xml
│   ├── copyright/
│   │   └── profiles_settings.xml
│   ├── gradle.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── runConfigurations.xml
│   └── vcs.xml
├── Face.iml
├── README.md
├── RxFace.iml
├── app/
│   ├── .gitignore
│   ├── app.iml
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── mrfu/
│       │           └── face/
│       │               └── ApplicationTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── mrfu/
│       │   │       └── rxface/
│       │   │           ├── AppApplication.java
│       │   │           ├── BaseActivity.java
│       │   │           ├── MainActivity.java
│       │   │           ├── business/
│       │   │           │   ├── Constants.java
│       │   │           │   └── DealData.java
│       │   │           ├── loader/
│       │   │           │   ├── ExecutorManager.java
│       │   │           │   ├── FaceApi.java
│       │   │           │   ├── SchedulersCompat.java
│       │   │           │   ├── WebServiceException.java
│       │   │           │   └── custom/
│       │   │           │       ├── AsciiTypeString.java
│       │   │           │       ├── CustomMultipartTypedOutput.java
│       │   │           │       └── CustomTypedByteArray.java
│       │   │           └── models/
│       │   │               ├── BaseResponse.java
│       │   │               ├── FaceResponse.java
│       │   │               └── NeedDataEntity.java
│       │   └── res/
│       │       ├── layout/
│       │       │   ├── activity_main.xml
│       │       │   └── content_main.xml
│       │       ├── menu/
│       │       │   └── menu_main.xml
│       │       ├── values/
│       │       │   ├── colors.xml
│       │       │   ├── dimens.xml
│       │       │   ├── strings.xml
│       │       │   └── styles.xml
│       │       ├── values-v21/
│       │       │   └── styles.xml
│       │       └── values-w820dp/
│       │           └── dimens.xml
│       └── test/
│           └── java/
│               └── mrfu/
│                   └── face/
│                       └── ExampleUnitTest.java
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sdk_unuse/
│   ├── HttpRequests.java
│   ├── MainActivity.java
│   └── PostParameters.java
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures


================================================
FILE: .idea/.name
================================================
RxFace

================================================
FILE: .idea/compiler.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="CompilerConfiguration">
    <option name="DEFAULT_COMPILER" value="Javac" />
    <resourceExtensions />
    <wildcardResourcePatterns>
      <entry name="!?*.java" />
      <entry name="!?*.form" />
      <entry name="!?*.class" />
      <entry name="!?*.groovy" />
      <entry name="!?*.scala" />
      <entry name="!?*.flex" />
      <entry name="!?*.kt" />
      <entry name="!?*.clj" />
    </wildcardResourcePatterns>
    <annotationProcessing>
      <profile default="true" name="Default" enabled="false">
        <processorPath useClasspath="true" />
      </profile>
    </annotationProcessing>
  </component>
</project>

================================================
FILE: .idea/copyright/profiles_settings.xml
================================================
<component name="CopyrightManager">
  <settings default="" />
</component>

================================================
FILE: .idea/gradle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="GradleSettings">
    <option name="linkedExternalProjectsSettings">
      <GradleProjectSettings>
        <option name="distributionType" value="DEFAULT_WRAPPED" />
        <option name="externalProjectPath" value="$PROJECT_DIR$" />
        <option name="gradleJvm" value="1.8" />
        <option name="modules">
          <set>
            <option value="$PROJECT_DIR$" />
            <option value="$PROJECT_DIR$/app" />
          </set>
        </option>
      </GradleProjectSettings>
    </option>
  </component>
</project>

================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="EntryPointsManager">
    <entry_points version="2.0" />
  </component>
  <component name="NullableNotNullManager">
    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
    <option name="myNullables">
      <value>
        <list size="4">
          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
        </list>
      </value>
    </option>
    <option name="myNotNulls">
      <value>
        <list size="4">
          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
        </list>
      </value>
    </option>
  </component>
  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
    <OptionsSetting value="true" id="Add" />
    <OptionsSetting value="true" id="Remove" />
    <OptionsSetting value="true" id="Checkout" />
    <OptionsSetting value="true" id="Update" />
    <OptionsSetting value="true" id="Status" />
    <OptionsSetting value="true" id="Edit" />
    <ConfirmationsSetting value="0" id="Add" />
    <ConfirmationsSetting value="0" id="Remove" />
  </component>
  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
    <output url="file://$PROJECT_DIR$/build/classes" />
  </component>
  <component name="ProjectType">
    <option name="id" value="Android" />
  </component>
  <component name="masterDetails">
    <states>
      <state key="ProjectJDKs.UI">
        <settings>
          <last-edited>Android API 21 Platform</last-edited>
          <splitter-proportions>
            <option name="proportions">
              <list>
                <option value="0.2" />
              </list>
            </option>
          </splitter-proportions>
        </settings>
      </state>
    </states>
  </component>
</project>

================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectModuleManager">
    <modules>
      <module fileurl="file://$PROJECT_DIR$/RxFace.iml" filepath="$PROJECT_DIR$/RxFace.iml" />
      <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
    </modules>
  </component>
</project>

================================================
FILE: .idea/runConfigurations.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RunConfigurationProducerService">
    <option name="ignoredProducers">
      <set>
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
      </set>
    </option>
  </component>
</project>

================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="VcsDirectoryMappings">
    <mapping directory="" vcs="" />
  </component>
</project>

================================================
FILE: Face.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="Face" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="java-gradle" name="Java-Gradle">
      <configuration>
        <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
        <option name="BUILDABLE" value="false" />
      </configuration>
    </facet>
  </component>
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>

================================================
FILE: README.md
================================================
RxFace
=====================

用 RxJava, Retrofit, Okhttp 处理人脸识别的简单用例

## Overview

这是一个人脸识别的简单 Demo, 使用了 [FacePlusPlus](http://www.faceplusplus.com.cn/) 的接口。他们的`/detection/detect` 人脸识别接口可以使用普通的 `get` 也可以用 `post` 传递图片二进制流的形式。其中 `post` 的时候遇到了相当多的坑,下面会提。

该 demo 的网络请求库使用了 [Retrofit](https://github.com/square/retrofit) 并集成了 [OkHttp](https://github.com/square/okhttp),使用 [RxJava](https://github.com/ReactiveX/RxJava) 进行封装,方便以流的形式处理网络回调以及图片处理,View 的注入框架用了 [ButterKnife](https://github.com/JakeWharton/butterknife),图片加载使用 [Glide](https://github.com/bumptech/glide)。

## Versions

### v1.1

1. 增加了 compose 复用 work thread 处理数据,然后在 main thread 处理结果的逻辑:你可以在这片文章看到更多:[RxWeekend——RxJava周末狂欢](http://www.jianshu.com/p/ce228f517586)
2. mSubscription.unsubscribe();
3. 增加了Service 返回错误情况的处理

### v1.0



## Main difficulties

当直接使用 `get` 通过传图片 Url 拿到人脸识别数据的话是相当简单的,如下请求链接只要使用 `Retrofit` 的 `get` 请求的 `@QueryMap` 传递参数即可: [Get数据Demo](http://apicn.faceplusplus.com/v2/detection/detect?api_key=7cd1e10dc037bbe9e6db2813d6127475&api_secret=gruCjvStG159LCJutENBt6yzeLK_5ggX&url=http://imglife.gmw.cn/attachement/jpg/site2/20111014/002564a5d7d21002188831.jpg)。


主要存在的困难点是,当获取本地图片,再使用 `post` 传二进制图片数据时,`post` 要使用 `MultipartTypedOutput`,可参考 [stackoverflow](http://stackoverflow.com/questions/25249042/retrofit-multiple-images-attached-in-one-multipart-request/25260556#25260556) 的回答。然而,这样并没有结束,根据 FacePlusPlus 提供的 SDK Sample 里的 Httpurlconnection 的得到的 `post` 请求头是这样的:

 `[Content-Disposition: form-data; name="api_key", Content-Type: text/plain; charset=US-ASCII, Content-Transfer-Encoding: 8bit]`
 
 `[Content-Disposition: form-data; name="img"; filename="NoName", Content-Type: application/octet-stream, Content-Transfer-Encoding: binary]`
 
 而使用 `Retrofit` 默认实现的话,我们这样来实现:
 
 ```java
 public static MultipartTypedOutput mulipartData(Bitmap bitmap, String boundary){
    byte[] data = getBitmapByte(bitmap);
    MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
    multipartTypedOutput.addPart("api_key", new TypedString(Constants.API_KEY));
    multipartTypedOutput.addPart("api_secret", new TypedString(Constants.API_SECRET));
    multipartTypedOutput.addPart("img", new TypedByteArray("application/octet-stream", data));
    return multipartTypedOutput;
}
 ```
 
 根据 Sample 的请求头,`RestAdapter` 的请求头参数我们这样设置来:
 
 ```java
 private RequestInterceptor mRequestInterceptor = new RequestInterceptor() {
    @Override
    public void intercept(RequestFacade request) {
        request.addHeader("connection", "keep-alive");
        request.addHeader("Content-Type", "multipart/form-data; boundary="+ getBoundary() + "; charset=UTF-8");
    }
};
 ```
 
 
但是!!!它得到的String参数的头是这样的,这里没有贴出其他的差异,

 ```java
Content-Disposition: form-data; name="api_key"
Content-Type: text/plain; charset=UTF-8
Content-Length: 32
Content-Transfer-Encoding: 8bit
 ``` 
 
所以需要重写三个类:

`MultipartTypedOutput` 为 final 类,所以重写为 `CustomMultipartTypedOutput`,并使其构造函数,增加 boundary 的设置;

`TypedString `默认的编码格式是`UTF-8`,所以重写为 `AsciiTypeString`类,使其编码格式改为 `US-ASCII`;

`TypedByteArray` 默认的的 `fileName()` 方法返回的是 null,而当传图片数据时需要 fileName 为 "NoName",所以重写为 `CustomTypedByteArray` 类,设置其 fileName 为 "NoName"。
 
 同时需要注意的是在设置 `RestAdapter` 的 header 时,其 boundary 一定要和 `CustomMultipartTypedOutput` 的 boundary 相同,否则服务端无法匹配的!(这个地方,一时没注意,被整了一个多小时才发现!!) 
 
 最后 body 的传参,这样来得到:
 
 ```java
 public static CustomMultipartTypedOutput mulipartData(Bitmap bitmap, String boundary){
    byte[] data = getBitmapByte(bitmap);
    CustomMultipartTypedOutput multipartTypedOutput = new CustomMultipartTypedOutput(boundary);
    multipartTypedOutput.addPart("api_key", "8bit", new AsciiTypeString(Constants.API_KEY));
    multipartTypedOutput.addPart("api_secret", "8bit", new AsciiTypeString(Constants.API_SECRET));
    multipartTypedOutput.addPart("img", new CustomTypedByteArray("application/octet-stream", data));
    return multipartTypedOutput;
}
 ```


## Preview

![image_screen](https://raw.githubusercontent.com/MrFuFuFu/RxFace/master/images/image_screen.png)

![movie_screen](https://raw.githubusercontent.com/MrFuFuFu/RxFace/master/images/movie_screen.gif)


## More about me

* [MrFu-傅圆的个人博客](http://mrfu.me/)



## Acknowledgments

* [Glide](https://github.com/bumptech/glide) -Glide
* [Retrofit](https://github.com/square/retrofit) - Retrofit
* [OkHttp](https://github.com/square/okhttp) - OkHttp
* [RxJava](https://github.com/ReactiveX/RxJava) - RxJava
* [ButterKnife](https://github.com/JakeWharton/butterknife) - ButterKnife



License
============

    Copyright 2015 MrFu

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/MrFuFuFu/rxface/trend.png)](https://bitdeli.com/free "Bitdeli Badge")



================================================
FILE: RxFace.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="RxFace" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="java-gradle" name="Java-Gradle">
      <configuration>
        <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
        <option name="BUILDABLE" value="false" />
      </configuration>
    </facet>
  </component>
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>

================================================
FILE: app/.gitignore
================================================
/build


================================================
FILE: app/app.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="RxFace" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="android-gradle" name="Android-Gradle">
      <configuration>
        <option name="GRADLE_PROJECT_PATH" value=":app" />
      </configuration>
    </facet>
    <facet type="android" name="Android">
      <configuration>
        <option name="SELECTED_BUILD_VARIANT" value="debug" />
        <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
        <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
        <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
        <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
        <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
        <afterSyncTasks>
          <task>generateDebugAndroidTestSources</task>
          <task>generateDebugSources</task>
        </afterSyncTasks>
        <option name="ALLOW_USER_CONFIGURATION" value="false" />
        <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
        <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
        <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
        <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
      </configuration>
    </facet>
  </component>
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
    <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
    <output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.1.1/jars" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.1.1/jars" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.1.1/jars" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.1.1/jars" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/io.reactivex/rxandroid/1.0.1/jars" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
      <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
      <excludeFolder url="file://$MODULE_DIR$/build/reports" />
      <excludeFolder url="file://$MODULE_DIR$/build/test-results" />
      <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
    </content>
    <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="library" exported="" name="butterknife-7.0.1" level="project" />
    <orderEntry type="library" exported="" name="gson-2.3.1" level="project" />
    <orderEntry type="library" exported="" name="rxandroid-1.0.1" level="project" />
    <orderEntry type="library" exported="" name="retrofit-1.9.0" level="project" />
    <orderEntry type="library" exported="" name="design-23.1.1" level="project" />
    <orderEntry type="library" exported="" name="recyclerview-v7-23.1.1" level="project" />
    <orderEntry type="library" exported="" name="support-v4-23.1.1" level="project" />
    <orderEntry type="library" exported="" name="rxjava-1.0.14" level="project" />
    <orderEntry type="library" exported="" name="okhttp-2.0.0" level="project" />
    <orderEntry type="library" exported="" name="okio-1.0.0" level="project" />
    <orderEntry type="library" exported="" name="support-annotations-23.1.1" level="project" />
    <orderEntry type="library" exported="" name="appcompat-v7-23.1.1" level="project" />
    <orderEntry type="library" exported="" name="glide-3.6.0" level="project" />
    <orderEntry type="library" exported="" name="okhttp-urlconnection-2.0.0" level="project" />
  </component>
</module>

================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "mrfu.face"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 3
        versionName "1.1"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    lintOptions {
        abortOnError false
    }

//    compileOptions {
//        sourceCompatibility JavaVersion.VERSION_1_8
//        targetCompatibility JavaVersion.VERSION_1_8
//    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.squareup.retrofit:retrofit:1.9.0'
    compile 'io.reactivex:rxjava:1.0.14'
    compile 'io.reactivex:rxandroid:1.0.1'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
    compile 'com.squareup.okhttp:okhttp:2.0.0'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
    compile 'com.github.bumptech.glide:glide:3.6.0'
}

================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/MrFu/Desktop/Android/adt-bundle-mac-x86_64-20131030/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: app/src/androidTest/java/mrfu/face/ApplicationTest.java
================================================
package mrfu.face;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
 * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
 */
public class ApplicationTest extends ApplicationTestCase<Application> {
    public ApplicationTest() {
        super(Application.class);
    }
}

================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="mrfu.rxface" >

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:name=".AppApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


================================================
FILE: app/src/main/java/mrfu/rxface/AppApplication.java
================================================
package mrfu.rxface;

import android.app.Application;
import android.content.Context;

/**
 * Created by MrFu on 15/12/15.
 */
public class AppApplication extends Application {

    private static Context context;

    public static Context getContext() {
        return context;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/BaseActivity.java
================================================
package mrfu.rxface;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import butterknife.ButterKnife;
import rx.Subscription;
import rx.subscriptions.Subscriptions;

/**
 * Created by MrFu on 16/1/10.
 */
public class BaseActivity extends AppCompatActivity {
    protected Subscription mSubscription = Subscriptions.empty();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        ButterKnife.bind(BaseActivity.this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ButterKnife.unbind(BaseActivity.this);
        if (mSubscription != null && !mSubscription.isUnsubscribed()) mSubscription.unsubscribe();
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/MainActivity.java
================================================
package mrfu.rxface;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import butterknife.Bind;
import butterknife.OnClick;
import mrfu.rxface.business.Constants;
import mrfu.rxface.business.DealData;
import mrfu.rxface.loader.FaceApi;
import mrfu.rxface.models.FaceResponse;
import mrfu.rxface.models.NeedDataEntity;
import rx.Observable;
import rx.Observer;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

public class MainActivity extends BaseActivity {

    @Bind(R.id.iv_face_get)
    ImageView iv_face_get;

    @Bind(R.id.iv_face_post)
    ImageView iv_face_post;

    @Bind(R.id.btn_recongize_get)
    Button btn_recongize_get;

    @Bind(R.id.btn_recongize_post)
    Button btn_recongize_post;

    @Bind(R.id.tv_age_get)
    TextView tv_age_get;

    @Bind(R.id.tv_age_post)
    TextView tv_age_post;

    /**
     * 0:GET button
     * 1:POST button
     */
    private int type = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Glide.with(this).load(Constants.IMAGE_URL).fitCenter().into(iv_face_get);
        iv_face_post.setImageResource(R.drawable.jobs);
    }

    @OnClick(R.id.btn_recongize_get)
    public void btn_recongize_get(View view){
        type = 0;
        Map<String, String> options = new HashMap<>();
        options.put("api_key", Constants.API_KEY);
        options.put("api_secret", Constants.API_SECRET);
        options.put("url", Constants.IMAGE_URL);
        mSubscription = FaceApi.getIns()//api_key={apiKey}&api_secret={apiSecret}&url={imgUrl}
                .getDataUrlGet(options)
                .observeOn(Schedulers.newThread())
                .flatMap(new Func1<FaceResponse, Observable<NeedDataEntity>>() {
                    @Override
                    public Observable<NeedDataEntity> call(FaceResponse faceResponse) {
                        Bitmap bitmap = null;
                        try {
                            //java.lang.IllegalArgumentException: YOu must call this method on a background thread
                            bitmap = Glide.with(MainActivity.this).load(Constants.IMAGE_URL).asBitmap().into(-1, -1).get();
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }
                        NeedDataEntity entity = new NeedDataEntity();
                        entity.bitmap = DealData.drawLineGetBitmap(faceResponse, bitmap);
                        entity.displayStr = DealData.getDisplayInfo(faceResponse);
                        return Observable.just(entity);
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(setBitmapDataObserver);
    }

    @OnClick(R.id.btn_recongize_post)
    public void btn_recongize_post(View view){
        type = 1;
        BitmapDrawable mDrawable =  (BitmapDrawable) iv_face_post.getDrawable();
        final Bitmap bitmap = mDrawable.getBitmap();

        mSubscription = FaceApi.getIns()
                .getDataPost(DealData.mulipartData(bitmap, FaceApi.getIns().getBoundary()))
                .flatMap(new Func1<FaceResponse, Observable<NeedDataEntity>>() {
                    @Override
                    public Observable<NeedDataEntity> call(FaceResponse faceResponse) {
                        NeedDataEntity entity = new NeedDataEntity();
                        entity.bitmap = DealData.drawLineGetBitmap(faceResponse, bitmap);
                        entity.displayStr = DealData.getDisplayInfo(faceResponse);
                        return Observable.just(entity);
                    }
                })
                .subscribe(setBitmapDataObserver);
    }

    private Observer<NeedDataEntity> setBitmapDataObserver = new Observer<NeedDataEntity>() {

        @Override
        public void onNext(final NeedDataEntity needDataEntity) {
            if (needDataEntity == null){
                return;
            }
            switch (type){
                case 0:
                    if (!TextUtils.isEmpty(needDataEntity.displayStr)){
                        tv_age_get.setText(needDataEntity.displayStr);
                    }
                    if (needDataEntity.bitmap != null){
                        iv_face_get.setImageBitmap(needDataEntity.bitmap);
                    }
                    break;
                case 1:
                    if (!TextUtils.isEmpty(needDataEntity.displayStr)){
                        tv_age_post.setText(needDataEntity.displayStr);
                    }
                    if (needDataEntity.bitmap != null){
                        iv_face_post.setImageBitmap(needDataEntity.bitmap);
                    }
                    break;
                default:
                    break;
            }
        }

        @Override
        public void onCompleted() {
            Log.i("MrFu", "onCompleted");
        }

        @Override
        public void onError(final Throwable error) {
            error.printStackTrace();
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Uri uri = Uri.parse("https://github.com/MrFuFuFu/RxFace");
            Intent i = new Intent(Intent.ACTION_VIEW, uri);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(i);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/business/Constants.java
================================================
package mrfu.rxface.business;

/**
 * Created by MrFu on 15/12/15.
 */
public class Constants {
//    public static final String FACE_SERVER_IP = "https://apicn.faceplusplus.com/v2";
    public static final String FACE_SERVER_IP = "http://apicn.faceplusplus.com/v2";

    public static final String API_KEY = "7cd1e10dc037bbe9e6db2813d6127475";
    public static final String API_SECRET = "gruCjvStG159LCJutENBt6yzeLK_5ggX";

    public static final String IMAGE_URL = "http://www.ipmm.cn/UploadImage/20130502/2013050209272791.jpg";

    public static final int TIME_OUT = 30 * 1000;
}


================================================
FILE: app/src/main/java/mrfu/rxface/business/DealData.java
================================================
package mrfu.rxface.business;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;

import java.io.ByteArrayOutputStream;

import mrfu.rxface.loader.custom.AsciiTypeString;
import mrfu.rxface.loader.custom.CustomMultipartTypedOutput;
import mrfu.rxface.loader.custom.CustomTypedByteArray;
import mrfu.rxface.models.FaceResponse;

/**
 * Created by MrFu on 15/12/15.
 */
public class DealData {

    /**
     * 设置参数
     * 使用 MultipartTypedOutput, 而不使用 Retrofit @Multipart 的 @Part 和 @PartMap 的形式
     * http://stackoverflow.com/questions/25249042/retrofit-multiple-images-attached-in-one-multipart-request/25260556#25260556
     *
     * @see CustomMultipartTypedOutput 重写 MultipartTypedOutput 使之接受 boundary 参数
     * @see AsciiTypeString , 重写 TypedByteArray, 使其编码格式为 US-ASCII
     * @see CustomTypedByteArray , 重写 TypedByteArray 设置其 fileName 为 "NoName",
     * 以上参数格式和参数类型都必须指定,否则会返回对应的错误
     * http://www.faceplusplus.com.cn/detection_detect/
     * @param bitmap need upload image
     * @param boundary must same with http header boundary
     * @return http post body param
     */
    public static CustomMultipartTypedOutput mulipartData(Bitmap bitmap, String boundary){
        byte[] data = getBitmapByte(bitmap);
        CustomMultipartTypedOutput multipartTypedOutput = new CustomMultipartTypedOutput(boundary);
        multipartTypedOutput.addPart("api_key", "8bit", new AsciiTypeString(Constants.API_KEY));
        multipartTypedOutput.addPart("api_secret", "8bit", new AsciiTypeString(Constants.API_SECRET));
        multipartTypedOutput.addPart("img", new CustomTypedByteArray("application/octet-stream", data));
        return multipartTypedOutput;
    }

    /**
     * convert bitmap to byte[]
     * @param bitmap need convert bitmap
     * @return byte[]
     */
    private static byte[] getBitmapByte(Bitmap bitmap){
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        float scale = Math.min(1, Math.min(600f / bitmap.getWidth(), 600f / bitmap.getHeight()));
        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);
        Bitmap imgSmall = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
        imgSmall.compress(Bitmap.CompressFormat.JPEG, 100, stream);
        return stream.toByteArray();
    }

    /**
     * draw to include face bitmap
     * @param entity data
     * @param viewBitmap display bitmap
     * @return face bitmap
     */
    public static Bitmap drawLineGetBitmap(FaceResponse entity, Bitmap viewBitmap){
        //use the red paint
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(Math.max(viewBitmap.getWidth(), viewBitmap.getHeight()) / 100f);

        //create a new canvas
        Bitmap bitmap = Bitmap.createBitmap(viewBitmap.getWidth(), viewBitmap.getHeight(), viewBitmap.getConfig());
        Canvas canvas = new Canvas(bitmap);
        canvas.drawBitmap(viewBitmap, new Matrix(), null);

        try {
            //find out all faces
            final int count = entity.face.size();
            for (int i = 0; i < count; ++i) {
                float x, y, w, h;
                //get the center point
                x = (float) entity.face.get(i).position.center.x;
                y = (float) entity.face.get(i).position.center.y;
                //get face size
                w = (float) entity.face.get(i).position.width;
                h = (float) entity.face.get(i).position.height;
                //change percent value to the real size
                x = x / 100 * viewBitmap.getWidth();
                w = w / 100 * viewBitmap.getWidth() * 0.7f;
                y = y / 100 * viewBitmap.getHeight();
                h = h / 100 * viewBitmap.getHeight() * 0.7f;
                //draw the box to mark it out
                canvas.drawLine(x - w, y - h, x - w, y + h, paint);
                canvas.drawLine(x - w, y - h, x + w, y - h, paint);
                canvas.drawLine(x + w, y + h, x - w, y + h, paint);
                canvas.drawLine(x + w, y + h, x + w, y - h, paint);
            }
            //save new image
            viewBitmap = bitmap;
            return viewBitmap;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public static String getDisplayInfo(FaceResponse entity){
        if (entity == null || entity.face == null || entity.face.size() == 0
                || entity.face.get(0).attribute == null){
            return "";
        }
        int age = 0;
        if (entity.face.get(0).attribute.age != null){
            age = entity.face.get(0).attribute.age.value;
        }
        String gender = "";
        if (entity.face.get(0).attribute.gender != null){
            gender = "male".equalsIgnoreCase(entity.face.get(0).attribute.gender.value) ? "男" : "女";
        }
        return "年龄约 " + age + " 性别为 " + gender;
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/loader/ExecutorManager.java
================================================
package mrfu.rxface.loader;

import android.os.Build;
import android.support.annotation.NonNull;

import java.io.File;
import java.io.FileFilter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by Joker on 2015/8/24.
 */
public class ExecutorManager {

    public static final int DEVICE_INFO_UNKNOWN = 0;
    public static ExecutorService eventExecutor;
    //private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CPU_COUNT = ExecutorManager.getCountOfCPU();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;
    private static final BlockingQueue<Runnable> eventPoolWaitQueue = new LinkedBlockingQueue<>(128);
    private static final ThreadFactory eventThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(@NonNull Runnable r) {
            return new Thread(r, "eventAsyncAndBackground #" + mCount.getAndIncrement());
        }
    };

    private static final RejectedExecutionHandler eventHandler =
            new ThreadPoolExecutor.CallerRunsPolicy();

    static {
        eventExecutor =
                new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS,
                        eventPoolWaitQueue, eventThreadFactory, eventHandler);
    }

    /**
     * Linux中的设备都是以文件的形式存在,CPU也不例外,因此CPU的文件个数就等价与核数。
     * Android的CPU 设备文件位于/sys/devices/system/cpu/目录,文件名的的格式为cpu\d+。
     *
     * 引用:http://www.jianshu.com/p/f7add443cd32#,感谢 liangfeizc :)
     * https://github.com/facebook/device-year-class
     */
    public static int getCountOfCPU() {

        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
            return 1;
        }
        int count;
        try {
            count = new File("/sys/devices/system/cpu/").listFiles(CPU_FILTER).length;
        } catch (SecurityException | NullPointerException e) {
            count = DEVICE_INFO_UNKNOWN;
        }
        return count;
    }

    private static final FileFilter CPU_FILTER = new FileFilter() {
        @Override public boolean accept(File pathname) {

            String path = pathname.getName();
            if (path.startsWith("cpu")) {
                for (int i = 3; i < path.length(); i++) {
                    if (path.charAt(i) < '0' || path.charAt(i) > '9') {
                        return false;
                    }
                }
                return true;
            }
            return false;
        }
    };
}

================================================
FILE: app/src/main/java/mrfu/rxface/loader/FaceApi.java
================================================
package mrfu.rxface.loader;

import com.squareup.okhttp.OkHttpClient;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import mrfu.rxface.BuildConfig;
import mrfu.rxface.business.Constants;
import mrfu.rxface.loader.custom.CustomMultipartTypedOutput;
import mrfu.rxface.models.FaceResponse;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.client.OkClient;
import retrofit.http.Body;
import retrofit.http.GET;
import retrofit.http.POST;
import retrofit.http.QueryMap;
import rx.Observable;
import rx.functions.Func1;

/**
 * face api
 * Created by MrFu on 15/12/15.
 */
public class FaceApi {
    private static String mBoundry;
    private final static int boundaryLength = 32;
    private final static String boundaryAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";

    public static FaceApi instance;

    public static FaceApi getIns() {
        if (null == instance) {
            synchronized (FaceApi.class) {
                if (null == instance) {
                    instance = new FaceApi();
                }
            }
        }
        return instance;
    }

    private final MrFuService mWebService;

    public FaceApi() {
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(Constants.FACE_SERVER_IP)
                .setClient(new OkClient(new OkHttpClient()))
                .setLogLevel(BuildConfig.DEBUG ? RestAdapter.LogLevel.FULL : RestAdapter.LogLevel.NONE)
                .setRequestInterceptor(mRequestInterceptor)
                .build();
        mWebService = restAdapter.create(MrFuService.class);
        mBoundry = setBoundary();
    }

    private RequestInterceptor mRequestInterceptor = new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {
            request.addHeader("connection", "keep-alive");
            request.addHeader("Content-Type", "multipart/form-data; boundary="+ getBoundary() + "; charset=UTF-8");
        }
    };

    public String getBoundary(){
        return mBoundry;
    }

    /**
     * 设置 Content-Type 的 boundary,这里有个强坑:
     * header 的 boundary 和 CustomMultipartTypedOutput 的 boundary 必须相同!!
     * @return mBoundry
     */
    private static String setBoundary() {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < boundaryLength; ++i)
            sb.append(boundaryAlphabet.charAt(random.nextInt(boundaryAlphabet.length())));
        return sb.toString();
    }

    public interface MrFuService {
        @POST("/detection/detect")
        Observable<FaceResponse> uploadImagePost(
                @Body CustomMultipartTypedOutput listMultipartOutput
        );

        //http://apicn.faceplusplus.com/v2/detection/detect?api_key=7cd1e10dc037bbe9e6db2813d6127475&api_secret=gruCjvStG159LCJutENBt6yzeLK_5ggX&url=http://imglife.gmw.cn/attachement/jpg/site2/20111014/002564a5d7d21002188831.jpg
        @GET("/detection/detect")
        Observable<FaceResponse> uploadImageUrlGet(
                @QueryMap Map<String, String> options
        );
    }

    public Observable<FaceResponse> getDataPost(CustomMultipartTypedOutput listMultipartOutput) {
        return mWebService.uploadImagePost(listMultipartOutput)
                .timeout(Constants.TIME_OUT, TimeUnit.MILLISECONDS)
                .concatMap(new Func1<FaceResponse, Observable<FaceResponse>>() {
                    @Override
                    public Observable<FaceResponse> call(FaceResponse faceResponse) {
                        return faceResponse.filterWebServiceErrors();
                    }
                }).compose(SchedulersCompat.<FaceResponse>applyExecutorSchedulers());
    }

    public Observable<FaceResponse> getDataUrlGet(Map<String, String> options) {
        return mWebService.uploadImageUrlGet(options)
                .timeout(Constants.TIME_OUT, TimeUnit.MILLISECONDS)
                .concatMap(new Func1<FaceResponse, Observable<FaceResponse>>() {
                    @Override
                    public Observable<FaceResponse> call(FaceResponse faceResponse) {
                        return faceResponse.filterWebServiceErrors();
                    }
                }).compose(SchedulersCompat.<FaceResponse>applyExecutorSchedulers());//http://www.jianshu.com/p/e9e03194199e
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/loader/SchedulersCompat.java
================================================
package mrfu.rxface.loader;

import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * 小鄧子:【译】避免打断链式结构:使用.compose( )操作符 http://www.jianshu.com/p/e9e03194199e
 * Created by Joker on 2015/8/10.
 */
public class SchedulersCompat {

    private static final Observable.Transformer computationTransformer =
            new Observable.Transformer() {
                @Override public Object call(Object observable) {
                    return ((Observable) observable).subscribeOn(Schedulers.computation())
                            .observeOn(AndroidSchedulers.mainThread());
                }
            };

    private static final Observable.Transformer ioTransformer = new Observable.Transformer() {
        @Override public Object call(Object observable) {
            return ((Observable) observable).subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread());
        }
    };
    private static final Observable.Transformer newTransformer = new Observable.Transformer() {
        @Override public Object call(Object observable) {
            return ((Observable) observable).subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread());
        }
    };
    private static final Observable.Transformer trampolineTransformer = new Observable.Transformer() {
        @Override public Object call(Object observable) {
            return ((Observable) observable).subscribeOn(Schedulers.trampoline())
                    .observeOn(AndroidSchedulers.mainThread());
        }
    };

    private static final Observable.Transformer executorTransformer = new Observable.Transformer() {
        @Override public Object call(Object observable) {
            return ((Observable) observable).subscribeOn(Schedulers.from(ExecutorManager.eventExecutor))
                    .observeOn(AndroidSchedulers.mainThread());
        }
    };

    /**
     * Don't break the chain: use RxJava's compose() operator
     */
    public static <T> Observable.Transformer<T, T> applyComputationSchedulers() {

        return (Observable.Transformer<T, T>) computationTransformer;
    }

    public static <T> Observable.Transformer<T, T> applyIoSchedulers() {

        return (Observable.Transformer<T, T>) ioTransformer;
    }

    public static <T> Observable.Transformer<T, T> applyNewSchedulers() {

        return (Observable.Transformer<T, T>) newTransformer;
    }

    public static <T> Observable.Transformer<T, T> applyTrampolineSchedulers() {

        return (Observable.Transformer<T, T>) trampolineTransformer;
    }

    public static <T> Observable.Transformer<T, T> applyExecutorSchedulers() {

        return (Observable.Transformer<T, T>) executorTransformer;
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/loader/WebServiceException.java
================================================
package mrfu.rxface.loader;

/**
 * Created by MrFu on 16/1/10.
 */
public class WebServiceException extends Exception {
    public WebServiceException(String detailMessage) {
        super(detailMessage);
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/loader/custom/AsciiTypeString.java
================================================
package mrfu.rxface.loader.custom;

import java.io.UnsupportedEncodingException;

import retrofit.mime.TypedByteArray;

/**
 * 重写 TypedByteArray, 使其编码格式为 US-ASCII
 * Created by MrFu on 15/12/16.
 */
public class AsciiTypeString extends TypedByteArray {

    public AsciiTypeString(String string) {
        super("text/plain; charset=US-ASCII", convertToBytes(string));
    }

    private static byte[] convertToBytes(String string) {
        try {
            return string.getBytes("US-ASCII");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override public String toString() {
        try {
            return "TypedString[" + new String(getBytes(), "US-ASCII") + "]";
        } catch (UnsupportedEncodingException e) {
            throw new AssertionError("Must be able to decode US-ASCII");
        }
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/loader/custom/CustomMultipartTypedOutput.java
================================================
package mrfu.rxface.loader.custom;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import retrofit.mime.TypedOutput;

/**
 * 重写 MultipartTypedOutput 使之接受 boundary 参数
 * Created by MrFu on 15/12/16.
 */
public class CustomMultipartTypedOutput implements TypedOutput {
    public static final String DEFAULT_TRANSFER_ENCODING = "binary";

    private static final class MimePart {
        private final TypedOutput body;
        private final String name;
        private final String transferEncoding;
        private final boolean isFirst;
        private final String boundary;

        private byte[] partBoundary;
        private byte[] partHeader;
        private boolean isBuilt;

        public MimePart(String name, String transferEncoding, TypedOutput body, String boundary,
                        boolean isFirst) {
            this.name = name;
            this.transferEncoding = transferEncoding;
            this.body = body;
            this.isFirst = isFirst;
            this.boundary = boundary;
        }

        public void writeTo(OutputStream out) throws IOException {
            build();
            out.write(partBoundary);
            out.write(partHeader);
            body.writeTo(out);
        }

        public long size() {
            build();
            if (body.length() > -1) {
                return body.length() + partBoundary.length + partHeader.length;
            } else {
                return -1;
            }
        }

        private void build() {
            if (isBuilt) return;
            partBoundary = buildBoundary(boundary, isFirst, false);
            partHeader = buildHeader(name, transferEncoding, body);
            isBuilt = true;
        }
    }

    private final List<MimePart> mimeParts = new LinkedList<MimePart>();

    private final byte[] footer;
    private final String boundary;
    private long length;

    public CustomMultipartTypedOutput() {
        this(UUID.randomUUID().toString());
    }

    public CustomMultipartTypedOutput(String boundary) {
        this.boundary = boundary;
        footer = buildBoundary(boundary, false, true);
        length = footer.length;
    }

    List<byte[]> getParts() throws IOException {
        List<byte[]> parts = new ArrayList<byte[]>(mimeParts.size());
        for (MimePart part : mimeParts) {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            part.writeTo(bos);
            parts.add(bos.toByteArray());
        }
        return parts;
    }

    public void addPart(String name, TypedOutput body) {
        addPart(name, DEFAULT_TRANSFER_ENCODING, body);
    }

    public void addPart(String name, String transferEncoding, TypedOutput body) {
        if (name == null) {
            throw new NullPointerException("Part name must not be null.");
        }
        if (transferEncoding == null) {
            throw new NullPointerException("Transfer encoding must not be null.");
        }
        if (body == null) {
            throw new NullPointerException("Part body must not be null.");
        }

        MimePart part = new MimePart(name, transferEncoding, body, boundary, mimeParts.isEmpty());
        mimeParts.add(part);

        long size = part.size();
        if (size == -1) {
            length = -1;
        } else if (length != -1) {
            length += size;
        }
    }

    public int getPartCount() {
        return mimeParts.size();
    }

    @Override public String fileName() {
        return null;
    }

    @Override public String mimeType() {
        return "multipart/form-data; boundary=" + boundary;
    }

    @Override public long length() {
        return length;
    }

    @Override public void writeTo(OutputStream out) throws IOException {
        for (MimePart part : mimeParts) {
            part.writeTo(out);
        }
        out.write(footer);
    }

    private static byte[] buildBoundary(String boundary, boolean first, boolean last) {
        try {
            // Pre-size for the last boundary, the worst case scenario.
            StringBuilder sb = new StringBuilder(boundary.length() + 8);

            if (!first) {
                sb.append("\r\n");
            }
            sb.append("--");
            sb.append(boundary);
            if (last) {
                sb.append("--");
            }
            sb.append("\r\n");
            return sb.toString().getBytes("UTF-8");
        } catch (IOException ex) {
            throw new RuntimeException("Unable to write multipart boundary", ex);
        }
    }

    private static byte[] buildHeader(String name, String transferEncoding, TypedOutput value) {
        try {
            // Initial size estimate based on always-present strings and conservative value lengths.
            StringBuilder headers = new StringBuilder(128);

            headers.append("Content-Disposition: form-data; name=\"");
            headers.append(name);

            String fileName = value.fileName();
            if (fileName != null) {
                headers.append("\"; filename=\"");
                headers.append(fileName);
            }

            headers.append("\"\r\nContent-Type: ");
            headers.append(value.mimeType());

            long length = value.length();
            if (length != -1) {
                headers.append("\r\nContent-Length: ").append(length);
            }

            headers.append("\r\nContent-Transfer-Encoding: ");
            headers.append(transferEncoding);
            headers.append("\r\n\r\n");

            return headers.toString().getBytes("UTF-8");
        } catch (IOException ex) {
            throw new RuntimeException("Unable to write multipart header", ex);
        }
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/loader/custom/CustomTypedByteArray.java
================================================
package mrfu.rxface.loader.custom;

import retrofit.mime.TypedByteArray;

/**
 * 重写 TypedByteArray 设置其 fileName 为 "NoName",
 * Created by MrFu on 15/12/16.
 */
public class CustomTypedByteArray extends TypedByteArray {
    /**
     * Constructs a new typed byte array.  Sets mimeType to {@code application/unknown} if absent.
     *
     * @param mimeType
     * @param bytes
     * @throws NullPointerException if bytes are null
     */
    public CustomTypedByteArray(String mimeType, byte[] bytes) {
        super(mimeType, bytes);
    }

    @Override
    public String fileName() {
        return "NoName";
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/models/BaseResponse.java
================================================
package mrfu.rxface.models;

import mrfu.rxface.loader.WebServiceException;
import rx.Observable;

/**
 * Created by MrFu on 16/1/10.
 */
public class BaseResponse {
    public Observable filterWebServiceErrors() {
        if (true){//judge result status is ok~~
            return Observable.just(this);
        }else {
            return Observable.error(new WebServiceException("Service return Error message"));
        }
        //demo code just like blow, the common is a class object, you can deal the error code in here.
//        public class BaseResponse {
//            public Common common;
//
//            public Observable filterWebServiceErrors() {
//                if (common == null){
//                    return Observable.error(new WebServiceException("啊喔,服务器除了点小问题"));
//                }else {
//                    int code = Integer.parseInt(common.status);
//                    switch (code){
//                        case Constants.RESULT_OK://正常
//                            return Observable.just(this);
//                        case Constants.RESULT_NORMAL_UPDATE://普通升级
//                        case Constants.RESULT_FORCE_UPDATE://墙纸升级
//                            if (AppApplication.getInstance().updateModel == null) {
//                                AppApplication.getInstance().updateModel = common.update;
//                                AppApplication.getInstance().updateModel.code = code;
//                            }
//                            return Observable.just(this);
//                        default://出错
//                            return Observable.error(new WebServiceException(BaseResponse.this.common.memo));
//                    }
//                }
//            }
//        }
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/models/FaceResponse.java
================================================
package mrfu.rxface.models;

import java.util.List;

/**
 * Created by MrFu on 15/12/16.
 */
public class FaceResponse extends BaseResponse{

    /**
     * face : [{"attribute":{"age":{"range":6,"value":18},"gender":{"confidence":99.9996,"value":"Male"},"race":{"confidence":99.8977,"value":"White"},"smiling":{"value":81.2229}},"face_id":"5bf244c54d5731974e25ee024b950cd3","position":{"center":{"x":47.833333,"y":49.036403},"eye_left":{"x":42.140333,"y":42.28394},"eye_right":{"x":53.658,"y":42.389936},"height":31.263383,"mouth_left":{"x":42.352167,"y":56.311991},"mouth_right":{"x":53.747833,"y":56.89379},"nose":{"x":47.392667,"y":51.794004},"width":24.333333},"tag":""},{"attribute":{"age":{"range":5,"value":24},"gender":{"confidence":99.5758,"value":"Male"},"race":{"confidence":99.94800000000001,"value":"White"},"smiling":{"value":93.0865}},"face_id":"092cb7660d3f8d115b8af331465624a1","position":{"center":{"x":83.833333,"y":52.462527},"eye_left":{"x":77.052667,"y":47.005353},"eye_right":{"x":87.198,"y":44.253961},"height":28.265525,"mouth_left":{"x":77.304167,"y":60.063169},"mouth_right":{"x":86.635167,"y":60.254176},"nose":{"x":86.9965,"y":54.840685},"width":22},"tag":""},{"attribute":{"age":{"range":11,"value":38},"gender":{"confidence":74.2956,"value":"Female"},"race":{"confidence":96.8155,"value":"White"},"smiling":{"value":86.556}},"face_id":"3c9d898f732c84d07d760f184bfec814","position":{"center":{"x":13,"y":52.248394},"eye_left":{"x":8.483217,"y":44.584797},"eye_right":{"x":18.669667,"y":46.517987},"height":27.837259,"mouth_left":{"x":8.44005,"y":60.162955},"mouth_right":{"x":17.914333,"y":60.197645},"nose":{"x":8.59085,"y":53.623769},"width":21.666667},"tag":""}]
     * img_height : 490
     * img_id : f3f8c2826537ce51ca1995143e8b9289
     * img_width : 629
     * session_id : a7f871065a064bdfabe06de48189dcac
     * url : http://imglife.gmw.cn/attachement/jpg/site2/20111014/002564a5d7d21002188831.jpg
     */

    public int img_height;
    public String img_id;
    public int img_width;
    public String session_id;
    public String url;
    /**
     * attribute : {"age":{"range":6,"value":18},"gender":{"confidence":99.9996,"value":"Male"},"race":{"confidence":99.8977,"value":"White"},"smiling":{"value":81.2229}}
     * face_id : 5bf244c54d5731974e25ee024b950cd3
     * position : {"center":{"x":47.833333,"y":49.036403},"eye_left":{"x":42.140333,"y":42.28394},"eye_right":{"x":53.658,"y":42.389936},"height":31.263383,"mouth_left":{"x":42.352167,"y":56.311991},"mouth_right":{"x":53.747833,"y":56.89379},"nose":{"x":47.392667,"y":51.794004},"width":24.333333}
     * tag :
     */

    public List<FaceEntity> face;

    public static class FaceEntity {
        /**
         * age : {"range":6,"value":18}
         * gender : {"confidence":99.9996,"value":"Male"}
         * race : {"confidence":99.8977,"value":"White"}
         * smiling : {"value":81.2229}
         */

        public AttributeEntity attribute;
        public String face_id;
        /**
         * center : {"x":47.833333,"y":49.036403}
         * eye_left : {"x":42.140333,"y":42.28394}
         * eye_right : {"x":53.658,"y":42.389936}
         * height : 31.263383
         * mouth_left : {"x":42.352167,"y":56.311991}
         * mouth_right : {"x":53.747833,"y":56.89379}
         * nose : {"x":47.392667,"y":51.794004}
         * width : 24.333333
         */

        public PositionEntity position;
        public String tag;

        public static class AttributeEntity {
            /**
             * range : 6
             * value : 18
             */

            public AgeEntity age;
            /**
             * confidence : 99.9996
             * value : Male
             */

            public GenderEntity gender;
            /**
             * confidence : 99.8977
             * value : White
             */

            public RaceEntity race;
            /**
             * value : 81.2229
             */

            public SmilingEntity smiling;

            public static class AgeEntity {
                public int range;
                public int value;
            }

            public static class GenderEntity {
                public double confidence;
                public String value;
            }

            public static class RaceEntity {
                public double confidence;
                public String value;
            }

            public static class SmilingEntity {
                public double value;
            }
        }

        public static class PositionEntity {
            /**
             * x : 47.833333
             * y : 49.036403
             */

            public CenterEntity center;
            /**
             * x : 42.140333
             * y : 42.28394
             */

            public EyeLeftEntity eye_left;
            /**
             * x : 53.658
             * y : 42.389936
             */

            public EyeRightEntity eye_right;
            public double height;
            /**
             * x : 42.352167
             * y : 56.311991
             */

            public MouthLeftEntity mouth_left;
            /**
             * x : 53.747833
             * y : 56.89379
             */

            public MouthRightEntity mouth_right;
            /**
             * x : 47.392667
             * y : 51.794004
             */

            public NoseEntity nose;
            public double width;

            public static class CenterEntity {
                public double x;
                public double y;
            }

            public static class EyeLeftEntity {
                public double x;
                public double y;
            }

            public static class EyeRightEntity {
                public double x;
                public double y;
            }

            public static class MouthLeftEntity {
                public double x;
                public double y;
            }

            public static class MouthRightEntity {
                public double x;
                public double y;
            }

            public static class NoseEntity {
                public double x;
                public double y;
            }
        }
    }
}


================================================
FILE: app/src/main/java/mrfu/rxface/models/NeedDataEntity.java
================================================
package mrfu.rxface.models;

import android.graphics.Bitmap;

/**
 * Created by MrFu on 15/12/16.
 */
public class NeedDataEntity {
    public Bitmap bitmap;
    public String displayStr;
}


================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

    <!--<android.support.design.widget.FloatingActionButton-->
        <!--android:id="@+id/fab"-->
        <!--android:layout_width="wrap_content"-->
        <!--android:layout_height="wrap_content"-->
        <!--android:layout_gravity="bottom|end"-->
        <!--android:layout_margin="@dimen/fab_margin"-->
        <!--android:src="@android:drawable/ic_dialog_email"/>-->

</android.support.design.widget.CoordinatorLayout>


================================================
FILE: app/src/main/res/layout/content_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">


    <ImageView
        android:id="@+id/iv_face_get"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"/>


    <ImageView
        android:id="@+id/iv_face_post"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        android:layout_weight="1">

        <Button
            android:id="@+id/btn_recongize_get"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_below="@+id/tv_age_get"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:padding="20dp"
            android:text="@string/reconginze_get"/>

        <TextView
            android:id="@+id/tv_age_get"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="20dp"/>

        <Button
            android:id="@+id/btn_recongize_post"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/tv_age_post"
            android:layout_marginRight="20dp"
            android:layout_marginTop="10dp"
            android:padding="20dp"
            android:text="@string/reconginze_post"/>

        <TextView
            android:id="@+id/tv_age_post"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="20dp"/>

    </RelativeLayout>


</LinearLayout>


================================================
FILE: app/src/main/res/menu/menu_main.xml
================================================
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      tools:context=".MainActivity">
    <item android:id="@+id/action_settings"
          android:title="@string/github"
          android:orderInCategory="100"
          app:showAsAction="never"/>
</menu>


================================================
FILE: app/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
</resources>


================================================
FILE: app/src/main/res/values/dimens.xml
================================================
<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="fab_margin">16dp</dimen>
</resources>


================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">RxFace</string>
    <string name="action_settings">Settings</string>
    <string name="github">Github</string>
    <string name="reconginze_get">Get识别</string>
    <string name="reconginze_post">Post识别</string>
</resources>


================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>

</resources>


================================================
FILE: app/src/main/res/values-v21/styles.xml
================================================
<resources>>
    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>


================================================
FILE: app/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
    <!-- Example customization of dimensions originally defined in res/values/dimens.xml
         (such as screen margins) for screens with more than 820dp of available width. This
         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
    <dimen name="activity_horizontal_margin">64dp</dimen>
</resources>


================================================
FILE: app/src/test/java/mrfu/face/ExampleUnitTest.java
================================================
package mrfu.face;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * To work on unit tests, switch the Test Artifact in the Build Variants view.
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
//        classpath 'me.tatarka:gradle-retrolambda:3.2.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Tue Dec 15 21:05:14 CST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip


================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

================================================
FILE: gradlew
================================================
#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
    echo "$*"
}

die ( ) {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: sdk_unuse/HttpRequests.java
================================================
package mrfu.face.sdk;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;

import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.StringBody;
import org.json.JSONException;
import org.json.JSONObject;

import com.facepp.error.FaceppParseException;

/**
 * request to faceplusplus.com<br />
 * {@code new HttpRequests(apiKey, apiSecret).request("detection", "detect", postParameters)}<br />
 * 
 * {@code new HttpRequests(apiKey, apiSecret).train()}
 * @author moon5ckq
 * @since 1.0.0
 * @version 1.3.0
 */
public class HttpRequests {
	
	static final private String WEBSITE_CN = "https://apicn.faceplusplus.com/v2/";
	static final private String DWEBSITE_CN = "http://apicn.faceplusplus.com/v2/";
	static final private String WEBSITE_US = "https://apius.faceplusplus.com/v2/";
	static final private String DWEBSITE_US = "http://apius.faceplusplus.com/v2/";
	 
	static final private int BUFFERSIZE = 1048576;
	static final private int TIMEOUT = 30000;
	static final private int SYNC_TIMEOUT = 60000;
	
	private String webSite;
	private String apiKey, apiSecret;
	private PostParameters params;
	private int httpTimeOut = TIMEOUT;
	
	
	/**
	 * default is 30 sec
	 * set http timeout limit (million second)
	 * @param timeOut
	 */
	public void setHttpTimeOut(int timeOut) {
		this.httpTimeOut = timeOut;
	}
	
	/**
	 * (million second)
	 * @return http timeout limit
	 */
	public int getHttpTimeOut() {
		return this.httpTimeOut;
	}
	
	/**
	 * @return api_key
	 */
	public String getApiKey() {
		return apiKey;
	}

	/**
	 * @param apiKey
	 */
	public void setApiKey(String apiKey) {
		this.apiKey = apiKey;
	}

	/**
	 * @return api_secret
	 */
	public String getApiSecret() {
		return apiSecret;
	}

	/**
	 * @param apiSecret
	 */
	public void setApiSecret(String apiSecret) {
		this.apiSecret = apiSecret;
	}
	
	/**
	 * if isCN is true, then use AliCloud, false to Amazon<br />
	 * if isDebug is true, then use http, otherwise https
	 * @param isCN
	 * @param isDebug
	 */
	public void setWebSite(boolean isCN, boolean isDebug) {
		if (isCN && isDebug) webSite = DWEBSITE_CN;
		else if (isCN && !isDebug) webSite = WEBSITE_CN;
		else if (!isCN && isDebug) webSite = DWEBSITE_US;
		else if (!isCN && !isDebug) webSite = WEBSITE_US;
	}
	
	/**
	 * @return a webSite clone
	 */
	public String getWebSite() {
		return new String(webSite);
	}

	/**
	 * {@link #request(String, String, PostParameters)}<br />
	 * faceplusplus.com/[control]/[action]<br />
	 * default use parameters which {@link #getParams}
	 * @param control
	 * @param action
	 * @return a result object
	 */
	public JSONObject request(String control, String action) throws FaceppParseException {
		return request(control, action, getParams());
	}
	

	/**
	 * default timeout time is 1 minute
	 * @param sessionId
	 * @return the getSession Result
	 * @throws FaceppParseException
	 */
	public JSONObject getSessionSync(String sessionId) throws FaceppParseException {
		return getSessionSync(sessionId, SYNC_TIMEOUT);
	}
	
	/**
	 * timeout time is [timeOut]ms, the method is synchronized.
	 * @param sessionId
	 * @param timeOut
	 * @return the getSession Result
	 * @throws FaceppParseException
	 */
	public JSONObject getSessionSync(String sessionId, long timeOut) throws FaceppParseException {
		final StringBuilder sb = new StringBuilder();
		long t = new Date().getTime() + timeOut;
		while (true) {
			JSONObject rst =  HttpRequests.this.request("info", "get_session", new PostParameters().setSessionId(sessionId));
			try {
				if (rst.getString("status").equals("SUCC")) {
					sb.append(rst.toString());
					break;
				} else if (rst.getString("status").equals("INVALID_SESSION")) {
					sb.append("INVALID_SESSION");
					break;
				}
			} catch (JSONException e) {
				sb.append("Unknow error.");
				break;
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				sb.append("Thread.sleep error.");
				break;
			}
			if (new Date().getTime() >= t) {
				sb.append("Time Out");
				break;
			}
		}
		
		String rst = sb.toString();
		if (rst.equals("INVALID_SESSION")) {
			throw new FaceppParseException("Invaild session, unknow error.");
		} else if (rst.equals("Unknow error.")) {
			throw new FaceppParseException("Unknow error.");
		} else if (rst.equals("Thread.sleep error.")) {
			throw new FaceppParseException("Thread.sleep error.");
		} else if (rst.equals("Time Out")) {
			throw new FaceppParseException("Get session time out.");
		} else {
			try {
				JSONObject result = new JSONObject(rst);
				result.put("response_code", 200);
				return result;
			} catch (JSONException e) {
			}
		}
		
		return null;
	}
	
	/**
	 * faceplusplus.com/[control]/[action]?[params]<br />
	 * http request timeout time is 5000ms
	 * @param control
	 * @param action
	 * @param params
	 * @return a result object
	 * @throws FaceppParseException
	 */
	public JSONObject request(String control, String action, PostParameters params) throws FaceppParseException {
		URL url;
		HttpURLConnection urlConn = null;
		try {
			url = new URL(webSite+control+"/"+action);
			urlConn = (HttpURLConnection) url.openConnection();
	        urlConn.setRequestMethod("POST");
	        urlConn.setConnectTimeout(httpTimeOut);
	        urlConn.setReadTimeout(httpTimeOut);
	        urlConn.setDoOutput(true);

	        urlConn.setRequestProperty("connection", "keep-alive");
	        urlConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + params.boundaryString());
			
	        MultipartEntity reqEntity =params.getMultiPart();

            reqEntity.addPart("api_key", new StringBody(apiKey));
            reqEntity.addPart("api_secret", new StringBody(apiSecret));

            reqEntity.writeTo(urlConn.getOutputStream());

            String resultString = null;
            if (urlConn.getResponseCode() == 200)
            	resultString = readString(urlConn.getInputStream());
            else
            	resultString = readString(urlConn.getErrorStream());
            //FaceppResult result = new FaceppResult( new JSONObject(resultString), urlConn.getResponseCode());

            JSONObject result = new JSONObject(resultString);
            if (result.has("error")) {

            	if (result.getString("error").equals("API not found"))
            		throw new FaceppParseException("API not found");

            	throw new FaceppParseException("API error.", result.getInt("error_code"),
            			result.getString("error"), urlConn.getResponseCode());
            }
            result.put("response_code", urlConn.getResponseCode());
            urlConn.getInputStream().close();

            return result;
		} catch (Exception e) {			throw new FaceppParseException("error :" + e.toString());

		} finally {			if (urlConn != null)
				urlConn.disconnect();

		}
	}
	
	private static String readString(InputStream is) {
		StringBuffer rst = new StringBuffer();
		
		byte[] buffer = new byte[BUFFERSIZE];
		int len = 0;
		
		try {
			while ((len = is.read(buffer)) > 0)
				for (int i = 0; i < len; ++i)
					rst.append((char)buffer[i]);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return rst.toString();
	}
	
	/**
	 * create {@link HttpRequests} <br />
	 * api_key=...,api_secret=... <br />
	 * use https and AliCloud default
	 * @param apiKey
	 * @param apiSecret
	 */
	public HttpRequests(String apiKey, String apiSecret) {
		super();
		this.apiKey = apiKey;
		this.apiSecret = apiSecret;
		this.webSite = WEBSITE_CN;
	}

	/**
	 * use https default
	 * create a empty {@link HttpRequests} object
	 */
	public HttpRequests() {
		super();
	}
	
	/**
	 * create {@link HttpRequests} <br />
	 * api_key=...,api_secret=...<br />
	 * the isCN and isDebug use like {@link setWebSite}}
	 * @param apiKey
	 * @param apiSecret
	 * @param isCN
	 * @param isDebug
	 */
	public HttpRequests(String apiKey, String apiSecret, boolean isCN, boolean isDebug) {
		super();
		this.apiKey = apiKey;
		this.apiSecret = apiSecret;
		setWebSite(isCN, isDebug);
	}
	
	/**
	 * @return {@link PostParameters} object
	 */
	public PostParameters getParams() {
		if (params == null) params = new PostParameters();
		return params;
	}
	
	/**
	 * set default PostParameters
	 * @param params
	 */
	public void setParams(PostParameters params) {
		this.params = params;
	}
	
	/**
	 * used by offline detect
	 * example: request.offlineDetect(detecter.getImageByteArray(), detecter.getResultJsonString());
	 * @param image
	 * @param jsonResult
	 * @return
	 * @throws FaceppParseException
	 */
	public JSONObject offlineDetect(byte[] image, String jsonResult) throws FaceppParseException {
		return offlineDetect(image, jsonResult, this.params);
	}
	/**
	 * used by offline detect
	 * example: request.offlineDetect(detecter.getImageByteArray(), detecter.getResultJsonString(), params);
	 * @param image
	 * @param jsonResult
	 * @param params
	 * @return
	 * @throws FaceppParseException
	 */
	public JSONObject offlineDetect(byte[] image, String jsonResult, PostParameters params) throws FaceppParseException{
		if (params == null) params = new PostParameters();
		params.setImg(image);
		params.setMode("offline");
		params.addAttribute("offline_result", jsonResult);
		return request("detection", "detect", params);
	}
	
	//all api here
	public JSONObject detectionDetect() throws FaceppParseException {
		return request("detection", "detect");
	}
	public JSONObject detectionDetect(PostParameters params) throws FaceppParseException{
		return request("detection", "detect", params);
	}
	
	public JSONObject detectionLandmark() throws FaceppParseException {
		return request("detection", "landmark");
	}
	public JSONObject detectionLandmark(PostParameters params) throws FaceppParseException{
		return request("detection", "landmark", params);
	}

	public JSONObject trainVerify() throws FaceppParseException {
		return request("train", "verify");
	}
	public JSONObject trainVerify(PostParameters params) throws FaceppParseException{
		return request("train", "verify", params);
	}

	public JSONObject trainSearch() throws FaceppParseException {
		return request("train", "search");
	}
	public JSONObject trainSearch(PostParameters params) throws FaceppParseException{
		return request("train", "search", params);
	}

	public JSONObject trainIdentify() throws FaceppParseException {
		return request("train", "identify");
	}
	public JSONObject trainIdentify(PostParameters params) throws FaceppParseException{
		return request("train", "identify", params);
	}

	public JSONObject recognitionCompare() throws FaceppParseException {
		return request("recognition", "compare");
	}
	public JSONObject recognitionCompare(PostParameters params) throws FaceppParseException{
		return request("recognition", "compare", params);
	}

	public JSONObject recognitionVerify() throws FaceppParseException {
		return request("recognition", "verify");
	}
	public JSONObject recognitionVerify(PostParameters params) throws FaceppParseException{
		return request("recognition", "verify", params);
	}

	public JSONObject recognitionSearch() throws FaceppParseException {
		return request("recognition", "search");
	}
	public JSONObject recognitionSearch(PostParameters params) throws FaceppParseException{
		return request("recognition", "search", params);
	}

	public JSONObject recognitionIdentify() throws FaceppParseException {
		return request("recognition", "identify");
	}
	public JSONObject recognitionIdentify(PostParameters params) throws FaceppParseException{
		return request("recognition", "identify", params);
	}

	public JSONObject groupingGrouping() throws FaceppParseException {
		return request("grouping", "grouping");
	}
	public JSONObject groupingGrouping(PostParameters params) throws FaceppParseException{
		return request("grouping", "grouping", params);
	}

	public JSONObject personCreate() throws FaceppParseException {
		return request("person", "create");
	}
	public JSONObject personCreate(PostParameters params) throws FaceppParseException{
		return request("person", "create", params);
	}

	public JSONObject personDelete() throws FaceppParseException {
		return request("person", "delete");
	}
	public JSONObject personDelete(PostParameters params) throws FaceppParseException{
		return request("person", "delete", params);
	}

	public JSONObject personAddFace() throws FaceppParseException {
		return request("person", "add_face");
	}
	public JSONObject personAddFace(PostParameters params) throws FaceppParseException{
		return request("person", "add_face", params);
	}

	public JSONObject personRemoveFace() throws FaceppParseException {
		return request("person", "remove_face");
	}
	public JSONObject personRemoveFace(PostParameters params) throws FaceppParseException{
		return request("person", "remove_face", params);
	}

	public JSONObject personSetInfo() throws FaceppParseException {
		return request("person", "set_info");
	}
	public JSONObject personSetInfo(PostParameters params) throws FaceppParseException{
		return request("person", "set_info", params);
	}

	public JSONObject personGetInfo() throws FaceppParseException {
		return request("person", "get_info");
	}
	public JSONObject personGetInfo(PostParameters params) throws FaceppParseException{
		return request("person", "get_info", params);
	}

	public JSONObject facesetCreate() throws FaceppParseException {
		return request("faceset", "create");
	}
	public JSONObject facesetCreate(PostParameters params) throws FaceppParseException{
		return request("faceset", "create", params);
	}

	public JSONObject facesetDelete() throws FaceppParseException {
		return request("faceset", "delete");
	}
	public JSONObject facesetDelete(PostParameters params) throws FaceppParseException{
		return request("faceset", "delete", params);
	}

	public JSONObject facesetAddFace() throws FaceppParseException {
		return request("faceset", "add_face");
	}
	public JSONObject facesetAddFace(PostParameters params) throws FaceppParseException{
		return request("faceset", "add_face", params);
	}

	public JSONObject facesetRemoveFace() throws FaceppParseException {
		return request("faceset", "remove_face");
	}
	public JSONObject facesetRemoveFace(PostParameters params) throws FaceppParseException{
		return request("faceset", "remove_face", params);
	}

	public JSONObject facesetSetInfo() throws FaceppParseException {
		return request("faceset", "set_info");
	}
	public JSONObject facesetSetInfo(PostParameters params) throws FaceppParseException{
		return request("faceset", "set_info", params);
	}

	public JSONObject facesetGetInfo() throws FaceppParseException {
		return request("faceset", "get_info");
	}
	public JSONObject facesetGetInfo(PostParameters params) throws FaceppParseException{
		return request("faceset", "get_info", params);
	}

	public JSONObject groupCreate() throws FaceppParseException {
		return request("group", "create");
	}
	public JSONObject groupCreate(PostParameters params) throws FaceppParseException{
		return request("group", "create", params);
	}

	public JSONObject groupDelete() throws FaceppParseException {
		return request("group", "delete");
	}
	public JSONObject groupDelete(PostParameters params) throws FaceppParseException{
		return request("group", "delete", params);
	}

	public JSONObject groupAddPerson() throws FaceppParseException {
		return request("group", "add_person");
	}
	public JSONObject groupAddPerson(PostParameters params) throws FaceppParseException{
		return request("group", "add_person", params);
	}

	public JSONObject groupRemovePerson() throws FaceppParseException {
		return request("group", "remove_person");
	}
	public JSONObject groupRemovePerson(PostParameters params) throws FaceppParseException{
		return request("group", "remove_person", params);
	}

	public JSONObject groupSetInfo() throws FaceppParseException {
		return request("group", "set_info");
	}
	public JSONObject groupSetInfo(PostParameters params) throws FaceppParseException{
		return request("group", "set_info", params);
	}

	public JSONObject groupGetInfo() throws FaceppParseException {
		return request("group", "get_info");
	}
	public JSONObject groupGetInfo(PostParameters params) throws FaceppParseException{
		return request("group", "get_info", params);
	}

	public JSONObject infoGetImage() throws FaceppParseException {
		return request("info", "get_image");
	}
	public JSONObject infoGetImage(PostParameters params) throws FaceppParseException{
		return request("info", "get_image", params);
	}

	public JSONObject infoGetFace() throws FaceppParseException {
		return request("info", "get_face");
	}
	public JSONObject infoGetFace(PostParameters params) throws FaceppParseException{
		return request("info", "get_face", params);
	}

	public JSONObject infoGetPersonList() throws FaceppParseException {
		return request("info", "get_person_list");
	}
	public JSONObject infoGetPersonList(PostParameters params) throws FaceppParseException{
		return request("info", "get_person_list", params);
	}

	public JSONObject infoGetFacesetList() throws FaceppParseException {
		return request("info", "get_faceset_list");
	}
	public JSONObject infoGetFacesetList(PostParameters params) throws FaceppParseException{
		return request("info", "get_faceset_list", params);
	}

	public JSONObject infoGetGroupList() throws FaceppParseException {
		return request("info", "get_group_list");
	}
	public JSONObject infoGetGroupList(PostParameters params) throws FaceppParseException{
		return request("info", "get_group_list", params);
	}

	public JSONObject infoGetSession() throws FaceppParseException {
		return request("info", "get_session");
	}
	public JSONObject infoGetSession(PostParameters params) throws FaceppParseException{
		return request("info", "get_session", params);
	}

	/**
	 * @deprecated this api is deprecated
	 * @return
	 * @throws FaceppParseException
	 */
	public JSONObject infoGetQuota() throws FaceppParseException {
		return request("info", "get_quota");
	}
	/**
	 * @deprecated this api is deprecated
	 * @return
	 * @throws FaceppParseException
	 */
	public JSONObject infoGetQuota(PostParameters params) throws FaceppParseException{
		return request("info", "get_quota", params);
	}

	public JSONObject infoGetApp() throws FaceppParseException {
		return request("info", "get_app");
	}
	public JSONObject infoGetApp(PostParameters params) throws FaceppParseException{
		return request("info", "get_app", params);
	}

}


================================================
FILE: sdk_unuse/MainActivity.java
================================================
package mrfu.face.sdk;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.provider.MediaStore.Images.ImageColumns;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.facepp.error.FaceppParseException;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;

import mrfu.face.R;

/**
 * A simple demo, get a picture form your phone<br />
 * Use the facepp api to detect<br />
 * Find all face on the picture, and mark them out.
 * @author moon5ckq
 */
public class MainActivity extends Activity {

	final private static String TAG = "MainActivity";
	final private int PICTURE_CHOOSE = 1;
	
	private ImageView imageView = null;
	private Bitmap img = null;
	private Button buttonDetect = null;
	private TextView textView = null;
	
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
//        Button button = (Button)this.findViewById(R.id.button1);
//        button.setOnClickListener(new OnClickListener() {
//			
//			public void onClick(View arg0) {
//				//get a picture form your phone
//				Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
//		        photoPickerIntent.setType("image/*");
//		        startActivityForResult(photoPickerIntent, PICTURE_CHOOSE);
//			}
//		});
        
//        textView = (TextView)this.findViewById(R.id.textView1);
        
//        buttonDetect = (Button)this.findViewById(R.id.button2);
        buttonDetect.setVisibility(View.INVISIBLE);
        buttonDetect.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				
				textView.setText("Waiting ...");
				
				FaceppDetect faceppDetect = new FaceppDetect();
				faceppDetect.setDetectCallback(new DetectCallback() {
					
					public void detectResult(JSONObject rst) {
						//Log.v(TAG, rst.toString());
						
						//use the red paint
						Paint paint = new Paint();
						paint.setColor(Color.RED);
						paint.setStrokeWidth(Math.max(img.getWidth(), img.getHeight()) / 100f);

						//create a new canvas
						Bitmap bitmap = Bitmap.createBitmap(img.getWidth(), img.getHeight(), img.getConfig());
						Canvas canvas = new Canvas(bitmap);
						canvas.drawBitmap(img, new Matrix(), null);
						
						
						try {
							//find out all faces
							final int count = rst.getJSONArray("face").length();
							for (int i = 0; i < count; ++i) {
								float x, y, w, h;
								//get the center point
								x = (float)rst.getJSONArray("face").getJSONObject(i)
										.getJSONObject("position").getJSONObject("center").getDouble("x");
								y = (float)rst.getJSONArray("face").getJSONObject(i)
										.getJSONObject("position").getJSONObject("center").getDouble("y");

								//get face size
								w = (float)rst.getJSONArray("face").getJSONObject(i)
										.getJSONObject("position").getDouble("width");
								h = (float)rst.getJSONArray("face").getJSONObject(i)
										.getJSONObject("position").getDouble("height");
								
								//change percent value to the real size
								x = x / 100 * img.getWidth();
								w = w / 100 * img.getWidth() * 0.7f;
								y = y / 100 * img.getHeight();
								h = h / 100 * img.getHeight() * 0.7f;

								//draw the box to mark it out
								canvas.drawLine(x - w, y - h, x - w, y + h, paint);
								canvas.drawLine(x - w, y - h, x + w, y - h, paint);
								canvas.drawLine(x + w, y + h, x - w, y + h, paint);
								canvas.drawLine(x + w, y + h, x + w, y - h, paint);
							}
							
							//save new image
							img = bitmap;

							MainActivity.this.runOnUiThread(new Runnable() {
								
								public void run() {
									//show the image
									imageView.setImageBitmap(img);
									textView.setText("Finished, "+ count + " faces.");
								}
							});
							
						} catch (JSONException e) {
							e.printStackTrace();
							MainActivity.this.runOnUiThread(new Runnable() {
								public void run() {
									textView.setText("Error.");
								}
							});
						}
						
					}
				});
				faceppDetect.detect(img);
			}
		});
        
//        imageView = (ImageView)this.findViewById(R.id.imageView1);
        imageView.setImageBitmap(img);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
//        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    	super.onActivityResult(requestCode, resultCode, intent);
    	
    	//the image picker callback
    	if (requestCode == PICTURE_CHOOSE) {
    		if (intent != null) {
    			//The Android api ~~~ 
    			//Log.d(TAG, "idButSelPic Photopicker: " + intent.getDataString());
    			Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null);
    			cursor.moveToFirst();
    			int idx = cursor.getColumnIndex(ImageColumns.DATA);
    			String fileSrc = cursor.getString(idx); 
    			//Log.d(TAG, "Picture:" + fileSrc);
    			
    			//just read size
    			Options options = new Options();
    			options.inJustDecodeBounds = true;
    			img = BitmapFactory.decodeFile(fileSrc, options);

    			//scale size to read
    			options.inSampleSize = Math.max(1, (int)Math.ceil(Math.max((double)options.outWidth / 1024f, (double)options.outHeight / 1024f)));
    			options.inJustDecodeBounds = false;
    			img = BitmapFactory.decodeFile(fileSrc, options);
    			textView.setText("Clik Detect. ==>");
    			
    			
    			imageView.setImageBitmap(img);
    			buttonDetect.setVisibility(View.VISIBLE);
    		}
    		else {
    			Log.d(TAG, "idButSelPic Photopicker canceled");
    		}
    	}
    }

    private class FaceppDetect {
    	DetectCallback callback = null;
    	
    	public void setDetectCallback(DetectCallback detectCallback) { 
    		callback = detectCallback;
    	}

    	public void detect(final Bitmap image) {
    		
    		new Thread(new Runnable() {
				
				public void run() {
					HttpRequests httpRequests = new HttpRequests("4480afa9b8b364e30ba03819f3e9eff5", "Pz9VFT8AP3g_Pz8_dz84cRY_bz8_Pz8M", true, false);
		    		//Log.v(TAG, "image size : " + img.getWidth() + " " + img.getHeight());
		    		
		    		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		    		float scale = Math.min(1, Math.min(600f / img.getWidth(), 600f / img.getHeight()));
		    		Matrix matrix = new Matrix();
		    		matrix.postScale(scale, scale);

		    		Bitmap imgSmall = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, false);
		    		//Log.v(TAG, "imgSmall size : " + imgSmall.getWidth() + " " + imgSmall.getHeight());
		    		
		    		imgSmall.compress(Bitmap.CompressFormat.JPEG, 100, stream);
		    		byte[] array = stream.toByteArray();
		    		
		    		try {
		    			//detect
						JSONObject result = httpRequests.detectionDetect(new PostParameters().setImg(array));
						//finished , then call the callback function
						if (callback != null) {
							callback.detectResult(result);
						}
					} catch (FaceppParseException e) {
						e.printStackTrace();
						MainActivity.this.runOnUiThread(new Runnable() {
							public void run() {
								textView.setText("Network error.");
							}
						});
					}
					
				}
			}).start();
    	}
    }

    interface DetectCallback {
    	void detectResult(JSONObject rst);
	}
}


================================================
FILE: sdk_unuse/PostParameters.java
================================================
package mrfu.face.sdk;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Random;

import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;

/**
 * Http Multipart<br />
 * {@code new PostParameters().setMode("oneface").setImg(new File("...")).setTag("some message")}
 * @author moon5kcq
 * @since 1.0.0
 * @version 1.3.0
 */
public class PostParameters {
	private MultipartEntity multiPart = null;
	private final static int boundaryLength = 32;
	private final static String boundaryAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
	private String boundary;
	
	/**
	 * auto generate boundary string
	 * @return a boundary string
	 */
	private String getBoundary() {
		StringBuilder sb = new StringBuilder();
		Random random = new Random();
		for (int i = 0; i < boundaryLength; ++i)
			sb.append(boundaryAlphabet.charAt(random.nextInt(boundaryAlphabet.length())));
		return sb.toString();
	}
	
	/**
	 * @return get MultipartEntity (apache)
	 */
	public MultipartEntity getMultiPart() {
		return multiPart;
	}
	
	/**
	 * default boundary is auto generate {@link #getBoundary()}
	 */
	public PostParameters() {
		super();
		boundary = getBoundary();
		multiPart = new MultipartEntity(HttpMultipartMode.STRICT , boundary,  Charset.forName("UTF-8"));
	}
	
	/**
	 * @return multipart boundary string
	 */
	public String boundaryString() {
		return boundary;
	}
	
	/**
	 * async=true|false
	 * @param flag
	 * @return this
	 */
	public PostParameters setAsync(boolean flag) {
		addString("async", ""+flag);
		return this;
	}
	
	/**
	 * url=...
	 * @param url
	 * @return this
	 */
	public PostParameters setUrl(String url){
		addString("url", url);
		return this;
	}
	
	/**
	 * attribute = gender | age | race | all | none
	 * @param type
	 * @return this
	 */
	public PostParameters setAttribute(String type){
		addString("attribute", type);
		return this;
	}
	
	/**
	 * tag=...
	 * @param tag
	 * @return this
	 */
	public PostParameters setTag(String tag){
		addString("tag", tag);
		return this;
	}
	
	/**
	 * img=...
	 * @param file
	 * @return this
	 */
	public PostParameters setImg(File file) {
		multiPart.addPart("img", new FileBody(file));
		return this;
	}
	
	/**
	 * img=...
	 * @param data
	 * @return this
	 */
	public PostParameters setImg(byte[] data) {
		setImg(data, "NoName");
		return this;
	}
	
	/**
	 * img=...(name in multipart is ...)
	 * @param data
	 * @param fileName
	 * @return this
	 */
	public PostParameters setImg(byte[] data, String fileName) {
		multiPart.addPart("img", new ByteArrayBody(data, fileName));
		return this;
	}
	
	/**
	 * face_id1=...
	 * @param id
	 * @return this
	 */
	public PostParameters setFaceId1(String id){
		addString("face_id1", id);
		return this;
	}
	
	/**
	 * face_id2=...
	 * @param id
	 * @return this
	 */
	public PostParameters setFaceId2(String id){
		addString("face_id2", id);
		return this;
	}
	
	/**
	 * group_name=...
	 * @param groupName
	 * @return this
	 */
	public PostParameters setGroupName(String groupName){
		addString("group_name", groupName);
		return this;
	}
	
	/**
	 * group_id=...
	 * @param groupId
	 * @return this
	 */
	public PostParameters setGroupId(String groupId){
		addString("group_id", groupId);
		return this;
	}
	
	/**
	 * key_face_id=...
	 * @param id
	 * @return this
	 */
	public PostParameters setKeyFaceId(String id){
		addString("key_face_id", id);
		return this;
	}
	
	/**
	 * count=...
	 * @param count
	 * @return this
	 */
	public PostParameters setCount(int count) {
		addString("count", new Integer(count).toString());
		return this;
	}
	
	/**
	 * type= all | search | recognize
	 * @param type
	 * @return this
	 */
	public PostParameters setType(String type) {
		addString("type", type);
		return this;
	}
	
	/**
	 * face_id=...
	 * @param faceId
	 * @return this
	 */
	public PostParameters setFaceId(String faceId) {
		addString("face_id", faceId);
		return this;
	}
	
	/**
	 * faceset_id=...
	 * @param facesetId
	 * @return this
	 */
	public PostParameters setFacesetId(String facesetId) {
		addString("faceset_id", facesetId);
		return this;
	}
	
	/**
	 * faceset_id=..., ..., ...
	 * @param facesetIds
	 * @return this
	 */
	public PostParameters setFacesetId(String[] facesetId) {
		setFacesetId(toStringList(facesetId));
		return this;
	}
	
	/**
	 * faceset_id=...
	 * @param facesetIds
	 * @return this
	 */
	public PostParameters setFacesetId(ArrayList<String> facesetId) {
		setFacesetId(toStringList(facesetId));
		return this;
	}
	
	/**
	 * person_id=...
	 * @param personId
	 * @return this
	 */
	public PostParameters setPersonId(String personId) {
		addString("person_id", personId);
		return this;
	}
	
	/**
	 * person_name=...
	 * @param personName
	 * @return this
	 */
	public PostParameters setPersonName(String personName) {
		addString("person_name", personName);
		return this;
	}
		
	/**
	 * name=...
	 * @param name
	 * @return this
	 */
	public PostParameters setName(String name) {
		addString("name", name);
		return this;
	}
	
	/**
	 * session_id=...
	 * @param id
	 * @return this
	 */
	public PostParameters setSessionId(String id) {
		addString("session_id", id);
		return this;
	}
	
	/**
	 * mode= oneface | normal
	 * @param type
	 * @return this
	 */
	public PostParameters setMode(String type) {
		addString("mode", type);
		return this;
	}
	
	
	/**
	 * face_id=... , ... , ...
	 * @param faceIds
	 * @return this
	 */
	public PostParameters setFaceId(String[] faceIds) {
		return setFaceId(toStringList(faceIds));
	}
	/**
	 * person_id=... , ... , ...
	 * @param personIds
	 * @return this
	 */
	public PostParameters setPersonId(String[] personIds) {
		return setPersonId(toStringList(personIds));
	}
	/**
	 * person_name=... , ... , ...
	 * @param personNames
	 * @return this
	 */
	public PostParameters setPersonName(String[] personNames) {
		return setPersonName(toStringList(personNames));
	}
	/**
	 * group_id=... , ... , ...
	 * @param groupIds
	 * @return this
	 */
	public PostParameters setGroupId(String[] groupIds) {
		return setGroupId(toStringList(groupIds));
	}
	/**
	 * group_name=... , ... , ...
	 * @param groupNames
	 * @return this
	 */
	public PostParameters setGroupName(String[] groupNames) {
		return setGroupName(toStringList(groupNames));
	}
	
	/**
	 * face=... , ... , ...
	 * @param faceIds
	 * @return this
	 */
	public PostParameters setFaceId(ArrayList<String> faceIds) {
		return setFaceId(toStringList(faceIds));
	}
	/**
	 * person_id=... , ... , ...
	 * @param personIds
	 * @return this
	 */
	public PostParameters setPersonId(ArrayList<String> personIds) {
		return setPersonId(toStringList(personIds));
	}
	/**
	 * person_name=... , ... , ...
	 * @param personNames
	 * @return this
	 */
	public PostParameters setPersonName(ArrayList<String> personNames) {
		return setPersonName(toStringList(personNames));
	}
	/**
	 * group_id=... , ... , ...
	 * @param groupIds
	 * @return this
	 */
	public PostParameters setGroupId(ArrayList<String> groupIds) {
		return  setGroupId(toStringList(groupIds));
	}
	/**
	 * group_name=... , ... , ...
	 * @param groupNames
	 * @return this
	 */
	public PostParameters setGroupName(ArrayList<String> groupNames) {
		return setGroupName(toStringList(groupNames));
	}
	
	/**
	 * img_id=...
	 * @param imgId
	 * @return this
	 */
	public PostParameters setImgId(String imgId) {
		addString("img_id", imgId);
		return this;
	}
	
	/**
	 * faceset_name=...
	 * @param facesetName
	 * @return this
	 */
	public PostParameters setFacesetName(String facesetName) {
		addString("faceset_name", facesetName);
		return this;
	}
	
	/**
	 * faceset_name=... , ... , ...
	 * @param facesetNames
	 * @return this
	 */
	public PostParameters setFacesetName(ArrayList<String> facesetNames) {
		return setFacesetName(toStringList(facesetNames));
	}
	/**
	 * faceset_name=... , ... , ...
	 * @param facesetNames
	 * @return this
	 */
	public PostParameters setFacesetName(String[] facesetNames) {
		return setFacesetName(toStringList(facesetNames));
	}
	
	/**
	 * `attr`=`value`
	 * @param attr value
	 * @return this
	 */
	public PostParameters addAttribute(String attr, String value) {
		addString(attr, value);
		return this;
	}
	
	private void addString(String id, String str) {
		try {
			multiPart.addPart(id, new StringBody(str, Charset.forName("UTF-8")));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
	
	private String toStringList(String[] sa) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < sa.length; ++i) {
			if (i != 0) sb.append(',');
			sb.append(sa[i]);
		}
		
		return sb.toString();
	}
	
	private String toStringList(ArrayList<String> sa) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < sa.size(); ++i) {
			if (i != 0) sb.append(',');
			sb.append(sa.get(i));
		}
		
		return sb.toString();
	}
}


================================================
FILE: settings.gradle
================================================
include ':app'
Download .txt
gitextract_nz7e2i3v/

├── .gitignore
├── .idea/
│   ├── .name
│   ├── compiler.xml
│   ├── copyright/
│   │   └── profiles_settings.xml
│   ├── gradle.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── runConfigurations.xml
│   └── vcs.xml
├── Face.iml
├── README.md
├── RxFace.iml
├── app/
│   ├── .gitignore
│   ├── app.iml
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── mrfu/
│       │           └── face/
│       │               └── ApplicationTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── mrfu/
│       │   │       └── rxface/
│       │   │           ├── AppApplication.java
│       │   │           ├── BaseActivity.java
│       │   │           ├── MainActivity.java
│       │   │           ├── business/
│       │   │           │   ├── Constants.java
│       │   │           │   └── DealData.java
│       │   │           ├── loader/
│       │   │           │   ├── ExecutorManager.java
│       │   │           │   ├── FaceApi.java
│       │   │           │   ├── SchedulersCompat.java
│       │   │           │   ├── WebServiceException.java
│       │   │           │   └── custom/
│       │   │           │       ├── AsciiTypeString.java
│       │   │           │       ├── CustomMultipartTypedOutput.java
│       │   │           │       └── CustomTypedByteArray.java
│       │   │           └── models/
│       │   │               ├── BaseResponse.java
│       │   │               ├── FaceResponse.java
│       │   │               └── NeedDataEntity.java
│       │   └── res/
│       │       ├── layout/
│       │       │   ├── activity_main.xml
│       │       │   └── content_main.xml
│       │       ├── menu/
│       │       │   └── menu_main.xml
│       │       ├── values/
│       │       │   ├── colors.xml
│       │       │   ├── dimens.xml
│       │       │   ├── strings.xml
│       │       │   └── styles.xml
│       │       ├── values-v21/
│       │       │   └── styles.xml
│       │       └── values-w820dp/
│       │           └── dimens.xml
│       └── test/
│           └── java/
│               └── mrfu/
│                   └── face/
│                       └── ExampleUnitTest.java
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sdk_unuse/
│   ├── HttpRequests.java
│   ├── MainActivity.java
│   └── PostParameters.java
└── settings.gradle
Download .txt
SYMBOL INDEX (244 symbols across 20 files)

FILE: app/src/androidTest/java/mrfu/face/ApplicationTest.java
  class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
    method ApplicationTest (line 10) | public ApplicationTest() {

FILE: app/src/main/java/mrfu/rxface/AppApplication.java
  class AppApplication (line 9) | public class AppApplication extends Application {
    method getContext (line 13) | public static Context getContext() {
    method onCreate (line 17) | @Override

FILE: app/src/main/java/mrfu/rxface/BaseActivity.java
  class BaseActivity (line 13) | public class BaseActivity extends AppCompatActivity {
    method onCreate (line 15) | @Override
    method setContentView (line 20) | @Override
    method onDestroy (line 26) | @Override

FILE: app/src/main/java/mrfu/rxface/MainActivity.java
  class MainActivity (line 37) | public class MainActivity extends BaseActivity {
    method onCreate (line 63) | @Override
    method btn_recongize_get (line 75) | @OnClick(R.id.btn_recongize_get)
    method btn_recongize_post (line 105) | @OnClick(R.id.btn_recongize_post)
    method onNext (line 127) | @Override
    method onCompleted (line 154) | @Override
    method onError (line 159) | @Override
    method onCreateOptionsMenu (line 165) | @Override
    method onOptionsItemSelected (line 172) | @Override

FILE: app/src/main/java/mrfu/rxface/business/Constants.java
  class Constants (line 6) | public class Constants {

FILE: app/src/main/java/mrfu/rxface/business/DealData.java
  class DealData (line 19) | public class DealData {
    method mulipartData (line 35) | public static CustomMultipartTypedOutput mulipartData(Bitmap bitmap, S...
    method getBitmapByte (line 49) | private static byte[] getBitmapByte(Bitmap bitmap){
    method drawLineGetBitmap (line 65) | public static Bitmap drawLineGetBitmap(FaceResponse entity, Bitmap vie...
    method getDisplayInfo (line 107) | public static String getDisplayInfo(FaceResponse entity){

FILE: app/src/main/java/mrfu/rxface/loader/ExecutorManager.java
  class ExecutorManager (line 20) | public class ExecutorManager {
    method newThread (line 33) | public Thread newThread(@NonNull Runnable r) {
    method getCountOfCPU (line 54) | public static int getCountOfCPU() {
    method accept (line 69) | @Override public boolean accept(File pathname) {

FILE: app/src/main/java/mrfu/rxface/loader/FaceApi.java
  class FaceApi (line 27) | public class FaceApi {
    method getIns (line 34) | public static FaceApi getIns() {
    method FaceApi (line 47) | public FaceApi() {
    method intercept (line 59) | @Override
    method getBoundary (line 66) | public String getBoundary(){
    method setBoundary (line 75) | private static String setBoundary() {
    type MrFuService (line 83) | public interface MrFuService {
      method uploadImagePost (line 84) | @POST("/detection/detect")
      method uploadImageUrlGet (line 90) | @GET("/detection/detect")
    method getDataPost (line 96) | public Observable<FaceResponse> getDataPost(CustomMultipartTypedOutput...
    method getDataUrlGet (line 107) | public Observable<FaceResponse> getDataUrlGet(Map<String, String> opti...

FILE: app/src/main/java/mrfu/rxface/loader/SchedulersCompat.java
  class SchedulersCompat (line 11) | public class SchedulersCompat {
    method call (line 15) | @Override public Object call(Object observable) {
    method call (line 22) | @Override public Object call(Object observable) {
    method call (line 28) | @Override public Object call(Object observable) {
    method call (line 34) | @Override public Object call(Object observable) {
    method call (line 41) | @Override public Object call(Object observable) {
    method applyComputationSchedulers (line 50) | public static <T> Observable.Transformer<T, T> applyComputationSchedul...
    method applyIoSchedulers (line 55) | public static <T> Observable.Transformer<T, T> applyIoSchedulers() {
    method applyNewSchedulers (line 60) | public static <T> Observable.Transformer<T, T> applyNewSchedulers() {
    method applyTrampolineSchedulers (line 65) | public static <T> Observable.Transformer<T, T> applyTrampolineSchedule...
    method applyExecutorSchedulers (line 70) | public static <T> Observable.Transformer<T, T> applyExecutorSchedulers...

FILE: app/src/main/java/mrfu/rxface/loader/WebServiceException.java
  class WebServiceException (line 6) | public class WebServiceException extends Exception {
    method WebServiceException (line 7) | public WebServiceException(String detailMessage) {

FILE: app/src/main/java/mrfu/rxface/loader/custom/AsciiTypeString.java
  class AsciiTypeString (line 11) | public class AsciiTypeString extends TypedByteArray {
    method AsciiTypeString (line 13) | public AsciiTypeString(String string) {
    method convertToBytes (line 17) | private static byte[] convertToBytes(String string) {
    method toString (line 25) | @Override public String toString() {

FILE: app/src/main/java/mrfu/rxface/loader/custom/CustomMultipartTypedOutput.java
  class CustomMultipartTypedOutput (line 17) | public class CustomMultipartTypedOutput implements TypedOutput {
    class MimePart (line 20) | private static final class MimePart {
      method MimePart (line 31) | public MimePart(String name, String transferEncoding, TypedOutput bo...
      method writeTo (line 40) | public void writeTo(OutputStream out) throws IOException {
      method size (line 47) | public long size() {
      method build (line 56) | private void build() {
    method CustomMultipartTypedOutput (line 70) | public CustomMultipartTypedOutput() {
    method CustomMultipartTypedOutput (line 74) | public CustomMultipartTypedOutput(String boundary) {
    method getParts (line 80) | List<byte[]> getParts() throws IOException {
    method addPart (line 90) | public void addPart(String name, TypedOutput body) {
    method addPart (line 94) | public void addPart(String name, String transferEncoding, TypedOutput ...
    method getPartCount (line 116) | public int getPartCount() {
    method fileName (line 120) | @Override public String fileName() {
    method mimeType (line 124) | @Override public String mimeType() {
    method length (line 128) | @Override public long length() {
    method writeTo (line 132) | @Override public void writeTo(OutputStream out) throws IOException {
    method buildBoundary (line 139) | private static byte[] buildBoundary(String boundary, boolean first, bo...
    method buildHeader (line 159) | private static byte[] buildHeader(String name, String transferEncoding...

FILE: app/src/main/java/mrfu/rxface/loader/custom/CustomTypedByteArray.java
  class CustomTypedByteArray (line 9) | public class CustomTypedByteArray extends TypedByteArray {
    method CustomTypedByteArray (line 17) | public CustomTypedByteArray(String mimeType, byte[] bytes) {
    method fileName (line 21) | @Override

FILE: app/src/main/java/mrfu/rxface/models/BaseResponse.java
  class BaseResponse (line 9) | public class BaseResponse {
    method filterWebServiceErrors (line 10) | public Observable filterWebServiceErrors() {

FILE: app/src/main/java/mrfu/rxface/models/FaceResponse.java
  class FaceResponse (line 8) | public class FaceResponse extends BaseResponse{
    class FaceEntity (line 33) | public static class FaceEntity {
      class AttributeEntity (line 57) | public static class AttributeEntity {
        class AgeEntity (line 82) | public static class AgeEntity {
        class GenderEntity (line 87) | public static class GenderEntity {
        class RaceEntity (line 92) | public static class RaceEntity {
        class SmilingEntity (line 97) | public static class SmilingEntity {
      class PositionEntity (line 102) | public static class PositionEntity {
        class CenterEntity (line 142) | public static class CenterEntity {
        class EyeLeftEntity (line 147) | public static class EyeLeftEntity {
        class EyeRightEntity (line 152) | public static class EyeRightEntity {
        class MouthLeftEntity (line 157) | public static class MouthLeftEntity {
        class MouthRightEntity (line 162) | public static class MouthRightEntity {
        class NoseEntity (line 167) | public static class NoseEntity {

FILE: app/src/main/java/mrfu/rxface/models/NeedDataEntity.java
  class NeedDataEntity (line 8) | public class NeedDataEntity {

FILE: app/src/test/java/mrfu/face/ExampleUnitTest.java
  class ExampleUnitTest (line 10) | public class ExampleUnitTest {
    method addition_isCorrect (line 11) | @Test

FILE: sdk_unuse/HttpRequests.java
  class HttpRequests (line 25) | public class HttpRequests {
    method setHttpTimeOut (line 47) | public void setHttpTimeOut(int timeOut) {
    method getHttpTimeOut (line 55) | public int getHttpTimeOut() {
    method getApiKey (line 62) | public String getApiKey() {
    method setApiKey (line 69) | public void setApiKey(String apiKey) {
    method getApiSecret (line 76) | public String getApiSecret() {
    method setApiSecret (line 83) | public void setApiSecret(String apiSecret) {
    method setWebSite (line 93) | public void setWebSite(boolean isCN, boolean isDebug) {
    method getWebSite (line 103) | public String getWebSite() {
    method request (line 115) | public JSONObject request(String control, String action) throws Facepp...
    method getSessionSync (line 126) | public JSONObject getSessionSync(String sessionId) throws FaceppParseE...
    method getSessionSync (line 137) | public JSONObject getSessionSync(String sessionId, long timeOut) throw...
    method request (line 196) | public JSONObject request(String control, String action, PostParameter...
    method readString (line 245) | private static String readString(InputStream is) {
    method HttpRequests (line 269) | public HttpRequests(String apiKey, String apiSecret) {
    method HttpRequests (line 280) | public HttpRequests() {
    method HttpRequests (line 293) | public HttpRequests(String apiKey, String apiSecret, boolean isCN, boo...
    method getParams (line 303) | public PostParameters getParams() {
    method setParams (line 312) | public void setParams(PostParameters params) {
    method offlineDetect (line 324) | public JSONObject offlineDetect(byte[] image, String jsonResult) throw...
    method offlineDetect (line 336) | public JSONObject offlineDetect(byte[] image, String jsonResult, PostP...
    method detectionDetect (line 345) | public JSONObject detectionDetect() throws FaceppParseException {
    method detectionDetect (line 348) | public JSONObject detectionDetect(PostParameters params) throws Facepp...
    method detectionLandmark (line 352) | public JSONObject detectionLandmark() throws FaceppParseException {
    method detectionLandmark (line 355) | public JSONObject detectionLandmark(PostParameters params) throws Face...
    method trainVerify (line 359) | public JSONObject trainVerify() throws FaceppParseException {
    method trainVerify (line 362) | public JSONObject trainVerify(PostParameters params) throws FaceppPars...
    method trainSearch (line 366) | public JSONObject trainSearch() throws FaceppParseException {
    method trainSearch (line 369) | public JSONObject trainSearch(PostParameters params) throws FaceppPars...
    method trainIdentify (line 373) | public JSONObject trainIdentify() throws FaceppParseException {
    method trainIdentify (line 376) | public JSONObject trainIdentify(PostParameters params) throws FaceppPa...
    method recognitionCompare (line 380) | public JSONObject recognitionCompare() throws FaceppParseException {
    method recognitionCompare (line 383) | public JSONObject recognitionCompare(PostParameters params) throws Fac...
    method recognitionVerify (line 387) | public JSONObject recognitionVerify() throws FaceppParseException {
    method recognitionVerify (line 390) | public JSONObject recognitionVerify(PostParameters params) throws Face...
    method recognitionSearch (line 394) | public JSONObject recognitionSearch() throws FaceppParseException {
    method recognitionSearch (line 397) | public JSONObject recognitionSearch(PostParameters params) throws Face...
    method recognitionIdentify (line 401) | public JSONObject recognitionIdentify() throws FaceppParseException {
    method recognitionIdentify (line 404) | public JSONObject recognitionIdentify(PostParameters params) throws Fa...
    method groupingGrouping (line 408) | public JSONObject groupingGrouping() throws FaceppParseException {
    method groupingGrouping (line 411) | public JSONObject groupingGrouping(PostParameters params) throws Facep...
    method personCreate (line 415) | public JSONObject personCreate() throws FaceppParseException {
    method personCreate (line 418) | public JSONObject personCreate(PostParameters params) throws FaceppPar...
    method personDelete (line 422) | public JSONObject personDelete() throws FaceppParseException {
    method personDelete (line 425) | public JSONObject personDelete(PostParameters params) throws FaceppPar...
    method personAddFace (line 429) | public JSONObject personAddFace() throws FaceppParseException {
    method personAddFace (line 432) | public JSONObject personAddFace(PostParameters params) throws FaceppPa...
    method personRemoveFace (line 436) | public JSONObject personRemoveFace() throws FaceppParseException {
    method personRemoveFace (line 439) | public JSONObject personRemoveFace(PostParameters params) throws Facep...
    method personSetInfo (line 443) | public JSONObject personSetInfo() throws FaceppParseException {
    method personSetInfo (line 446) | public JSONObject personSetInfo(PostParameters params) throws FaceppPa...
    method personGetInfo (line 450) | public JSONObject personGetInfo() throws FaceppParseException {
    method personGetInfo (line 453) | public JSONObject personGetInfo(PostParameters params) throws FaceppPa...
    method facesetCreate (line 457) | public JSONObject facesetCreate() throws FaceppParseException {
    method facesetCreate (line 460) | public JSONObject facesetCreate(PostParameters params) throws FaceppPa...
    method facesetDelete (line 464) | public JSONObject facesetDelete() throws FaceppParseException {
    method facesetDelete (line 467) | public JSONObject facesetDelete(PostParameters params) throws FaceppPa...
    method facesetAddFace (line 471) | public JSONObject facesetAddFace() throws FaceppParseException {
    method facesetAddFace (line 474) | public JSONObject facesetAddFace(PostParameters params) throws FaceppP...
    method facesetRemoveFace (line 478) | public JSONObject facesetRemoveFace() throws FaceppParseException {
    method facesetRemoveFace (line 481) | public JSONObject facesetRemoveFace(PostParameters params) throws Face...
    method facesetSetInfo (line 485) | public JSONObject facesetSetInfo() throws FaceppParseException {
    method facesetSetInfo (line 488) | public JSONObject facesetSetInfo(PostParameters params) throws FaceppP...
    method facesetGetInfo (line 492) | public JSONObject facesetGetInfo() throws FaceppParseException {
    method facesetGetInfo (line 495) | public JSONObject facesetGetInfo(PostParameters params) throws FaceppP...
    method groupCreate (line 499) | public JSONObject groupCreate() throws FaceppParseException {
    method groupCreate (line 502) | public JSONObject groupCreate(PostParameters params) throws FaceppPars...
    method groupDelete (line 506) | public JSONObject groupDelete() throws FaceppParseException {
    method groupDelete (line 509) | public JSONObject groupDelete(PostParameters params) throws FaceppPars...
    method groupAddPerson (line 513) | public JSONObject groupAddPerson() throws FaceppParseException {
    method groupAddPerson (line 516) | public JSONObject groupAddPerson(PostParameters params) throws FaceppP...
    method groupRemovePerson (line 520) | public JSONObject groupRemovePerson() throws FaceppParseException {
    method groupRemovePerson (line 523) | public JSONObject groupRemovePerson(PostParameters params) throws Face...
    method groupSetInfo (line 527) | public JSONObject groupSetInfo() throws FaceppParseException {
    method groupSetInfo (line 530) | public JSONObject groupSetInfo(PostParameters params) throws FaceppPar...
    method groupGetInfo (line 534) | public JSONObject groupGetInfo() throws FaceppParseException {
    method groupGetInfo (line 537) | public JSONObject groupGetInfo(PostParameters params) throws FaceppPar...
    method infoGetImage (line 541) | public JSONObject infoGetImage() throws FaceppParseException {
    method infoGetImage (line 544) | public JSONObject infoGetImage(PostParameters params) throws FaceppPar...
    method infoGetFace (line 548) | public JSONObject infoGetFace() throws FaceppParseException {
    method infoGetFace (line 551) | public JSONObject infoGetFace(PostParameters params) throws FaceppPars...
    method infoGetPersonList (line 555) | public JSONObject infoGetPersonList() throws FaceppParseException {
    method infoGetPersonList (line 558) | public JSONObject infoGetPersonList(PostParameters params) throws Face...
    method infoGetFacesetList (line 562) | public JSONObject infoGetFacesetList() throws FaceppParseException {
    method infoGetFacesetList (line 565) | public JSONObject infoGetFacesetList(PostParameters params) throws Fac...
    method infoGetGroupList (line 569) | public JSONObject infoGetGroupList() throws FaceppParseException {
    method infoGetGroupList (line 572) | public JSONObject infoGetGroupList(PostParameters params) throws Facep...
    method infoGetSession (line 576) | public JSONObject infoGetSession() throws FaceppParseException {
    method infoGetSession (line 579) | public JSONObject infoGetSession(PostParameters params) throws FaceppP...
    method infoGetQuota (line 588) | public JSONObject infoGetQuota() throws FaceppParseException {
    method infoGetQuota (line 596) | public JSONObject infoGetQuota(PostParameters params) throws FaceppPar...
    method infoGetApp (line 600) | public JSONObject infoGetApp() throws FaceppParseException {
    method infoGetApp (line 603) | public JSONObject infoGetApp(PostParameters params) throws FaceppParse...

FILE: sdk_unuse/MainActivity.java
  class MainActivity (line 38) | public class MainActivity extends Activity {
    method onCreate (line 49) | @Override
    method onCreateOptionsMenu (line 152) | @Override
    method onActivityResult (line 158) | @Override
    class FaceppDetect (line 194) | private class FaceppDetect {
      method setDetectCallback (line 197) | public void setDetectCallback(DetectCallback detectCallback) {
      method detect (line 201) | public void detect(final Bitmap image) {
    type DetectCallback (line 241) | interface DetectCallback {
      method detectResult (line 242) | void detectResult(JSONObject rst);

FILE: sdk_unuse/PostParameters.java
  class PostParameters (line 22) | public class PostParameters {
    method getBoundary (line 32) | private String getBoundary() {
    method getMultiPart (line 43) | public MultipartEntity getMultiPart() {
    method PostParameters (line 50) | public PostParameters() {
    method boundaryString (line 59) | public String boundaryString() {
    method setAsync (line 68) | public PostParameters setAsync(boolean flag) {
    method setUrl (line 78) | public PostParameters setUrl(String url){
    method setAttribute (line 88) | public PostParameters setAttribute(String type){
    method setTag (line 98) | public PostParameters setTag(String tag){
    method setImg (line 108) | public PostParameters setImg(File file) {
    method setImg (line 118) | public PostParameters setImg(byte[] data) {
    method setImg (line 129) | public PostParameters setImg(byte[] data, String fileName) {
    method setFaceId1 (line 139) | public PostParameters setFaceId1(String id){
    method setFaceId2 (line 149) | public PostParameters setFaceId2(String id){
    method setGroupName (line 159) | public PostParameters setGroupName(String groupName){
    method setGroupId (line 169) | public PostParameters setGroupId(String groupId){
    method setKeyFaceId (line 179) | public PostParameters setKeyFaceId(String id){
    method setCount (line 189) | public PostParameters setCount(int count) {
    method setType (line 199) | public PostParameters setType(String type) {
    method setFaceId (line 209) | public PostParameters setFaceId(String faceId) {
    method setFacesetId (line 219) | public PostParameters setFacesetId(String facesetId) {
    method setFacesetId (line 229) | public PostParameters setFacesetId(String[] facesetId) {
    method setFacesetId (line 239) | public PostParameters setFacesetId(ArrayList<String> facesetId) {
    method setPersonId (line 249) | public PostParameters setPersonId(String personId) {
    method setPersonName (line 259) | public PostParameters setPersonName(String personName) {
    method setName (line 269) | public PostParameters setName(String name) {
    method setSessionId (line 279) | public PostParameters setSessionId(String id) {
    method setMode (line 289) | public PostParameters setMode(String type) {
    method setFaceId (line 300) | public PostParameters setFaceId(String[] faceIds) {
    method setPersonId (line 308) | public PostParameters setPersonId(String[] personIds) {
    method setPersonName (line 316) | public PostParameters setPersonName(String[] personNames) {
    method setGroupId (line 324) | public PostParameters setGroupId(String[] groupIds) {
    method setGroupName (line 332) | public PostParameters setGroupName(String[] groupNames) {
    method setFaceId (line 341) | public PostParameters setFaceId(ArrayList<String> faceIds) {
    method setPersonId (line 349) | public PostParameters setPersonId(ArrayList<String> personIds) {
    method setPersonName (line 357) | public PostParameters setPersonName(ArrayList<String> personNames) {
    method setGroupId (line 365) | public PostParameters setGroupId(ArrayList<String> groupIds) {
    method setGroupName (line 373) | public PostParameters setGroupName(ArrayList<String> groupNames) {
    method setImgId (line 382) | public PostParameters setImgId(String imgId) {
    method setFacesetName (line 392) | public PostParameters setFacesetName(String facesetName) {
    method setFacesetName (line 402) | public PostParameters setFacesetName(ArrayList<String> facesetNames) {
    method setFacesetName (line 410) | public PostParameters setFacesetName(String[] facesetNames) {
    method addAttribute (line 419) | public PostParameters addAttribute(String attr, String value) {
    method addString (line 424) | private void addString(String id, String str) {
    method toStringList (line 432) | private String toStringList(String[] sa) {
    method toStringList (line 442) | private String toStringList(ArrayList<String> sa) {
Condensed preview — 53 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (131K chars).
[
  {
    "path": ".gitignore",
    "chars": 91,
    "preview": ".gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n"
  },
  {
    "path": ".idea/.name",
    "chars": 6,
    "preview": "RxFace"
  },
  {
    "path": ".idea/compiler.xml",
    "chars": 709,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <option name"
  },
  {
    "path": ".idea/copyright/profiles_settings.xml",
    "chars": 74,
    "preview": "<component name=\"CopyrightManager\">\n  <settings default=\"\" />\n</component>"
  },
  {
    "path": ".idea/gradle.xml",
    "chars": 608,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linke"
  },
  {
    "path": ".idea/misc.xml",
    "chars": 2649,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"EntryPointsManager\">\n    <entry_points v"
  },
  {
    "path": ".idea/modules.xml",
    "chars": 349,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n   "
  },
  {
    "path": ".idea/runConfigurations.xml",
    "chars": 564,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <o"
  },
  {
    "path": ".idea/vcs.xml",
    "chars": 164,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping dire"
  },
  {
    "path": "Face.iml",
    "chars": 935,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\"Face\" external.linked.project.path=\"$MODULE_D"
  },
  {
    "path": "README.md",
    "chars": 5183,
    "preview": "RxFace\n=====================\n\n用 RxJava, Retrofit, Okhttp 处理人脸识别的简单用例\n\n## Overview\n\n这是一个人脸识别的简单 Demo, 使用了 [FacePlusPlus]("
  },
  {
    "path": "RxFace.iml",
    "chars": 937,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\"RxFace\" external.linked.project.path=\"$MODULE"
  },
  {
    "path": "app/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "app/app.iml",
    "chars": 9043,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\":app\" external.linked.project.path=\"$MODULE_D"
  },
  {
    "path": "app/build.gradle",
    "chars": 1253,
    "preview": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 23\n    buildToolsVersion \"23.0.2\"\n\n    defaultC"
  },
  {
    "path": "app/proguard-rules.pro",
    "chars": 693,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /U"
  },
  {
    "path": "app/src/androidTest/java/mrfu/face/ApplicationTest.java",
    "chars": 340,
    "preview": "package mrfu.face;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.a"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "chars": 874,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "app/src/main/java/mrfu/rxface/AppApplication.java",
    "chars": 407,
    "preview": "package mrfu.rxface;\n\nimport android.app.Application;\nimport android.content.Context;\n\n/**\n * Created by MrFu on 15/12/1"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/BaseActivity.java",
    "chars": 862,
    "preview": "package mrfu.rxface;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\n\nimport butterknife.But"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/MainActivity.java",
    "chars": 6763,
    "preview": "package mrfu.rxface;\n\nimport android.content.Intent;\nimport android.graphics.Bitmap;\nimport android.graphics.drawable.Bi"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/business/Constants.java",
    "chars": 586,
    "preview": "package mrfu.rxface.business;\n\n/**\n * Created by MrFu on 15/12/15.\n */\npublic class Constants {\n//    public static fina"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/business/DealData.java",
    "chars": 5031,
    "preview": "package mrfu.rxface.business;\n\nimport android.graphics.Bitmap;\nimport android.graphics.Canvas;\nimport android.graphics.C"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/loader/ExecutorManager.java",
    "chars": 2975,
    "preview": "package mrfu.rxface.loader;\n\nimport android.os.Build;\nimport android.support.annotation.NonNull;\n\nimport java.io.File;\ni"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/loader/FaceApi.java",
    "chars": 4407,
    "preview": "package mrfu.rxface.loader;\n\nimport com.squareup.okhttp.OkHttpClient;\n\nimport java.util.Map;\nimport java.util.Random;\nim"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/loader/SchedulersCompat.java",
    "chars": 2793,
    "preview": "package mrfu.rxface.loader;\n\nimport rx.Observable;\nimport rx.android.schedulers.AndroidSchedulers;\nimport rx.schedulers."
  },
  {
    "path": "app/src/main/java/mrfu/rxface/loader/WebServiceException.java",
    "chars": 214,
    "preview": "package mrfu.rxface.loader;\n\n/**\n * Created by MrFu on 16/1/10.\n */\npublic class WebServiceException extends Exception {"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/loader/custom/AsciiTypeString.java",
    "chars": 882,
    "preview": "package mrfu.rxface.loader.custom;\n\nimport java.io.UnsupportedEncodingException;\n\nimport retrofit.mime.TypedByteArray;\n\n"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/loader/custom/CustomMultipartTypedOutput.java",
    "chars": 5857,
    "preview": "package mrfu.rxface.loader.custom;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.Out"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/loader/custom/CustomTypedByteArray.java",
    "chars": 620,
    "preview": "package mrfu.rxface.loader.custom;\n\nimport retrofit.mime.TypedByteArray;\n\n/**\n * 重写 TypedByteArray 设置其 fileName 为 \"NoNam"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/models/BaseResponse.java",
    "chars": 1761,
    "preview": "package mrfu.rxface.models;\n\nimport mrfu.rxface.loader.WebServiceException;\nimport rx.Observable;\n\n/**\n * Created by MrF"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/models/FaceResponse.java",
    "chars": 6218,
    "preview": "package mrfu.rxface.models;\n\nimport java.util.List;\n\n/**\n * Created by MrFu on 15/12/16.\n */\npublic class FaceResponse e"
  },
  {
    "path": "app/src/main/java/mrfu/rxface/models/NeedDataEntity.java",
    "chars": 190,
    "preview": "package mrfu.rxface.models;\n\nimport android.graphics.Bitmap;\n\n/**\n * Created by MrFu on 15/12/16.\n */\npublic class NeedD"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "chars": 1428,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout\n    xmlns:android=\"http://schema"
  },
  {
    "path": "app/src/main/res/layout/content_main.xml",
    "chars": 2672,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    "
  },
  {
    "path": "app/src/main/res/menu/menu_main.xml",
    "chars": 383,
    "preview": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      xmlns:app=\"http://schemas.android.com/apk/res-aut"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"color"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "chars": 253,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "chars": 264,
    "preview": "<resources>\n    <string name=\"app_name\">RxFace</string>\n    <string name=\"action_settings\">Settings</string>\n    <string"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "chars": 703,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "app/src/main/res/values-v21/styles.xml",
    "chars": 327,
    "preview": "<resources>>\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item nam"
  },
  {
    "path": "app/src/main/res/values-w820dp/dimens.xml",
    "chars": 358,
    "preview": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as s"
  },
  {
    "path": "app/src/test/java/mrfu/face/ExampleUnitTest.java",
    "chars": 302,
    "preview": "package mrfu.face;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the "
  },
  {
    "path": "build.gradle",
    "chars": 556,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    r"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 230,
    "preview": "#Tue Dec 15 21:05:14 CST 2015\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 855,
    "preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
  },
  {
    "path": "gradlew",
    "chars": 5080,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2404,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "sdk_unuse/HttpRequests.java",
    "chars": 19106,
    "preview": "package mrfu.face.sdk;\r\n\r\nimport java.io.IOException;\r\nimport java.io.InputStream;\r\nimport java.net.HttpURLConnection;\r\n"
  },
  {
    "path": "sdk_unuse/MainActivity.java",
    "chars": 7932,
    "preview": "package mrfu.face.sdk;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.database.Cursor;\nimpo"
  },
  {
    "path": "sdk_unuse/PostParameters.java",
    "chars": 9573,
    "preview": "package mrfu.face.sdk;\r\n\r\nimport java.io.File;\r\nimport java.io.UnsupportedEncodingException;\r\nimport java.nio.charset.Ch"
  },
  {
    "path": "settings.gradle",
    "chars": 15,
    "preview": "include ':app'\n"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the MrFuFuFu/RxFace GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 53 files (114.0 KB), approximately 30.3k tokens, and a symbol index with 244 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!