[
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <resourceExtensions />\n    <wildcardResourcePatterns>\n      <entry name=\"!?*.java\" />\n      <entry name=\"!?*.form\" />\n      <entry name=\"!?*.class\" />\n      <entry name=\"!?*.groovy\" />\n      <entry name=\"!?*.scala\" />\n      <entry name=\"!?*.flex\" />\n      <entry name=\"!?*.kt\" />\n      <entry name=\"!?*.clj\" />\n      <entry name=\"!?*.aj\" />\n    </wildcardResourcePatterns>\n    <annotationProcessing>\n      <profile default=\"true\" name=\"Default\" enabled=\"false\">\n        <processorPath useClasspath=\"true\" />\n      </profile>\n    </annotationProcessing>\n  </component>\n</project>"
  },
  {
    "path": ".idea/copyright/profiles_settings.xml",
    "content": "<component name=\"CopyrightManager\">\n  <settings default=\"\" />\n</component>"
  },
  {
    "path": ".idea/encodings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Encoding\">\n    <file url=\"PROJECT\" charset=\"UTF-8\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/app\" />\n          </set>\n        </option>\n        <option name=\"resolveModulePerSourceSet\" value=\"false\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"EntryPointsManager\">\n    <entry_points version=\"2.0\" />\n  </component>\n  <component name=\"NullableNotNullManager\">\n    <option name=\"myDefaultNullable\" value=\"android.support.annotation.Nullable\" />\n    <option name=\"myDefaultNotNull\" value=\"android.support.annotation.NonNull\" />\n    <option name=\"myNullables\">\n      <value>\n        <list size=\"4\">\n          <item index=\"0\" class=\"java.lang.String\" itemvalue=\"org.jetbrains.annotations.Nullable\" />\n          <item index=\"1\" class=\"java.lang.String\" itemvalue=\"javax.annotation.Nullable\" />\n          <item index=\"2\" class=\"java.lang.String\" itemvalue=\"edu.umd.cs.findbugs.annotations.Nullable\" />\n          <item index=\"3\" class=\"java.lang.String\" itemvalue=\"android.support.annotation.Nullable\" />\n        </list>\n      </value>\n    </option>\n    <option name=\"myNotNulls\">\n      <value>\n        <list size=\"4\">\n          <item index=\"0\" class=\"java.lang.String\" itemvalue=\"org.jetbrains.annotations.NotNull\" />\n          <item index=\"1\" class=\"java.lang.String\" itemvalue=\"javax.annotation.Nonnull\" />\n          <item index=\"2\" class=\"java.lang.String\" itemvalue=\"edu.umd.cs.findbugs.annotations.NonNull\" />\n          <item index=\"3\" class=\"java.lang.String\" itemvalue=\"android.support.annotation.NonNull\" />\n        </list>\n      </value>\n    </option>\n  </component>\n  <component name=\"ProjectInspectionProfilesVisibleTreeState\">\n    <entry key=\"Project Default\">\n      <profile-state>\n        <expanded-state>\n          <State>\n            <id />\n          </State>\n          <State>\n            <id>Abstraction issuesJava</id>\n          </State>\n          <State>\n            <id>Android &gt; Lint &gt; Correctness</id>\n          </State>\n          <State>\n            <id>Android &gt; Lint &gt; Correctness &gt; Messages</id>\n          </State>\n          <State>\n            <id>Android &gt; Lint &gt; Performance</id>\n          </State>\n          <State>\n            <id>Android &gt; Lint &gt; Security</id>\n          </State>\n          <State>\n            <id>Android &gt; Lint &gt; Usability &gt; Icons</id>\n          </State>\n          <State>\n            <id>Internationalization issuesJava</id>\n          </State>\n          <State>\n            <id>J2ME issuesJava</id>\n          </State>\n          <State>\n            <id>Java</id>\n          </State>\n          <State>\n            <id>Java language level issuesJava</id>\n          </State>\n          <State>\n            <id>Logging issuesJava</id>\n          </State>\n          <State>\n            <id>Numeric issuesJava</id>\n          </State>\n          <State>\n            <id>Portability issuesJava</id>\n          </State>\n          <State>\n            <id>Security issuesJava</id>\n          </State>\n          <State>\n            <id>Serialization issuesJava</id>\n          </State>\n        </expanded-state>\n        <selected-state>\n          <State>\n            <id>Android</id>\n          </State>\n        </selected-state>\n      </profile-state>\n    </entry>\n  </component>\n  <component name=\"ProjectLevelVcsManager\" settingsEditedManually=\"false\">\n    <OptionsSetting value=\"true\" id=\"Add\" />\n    <OptionsSetting value=\"true\" id=\"Remove\" />\n    <OptionsSetting value=\"true\" id=\"Checkout\" />\n    <OptionsSetting value=\"true\" id=\"Update\" />\n    <OptionsSetting value=\"true\" id=\"Status\" />\n    <OptionsSetting value=\"true\" id=\"Edit\" />\n    <ConfirmationsSetting value=\"0\" id=\"Add\" />\n    <ConfirmationsSetting value=\"0\" id=\"Remove\" />\n  </component>\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_7\" default=\"true\" assert-keyword=\"true\" jdk-15=\"true\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n  <component name=\"ProjectType\">\n    <option name=\"id\" value=\"Android\" />\n  </component>\n  <component name=\"SvnConfiguration\">\n    <configuration useDefault=\"false\">C:\\Users\\周康\\AppData\\Roaming\\Subversion</configuration>\n  </component>\n  <component name=\"masterDetails\">\n    <states>\n      <state key=\"ProjectJDKs.UI\">\n        <settings>\n          <last-edited>1.8</last-edited>\n          <splitter-proportions>\n            <option name=\"proportions\">\n              <list>\n                <option value=\"0.2\" />\n              </list>\n            </option>\n          </splitter-proportions>\n        </settings>\n      </state>\n    </states>\n  </component>\n</project>"
  },
  {
    "path": ".idea/modules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n      <module fileurl=\"file://$PROJECT_DIR$/IDCardOCR_China.iml\" filepath=\"$PROJECT_DIR$/IDCardOCR_China.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/app/app.iml\" filepath=\"$PROJECT_DIR$/app/app.iml\" />\n    </modules>\n  </component>\n</project>"
  },
  {
    "path": ".idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "README.md",
    "content": "# IDCardOCR_China\n基于tesseract，实现摄像头扫描识别中国二代身份证\n# Usage\ndemo主要提供思路，通过摄像头取景，预览裁剪，ocr识别.\n# ScreenShots\n ![image](https://github.com/465857721/IDCardOCR_China/blob/master/ScreenShots/device-2016-12-24-095238-small.jpg)\n# TODO\n- 姓名ocr识别\n- 民族识别\n\n# 建议\n1.对esseract进行训练，目前用的文件为eng数据，没有针对二代身份证进行优化，可以自己进行训练，只识别1-0和英文X。数据包也会相应减小。\n（ baseApi.setVariable(\"tessedit_char_whitelist\", \"0123456789Xx\");）也可以设置白名单，代码里设置了，但是这样没有减少训练文件的大小.\n\n2.目前demo仅仅识别了身份证号码，可以裁剪出来其他信息进行ocr，后续进行优化....\n#Thanks\nhttps://github.com/tdk-farkas/CameraSFZ    身份证裁剪\n#Changelog\nV0.0.2(2016/12/24)\n- 6.0权限适配\n- 识别单词设置白名单 增加识别率\n\nV0.0.1(2016/12/01)\n- 项目导入\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.2\"\n    defaultConfig {\n        applicationId \"com.kingsoft.idcardocr_china\"\n        minSdkVersion 21\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {\n        exclude group: 'com.android.support', module: 'support-annotations'\n    })\n    compile 'com.android.support:appcompat-v7:25.0.0'\n    testCompile 'junit:junit:4.12'\n    compile 'com.rmtheis:tess-two:6.1.1'\n    compile 'com.anthonycr.grant:permissions:1.0'\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in C:\\dev\\android-sdk-windows/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "app/src/androidTest/java/com/kingsoft/idcardocr_china/ExampleInstrumentedTest.java",
    "content": "package com.kingsoft.idcardocr_china;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumentation test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() throws Exception {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"com.kingsoft.idcardocr_china\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.kingsoft.idcardocr_china\">\n\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>\n    <uses-permission android:name=\"android.permission.CAMERA\"/>\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n        <activity\n            android:name=\".idcardocr.CameraActivity\"\n            android:screenOrientation=\"landscape\"\n            android:theme=\"@android:style/Theme.NoTitleBar.Fullscreen\"/>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/kingsoft/idcardocr_china/MainActivity.java",
    "content": "package com.kingsoft.idcardocr_china;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.Message;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.View;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.anthonycr.grant.PermissionsManager;\nimport com.anthonycr.grant.PermissionsResultAction;\nimport com.kingsoft.idcardocr_china.idcardocr.CameraActivity;\n\npublic class MainActivity extends AppCompatActivity {\n    private static final int GETPERMISSION_SUCCESS = 1;//获取权限成功\n    private static final int GETPERMISSION_FAILER = 2;//获取权限失败\n    private TextView tv_id;\n    private int MY_SCAN_REQUEST_CODE = 100;\n    private Context mContext;\n    private MyHandler myHandler = new MyHandler();\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        mContext = this;\n        tv_id = (TextView) findViewById(R.id.tv_id);\n        findViewById(R.id.btn_go).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n//                getPermissions();\n                requestAllPermission();\n            }\n        });\n    }\n\n    private void requestAllPermission() {\n        PermissionsManager.getInstance().requestAllManifestPermissionsIfNecessary(MainActivity.this,\n                new PermissionsResultAction() {\n                    @Override\n                    public void onGranted() {\n                        myHandler.sendEmptyMessage(GETPERMISSION_SUCCESS);\n                    }\n\n                    @Override\n                    public void onDenied(String permission) {\n                        myHandler.sendEmptyMessage(GETPERMISSION_FAILER);\n                    }\n                });\n    }\n\n    //因为权限管理类无法监听系统，所以需要重写onRequestPermissionResult方法，更新权限管理类，并回调结果。这个是必须要有的。\n    @Override\n    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {\n        PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);\n    }\n\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n        super.onActivityResult(requestCode, resultCode, data);\n        if (requestCode == MY_SCAN_REQUEST_CODE && resultCode == RESULT_OK && data != null) {\n            String id = data.getStringExtra(\"id\");\n            Toast.makeText(this, id, Toast.LENGTH_LONG).show();\n            if (id != null && id.length() == 18) {\n                tv_id.setText(id);\n            }\n        }\n    }\n\n\n    private class MyHandler extends Handler {\n        @Override\n        public void handleMessage(Message msg) {\n            super.handleMessage(msg);\n            switch (msg.what) {\n                case GETPERMISSION_SUCCESS:\n                    Intent scanIntent = new Intent(mContext, CameraActivity.class);\n                    startActivityForResult(scanIntent, MY_SCAN_REQUEST_CODE);\n                    break;\n                case GETPERMISSION_FAILER:\n                    Toast.makeText(mContext, \"此功能须获摄像头权限1111111\", Toast.LENGTH_LONG).show();\n                    break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/kingsoft/idcardocr_china/idcardocr/AutoFocusManager.java",
    "content": "package com.kingsoft.idcardocr_china.idcardocr;\n\nimport android.hardware.Camera;\nimport android.os.AsyncTask;\nimport android.util.Log;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.concurrent.RejectedExecutionException;\n\n\npublic class AutoFocusManager implements Camera.AutoFocusCallback{\n    private static final String TAG = AutoFocusManager.class.getSimpleName();\n    private static final long AUTO_FOCUS_INTERVAL_MS = 3000L;\n    private static final Collection<String> FOCUS_MODES_CALLING_AF;\n    static {\n        FOCUS_MODES_CALLING_AF = new ArrayList<String>(2);\n        FOCUS_MODES_CALLING_AF.add(Camera.Parameters.FOCUS_MODE_AUTO);\n        FOCUS_MODES_CALLING_AF.add(Camera.Parameters.FOCUS_MODE_MACRO);\n    }\n\n    private boolean stopped;\n    private boolean focusing;\n    private final boolean useAutoFocus;\n    private final Camera camera;\n    private AsyncTask<?,?,?> outstandingTask;\n    private Camera.PreviewCallback mp;\n    public AutoFocusManager(Camera camera, Camera.PreviewCallback mp) {\n        this.camera = camera;\n        String currentFocusMode = camera.getParameters().getFocusMode();\n        useAutoFocus = FOCUS_MODES_CALLING_AF.contains(currentFocusMode);\n        Log.e(TAG, \"Current focus mode '\" + currentFocusMode + \"'; use auto focus? \" + useAutoFocus);\n        this.mp = mp;\n        start();\n    }\n\n    @Override\n    public synchronized void onAutoFocus(final boolean success, Camera theCamera) {\n//        if(success){\n//            camera.takePicture(null, null, myjpegCallback);\n//        }\n\n;\n        focusing = false;\n        autoFocusAgainLater();\n    }\n\n\n    private synchronized void autoFocusAgainLater() {\n        if (!stopped && outstandingTask == null) {\n            AutoFocusTask newTask = new AutoFocusTask();\n            try {\n                newTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);\n                outstandingTask = newTask;\n            } catch (RejectedExecutionException ree) {\n                Log.e(TAG, \"Could not request auto focus\", ree);\n            }\n        }\n    }\n\n    /**\n     * 开始自动对焦\n     */\n    public synchronized void start() {\n//        camera.setOneShotPreviewCallback(new Camera.PreviewCallback() {\n//            @Override\n//            public void onPreviewFrame(byte[] data, Camera camera)\n//        });\n        if (useAutoFocus) {\n            outstandingTask = null;\n            if (!stopped && !focusing) {\n                try {\n                    camera.setOneShotPreviewCallback(mp);\n                    camera.autoFocus(this);\n                    focusing = true;\n                } catch (RuntimeException re) {\n                    // Have heard RuntimeException reported in Android 4.0.x+; continue?\n                    Log.e(TAG, \"Unexpected exception while focusing\", re);\n                    // Try again later to keep cycle going\n                    autoFocusAgainLater();\n                }\n            }\n        }\n    }\n\n\n    private synchronized void cancelOutstandingTask() {\n        if (outstandingTask != null) {\n            if (outstandingTask.getStatus() != AsyncTask.Status.FINISHED) {\n                outstandingTask.cancel(true);\n            }\n            outstandingTask = null;\n        }\n    }\n\n    /**\n     * 停止自动对焦\n     */\n    public synchronized void stop() {\n        stopped = true;\n        if (useAutoFocus) {\n            cancelOutstandingTask();\n            // Doesn't hurt to call this even if not focusing\n            try {\n                camera.cancelAutoFocus();\n            } catch (RuntimeException re) {\n                // Have heard RuntimeException reported in Android 4.0.x+; continue?\n                Log.e(TAG, \"Unexpected exception while cancelling focusing\", re);\n            }\n        }\n    }\n\n\n    private final class AutoFocusTask extends AsyncTask<Object,Object,Object> {\n        @Override\n        protected Object doInBackground(Object... voids) {\n            try {\n                Thread.sleep(AUTO_FOCUS_INTERVAL_MS);\n            } catch (InterruptedException e) {\n                // continue\n            }\n            start();\n            return null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/kingsoft/idcardocr_china/idcardocr/CameraActivity.java",
    "content": "package com.kingsoft.idcardocr_china.idcardocr;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.graphics.ImageFormat;\nimport android.graphics.Rect;\nimport android.graphics.YuvImage;\nimport android.hardware.Camera;\nimport android.os.Bundle;\nimport android.os.Environment;\nimport android.os.Handler;\nimport android.util.Log;\nimport android.view.SurfaceHolder;\nimport android.view.SurfaceView;\nimport android.view.View;\nimport android.widget.Button;\nimport android.widget.TextView;\n\nimport com.googlecode.tesseract.android.TessBaseAPI;\nimport com.kingsoft.idcardocr_china.R;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.InputStream;\nimport java.io.OutputStream;\n\n\npublic class CameraActivity extends Activity implements SurfaceHolder.Callback, Camera.PreviewCallback {\n\n    private TessBaseAPI baseApi;\n\n    //    Camera.PreviewCallback mp = ;\n    private CameraManager cameraManager;\n    private boolean hasSurface;\n    private String type;\n    private Button btn_close, light, btn_resacn;\n    private boolean toggleLight = false;\n    private Handler mHandler;\n    private TextView tv_lightstate, tv_input;\n    private String sdPath;\n    //    private ImageView iv_close;\n//    private View ErrorView;\n    private int times = 0;\n    private Long opentime;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        opentime = System.currentTimeMillis();\n        sdPath = Environment.getExternalStorageDirectory() + \"/ayy/\";\n        try {\n            copyAssetFile();\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        baseApi = new TessBaseAPI();\n\n        baseApi.init(sdPath, \"eng\");\n        baseApi.setVariable(\"tessedit_char_whitelist\", \"0123456789Xx\");\n//        baseApi.\n        setContentView(R.layout.activity_camera);\n        tv_lightstate = (TextView) findViewById(R.id.tv_openlight);\n        mHandler = new Handler();\n        initLayoutParams();\n    }\n\n    /**\n     * 重置surface宽高比例为3:4，不重置的话图形会拉伸变形\n     */\n    private void initLayoutParams() {\n//        ErrorView = findViewById(R.id.ll_cameraerrorview);\n\n\n        btn_close = (Button) findViewById(R.id.btn_close);\n        light = (Button) findViewById(R.id.light);\n        btn_close.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                setResult(RESULT_CANCELED);\n                onBackPressed();\n\n            }\n        });\n        light.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                long time = System.currentTimeMillis();// 摄像头 初始化 需要时间\n                if (time - opentime > 2000) {\n                    opentime = time;\n                    if (!toggleLight) {\n                        toggleLight = true;\n                        tv_lightstate.setText(\"关闭闪关灯\");\n                        cameraManager.openLight();\n                    } else {\n                        toggleLight = false;\n                        tv_lightstate.setText(\"打开闪关灯\");\n                        cameraManager.offLight();\n                    }\n                }\n            }\n        });\n//        btn_resacn = (Button) findViewById(R.id.btn_rescan);\n//        btn_resacn.setOnClickListener(new View.OnClickListener() {\n//            @Override\n//            public void onClick(View v) {\n//                times = 0;\n//                ErrorView.setVisibility(View.GONE);\n//            }\n//        });\n//        tv_input = (TextView) findViewById(R.id.tv_inputbyself);\n//        tv_input.setOnClickListener(new View.OnClickListener() {\n//            @Override\n//            public void onClick(View v) {\n//                setResult(RESULT_CANCELED);\n//                onBackPressed();\n//            }\n//        });\n//        iv_close = (ImageView) findViewById(R.id.iv_closetips);\n//        iv_close.setOnClickListener(new View.OnClickListener() {\n//            @Override\n//            public void onClick(View v) {\n//                times = 0;\n//                ErrorView.setVisibility(View.GONE);\n//\n//            }\n//        });\n\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        /**\n         * 初始化camera\n         */\n        cameraManager = new CameraManager();\n        SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceview);\n        SurfaceHolder surfaceHolder = surfaceView.getHolder();\n\n        if (hasSurface) {\n            // activity在paused时但不会stopped,因此surface仍旧存在；\n            // surfaceCreated()不会调用，因此在这里初始化camera\n            initCamera(surfaceHolder);\n        } else {\n            // 重置callback，等待surfaceCreated()来初始化camera\n            surfaceHolder.addCallback(this);\n        }\n    }\n\n    @Override\n    public void surfaceCreated(SurfaceHolder holder) {\n        if (!hasSurface) {\n            hasSurface = true;\n            initCamera(holder);\n        }\n    }\n\n    @Override\n    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {\n\n    }\n\n    @Override\n    public void surfaceDestroyed(SurfaceHolder holder) {\n        hasSurface = false;\n    }\n\n    /**\n     * 初始camera\n     *\n     * @param surfaceHolder SurfaceHolder\n     */\n    private void initCamera(SurfaceHolder surfaceHolder) {\n        if (surfaceHolder == null) {\n            throw new IllegalStateException(\"No SurfaceHolder provided\");\n        }\n        if (cameraManager.isOpen()) {\n            return;\n        }\n        try {\n            // 打开Camera硬件设备\n            cameraManager.openDriver(surfaceHolder, this);\n            // 创建一个handler来打开预览，并抛出一个运行时异常\n            cameraManager.startPreview(this);\n        } catch (Exception ioe) {\n            Log.d(\"zk\", ioe.toString());\n\n        }\n    }\n\n    @Override\n    protected void onPause() {\n        /**\n         * 停止camera，是否资源操作\n         */\n        cameraManager.stopPreview();\n        cameraManager.closeDriver();\n        if (!hasSurface) {\n            SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceview);\n            SurfaceHolder surfaceHolder = surfaceView.getHolder();\n            surfaceHolder.removeCallback(this);\n        }\n        super.onPause();\n    }\n\n    private boolean copyAssetFile() throws Exception {\n\n        String dir = sdPath + \"/tessdata\";\n        String filePath = sdPath + \"/tessdata/eng.traineddata\";\n        File f = new File(dir);\n        if (f.exists()) {\n        } else {\n            f.mkdirs();\n        }\n        File dataFile = new File(filePath);\n        if (dataFile.exists()) {\n            return true;// 文件存在\n        } else {\n\n            InputStream in = this.getAssets().open(\"eng.traineddata\");\n\n            File outFile = new File(filePath);\n            if (outFile.exists()) {\n                outFile.delete();\n            }\n            OutputStream out = new FileOutputStream(outFile);\n            byte[] buf = new byte[1024];\n            int len;\n            while ((len = in.read(buf)) > 0) {\n                out.write(buf, 0, len);\n            }\n            in.close();\n            out.close();\n        }\n\n        return false;\n    }\n\n    public String doOcr(Bitmap bitmap) {\n        bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);\n        baseApi.setImage(bitmap);\n        String text = baseApi.getUTF8Text();\n        baseApi.clear();\n//        baseApi.end();\n        return text;\n    }\n\n\n    @Override\n    public void onBackPressed() {\n        if (baseApi != null)\n            baseApi.end();\n        super.onBackPressed();\n    }\n\n    @Override\n    public void onPreviewFrame(byte[] data, Camera camera) {\n        ByteArrayOutputStream baos;\n        byte[] rawImage;\n        Bitmap bitmap;\n        Camera.Size previewSize = camera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到\n        BitmapFactory.Options newOpts = new BitmapFactory.Options();\n        newOpts.inJustDecodeBounds = true;\n        YuvImage yuvimage = new YuvImage(\n                data,\n                ImageFormat.NV21,\n                previewSize.width,\n                previewSize.height,\n                null);\n        baos = new ByteArrayOutputStream();\n        yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);// 80--JPG图片的质量[0-100],100最高\n        rawImage = baos.toByteArray();\n        //将rawImage转换成bitmap\n        BitmapFactory.Options options = new BitmapFactory.Options();\n        options.inPreferredConfig = Bitmap.Config.RGB_565;\n        bitmap = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length, options);\n        if (bitmap == null) {\n            Log.d(\"zka\", \"bitmap is nlll\");\n            return;\n        } else {\n            int height = bitmap.getHeight();\n            int width = bitmap.getWidth();\n            final Bitmap bitmap1 = Bitmap.createBitmap(bitmap, (width - height) / 2, height / 6, height, height * 2 / 3);\n            int x, y, w, h;\n            x = (int) (bitmap1.getWidth() * 0.340);\n            y = (int) (bitmap1.getHeight() * 0.800);\n            w = (int) (bitmap1.getWidth() * 0.6 + 0.5f);\n            h = (int) (bitmap1.getHeight() * 0.12 + 0.5f);\n            Bitmap bit_hm = Bitmap.createBitmap(bitmap1, x, y, w, h);\n            String id = doOcr(bit_hm);\n//            if (++times > 10)\n//                ErrorView.setVisibility(View.VISIBLE);\n            if (id.length() == 18) {\n                Intent i = new Intent();\n                i.putExtra(\"id\", id);\n                setResult(RESULT_OK, i);\n                onBackPressed();\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/kingsoft/idcardocr_china/idcardocr/CameraManager.java",
    "content": "package com.kingsoft.idcardocr_china.idcardocr;\n\nimport android.content.Context;\nimport android.hardware.Camera;\nimport android.hardware.Camera.Size;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.view.SurfaceHolder;\n\nimport java.io.IOException;\nimport java.util.List;\n\npublic class CameraManager {\n    private static final String TAG = CameraManager.class.getName();\n    private Camera camera;\n    private Camera.Parameters parameters;\n    private AutoFocusManager autoFocusManager;\n    private int requestedCameraId = -1;\n\n    private boolean initialized;\n    private boolean previewing;\n\n    private Size mPreviewSize;\n    private List<Size> mSupportedPreviewSizes;\n\n    /**\n     * 打开摄像头\n     *\n     * @param cameraId 摄像头id\n     * @return Camera\n     */\n    public Camera open(int cameraId, Context mContext) {\n        int nucameras = Camera.getNumberOfCameras();\n        if (nucameras == 0) {\n            Log.e(TAG, \"No cameras!\");\n            return null;\n        }\n        boolean explicitRequest = cameraId >= 0;\n        if (!explicitRequest) {\n            // Select a camera if no explicit camera requested\n            int index = 0;\n            while (index < nucameras) {\n                Camera.CameraInfo cameraInfo = new Camera.CameraInfo();\n                Camera.getCameraInfo(index, cameraInfo);\n                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {\n                    break;\n                }\n                index++;\n            }\n            cameraId = index;\n        }\n        Camera camera;\n        if (cameraId < nucameras) {\n            Log.e(TAG, \"Opening camera #\" + cameraId);\n            camera = Camera.open(cameraId);\n        } else {\n            if (explicitRequest) {\n                Log.e(TAG, \"Requested camera does not exist: \" + cameraId);\n                camera = null;\n            } else {\n                Log.e(TAG, \"No camera facing back; returning camera #0\");\n                camera = Camera.open(0);\n            }\n        }\n        mSupportedPreviewSizes = camera.getParameters()\n                .getSupportedPreviewSizes();\n        if (mSupportedPreviewSizes != null) {\n            mPreviewSize = getOptimalPreviewSize(\n                    mSupportedPreviewSizes, getScreenWidth(mContext), getScreenHeight(mContext));\n        }\n        Log.d(\"zkcam\", \"w=\" + getScreenWidth(mContext));\n        Log.d(\"zkcam\", \"h=\" + getScreenHeight(mContext));\n        Camera.Parameters parameters = camera.getParameters();\n        parameters.setPreviewSize(mPreviewSize.width,\n                mPreviewSize.height);\n        Log.d(\"zkcam\", \"pw=\" + mPreviewSize.width);\n        Log.d(\"zkcam\", \"ph=\" + mPreviewSize.height);\n        camera.setParameters(parameters);\n        return camera;\n    }\n\n    private Camera.Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {\n        final double ASPECT_TOLERANCE = 0.2;\n        double targetRatio = (double) w / h;\n\n        if (sizes == null) return null;\n\n        Camera.Size optimalSize = null;\n        double minDiff = Double.MAX_VALUE;\n\n        int targetHeight = h;\n\n        for (Camera.Size size : sizes) {\n            double ratio = (double) size.width / size.height;\n            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;\n            if (Math.abs(size.height - targetHeight) < minDiff) {\n                optimalSize = size;\n                minDiff = Math.abs(size.height - targetHeight);\n            }\n        }\n\n        if (optimalSize == null) {\n            minDiff = Double.MAX_VALUE;\n            for (Camera.Size size : sizes) {\n                if (Math.abs(size.height - targetHeight) < minDiff) {\n                    optimalSize = size;\n                    minDiff = Math.abs(size.height - targetHeight);\n                }\n            }\n        }\n\n\n        return optimalSize;\n    }\n\n    /**\n     * 打开camera\n     *\n     * @param holder SurfaceHolder\n     * @throws IOException IOException\n     */\n    public synchronized void openDriver(SurfaceHolder holder, Context mContext)\n            throws IOException {\n        Log.e(TAG, \"openDriver\");\n        Camera theCamera = camera;\n        if (theCamera == null) {\n            theCamera = open(requestedCameraId, mContext);\n            if (theCamera == null) {\n                throw new IOException();\n            }\n            camera = theCamera;\n        }\n        theCamera.setPreviewDisplay(holder);\n\n//        if (!initialized) {\n//            initialized = true;\n//            parameters = camera.getParameters();\n//            parameters.setPreviewSize(800, 600);\n//            parameters.setPictureFormat(ImageFormat.JPEG);\n//            parameters.setJpegQuality(100);\n//            parameters.setPictureSize(800, 600);\n////            theCamera.setParameters(parameters);\n//        }\n    }\n\n    /**\n     * camera是否打开\n     *\n     * @return camera是否打开\n     */\n    public synchronized boolean isOpen() {\n        return camera != null;\n    }\n\n    /**\n     * 关闭camera\n     */\n    public synchronized void closeDriver() {\n        Log.e(TAG, \"closeDriver\");\n        if (camera != null) {\n            camera.release();\n            camera = null;\n        }\n    }\n\n    /**\n     * 开始预览\n     */\n    public synchronized void startPreview(Camera.PreviewCallback mp) {\n        Log.e(TAG, \"startPreview\");\n        Camera theCamera = camera;\n        if (theCamera != null && !previewing) {\n//            theCamera.setOneShotPreviewCallback(mp);\n            theCamera.startPreview();\n            previewing = true;\n            autoFocusManager = new AutoFocusManager(camera, mp);\n        }\n//        camera.setPreviewCallback(new Camera.PreviewCallback() {\n//            @Override\n//            public void onPreviewFrame(byte[] data, Camera camera) {\n//                Log.d(\"zka\",\"onPreviewFrame\");\n//            }\n//        });\n    }\n\n    /**\n     * 关闭预览\n     */\n    public synchronized void stopPreview() {\n        Log.e(TAG, \"stopPreview\");\n        if (autoFocusManager != null) {\n            autoFocusManager.stop();\n            autoFocusManager = null;\n        }\n        if (camera != null && previewing) {\n            camera.stopPreview();\n            previewing = false;\n        }\n    }\n\n    /**\n     * 打开闪光灯\n     */\n    public synchronized void openLight() {\n        Log.e(TAG, \"openLight\");\n        if (camera != null) {\n            parameters = camera.getParameters();\n            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);\n            camera.setParameters(parameters);\n        }\n    }\n\n    /**\n     * 关闭闪光灯\n     */\n    public synchronized void offLight() {\n        Log.e(TAG, \"offLight\");\n        if (camera != null) {\n            parameters = camera.getParameters();\n            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);\n            camera.setParameters(parameters);\n        }\n    }\n\n    /**\n     * 拍照\n     *\n     * @param shutter ShutterCallback\n     * @param raw     PictureCallback\n     * @param jpeg    PictureCallback\n     */\n    public synchronized void takePicture(final Camera.ShutterCallback shutter, final Camera.PictureCallback raw,\n                                         final Camera.PictureCallback jpeg) {\n\n        camera.takePicture(shutter, raw, jpeg);\n\n\n    }\n\n    public int getScreenWidth(Context context) {\n        DisplayMetrics dm = context.getResources().getDisplayMetrics();\n        return dm.widthPixels;\n    }\n\n    /**\n     * 获得屏幕高度\n     *\n     * @param context 上下文\n     * @return 屏幕除去通知栏的高度\n     */\n    public int getScreenHeight(Context context) {\n        DisplayMetrics dm = context.getResources().getDisplayMetrics();\n        return dm.heightPixels;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/kingsoft/idcardocr_china/idcardocr/PreviewBorderView.java",
    "content": "package com.kingsoft.idcardocr_china.idcardocr;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.graphics.PixelFormat;\nimport android.graphics.PorterDuff;\nimport android.graphics.PorterDuffXfermode;\nimport android.graphics.RectF;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.util.TypedValue;\nimport android.view.SurfaceHolder;\nimport android.view.SurfaceView;\n\nimport com.kingsoft.idcardocr_china.R;\n\n\npublic class PreviewBorderView extends SurfaceView implements SurfaceHolder.Callback, Runnable {\n    private static final String DEFAULT_TIPS_TEXT = \"请将身份证照片面置于框内扫描，并尽量对齐边框\";\n    private static final int DEFAULT_TIPS_TEXT_SIZE = 18;\n    private static final int DEFAULT_TIPS_TEXT_COLOR = Color.GREEN;\n    private int mScreenH;\n    private int mScreenW;\n    private Canvas mCanvas;\n    private Paint mPaint;\n    private Paint mPaintLine;\n    private SurfaceHolder mHolder;\n    private Thread mThread;\n    /**\n     * 自定义属性\n     */\n    private float tipTextSize;\n    private int tipTextColor;\n    private String tipText;\n\n    public PreviewBorderView(Context context) {\n        this(context, null);\n    }\n\n    public PreviewBorderView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public PreviewBorderView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initAttrs(context, attrs);\n        init();\n    }\n\n    /**\n     * 初始化自定义属性\n     *\n     * @param context Context\n     * @param attrs   AttributeSet\n     */\n    private void initAttrs(Context context, AttributeSet attrs) {\n        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PreviewBorderView);\n        try {\n            tipTextSize = a.getDimension(R.styleable.PreviewBorderView_tipTextSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_TIPS_TEXT_SIZE, getResources().getDisplayMetrics()));\n            tipTextColor = a.getColor(R.styleable.PreviewBorderView_tipTextColor, DEFAULT_TIPS_TEXT_COLOR);\n            tipText = a.getString(R.styleable.PreviewBorderView_tipText);\n            if (tipText == null) {\n                tipText = DEFAULT_TIPS_TEXT;\n            }\n        } finally {\n            a.recycle();\n        }\n\n\n    }\n\n    /**\n     * 初始化绘图变量\n     */\n    private void init() {\n        this.mHolder = getHolder();\n        this.mHolder.addCallback(this);\n        this.mHolder.setFormat(PixelFormat.TRANSPARENT);\n        setZOrderOnTop(true);\n        setZOrderMediaOverlay(true);\n        this.mPaint = new Paint();\n        this.mPaint.setAntiAlias(true);\n        this.mPaint.setColor(Color.WHITE);\n        this.mPaint.setStyle(Paint.Style.FILL_AND_STROKE);\n        this.mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));\n        this.mPaintLine = new Paint();\n        this.mPaintLine.setColor(Color.WHITE);\n        this.mPaintLine.setStrokeWidth(3.0F);\n        setKeepScreenOn(true);\n    }\n\n    /**\n     * 绘制取景框\n     */\n    private void draw() {\n        try {\n            this.mCanvas = this.mHolder.lockCanvas();\n            this.mCanvas.drawARGB(100, 0, 0, 0);\n//            this.mScreenW = (this.mScreenH * 4 / 3);\n            Log.e(\"TAG\", \"mScreenW:\" + mScreenW + \" mScreenH:\" + mScreenH);\n            this.mCanvas.drawRect(new RectF(this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6, this.mScreenH * 1 / 6, this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6, this.mScreenH - this.mScreenH * 1 / 6), this.mPaint);\n            this.mCanvas.drawLine(this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6, this.mScreenH * 1 / 6, this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6, this.mScreenH * 1 / 6 + 150, this.mPaintLine);\n            this.mCanvas.drawLine(this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6, this.mScreenH * 1 / 6, this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6 + 150, this.mScreenH * 1 / 6, this.mPaintLine);\n            this.mCanvas.drawLine(this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6, this.mScreenH * 1 / 6, this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6, this.mScreenH * 1 / 6 + 150, this.mPaintLine);\n            this.mCanvas.drawLine(this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6, this.mScreenH * 1 / 6, this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6 - 150, this.mScreenH * 1 / 6, this.mPaintLine);\n            this.mCanvas.drawLine(this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6, this.mScreenH - this.mScreenH * 1 / 6, this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6, this.mScreenH - this.mScreenH * 1 / 6 - 150, this.mPaintLine);\n            this.mCanvas.drawLine(this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6, this.mScreenH - this.mScreenH * 1 / 6, this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6 + 150, this.mScreenH - this.mScreenH * 1 / 6, this.mPaintLine);\n            this.mCanvas.drawLine(this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6, this.mScreenH - this.mScreenH * 1 / 6, this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6, this.mScreenH - this.mScreenH * 1 / 6 - 150, this.mPaintLine);\n            this.mCanvas.drawLine(this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6, this.mScreenH - this.mScreenH * 1 / 6, this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6 - 150, this.mScreenH - this.mScreenH * 1 / 6, this.mPaintLine);\n\n            mPaintLine.setTextSize(tipTextSize);\n            mPaintLine.setAntiAlias(true);\n            mPaintLine.setDither(true);\n            float length = mPaintLine.measureText(tipText);\n\n            this.mCanvas.drawText(tipText, this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6 + this.mScreenH / 2 - length / 2, this.mScreenH * 1 / 2 - tipTextSize, mPaintLine);\n            Log.e(\"TAG\", \"left:\" + (this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 / 6));\n            Log.e(\"TAG\", \"top:\" + (this.mScreenH * 1 / 6));\n            Log.e(\"TAG\", \"right:\" + (this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 / 6));\n            Log.e(\"TAG\", \"bottom:\" + (this.mScreenH - this.mScreenH * 1 / 6));\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            if (this.mCanvas != null) {\n                this.mHolder.unlockCanvasAndPost(this.mCanvas);\n            }\n        }\n    }\n\n\n    @Override\n    public void surfaceCreated(SurfaceHolder holder) {\n        //获得宽高，开启子线程绘图\n        this.mScreenW = getWidth();\n        this.mScreenH = getHeight();\n        this.mThread = new Thread(this);\n        this.mThread.start();\n    }\n\n    @Override\n    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {\n\n    }\n\n    @Override\n    public void surfaceDestroyed(SurfaceHolder holder) {\n        //停止线程\n        try {\n            mThread.interrupt();\n            mThread = null;\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Override\n    public void run() {\n        //子线程绘图\n        draw();\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/layout/activity_camera.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\">\n\n\n    <SurfaceView\n        android:id=\"@+id/surfaceview\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"/>\n\n\n    <com.kingsoft.idcardocr_china.idcardocr.PreviewBorderView\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/borderview\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentLeft=\"true\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_centerInParent=\"true\"\n        app:tipTextSize=\"16dp\"\n        />\n\n    <Button\n        android:id=\"@+id/btn_close\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginLeft=\"10dp\"\n        android:layout_marginTop=\"10dp\"\n        android:background=\"@mipmap/carmer_back\"/>\n\n    <LinearLayout\n        android:id=\"@+id/linearlaout\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_marginRight=\"10dp\"\n        android:layout_marginTop=\"10dp\"\n        android:gravity=\"center\"\n        android:orientation=\"vertical\">\n\n\n        <Button\n            android:id=\"@+id/light\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n\n            android:background=\"@mipmap/open_falshlight\"\n            android:textColor=\"#ffffffff\"/>\n\n        <TextView\n\n            android:id=\"@+id/tv_openlight\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"打开闪光灯\"\n            android:textColor=\"#ffffffff\"/>\n\n    </LinearLayout>\n\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/activity_main\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <Button\n        android:id=\"@+id/btn_go\"\n        android:layout_marginTop=\"20dp\"\n        android:textSize=\"20sp\"\n        android:text=\"开始扫描\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"/>\n    <TextView\n        android:id=\"@+id/tv_id\"\n        android:textSize=\"20sp\"\n        android:layout_marginTop=\"20dp\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"身份证号：\"/>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"CircleImageView\">\n        <attr name=\"border_width\" format=\"dimension\" />\n        <attr name=\"border_color\" format=\"color\" />\n    </declare-styleable>\n    <declare-styleable name=\"PreviewBorderView\">\n        <attr name=\"tipText\" format=\"string\"/>\n        <attr name=\"tipTextColor\" format=\"color|reference\"/>\n        <attr name=\"tipTextSize\" format=\"dimension\"/>\n    </declare-styleable>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">IDCardOCR_China</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/test/java/com/kingsoft/idcardocr_china/ExampleUnitTest.java",
    "content": "package com.kingsoft.idcardocr_china;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.2.3'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Dec 28 10:00:20 PST 2015\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.14.1-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\n"
  }
]