Browse Source

Functional QR Code Reader with Lineage OS

master
jahway603 4 years ago
parent
commit
eb77fceab0
  1. 4
      app/build.gradle
  2. 3
      app/src/main/AndroidManifest.xml
  3. 105
      app/src/main/java/org/myhush/silentdragon/MainActivity.kt
  4. 131
      app/src/main/java/org/myhush/silentdragon/QrReaderActivity.kt
  5. 20
      app/src/main/res/layout/activity_qr_reader.xml
  6. 24
      app/src/main/res/layout/custom_qrcode_layout.xml
  7. 2
      build.gradle

4
app/build.gradle

@ -86,7 +86,9 @@ dependencies {
implementation 'com.google.android.gms:play-services-vision:17.0.2'
implementation 'com.github.joshjdevl.libsodiumjni:libsodium-jni-aar:2.0.1'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.19'
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
//implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
implementation 'com.journeyapps:zxing-android-embedded:3.6.0@aar'
implementation 'com.google.zxing:core:3.3.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'

3
app/src/main/AndroidManifest.xml

@ -52,7 +52,8 @@
<activity
android:name="org.myhush.silentdragon.QrReaderActivity"
android:screenOrientation="portrait"/>
android:screenOrientation="fullSensor"
tools:replace="screenOrientation" />
<activity
android:name="org.myhush.silentdragon.TxDetailsActivity"
android:label="@string/title_activity_tx_details"

105
app/src/main/java/org/myhush/silentdragon/MainActivity.kt

@ -14,23 +14,16 @@ import android.text.Html
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.ScrollView
import android.widget.TextView
import android.widget.Toast
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.text.HtmlCompat
import com.beust.klaxon.Klaxon
import com.google.android.material.snackbar.Snackbar
import com.google.zxing.client.android.Intents
import com.google.zxing.client.android.Intents.Scan.QR_CODE_MODE
import com.google.zxing.integration.android.IntentIntegrator
import com.google.zxing.integration.android.IntentResult
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_qr_reader.*
import kotlinx.android.synthetic.main.content_main.*
import org.myhush.silentdragon.DataModel.ConnectionStatus
import org.myhush.silentdragon.DataModel.connStatus
@ -45,9 +38,6 @@ class MainActivity : AppCompatActivity(),
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
// IntentIntegrator is part of zxing-android-embedded to read QR codes
private lateinit var intentIntegrator: IntentIntegrator
override fun onCreate(savedInstanceState: Bundle?) {
//StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()) // TESTING
@ -60,20 +50,17 @@ class MainActivity : AppCompatActivity(),
// When creating, clear all the data first
setMainStatus("")
DataModel.init()
intentIntegrator = IntentIntegrator(this)
DataModel.init()
btnConnect.setOnClickListener {
//startActivity(Intent(this@MainActivity, QrReaderActivity::class.java))
run {
intentIntegrator.setDesiredBarcodeFormats(QR_CODE_MODE)
intentIntegrator.setCameraId(0) // set to back camera
intentIntegrator.setBeepEnabled(true)
intentIntegrator.setOrientationLocked(false) // trying to force portrait here, but it's not working
intentIntegrator.setPrompt("Go to Apps -> Connect mobile app on your desktop wallet and scan the QR Code to connect")
intentIntegrator.initiateScan()
}
val intent = Intent(this, QrReaderActivity::class.java)
intent.putExtra("REQUEST_CODE",
QrReaderActivity.REQUEST_CONNDATA
)
startActivityForResult(intent,
QrReaderActivity.REQUEST_CONNDATA
)
}
btnReconnect.setOnClickListener {
@ -353,39 +340,49 @@ class MainActivity : AppCompatActivity(),
super.onDestroy()
}
// the toasts work here so commenting out
/*override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
QrReaderActivity.REQUEST_CONNDATA -> {
if (resultCode == Activity.RESULT_OK) {
Log.i(TAG, "Main Activity got result for QrCode: ${data?.dataString}")
// Check to make sure that the result is an actual address
if (!(data?.dataString ?: "").startsWith("ws")) {
Toast.makeText(
applicationContext,
getString(R.string.is_not_a_valid_connection_string, data?.dataString),
Toast.LENGTH_SHORT
).show()
return
}
var result: IntentResult? = IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
val conComponents = data?.dataString?.split(",")
if (conComponents?.size ?: 0 < 2 || conComponents?.size ?: 0 > 3) {
Toast.makeText(
applicationContext,
getString(R.string.is_not_a_valid_connection_string, data?.dataString),
Toast.LENGTH_SHORT
).show()
return
}
if(result != null){
val conString = conComponents!![0]
val secretHex = conComponents[1]
val allowInternetConnections =
if (conComponents.size == 3) conComponents[2] == "1" else false
if(result.contents != null){
//Toast.makeText(applicationContext, result.contents,Toast.LENGTH_LONG).show()
Toast.makeText(this, "Scanned: " + result.contents, Toast.LENGTH_LONG).show();
} else {
//Toast.makeText(applicationContext,"scan failed",Toast.LENGTH_SHORT).show()
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show()
}
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}*/
DataModel.setSecretHex(secretHex)
DataModel.setConnString(
conString,
applicationContext
)
DataModel.setAllowInternet(
allowInternetConnections
)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
var result: IntentResult? = IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
if(result != null){
if(result.contents != null){
Log.d("MainActivity", "Scanned" + result.contents)
Toast.makeText(this, "Scanned: " + result.contents, Toast.LENGTH_LONG).show();
processMobileConnectorText(result.contents)
} else {
Log.d("MainActivity", "Cancelled scan")
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show()
ConnectionManager.refreshAllData()
}
}
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}
@ -400,15 +397,5 @@ class MainActivity : AppCompatActivity(),
updateUI(true)
}
private fun processMobileConnectorText(qrcodeInfo: String) {
if (qrcodeInfo.startsWith("ws")) {
Log.i(TAG, "It's a ws connection")
//Toast.makeText(this, "YEAH " + qrcodeInfo.toString(), Toast.LENGTH_SHORT).show();
} else {
Log.i(TAG, "Not a ws connection")
//Toast.makeText(this, "Not a ws connection", Toast.LENGTH_SHORT).show();
}
}
private val TAG = "MainActivity"
}

131
app/src/main/java/org/myhush/silentdragon/QrReaderActivity.kt

@ -2,29 +2,26 @@
package org.myhush.silentdragon
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.appcompat.app.AppCompatActivity
import android.text.InputType
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.SurfaceHolder
import android.view.SurfaceView
import com.google.android.gms.vision.CameraSource
import com.google.android.gms.vision.Detector
import com.google.android.gms.vision.barcode.Barcode
import com.google.android.gms.vision.barcode.BarcodeDetector
import kotlinx.android.synthetic.main.activity_qr_reader.*
import java.io.IOException
import android.app.AlertDialog
import android.text.InputType
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.zxing.ResultPoint
import com.journeyapps.barcodescanner.BarcodeCallback
import com.journeyapps.barcodescanner.BarcodeResult
import com.journeyapps.barcodescanner.CaptureManager
import kotlinx.android.synthetic.main.activity_qr_reader.*
class QrReaderActivity : AppCompatActivity() {
lateinit var captureManager: CaptureManager
companion object {
const val REQUEST_ADDRESS = 1
@ -43,7 +40,26 @@ class QrReaderActivity : AppCompatActivity() {
lblErrorMsg.text = ""
setupCamera()
btnQrCodeCancel.setOnClickListener {
setResult(Activity.RESULT_CANCELED)
finish()
}
captureManager = CaptureManager(this, barcodeView)
captureManager.initializeFromIntent(intent, savedInstanceState)
barcodeView.decodeSingle(object: BarcodeCallback{
override fun barcodeResult(result: BarcodeResult?) {
result?.let {
if (result.text != null) {
processQrCodeText(result.text)
}
}
}
override fun possibleResultPoints(resultPoints: MutableList<ResultPoint>?) {
}
})
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
@ -92,63 +108,19 @@ class QrReaderActivity : AppCompatActivity() {
}
}
private fun setupCamera() {
val cameraView = findViewById<SurfaceView>(R.id.camera_view)
val barcodeDetector = BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.QR_CODE).build()
val cameraSource = CameraSource.Builder(this, barcodeDetector)
.setAutoFocusEnabled(true)
.setRequestedPreviewSize(640, 480)
.build()
cameraView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
try {
if (ContextCompat.checkSelfPermission(applicationContext, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this@QrReaderActivity, arrayOf(android.Manifest.permission.CAMERA), 50)
} else {
cameraSource.start(cameraView.holder)
val w = cameraView.width
val h = cameraView.height
val scale = cameraSource.previewSize.width.toDouble() / cameraSource.previewSize.height.toDouble()
val scaleWidth = (h.toDouble() / scale).toInt()
cameraView.layout((w - scaleWidth)/2, 0, scaleWidth , h)
println("Preview size: ${cameraSource.previewSize}")
}
} catch (ie: IOException) {
Log.e("CAMERA SOURCE", ie.toString())
}
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}
override fun surfaceDestroyed(holder: SurfaceHolder) {
cameraSource.stop()
}
})
btnQrCodeCancel.setOnClickListener {
setResult(Activity.RESULT_CANCELED)
finish()
}
override fun onPause() {
super.onPause()
captureManager.onPause()
}
barcodeDetector.setProcessor(object : Detector.Processor<Barcode> {
override fun release() {}
override fun onResume() {
super.onResume()
captureManager.onResume()
}
override fun receiveDetections(detections: Detector.Detections<Barcode>) {
val barcodes = detections.detectedItems
if (barcodes.size() != 0) {
runOnUiThread {
val barcodeInfo = barcodes.valueAt(0).displayValue
processText(barcodeInfo)
}
}
}
})
override fun onDestroy() {
super.onDestroy()
captureManager.onDestroy()
}
private fun processText(barcodeInfo: String) {
@ -174,15 +146,13 @@ class QrReaderActivity : AppCompatActivity() {
err = err.substring(0, 22) + "...." + err.substring(err.length - 22, err.length)
}
lblErrorMsg.text = getString(R.string.is_not_a_valid_hush_address, err)
return
}
// The data seems valid, so return it.
val data = Intent()
// Payment URIs are often formatted as "hush:<addr>", but this casuses parsing problems.
// Payment URIs are often formatted as "hush:<addr>", but this causes parsing problems.
// So change it to hush://<addr>, so that it parses properly
if (barcodeInfo.startsWith("hush:") && !barcodeInfo.startsWith("hush://")) {
data.data = Uri.parse(barcodeInfo.replaceFirst("hush:", "hush://"))
@ -194,5 +164,22 @@ class QrReaderActivity : AppCompatActivity() {
finish()
}
private fun processQrCodeText(qrcodeInfo: String) {
if (qrcodeInfo.startsWith("ws")) {
Log.i(TAG, "It's a ws connection")
//Toast.makeText(this, "YEAH: " + qrcodeInfo, Toast.LENGTH_SHORT).show();
val data = Intent() // The data seems valid, so return it
data.data = Uri.parse(qrcodeInfo)
setResult(Activity.RESULT_OK, data)
finish()
} else {
Log.i(TAG, "Not a ws connection")
//Toast.makeText(this, "Not a ws connection", Toast.LENGTH_SHORT).show();
setResult(Activity.RESULT_CANCELED)
finish()
}
}
private val TAG = "QrReader"
}

20
app/src/main/res/layout/activity_qr_reader.xml

@ -9,23 +9,15 @@
tools:context="org.myhush.silentdragon.QrReaderActivity"
tools:showIn="@layout/activity_qr_reader">
<SurfaceView
android:id="@+id/camera_view"
android:layout_width="0dp"
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="@+id/barcodeView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/txtQrCodeHelp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="0dp"
android:layout_height="200dp"
android:src="#ee000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintTop_toTopOf="parent"
app:zxing_scanner_layout="@layout/custom_qrcode_layout" />
<TextView
android:id="@+id/txtQrCodeHelp"

24
app/src/main/res/layout/custom_qrcode_layout.xml

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.journeyapps.barcodescanner.BarcodeView
android:id="@+id/zxing_barcode_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_framing_rect_height="300dp"
app:zxing_framing_rect_width="300dp" />
<com.journeyapps.barcodescanner.ViewfinderView
android:id="@+id/zxing_viewfinder_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
app:zxing_result_view="@color/zxing_custom_result_view"
app:zxing_viewfinder_laser="@color/zxing_custom_viewfinder_laser"
app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask" />
</androidx.constraintlayout.widget.ConstraintLayout>

2
build.gradle

@ -11,7 +11,7 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.0' // does this need 4.0 or another version?
classpath 'com.android.tools.build:gradle:3.6.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Deps.kotlinVersion}"
classpath 'io.fabric.tools:gradle:1.31.2'

Loading…
Cancel
Save