Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47d5923a04 | ||
|
|
8c22a8ab00 | ||
|
|
8152cb6a24 | ||
|
|
ffed4fc5cf | ||
|
|
d8bd3c1176 | ||
|
|
3b12aa4b7b | ||
|
|
099b522d35 | ||
|
|
166d181469 | ||
|
|
a4a2a67177 | ||
|
|
7fe3de78af | ||
|
|
e75d658092 | ||
|
|
c840462fa2 | ||
|
|
c3475a37d2 | ||
|
|
183fe2c6f2 | ||
|
|
056f5e263e | ||
|
|
386c7a6056 | ||
|
|
80c876f35d | ||
|
|
30ae51d945 | ||
|
|
95b54ed4ab | ||
|
|
3650bda107 | ||
|
|
2bdf13761e |
@@ -1,5 +1,21 @@
|
||||
# Change Log
|
||||
|
||||
# 1.14.0
|
||||
* Add OTP support
|
||||
* Update Indonesian translation
|
||||
|
||||
# 1.13.1
|
||||
* Fix crash caused by missing support for Regex on Android < 6
|
||||
|
||||
# 1.13.0
|
||||
* Add missing extras for ZXing result intents
|
||||
|
||||
# 1.12.0
|
||||
* Add preferences dialog and the option to use a custom URL with read contents
|
||||
* Add Brazilian Portuguese translation
|
||||
* Add Chinese translation
|
||||
* Encode text using UTF-8 encoding when creating a barcode
|
||||
|
||||
# 1.11.2
|
||||
* Downgrade ZXing version
|
||||
* Improve getting system UI metrics
|
||||
|
||||
@@ -5,15 +5,29 @@ Yet another barcode scanner for Android. As if there weren't [enough][play].
|
||||
This one is totally free, open source and does use the [ZXing][zxing] barcode
|
||||
scanning library.
|
||||
|
||||
Unlike many others it works in portrait and landscape orientation, can read
|
||||
inverted codes, uses Material Design and doesn't do anything else but decoding
|
||||
Unlike many others, it works in portrait and landscape orientation, can read
|
||||
inverted codes, comes in Material Design and doesn't do much else but decoding
|
||||
a barcode.
|
||||
|
||||
<a href="https://f-droid.org/en/packages/de.markusfisch.android.binaryeye/"><img alt="Get it on F-Droid" src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="80"/></a> <a href="https://play.google.com/store/apps/details?id=de.markusfisch.android.binaryeye"><img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" height="80"/></a>
|
||||
|
||||
And it's written in [Kotlin][kotlin] because I wanted to explore that a
|
||||
bit more.
|
||||
|
||||
## Screenshots
|
||||
|
||||
<img
|
||||
src="https://raw.githubusercontent.com/markusfisch/BinaryEye/gh-pages/screencap-scanning.png"
|
||||
alt="Screenshot Scanning" width="160"/>
|
||||
<img
|
||||
src="https://raw.githubusercontent.com/markusfisch/BinaryEye/gh-pages/screencap-decoded.png"
|
||||
alt="Screenshot Result" width="160"/>
|
||||
<img
|
||||
src="https://raw.githubusercontent.com/markusfisch/BinaryEye/gh-pages/screencap-compose-barcode.png"
|
||||
alt="Screenshot Compose Barcode" width="160"/>
|
||||
|
||||
## Download
|
||||
|
||||
<a href="https://f-droid.org/en/packages/de.markusfisch.android.binaryeye/"><img alt="Get it on F-Droid" src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="80"/></a> <a href="https://play.google.com/store/apps/details?id=de.markusfisch.android.binaryeye"><img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" height="80"/></a>
|
||||
|
||||
[play]: https://play.google.com/store/search?q=barcode%20scanner&c=apps
|
||||
[zxing]: https://github.com/zxing/zxing
|
||||
[kotlin]: http://kotlinlang.org/
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ android {
|
||||
minSdkVersion 9
|
||||
targetSdkVersion sdk_version
|
||||
|
||||
versionCode 33
|
||||
versionName '1.11.2'
|
||||
versionCode 39
|
||||
versionName '1.14.0'
|
||||
|
||||
// it's recommended to set this value to the lowest API level
|
||||
// able to provide all the functionality
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.markusfisch.android.binaryeye.actions
|
||||
|
||||
import de.markusfisch.android.binaryeye.actions.mail.MailAction
|
||||
import de.markusfisch.android.binaryeye.actions.otpauth.OtpauthAction
|
||||
import de.markusfisch.android.binaryeye.actions.sms.SmsAction
|
||||
import de.markusfisch.android.binaryeye.actions.tel.TelAction
|
||||
import de.markusfisch.android.binaryeye.actions.vtype.vcard.VCardAction
|
||||
@@ -9,7 +10,7 @@ import de.markusfisch.android.binaryeye.actions.wifi.WifiAction
|
||||
|
||||
object ActionRegistry {
|
||||
val REGISTRY: Set<IAction> = setOf(
|
||||
MailAction, SmsAction, TelAction, VCardAction, VEventAction, WifiAction
|
||||
MailAction, OtpauthAction, SmsAction, TelAction, VCardAction, VEventAction, WifiAction
|
||||
)
|
||||
|
||||
fun getAction(data: ByteArray): IAction? = REGISTRY.find {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package de.markusfisch.android.binaryeye.actions
|
||||
|
||||
import de.markusfisch.android.binaryeye.app.execShareIntent
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import de.markusfisch.android.binaryeye.app.execShareIntent
|
||||
|
||||
interface IAction {
|
||||
val iconResId: Int
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package de.markusfisch.android.binaryeye.actions.mail
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
|
||||
object MailAction : SimpleIntentIAction() {
|
||||
private val mailRegex =
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.markusfisch.android.binaryeye.actions.otpauth
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
|
||||
object OtpauthAction : SimpleIntentIAction() {
|
||||
override val iconResId: Int = R.drawable.ic_action_otpauth
|
||||
override val titleResId: Int = R.string.otpauth_add
|
||||
override val errorMsg: Int = R.string.otpauth_error
|
||||
|
||||
override fun canExecuteOn(data: ByteArray): Boolean {
|
||||
return OtpauthParser(String(data)) != null
|
||||
}
|
||||
|
||||
override fun executeForIntent(context: Context, data: ByteArray): Intent? {
|
||||
return OtpauthParser(String(data))?.let {
|
||||
Intent(Intent.ACTION_VIEW, it.uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package de.markusfisch.android.binaryeye.actions.otpauth
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
class OtpauthParser private constructor(private val match: MatchResult) {
|
||||
val otpType: String
|
||||
get() = match.groupValues[1]
|
||||
private val labelIssuer: String
|
||||
get() = match.groupValues[2]
|
||||
val accountName: String
|
||||
get() = match.groupValues[3].takeIf { it.isNotEmpty() } ?: match.groupValues[4]
|
||||
val secret: String
|
||||
get() = match.groupValues[5]
|
||||
private val parameterIssuer: String
|
||||
get() = match.groupValues[6]
|
||||
val algorithm: String
|
||||
get() = match.groupValues[7].takeIf { it.isNotEmpty() } ?: "SHA1"
|
||||
val digits: Int
|
||||
get() = match.groupValues[8].toIntOrNull() ?: 6
|
||||
val period: Int
|
||||
get() = match.groupValues[9].toIntOrNull() ?: 30
|
||||
private val parameterCounter: String
|
||||
get() = match.groupValues[10]
|
||||
val issuer: String
|
||||
get() = labelIssuer.takeIf { it.isNotEmpty() } ?: parameterIssuer
|
||||
val counter: Int
|
||||
get() = parameterCounter.toInt()
|
||||
private val isHotp: Boolean = otpType == "hotp"
|
||||
val isValid: Boolean =
|
||||
(labelIssuer.isNotEmpty() == parameterIssuer.isEmpty() || labelIssuer.isEmpty())
|
||||
&& secret.isNotEmpty() && isHotp == parameterCounter.isNotEmpty()
|
||||
|
||||
val uri: Uri
|
||||
get() = Uri.Builder().apply {
|
||||
scheme("otpauth")
|
||||
authority(otpType)
|
||||
|
||||
if (issuer.isNotEmpty()) {
|
||||
encodedPath("/$issuer:$accountName")
|
||||
appendQueryParameter("issuer", issuer)
|
||||
} else {
|
||||
encodedPath("/$accountName")
|
||||
}
|
||||
|
||||
appendQueryParameter("secret", secret)
|
||||
appendQueryParameter("algorithm", algorithm)
|
||||
appendQueryParameter("digits", digits.toString())
|
||||
|
||||
if (isHotp) {
|
||||
appendQueryParameter("counter", counter.toString())
|
||||
} else {
|
||||
appendQueryParameter("period", period.toString())
|
||||
}
|
||||
}.build()
|
||||
|
||||
companion object {
|
||||
private const val issuerAndAccount =
|
||||
"""(?:(?:([^?:]+)(?::|%3A)(?:%20)*([^?]+))|([^?]+))"""//.toRegex()
|
||||
/** allowing `padding` even though it should not be there, will be removed in output*/
|
||||
private const val secret = """(?:secret=([2-7A-Z]+)=*)"""//.toRegex()
|
||||
/** `\2` references the issuer of [issuerAndAccount] */
|
||||
private const val issuer = """(?:issuer=\2)|(?:issuer=([^&]+))"""//.toRegex()
|
||||
private const val algorithm = """(?:algorithm=(SHA(?:1|256|512)))"""//.toRegex()
|
||||
private const val digits = """(?:digits=([0-9]+))"""//.toRegex()
|
||||
private const val period = """(?:period=([0-9]+))"""//.toRegex()
|
||||
private const val counter = """(?:counter=([0-9]+))"""//.toRegex()
|
||||
private val otpauthRegex =
|
||||
"""^otpauth://([ht]otp)/$issuerAndAccount\?(?:&?(?:$secret|$issuer|$algorithm|$digits|$period|$counter))+$""".toRegex(
|
||||
RegexOption.IGNORE_CASE
|
||||
)
|
||||
|
||||
operator fun invoke(input: String): OtpauthParser? {
|
||||
return otpauthRegex.matchEntire(input)?.let(::OtpauthParser)?.takeIf { it.isValid }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package de.markusfisch.android.binaryeye.actions.sms
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
|
||||
object SmsAction : SimpleIntentIAction() {
|
||||
private val smsRegex = """^sms(?:to)?:(\+?[0-9]+)(?::([\S\s]*))?$""".toRegex(RegexOption.IGNORE_CASE)
|
||||
private val smsRegex =
|
||||
"""^sms(?:to)?:(\+?[0-9]+)(?::([\S\s]*))?$""".toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
override val iconResId: Int = R.drawable.ic_action_sms
|
||||
override val titleResId: Int = R.string.sms_send
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package de.markusfisch.android.binaryeye.actions.tel
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
|
||||
object TelAction : SimpleIntentIAction() {
|
||||
private val telRegex = """^tel:(\+?[0-9]+)$""".toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package de.markusfisch.android.binaryeye.actions.vtype
|
||||
|
||||
object VTypeParser {
|
||||
private const val BACKSLASH_R_LEGACY =
|
||||
"(?:\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029])"
|
||||
private val vTypeRegex =
|
||||
"""^BEGIN:(VCARD|VEVENT)(?:\R.+?:[\s\S]+?)+?\REND:\1\R?$""".toRegex(RegexOption.IGNORE_CASE)
|
||||
"""^BEGIN:(VCARD|VEVENT)(?:$BACKSLASH_R_LEGACY.+?:[\s\S]+?)+?${BACKSLASH_R_LEGACY}END:\1$BACKSLASH_R_LEGACY?$""".toRegex(
|
||||
RegexOption.IGNORE_CASE
|
||||
)
|
||||
private val propertyRegex = """^(.+?):([\s\S]*?)$""".toRegex(RegexOption.MULTILINE)
|
||||
|
||||
fun parseVType(data: String): String? = vTypeRegex.matchEntire(data)?.groupValues?.get(1)?.toUpperCase()
|
||||
fun parseVType(data: String): String? =
|
||||
vTypeRegex.matchEntire(data)?.groupValues?.get(1)?.toUpperCase()
|
||||
|
||||
fun parseMap(data: String): Map<String, List<VTypeProperty>> = propertyRegex.findAll(data).map {
|
||||
it.groupValues[1].split(';').let { typeAndInfo ->
|
||||
|
||||
+15
-7
@@ -1,14 +1,13 @@
|
||||
package de.markusfisch.android.binaryeye.actions.vtype.vcard
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
import de.markusfisch.android.binaryeye.actions.vtype.VTypeParser
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.provider.ContactsContract
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
import de.markusfisch.android.binaryeye.actions.vtype.VTypeParser
|
||||
|
||||
object VCardAction : SimpleIntentIAction() {
|
||||
override val iconResId: Int
|
||||
@@ -116,14 +115,23 @@ object VCardAction : SimpleIntentIAction() {
|
||||
}
|
||||
|
||||
private val String.locationFormat: String
|
||||
get() = """^([^;]*?);([^;]*?);([^;]*?);([^;]*?);([^;]*?);([^;]*?);([^;]*?)$""".toRegex().matchEntire(this)?.groupValues?.let {
|
||||
listOf(it[1], it[2], it[3], "${it[4]} ${it[6]}", "${it[5]} ${it[7]}").filter { line -> line.isNotBlank() }
|
||||
get() = """^([^;]*?);([^;]*?);([^;]*?);([^;]*?);([^;]*?);([^;]*?);([^;]*?)$""".toRegex().matchEntire(
|
||||
this
|
||||
)?.groupValues?.let {
|
||||
listOf(
|
||||
it[1],
|
||||
it[2],
|
||||
it[3],
|
||||
"${it[4]} ${it[6]}",
|
||||
"${it[5]} ${it[7]}"
|
||||
).filter { line -> line.isNotBlank() }
|
||||
.joinToString("\n").takeIf { location -> location.isNotBlank() }
|
||||
} ?: this
|
||||
|
||||
private val String.nameFormat: String
|
||||
get() = """^([^;]*?);([^;]*?);([^;]*?);([^;]*?);([^;]*?)$""".toRegex().matchEntire(this)?.groupValues?.let {
|
||||
listOf(it[4], it[2], it[3], it[1], it[5]).joinToString(" ").takeIf { name -> name.isNotBlank() }
|
||||
listOf(it[4], it[2], it[3], it[1], it[5]).joinToString(" ")
|
||||
.takeIf { name -> name.isNotBlank() }
|
||||
} ?: this
|
||||
|
||||
private val String.mailType: Int?
|
||||
|
||||
+4
-6
@@ -1,18 +1,16 @@
|
||||
package de.markusfisch.android.binaryeye.actions.vtype.vevent
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
import de.markusfisch.android.binaryeye.actions.vtype.VTypeParser
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.provider.CalendarContract
|
||||
import android.support.annotation.RequiresApi
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.SimpleIntentIAction
|
||||
import de.markusfisch.android.binaryeye.actions.vtype.VTypeParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.*
|
||||
|
||||
object VEventAction : SimpleIntentIAction() {
|
||||
override val iconResId: Int
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
package de.markusfisch.android.binaryeye.actions.wifi
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.IAction
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Context.WIFI_SERVICE
|
||||
import android.net.wifi.WifiConfiguration
|
||||
import android.net.wifi.WifiManager
|
||||
import android.widget.Toast
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.IAction
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
object WifiAction : IAction {
|
||||
override val iconResId = R.drawable.ic_action_wifi
|
||||
|
||||
+4
-2
@@ -194,8 +194,10 @@ object WifiConfigurationFactory {
|
||||
enterpriseConfig.identity = data.identity
|
||||
enterpriseConfig.anonymousIdentity = data.anonymousIdentity
|
||||
enterpriseConfig.password = data.password
|
||||
enterpriseConfig.eapMethod = data.eapMethod ?: return null // non valid eapMethod
|
||||
enterpriseConfig.phase2Method = data.phase2Method ?: return null // non valid phase2Method
|
||||
enterpriseConfig.eapMethod =
|
||||
data.eapMethod ?: return null // non valid eapMethod
|
||||
enterpriseConfig.phase2Method =
|
||||
data.phase2Method ?: return null // non valid phase2Method
|
||||
} ?: return null // api isn't high enough
|
||||
}
|
||||
return this
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
package de.markusfisch.android.binaryeye.activity
|
||||
|
||||
import com.google.zxing.Result
|
||||
import com.google.zxing.ResultMetadataType
|
||||
|
||||
import de.markusfisch.android.cameraview.widget.CameraView
|
||||
|
||||
import de.markusfisch.android.binaryeye.app.db
|
||||
import de.markusfisch.android.binaryeye.app.hasCameraPermission
|
||||
import de.markusfisch.android.binaryeye.app.initSystemBars
|
||||
import de.markusfisch.android.binaryeye.app.prefs
|
||||
import de.markusfisch.android.binaryeye.rs.Preprocessor
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
@@ -30,10 +17,18 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.SeekBar
|
||||
import android.widget.Toast
|
||||
|
||||
import com.google.zxing.Result
|
||||
import com.google.zxing.ResultMetadataType
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.db
|
||||
import de.markusfisch.android.binaryeye.app.hasCameraPermission
|
||||
import de.markusfisch.android.binaryeye.app.initSystemBars
|
||||
import de.markusfisch.android.binaryeye.app.prefs
|
||||
import de.markusfisch.android.binaryeye.rs.Preprocessor
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
import de.markusfisch.android.cameraview.widget.CameraView
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
import java.io.IOException
|
||||
|
||||
class CameraActivity : AppCompatActivity() {
|
||||
@@ -165,6 +160,10 @@ class CameraActivity : AppCompatActivity() {
|
||||
switchCamera()
|
||||
true
|
||||
}
|
||||
R.id.preferences -> {
|
||||
startActivity(MainActivity.getPreferencesIntent(this))
|
||||
true
|
||||
}
|
||||
R.id.info -> {
|
||||
openReadme()
|
||||
true
|
||||
@@ -409,9 +408,7 @@ class CameraActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
if (returnResult) {
|
||||
val resultIntent = Intent()
|
||||
resultIntent.putExtra("SCAN_RESULT", result.text)
|
||||
setResult(RESULT_OK, resultIntent)
|
||||
setResult(RESULT_OK, getReturnIntent(result))
|
||||
finish()
|
||||
return
|
||||
}
|
||||
@@ -462,7 +459,53 @@ fun getRawBytes(result: Result): ByteArray? {
|
||||
for (seg in segments as Iterable<ByteArray>) {
|
||||
bytes += seg
|
||||
}
|
||||
// byte segments can never be shorter than the text;
|
||||
// byte segments can never be shorter than the text.
|
||||
// Zxing cuts off content prefixes like "WIFI:"
|
||||
return if (bytes.size >= result.text.length) bytes else null
|
||||
}
|
||||
|
||||
fun getReturnIntent(result: Result): Intent {
|
||||
val intent = Intent()
|
||||
intent.putExtra("SCAN_RESULT", result.text)
|
||||
intent.putExtra(
|
||||
"SCAN_RESULT_FORMAT",
|
||||
result.barcodeFormat.toString()
|
||||
)
|
||||
if (result.rawBytes?.isNotEmpty() == true) {
|
||||
intent.putExtra("SCAN_RESULT_BYTES", result.rawBytes)
|
||||
}
|
||||
val metadata = result.resultMetadata
|
||||
metadata?.let {
|
||||
val orientation = metadata[ResultMetadataType.UPC_EAN_EXTENSION]
|
||||
orientation?.let {
|
||||
intent.putExtra(
|
||||
"SCAN_RESULT_ORIENTATION",
|
||||
orientation.toString()
|
||||
)
|
||||
}
|
||||
val ecLevel = metadata[ResultMetadataType.ERROR_CORRECTION_LEVEL]
|
||||
ecLevel?.let {
|
||||
intent.putExtra(
|
||||
"SCAN_RESULT_ERROR_CORRECTION_LEVEL",
|
||||
ecLevel.toString()
|
||||
)
|
||||
}
|
||||
val upcEanExtension = metadata[ResultMetadataType.UPC_EAN_EXTENSION]
|
||||
upcEanExtension?.let {
|
||||
intent.putExtra(
|
||||
"SCAN_RESULT_UPC_EAN_EXTENSION",
|
||||
upcEanExtension.toString()
|
||||
)
|
||||
}
|
||||
val segments = metadata[ResultMetadataType.BYTE_SEGMENTS]
|
||||
segments?.let {
|
||||
var i = 0
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
for (seg in segments as Iterable<ByteArray>) {
|
||||
intent.putExtra("SCAN_RESULT_BYTE_SEGMENTS_$i", seg)
|
||||
++i
|
||||
}
|
||||
}
|
||||
}
|
||||
return intent
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
package de.markusfisch.android.binaryeye.activity
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.initSystemBars
|
||||
import de.markusfisch.android.binaryeye.app.setFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.DecodeFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.EncodeFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.HistoryFragment
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.initSystemBars
|
||||
import de.markusfisch.android.binaryeye.app.setFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.DecodeFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.EncodeFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.HistoryFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.PreferencesFragment
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
@@ -38,17 +37,22 @@ class MainActivity : AppCompatActivity() {
|
||||
if (state == null) {
|
||||
setFragment(
|
||||
supportFragmentManager, when {
|
||||
intent?.hasExtra(HISTORY) == true -> HistoryFragment()
|
||||
intent?.hasExtra(ENCODE) == true -> EncodeFragment.newInstance(
|
||||
intent.getStringExtra(ENCODE)
|
||||
)
|
||||
intent?.hasExtra(DECODED_TEXT) == true -> DecodeFragment.newInstance(
|
||||
intent.getStringExtra(DECODED_TEXT),
|
||||
intent.getSerializableExtra(
|
||||
DECODED_FORMAT
|
||||
) as BarcodeFormat,
|
||||
intent.getByteArrayExtra(DECODED_RAW)
|
||||
)
|
||||
intent?.hasExtra(PREFERENCES) == true ->
|
||||
PreferencesFragment()
|
||||
intent?.hasExtra(HISTORY) == true ->
|
||||
HistoryFragment()
|
||||
intent?.hasExtra(ENCODE) == true ->
|
||||
EncodeFragment.newInstance(
|
||||
intent.getStringExtra(ENCODE)
|
||||
)
|
||||
intent?.hasExtra(DECODED_TEXT) == true ->
|
||||
DecodeFragment.newInstance(
|
||||
intent.getStringExtra(DECODED_TEXT),
|
||||
intent.getSerializableExtra(
|
||||
DECODED_FORMAT
|
||||
) as BarcodeFormat,
|
||||
intent.getByteArrayExtra(DECODED_RAW)
|
||||
)
|
||||
else -> DecodeFragment()
|
||||
}
|
||||
)
|
||||
@@ -56,12 +60,19 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PREFERENCES = "preferences"
|
||||
private const val HISTORY = "history"
|
||||
private const val ENCODE = "encode"
|
||||
private const val DECODED_TEXT = "decoded_text"
|
||||
private const val DECODED_FORMAT = "decoded_format"
|
||||
private const val DECODED_RAW = "decoded_raw"
|
||||
|
||||
fun getPreferencesIntent(context: Context): Intent {
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
intent.putExtra(PREFERENCES, true)
|
||||
return intent
|
||||
}
|
||||
|
||||
fun getHistoryIntent(context: Context): Intent {
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
intent.putExtra(HISTORY, true)
|
||||
@@ -76,9 +87,10 @@ class MainActivity : AppCompatActivity() {
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
intent.putExtra(ENCODE, text)
|
||||
if (isExternal) {
|
||||
val flagActivityClearTask = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
} else 0
|
||||
val flagActivityClearTask =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
} else 0
|
||||
intent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NO_HISTORY or
|
||||
flagActivityClearTask or
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package de.markusfisch.android.binaryeye.adapter
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.data.Database
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.view.LayoutInflater
|
||||
@@ -10,6 +7,8 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CursorAdapter
|
||||
import android.widget.TextView
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.data.Database
|
||||
|
||||
class ScansAdapter(context: Context, cursor: Cursor) :
|
||||
CursorAdapter(context, cursor, false) {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package de.markusfisch.android.binaryeye.app
|
||||
|
||||
import de.markusfisch.android.binaryeye.data.Database
|
||||
import de.markusfisch.android.binaryeye.preference.Preferences
|
||||
|
||||
import android.app.Application
|
||||
import android.support.v8.renderscript.RenderScript
|
||||
import de.markusfisch.android.binaryeye.data.Database
|
||||
import de.markusfisch.android.binaryeye.preference.Preferences
|
||||
|
||||
val db = Database()
|
||||
val prefs = Preferences()
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package de.markusfisch.android.binaryeye.app
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentTransaction
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
fun setFragment(fm: FragmentManager?, fragment: Fragment) {
|
||||
fm?.let { getTransaction(fm, fragment).commit() }
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package de.markusfisch.android.binaryeye.app
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.pm.PackageManager
|
||||
import android.support.v4.app.ActivityCompat
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.Manifest
|
||||
|
||||
fun hasCameraPermission(activity: Activity, requestCode: Int): Boolean {
|
||||
return hasPermission(activity, Manifest.permission.CAMERA, requestCode)
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package de.markusfisch.android.binaryeye.app
|
||||
|
||||
import de.markusfisch.android.binaryeye.BuildConfig
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.support.v4.content.FileProvider
|
||||
import android.widget.Toast
|
||||
|
||||
import de.markusfisch.android.binaryeye.BuildConfig
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import java.io.File
|
||||
|
||||
fun shareText(context: Context, text: String, type: String = "text/plain") {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package de.markusfisch.android.binaryeye.app
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
import android.os.Build
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.view.ViewCompat
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
fun initSystemBars(activity: AppCompatActivity?) {
|
||||
val view = activity?.findViewById(R.id.main_layout) ?: return
|
||||
@@ -40,7 +39,7 @@ fun setSystemBarColor(window: Window, color: Int): Boolean {
|
||||
window.navigationBarColor = color
|
||||
window.decorView.systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package de.markusfisch.android.binaryeye.data
|
||||
|
||||
import de.markusfisch.android.binaryeye.app.hasNonPrintableCharacters
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import android.text.format.DateFormat
|
||||
import de.markusfisch.android.binaryeye.app.hasNonPrintableCharacters
|
||||
|
||||
class Database {
|
||||
private lateinit var db: SQLiteDatabase
|
||||
|
||||
@@ -1,27 +1,23 @@
|
||||
package de.markusfisch.android.binaryeye.fragment
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
|
||||
import de.markusfisch.android.binaryeye.app.shareFile
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
import android.os.Bundle
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.Toast
|
||||
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.shareFile
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
|
||||
class BarcodeFragment : Fragment() {
|
||||
override fun onCreateView(
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
package de.markusfisch.android.binaryeye.fragment
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.IAction
|
||||
import de.markusfisch.android.binaryeye.actions.validateOrGetNew
|
||||
import de.markusfisch.android.binaryeye.app.addFragment
|
||||
import de.markusfisch.android.binaryeye.app.hasNonPrintableCharacters
|
||||
import de.markusfisch.android.binaryeye.app.hasWritePermission
|
||||
import de.markusfisch.android.binaryeye.app.shareText
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -21,17 +12,16 @@ import android.support.v4.app.Fragment
|
||||
import android.text.ClipboardManager
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.*
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.IAction
|
||||
import de.markusfisch.android.binaryeye.actions.validateOrGetNew
|
||||
import de.markusfisch.android.binaryeye.app.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URLEncoder
|
||||
@@ -211,12 +201,19 @@ class DecodeFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun pickSearchEngineAndSearch(context: Context, query: String) {
|
||||
val names = context.resources.getStringArray(
|
||||
R.array.search_engines_names
|
||||
).toMutableList()
|
||||
val urls = context.resources.getStringArray(
|
||||
R.array.search_engines_values
|
||||
)
|
||||
).toMutableList()
|
||||
if (prefs.openWithUrl.isNotEmpty()) {
|
||||
names.add(prefs.openWithUrl)
|
||||
urls.add(prefs.openWithUrl)
|
||||
}
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(R.string.pick_search_engine)
|
||||
.setItems(R.array.search_engines_names) { _, which ->
|
||||
.setItems(names.toTypedArray()) { _, which ->
|
||||
openUrl(
|
||||
urls[which] + URLEncoder.encode(query, "utf-8"),
|
||||
executeCustomAction = false,
|
||||
@@ -226,6 +223,9 @@ class DecodeFragment : Fragment() {
|
||||
.show()
|
||||
}
|
||||
|
||||
// dialogs don't have a parent layout and must therefore be
|
||||
// inflated with a null root layout
|
||||
@SuppressLint("InflateParams")
|
||||
private fun askForFileNameAndSave(raw: ByteArray) {
|
||||
val ac = activity ?: return
|
||||
val view = ac.layoutInflater.inflate(R.layout.dialog_save_file, null)
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
package de.markusfisch.android.binaryeye.fragment
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
|
||||
import de.markusfisch.android.binaryeye.app.addFragment
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.EditText
|
||||
import android.widget.SeekBar
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.*
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.addFragment
|
||||
|
||||
class EncodeFragment : Fragment() {
|
||||
private lateinit var formatView: Spinner
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
package de.markusfisch.android.binaryeye.fragment
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
|
||||
import de.markusfisch.android.binaryeye.adapter.ScansAdapter
|
||||
import de.markusfisch.android.binaryeye.app.addFragment
|
||||
import de.markusfisch.android.binaryeye.app.db
|
||||
import de.markusfisch.android.binaryeye.app.prefs
|
||||
import de.markusfisch.android.binaryeye.app.shareText
|
||||
import de.markusfisch.android.binaryeye.data.Database
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.widget.SwitchCompat
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.*
|
||||
import android.widget.ListView
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.adapter.ScansAdapter
|
||||
import de.markusfisch.android.binaryeye.app.addFragment
|
||||
import de.markusfisch.android.binaryeye.app.db
|
||||
import de.markusfisch.android.binaryeye.app.prefs
|
||||
import de.markusfisch.android.binaryeye.app.shareText
|
||||
import de.markusfisch.android.binaryeye.data.Database
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package de.markusfisch.android.binaryeye.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.widget.SwitchCompat
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.prefs
|
||||
|
||||
class PreferencesFragment : Fragment() {
|
||||
private lateinit var useHistorySwitch: SwitchCompat
|
||||
private lateinit var openWithUrlInput: EditText
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
state: Bundle?
|
||||
): View? {
|
||||
activity.setTitle(R.string.preferences)
|
||||
|
||||
val view = inflater.inflate(
|
||||
R.layout.fragment_preferences,
|
||||
container,
|
||||
false
|
||||
)
|
||||
|
||||
useHistorySwitch = view.findViewById<SwitchCompat>(R.id.use_history)
|
||||
if (prefs.useHistory) {
|
||||
useHistorySwitch.toggle()
|
||||
}
|
||||
|
||||
openWithUrlInput = view.findViewById<EditText>(R.id.open_with_url)
|
||||
openWithUrlInput.setText(prefs.openWithUrl)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
prefs.useHistory = useHistorySwitch.isChecked()
|
||||
prefs.openWithUrl = openWithUrlInput.text.toString()
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,11 @@ class Preferences {
|
||||
setBoolean(USE_HISTORY, value)
|
||||
field = value
|
||||
}
|
||||
var openWithUrl: String = ""
|
||||
set(value) {
|
||||
setString(OPEN_WITH_URL, value)
|
||||
field = value
|
||||
}
|
||||
|
||||
fun init(context: Context) {
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
@@ -20,6 +25,7 @@ class Preferences {
|
||||
|
||||
fun update() {
|
||||
useHistory = preferences.getBoolean(USE_HISTORY, useHistory)
|
||||
openWithUrl = preferences.getString(OPEN_WITH_URL, openWithUrl)
|
||||
}
|
||||
|
||||
private fun setBoolean(label: String, value: Boolean) {
|
||||
@@ -28,7 +34,14 @@ class Preferences {
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
private fun setString(label: String, value: String) {
|
||||
val editor = preferences.edit()
|
||||
editor.putString(label, value)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val USE_HISTORY = "use_history"
|
||||
const val OPEN_WITH_URL = "open_with_url"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
package de.markusfisch.android.binaryeye.rs
|
||||
|
||||
import de.markusfisch.android.binaryeye.renderscript.ScriptC_rotator
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v8.renderscript.Allocation
|
||||
import android.support.v8.renderscript.Element
|
||||
import android.support.v8.renderscript.RenderScript
|
||||
import android.support.v8.renderscript.ScriptIntrinsicResize
|
||||
import android.support.v8.renderscript.Type
|
||||
import android.support.v8.renderscript.*
|
||||
import de.markusfisch.android.binaryeye.renderscript.ScriptC_rotator
|
||||
|
||||
class Preprocessor(
|
||||
context: Context,
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
package de.markusfisch.android.binaryeye.zxing
|
||||
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import com.google.zxing.BinaryBitmap
|
||||
import com.google.zxing.DecodeHintType
|
||||
import com.google.zxing.LuminanceSource
|
||||
import com.google.zxing.MultiFormatReader
|
||||
import com.google.zxing.MultiFormatWriter
|
||||
import com.google.zxing.PlanarYUVLuminanceSource
|
||||
import com.google.zxing.RGBLuminanceSource
|
||||
import com.google.zxing.ReaderException
|
||||
import com.google.zxing.Result
|
||||
import com.google.zxing.common.HybridBinarizer
|
||||
|
||||
import android.graphics.Bitmap
|
||||
|
||||
import java.util.Arrays
|
||||
import java.util.EnumMap
|
||||
import java.util.EnumSet
|
||||
import com.google.zxing.*
|
||||
import com.google.zxing.common.HybridBinarizer
|
||||
import java.util.*
|
||||
|
||||
class Zxing {
|
||||
private val multiFormatReader: MultiFormatReader = MultiFormatReader()
|
||||
@@ -137,12 +124,14 @@ class Zxing {
|
||||
width: Int,
|
||||
height: Int
|
||||
): Bitmap? {
|
||||
val hints = EnumMap<EncodeHintType, Any>(EncodeHintType::class.java)
|
||||
hints[EncodeHintType.CHARACTER_SET] = "utf-8"
|
||||
val result = MultiFormatWriter().encode(
|
||||
text,
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
null
|
||||
hints
|
||||
)
|
||||
val w = result.width
|
||||
val h = result.height
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0"
|
||||
android:width="24dp">
|
||||
<path android:fillColor="#FF000000"
|
||||
android:pathData="M14,10L2,10v2h12v-2zM14,6L2,6v2h12L14,6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2,16h8v-2L2,14v2z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/>
|
||||
</vector>
|
||||
@@ -1,5 +1,6 @@
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
@@ -10,9 +11,11 @@
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/save_as_file_name"/>
|
||||
<EditText
|
||||
tools:targetApi="o"
|
||||
android:id="@+id/file_name"
|
||||
android:inputType="text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/file_name" />
|
||||
android:hint="@string/file_name"
|
||||
android:importantForAutofill="no"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
android:orientation="vertical">
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/use_history"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/use_history"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/open_with_url"/>
|
||||
<EditText
|
||||
tools:targetApi="o"
|
||||
android:id="@+id/open_with_url"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:gravity="start|top"
|
||||
android:typeface="monospace"
|
||||
android:imeOptions="flagNoExtractUi"
|
||||
android:inputType="textUri"
|
||||
android:hint="@string/open_with_url_hint"
|
||||
android:importantForAutofill="no"/>
|
||||
</LinearLayout>
|
||||
@@ -16,6 +16,11 @@
|
||||
android:title="@string/switch_camera"
|
||||
android:icon="@drawable/ic_action_switch_camera"
|
||||
material:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/preferences"
|
||||
android:title="@string/preferences"
|
||||
android:icon="@drawable/ic_action_preferences"
|
||||
material:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/info"
|
||||
android:title="@string/info"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<string name="cannot_resolve_action">Keine App kann das öffnen</string>
|
||||
<string name="pick_search_engine">Suchmaschine auswählen</string>
|
||||
<string name="format">Format</string>
|
||||
<string name="size">Größe in Pixeln</string>
|
||||
<string name="size">Größe in Pixel</string>
|
||||
<string name="width_by_height">%1$d×%2$d</string>
|
||||
<string name="input_content_here">Gib den Inhalt hier ein</string>
|
||||
<string name="encode">KODIEREN</string>
|
||||
@@ -28,7 +28,9 @@
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Kamera wechseln</string>
|
||||
<string name="history">Gespeicherte Codes</string>
|
||||
<string name="preferences">Einstellungen</string>
|
||||
<string name="use_history">Codes speichern</string>
|
||||
<string name="open_with_url">URL zum Öffnen unbekannter Daten</string>
|
||||
<string name="really_remove_scan">Code wirklich entfernen?</string>
|
||||
<string name="really_remove_all_scans">Alle Codes entfernen?</string>
|
||||
<string name="clear_history">Gespeicherte Codes löschen</string>
|
||||
@@ -53,4 +55,6 @@
|
||||
<string name="vcard_failed">Konnte nicht zu den Kontakten hinzufügen</string>
|
||||
<string name="vevent_add">Zum Kalender hinzufügen</string>
|
||||
<string name="vevent_failed">Konnte nicht zum Kalender hinzufügen</string>
|
||||
<string name="otpauth_add">2FA hinzufügen</string>
|
||||
<string name="otpauth_error">Konnte 2FA nicht hinzufügen</string>
|
||||
</resources>
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Changer de camera</string>
|
||||
<string name="history">Historique</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="use_history">Sauvegarder l\'histoire des scans</string>
|
||||
<string name="open_with_url">Open unknown data with URL</string>
|
||||
<string name="really_remove_scan">Supprimer le scan ?</string>
|
||||
<string name="really_remove_all_scans">Supprimer tous les scans ?</string>
|
||||
<string name="clear_history">Clear history</string>
|
||||
@@ -53,4 +55,6 @@
|
||||
<string name="vcard_failed">Could not add to contacts</string>
|
||||
<string name="vevent_add">Add to calendar</string>
|
||||
<string name="vevent_failed">Could not add to calendar</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
<string name="info">Információ</string>
|
||||
<string name="switch_camera">Kamera átkapcsolása</string>
|
||||
<string name="history">Előzmények</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="use_history">Beolvasási előzmények mentése</string>
|
||||
<string name="open_with_url">Open unknown data with URL</string>
|
||||
<string name="really_remove_scan">Valóban eltávolítja a beolvasást?</string>
|
||||
<string name="really_remove_all_scans">Valóban eltávolítja az összes beolvasását?</string>
|
||||
<string name="clear_history">Előzmények törlése</string>
|
||||
@@ -53,4 +55,6 @@
|
||||
<string name="vcard_failed">Could not add to contacts</string>
|
||||
<string name="vevent_add">Add to calendar</string>
|
||||
<string name="vevent_failed">Could not add to calendar</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="no_camera_no_fun">Aplikasi ini tidak akan bisa bekerja tanpa akses kamera. Selamat tinggal.</string>
|
||||
<resources>
|
||||
<string name="no_camera_no_fun">Aplikasi tidak akan bisa bekerja tanpa akses kamera. Selamat tinggal.</string>
|
||||
<string name="camera_error">Tidak bisa mengakses kamera, silakan coba lagi</string>
|
||||
<string name="scan_code">Pindai kode</string>
|
||||
<string name="compose_barcode">Buat barcode</string>
|
||||
<string name="decode_barcode">Dekode barcode</string>
|
||||
<string name="content">Konten</string>
|
||||
<string name="binary_data">(data binari)</string>
|
||||
<plurals name="barcode_info" tools:ignore="UnusedQuantity">
|
||||
<plurals name="barcode_info">
|
||||
<item quantity="one">%1$s\n%2$d karakter</item>
|
||||
<item quantity="other">%1$s\n%2$d karakter</item>
|
||||
</plurals>
|
||||
@@ -28,7 +28,9 @@
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Ganti kamera</string>
|
||||
<string name="history">Riwayat</string>
|
||||
<string name="preferences">Preferensi</string>
|
||||
<string name="use_history">Simpan riwayat pemindaian</string>
|
||||
<string name="open_with_url">Buka data tak dikenal dengan URL</string>
|
||||
<string name="really_remove_scan">Yakin menghapus pemindaian?</string>
|
||||
<string name="really_remove_all_scans">Yakin menghapus semua pemindaian?</string>
|
||||
<string name="clear_history">Hapus riwayat</string>
|
||||
@@ -40,17 +42,19 @@
|
||||
<string name="file_name">Nama berkas</string>
|
||||
<string name="error_saving_binary_data">Tidak bisa menyimpan berkas</string>
|
||||
<string name="error_file_exists">Berkas sudah ada</string>
|
||||
<string name="connect_to_wifi">Connect to WiFi</string>
|
||||
<string name="wifi_config_failed">Could not configure WiFi</string>
|
||||
<string name="wifi_added">WiFi added</string>
|
||||
<string name="sms_send">Send SMS</string>
|
||||
<string name="sms_error">Could not send SMS</string>
|
||||
<string name="tel_dial">Dial number</string>
|
||||
<string name="tel_error">Could not dial number</string>
|
||||
<string name="mail_send">Send mail</string>
|
||||
<string name="mail_error">Could not send mail</string>
|
||||
<string name="vcard_add">Add to contacts</string>
|
||||
<string name="vcard_failed">Could not add to contacts</string>
|
||||
<string name="vevent_add">Add to calendar</string>
|
||||
<string name="vevent_failed">Could not add to calendar</string>
|
||||
<string name="connect_to_wifi">Sambungkan ke WiFi</string>
|
||||
<string name="wifi_config_failed">Tidak bisa mengelola WiFi</string>
|
||||
<string name="wifi_added">WiFi ditambahkan</string>
|
||||
<string name="sms_send">Kirim SMS</string>
|
||||
<string name="sms_error">Tidak bisa mengirim SMS</string>
|
||||
<string name="tel_dial">Panggil nomor</string>
|
||||
<string name="tel_error">Tidak bisa memanggil nomor</string>
|
||||
<string name="mail_send">Kirim surel</string>
|
||||
<string name="mail_error">Tidak bisa mengirim surel</string>
|
||||
<string name="vcard_add">Tambahkan ke kontak</string>
|
||||
<string name="vcard_failed">Tidak bisa menambahkan ke kontak</string>
|
||||
<string name="vevent_add">Tambahkan ke kalender</string>
|
||||
<string name="vevent_failed">Tidak bisa menambahkan ke kalender</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Cambia camera</string>
|
||||
<string name="history">Cronologia</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="use_history">Salva cronologia delle scansioni</string>
|
||||
<string name="open_with_url">Open unknown data with URL</string>
|
||||
<string name="really_remove_scan">Vuoi veramente rimuovere la scansione?</string>
|
||||
<string name="really_remove_all_scans">Vuoi veramente rimuovere tutte le scansioni?</string>
|
||||
<string name="clear_history">Pulisci cronologia</string>
|
||||
@@ -53,4 +55,6 @@
|
||||
<string name="vcard_failed">Could not add to contacts</string>
|
||||
<string name="vevent_add">Add to calendar</string>
|
||||
<string name="vevent_failed">Could not add to calendar</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
<string name="info">Informatie</string>
|
||||
<string name="switch_camera">Camera wisselen</string>
|
||||
<string name="history">History</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="use_history">Save scan history</string>
|
||||
<string name="open_with_url">Open unknown data with URL</string>
|
||||
<string name="really_remove_scan">Really remove scan?</string>
|
||||
<string name="really_remove_all_scans">Really remove all scans?</string>
|
||||
<string name="clear_history">Clear history</string>
|
||||
@@ -53,4 +55,6 @@
|
||||
<string name="vcard_failed">Could not add to contacts</string>
|
||||
<string name="vevent_add">Add to calendar</string>
|
||||
<string name="vevent_failed">Could not add to calendar</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<resources>
|
||||
<string name="no_camera_no_fun">Esse aplicativo não faz sentido de uso sem acesso para a câmera. Adeus.</string>
|
||||
<string name="camera_error">Sem acesso a câmera, por favor tente novamente</string>
|
||||
<string name="scan_code">Escaneie o código de barras</string>
|
||||
<string name="compose_barcode">Compor código de barras</string>
|
||||
<string name="decode_barcode">Decodificar código de barras</string>
|
||||
<string name="content">Conteúdo</string>
|
||||
<string name="binary_data">(binários)</string>
|
||||
<plurals name="barcode_info">
|
||||
<item quantity="one">%1$s\n%2$d cacractere</item>
|
||||
<item quantity="other">%1$s\n%2$d caracteres</item>
|
||||
</plurals>
|
||||
<string name="toggle_flash">Ativar lanterna</string>
|
||||
<string name="share">Compartilhar</string>
|
||||
<string name="copy_to_clipboard">Copiar para área de transferência</string>
|
||||
<string name="put_into_clipboard">Colocar na área de transferência</string>
|
||||
<string name="open_url">Abrir url</string>
|
||||
<string name="cannot_resolve_action">Nenhuma aplicativo pode abrir isso</string>
|
||||
<string name="pick_search_engine">Escolha um mecanismo de busca</string>
|
||||
<string name="format">Formatar</string>
|
||||
<string name="size">Tamanho em pixels</string>
|
||||
<string name="width_by_height">%1$d×%2$d</string>
|
||||
<string name="input_content_here">Insira o conteúdo aqui</string>
|
||||
<string name="encode">CODIFICAR</string>
|
||||
<string name="error_no_content">Conteúdo não disponível</string>
|
||||
<string name="error_encoding_barcode">Não foi possível gerar o código de barras</string>
|
||||
<string name="view_barcode">Ver código de barras</string>
|
||||
<string name="info">Informações</string>
|
||||
<string name="switch_camera">Trocar câmera</string>
|
||||
<string name="history">Histórico</string>
|
||||
<string name="preferences">Preferências</string>
|
||||
<string name="use_history">Salvar histórico de escaneamento</string>
|
||||
<string name="open_with_url">Abrir dados desconhecidos com URL</string>
|
||||
<string name="really_remove_scan">Realmente deseja remover o escaneamento?</string>
|
||||
<string name="really_remove_all_scans">Realmente deseja remover todos escaneamentos?</string>
|
||||
<string name="clear_history">Limpar histórico</string>
|
||||
<string name="no_barcode_found">Código de barras não encontrado</string>
|
||||
<string name="pick_list_separator">Como separar itens da lista?</string>
|
||||
<string name="separator_line_break">Quebra de linha</string>
|
||||
<string name="separator_ruler">Régua</string>
|
||||
<string name="save_as_file_name">Salvar como arquivo de imagem?</string>
|
||||
<string name="file_name">Nome do arquivo</string>
|
||||
<string name="error_saving_binary_data">Arquivo não pode ser salvo</string>
|
||||
<string name="error_file_exists">Arquivo já existe</string>
|
||||
<string name="connect_to_wifi">Conectar para o WiFi</string>
|
||||
<string name="wifi_config_failed">Não foi possível configurar o WiFi</string>
|
||||
<string name="wifi_added">WiFi adicionado</string>
|
||||
<string name="sms_send">Enviar SMS</string>
|
||||
<string name="sms_error">Não foi possível enviar o SMS</string>
|
||||
<string name="tel_dial">Discar número</string>
|
||||
<string name="tel_error">Não foi possível discar o número</string>
|
||||
<string name="mail_send">Enviar e-mail</string>
|
||||
<string name="mail_error">Não foi possível enviar o e-mail</string>
|
||||
<string name="vcard_add">Adicionar para os contatos</string>
|
||||
<string name="vcard_failed">NNão foi possível adicionar para os contatos</string>
|
||||
<string name="vevent_add">Adicionar ao calendário</string>
|
||||
<string name="vevent_failed">Não foi possível adicionar ao calendário</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,60 @@
|
||||
<resources>
|
||||
<string name="no_camera_no_fun">没有相机权限,这个软件有啥意义。再见!</string>
|
||||
<string name="camera_error">无法访问相机,请重试。</string>
|
||||
<string name="scan_code">Scan code</string>
|
||||
<string name="compose_barcode">制作条形码</string>
|
||||
<string name="decode_barcode">解码条形码</string>
|
||||
<string name="content">内容</string>
|
||||
<string name="binary_data">(二进制数据)</string>
|
||||
<plurals name="barcode_info">
|
||||
<item quantity="one">%1$s\n%2$d 字符</item>
|
||||
<item quantity="other">%1$s\n%2$d 字符</item>
|
||||
</plurals>
|
||||
<string name="toggle_flash">切换闪光灯</string>
|
||||
<string name="share">分享</string>
|
||||
<string name="copy_to_clipboard">复制到剪切板</string>
|
||||
<string name="put_into_clipboard">复制到剪切板</string>
|
||||
<string name="open_url">打开链接</string>
|
||||
<string name="cannot_resolve_action">没有应用程序可以打开它</string>
|
||||
<string name="pick_search_engine">选择一个搜索引擎</string>
|
||||
<string name="format">编码格式</string>
|
||||
<string name="size">图片尺寸</string>
|
||||
<string name="width_by_height">%1$d×%2$d</string>
|
||||
<string name="input_content_here">在这里输入内容</string>
|
||||
<string name="encode">编码</string>
|
||||
<string name="error_no_content">缺少内容</string>
|
||||
<string name="error_encoding_barcode">无法生成条形码</string>
|
||||
<string name="view_barcode">查看条形码</string>
|
||||
<string name="info">信息</string>
|
||||
<string name="switch_camera">切换摄像头</string>
|
||||
<string name="history">历史</string>
|
||||
<string name="preferences">首选项</string>
|
||||
<string name="use_history">保存扫描历史</string>
|
||||
<string name="open_with_url">使用URL打开未知数据</string>
|
||||
<string name="really_remove_scan">确定删除记录?</string>
|
||||
<string name="really_remove_all_scans">确定删除全部记录?</string>
|
||||
<string name="clear_history">删除记录</string>
|
||||
<string name="no_barcode_found">未找到条形码</string>
|
||||
<string name="pick_list_separator">如何分隔列表项?</string>
|
||||
<string name="separator_line_break">无</string>
|
||||
<string name="separator_ruler">分割线</string>
|
||||
<string name="save_as_file_name">保存为文件?</string>
|
||||
<string name="file_name">文件名</string>
|
||||
<string name="error_saving_binary_data">无法保存文件</string>
|
||||
<string name="error_file_exists">文件已存在</string>
|
||||
<string name="connect_to_wifi">连接到WiFi</string>
|
||||
<string name="wifi_config_failed">无法配置WiFi</string>
|
||||
<string name="wifi_added">WiFi已添加</string>
|
||||
<string name="sms_send">发送短信</string>
|
||||
<string name="sms_error">无法发送短信</string>
|
||||
<string name="tel_dial">拨打号码</string>
|
||||
<string name="tel_error">无法拨打此号码</string>
|
||||
<string name="mail_send">发送邮件</string>
|
||||
<string name="mail_error">无法发送邮件</string>
|
||||
<string name="vcard_add">添加到通讯录</string>
|
||||
<string name="vcard_failed">无法添加到通讯录</string>
|
||||
<string name="vevent_add">添加到日历</string>
|
||||
<string name="vevent_failed">无法添加到日历</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,60 @@
|
||||
<resources>
|
||||
<string name="no_camera_no_fun">沒有相機權限的話,這個程式根本什麽都做不了。再見!</string>
|
||||
<string name="camera_error">不能開啓相機,請重試</string>
|
||||
<string name="scan_code">掃描條碼</string>
|
||||
<string name="compose_barcode">製作條碼</string>
|
||||
<string name="decode_barcode">解讀條碼</string>
|
||||
<string name="content">内容</string>
|
||||
<string name="binary_data">(2進制碼)</string>
|
||||
<plurals name="barcode_info">
|
||||
<item quantity="one">%1$s\n%2$d 個字符</item>
|
||||
<item quantity="other">%1$s\n%2$d 個字符</item>
|
||||
</plurals>
|
||||
<string name="toggle_flash">閃光燈</string>
|
||||
<string name="share">分享</string>
|
||||
<string name="copy_to_clipboard">複製</string>
|
||||
<string name="put_into_clipboard">複製</string>
|
||||
<string name="open_url">開啓</string>
|
||||
<string name="cannot_resolve_action">無應用程式可以開啓</string>
|
||||
<string name="pick_search_engine">選擇搜尋引擎</string>
|
||||
<string name="format">格式</string>
|
||||
<string name="size">大小(pixels)</string>
|
||||
<string name="width_by_height">%1$d×%2$d</string>
|
||||
<string name="input_content_here">在此輸入</string>
|
||||
<string name="encode">製作條碼</string>
|
||||
<string name="error_no_content">找不到内容</string>
|
||||
<string name="error_encoding_barcode">條碼製作失敗</string>
|
||||
<string name="view_barcode">檢視條碼</string>
|
||||
<string name="info">資訊</string>
|
||||
<string name="switch_camera">切換相機</string>
|
||||
<string name="history">歷史</string>
|
||||
<string name="use_history">儲存掃描歷史</string>
|
||||
<string name="really_remove_scan">真的要移除掃描記錄?</string>
|
||||
<string name="really_remove_all_scans">真的要移除所有掃描記錄?</string>
|
||||
<string name="clear_history">清除記錄</string>
|
||||
<string name="no_barcode_found">找不到條碼</string>
|
||||
<string name="pick_list_separator">如何分開列表項目?</string>
|
||||
<string name="separator_line_break">Line break</string>
|
||||
<string name="separator_ruler">直尺</string>
|
||||
<string name="save_as_file_name">儲存成檔案?</string>
|
||||
<string name="file_name">檔案名稱</string>
|
||||
<string name="error_saving_binary_data">不能儲存檔案</string>
|
||||
<string name="error_file_exists">檔案已存在</string>
|
||||
<string name="connect_to_wifi">連接至 WiFi</string>
|
||||
<string name="wifi_config_failed">WiFi連接設定失敗</string>
|
||||
<string name="wifi_added">成功添加WiFi</string>
|
||||
<string name="sms_send">傳送SMS</string>
|
||||
<string name="sms_error">不能傳送SMS</string>
|
||||
<string name="tel_dial">撥號</string>
|
||||
<string name="tel_error">不能撥號</string>
|
||||
<string name="mail_send">發送電郵</string>
|
||||
<string name="mail_error">不能發送電郵</string>
|
||||
<string name="vcard_add">添加至聯絡人</string>
|
||||
<string name="vcard_failed">不能添加至聯絡人</string>
|
||||
<string name="vevent_add">添加至行事曆</string>
|
||||
<string name="vevent_failed">不能添加至行事曆</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="open_with_url">Preferences</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
@@ -1,3 +1,4 @@
|
||||
<resources>
|
||||
<string name="app_name">Binary Eye</string>
|
||||
<string name="open_with_url_hint">http://example.com?data=</string>
|
||||
</resources>
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Switch camera</string>
|
||||
<string name="history">History</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="use_history">Save scan history</string>
|
||||
<string name="open_with_url">Open unknown data with URL</string>
|
||||
<string name="really_remove_scan">Really remove scan?</string>
|
||||
<string name="really_remove_all_scans">Really remove all scans?</string>
|
||||
<string name="clear_history">Clear history</string>
|
||||
@@ -53,4 +55,6 @@
|
||||
<string name="vcard_failed">Could not add to contacts</string>
|
||||
<string name="vevent_add">Add to calendar</string>
|
||||
<string name="vevent_failed">Could not add to calendar</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="otpauth_error">Could not add 2FA</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.markusfisch.android.binaryeye
|
||||
|
||||
import junit.framework.TestCase.fail
|
||||
|
||||
fun simpleFail(message: String = "Unknown reason, but failed"): Nothing {
|
||||
fail(message)
|
||||
throw IllegalStateException("You should never have reached this point in the code, but anyways: $message")
|
||||
}
|
||||
|
||||
inline fun <reified E : Throwable> assertThrows(message: String = "Unknown reason, but didn't failed even though should fail", block: () -> Unit) {
|
||||
try {
|
||||
block()
|
||||
fail(message)
|
||||
} catch (e: Throwable) {
|
||||
if (e !is E) {
|
||||
fail("Got unexpected other Throwable: ${e::class.java.simpleName}\n$e")
|
||||
}
|
||||
}
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
package de.markusfisch.android.binaryeye.actions.otpauth
|
||||
|
||||
import de.markusfisch.android.binaryeye.assertThrows
|
||||
import de.markusfisch.android.binaryeye.simpleFail
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import junit.framework.TestCase.assertNull
|
||||
import org.junit.Test
|
||||
|
||||
class OtpauthParserTest {
|
||||
@Test
|
||||
fun noOtpauthUri() {
|
||||
assertNull(OtpauthParser("random string"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun missingSecret() {
|
||||
assertNull(OtpauthParser("otpauth://totp/issuerName:accountName"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun missingCounterHotp() {
|
||||
assertNull(OtpauthParser("otpauth://hotp/accountName?secret=secretString"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minimalHotp() {
|
||||
val parser = validParser("otpauth://hotp/accountName?secret=secretString&counter=50")
|
||||
assertEquals("hotp", parser.otpType)
|
||||
assertEquals("accountName", parser.accountName)
|
||||
assertEquals("secretString", parser.secret)
|
||||
assertEquals("SHA1", parser.algorithm)
|
||||
assertEquals(6, parser.digits)
|
||||
assertEquals(30, parser.period)
|
||||
assertEquals(50, parser.counter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun normalHotp() {
|
||||
val parser = validParser("otpauth://hotp/issuerName:accountName?secret=secretString&counter=0")
|
||||
assertEquals("hotp", parser.otpType)
|
||||
assertEquals("issuerName", parser.issuer)
|
||||
assertEquals("accountName", parser.accountName)
|
||||
assertEquals("secretString", parser.secret)
|
||||
assertEquals("SHA1", parser.algorithm)
|
||||
assertEquals(6, parser.digits)
|
||||
assertEquals(30, parser.period)
|
||||
assertEquals(0, parser.counter)
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun missingIssuerParamHotp() {
|
||||
val parser = validParser("otpauth://hotp/issuerName:accountName?secret=secretString&counter=50&algorithm=SHA256&digits=8")
|
||||
assertEquals("hotp", parser.otpType)
|
||||
assertEquals("issuerName", parser.issuer)
|
||||
assertEquals("accountName", parser.accountName)
|
||||
assertEquals("secretString", parser.secret)
|
||||
assertEquals("SHA256", parser.algorithm)
|
||||
assertEquals(8, parser.digits)
|
||||
assertEquals(30, parser.period)
|
||||
assertEquals(50, parser.counter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fullHotp() {
|
||||
val parser = validParser("otpauth://hotp/issuerName:accountName?secret=secretString&counter=50&issuer=issuerName&algorithm=SHA256&digits=8")
|
||||
assertEquals("hotp", parser.otpType)
|
||||
assertEquals("issuerName", parser.issuer)
|
||||
assertEquals("accountName", parser.accountName)
|
||||
assertEquals("secretString", parser.secret)
|
||||
assertEquals("SHA256", parser.algorithm)
|
||||
assertEquals(8, parser.digits)
|
||||
assertEquals(30, parser.period)
|
||||
assertEquals(50, parser.counter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minimalTotp() {
|
||||
val parser = validParser("otpauth://totp/accountName?secret=secretString")
|
||||
assertEquals("totp", parser.otpType)
|
||||
assertEquals("accountName", parser.accountName)
|
||||
assertEquals("secretString", parser.secret)
|
||||
assertEquals("SHA1", parser.algorithm)
|
||||
assertEquals(6, parser.digits)
|
||||
assertEquals(30, parser.period)
|
||||
assertThrows<NumberFormatException> {
|
||||
parser.counter
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun normalTotp() {
|
||||
val parser = validParser("otpauth://totp/issuerName:accountName?secret=secretString")
|
||||
assertEquals("totp", parser.otpType)
|
||||
assertEquals("issuerName", parser.issuer)
|
||||
assertEquals("accountName", parser.accountName)
|
||||
assertEquals("secretString", parser.secret)
|
||||
assertEquals("SHA1", parser.algorithm)
|
||||
assertEquals(6, parser.digits)
|
||||
assertEquals(30, parser.period)
|
||||
assertThrows<NumberFormatException> {
|
||||
parser.counter
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun missingIssuerParamTotp() {
|
||||
val parser = validParser("otpauth://totp/issuerName:accountName?secret=secretString&algorithm=SHA256&digits=8&period=60")
|
||||
assertEquals("totp", parser.otpType)
|
||||
assertEquals("issuerName", parser.issuer)
|
||||
assertEquals("accountName", parser.accountName)
|
||||
assertEquals("secretString", parser.secret)
|
||||
assertEquals("SHA256", parser.algorithm)
|
||||
assertEquals(8, parser.digits)
|
||||
assertEquals(60, parser.period)
|
||||
assertThrows<NumberFormatException> {
|
||||
parser.counter
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fullTotp() {
|
||||
val parser = validParser("otpauth://totp/issuerName:accountName?secret=secretString&issuer=issuerName&algorithm=SHA256&digits=8&period=60")
|
||||
assertEquals("totp", parser.otpType)
|
||||
assertEquals("issuerName", parser.issuer)
|
||||
assertEquals("accountName", parser.accountName)
|
||||
assertEquals("secretString", parser.secret)
|
||||
assertEquals("SHA256", parser.algorithm)
|
||||
assertEquals(8, parser.digits)
|
||||
assertEquals(60, parser.period)
|
||||
assertThrows<NumberFormatException> {
|
||||
parser.counter
|
||||
}
|
||||
}
|
||||
|
||||
private fun validParser(input: String): OtpauthParser {
|
||||
return OtpauthParser(input) ?: simpleFail("Could not get parser of valid input")
|
||||
}
|
||||
}
|
||||
+1
-6
@@ -1,10 +1,10 @@
|
||||
package de.markusfisch.android.binaryeye.actions.wifi
|
||||
|
||||
import de.markusfisch.android.binaryeye.simpleFail
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import junit.framework.TestCase.assertFalse
|
||||
import junit.framework.TestCase.assertNull
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import junit.framework.TestCase.fail
|
||||
import org.junit.Test
|
||||
|
||||
class WifiConfigurationFactoryTest {
|
||||
@@ -84,11 +84,6 @@ class WifiConfigurationFactoryTest {
|
||||
assertFalse(info.hidden)
|
||||
}
|
||||
|
||||
private fun simpleFail(message: String = "Unknown reason, but failed"): Nothing {
|
||||
fail(message)
|
||||
throw IllegalStateException("You should never have reached this point in the code, but anyways: $message")
|
||||
}
|
||||
|
||||
private fun simpleDataAccessor(wifiString: String): WifiConfigurationFactory.SimpleDataAccessor {
|
||||
val map = WifiConfigurationFactory.parseMap(wifiString)
|
||||
?: simpleFail("parsing map of valid string fails ($wifiString)")
|
||||
|
||||
Reference in New Issue
Block a user