├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── aadhaar_icon-web.png
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── aadhaar_icon.png
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── aadhaar_icon.png
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── aadhaar_icon.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── aadhaar_icon.png
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── aadhaar_icon.png
│ │ │ ├── values
│ │ │ │ ├── styles.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── strings.xml
│ │ │ ├── menu
│ │ │ │ └── menu_main.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ └── layout
│ │ │ │ └── activity_main.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── org
│ │ │ └── commcarehq
│ │ │ └── aadharuid
│ │ │ ├── ScanResultResponseAdapter.java
│ │ │ ├── MainActivity.java
│ │ │ └── ScanResult.java
│ ├── androidTest
│ │ └── java
│ │ │ └── org
│ │ │ └── commcarehq
│ │ │ └── aadharuid
│ │ │ └── ApplicationTest.java
│ └── test
│ │ └── java
│ │ └── org
│ │ └── commcarehq
│ │ └── aadharuid
│ │ └── ScanResultTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .travis.yml
├── .gitignore
├── gradle.properties
├── LICENSE
├── README.md
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/src/main/aadhaar_icon-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/aadhaar_icon-web.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/aadhaar_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-hdpi/aadhaar_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/aadhaar_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-mdpi/aadhaar_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/aadhaar_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-xhdpi/aadhaar_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/aadhaar_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-xxhdpi/aadhaar_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/aadhaar_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimagi/AadharUID/HEAD/app/src/main/res/mipmap-xxxhdpi/aadhaar_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Oct 26 21:25:33 IST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | script: "./gradlew check"
3 | android:
4 | components:
5 | - platform-tools
6 | - tools
7 | - build-tools-28.0.3
8 | - android-28
9 | - extra-android-m2repository
10 | before_cache:
11 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
12 | cache:
13 | directories:
14 | - $HOME/.gradle/caches/
15 | - $HOME/.gradle/wrapper/
16 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Aadhar UID
3 |
4 | Hello world!
5 | Settings
6 | Please install barcode scanner
7 | Unrecognized field for odk_intent_data:
8 |
9 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/org/commcarehq/aadharuid/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package org.commcarehq.aadharuid;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 | /*/build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 |
30 | # Android Studio
31 | /.idea/*
32 | .DS_Store
33 | /captures
34 | *.iml
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/droberts/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015, Dimagi
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of AadharUID nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | ext {
4 | // Obtained from ~/.gradle/gradle.properites on build server or load default
5 | // empty strings.
6 | RELEASE_STORE_FILE = project.properties['RELEASE_STORE_FILE'] ?: "."
7 | RELEASE_STORE_PASSWORD = project.properties['RELEASE_STORE_PASSWORD'] ?: ""
8 | RELEASE_KEY_ALIAS = project.properties['RELEASE_KEY_ALIAS'] ?: ""
9 | RELEASE_KEY_PASSWORD = project.properties['RELEASE_KEY_PASSWORD'] ?: ""
10 | TRUSTED_SOURCE_PUBLIC_KEY = project.properties['TRUSTED_SOURCE_PUBLIC_KEY'] ?:
11 | "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHiuy2ULV4pobkuQN2TEjmR1tn" +
12 | "HJ+F335hm/lVdaFQzvBmeq64MUMbumheVLDJaSUiAVzqSHDKJWH01ZQRowqBYjwo" +
13 | "ycVSQSeO2glc6XZZ+CJudAPXe8iFWLQp3kBBnBmVcBXCOQFO7aLgQMv4nqKZsLW0" +
14 | "HaAJkjpnc165Os+aYwIDAQAB";
15 | }
16 |
17 | android {
18 | compileSdkVersion 28
19 |
20 | defaultConfig {
21 | applicationId "org.commcarehq.aadharuid"
22 | minSdkVersion 14
23 | targetSdkVersion 27
24 | versionCode 4
25 | versionName "1.0.6"
26 | }
27 | signingConfigs {
28 | release {
29 | storeFile file(project.ext.RELEASE_STORE_FILE)
30 | storePassword project.ext.RELEASE_STORE_PASSWORD
31 | keyAlias project.ext.RELEASE_KEY_ALIAS
32 | keyPassword project.ext.RELEASE_KEY_PASSWORD
33 | }
34 | }
35 | buildTypes {
36 | release {
37 | minifyEnabled false
38 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
39 | signingConfig signingConfigs.release
40 | }
41 | }
42 | }
43 |
44 | dependencies {
45 | testImplementation 'junit:junit:4.12'
46 | implementation 'com.android.support:appcompat-v7:28.0.0'
47 | implementation ('com.journeyapps:zxing-android-embedded:3.6.0') { transitive = false }
48 | // Don't update this untill we drop support for pre-19 devices
49 | implementation 'com.google.zxing:core:3.3.0'
50 | }
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AadharUID
2 |
3 | AadharUID is an all-purpose scanner app1 for the national Indian Aadhar2 health card.
4 |
5 |
6 | 1. AadharUID does no scanning itself, but can be used with any popular Android barcode scanner,
7 | such as QR Droid or Barcode.
8 | 2. also spelled Aadhaar
9 |
10 |
11 | ## Callout interface
12 |
13 | AadharUID does not do much as an app by itself, but rather provides an interface through which
14 | other applications can call it. It was built for integration with CommCare, but any Android app
15 | can access it through the following callout interface.
16 |
17 | ### Making a request
18 |
19 | ```java
20 | Intent intent = new Intent("org.commcarehq.aadharuid.barcode.LAUNCH");
21 | // optional: specify which field you want returned to you
22 | // as `intent.getExtra("odk_intent_data")`.
23 | // default value is "statusText"
24 | intent.putExtra("odk_intent_data_field", "uid");
25 | ```
26 |
27 | ### Receiving a response
28 |
29 | #### odk_intent_bundle
30 | ```java
31 | intent.getBundleExtra("odk_intent_bundle")
32 | ```
33 |
34 | This bundle will contain the following fields:
35 | - Special values:
36 | - `statusCode` either `"0"` (success) or `"1"` (parse error)
37 | - `statusText` either `"✓"` (success) or `"✗"` (any failure)
38 | - `rawString` the raw string represented by the QR Code or barcode
39 | - Values straight from the Aadhar barcode
40 | - `co`
41 | - `dist`
42 | - `dob` normalized to YYYY-MM-DD
43 | - `dobGuess` dob if provided or else yob-06-01
44 | - `gender` normalized to `M` or `F`
45 | - `house`
46 | - `lm`
47 | - `loc`
48 | - `name`
49 | - `pc`
50 | - `po`
51 | - `state`
52 | - `street`
53 | - `subdist`
54 | - `uid`
55 | - `vtc`
56 | - `yob`
57 |
58 | Some Aadhar cards use a 2D barcode. On these cards,
59 | only the `uid` is encoded; the rest of the values will be `""`.
60 |
61 | #### odk_intent_data
62 | ```java
63 | intent.getStringExtra("odk_intent_data")
64 | ```
65 |
66 | This value will be set to whatever field was requested through
67 | the `odk_intent_data_field` extra. For example, if `odk_intent_data_field` was set to `"uid"` in the request intent,
68 | then the `odk_intent_data` extra will be set to the `uid` value.
69 | By default it is set to `statusText`.
70 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/java/org/commcarehq/aadharuid/ScanResultResponseAdapter.java:
--------------------------------------------------------------------------------
1 | package org.commcarehq.aadharuid;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 |
6 | /**
7 | * Created by droberts on 10/8/15.
8 | */
9 | public class ScanResultResponseAdapter {
10 | private ScanResult scanResult;
11 |
12 | private String odkIntentDataField;
13 | private Intent responseIntent;
14 | private boolean hasOdkIntentDataFieldError = false;
15 |
16 | public String getOdkIntentDataField() {
17 | return odkIntentDataField;
18 | }
19 |
20 | public boolean getHasOdkIntentDataFieldError() {
21 | return hasOdkIntentDataFieldError;
22 | }
23 |
24 | public Intent getResponseIntent() {
25 | return responseIntent;
26 | }
27 |
28 | public ScanResultResponseAdapter(ScanResult scanResult, Intent requestIntent) {
29 | this.scanResult = scanResult;
30 | parseRequestIntent(requestIntent);
31 | populateResponseIntent();
32 | }
33 |
34 | private void parseRequestIntent(Intent inputIntent) {
35 | odkIntentDataField = inputIntent.getStringExtra("odk_intent_data_field");
36 | if (odkIntentDataField == null) {
37 | odkIntentDataField = "statusText";
38 | }
39 | }
40 |
41 | private void populateResponseIntent() {
42 | responseIntent = new Intent();
43 |
44 | Bundle responses = new Bundle();
45 | responses.putString("statusCode", Integer.toString(scanResult.statusCode));
46 | responses.putString("statusText", scanResult.statusText);
47 | responses.putString("rawString", scanResult.rawString);
48 | responses.putString("type", scanResult.type);
49 | responses.putString("uid", scanResult.uid);
50 | responses.putString("name", scanResult.name);
51 | responses.putString("gender", scanResult.gender);
52 | responses.putString("yob", scanResult.yob);
53 | responses.putString("co", scanResult.co);
54 | responses.putString("house", scanResult.house);
55 | responses.putString("street", scanResult.street);
56 | responses.putString("lm", scanResult.lm);
57 | responses.putString("loc", scanResult.loc);
58 | responses.putString("vtc", scanResult.vtc);
59 | responses.putString("po", scanResult.po);
60 | responses.putString("dist", scanResult.dist);
61 | responses.putString("subdist", scanResult.subdist);
62 | responses.putString("state", scanResult.state);
63 | responses.putString("pc", scanResult.pc);
64 | responses.putString("dob", scanResult.dob);
65 | responses.putString("dobGuess", scanResult.dobGuess);
66 |
67 | String odkIntentData = responses.getString(odkIntentDataField);
68 | responseIntent.putExtra("odk_intent_bundle", responses);
69 | responseIntent.putExtra("odk_intent_data", odkIntentData);
70 | if (odkIntentData == null) {
71 | hasOdkIntentDataFieldError = true;
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/org/commcarehq/aadharuid/MainActivity.java:
--------------------------------------------------------------------------------
1 | package org.commcarehq.aadharuid;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.Menu;
8 | import android.view.MenuItem;
9 | import android.widget.Toast;
10 |
11 | import com.google.zxing.integration.android.IntentIntegrator;
12 | import com.google.zxing.integration.android.IntentResult;
13 |
14 |
15 | public class MainActivity extends AppCompatActivity {
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_main);
21 | }
22 |
23 | @Override
24 | protected void onResume() {
25 | super.onResume();
26 | if (!isFinishing()) {
27 | callBarcodeScanner();
28 | }
29 | }
30 |
31 | @Override
32 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
33 |
34 | if (requestCode == IntentIntegrator.REQUEST_CODE) {
35 | IntentResult intentResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
36 | if (intentResult != null) {
37 | if (intentResult.getContents() == null) {
38 | setResult(Activity.RESULT_CANCELED);
39 | finish();
40 | } else {
41 | String result = intentResult.getContents();
42 | returnOdkResult(result);
43 | }
44 | }
45 | } else {
46 | super.onActivityResult(requestCode, resultCode, data);
47 | }
48 | }
49 |
50 | private void callBarcodeScanner() {
51 | Intent intent = new IntentIntegrator(this)
52 | .setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
53 | .createScanIntent();
54 | startActivityForResult(intent, IntentIntegrator.REQUEST_CODE);
55 | }
56 |
57 |
58 | private void returnOdkResult(String result) {
59 | ScanResult scanResult = new ScanResult(result);
60 | ScanResultResponseAdapter responseAdapter = new ScanResultResponseAdapter(scanResult, getIntent());
61 | if (responseAdapter.getHasOdkIntentDataFieldError()) {
62 | Toast.makeText(this,
63 | getResources().getString(R.string.odk_intent_data_field_error)
64 | + " " + responseAdapter.getOdkIntentDataField(),
65 | Toast.LENGTH_SHORT).show();
66 | }
67 | setResult(Activity.RESULT_OK, responseAdapter.getResponseIntent());
68 | finish();
69 | }
70 |
71 | @Override
72 | public boolean onCreateOptionsMenu(Menu menu) {
73 | // Inflate the menu; this adds items to the action bar if it is present.
74 | getMenuInflater().inflate(R.menu.menu_main, menu);
75 | return true;
76 | }
77 |
78 | @Override
79 | public boolean onOptionsItemSelected(MenuItem item) {
80 | // Handle action bar item clicks here. The action bar will
81 | // automatically handle clicks on the Home/Up button, so long
82 | // as you specify a parent activity in AndroidManifest.xml.
83 | int id = item.getItemId();
84 |
85 | //noinspection SimplifiableIfStatement
86 | if (id == R.id.action_settings) {
87 | return true;
88 | }
89 |
90 | return super.onOptionsItemSelected(item);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/app/src/main/java/org/commcarehq/aadharuid/ScanResult.java:
--------------------------------------------------------------------------------
1 | package org.commcarehq.aadharuid;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import org.w3c.dom.Document;
6 | import org.w3c.dom.NamedNodeMap;
7 | import org.w3c.dom.Node;
8 | import org.xml.sax.SAXException;
9 |
10 | import java.io.ByteArrayInputStream;
11 | import java.io.ByteArrayOutputStream;
12 | import java.io.IOException;
13 | import java.math.BigInteger;
14 | import java.nio.charset.Charset;
15 | import java.text.ParseException;
16 | import java.text.SimpleDateFormat;
17 | import java.util.Arrays;
18 | import java.util.Date;
19 | import java.util.zip.GZIPInputStream;
20 |
21 | import javax.xml.parsers.DocumentBuilder;
22 | import javax.xml.parsers.DocumentBuilderFactory;
23 | import javax.xml.parsers.ParserConfigurationException;
24 |
25 | /**
26 | * Created by droberts on 7/24/15.
27 | *
31 | */
32 | public class ScanResult {
33 | public static final int STATUS_SUCCESS = 0;
34 | public static final int STATUS_PARSE_ERROR = 1;
35 | private static final int NUMBER_OF_PARAMS_IN_SECURE_QR_CODE = 15;
36 |
37 | public static final String QR_CODE_TYPE_SECURE = "secure";
38 | public static final String QR_CODE_TYPE_XML = "xml";
39 | public static final String QR_CODE_TYPE_UID_NUMBER = "uid_number";
40 | public static final String QR_CODE_TYPE_UNKNOWN = "unknown";
41 |
42 | public final int statusCode;
43 | public final String rawString;
44 | public final String uid;
45 | public final String name;
46 | public final String gender; // M/F
47 | public final String yob; // year of birth
48 | public final String co; // "D/O: Father Name" (DMR): not sure what this means
49 | public final String house;
50 | public final String street;
51 | public final String lm; // address
52 | public final String loc; // neighborhood
53 | public final String vtc; // village
54 | public final String po; // city
55 | public final String dist; // district
56 | public final String subdist; // region
57 | public final String state;
58 | public final String pc; // postal code
59 | public final String dob; // date of birth
60 | public final String dobGuess; // date of birth or June 1 of year of birth
61 | public final String statusText; // either `"✓"` (success) or `"✗"` (any failure)
62 | public final String type; // either `"✓"` (success) or `"✗"` (any failure)
63 |
64 | private String getAttributeOrEmptyString(NamedNodeMap attributes, String attributeName) {
65 | Node node = attributes.getNamedItem(attributeName);
66 | if (node != null) {
67 | return node.getTextContent();
68 | } else {
69 | return "";
70 | }
71 | }
72 |
73 | public ScanResult(String input) {
74 | rawString = input;
75 |
76 | // copied from http://www.java-samples.com/showtutorial.php?tutorialid=152
77 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
78 | Document dom;
79 | try {
80 |
81 | //Using factory get an instance of document builder
82 | DocumentBuilder db = dbf.newDocumentBuilder();
83 | // Replace ?xml... with with
88 | input = input.replaceFirst("^<\\?xml ([^>]+)\\?\">", "");
89 | //parse using builder to get DOM representation of the XML file
90 | dom = db.parse(new ByteArrayInputStream(input.getBytes("UTF-8")));
91 |
92 | } catch (ParserConfigurationException | SAXException | IOException e) {
93 | dom = null;
94 | }
95 |
96 | if (dom != null) {
97 | type = QR_CODE_TYPE_XML;
98 | Node node = dom.getChildNodes().item(0);
99 | NamedNodeMap attributes = node.getAttributes();
100 | statusCode = STATUS_SUCCESS;
101 | uid = getAttributeOrEmptyString(attributes, "uid");
102 | name = getAttributeOrEmptyString(attributes, "name");
103 | String rawGender = getAttributeOrEmptyString(attributes, "gender");
104 | try {
105 | rawGender = formatGender(rawGender);
106 | } catch (ParseException e) {
107 | System.err.println("Expected gender to be one of m, f, male, female; got " + rawGender);
108 | }
109 | gender = rawGender;
110 | yob = getAttributeOrEmptyString(attributes, "yob");
111 | co = getAttributeOrEmptyString(attributes, "co");
112 | house = getAttributeOrEmptyString(attributes, "house");
113 | street = getAttributeOrEmptyString(attributes, "street");
114 | lm = getAttributeOrEmptyString(attributes, "lm");
115 | loc = getAttributeOrEmptyString(attributes, "loc");
116 | vtc = getAttributeOrEmptyString(attributes, "vtc");
117 | po = getAttributeOrEmptyString(attributes, "po");
118 | dist = getAttributeOrEmptyString(attributes, "dist");
119 | subdist = getAttributeOrEmptyString(attributes, "subdist");
120 | state = getAttributeOrEmptyString(attributes, "state");
121 | pc = getAttributeOrEmptyString(attributes, "pc");
122 | dob= formatDate(getAttributeOrEmptyString(attributes, "dob"),
123 | new String[] {"dd/MM/yyyy", "yyyy-MM-dd"});
124 |
125 | } else if (rawString.matches("\\d{12}")) {
126 | type = QR_CODE_TYPE_UID_NUMBER;
127 | statusCode = STATUS_SUCCESS;
128 | uid = rawString;
129 | name = "";
130 | gender = "";
131 | yob = "";
132 | co = "";
133 | house = "";
134 | street = "";
135 | lm = "";
136 | loc = "";
137 | vtc = "";
138 | po = "";
139 | dist = "";
140 | subdist = "";
141 | state = "";
142 | pc = "";
143 | dob = "";
144 | } else if (rawString.matches("[0-9]*")) {
145 | type = QR_CODE_TYPE_SECURE;
146 | byte[] msgInBytes = null;
147 | try {
148 | msgInBytes = decompressByteArray(new BigInteger(rawString).toByteArray());
149 | } catch (IOException e) {
150 | e.printStackTrace();
151 | }
152 | if (msgInBytes != null) {
153 | int[] delimiters = locateDelimiters(msgInBytes);
154 | String referenceId = getValueInRange(msgInBytes, delimiters[0] + 1, delimiters[1]);
155 | uid = referenceId.substring(0, 4);
156 | name = getValueInRange(msgInBytes, delimiters[1] + 1, delimiters[2]);
157 | dob = formatDate(getValueInRange(msgInBytes, delimiters[2] + 1, delimiters[3]),
158 | new String[] {"dd-MM-yyyy", "dd/MM/yyyy"});
159 | yob = dob.substring(0, 4);
160 | gender = getValueInRange(msgInBytes, delimiters[3] + 1, delimiters[4]);
161 | co = getValueInRange(msgInBytes, delimiters[4] + 1, delimiters[5]);
162 | dist = getValueInRange(msgInBytes, delimiters[5] + 1, delimiters[6]);
163 | lm = getValueInRange(msgInBytes, delimiters[6] + 1, delimiters[7]);
164 | house = getValueInRange(msgInBytes, delimiters[7] + 1, delimiters[8]);
165 | loc = getValueInRange(msgInBytes, delimiters[8] + 1, delimiters[9]);
166 | pc = getValueInRange(msgInBytes, delimiters[9] + 1, delimiters[10]);
167 | po = getValueInRange(msgInBytes, delimiters[10] + 1, delimiters[11]);
168 | state = getValueInRange(msgInBytes, delimiters[11] + 1, delimiters[12]);
169 | street = getValueInRange(msgInBytes, delimiters[12] + 1, delimiters[13]);
170 | subdist = getValueInRange(msgInBytes, delimiters[13] + 1, delimiters[14]);
171 | vtc = getValueInRange(msgInBytes, delimiters[14] + 1, delimiters[15]);
172 | statusCode = STATUS_SUCCESS;
173 | } else {
174 | statusCode = STATUS_PARSE_ERROR;
175 | uid = "";
176 | name = "";
177 | gender = "";
178 | yob = "";
179 | co = "";
180 | house = "";
181 | street = "";
182 | lm = "";
183 | loc = "";
184 | vtc = "";
185 | po = "";
186 | dist = "";
187 | subdist = "";
188 | state = "";
189 | pc = "";
190 | dob = "";
191 | }
192 | } else {
193 | type = QR_CODE_TYPE_UNKNOWN;
194 | statusCode = STATUS_PARSE_ERROR;
195 | uid = "";
196 | name = "";
197 | gender = "";
198 | yob = "";
199 | co = "";
200 | house = "";
201 | street = "";
202 | lm = "";
203 | loc = "";
204 | vtc = "";
205 | po = "";
206 | dist = "";
207 | subdist = "";
208 | state = "";
209 | pc = "";
210 | dob = "";
211 | }
212 |
213 | dobGuess = getDobGuess(dob, yob);
214 | statusText = getStatusText(statusCode);
215 | }
216 |
217 | private static int[] locateDelimiters(byte[] msgInBytes) {
218 | int[] delimiters = new int[NUMBER_OF_PARAMS_IN_SECURE_QR_CODE + 1];
219 | int index = 0;
220 | int delimiterIndex;
221 | for (int i = 0; i <= NUMBER_OF_PARAMS_IN_SECURE_QR_CODE; i++) {
222 | delimiterIndex = getNextDelimiterIndex(msgInBytes, index);
223 | delimiters[i] = delimiterIndex;
224 | index = delimiterIndex + 1;
225 | }
226 | return delimiters;
227 | }
228 |
229 |
230 | private static String getValueInRange(byte[] msgInBytes, int start, int end) {
231 | return new String(Arrays.copyOfRange(msgInBytes, start, end), Charset.forName("ISO-8859-1"));
232 | }
233 |
234 | private static int getNextDelimiterIndex(byte[] msgInBytes, int index) {
235 | int i = index;
236 | for (; i < msgInBytes.length; i++) {
237 | if (msgInBytes[i] == -1) {
238 | break;
239 | }
240 | }
241 | return i;
242 | }
243 |
244 | private static byte[] decompressByteArray(byte[] bytes) throws IOException {
245 | java.io.ByteArrayInputStream bytein = new ByteArrayInputStream(bytes);
246 | java.util.zip.GZIPInputStream gzin = new GZIPInputStream(bytein);
247 | java.io.ByteArrayOutputStream byteout = new ByteArrayOutputStream();
248 |
249 | int res = 0;
250 | byte buf[] = new byte[1024];
251 | while (res >= 0) {
252 | res = gzin.read(buf, 0, buf.length);
253 | if (res > 0) {
254 | byteout.write(buf, 0, res);
255 | }
256 | }
257 | return byteout.toByteArray();
258 | }
259 |
260 | private String formatDate(String rawDateString, String[] possibleFormats) {
261 | if (rawDateString.equals("")) {
262 | return "";
263 | }
264 | SimpleDateFormat toFormat = new SimpleDateFormat("yyyy-MM-dd");
265 | Date date = null;
266 | ParseException parseException = null;
267 | for (String fromFormatPattern : possibleFormats) {
268 | try {
269 | SimpleDateFormat fromFormat = new SimpleDateFormat(fromFormatPattern);
270 | date = fromFormat.parse(rawDateString);
271 | break;
272 | } catch (ParseException e) {
273 | parseException = e;
274 | }
275 | }
276 | if (date != null) {
277 | return toFormat.format(date);
278 | } else if (parseException != null) {
279 | System.err.println("Expected dob to be in dd/mm/yyyy or yyyy-mm-dd format, got " + rawDateString);
280 | return rawDateString;
281 | } else {
282 | throw new AssertionError("This code is unreachable");
283 | }
284 | }
285 |
286 | @NonNull
287 | protected String formatGender(String gender) throws ParseException {
288 | String lowercaseGender = gender.toLowerCase();
289 | if (lowercaseGender.equals("male") || lowercaseGender.equals("m")) {
290 | return "M";
291 | } else if (lowercaseGender.equals("female") || lowercaseGender.equals("f")) {
292 | return "F";
293 | } else if (lowercaseGender.equals("other") || lowercaseGender.equals("o")) {
294 | return "O";
295 | } else {
296 | throw new ParseException("404 gender not found", 0);
297 | }
298 | }
299 |
300 | @NonNull
301 | private String getStatusText(int statusCode) {
302 | switch (statusCode) {
303 | case ScanResult.STATUS_SUCCESS:
304 | return "✓";
305 | default:
306 | return "✗";
307 | }
308 | }
309 |
310 | @NonNull
311 | private String getDobGuess(String dob, String yob) {
312 | if (dob.equals("")) {
313 | Integer yearInt;
314 | try {
315 | yearInt = Integer.parseInt(yob);
316 | } catch (NumberFormatException e) {
317 | return "";
318 | }
319 | // June 1 of the year
320 | return Integer.toString(yearInt) + "-06-01";
321 | } else {
322 | return dob;
323 | }
324 | }
325 | }
326 |
--------------------------------------------------------------------------------
/app/src/test/java/org/commcarehq/aadharuid/ScanResultTest.java:
--------------------------------------------------------------------------------
1 | package org.commcarehq.aadharuid;
2 |
3 | import junit.framework.TestCase;
4 |
5 |
6 | /**
7 | * Created by droberts on 7/24/15.
8 | */
9 | public class ScanResultTest extends TestCase {
10 | public void testXML() {
11 | String rawString = "";
16 | ScanResult scanResult = new ScanResult(rawString);
17 | assertEquals(scanResult.type, ScanResult.QR_CODE_TYPE_XML);
18 | assertEquals(scanResult.statusCode, 0);
19 | assertEquals(scanResult.statusText, "✓");
20 | assertEquals(scanResult.rawString, rawString);
21 | assertEquals(scanResult.uid, "123456789012");
22 | assertEquals(scanResult.name, "First Last");
23 | assertEquals(scanResult.gender, "M/F");
24 | assertEquals(scanResult.yob, "YYYY");
25 | assertEquals(scanResult.co, "D/O: Father Name");
26 | assertEquals(scanResult.house, "house num");
27 | assertEquals(scanResult.street, "street name");
28 | assertEquals(scanResult.lm, "address");
29 | assertEquals(scanResult.loc, "neighborhood");
30 | assertEquals(scanResult.vtc, "village");
31 | assertEquals(scanResult.po, "city");
32 | assertEquals(scanResult.dist, "district");
33 | assertEquals(scanResult.subdist, "region");
34 | assertEquals(scanResult.state, "state");
35 | assertEquals(scanResult.pc, "postalcode");
36 | assertEquals(scanResult.dob, "1999-11-23");
37 | assertEquals(scanResult.dobGuess, "1999-11-23");
38 | }
39 |
40 | public void testSheelXML() {
41 | String rawString = "?xml version=\"1.0\" encoding=\"UTF-8\"?> " +
42 | "";
46 | ScanResult scanResult = new ScanResult(rawString);
47 | assertEquals(scanResult.type, ScanResult.QR_CODE_TYPE_XML);
48 | assertEquals(scanResult.statusCode, 0);
49 | assertEquals(scanResult.statusText, "✓");
50 | assertEquals(scanResult.rawString, rawString);
51 | assertEquals(scanResult.uid, "987098654123");
52 | assertEquals(scanResult.name, "Mockit");
53 | assertEquals(scanResult.gender, "M");
54 | assertEquals(scanResult.yob, "1989");
55 | assertEquals(scanResult.co, "S/O Jhailendno Kaear Kuioy");
56 | assertEquals(scanResult.house, "");
57 | assertEquals(scanResult.street, "");
58 | assertEquals(scanResult.lm, "null");
59 | assertEquals(scanResult.loc, "Vaishali Fiuhy");
60 | assertEquals(scanResult.vtc, "Jaipur");
61 | assertEquals(scanResult.po, "Vaishali Hugar");
62 | assertEquals(scanResult.dist, "Jaipur");
63 | assertEquals(scanResult.subdist, "");
64 | assertEquals(scanResult.state, "Rajasthan");
65 | assertEquals(scanResult.pc, "345234");
66 | assertEquals(scanResult.dob, "1989-06-07");
67 | assertEquals(scanResult.dobGuess, "1989-06-07");
68 | }
69 |
70 | public void testJustUID() {
71 | ScanResult scanResult = new ScanResult("123456789012");
72 | assertEquals(scanResult.type, ScanResult.QR_CODE_TYPE_UID_NUMBER);
73 | assertEquals(scanResult.statusCode, 0);
74 | assertEquals(scanResult.statusText, "✓");
75 | assertEquals(scanResult.rawString, "123456789012");
76 | assertEquals(scanResult.uid, "123456789012");
77 | assertEquals(scanResult.name, "");
78 | assertEquals(scanResult.gender, "");
79 | assertEquals(scanResult.yob, "");
80 | assertEquals(scanResult.co, "");
81 | assertEquals(scanResult.house, "");
82 | assertEquals(scanResult.street, "");
83 | assertEquals(scanResult.lm, "");
84 | assertEquals(scanResult.loc, "");
85 | assertEquals(scanResult.vtc, "");
86 | assertEquals(scanResult.po, "");
87 | assertEquals(scanResult.dist, "");
88 | assertEquals(scanResult.subdist, "");
89 | assertEquals(scanResult.state, "");
90 | assertEquals(scanResult.pc, "");
91 | assertEquals(scanResult.dob, "");
92 | assertEquals(scanResult.dobGuess, "");
93 | }
94 |
95 | public void testBizarreInput() {
96 | ScanResult scanResult = new ScanResult("http://i.imgur.com/XpgmoU1.jpg");
97 | assertEquals(scanResult.type, ScanResult.QR_CODE_TYPE_UNKNOWN);
98 | assertEquals(scanResult.statusCode, 1);
99 | assertEquals(scanResult.statusText, "✗");
100 | assertEquals(scanResult.rawString, "http://i.imgur.com/XpgmoU1.jpg");
101 | assertEquals(scanResult.uid, "");
102 | assertEquals(scanResult.name, "");
103 | assertEquals(scanResult.gender, "");
104 | assertEquals(scanResult.yob, "");
105 | assertEquals(scanResult.co, "");
106 | assertEquals(scanResult.house, "");
107 | assertEquals(scanResult.street, "");
108 | assertEquals(scanResult.lm, "");
109 | assertEquals(scanResult.loc, "");
110 | assertEquals(scanResult.vtc, "");
111 | assertEquals(scanResult.po, "");
112 | assertEquals(scanResult.dist, "");
113 | assertEquals(scanResult.subdist, "");
114 | assertEquals(scanResult.state, "");
115 | assertEquals(scanResult.pc, "");
116 | assertEquals(scanResult.dob, "");
117 | assertEquals(scanResult.dobGuess, "");
118 | }
119 |
120 | public void testNoDob() {
121 | String rawString = "?xml version=\"1.0\" encoding=\"UTF-8\"?> " +
122 | "";
126 | ScanResult scanResult = new ScanResult(rawString);
127 | assertEquals(scanResult.type, ScanResult.QR_CODE_TYPE_XML);
128 | assertEquals(scanResult.statusCode, 0);
129 | assertEquals(scanResult.statusText, "✓");
130 | assertEquals(scanResult.rawString, rawString);
131 | assertEquals(scanResult.uid, "987098654123");
132 | assertEquals(scanResult.name, "Mockit");
133 | assertEquals(scanResult.gender, "M");
134 | assertEquals(scanResult.yob, "1989");
135 | assertEquals(scanResult.co, "S/O Jhailendno Kaear Kuioy");
136 | assertEquals(scanResult.house, "");
137 | assertEquals(scanResult.street, "");
138 | assertEquals(scanResult.lm, "null");
139 | assertEquals(scanResult.loc, "Vaishali Fiuhy");
140 | assertEquals(scanResult.vtc, "Jaipur");
141 | assertEquals(scanResult.po, "Vaishali Hugar");
142 | assertEquals(scanResult.dist, "Jaipur");
143 | assertEquals(scanResult.subdist, "");
144 | assertEquals(scanResult.state, "Rajasthan");
145 | assertEquals(scanResult.pc, "345234");
146 | assertEquals(scanResult.dob, "");
147 | assertEquals(scanResult.dobGuess, "1989-06-01");
148 | }
149 | public void testMisplacedQuestionMark() {
150 | // same as testXML, but with a bad xml declaration: ...?"> intead of ..."?>
151 | String rawString = " " +
152 | "";
156 | ScanResult scanResult = new ScanResult(rawString);
157 | assertEquals(scanResult.type, ScanResult.QR_CODE_TYPE_XML);
158 | assertEquals(scanResult.statusCode, 0);
159 | assertEquals(scanResult.statusText, "✓");
160 | assertEquals(scanResult.rawString, rawString);
161 | assertEquals(scanResult.uid, "987098654123");
162 | assertEquals(scanResult.name, "Mockit");
163 | assertEquals(scanResult.gender, "M");
164 | assertEquals(scanResult.yob, "1989");
165 | assertEquals(scanResult.co, "S/O Jhailendno Kaear Kuioy");
166 | assertEquals(scanResult.house, "");
167 | assertEquals(scanResult.street, "");
168 | assertEquals(scanResult.lm, "null");
169 | assertEquals(scanResult.loc, "Vaishali Fiuhy");
170 | assertEquals(scanResult.vtc, "Jaipur");
171 | assertEquals(scanResult.po, "Vaishali Hugar");
172 | assertEquals(scanResult.dist, "Jaipur");
173 | assertEquals(scanResult.subdist, "");
174 | assertEquals(scanResult.state, "Rajasthan");
175 | assertEquals(scanResult.pc, "345234");
176 | assertEquals(scanResult.dob, "1989-06-07");
177 | assertEquals(scanResult.dobGuess, "1989-06-07");
178 | }
179 |
180 | public void testSecureQRCode() {
181 | // This is test data published from UIDAI
182 | String rawString = "6979414848205548481619299442879901900893978332594614407044767717485407280104077714658698163325401659212830920734233047578454701810567032015270223682917915825234703754712504887921309181789607809168884583848396456653007022479356336240198130363930881632367124738541517499494458139647378808680614169273221404741476596583953169248831376224396335169577064812987140578144885819479190173537644970232125142253963784979138011318798385442436099901621998283624816070080504830712594525760596934341576755626791590403636878139861665599383319429228364434183913197958738697001410493839281298692342829951566712530309758759364649701153639921979798429707566199261950037418171329283207372048014948669160666776198414040633384677104717697507521717586776709084200364956178863636105988867260929887577092955570407803783021397897341999914616790441029837229129746669225095633201097644321593502503404440714110515167034889128258965583435965030225845348564582051521348800742574442877087774194668983516629631073341202705453382780613775427336949283388084891654484225446940941660942440637784744293259916479841407088189462964489670231866481904237338494872813098890875845640034370370387108798950180220865436012752487216677041817312930119747601017807577565413977545693375480131324240696099879479436722576566447939593195590684591261809038023122178172006150499569185218838749337238281597037288924464009997530938336798176023597292328320965086990184531426188862965408313308973495924965144113396593829090645266653313774582036138982013368561474719154447134894466611560589758251829063226370300282175823479569847261439348404558251402273730865053482214589180028302043821438357583302818374143973997002745047526405755760407045006694423501337081780299815080324840337828812644300041900356816429114261098230198976752026002079876882796597235615015594486182057781476152918170746403157005216896239428521706033466061587608065036133153074432195952131368564234168005447770190345777024917629879639171161719929852078265309160759260989590618158889891835294735614366674503961584445497685736312628248483551986529867423016255476553691922054241686230968975229511700928171281549902682365302333677412951788839806869796040512235899311734337858684531156721416280114473368826463098485252394260075790386415875290922570568686439586036262465414002334117870088922801660529414759784318799843806130096998190881240404138869293309782335305296720666220243304175086358278211355789957998014801209332293458940463859106591986434520433810583569309224929264228263841477378949329312443958215939294432669464260216534074560882723006838459792812340253078330291135526952675203790833430237852831740601433198364243363569730205351077393441691141240055900819091229931605146865520183001810239708464322588389956036291760175558843819105418234580239610174323636606095262722940143706063698846499673285377621180570537788160304936809915237889489342387891057012783726694920184573202789672963922380028271124448024265644396686341508447830351380242127542393849410283830409594988503246799544444687606954881510597515686410993828907588979699141180160893062603338104857903239845856783130275935413569275439908789983311663211937449259444259898972766208";
183 | ScanResult scanResult = new ScanResult(rawString);
184 | assertEquals(scanResult.type, ScanResult.QR_CODE_TYPE_SECURE);
185 | assertEquals(scanResult.statusCode, 0);
186 | assertEquals(scanResult.statusText, "✓");
187 | assertEquals(scanResult.rawString, rawString);
188 | assertEquals(scanResult.uid, "8908");
189 | assertEquals(scanResult.name, "Penumarthi Venkat");
190 | assertEquals(scanResult.gender, "M");
191 | assertEquals(scanResult.yob, "1987");
192 | assertEquals(scanResult.co, "S/O: Pattabhi Rama Rao");
193 | assertEquals(scanResult.house, "4-83");
194 | assertEquals(scanResult.street, "Main Road");
195 | assertEquals(scanResult.lm, "Near Siva Temple");
196 | assertEquals(scanResult.loc, "Sctor-2");
197 | assertEquals(scanResult.vtc, "Aratlakatta");
198 | assertEquals(scanResult.po, "Aratlakatta");
199 | assertEquals(scanResult.dist, "East Godavari");
200 | assertEquals(scanResult.subdist, "Karapa");
201 | assertEquals(scanResult.state, "Andhra Pradesh");
202 | assertEquals(scanResult.pc, "533016");
203 | assertEquals(scanResult.dob, "1987-05-07");
204 | assertEquals(scanResult.dobGuess, "1987-05-07");
205 | }
206 | }
--------------------------------------------------------------------------------