giag
This commit is contained in:
parent
0c350c8553
commit
06a3dc6256
7 changed files with 180 additions and 46 deletions
31
app/src/main/java/uk/ac/lancaster/auditor/AuditActivity.kt
Normal file
31
app/src/main/java/uk/ac/lancaster/auditor/AuditActivity.kt
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package uk.ac.lancaster.auditor
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.support.v7.app.AppCompatActivity
|
||||||
|
import android.widget.Button
|
||||||
|
import uk.ac.lancaster.auditor.barcode.BarcodeScanActivity
|
||||||
|
|
||||||
|
class AuditActivity : AppCompatActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_audit)
|
||||||
|
|
||||||
|
findViewById<Button>(R.id.button).setOnClickListener {
|
||||||
|
val intent = Intent(applicationContext, ChooseRecordActivity::class.java)
|
||||||
|
startActivityForResult(intent, 1)
|
||||||
|
}
|
||||||
|
findViewById<Button>(R.id.button2).setOnClickListener {
|
||||||
|
val intent = Intent(applicationContext, ChooseRecordActivity::class.java)
|
||||||
|
startActivityForResult(intent, 1)
|
||||||
|
}
|
||||||
|
findViewById<Button>(R.id.button3).setOnClickListener {
|
||||||
|
val intent = Intent(applicationContext, ChooseRecordActivity::class.java)
|
||||||
|
startActivityForResult(intent, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(data: Intent?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package uk.ac.lancaster.auditor
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.support.v7.app.AppCompatActivity
|
||||||
|
import android.R.array
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ChooseRecordActivity : AppCompatActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_choose_record)
|
||||||
|
|
||||||
|
var fileList = getFilesDir().listFiles()
|
||||||
|
|
||||||
|
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, fileList)
|
||||||
|
(R.id.list).setAdapter(aa)
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,9 +11,13 @@ class MainActivity : AppCompatActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
findViewById<Button>(R.id.scan_ballot_qr).setOnClickListener {
|
findViewById<Button>(R.id.cast_vote).setOnClickListener {
|
||||||
val intent = Intent(applicationContext, BarcodeScanActivity::class.java)
|
val intent = Intent(applicationContext, BarcodeScanActivity::class.java)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
findViewById<Button>(R.id.audit_election).setOnClickListener {
|
||||||
|
val intent = Intent(applicationContext, AuditActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package uk.ac.lancaster.auditor.barcode
|
package uk.ac.lancaster.auditor.barcode
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.support.v7.app.AppCompatActivity
|
import android.support.v7.app.AppCompatActivity
|
||||||
|
@ -9,7 +10,7 @@ import android.util.Log
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileWriter
|
import java.io.FileOutputStream
|
||||||
import com.google.android.gms.common.api.CommonStatusCodes
|
import com.google.android.gms.common.api.CommonStatusCodes
|
||||||
import com.google.android.gms.vision.barcode.Barcode
|
import com.google.android.gms.vision.barcode.Barcode
|
||||||
import uk.ac.lancaster.auditor.BallotVerifyActivity
|
import uk.ac.lancaster.auditor.BallotVerifyActivity
|
||||||
|
@ -19,6 +20,18 @@ import uk.ac.lancaster.auditor.R
|
||||||
class BarcodeScanActivity : AppCompatActivity() {
|
class BarcodeScanActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var mResultTextView: TextView
|
private lateinit var mResultTextView: TextView
|
||||||
|
private var stage = 0
|
||||||
|
|
||||||
|
data class Record(val recordID: Int) {
|
||||||
|
var voterID: String = ""
|
||||||
|
var eventID: String = ""
|
||||||
|
var pollID: String = ""
|
||||||
|
var hashes: String = ""
|
||||||
|
var handle: String = ""
|
||||||
|
var hmac: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
private val record = Record(0)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -38,50 +51,32 @@ class BarcodeScanActivity : AppCompatActivity() {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
val barcode = data.getParcelableExtra<Barcode>(BarcodeCaptureActivity.BarcodeObject)
|
val barcode = data.getParcelableExtra<Barcode>(BarcodeCaptureActivity.BarcodeObject)
|
||||||
mResultTextView.text = barcode.displayValue
|
mResultTextView.text = barcode.displayValue
|
||||||
val handle = barcode.displayValue.split(";")[0]
|
|
||||||
val hmac = String(Base64.decode(barcode.displayValue.split(";")[1], Base64.DEFAULT))
|
|
||||||
|
|
||||||
// save the ballot
|
// Store the relevant info from whatever this QR code is for
|
||||||
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
|
when (stage) {
|
||||||
val dir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "ballots")
|
// Stage 0 is getting the voter ID, poll ID and event ID
|
||||||
if (!dir?.mkdirs()) {
|
0 -> {
|
||||||
Log.e(LOG_TAG, "Directory not created")
|
val barcodeVal = barcode.displayValue.split(";")
|
||||||
|
record.voterID = barcodeVal[0]
|
||||||
|
record.eventID = barcodeVal[1]
|
||||||
|
record.pollID = barcodeVal[2]
|
||||||
}
|
}
|
||||||
|
// Stage 1 is getting the hashes of both ballots
|
||||||
val ballotFile = File(dir, "$handle.ballot")
|
1 -> {
|
||||||
if (ballotFile.exists()) {
|
record.hashes = barcode.displayValue
|
||||||
ballotFile.delete()
|
|
||||||
}
|
}
|
||||||
|
// Stage 2 is getting the handle of the unselected ballot on the server
|
||||||
try {
|
2 -> {
|
||||||
val out = FileWriter(ballotFile)
|
record.handle = barcode.displayValue.split(";")[0]
|
||||||
out.write(handle)
|
record.hmac = String(Base64.decode(barcode.displayValue.split(";")[1], Base64.DEFAULT))
|
||||||
out.flush()
|
saveRecord()
|
||||||
out.close()
|
finish()
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
|
else -> {
|
||||||
val hmacFile = File(dir, "$handle.hmac")
|
//something's gone wrong if this gets called
|
||||||
if (hmacFile.exists()) {
|
|
||||||
hmacFile.delete()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
val out = FileWriter(hmacFile)
|
|
||||||
out.write(hmac)
|
|
||||||
out.flush()
|
|
||||||
out.close()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
|
stage++
|
||||||
}
|
|
||||||
|
|
||||||
//if some test of the QR = ballot handle
|
|
||||||
val intent = Intent(baseContext, BallotVerifyActivity::class.java)
|
|
||||||
intent.putExtra("ballotHandle", handle)
|
|
||||||
startActivity(intent)
|
|
||||||
} else
|
} else
|
||||||
mResultTextView.setText(R.string.no_barcode_captured)
|
mResultTextView.setText(R.string.no_barcode_captured)
|
||||||
} else
|
} else
|
||||||
|
@ -91,6 +86,22 @@ class BarcodeScanActivity : AppCompatActivity() {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saveRecord() {
|
||||||
|
// save the ballot
|
||||||
|
val filename = record.handle
|
||||||
|
val fileContents = record.toString()
|
||||||
|
val outputStream: FileOutputStream
|
||||||
|
|
||||||
|
try {
|
||||||
|
outputStream = openFileOutput(filename, Context.MODE_PRIVATE)
|
||||||
|
outputStream.write(fileContents.toByteArray())
|
||||||
|
outputStream.close()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val LOG_TAG = MainActivity::class.java.simpleName
|
private val LOG_TAG = MainActivity::class.java.simpleName
|
||||||
private val BARCODE_READER_REQUEST_CODE = 1
|
private val BARCODE_READER_REQUEST_CODE = 1
|
||||||
|
|
44
app/src/main/res/layout/activity_audit.xml
Normal file
44
app/src/main/res/layout/activity_audit.xml
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.constraint.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="Check ballot exist"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="Verify cast-as-recorded"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="Verify tallied-as-cast"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/button2" />
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
21
app/src/main/res/layout/activity_choose_record.xml
Normal file
21
app/src/main/res/layout/activity_choose_record.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.constraint.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/list"
|
||||||
|
android:layout_width="368dp"
|
||||||
|
android:layout_height="495dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="1.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
|
@ -2,30 +2,33 @@
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/scan_hash_qr"
|
android:id="@+id/cast_vote"
|
||||||
android:layout_width="218dp"
|
android:layout_width="218dp"
|
||||||
android:layout_height="64dp"
|
android:layout_height="64dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:text="Scan Hash QR"
|
android:text="I'm casting a vote"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/scan_ballot_qr"
|
android:id="@+id/audit_election"
|
||||||
android:layout_width="218dp"
|
android:layout_width="218dp"
|
||||||
android:layout_height="64dp"
|
android:layout_height="64dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="336dp"
|
||||||
android:text="Scan Ballot QR"
|
android:text="I'm auditing an election"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/scan_hash_qr" />
|
app:layout_constraintTop_toBottomOf="@+id/cast_vote" />
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
Reference in a new issue