├── 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 | 4 | 6 | 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 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 = " " + 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 = " " + 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 | } --------------------------------------------------------------------------------