Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3274fd065 | ||
|
|
c75b9f73ab | ||
|
|
1432669aee | ||
|
|
00a8a94b59 | ||
|
|
c8c3da91ae | ||
|
|
8cbc73b7f8 | ||
|
|
941d875b3e | ||
|
|
1ac578845e | ||
|
|
e816e8bf89 | ||
|
|
54c368fcd8 | ||
|
|
c225e7d9eb | ||
|
|
6a0ce45a65 | ||
|
|
11c97cc4ef | ||
|
|
e3f6732bb8 | ||
|
|
53ae706b9c | ||
|
|
26a7ad2e6e | ||
|
|
9c3984ce7a | ||
|
|
f7d07e0b8a | ||
|
|
3fe0f50289 | ||
|
|
e86cf9d2cc | ||
|
|
4f1482d2c9 | ||
|
|
c42ad7dbea | ||
|
|
fa3cc8c408 | ||
|
|
e4863bad4c | ||
|
|
484bbbc997 | ||
|
|
565643f19e | ||
|
|
4c92045563 | ||
|
|
7116aa7278 | ||
|
|
860e867ad4 | ||
|
|
3b509cd09c | ||
|
|
51ec228fd8 | ||
|
|
9d1dec146d | ||
|
|
7bd9fe36fe | ||
|
|
85dba0604c | ||
|
|
56c70f5974 | ||
|
|
098b7740a0 | ||
|
|
7d92481fa6 | ||
|
|
2e285a5b1d | ||
|
|
ad25c4681f | ||
|
|
c00c87ceca | ||
|
|
e001a92870 | ||
|
|
7a32b00e1f | ||
|
|
50cedf782d | ||
|
|
fb0d22198f | ||
|
|
af528df448 | ||
|
|
a9b5771d57 | ||
|
|
a161e8fc0f | ||
|
|
ec17d07695 | ||
|
|
be2fc2f559 | ||
|
|
de3aa752ff | ||
|
|
411cbb243f | ||
|
|
f76c1521fe | ||
|
|
9b9224b100 |
@@ -1,5 +1,33 @@
|
||||
# Change Log
|
||||
|
||||
## 1.34.0
|
||||
* Use Material Design settings with headers
|
||||
* Add a setting to choose the message type when forwarding scanned content
|
||||
|
||||
## 1.33.0
|
||||
* Add a setting to automatically send the scanned content to a custom URL
|
||||
* Add a setting to automatically put contents into clipboard
|
||||
* Add an explicit button to copy WiFi password into clipboard
|
||||
* Update Indonesian translation
|
||||
|
||||
## 1.32.1
|
||||
* Alternatively remove region of interest by dragging handle to a screen corner
|
||||
* Restrict region of interest to screen space
|
||||
* Remove extra action item to create barcode
|
||||
|
||||
## 1.32.0
|
||||
* Add bulk mode
|
||||
* Remember region of interest permanently
|
||||
* Export generated barcode as SVG
|
||||
* Run detection on images in background
|
||||
* Remove a scan from result view
|
||||
* Update Indonesian translation
|
||||
|
||||
## 1.31.0
|
||||
* Stop detection while region of interest is modified
|
||||
* Fix resetting region of interest
|
||||
* Add Polish translation
|
||||
|
||||
## 1.30.1
|
||||
* Improve usability of cropping limiter
|
||||
* Draw round corners around region of interest
|
||||
|
||||
@@ -79,29 +79,6 @@ be thrown and the only option is to restart the app, this time with calling
|
||||
Calling `RenderScript.forceCompat()` means the processing is done in
|
||||
software so you probably don't want to enable it by default.
|
||||
|
||||
### macOS Catalina
|
||||
|
||||
At the time of writing, calling `RenderScript.forceCompat()` in a build made
|
||||
on macOS Catalina with build tools 29.0.3 will crash the app. This is a bug
|
||||
in the build tools for Catalina.
|
||||
|
||||
So *do not* build release builts on macOS Catalina with build tools 29.0.3.
|
||||
|
||||
Building on Linux with 29.0.3 works fine.
|
||||
|
||||
### Side by Side NDK
|
||||
|
||||
At the time of writing, it's important to _not_ have the NDK available when
|
||||
compiling the custom rotation kernel. This will produce a broken build for
|
||||
some ARMv7 devices running Android 6 (e.g. One Plus X, Yotaphone 2, Moto E)
|
||||
while it works for newer Android versions.
|
||||
|
||||
### App Bundle
|
||||
|
||||
At the time of writing, `./gradlew bundleRelease` will produce a broken
|
||||
App Bundle without the necessary RenderScript libraries. This is another
|
||||
bug in the build tools.
|
||||
|
||||
### 2D barcodes
|
||||
|
||||
If you want to fork this and are only interested in reading 2D barcodes
|
||||
|
||||
@@ -9,13 +9,14 @@ android {
|
||||
minSdkVersion 9
|
||||
targetSdkVersion sdk_version
|
||||
|
||||
versionCode 67
|
||||
versionName '1.30.1'
|
||||
versionCode 72
|
||||
versionName '1.34.0'
|
||||
|
||||
// it's recommended to set this value to the lowest API level
|
||||
// able to provide all the functionality
|
||||
renderscriptTargetApi 24
|
||||
renderscriptSupportModeEnabled true
|
||||
renderscriptSupportModeBlasEnabled true
|
||||
|
||||
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
|
||||
}
|
||||
@@ -70,6 +71,8 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
|
||||
implementation "com.android.support:appcompat-v7:$support_version"
|
||||
implementation "com.android.support:design:$support_version"
|
||||
implementation "com.android.support:preference-v7:$support_version"
|
||||
implementation "com.android.support:preference-v14:$support_version"
|
||||
// Do NOT upgrade ZXing because newer versions won't work on API < 24
|
||||
// https://github.com/zxing/zxing/issues/1170
|
||||
implementation 'com.google.zxing:core:3.3.3'
|
||||
|
||||
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 47 KiB |
@@ -1,14 +1,14 @@
|
||||
package de.markusfisch.android.binaryeye
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.support.test.InstrumentationRegistry
|
||||
import android.support.test.runner.AndroidJUnit4
|
||||
|
||||
import de.markusfisch.android.binaryeye.rs.Preprocessor
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
|
||||
import org.junit.Assert.fail;
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@@ -19,22 +19,27 @@ class PreprocessorTest {
|
||||
val assets = InstrumentationRegistry.getInstrumentation()
|
||||
.context.assets
|
||||
val pattern = Pattern.compile(
|
||||
"[0-9]+-([0-9]+)x([0-9]+)-([0-9]+)deg.yuv"
|
||||
"[0-9]+-([0-9]+)deg.jpg"
|
||||
)
|
||||
val files = assets.list("yuv") ?: return
|
||||
for (file in files) {
|
||||
val m = pattern.matcher(file)
|
||||
if (!m.find() || m.groupCount() < 3) {
|
||||
continue
|
||||
val samples = assets.list("samples")
|
||||
checkNotNull(samples) { "no samples found" }
|
||||
for (sample in samples) {
|
||||
val m = pattern.matcher(sample)
|
||||
if (!m.find() || m.groupCount() < 1) {
|
||||
fail("invalid sample: $sample")
|
||||
}
|
||||
val frameWidth = m.group(1) ?: return
|
||||
val frameHeight = m.group(2) ?: return
|
||||
val frameOrientation = m.group(3) ?: return
|
||||
val frameData = assets.open("yuv/$file").readBytes()
|
||||
val bitmap = BitmapFactory.decodeStream(
|
||||
assets.open("samples/$sample")
|
||||
)
|
||||
val frameData = getNV21(bitmap)
|
||||
val frameWidth = bitmap.width
|
||||
val frameHeight = bitmap.height
|
||||
val frameOrientation = m.group(1) ?: return
|
||||
val preprocessor = Preprocessor(
|
||||
InstrumentationRegistry.getTargetContext(),
|
||||
frameWidth.toInt(),
|
||||
frameHeight.toInt()
|
||||
frameWidth,
|
||||
frameHeight,
|
||||
null
|
||||
)
|
||||
val outWidth: Int
|
||||
val outHeight: Int
|
||||
@@ -51,7 +56,48 @@ class PreprocessorTest {
|
||||
val result = zxing.decode(frameData, outWidth, outHeight)
|
||||
preprocessor.destroy()
|
||||
|
||||
checkNotNull(result) { "no barcode found in $file" }
|
||||
checkNotNull(result) { "no barcode found in $sample" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getNV21(bitmap: Bitmap): ByteArray {
|
||||
val width = bitmap.width
|
||||
val height = bitmap.height
|
||||
val argb = IntArray(width * height)
|
||||
bitmap.getPixels(argb, 0, width, 0, 0, width, height)
|
||||
return encodeYUV420SP(argb, width, height)
|
||||
}
|
||||
|
||||
private fun encodeYUV420SP(argb: IntArray, width: Int, height: Int): ByteArray {
|
||||
val yuv = ByteArray(ceilIfUneven(width) * ceilIfUneven(height) * 3 / 2)
|
||||
var yIndex = 0
|
||||
var uvIndex = width * height
|
||||
var r: Int
|
||||
var g: Int
|
||||
var b: Int
|
||||
var Y: Int
|
||||
var u: Int
|
||||
var v: Int
|
||||
var index = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val pixel = argb[index]
|
||||
r = pixel and 0xff0000 shr 16
|
||||
g = pixel and 0xff00 shr 8
|
||||
b = pixel and 0xff
|
||||
Y = (66 * r + 129 * g + 25 * b + 128 shr 8) + 16
|
||||
u = (-38 * r - 74 * g + 112 * b + 128 shr 8) + 128
|
||||
v = (112 * r - 94 * g - 18 * b + 128 shr 8) + 128
|
||||
yuv[yIndex++] = (if (Y < 0) 0 else if (Y > 255) 255 else Y).toByte()
|
||||
if (y % 2 == 0 && index % 2 == 0) {
|
||||
yuv[uvIndex++] = (if (v < 0) 0 else if (v > 255) 255 else v).toByte()
|
||||
yuv[uvIndex++] = (if (u < 0) 0 else if (u > 255) 255 else u).toByte()
|
||||
}
|
||||
++index
|
||||
}
|
||||
}
|
||||
return yuv
|
||||
}
|
||||
|
||||
private fun ceilIfUneven(n: Int) = if (n and 1 == 1) n + 1 else n
|
||||
|
||||
@@ -7,15 +7,18 @@
|
||||
android:xlargeScreens="true"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-feature android:name="android.hardware.camera"/>
|
||||
<uses-feature android:name="android.hardware.camera.autofocus"/>
|
||||
<uses-sdk tools:overrideLibrary="android.support.v14.preference"/>
|
||||
<application
|
||||
tools:ignore="UnusedAttribute"
|
||||
android:name=".app.BinaryEyeApp"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:supportsRtl="true"
|
||||
|
||||
@@ -24,18 +24,17 @@ import com.google.zxing.ResultMetadataType
|
||||
import com.google.zxing.ResultPointCallback
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.*
|
||||
import de.markusfisch.android.binaryeye.data.Scan
|
||||
import de.markusfisch.android.binaryeye.database.Scan
|
||||
import de.markusfisch.android.binaryeye.graphics.Mapping
|
||||
import de.markusfisch.android.binaryeye.graphics.frameToView
|
||||
import de.markusfisch.android.binaryeye.graphics.isPortrait
|
||||
import de.markusfisch.android.binaryeye.net.sendAsync
|
||||
import de.markusfisch.android.binaryeye.rs.Preprocessor
|
||||
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
|
||||
import de.markusfisch.android.binaryeye.widget.DetectorView
|
||||
import de.markusfisch.android.binaryeye.widget.toast
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
import de.markusfisch.android.cameraview.widget.CameraView
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
@@ -64,8 +63,11 @@ class CameraActivity : AppCompatActivity() {
|
||||
private var rotate = false
|
||||
private var invert = false
|
||||
private var flash = false
|
||||
private var decoding = true
|
||||
private var returnResult = false
|
||||
private var frontFacing = false
|
||||
private var bulkMode = false
|
||||
private var ignoreNext: String? = null
|
||||
private var fallbackBuffer: IntArray? = null
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
@@ -74,7 +76,7 @@ class CameraActivity : AppCompatActivity() {
|
||||
grantResults: IntArray
|
||||
) {
|
||||
when (requestCode) {
|
||||
REQUEST_CAMERA -> if (grantResults.isNotEmpty() &&
|
||||
PERMISSION_CAMERA -> if (grantResults.isNotEmpty() &&
|
||||
grantResults[0] != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
toast(R.string.no_camera_no_fun)
|
||||
@@ -116,9 +118,7 @@ class CameraActivity : AppCompatActivity() {
|
||||
|
||||
initCameraView()
|
||||
initZoomBar()
|
||||
restoreZoom()
|
||||
detectorView.updateRoi = { recreatePreprocessor = true }
|
||||
detectorView.setPaddingFromWindowInsets()
|
||||
initDetectorView()
|
||||
|
||||
if (intent?.action == Intent.ACTION_SEND &&
|
||||
intent.type == "text/plain"
|
||||
@@ -132,6 +132,7 @@ class CameraActivity : AppCompatActivity() {
|
||||
resetPreProcessor()
|
||||
fallbackBuffer = null
|
||||
saveZoom()
|
||||
saveCropHandlePos()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -139,7 +140,7 @@ class CameraActivity : AppCompatActivity() {
|
||||
System.gc()
|
||||
zxing.updateHints(prefs.tryHarder)
|
||||
returnResult = "com.google.zxing.client.android.SCAN" == intent.action
|
||||
if (hasCameraPermission(this, REQUEST_CAMERA)) {
|
||||
if (hasCameraPermission(this)) {
|
||||
openCamera()
|
||||
}
|
||||
}
|
||||
@@ -178,17 +179,29 @@ class CameraActivity : AppCompatActivity() {
|
||||
zoomBar.max = savedState.getInt(ZOOM_MAX)
|
||||
zoomBar.progress = savedState.getInt(ZOOM_LEVEL)
|
||||
frontFacing = savedState.getBoolean(FRONT_FACING)
|
||||
bulkMode = savedState.getBoolean(BULK_MODE)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putInt(ZOOM_MAX, zoomBar.max)
|
||||
outState.putInt(ZOOM_LEVEL, zoomBar.progress)
|
||||
outState.putBoolean(FRONT_FACING, frontFacing)
|
||||
outState.putBoolean(BULK_MODE, bulkMode)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
||||
// always give crop handle precedence over other controls
|
||||
// because it can easily overlap and would then be inaccessible
|
||||
if (detectorView.onTouchEvent(ev)) {
|
||||
return true
|
||||
}
|
||||
return super.dispatchTouchEvent(ev)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.activity_camera, menu)
|
||||
menu.findItem(R.id.bulk_mode).isChecked = bulkMode
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -218,6 +231,11 @@ class CameraActivity : AppCompatActivity() {
|
||||
switchCamera()
|
||||
true
|
||||
}
|
||||
R.id.bulk_mode -> {
|
||||
bulkMode = bulkMode xor true
|
||||
item.isChecked = bulkMode
|
||||
true
|
||||
}
|
||||
R.id.preferences -> {
|
||||
startActivity(MainActivity.getPreferencesIntent(this))
|
||||
true
|
||||
@@ -347,7 +365,8 @@ class CameraActivity : AppCompatActivity() {
|
||||
val frameWidth = cameraView.frameWidth
|
||||
val frameHeight = cameraView.frameHeight
|
||||
val frameOrientation = cameraView.frameOrientation
|
||||
var decoding = true
|
||||
ignoreNext = null
|
||||
decoding = true
|
||||
camera.setPreviewCallback { frameData, _ ->
|
||||
if (decoding) {
|
||||
decodeFrame(
|
||||
@@ -356,8 +375,10 @@ class CameraActivity : AppCompatActivity() {
|
||||
frameHeight,
|
||||
frameOrientation
|
||||
)?.let { result ->
|
||||
postResult(result)
|
||||
decoding = false
|
||||
if (result.text != ignoreNext) {
|
||||
postResult(result)
|
||||
decoding = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -387,6 +408,7 @@ class CameraActivity : AppCompatActivity() {
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {}
|
||||
})
|
||||
restoreZoom()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@@ -418,6 +440,33 @@ class CameraActivity : AppCompatActivity() {
|
||||
)
|
||||
}
|
||||
|
||||
private fun initDetectorView() {
|
||||
detectorView.onRoiChange = {
|
||||
decoding = false
|
||||
}
|
||||
detectorView.onRoiChanged = {
|
||||
decoding = true
|
||||
recreatePreprocessor = true
|
||||
}
|
||||
detectorView.setPaddingFromWindowInsets()
|
||||
restoreCropHandlePos()
|
||||
}
|
||||
|
||||
private fun saveCropHandlePos() {
|
||||
val pos = detectorView.getCropHandlePos()
|
||||
prefs.cropHandleX = pos.x
|
||||
prefs.cropHandleY = pos.y
|
||||
prefs.cropHandleOrientation = detectorView.currentOrientation
|
||||
}
|
||||
|
||||
private fun restoreCropHandlePos() {
|
||||
detectorView.setCropHandlePos(
|
||||
prefs.cropHandleX,
|
||||
prefs.cropHandleY,
|
||||
prefs.cropHandleOrientation
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateFlashFab(unavailable: Boolean) {
|
||||
if (unavailable) {
|
||||
flashFab.setImageResource(R.drawable.ic_action_create)
|
||||
@@ -542,14 +591,19 @@ class CameraActivity : AppCompatActivity() {
|
||||
) {
|
||||
null
|
||||
} else {
|
||||
// map ROI in detectorView to cameraView because cameraView may
|
||||
// be larger than the detectorView
|
||||
// map ROI in detectorView to cameraView
|
||||
val previewRect = cameraView.previewRect
|
||||
// previewRect may be larger than the screen (and thus as the
|
||||
// detectorView) in which case its left and/or top coordinate
|
||||
// will be negative which must then be clamped to the
|
||||
// screen/DetectorView
|
||||
val previewLeft = max(0, previewRect.left)
|
||||
val previewTop = max(0, previewRect.top)
|
||||
val previewRoi = Rect(
|
||||
previewRect.left + viewRoi.left,
|
||||
previewRect.top + viewRoi.top,
|
||||
previewRect.left + viewRoi.right,
|
||||
previewRect.top + viewRoi.bottom
|
||||
previewLeft + viewRoi.left,
|
||||
previewTop + viewRoi.top,
|
||||
previewLeft + viewRoi.right,
|
||||
previewTop + viewRoi.bottom
|
||||
)
|
||||
val previewRectWidth = previewRect.width().toFloat()
|
||||
val previewRectHeight = previewRect.height().toFloat()
|
||||
@@ -591,37 +645,56 @@ class CameraActivity : AppCompatActivity() {
|
||||
showResult(
|
||||
this@CameraActivity,
|
||||
result,
|
||||
returnResult
|
||||
returnResult,
|
||||
bulkMode
|
||||
)
|
||||
if (bulkMode) {
|
||||
ignoreNext = result.text
|
||||
toast(result.text)
|
||||
detectorView.postDelayed({
|
||||
decoding = true
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMapping() = if (rotate) rotatedMapping else nativeMapping
|
||||
|
||||
companion object {
|
||||
private const val REQUEST_CAMERA = 1
|
||||
private const val PICK_FILE_RESULT_CODE = 1
|
||||
private const val ZOOM_MAX = "zoom_max"
|
||||
private const val ZOOM_LEVEL = "zoom_level"
|
||||
private const val FRONT_FACING = "front_facing"
|
||||
private const val BULK_MODE = "bulk_mode"
|
||||
}
|
||||
}
|
||||
|
||||
fun showResult(
|
||||
activity: Activity,
|
||||
result: Result,
|
||||
isResult: Boolean = false
|
||||
isResult: Boolean = false,
|
||||
bulkMode: Boolean = false
|
||||
) {
|
||||
val scan = Scan(result)
|
||||
if (isResult) {
|
||||
activity.setResult(Activity.RESULT_OK, getReturnIntent(result))
|
||||
activity.finish()
|
||||
} else {
|
||||
if (prefs.useHistory) {
|
||||
GlobalScope.launch {
|
||||
db.insertScan(scan)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
if (prefs.copyImmediately) {
|
||||
activity.copyToClipboard(result.text)
|
||||
}
|
||||
val scan = Scan(result)
|
||||
if (prefs.sendScanUrl.isNotEmpty()) {
|
||||
scan.sendAsync(
|
||||
activity.applicationContext,
|
||||
prefs.sendScanUrl,
|
||||
prefs.sendScanType
|
||||
)
|
||||
}
|
||||
if (prefs.useHistory) {
|
||||
scan.id = db.insertScan(scan)
|
||||
}
|
||||
if (!bulkMode) {
|
||||
activity.startActivity(
|
||||
MainActivity.getDecodeIntent(activity, scan)
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.colorSystemAndToolBars
|
||||
import de.markusfisch.android.binaryeye.app.initSystemBars
|
||||
import de.markusfisch.android.binaryeye.app.setFragment
|
||||
import de.markusfisch.android.binaryeye.data.Scan
|
||||
import de.markusfisch.android.binaryeye.database.Scan
|
||||
import de.markusfisch.android.binaryeye.fragment.DecodeFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.EncodeFragment
|
||||
import de.markusfisch.android.binaryeye.fragment.HistoryFragment
|
||||
|
||||
@@ -25,6 +25,10 @@ import de.markusfisch.android.binaryeye.view.recordToolbarHeight
|
||||
import de.markusfisch.android.binaryeye.widget.CropImageView
|
||||
import de.markusfisch.android.binaryeye.widget.toast
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class PickActivity : AppCompatActivity() {
|
||||
private val zxing = Zxing()
|
||||
@@ -68,6 +72,7 @@ class PickActivity : AppCompatActivity() {
|
||||
return
|
||||
}
|
||||
|
||||
var result: Result? = null
|
||||
val scannedRect = Rect()
|
||||
fun scanWithinBounds() = crop(
|
||||
bitmap,
|
||||
@@ -75,31 +80,38 @@ class PickActivity : AppCompatActivity() {
|
||||
cropImageView.imageRotation
|
||||
)?.let {
|
||||
scannedRect.set(0, 0, it.width, it.height)
|
||||
zxing.decodePositiveNegative(it)
|
||||
CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
|
||||
result = zxing.decodePositiveNegative(it)
|
||||
result?.let {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!isFinishing) {
|
||||
vibrator.vibrate()
|
||||
}
|
||||
cropImageView.updateResultPoints(
|
||||
mapResult(
|
||||
scannedRect.width(),
|
||||
scannedRect.height(),
|
||||
0,
|
||||
cropImageView.getBoundsRect(),
|
||||
it
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cropImageView = findViewById(R.id.image) as CropImageView
|
||||
cropImageView.setImageBitmap(bitmap)
|
||||
cropImageView.onScan = {
|
||||
scanWithinBounds()?.let {
|
||||
if (!isFinishing) {
|
||||
vibrator.vibrate()
|
||||
}
|
||||
mapResult(
|
||||
scannedRect.width(),
|
||||
scannedRect.height(),
|
||||
0,
|
||||
cropImageView.getBoundsRect(),
|
||||
it
|
||||
)
|
||||
}
|
||||
scanWithinBounds()
|
||||
}
|
||||
cropImageView.doOnApplyWindowInsets { v, insets ->
|
||||
(v as CropImageView).windowInsets.set(insets)
|
||||
}
|
||||
|
||||
findViewById(R.id.scan).setOnClickListener {
|
||||
scanImage(scanWithinBounds())
|
||||
scanImage(result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ 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
|
||||
import de.markusfisch.android.binaryeye.database.Database
|
||||
|
||||
class ScansAdapter(context: Context, cursor: Cursor) :
|
||||
CursorAdapter(context, cursor, false) {
|
||||
|
||||
@@ -2,7 +2,7 @@ package de.markusfisch.android.binaryeye.app
|
||||
|
||||
import android.app.Application
|
||||
import android.support.v8.renderscript.RenderScript
|
||||
import de.markusfisch.android.binaryeye.data.Database
|
||||
import de.markusfisch.android.binaryeye.database.Database
|
||||
import de.markusfisch.android.binaryeye.preference.Preferences
|
||||
|
||||
val db = Database()
|
||||
@@ -11,12 +11,11 @@ val prefs = Preferences()
|
||||
class BinaryEyeApp : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
db.open(this)
|
||||
prefs.init(this)
|
||||
|
||||
if (prefs.forceCompat) {
|
||||
RenderScript.forceCompat()
|
||||
}
|
||||
|
||||
db.open(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,41 +6,48 @@ import android.content.pm.PackageManager
|
||||
import android.support.v4.app.ActivityCompat
|
||||
import android.support.v4.content.ContextCompat
|
||||
|
||||
fun hasCameraPermission(activity: Activity, requestCode: Int = 1): Boolean {
|
||||
return hasPermission(activity, Manifest.permission.CAMERA, requestCode)
|
||||
const val PERMISSION_CAMERA = 1
|
||||
fun hasCameraPermission(activity: Activity): Boolean {
|
||||
return hasPermission(
|
||||
activity,
|
||||
Manifest.permission.CAMERA,
|
||||
PERMISSION_CAMERA
|
||||
)
|
||||
}
|
||||
|
||||
fun hasWritePermission(activity: Activity, requestCode: Int = 2): Boolean {
|
||||
const val PERMISSION_WRITE = 2
|
||||
fun hasWritePermission(activity: Activity): Boolean {
|
||||
return hasPermission(
|
||||
activity,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
requestCode
|
||||
PERMISSION_WRITE
|
||||
)
|
||||
}
|
||||
|
||||
fun hasLocationPermission(activity: Activity, requestCode: Int = 3): Boolean {
|
||||
const val PERMISSION_LOCATION = 3
|
||||
fun hasLocationPermission(activity: Activity): Boolean {
|
||||
return hasPermission(
|
||||
activity,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
requestCode
|
||||
PERMISSION_LOCATION
|
||||
)
|
||||
}
|
||||
|
||||
fun hasPermission(
|
||||
private fun hasPermission(
|
||||
activity: Activity,
|
||||
permission: String,
|
||||
requestCode: Int
|
||||
): Boolean {
|
||||
return if (ContextCompat.checkSelfPermission(activity, permission) !=
|
||||
PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
ActivityCompat.requestPermissions(
|
||||
activity,
|
||||
arrayOf(permission),
|
||||
requestCode
|
||||
)
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
) = if (ContextCompat.checkSelfPermission(
|
||||
activity,
|
||||
permission
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
ActivityCompat.requestPermissions(
|
||||
activity,
|
||||
arrayOf(permission),
|
||||
requestCode
|
||||
)
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -6,11 +6,14 @@ import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.AbsListView
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
val systemBarScrollListener = object : AbsListView.OnScrollListener {
|
||||
val systemBarListViewScrollListener = object : AbsListView.OnScrollListener {
|
||||
override fun onScroll(
|
||||
view: AbsListView,
|
||||
firstVisibleItem: Int,
|
||||
@@ -22,19 +25,25 @@ val systemBarScrollListener = object : AbsListView.OnScrollListener {
|
||||
view.post {
|
||||
val scrolled = firstVisibleItem > 0 ||
|
||||
(totalItemCount > 0 && firstChildScrolled(view))
|
||||
val scrollable = if (scrolled) {
|
||||
true
|
||||
} else {
|
||||
totalItemCount > 0 && lastChildOutOfView(view)
|
||||
}
|
||||
val scrollable = scrolled || totalItemCount > 0 && lastChildOutOfView(view)
|
||||
colorSystemAndToolBars(view.context, scrolled, scrollable)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(
|
||||
view: AbsListView,
|
||||
scrollState: Int
|
||||
) {
|
||||
override fun onScrollStateChanged(view: AbsListView, scrollState: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
val systemBarRecyclerViewScrollListener = object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||
val scrolled = layoutManager.findFirstCompletelyVisibleItemPosition() != 0
|
||||
val scrollable = scrolled || layoutManager.findLastVisibleItemPosition() <
|
||||
recyclerView.adapter.itemCount - 1
|
||||
colorSystemAndToolBars(recyclerView.context, scrolled, scrollable)
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +59,12 @@ private fun lastChildOutOfView(listView: AbsListView): Boolean {
|
||||
|
||||
fun initSystemBars(activity: AppCompatActivity) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
activity.window.decorView.systemUiVisibility =
|
||||
// keeps the soft keyboard from repositioning the layout
|
||||
val window = activity.window
|
||||
window.setSoftInputMode(
|
||||
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
|
||||
)
|
||||
window.decorView.systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.markusfisch.android.binaryeye.data
|
||||
package de.markusfisch.android.binaryeye.database
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.markusfisch.android.binaryeye.data
|
||||
package de.markusfisch.android.binaryeye.database
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
@@ -1,16 +1,12 @@
|
||||
package de.markusfisch.android.binaryeye.data
|
||||
package de.markusfisch.android.binaryeye.database
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Environment
|
||||
import de.markusfisch.android.binaryeye.app.hasWritePermission
|
||||
import de.markusfisch.android.binaryeye.app.writeExternalFile
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
|
||||
fun exportDatabase(activity: Activity, fileName: String): Boolean {
|
||||
if (!hasWritePermission(activity)) {
|
||||
return false
|
||||
}
|
||||
val dbFile = File(
|
||||
Environment.getDataDirectory(),
|
||||
"//data//${activity.packageName}//databases//${Database.FILE_NAME}"
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.markusfisch.android.binaryeye.data
|
||||
package de.markusfisch.android.binaryeye.database
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.markusfisch.android.binaryeye.data
|
||||
package de.markusfisch.android.binaryeye.database
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
@@ -19,7 +19,7 @@ data class Scan(
|
||||
val suggestedPrice: String?,
|
||||
val upcEanExtension: String?,
|
||||
val timestamp: String = getDateTime(),
|
||||
val id: Long = 0L
|
||||
var id: Long = 0L
|
||||
) : Parcelable {
|
||||
constructor(result: Result) : this(
|
||||
result.text,
|
||||
@@ -25,7 +25,12 @@ import java.io.OutputStream
|
||||
import java.util.*
|
||||
|
||||
class BarcodeFragment : Fragment() {
|
||||
private var barcode: Bitmap? = null
|
||||
private enum class FileType {
|
||||
PNG, SVG
|
||||
}
|
||||
|
||||
private var barcodeBitmap: Bitmap? = null
|
||||
private var barcodeSvg: String? = null
|
||||
private var content: String = ""
|
||||
private var format: BarcodeFormat? = null
|
||||
|
||||
@@ -53,7 +58,8 @@ class BarcodeFragment : Fragment() {
|
||||
val format = args.getSerializable(FORMAT) as BarcodeFormat? ?: return view
|
||||
val size = args.getInt(SIZE)
|
||||
try {
|
||||
barcode = Zxing.encodeAsBitmap(content, format, size, size)
|
||||
barcodeBitmap = Zxing.encodeAsBitmap(content, format, size, size)
|
||||
barcodeSvg = Zxing.encodeAsSvg(content, format, size, size)
|
||||
} catch (e: Exception) {
|
||||
var message = e.message
|
||||
if (message == null || message.isEmpty()) {
|
||||
@@ -71,14 +77,14 @@ class BarcodeFragment : Fragment() {
|
||||
val imageView = view.findViewById<ConfinedScalingImageView>(
|
||||
R.id.barcode
|
||||
)
|
||||
imageView.setImageBitmap(barcode)
|
||||
imageView.setImageBitmap(barcodeBitmap)
|
||||
imageView.post {
|
||||
// make sure to invoke this after ScalingImageView.onLayout()
|
||||
imageView.minWidth /= 2f
|
||||
}
|
||||
|
||||
view.findViewById<View>(R.id.share).setOnClickListener {
|
||||
val bitmap = barcode
|
||||
val bitmap = barcodeBitmap
|
||||
bitmap?.let {
|
||||
share(bitmap)
|
||||
}
|
||||
@@ -98,8 +104,12 @@ class BarcodeFragment : Fragment() {
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.save -> {
|
||||
askForFileNameAndSave()
|
||||
R.id.export_svg -> {
|
||||
askForFileNameAndSave(FileType.SVG)
|
||||
true
|
||||
}
|
||||
R.id.export_png -> {
|
||||
askForFileNameAndSave(FileType.PNG)
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
@@ -108,23 +118,33 @@ class BarcodeFragment : Fragment() {
|
||||
|
||||
// dialogs do not have a parent view
|
||||
@SuppressLint("InflateParams")
|
||||
private fun askForFileNameAndSave() {
|
||||
private fun askForFileNameAndSave(fileType: FileType) {
|
||||
val ac = activity ?: return
|
||||
if (!hasWritePermission(ac)) {
|
||||
return
|
||||
}
|
||||
val view = ac.layoutInflater.inflate(R.layout.dialog_save_file, null)
|
||||
val editText = view.findViewById<EditText>(R.id.file_name)
|
||||
editText.setText(encodeFileName("${format.toString()}_$content"))
|
||||
AlertDialog.Builder(ac)
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val bitmap = barcode
|
||||
bitmap?.let {
|
||||
saveAsFile(
|
||||
bitmap,
|
||||
addSuffixIfNotGiven(
|
||||
editText.text.toString(),
|
||||
".png"
|
||||
)
|
||||
)
|
||||
val fileName = editText.text.toString()
|
||||
when (fileType) {
|
||||
FileType.PNG -> saveAs(
|
||||
addSuffixIfNotGiven(fileName, ".png"),
|
||||
"image/png"
|
||||
) {
|
||||
barcodeBitmap?.saveAsPng(it)
|
||||
}
|
||||
FileType.SVG -> saveAs(
|
||||
addSuffixIfNotGiven(fileName, ".svg"),
|
||||
"image/svg+xmg"
|
||||
) { outputStream ->
|
||||
barcodeSvg?.let {
|
||||
outputStream.write(it.toByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
@@ -132,15 +152,14 @@ class BarcodeFragment : Fragment() {
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun saveAsFile(bitmap: Bitmap, fileName: String) {
|
||||
private fun saveAs(
|
||||
fileName: String,
|
||||
mimeType: String,
|
||||
write: (outputStream: OutputStream) -> Unit
|
||||
) {
|
||||
val ac = activity ?: return
|
||||
if (!hasWritePermission(ac)) {
|
||||
return
|
||||
}
|
||||
GlobalScope.launch {
|
||||
val message = writeExternalFile(ac, fileName, "image/png") {
|
||||
bitmap.saveAsPng(it)
|
||||
}.toSaveResult()
|
||||
val message = writeExternalFile(ac, fileName, mimeType, write).toSaveResult()
|
||||
GlobalScope.launch(Main) {
|
||||
ac.toast(message)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.actions.ActionRegistry
|
||||
import de.markusfisch.android.binaryeye.actions.wifi.WifiAction
|
||||
import de.markusfisch.android.binaryeye.app.*
|
||||
import de.markusfisch.android.binaryeye.data.Scan
|
||||
import de.markusfisch.android.binaryeye.database.Scan
|
||||
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
|
||||
import de.markusfisch.android.binaryeye.widget.toast
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -31,13 +31,14 @@ class DecodeFragment : Fragment() {
|
||||
private lateinit var format: String
|
||||
private lateinit var fab: FloatingActionButton
|
||||
|
||||
private var action = ActionRegistry.DEFAULT_ACTION
|
||||
private var isBinary = false
|
||||
private val parentJob = Job()
|
||||
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Main + parentJob)
|
||||
private val content: String
|
||||
get() = contentView.text.toString()
|
||||
|
||||
private val parentJob = Job()
|
||||
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Main + parentJob)
|
||||
private var action = ActionRegistry.DEFAULT_ACTION
|
||||
private var isBinary = false
|
||||
private var id = 0L
|
||||
|
||||
override fun onCreate(state: Bundle?) {
|
||||
super.onCreate(state)
|
||||
@@ -59,6 +60,7 @@ class DecodeFragment : Fragment() {
|
||||
|
||||
val scan = arguments?.getParcelable(SCAN) as Scan?
|
||||
?: throw IllegalArgumentException("DecodeFragment needs a Scan")
|
||||
id = scan.id
|
||||
|
||||
val inputContent = scan.content
|
||||
isBinary = hasNonPrintableCharacters(
|
||||
@@ -113,15 +115,6 @@ class DecodeFragment : Fragment() {
|
||||
hexView = view.findViewById(R.id.hex)
|
||||
|
||||
updateViewsAndAction(raw)
|
||||
if (action is WifiAction) {
|
||||
val password = (action as WifiAction).password
|
||||
if (password != null) {
|
||||
activity?.apply {
|
||||
copyToClipboard(password)
|
||||
toast(R.string.copied_password_to_clipboard)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prefs.showMetaData) {
|
||||
fillMetaView(metaView, scan)
|
||||
@@ -133,6 +126,11 @@ class DecodeFragment : Fragment() {
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
parentJob.cancel()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
private fun updateViewsAndAction(bytes: ByteArray) {
|
||||
val prevAction = action
|
||||
if (!prevAction.canExecuteOn(bytes)) {
|
||||
@@ -160,7 +158,7 @@ class DecodeFragment : Fragment() {
|
||||
|
||||
private fun fillMetaView(tableLayout: TableLayout, scan: Scan) {
|
||||
val ctx = tableLayout.context
|
||||
val spaceBetween = (ctx.resources.displayMetrics.density * 16f).toInt()
|
||||
val spaceBetween = (16f * ctx.resources.displayMetrics.density).toInt()
|
||||
var hasMeta = false
|
||||
sortedMapOf(
|
||||
R.string.error_correction_level to scan.errorCorrectionLevel,
|
||||
@@ -196,10 +194,20 @@ class DecodeFragment : Fragment() {
|
||||
menu.findItem(R.id.copy_to_clipboard).isVisible = false
|
||||
menu.findItem(R.id.create).isVisible = false
|
||||
}
|
||||
if (id > 0L) {
|
||||
menu.findItem(R.id.remove).isVisible = true
|
||||
}
|
||||
if (action is WifiAction) {
|
||||
menu.findItem(R.id.copy_password).isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.copy_password -> {
|
||||
copyPasswordToClipboard()
|
||||
true
|
||||
}
|
||||
R.id.copy_to_clipboard -> {
|
||||
copyToClipboard(content)
|
||||
true
|
||||
@@ -215,10 +223,27 @@ class DecodeFragment : Fragment() {
|
||||
)
|
||||
true
|
||||
}
|
||||
R.id.remove -> {
|
||||
db.removeScan(id)
|
||||
backOrFinish()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyPasswordToClipboard() {
|
||||
val ac = action
|
||||
if (ac is WifiAction) {
|
||||
ac.password?.let { password ->
|
||||
activity?.apply {
|
||||
copyToClipboard(password)
|
||||
toast(R.string.copied_password_to_clipboard)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyToClipboard(text: String) {
|
||||
activity?.apply {
|
||||
copyToClipboard(text)
|
||||
@@ -226,6 +251,15 @@ class DecodeFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun backOrFinish() {
|
||||
val fm = fragmentManager
|
||||
if (fm != null && fm.backStackEntryCount > 0) {
|
||||
fm.popBackStack()
|
||||
} else {
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeAction(content: ByteArray) {
|
||||
val ac = activity ?: return
|
||||
if (content.isNotEmpty()) {
|
||||
@@ -259,11 +293,6 @@ class DecodeFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
parentJob.cancel()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SCAN = "scan"
|
||||
|
||||
@@ -277,7 +306,7 @@ class DecodeFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
fun hexDump(bytes: ByteArray, charsPerLine: Int = 33): String {
|
||||
private fun hexDump(bytes: ByteArray, charsPerLine: Int = 33): String {
|
||||
if (charsPerLine < 4 || bytes.isEmpty()) {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package de.markusfisch.android.binaryeye.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.view.*
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
@@ -31,11 +33,6 @@ class EncodeFragment : Fragment() {
|
||||
BarcodeFormat.UPC_A
|
||||
)
|
||||
|
||||
override fun onCreate(state: Bundle?) {
|
||||
super.onCreate(state)
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -94,20 +91,6 @@ class EncodeFragment : Fragment() {
|
||||
prefs.indexOfLastSelectedFormat = formatView.selectedItemPosition
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.fragment_encode, menu)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.next -> {
|
||||
encode()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun encode() {
|
||||
val format = writers[formatView.selectedItemPosition]
|
||||
val size = getSize(sizeBarView.progress)
|
||||
|
||||
@@ -21,10 +21,10 @@ import android.widget.ListView
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.adapter.ScansAdapter
|
||||
import de.markusfisch.android.binaryeye.app.*
|
||||
import de.markusfisch.android.binaryeye.data.Database
|
||||
import de.markusfisch.android.binaryeye.data.exportCsv
|
||||
import de.markusfisch.android.binaryeye.data.exportDatabase
|
||||
import de.markusfisch.android.binaryeye.data.exportJson
|
||||
import de.markusfisch.android.binaryeye.database.Database
|
||||
import de.markusfisch.android.binaryeye.database.exportCsv
|
||||
import de.markusfisch.android.binaryeye.database.exportDatabase
|
||||
import de.markusfisch.android.binaryeye.database.exportJson
|
||||
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
|
||||
import de.markusfisch.android.binaryeye.view.useVisibility
|
||||
import de.markusfisch.android.binaryeye.widget.toast
|
||||
@@ -151,7 +151,7 @@ class HistoryFragment : Fragment() {
|
||||
}
|
||||
true
|
||||
}
|
||||
listView.setOnScrollListener(systemBarScrollListener)
|
||||
listView.setOnScrollListener(systemBarListViewScrollListener)
|
||||
|
||||
fab = view.findViewById(R.id.share)
|
||||
fab.setOnClickListener { v ->
|
||||
|
||||
@@ -1,114 +1,81 @@
|
||||
package de.markusfisch.android.binaryeye.fragment
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||
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 android.support.v7.preference.ListPreference
|
||||
import android.support.v7.preference.Preference
|
||||
import android.support.v7.preference.PreferenceFragmentCompat
|
||||
import android.support.v7.preference.PreferenceGroup
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.prefs
|
||||
import de.markusfisch.android.binaryeye.app.systemBarRecyclerViewScrollListener
|
||||
import de.markusfisch.android.binaryeye.preference.UrlPreference
|
||||
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
|
||||
|
||||
class PreferencesFragment : Fragment() {
|
||||
private lateinit var showCropHandleSwitch: SwitchCompat
|
||||
private lateinit var zoomBySwipingSwitch: SwitchCompat
|
||||
private lateinit var autoResizeSwitch: SwitchCompat
|
||||
private lateinit var tryHarderSwitch: SwitchCompat
|
||||
private lateinit var vibrateSwitch: SwitchCompat
|
||||
private lateinit var useHistorySwitch: SwitchCompat
|
||||
private lateinit var ignoreConsecutiveDuplicatesSwitch: SwitchCompat
|
||||
private lateinit var openImmediatelySwitch: SwitchCompat
|
||||
private lateinit var showMetaDataSwitch: SwitchCompat
|
||||
private lateinit var showHexDumpSwitch: 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
|
||||
)
|
||||
|
||||
showCropHandleSwitch = view.findViewById(R.id.show_crop_handle)
|
||||
if (prefs.showCropHandle) {
|
||||
showCropHandleSwitch.toggle()
|
||||
class PreferencesFragment : PreferenceFragmentCompat() {
|
||||
private val changeListener = object : OnSharedPreferenceChangeListener {
|
||||
override fun onSharedPreferenceChanged(
|
||||
sharedPreferences: SharedPreferences,
|
||||
key: String
|
||||
) {
|
||||
val preference = findPreference(key) ?: return
|
||||
prefs.update()
|
||||
setSummary(preference)
|
||||
}
|
||||
|
||||
zoomBySwipingSwitch = view.findViewById(R.id.zoom_by_swiping)
|
||||
if (prefs.zoomBySwiping) {
|
||||
zoomBySwipingSwitch.toggle()
|
||||
}
|
||||
|
||||
autoResizeSwitch = view.findViewById(R.id.auto_rotate)
|
||||
if (prefs.autoRotate) {
|
||||
autoResizeSwitch.toggle()
|
||||
}
|
||||
|
||||
tryHarderSwitch = view.findViewById(R.id.try_harder)
|
||||
if (prefs.tryHarder) {
|
||||
tryHarderSwitch.toggle()
|
||||
}
|
||||
|
||||
vibrateSwitch = view.findViewById(R.id.vibrate)
|
||||
if (prefs.vibrate) {
|
||||
vibrateSwitch.toggle()
|
||||
}
|
||||
|
||||
useHistorySwitch = view.findViewById(R.id.use_history)
|
||||
if (prefs.useHistory) {
|
||||
useHistorySwitch.toggle()
|
||||
}
|
||||
|
||||
ignoreConsecutiveDuplicatesSwitch = view.findViewById(
|
||||
R.id.ignore_consecutive_duplicates
|
||||
)
|
||||
if (prefs.ignoreConsecutiveDuplicates) {
|
||||
ignoreConsecutiveDuplicatesSwitch.toggle()
|
||||
}
|
||||
|
||||
openImmediatelySwitch = view.findViewById(R.id.open_immediately)
|
||||
if (prefs.openImmediately) {
|
||||
openImmediatelySwitch.toggle()
|
||||
}
|
||||
|
||||
showMetaDataSwitch = view.findViewById(R.id.show_meta_data)
|
||||
if (prefs.showMetaData) {
|
||||
showMetaDataSwitch.toggle()
|
||||
}
|
||||
|
||||
showHexDumpSwitch = view.findViewById(R.id.show_hex_dump)
|
||||
if (prefs.showHexDump) {
|
||||
showHexDumpSwitch.toggle()
|
||||
}
|
||||
|
||||
openWithUrlInput = view.findViewById(R.id.open_with_url)
|
||||
openWithUrlInput.setText(prefs.openWithUrl)
|
||||
|
||||
(view.findViewById(R.id.scroll_view) as View).setPaddingFromWindowInsets()
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
prefs.showCropHandle = showCropHandleSwitch.isChecked
|
||||
prefs.zoomBySwiping = zoomBySwipingSwitch.isChecked
|
||||
prefs.autoRotate = autoResizeSwitch.isChecked
|
||||
prefs.tryHarder = tryHarderSwitch.isChecked
|
||||
prefs.vibrate = vibrateSwitch.isChecked
|
||||
prefs.useHistory = useHistorySwitch.isChecked
|
||||
prefs.ignoreConsecutiveDuplicates = ignoreConsecutiveDuplicatesSwitch.isChecked
|
||||
prefs.openImmediately = openImmediatelySwitch.isChecked
|
||||
prefs.showMetaData = showMetaDataSwitch.isChecked
|
||||
prefs.showHexDump = showHexDumpSwitch.isChecked
|
||||
prefs.openWithUrl = openWithUrlInput.text.toString()
|
||||
override fun onCreatePreferences(state: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.preferences)
|
||||
activity?.setTitle(R.string.preferences)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
listView.setPaddingFromWindowInsets()
|
||||
listView.removeOnScrollListener(systemBarRecyclerViewScrollListener)
|
||||
listView.addOnScrollListener(systemBarRecyclerViewScrollListener)
|
||||
preferenceScreen.sharedPreferences
|
||||
.registerOnSharedPreferenceChangeListener(changeListener)
|
||||
setSummaries(preferenceScreen)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
preferenceScreen.sharedPreferences
|
||||
.unregisterOnSharedPreferenceChangeListener(changeListener)
|
||||
}
|
||||
|
||||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
if (preference is UrlPreference) {
|
||||
val fm = fragmentManager
|
||||
UrlDialogFragment.newInstance(preference.key).apply {
|
||||
setTargetFragment(this@PreferencesFragment, 0)
|
||||
show(fm, null)
|
||||
}
|
||||
} else {
|
||||
super.onDisplayPreferenceDialog(preference)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSummaries(screen: PreferenceGroup) {
|
||||
var i = screen.preferenceCount
|
||||
while (i-- > 0) {
|
||||
setSummary(screen.getPreference(i))
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSummary(preference: Preference) {
|
||||
when (preference) {
|
||||
is UrlPreference -> {
|
||||
preference.setSummary(preference.getUrl())
|
||||
}
|
||||
is ListPreference -> {
|
||||
preference.setSummary(preference.entry)
|
||||
}
|
||||
is PreferenceGroup -> {
|
||||
setSummaries(preference)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.markusfisch.android.binaryeye.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.preference.PreferenceDialogFragmentCompat
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.preference.UrlPreference
|
||||
|
||||
class UrlDialogFragment : PreferenceDialogFragmentCompat() {
|
||||
private var urlView: TextView? = null
|
||||
|
||||
override fun onBindDialogView(view: View?) {
|
||||
super.onBindDialogView(view)
|
||||
urlView = view?.findViewById(R.id.url)
|
||||
urlView?.text = urlPreference().getUrl()
|
||||
}
|
||||
|
||||
override fun onDialogClosed(positiveResult: Boolean) {
|
||||
if (positiveResult) {
|
||||
urlPreference().setUrl(urlView?.text.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun urlPreference() = preference as UrlPreference
|
||||
|
||||
companion object {
|
||||
fun newInstance(key: String): UrlDialogFragment {
|
||||
val args = Bundle()
|
||||
args.putString(ARG_KEY, key)
|
||||
val fragment = UrlDialogFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,7 @@ class Dots(context: Context) {
|
||||
private val radius = 8f * context.resources.displayMetrics.density
|
||||
|
||||
init {
|
||||
paint.color = ContextCompat.getColor(
|
||||
context,
|
||||
R.color.dot
|
||||
)
|
||||
paint.color = ContextCompat.getColor(context, R.color.dot)
|
||||
paint.style = Paint.Style.FILL
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package de.markusfisch.android.binaryeye.net
|
||||
|
||||
import android.content.Context
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
import de.markusfisch.android.binaryeye.app.toHexString
|
||||
import de.markusfisch.android.binaryeye.database.Scan
|
||||
import de.markusfisch.android.binaryeye.widget.toast
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.net.URLEncoder
|
||||
|
||||
fun Scan.sendAsync(context: Context, url: String, type: String) {
|
||||
CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
|
||||
val code = send(url, type)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (code < 200 || code > 299) {
|
||||
context.toast(R.string.background_request_failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Scan.send(url: String, type: String): Int {
|
||||
return when (type) {
|
||||
"1" -> request(
|
||||
url + "?" + asUrlArguments()
|
||||
)
|
||||
"2" -> request(url) { con ->
|
||||
con.requestMethod = "POST"
|
||||
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
|
||||
con.outputStream.apply {
|
||||
write(asUrlArguments().toByteArray())
|
||||
close()
|
||||
}
|
||||
}
|
||||
"3" -> request(url) { con ->
|
||||
con.requestMethod = "POST"
|
||||
con.setRequestProperty("Content-Type", "application/json")
|
||||
con.outputStream.apply {
|
||||
write(asJson().toString().toByteArray())
|
||||
close()
|
||||
}
|
||||
}
|
||||
else -> request(
|
||||
url + urlEncode(content)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Scan.asUrlArguments(): String = getMap().map { (k, v) ->
|
||||
"${k}=${urlEncode(v)}"
|
||||
}.joinToString("&")
|
||||
|
||||
private fun Scan.asJson() = JSONObject().apply {
|
||||
getMap().forEach { (k, v) -> put(k, v) }
|
||||
}
|
||||
|
||||
private fun urlEncode(s: String) = URLEncoder.encode(s, "utf-8")
|
||||
|
||||
private fun Scan.getMap(): Map<String, String> = mapOf(
|
||||
"content" to content,
|
||||
"raw" to raw?.toHexString(),
|
||||
"format" to format,
|
||||
"errorCorrectionLevel" to errorCorrectionLevel,
|
||||
"issueNumber" to issueNumber,
|
||||
"orientation" to orientation,
|
||||
"otherMetaData" to otherMetaData,
|
||||
"pdf417ExtraMetaData" to pdf417ExtraMetaData,
|
||||
"possibleCountry" to possibleCountry,
|
||||
"suggestedPrice" to suggestedPrice,
|
||||
"upcEanExtension" to upcEanExtension,
|
||||
"timestamp" to timestamp
|
||||
).filterNullValues()
|
||||
|
||||
private fun Map<String, String?>.filterNullValues() =
|
||||
filterValues { it != null }.mapValues { it.value as String }
|
||||
|
||||
private fun request(
|
||||
url: String,
|
||||
writer: ((HttpURLConnection) -> Any)? = null
|
||||
): Int {
|
||||
var con: HttpURLConnection? = null
|
||||
return try {
|
||||
con = URL(url).openConnection() as HttpURLConnection
|
||||
writer?.invoke(con)
|
||||
con.responseCode
|
||||
} catch (e: IOException) {
|
||||
-1
|
||||
} finally {
|
||||
con?.disconnect()
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,21 @@ import android.preference.PreferenceManager
|
||||
class Preferences {
|
||||
lateinit var preferences: SharedPreferences
|
||||
|
||||
var cropHandleX = -1
|
||||
set(value) {
|
||||
apply(CROP_HANDLE_X, value)
|
||||
field = value
|
||||
}
|
||||
var cropHandleY = -1
|
||||
set(value) {
|
||||
apply(CROP_HANDLE_Y, value)
|
||||
field = value
|
||||
}
|
||||
var cropHandleOrientation = 0
|
||||
set(value) {
|
||||
apply(CROP_HANDLE_ORIENTATION, value)
|
||||
field = value
|
||||
}
|
||||
var showCropHandle = true
|
||||
set(value) {
|
||||
apply(SHOW_CROP_HANDLE, value)
|
||||
@@ -46,6 +61,11 @@ class Preferences {
|
||||
apply(IGNORE_CONSECUTIVE_DUPLICATES, value)
|
||||
field = value
|
||||
}
|
||||
var copyImmediately = false
|
||||
set(value) {
|
||||
apply(COPY_IMMEDIATELY, value)
|
||||
field = value
|
||||
}
|
||||
var openImmediately = false
|
||||
set(value) {
|
||||
apply(OPEN_IMMEDIATELY, value)
|
||||
@@ -66,6 +86,16 @@ class Preferences {
|
||||
apply(OPEN_WITH_URL, value)
|
||||
field = value
|
||||
}
|
||||
var sendScanUrl: String = ""
|
||||
set(value) {
|
||||
apply(SEND_SCAN_URL, value)
|
||||
field = value
|
||||
}
|
||||
var sendScanType: String = "0"
|
||||
set(value) {
|
||||
apply(SEND_SCAN_TYPE, value)
|
||||
field = value
|
||||
}
|
||||
var indexOfLastSelectedFormat: Int = 0
|
||||
set(value) {
|
||||
apply(INDEX_OF_LAST_SELECTED_FORMAT, value)
|
||||
@@ -85,6 +115,12 @@ class Preferences {
|
||||
}
|
||||
|
||||
fun update() {
|
||||
cropHandleX = preferences.getInt(CROP_HANDLE_X, cropHandleX)
|
||||
cropHandleY = preferences.getInt(CROP_HANDLE_Y, cropHandleY)
|
||||
cropHandleOrientation = preferences.getInt(
|
||||
CROP_HANDLE_ORIENTATION,
|
||||
cropHandleOrientation
|
||||
)
|
||||
showCropHandle = preferences.getBoolean(SHOW_CROP_HANDLE, showCropHandle)
|
||||
zoomBySwiping = preferences.getBoolean(ZOOM_BY_SWIPING, zoomBySwiping)
|
||||
autoRotate = preferences.getBoolean(AUTO_ROTATE, autoRotate)
|
||||
@@ -95,6 +131,10 @@ class Preferences {
|
||||
IGNORE_CONSECUTIVE_DUPLICATES,
|
||||
ignoreConsecutiveDuplicates
|
||||
)
|
||||
copyImmediately = preferences.getBoolean(
|
||||
COPY_IMMEDIATELY,
|
||||
copyImmediately
|
||||
)
|
||||
openImmediately = preferences.getBoolean(
|
||||
OPEN_IMMEDIATELY,
|
||||
openImmediately
|
||||
@@ -104,6 +144,12 @@ class Preferences {
|
||||
preferences.getString(OPEN_WITH_URL, openWithUrl)?.also {
|
||||
openWithUrl = it
|
||||
}
|
||||
preferences.getString(SEND_SCAN_URL, sendScanUrl)?.also {
|
||||
sendScanUrl = it
|
||||
}
|
||||
preferences.getString(SEND_SCAN_TYPE, sendScanType)?.also {
|
||||
sendScanType = it
|
||||
}
|
||||
indexOfLastSelectedFormat = preferences.getInt(
|
||||
INDEX_OF_LAST_SELECTED_FORMAT,
|
||||
indexOfLastSelectedFormat
|
||||
@@ -131,6 +177,9 @@ class Preferences {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CROP_HANDLE_X = "crop_handle_x"
|
||||
const val CROP_HANDLE_Y = "crop_handle_y"
|
||||
const val CROP_HANDLE_ORIENTATION = "crop_handle_orientation"
|
||||
const val SHOW_CROP_HANDLE = "show_crop_handle"
|
||||
const val ZOOM_BY_SWIPING = "zoom_by_swiping"
|
||||
const val AUTO_ROTATE = "auto_rotate"
|
||||
@@ -139,9 +188,12 @@ class Preferences {
|
||||
const val USE_HISTORY = "use_history"
|
||||
const val IGNORE_CONSECUTIVE_DUPLICATES = "ignore_consecutive_duplicates"
|
||||
const val OPEN_IMMEDIATELY = "open_immediately"
|
||||
const val COPY_IMMEDIATELY = "copy_immediately"
|
||||
const val SHOW_HEX_DUMP = "show_hex_dump"
|
||||
const val SHOW_META_DATA = "show_meta_data"
|
||||
const val OPEN_WITH_URL = "open_with_url"
|
||||
const val SEND_SCAN_URL = "send_scan_url"
|
||||
const val SEND_SCAN_TYPE = "send_scan_type"
|
||||
const val INDEX_OF_LAST_SELECTED_FORMAT = "index_of_last_selected_format"
|
||||
const val FORCE_COMPAT = "force_compat"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package de.markusfisch.android.binaryeye.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.preference.DialogPreference
|
||||
import android.util.AttributeSet
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
class UrlPreference(
|
||||
context: Context?,
|
||||
attrs: AttributeSet?
|
||||
) : DialogPreference(context, attrs) {
|
||||
private var url: String? = null
|
||||
|
||||
init {
|
||||
dialogLayoutResource = R.layout.dialog_url
|
||||
}
|
||||
|
||||
fun getUrl() = url
|
||||
|
||||
fun setUrl(url: String) {
|
||||
this.url = url
|
||||
persistString(url)
|
||||
}
|
||||
|
||||
override fun onSetInitialValue(
|
||||
restorePersistedValue: Boolean,
|
||||
defaultValue: Any?
|
||||
) {
|
||||
setUrl(
|
||||
if (restorePersistedValue) {
|
||||
getPersistedString(url)
|
||||
} else {
|
||||
defaultValue as String
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package de.markusfisch.android.binaryeye.rs
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.support.v8.renderscript.*
|
||||
import de.markusfisch.android.binaryeye.renderscript.ScriptC_rotator
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
private const val SCALE_FACTOR = .75f
|
||||
@@ -19,7 +19,7 @@ class Preprocessor(
|
||||
|
||||
private val rs = RenderScript.create(context)
|
||||
private val resizeScript = ScriptIntrinsicResize.create(rs)
|
||||
private val rotatorScript = ScriptC_rotator(rs)
|
||||
private val rotateScript = ScriptC_rotate(rs)
|
||||
|
||||
private var yuvType: Type? = null
|
||||
private var yuvAlloc: Allocation? = null
|
||||
@@ -65,6 +65,10 @@ class Preprocessor(
|
||||
// make sure the dimensions are always a multiple of 4
|
||||
outWidth -= outWidth % 4
|
||||
outHeight -= outHeight % 4
|
||||
|
||||
// make sure the dimensions are always greater than 4
|
||||
outWidth = max(4, outWidth)
|
||||
outHeight = max(4, outHeight)
|
||||
} else {
|
||||
outWidth = (width * SCALE_FACTOR).roundToInt()
|
||||
outHeight = (height * SCALE_FACTOR).roundToInt()
|
||||
@@ -113,7 +117,7 @@ class Preprocessor(
|
||||
rotatedAlloc?.destroy()
|
||||
rotatedAlloc = null
|
||||
resizeScript.destroy()
|
||||
rotatorScript.destroy()
|
||||
rotateScript.destroy()
|
||||
rs.destroy()
|
||||
}
|
||||
|
||||
@@ -125,10 +129,10 @@ class Preprocessor(
|
||||
fun resizeAndRotate(frame: ByteArray) {
|
||||
resize(frame)
|
||||
val t = resizedType ?: return
|
||||
rotatorScript._inImage = resizedAlloc
|
||||
rotatorScript._inWidth = t.x
|
||||
rotatorScript._inHeight = t.y
|
||||
rotatorScript.forEach_rotate90(
|
||||
rotateScript._inImage = resizedAlloc
|
||||
rotateScript._inWidth = t.x
|
||||
rotateScript._inHeight = t.y
|
||||
rotateScript.forEach_rotate90(
|
||||
rotatedAlloc, // ignored in kernel, just to satisfy forEach
|
||||
rotatedAlloc
|
||||
)
|
||||
@@ -143,7 +147,7 @@ class Preprocessor(
|
||||
0, 0,
|
||||
roi.width(), roi.height(),
|
||||
yuvAlloc,
|
||||
roi.left, roi.top
|
||||
max(0, roi.left), max(0, roi.top)
|
||||
)
|
||||
roiAlloc
|
||||
} else {
|
||||
|
||||
@@ -14,18 +14,13 @@ class CropImageView(context: Context, attr: AttributeSet) :
|
||||
ConfinedScalingImageView(context, attr) {
|
||||
val windowInsets = Rect()
|
||||
|
||||
var onScan: (() -> List<Point>?)? = null
|
||||
var onScan: (() -> Unit)? = null
|
||||
|
||||
private val dots = Dots(context)
|
||||
private val boundsPaint = context.getDashedBorderPaint()
|
||||
private val lastMappedRect = RectF()
|
||||
private val padding: Int = (24f * context.resources.displayMetrics.density).roundToInt()
|
||||
private val onScanRunnable = Runnable {
|
||||
onScan?.invoke()?.let {
|
||||
resultPoints = it
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
private val onScanRunnable = Runnable { onScan?.invoke() }
|
||||
|
||||
private var resultPoints: List<Point>? = null
|
||||
|
||||
@@ -33,6 +28,11 @@ class CropImageView(context: Context, attr: AttributeSet) :
|
||||
scaleType = ScaleType.CENTER_CROP
|
||||
}
|
||||
|
||||
fun updateResultPoints(points: List<Point>) {
|
||||
resultPoints = points
|
||||
invalidate()
|
||||
}
|
||||
|
||||
override fun onLayout(
|
||||
changed: Boolean,
|
||||
left: Int,
|
||||
|
||||
@@ -15,13 +15,16 @@ import de.markusfisch.android.binaryeye.graphics.Dots
|
||||
import de.markusfisch.android.binaryeye.graphics.getBitmapFromDrawable
|
||||
import de.markusfisch.android.binaryeye.graphics.getDashedBorderPaint
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class DetectorView : View {
|
||||
val currentOrientation = resources.configuration.orientation
|
||||
val roi = Rect()
|
||||
|
||||
var updateRoi: (() -> Unit)? = null
|
||||
var onRoiChange: (() -> Unit)? = null
|
||||
var onRoiChanged: (() -> Unit)? = null
|
||||
|
||||
private val dots = Dots(context)
|
||||
private val invalidateRunnable: Runnable = Runnable {
|
||||
@@ -34,8 +37,8 @@ class DetectorView : View {
|
||||
)
|
||||
private val handleXRadius = handleBitmap.width / 2
|
||||
private val handleYRadius = handleBitmap.height / 2
|
||||
private val handleHome = Point()
|
||||
private val handlePos = Point(-1, -1)
|
||||
private val handleHome = Point()
|
||||
private val center = Point()
|
||||
private val touchDown = Point()
|
||||
private val distToFull: Int
|
||||
@@ -45,9 +48,11 @@ class DetectorView : View {
|
||||
private val padding: Int
|
||||
|
||||
private var marks: List<Point>? = null
|
||||
private var orientation = resources.configuration.orientation
|
||||
private var handleGrabbed = false
|
||||
private var handleMoved = false
|
||||
private var handleActive = false
|
||||
private var minY = 0
|
||||
private var maxY = 0
|
||||
private var minDist = 0
|
||||
private var shadeColor = 0
|
||||
|
||||
init {
|
||||
@@ -67,6 +72,23 @@ class DetectorView : View {
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) :
|
||||
super(context, attrs, defStyleAttr)
|
||||
|
||||
fun setCropHandlePos(x: Int, y: Int, orientation: Int) {
|
||||
if (orientation == currentOrientation) {
|
||||
handlePos.set(x, y)
|
||||
} else {
|
||||
handlePos.set(y, x)
|
||||
}
|
||||
if (x > -1) {
|
||||
handleActive = true
|
||||
}
|
||||
}
|
||||
|
||||
fun getCropHandlePos() = if (handleActive) {
|
||||
handlePos
|
||||
} else {
|
||||
Point(-1, -1)
|
||||
}
|
||||
|
||||
fun mark(points: List<Point>) {
|
||||
marks = points
|
||||
invalidate()
|
||||
@@ -75,27 +97,23 @@ class DetectorView : View {
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(): Parcelable? {
|
||||
if (!handleMoved) {
|
||||
if (!handleActive) {
|
||||
return super.onSaveInstanceState()
|
||||
}
|
||||
return SavedState(super.onSaveInstanceState()).apply {
|
||||
savedHandlePos.set(handlePos)
|
||||
savedOrientation = orientation
|
||||
savedHandlePos.set(getCropHandlePos())
|
||||
savedOrientation = currentOrientation
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(state: Parcelable) {
|
||||
super.onRestoreInstanceState(
|
||||
if (state is SavedState) {
|
||||
if (state.savedOrientation == orientation) {
|
||||
handlePos.set(state.savedHandlePos)
|
||||
} else {
|
||||
handlePos.set(
|
||||
state.savedHandlePos.y,
|
||||
state.savedHandlePos.x
|
||||
)
|
||||
}
|
||||
handleMoved = true
|
||||
setCropHandlePos(
|
||||
state.savedHandlePos.x,
|
||||
state.savedHandlePos.y,
|
||||
state.savedOrientation
|
||||
)
|
||||
state.superState
|
||||
} else {
|
||||
state
|
||||
@@ -114,6 +132,9 @@ class DetectorView : View {
|
||||
touchDown.set(x, y)
|
||||
handleGrabbed = abs(x - handlePos.x) < handleXRadius &&
|
||||
abs(y - handlePos.y) < handleYRadius
|
||||
if (handleGrabbed) {
|
||||
onRoiChange?.invoke()
|
||||
}
|
||||
handleGrabbed
|
||||
} else {
|
||||
false
|
||||
@@ -123,8 +144,9 @@ class DetectorView : View {
|
||||
if (handleGrabbed) {
|
||||
handlePos.set(x, y)
|
||||
if (distSq(handlePos, touchDown) > minMoveThresholdSq) {
|
||||
handleMoved = true
|
||||
handleActive = true
|
||||
}
|
||||
updateClipRect()
|
||||
invalidate()
|
||||
true
|
||||
} else {
|
||||
@@ -140,17 +162,19 @@ class DetectorView : View {
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
if (handleGrabbed) {
|
||||
if (!handleMoved) {
|
||||
if (!handleActive) {
|
||||
val mn = min(center.x, center.y) * .8f
|
||||
handlePos.set(
|
||||
(center.x * 1.5f).roundToInt(),
|
||||
(center.y * 1.25f).roundToInt()
|
||||
(center.x + mn).roundToInt(),
|
||||
(center.y + mn).roundToInt()
|
||||
)
|
||||
handleMoved = true
|
||||
handleActive = true
|
||||
invalidate()
|
||||
} else {
|
||||
snap(x, y)
|
||||
}
|
||||
updateRoi?.invoke()
|
||||
updateClipRect()
|
||||
onRoiChanged?.invoke()
|
||||
handleGrabbed = false
|
||||
}
|
||||
false
|
||||
@@ -160,15 +184,28 @@ class DetectorView : View {
|
||||
}
|
||||
|
||||
private fun snap(x: Int, y: Int) {
|
||||
if (abs(x - center.x) < distToFull ||
|
||||
abs(y - center.y) < distToFull
|
||||
val cx = clampX(x)
|
||||
val cy = clampY(y)
|
||||
val dx = abs(cx - center.x)
|
||||
val dy = abs(cy - center.y)
|
||||
// check if handle is close to the vertical or horizontal center line
|
||||
if (dx < distToFull ||
|
||||
dy < distToFull ||
|
||||
// check if handle is close to a screen corner
|
||||
((abs(cy - minY) < distToFull || abs(maxY - cy) < distToFull) &&
|
||||
abs(dx - center.x) < distToFull)
|
||||
) {
|
||||
handlePos.set(handleHome)
|
||||
handleMoved = false
|
||||
reset()
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
private fun reset() {
|
||||
handlePos.set(handleHome)
|
||||
handleActive = false
|
||||
roi.set(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
val width = right - left
|
||||
@@ -177,18 +214,22 @@ class DetectorView : View {
|
||||
left + (width / 2),
|
||||
top + (height / 2)
|
||||
)
|
||||
minY = padding * 2
|
||||
maxY = height - minY
|
||||
handleHome.set(
|
||||
width - handleXRadius - paddingRight - padding,
|
||||
height - handleYRadius - paddingBottom - fabHeight
|
||||
)
|
||||
if (handlePos.x < 0) {
|
||||
handlePos.set(handleHome)
|
||||
if (handleActive) {
|
||||
updateClipRect()
|
||||
} else {
|
||||
reset()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
canvas.drawColor(0, PorterDuff.Mode.CLEAR)
|
||||
if (handleMoved) {
|
||||
if (handleActive) {
|
||||
drawClip(canvas)
|
||||
}
|
||||
marks?.let {
|
||||
@@ -205,7 +246,6 @@ class DetectorView : View {
|
||||
}
|
||||
|
||||
private fun drawClip(canvas: Canvas) {
|
||||
val minDist = updateClipRect()
|
||||
if (minDist < 1) {
|
||||
return
|
||||
}
|
||||
@@ -230,13 +270,14 @@ class DetectorView : View {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateClipRect(): Int {
|
||||
private fun updateClipRect() {
|
||||
clampHandlePos()
|
||||
val dx = abs(handlePos.x - center.x)
|
||||
val dy = abs(handlePos.y - center.y)
|
||||
val d = min(dx, dy)
|
||||
minDist = min(dx, dy)
|
||||
shadeColor = (min(
|
||||
1f,
|
||||
d.toFloat() / distToFull.toFloat()
|
||||
minDist.toFloat() / distToFull.toFloat()
|
||||
) * 128f).toInt() shl 24
|
||||
roi.set(
|
||||
center.x - dx,
|
||||
@@ -244,9 +285,17 @@ class DetectorView : View {
|
||||
center.x + dx,
|
||||
center.y + dy
|
||||
)
|
||||
return d
|
||||
}
|
||||
|
||||
private fun clampHandlePos() {
|
||||
handlePos.x = clampX(handlePos.x)
|
||||
handlePos.y = clampY(handlePos.y)
|
||||
}
|
||||
|
||||
private fun clampX(x: Int) = min(center.x * 2, max(0, x))
|
||||
|
||||
private fun clampY(y: Int) = min(maxY, max(minY, y))
|
||||
|
||||
internal class SavedState : BaseSavedState {
|
||||
val savedHandlePos = Point()
|
||||
|
||||
|
||||
@@ -156,5 +156,42 @@ class Zxing(possibleResultPoint: ResultPointCallback? = null) {
|
||||
bitmap.setPixels(pixels, 0, w, 0, 0, w, h)
|
||||
return bitmap
|
||||
}
|
||||
|
||||
fun encodeAsSvg(
|
||||
text: String,
|
||||
format: BarcodeFormat,
|
||||
width: Int,
|
||||
height: Int
|
||||
): String {
|
||||
val hints = EnumMap<EncodeHintType, Any>(EncodeHintType::class.java)
|
||||
hints[EncodeHintType.CHARACTER_SET] = "utf-8"
|
||||
val result = MultiFormatWriter().encode(
|
||||
text,
|
||||
format,
|
||||
0,
|
||||
0,
|
||||
hints
|
||||
)
|
||||
val sb = StringBuilder()
|
||||
sb.append("<svg width=\"$width\" height=\"$height\"")
|
||||
sb.append(" viewBox=\"0 0 $width $height\"")
|
||||
sb.append(" xmlns=\"http://www.w3.org/2000/svg\">\n")
|
||||
val w = result.width
|
||||
val h = result.height
|
||||
val xf = width.toFloat() / w
|
||||
val yf = height.toFloat() / h
|
||||
for (y in 0 until h) {
|
||||
for (x in 0 until w) {
|
||||
if (result.get(x, y)) {
|
||||
val ox = x * xf
|
||||
val oy = y * yf
|
||||
sb.append("<rect x=\"$ox\" y=\"$oy\"")
|
||||
sb.append(" width=\"$xf\" height=\"$yf\"/>\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append("</svg>\n")
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="56dp"
|
||||
android:height="56dp"
|
||||
android:viewportWidth="56"
|
||||
android:viewportHeight="56">
|
||||
<path
|
||||
android:pathData="M28,32m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:gradientRadius="24"
|
||||
android:centerX="28"
|
||||
android:centerY="32"
|
||||
android:type="radial">
|
||||
<item android:offset="0" android:color="#FF000000"/>
|
||||
<item android:offset="1" android:color="#00000000"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M28,28m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"
|
||||
android:fillColor="#B6D46F"/>
|
||||
<path
|
||||
android:pathData="M33,31L35,31L35,23C35,21.9 34.1,21 33,21L25,21L25,23L33,23L33,31ZM23,33L23,17L21,17L21,21L17,21L17,23L21,23L21,33C21,34.1 21.9,35 23,35L33,35L33,39L35,39L35,35L39,35L39,33L23,33Z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="56dp" android:height="56dp" android:viewportWidth="56" android:viewportHeight="56">
|
||||
<path android:pathData="M4 32a24 24 0 1 1 48 0 24 24 0 1 1-48 0">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient android:gradientRadius="24" android:centerX="28" android:centerY="32" android:type="radial">
|
||||
<item android:offset="0" android:color="#FF000000"/>
|
||||
<item android:offset="1" android:color="#00000000"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path android:pathData="M4 28a24 24 0 1 1 48 0 24 24 0 1 1-48 0" android:fillColor="#B6D46F"/>
|
||||
<path android:pathData="M33 31h2v-8c0-1.1-0.9-2-2-2h-8v2h8v8zm-10 2V17h-2v4h-4v2h4v10c0 1.1 0.9 2 2 2h10v4h2v-4h4v-2H23z" android:fillColor="#FFFFFF"/>
|
||||
</vector>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M14 10H2v2h12v-2zm0-4H2v2h12V6zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2 16h8v-2H2v2z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<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="@android:color/white" android:pathData="M12.65 10C11.83 7.67 9.61 6 7 6c-3.31 0-6 2.69-6 6s2.69 6 6 6c2.61 0 4.83-1.67 5.65-4H17v4h4v-4h2v-4H12.65zM7 14c-1.1 0-2-0.9-2-2s0.9-2 2-2 2 0.9 2 2-0.9 2-2 2z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:fillColor="#FFFFFFFF" android:pathData="M4.413 15.067h-0.88v1.93h-1.37v-5.69h2.27c0.433 0 0.817 0.08 1.15 0.24 0.34 0.16 0.6 0.39 0.78 0.69 0.187 0.293 0.28 0.627 0.28 1 0 0.553-0.2 0.997-0.6 1.33-0.4 0.333-0.943 0.5-1.63 0.5zm-0.88-2.7v1.64h0.9c0.267 0 0.47-0.067 0.61-0.2s0.21-0.32 0.21-0.56c0-0.267-0.073-0.48-0.22-0.64-0.14-0.16-0.337-0.24-0.59-0.24h-0.91zm8.587-1.06v5.69h-1.36l-2.02-3.54v3.54H7.37v-5.69h1.37l2.01 3.54v-3.54h1.37zm5.527 2.65v2.34c-0.213 0.233-0.523 0.42-0.93 0.56-0.407 0.147-0.853 0.22-1.34 0.22-0.74 0-1.333-0.23-1.78-0.69-0.447-0.453-0.687-1.087-0.72-1.9v-0.49c0-0.56 0.1-1.05 0.3-1.47 0.193-0.413 0.477-0.733 0.85-0.96 0.367-0.227 0.793-0.34 1.28-0.34 0.707 0 1.257 0.163 1.65 0.49 0.387 0.32 0.613 0.803 0.68 1.45h-1.32c-0.047-0.32-0.147-0.547-0.3-0.68-0.16-0.133-0.383-0.2-0.67-0.2-0.34 0-0.603 0.143-0.79 0.43-0.193 0.293-0.29 0.71-0.29 1.25v0.35c0 0.567 0.097 0.993 0.29 1.28 0.193 0.28 0.5 0.42 0.92 0.42 0.353 0 0.617-0.077 0.79-0.23v-0.89h-0.95v-0.94h2.33zm4.733-6.991L18.481 6.96l1.463 1.464-2.065 2.066 0.975 0.975L20.921 9.4l1.463 1.464-0.005-3.898z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:fillColor="#FFFFFFFF" android:pathData="M5.45 15.487c0-0.2-0.07-0.357-0.21-0.47-0.14-0.113-0.39-0.23-0.75-0.35-0.353-0.12-0.643-0.237-0.87-0.35-0.74-0.36-1.11-0.857-1.11-1.49 0-0.313 0.093-0.59 0.28-0.83 0.18-0.24 0.44-0.427 0.78-0.56 0.333-0.14 0.71-0.21 1.13-0.21 0.407 0 0.773 0.073 1.1 0.22 0.327 0.147 0.577 0.357 0.75 0.63 0.18 0.267 0.27 0.573 0.27 0.92H5.46c0-0.233-0.073-0.413-0.22-0.54-0.14-0.127-0.33-0.19-0.57-0.19-0.247 0-0.44 0.053-0.58 0.16-0.14 0.107-0.21 0.243-0.21 0.41 0 0.147 0.077 0.28 0.23 0.4 0.153 0.12 0.427 0.243 0.82 0.37 0.393 0.127 0.717 0.263 0.97 0.41 0.613 0.353 0.92 0.84 0.92 1.46 0 0.5-0.187 0.89-0.56 1.17-0.373 0.287-0.887 0.43-1.54 0.43-0.46 0-0.877-0.083-1.25-0.25-0.373-0.167-0.657-0.393-0.85-0.68-0.187-0.287-0.28-0.617-0.28-0.99h1.38c0 0.3 0.077 0.523 0.23 0.67 0.16 0.147 0.417 0.22 0.77 0.22 0.227 0 0.407-0.05 0.54-0.15 0.127-0.1 0.19-0.237 0.19-0.41zm3.158-4.18l1.13 4.14 1.13-4.14h1.53l-1.91 5.69h-1.5l-1.9-5.69h1.52zm8.814 2.65v2.34c-0.213 0.233-0.523 0.42-0.93 0.56-0.407 0.147-0.853 0.22-1.34 0.22-0.74 0-1.333-0.23-1.78-0.69-0.447-0.453-0.687-1.087-0.72-1.9v-0.49c0-0.56 0.1-1.05 0.3-1.47 0.193-0.413 0.477-0.733 0.85-0.96 0.367-0.227 0.793-0.34 1.28-0.34 0.707 0 1.257 0.163 1.65 0.49 0.387 0.32 0.613 0.803 0.68 1.45h-1.32c-0.047-0.32-0.147-0.547-0.3-0.68-0.16-0.133-0.383-0.2-0.67-0.2-0.34 0-0.603 0.143-0.79 0.43-0.193 0.293-0.29 0.71-0.29 1.25v0.35c0 0.567 0.097 0.993 0.29 1.28 0.193 0.28 0.5 0.42 0.92 0.42 0.353 0 0.617-0.077 0.79-0.23v-0.89h-0.95v-0.94h2.33zm4.164-7.051L17.69 6.9l1.463 1.464-2.065 2.066 0.975 0.975 2.065-2.066 1.464 1.464-0.005-3.898z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,16 @@
|
||||
<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"
|
||||
android:padding="16dp">
|
||||
<EditText
|
||||
tools:targetApi="o"
|
||||
android:id="@+id/url"
|
||||
android:inputType="textUri"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/url_hint"
|
||||
android:importantForAutofill="no"/>
|
||||
</LinearLayout>
|
||||
@@ -1,90 +0,0 @@
|
||||
<de.markusfisch.android.binaryeye.widget.ConfinedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/scroll_view"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
android:orientation="vertical">
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/show_crop_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/show_crop_handle"/>
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/zoom_by_swiping"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/zoom_by_swiping"/>
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/auto_rotate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/auto_rotate"/>
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/try_harder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/try_harder"/>
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/vibrate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/vibrate"/>
|
||||
<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"/>
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/ignore_consecutive_duplicates"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/ignore_consecutive_duplicates"/>
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/open_immediately"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/open_immediately"/>
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/show_meta_data"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/show_meta_data"/>
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/show_hex_dump"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/show_hex_dump"/>
|
||||
<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>
|
||||
</de.markusfisch.android.binaryeye.widget.ConfinedScrollView>
|
||||
@@ -21,6 +21,12 @@
|
||||
android:title="@string/switch_camera"
|
||||
android:icon="@drawable/ic_action_switch_camera"
|
||||
material:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/bulk_mode"
|
||||
android:title="@string/bulk_mode"
|
||||
android:icon="@drawable/ic_action_bulk_mode"
|
||||
android:checkable="true"
|
||||
material:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/preferences"
|
||||
android:title="@string/preferences"
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:material="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/save"
|
||||
android:title="@string/export_to_file"
|
||||
android:icon="@drawable/ic_action_save"
|
||||
android:id="@+id/export_svg"
|
||||
android:title="@string/export_svg"
|
||||
android:icon="@drawable/ic_action_save_svg"
|
||||
material:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/export_png"
|
||||
android:title="@string/export_png"
|
||||
android:icon="@drawable/ic_action_save_png"
|
||||
material:showAsAction="ifRoom"/>
|
||||
</menu>
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:material="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/remove"
|
||||
android:title="@string/remove_scan"
|
||||
android:icon="@drawable/ic_action_remove"
|
||||
android:visible="false"
|
||||
material:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/copy_password"
|
||||
android:title="@string/copy_password"
|
||||
android:icon="@drawable/ic_action_copy_password"
|
||||
android:visible="false"
|
||||
material:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/copy_to_clipboard"
|
||||
android:title="@string/copy_to_clipboard"
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:material="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/next"
|
||||
android:title="@string/encode"
|
||||
android:icon="@drawable/ic_action_next"
|
||||
material:showAsAction="ifRoom"/>
|
||||
</menu>
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="share">Teilen</string>
|
||||
<string name="copy_to_clipboard">In die Zwischenablage kopieren</string>
|
||||
<string name="copied_to_clipboard">Inhalt wurde in die Zwischenablage kopiert</string>
|
||||
<string name="copy_password">Passwort in die Zwischenablage kopieren</string>
|
||||
<string name="copied_password_to_clipboard">Passwort wurde in die Zwischenablage kopiert</string>
|
||||
<string name="open_url">URL öffnen</string>
|
||||
<string name="cannot_resolve_action">Keine App kann das öffnen</string>
|
||||
@@ -36,19 +37,41 @@
|
||||
<string name="view_barcode">Barcode ansehen</string>
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Kamera wechseln</string>
|
||||
<string name="bulk_mode">Fortlaufend Scannen</string>
|
||||
<string name="history">Gespeicherte Codes</string>
|
||||
<string name="preferences">Einstellungen</string>
|
||||
<string name="show_crop_handle">Bereich verkleinern anzeigen</string>
|
||||
<string name="zoom_by_swiping">Hoch/Runter streichen um zu zoomen</string>
|
||||
<string name="auto_rotate">Vertikale Erkennung von 1D Barcodes</string>
|
||||
<string name="try_harder">Suche länger und gründlicher nach Barcodes</string>
|
||||
<string name="scan_category">Scannen</string>
|
||||
<string name="content_category">Inhalt</string>
|
||||
<string name="show_crop_handle">Ausschnitt verkleinern anzeigen</string>
|
||||
<string name="show_crop_handle_summary">Scannen auf einen anpassbaren Bereich einschränken.</string>
|
||||
<string name="zoom_by_swiping">Geste für Kamerazoom</string>
|
||||
<string name="zoom_by_swiping_summary">Im Kamerabildschirm nach oben oder unten streichen, um den Kamerazoom zu steuern.</string>
|
||||
<string name="auto_rotate">Vertikale Erkennung</string>
|
||||
<string name="auto_rotate_summary">Das Kamerabild automatisch drehen um vertikale 1D Barcodes zu erkennen. Je nach Gerät kann dies die Leistung beeinträchtigen.</string>
|
||||
<string name="try_harder">Gründliche Suche</string>
|
||||
<string name="try_harder_summary">Aktivieren Sie diese Option für sehr schwer lesbare Codes. Beeinträchtigt die Leistung.</string>
|
||||
<string name="vibrate">Bei Erkennung vibrieren</string>
|
||||
<string name="vibrate_summary">Das Gerät soll vibrieren wenn ein Code erkannt wird.</string>
|
||||
<string name="use_history">Codes speichern</string>
|
||||
<string name="ignore_consecutive_duplicates">Keine aufeinanderfolgenden Duplikate speichern</string>
|
||||
<string name="open_immediately">Inspektion überspringen und Inhalte sofort öffnen</string>
|
||||
<string name="use_history_summary">Eingelesene Barcodes auf dem Gerät speichern.</string>
|
||||
<string name="ignore_consecutive_duplicates">Duplikate ignorieren</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Aufeinanderfolgende Duplikate werden nicht in der Scan-Historie gespeichert.</string>
|
||||
<string name="open_immediately">Inhalte sofort öffnen</string>
|
||||
<string name="open_immediately_summary">Inspektion überspringen und Inhalt sofort öffnen. Kann schädliche Inhalte öffnen, wenn aktiviert.</string>
|
||||
<string name="copy_immediately">Automatisch in Zwischenablage</string>
|
||||
<string name="copy_immediately_summary">Eingelesene Inhalte werden automatisch in die Zwischenablage kopiert. Bitte beachten Sie, dass andere Anwendungen die Zwischenablage im Hintergrund auslesen können.</string>
|
||||
<string name="show_meta_data">Meta Daten anzeigen</string>
|
||||
<string name="show_meta_data_summary">Zusätzliche Daten über den eingelesenen Barcode anzeigen.</string>
|
||||
<string name="show_hex_dump">Hex Dump anzeigen</string>
|
||||
<string name="show_hex_dump_summary">Zeigt einen Hexdump des eingelesenen Inhalts an.</string>
|
||||
<string name="open_with_url">URL zum Öffnen unbekannter Daten</string>
|
||||
<string name="send_category">Weiterleitung</string>
|
||||
<string name="send_scan_url">URL die für jeden Scan aufgerufen werden soll</string>
|
||||
<string name="send_scan_type">Typ des Requests für jeden Scan</string>
|
||||
<string name="send_type_get_add_content">GET mit an die URL angehängtem Inhalt</string>
|
||||
<string name="send_type_get_query_string">GET mit vollständigem Query-String</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="really_remove_scan">Code wirklich entfernen?</string>
|
||||
<string name="really_remove_all_scans">Alle Codes entfernen?</string>
|
||||
<string name="really_remove_selected_scans">Alle ausgewählten Codes entfernen?</string>
|
||||
@@ -83,6 +106,8 @@
|
||||
<string name="search_web">Suche im Internet</string>
|
||||
<string name="search_scan">Code suchen</string>
|
||||
<string name="export_to_file">In Datei exportieren</string>
|
||||
<string name="export_png">Als PNG exportieren</string>
|
||||
<string name="export_svg">Als SVG exportieren</string>
|
||||
<string name="export_as">Exportieren als?</string>
|
||||
<string name="export_csv_comma">CSV mit Kommas</string>
|
||||
<string name="export_csv_semicolon">CSV mit Semikolons</string>
|
||||
@@ -92,7 +117,8 @@
|
||||
<string name="rotate_image_cw">Bild im Uhrzeigersinn rotieren</string>
|
||||
<string name="pick_file">Bilddatei auswählen</string>
|
||||
<string name="pick_code_to_scan">Code im Bild auswählen</string>
|
||||
<string name="shortcut_decode">Barcode einlesen</string>
|
||||
<string name="shortcut_decode">Barcode lesen</string>
|
||||
<string name="shortcut_encode">Barcode erstellen</string>
|
||||
<string name="shortcut_preferences">Einstellungen</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="share">Compartir</string>
|
||||
<string name="copy_to_clipboard">Copiar al portapapeles</string>
|
||||
<string name="copied_to_clipboard">Copiado al portapapeles</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Contraseña copiada al portapapeles</string>
|
||||
<string name="open_url">Abrir URL</string>
|
||||
<string name="cannot_resolve_action">Ninguna aplicación puede abrir esto</string>
|
||||
@@ -36,19 +37,41 @@
|
||||
<string name="view_barcode">Ver código de barras</string>
|
||||
<string name="info">Información</string>
|
||||
<string name="switch_camera">Cambiar cámara</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">Historial</string>
|
||||
<string name="preferences">Configuración</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Aumento de cámara al deslizar hacia arriba/abajo</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Reconocer los códigos de barras 1D verticalmente</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimizar el lector para la precisión, no la velocidad</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibración en la detección</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Guardar historial de escaneados</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">No guardar duplicados consecutivos</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Saltar la inspección y abrir el contenido inmediatamente</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Mostrar metadatos</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Mostrar volcado hexagonal</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">Abrir datos desconocidos con URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="really_remove_scan">¿Realmente desea borrar el escaneo seleccionado?</string>
|
||||
<string name="really_remove_all_scans">¿Realmente desea borrar todo lo escaneado?</string>
|
||||
<string name="really_remove_selected_scans">¿Realmente desea borrar los escaneos seleccionados?</string>
|
||||
@@ -83,6 +106,8 @@
|
||||
<string name="search_web">Buscar en la web</string>
|
||||
<string name="search_scan">Buscar escaneos</string>
|
||||
<string name="export_to_file">Exportar a archivo</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">¿Dónde desea exportar?</string>
|
||||
<string name="export_csv_comma">CSV con comas</string>
|
||||
<string name="export_csv_semicolon">CSV con punto y coma</string>
|
||||
@@ -95,4 +120,5 @@
|
||||
<string name="shortcut_decode">Escanear un código de barras</string>
|
||||
<string name="shortcut_encode">Crear un código de barras</string>
|
||||
<string name="shortcut_preferences">Ajustes</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="share">Share</string>
|
||||
<string name="copy_to_clipboard">Copier dans le presse-papier</string>
|
||||
<string name="copied_to_clipboard">Mis dans le presse-papiers</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Password copied to clipboard</string>
|
||||
<string name="open_url">Ouvrir l\'url</string>
|
||||
<string name="cannot_resolve_action">Aucune application ne peut ouvrir ça</string>
|
||||
@@ -36,19 +37,41 @@
|
||||
<string name="view_barcode">Voir le code barre</string>
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Changer de camera</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">Historique</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Zoom camera by swiping up/down</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimize reader for accuracy, not speed</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibrate on detection</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Sauvegarder l\'histoire des scans</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Do not save consecutive duplicates</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Skip inspection and open contents immediately</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Show metadata</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Show hex dump</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">Open unknown data with URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="really_remove_scan">Supprimer le scan?</string>
|
||||
<string name="really_remove_all_scans">Supprimer tous les scans?</string>
|
||||
<string name="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -83,6 +106,8 @@
|
||||
<string name="search_web">Search the web</string>
|
||||
<string name="search_scan">Search scan</string>
|
||||
<string name="export_to_file">Export to file</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Export as?</string>
|
||||
<string name="export_csv_comma">CSV with commas</string>
|
||||
<string name="export_csv_semicolon">CSV with semicolons</string>
|
||||
@@ -95,4 +120,5 @@
|
||||
<string name="shortcut_decode">Scan a barcode</string>
|
||||
<string name="shortcut_encode">Create a barcode</string>
|
||||
<string name="shortcut_preferences">Settings</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="share">Megosztás</string>
|
||||
<string name="copy_to_clipboard">Másolás a vágólapra</string>
|
||||
<string name="copied_to_clipboard">Vágólapra helyezés</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Password copied to clipboard</string>
|
||||
<string name="open_url">URL megnyitása</string>
|
||||
<string name="cannot_resolve_action">Nincs alkalmazás, amely meg tudná nyitni azt</string>
|
||||
@@ -36,19 +37,41 @@
|
||||
<string name="view_barcode">Vonalkód megtekintése</string>
|
||||
<string name="info">Információ</string>
|
||||
<string name="switch_camera">Kamera átkapcsolása</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">Előzmények</string>
|
||||
<string name="preferences">Beállítások</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Zoom camera by swiping up/down</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimize reader for accuracy, not speed</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibrate on detection</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Beolvasási előzmények mentése</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Do not save consecutive duplicates</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Vizsgálat kihagyása és a tartalom azonnali megnyitása</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Show metadata</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Show hex dump</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">Ismeretlen adat megnyitása URL-lel</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</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="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -83,6 +106,8 @@
|
||||
<string name="search_web">Keresés a weben</string>
|
||||
<string name="search_scan">Search scan</string>
|
||||
<string name="export_to_file">Exportálás fájlba</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Export as?</string>
|
||||
<string name="export_csv_comma">CSV with commas</string>
|
||||
<string name="export_csv_semicolon">CSV with semicolons</string>
|
||||
@@ -95,4 +120,5 @@
|
||||
<string name="shortcut_decode">Scan a barcode</string>
|
||||
<string name="shortcut_encode">Create a barcode</string>
|
||||
<string name="shortcut_preferences">Settings</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<string name="binary_data">(data biner)</string>
|
||||
<plurals name="barcode_info">
|
||||
<item quantity="other">%1$s, %2$d karakter</item>
|
||||
|
||||
</plurals>
|
||||
<string name="error_correction_level">Level koreksi kesalahan</string>
|
||||
<string name="issue_number">Nomor pemindaian</string>
|
||||
@@ -22,6 +21,7 @@
|
||||
<string name="share">Bagikan</string>
|
||||
<string name="copy_to_clipboard">Salin ke papan klip</string>
|
||||
<string name="copied_to_clipboard">Simpan ke papan klip</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Sandi disalin ke papan klip</string>
|
||||
<string name="open_url">Buka url</string>
|
||||
<string name="cannot_resolve_action">Tidak ada aplikasi yang bisa membukanya</string>
|
||||
@@ -36,19 +36,41 @@
|
||||
<string name="view_barcode">Lihat barcode</string>
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Ganti kamera</string>
|
||||
<string name="bulk_mode">Pindai tanpa henti</string>
|
||||
<string name="history">Riwayat</string>
|
||||
<string name="preferences">Preferensi</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Tampilkan pembatas pemotongan</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Perbesar kamera dengan menggeser ke atas/bawah</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Kenali barcode 1D secara vertikal</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimalkan akurasi, bukan kecepatan</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Bergetar saat mendeteksi</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Simpan riwayat pemindaian</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Jangan simpan duplikat berturutan</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Lewati inspeksi dan segera buka konten</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Tampilkan metadata</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Tampilkan hex dump</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">Buka data tak dikenal dengan URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="really_remove_scan">Yakin menghapus pemindaian?</string>
|
||||
<string name="really_remove_all_scans">Yakin menghapus semua pemindaian?</string>
|
||||
<string name="really_remove_selected_scans">Yakin menghapus semua pemindaian?</string>
|
||||
@@ -83,6 +105,8 @@
|
||||
<string name="search_web">Cari secara daring</string>
|
||||
<string name="search_scan">Cari pindaian</string>
|
||||
<string name="export_to_file">Ekspor ke berkas</string>
|
||||
<string name="export_png">Ekspor sebagai PNG</string>
|
||||
<string name="export_svg">Ekspor sebagai SVG</string>
|
||||
<string name="export_as">Ekspor sebagai?</string>
|
||||
<string name="export_csv_comma">CSV dengan koma</string>
|
||||
<string name="export_csv_semicolon">CSV dengan titik koma</string>
|
||||
@@ -95,4 +119,5 @@
|
||||
<string name="shortcut_decode">Pindai barcode</string>
|
||||
<string name="shortcut_encode">Buat barcode</string>
|
||||
<string name="shortcut_preferences">Pengaturan</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="share">Condividi</string>
|
||||
<string name="copy_to_clipboard">Copia negli appunti</string>
|
||||
<string name="copied_to_clipboard">Metti negli appunti</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Password copiata negli appunti</string>
|
||||
<string name="open_url">Apri URL</string>
|
||||
<string name="cannot_resolve_action">Nessuna app può aprirlo</string>
|
||||
@@ -36,19 +37,41 @@
|
||||
<string name="view_barcode">Vedi codice a barre</string>
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Cambia fotocamera</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">Cronologia</string>
|
||||
<string name="preferences">Preferenze</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Zoom fotocamera scorrendo su/giù</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Ottimizza il lettore per accuratezza, non velocità</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibra quando rilevato</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Salva cronologia delle scansioni</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Non salvare doppi consecutivi</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Salta l\'analisi e apri i contenuti direttamente</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Mostra metadati</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Mostra dump esadecimale</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">Apri dati sconosciuti con URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</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="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -83,6 +106,8 @@
|
||||
<string name="search_web">Cerca nel web</string>
|
||||
<string name="search_scan">Cerca scansione</string>
|
||||
<string name="export_to_file">Esporta su file</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Esportare come?</string>
|
||||
<string name="export_csv_comma">CSV con virgole</string>
|
||||
<string name="export_csv_semicolon">CSV con punti e virgola</string>
|
||||
@@ -95,4 +120,5 @@
|
||||
<string name="shortcut_decode">Scansiona un codice a barre</string>
|
||||
<string name="shortcut_encode">Crea un codice a barre</string>
|
||||
<string name="shortcut_preferences">Impostazioni</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="share">Delen</string>
|
||||
<string name="copy_to_clipboard">Kopiëren naar klembord</string>
|
||||
<string name="copied_to_clipboard">Kopieer de inhoud naar het klembord</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Password copied to clipboard</string>
|
||||
<string name="open_url">URL openen</string>
|
||||
<string name="cannot_resolve_action">Er is geen app aangetroffen die dit kan openen</string>
|
||||
@@ -36,18 +37,33 @@
|
||||
<string name="view_barcode">Barcode bekijken</string>
|
||||
<string name="info">Informatie</string>
|
||||
<string name="switch_camera">Camera wisselen</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">Geschiedenis</string>
|
||||
<string name="preferences">Voorkeuren</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Zoom camera by swiping up/down</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimize reader for accuracy, not speed</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibrate on detection</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Scan-geschiedenis behouden</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Do not save consecutive duplicates</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Skip inspection and open contents immediately</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Show metadata</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Show hex dump</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="really_remove_scan">Scan echt verwijderen?</string>
|
||||
<string name="really_remove_all_scans">Echt alle scans verwijderen?</string>
|
||||
<string name="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -79,6 +95,8 @@
|
||||
<string name="search_web">Het net doorzoeken</string>
|
||||
<string name="search_scan">Search scan</string>
|
||||
<string name="export_to_file">Naar bestand exporteren</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Export as?</string>
|
||||
<string name="export_csv_comma">CSV with commas</string>
|
||||
<string name="export_csv_semicolon">CSV with semicolons</string>
|
||||
@@ -86,6 +104,13 @@
|
||||
<string name="export_database">Export SQLite database</string>
|
||||
<string name="error_saving_file">Kon bestand niet opslaan</string>
|
||||
<string name="open_with_url">Niet herkende data met URL openen</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="pick_list_separator">Hoe de lijstonderdelen te separeren?</string>
|
||||
<string name="saved_in_downloads">In downloads opgeslagen</string>
|
||||
<string name="vevent_failed">Kon niet aan kalender toevoegen</string>
|
||||
@@ -95,4 +120,5 @@
|
||||
<string name="shortcut_decode">Scan a barcode</string>
|
||||
<string name="shortcut_encode">Create a barcode</string>
|
||||
<string name="shortcut_preferences">Settings</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
<resources>
|
||||
<string name="open_url">Otwórz url</string>
|
||||
<string name="content">Zawartość</string>
|
||||
<string name="copied_to_clipboard">Skopiowano do schowka</string>
|
||||
<string name="copy_to_clipboard">Skopiuj do schowka</string>
|
||||
<string name="info">Informacje</string>
|
||||
<string name="vcard_add">Dodaj do kontaktów</string>
|
||||
<string name="vevent_add">Dodaj do kalendarza</string>
|
||||
<string name="shortcut_preferences">Ustawienia</string>
|
||||
<string name="share">Udostępnij</string>
|
||||
<string name="error_saving_file">Nie można zapisać pliku</string>
|
||||
<string name="clear_history">Wyczyść historię</string>
|
||||
<string name="compose_barcode">Utwórz kod kreskowy</string>
|
||||
<string name="history">Historia</string>
|
||||
<string name="format">Format</string>
|
||||
<string name="export_to_file">Eksportuj do pliku</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="file_name">Nazwa pliku</string>
|
||||
<string name="export_json">Eksportuj jako JSON</string>
|
||||
<string name="pick_search_engine">Wybierz wyszukiwarkę</string>
|
||||
<string name="pick_file">Wybierz plik obrazu</string>
|
||||
<string name="pick_code_to_scan">Wybierz kod do zeskanowania</string>
|
||||
<string name="sms_send">Wyślij SMS</string>
|
||||
<string name="mail_send">Wyślij e-mail</string>
|
||||
<string name="saved_in_downloads">Zapisano w pobranych</string>
|
||||
<string name="separator_ruler">Linijka</string>
|
||||
<string name="scan_code">Skanuj kod</string>
|
||||
<string name="error_correction_level">Poziom korekcji błędów</string>
|
||||
<string name="export_csv_comma">CSV z przecinkami</string>
|
||||
<string name="export_csv_semicolon">CSV z średnikami</string>
|
||||
<string name="shortcut_encode">Stwórz kod kreskowy</string>
|
||||
<string name="error_file_exists">Plik już istnieje</string>
|
||||
<string name="no_barcode_found">Nie znaleziono kodu kreskowego</string>
|
||||
<string name="no_camera_no_fun">Ta aplikacja nie ma żadnego sensu bez dostępu do kamery. Do widzenia.</string>
|
||||
<string name="tel_dial">Wybierz numer</string>
|
||||
<string name="connect_to_wifi">Połącz z Wi-Fi</string>
|
||||
<string name="vcard_failed">Nie można dodać do kontaktów</string>
|
||||
<string name="tel_error">Nie można wybrać numeru</string>
|
||||
<string name="sms_error">Nie można wysłać SMS-a</string>
|
||||
<string name="mail_error">Nie można wysłać e-maila</string>
|
||||
<string name="rotate_image_cw">Obróć obraz zgodnie z ruchem wskazówek zegara</string>
|
||||
<string name="edit_scan">Edytuj etykietę</string>
|
||||
<string name="enter_name_hint">Nazwa skanu</string>
|
||||
<string name="camera_error">Nie można uzyskać dostępu do kamery, spróbuj ponownie</string>
|
||||
<string name="copy_scan">Skopiuj skan</string>
|
||||
<string name="vevent_failed">Nie można dodać do kalendarza</string>
|
||||
<string name="wifi_config_failed">Nie można skonfigurować Wi-Fi</string>
|
||||
<string name="size">Rozmiar w pikselach</string>
|
||||
<string name="export_as">Eksportuj jako?</string>
|
||||
<string name="really_remove_all_scans">Czy naprawdę usunąć wszystkie skany?</string>
|
||||
<string name="really_remove_scan">Czy naprawdę usunąć skan?</string>
|
||||
<string name="really_remove_selected_scans">Czy naprawdę usunąć wybrane skany?</string>
|
||||
<string name="binary_data">(dane binarne)</string>
|
||||
<string name="show_hex_dump">Pokazuj zrzut szesnastkowy</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="show_meta_data">Pokazuj metadane</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="switch_camera">Przełącz aparat</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="toggle_flash">Przełącz lampę błyskową</string>
|
||||
<string name="wifi_added">Wi-Fi dodane</string>
|
||||
<string name="zoom_by_swiping">Przybliżaj kamerę, przesuwając w górę/dół</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="view_barcode">Wyświetl kod kreskowy</string>
|
||||
<string name="orientation">Orientacja</string>
|
||||
<string name="error_encoding_barcode">Nie można utworzyć kodu kreskowego</string>
|
||||
<string name="otpauth_add">Dodaj 2FA</string>
|
||||
<string name="other_meta_data">Metadane</string>
|
||||
<string name="remove_scan">Usuń skan</string>
|
||||
<string name="separator_line_break">Przerwanie linii</string>
|
||||
<string name="shortcut_decode">Zeskanuj kod kreskowy</string>
|
||||
<string name="use_history">Zapisuj historię skanowania</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="vibrate">Wibruj po wykryciu</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="open_immediately">Pomiń kontrolę i natychmiast otwórz zawartość</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_crop_handle">Pokazuj ogranicznik przycinania</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="search_web">Szukaj w sieci</string>
|
||||
<string name="search_scan">Szukaj skanu</string>
|
||||
<string name="export_database">Eksportuj do bazy danych SQLite</string>
|
||||
<string name="ignore_consecutive_duplicates">Nie zapisuj kolejnych duplikatów</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_with_url">Otwieraj nieznane dane za pomocą adresu URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Hasło skopiowane do schowka</string>
|
||||
<string name="pdf417_extra_metadata">Metadane PDF417</string>
|
||||
<string name="suggested_price">Sugerowana cena</string>
|
||||
<string name="preferences">Ustawienia</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="decode_barcode">Dekoduj kod kreskowy</string>
|
||||
<string name="upc_ean_extension">Dodatek UPC EAN</string>
|
||||
<string name="possible_country">Możliwy kraj produkcji</string>
|
||||
<string name="encode">ZAKODUJ</string>
|
||||
<string name="error_no_content">Brak zawartości</string>
|
||||
<string name="try_harder">Zoptymalizuj czytnik pod kątem dokładności, a nie prędkości</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="cannot_resolve_action">Żadna aplikacja nie może tego otworzyć</string>
|
||||
<string name="width_by_height">%1$d×%2$d</string>
|
||||
<string name="input_content_here">Wprowadź zawartość tutaj</string>
|
||||
<string name="pick_list_separator">Jak oddzielić elementy listy?</string>
|
||||
<string name="enter_name">Wprowadź nazwę opisującą skan</string>
|
||||
<string name="auto_rotate">Rozpoznawaj kody kreskowe 1D pionowo</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="save_as_file_name">Jak zapisać plik w pobranych?</string>
|
||||
<string name="issue_number">Numer wydania</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="share">Compartilhar</string>
|
||||
<string name="copy_to_clipboard">Copiar para área de transferência</string>
|
||||
<string name="copied_to_clipboard">Colocar na área de transferência</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Password copied to clipboard</string>
|
||||
<string name="open_url">Abrir url</string>
|
||||
<string name="cannot_resolve_action">Nenhuma aplicativo pode abrir isso</string>
|
||||
@@ -36,19 +37,41 @@
|
||||
<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="bulk_mode">Scan continuously</string>
|
||||
<string name="history">Histórico</string>
|
||||
<string name="preferences">Preferências</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Zoom camera by swiping up/down</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimize reader for accuracy, not speed</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibrate on detection</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Salvar histórico de escaneamento</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Do not save consecutive duplicates</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Skip inspection and open contents immediately</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Show metadata</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Show hex dump</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">Abrir dados desconhecidos com URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</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="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -83,6 +106,8 @@
|
||||
<string name="search_web">Search the web</string>
|
||||
<string name="search_scan">Search scan</string>
|
||||
<string name="export_to_file">Export to file</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Export as?</string>
|
||||
<string name="export_csv_comma">CSV with commas</string>
|
||||
<string name="export_csv_semicolon">CSV with semicolons</string>
|
||||
@@ -95,4 +120,5 @@
|
||||
<string name="shortcut_decode">Scan a barcode</string>
|
||||
<string name="shortcut_encode">Create a barcode</string>
|
||||
<string name="shortcut_preferences">Settings</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
<string name="content">Текст</string>
|
||||
<string name="binary_data">(двоичные данные)</string>
|
||||
<plurals name="barcode_info">
|
||||
<item quantity="zero">%2$d символов, %1$s</item>
|
||||
<item quantity="one">%2$d символ, %1$s</item>
|
||||
<item quantity="two">%2$d символа, %1$s</item>
|
||||
<item quantity="few">%2$d символа, %1$s</item>
|
||||
<item quantity="many">%2$d символов, %1$s</item>
|
||||
<item quantity="other">%2$d символов, %1$s</item>
|
||||
@@ -26,6 +24,7 @@
|
||||
<string name="share">Поделиться</string>
|
||||
<string name="copy_to_clipboard">Скопировать в буфер обмена</string>
|
||||
<string name="copied_to_clipboard">Скопирован в буфер обмена</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Пароль скопирован в буфер обмена</string>
|
||||
<string name="open_url">Открыть URL</string>
|
||||
<string name="cannot_resolve_action">Не найдено приложение для этого действия</string>
|
||||
@@ -40,19 +39,41 @@
|
||||
<string name="view_barcode">Просмотр штрих-кода</string>
|
||||
<string name="info">Информация</string>
|
||||
<string name="switch_camera">Переключить камеру</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">История</string>
|
||||
<string name="preferences">Настройки</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Масштабировать движением пальцем вверх/вниз</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Оптимизировать считывание на точность, а не скорость</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Вибрировать при обнаружении</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Сохранять историю сканирования</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Не сохранять последовательные дубликаты</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Пропускать проверку и сразу открыть содержимое</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Показывать метаданные</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Показать шестнадцатеричный дамп</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">Открыть неизвестные данные с помощью URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="really_remove_scan">Действительно удалить сканирование?</string>
|
||||
<string name="really_remove_all_scans">Действительно удалить все сканирования?</string>
|
||||
<string name="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -87,6 +108,8 @@
|
||||
<string name="search_web">Искать в сети</string>
|
||||
<string name="search_scan">Поиск сканирования</string>
|
||||
<string name="export_to_file">Экспортировать в файл</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Формат экспортируемого файла</string>
|
||||
<string name="export_csv_comma">CSV (разделитель - запятая)</string>
|
||||
<string name="export_csv_semicolon">CSV (разделитель - точка с запятой)</string>
|
||||
@@ -99,4 +122,5 @@
|
||||
<string name="shortcut_decode">Сканировать штрих-код</string>
|
||||
<string name="shortcut_encode">Создать штрих-код</string>
|
||||
<string name="shortcut_preferences">Настройки</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<resources>
|
||||
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@android:color/transparent</item>
|
||||
<item name="colorAccent">@color/accent</item>
|
||||
<item name="android:windowBackground">@drawable/background_window</item>
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="actionModeBackground">@color/accent</item>
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -1,7 +1,5 @@
|
||||
<resources>
|
||||
<style
|
||||
name="Button"
|
||||
parent="@android:style/Widget.Button">
|
||||
<style name="Button" parent="@android:style/Widget.Button">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:background">@drawable/button_raised</item>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<string name="share">分享</string>
|
||||
<string name="copy_to_clipboard">复制到剪切板</string>
|
||||
<string name="copied_to_clipboard">复制到剪切板</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Password copied to clipboard</string>
|
||||
<string name="open_url">打开链接</string>
|
||||
<string name="cannot_resolve_action">没有相关APP可以打开它</string>
|
||||
@@ -35,19 +36,41 @@
|
||||
<string name="view_barcode">查看条形码</string>
|
||||
<string name="info">信息</string>
|
||||
<string name="switch_camera">切换摄像头</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">历史</string>
|
||||
<string name="preferences">首选项</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Zoom camera by swiping up/down</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimize reader for accuracy, not speed</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibrate on detection</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">保存扫描历史</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Do not save consecutive duplicates</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">跳过内容展示并立即打开</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Show metadata</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Show hex dump</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">使用URL打开未知数据</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="really_remove_scan">确定删除记录?</string>
|
||||
<string name="really_remove_all_scans">确定删除全部记录?</string>
|
||||
<string name="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -82,6 +105,8 @@
|
||||
<string name="search_web">在互联网中搜索</string>
|
||||
<string name="search_scan">Search scan</string>
|
||||
<string name="export_to_file">导出为CSV文件</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Export as?</string>
|
||||
<string name="export_csv_comma">CSV with commas</string>
|
||||
<string name="export_csv_semicolon">CSV with semicolons</string>
|
||||
@@ -94,4 +119,5 @@
|
||||
<string name="shortcut_decode">Scan a barcode</string>
|
||||
<string name="shortcut_encode">Create a barcode</string>
|
||||
<string name="shortcut_preferences">Settings</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<string name="share">分享</string>
|
||||
<string name="copy_to_clipboard">複製</string>
|
||||
<string name="copied_to_clipboard">複製</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Password copied to clipboard</string>
|
||||
<string name="open_url">開啓</string>
|
||||
<string name="cannot_resolve_action">無應用程式可以開啓</string>
|
||||
@@ -35,17 +36,30 @@
|
||||
<string name="view_barcode">檢視條碼</string>
|
||||
<string name="info">資訊</string>
|
||||
<string name="switch_camera">切換相機</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">歷史</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Zoom camera by swiping up/down</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimize reader for accuracy, not speed</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibrate on detection</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">儲存掃描歷史</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Do not save consecutive duplicates</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Skip inspection and open contents immediately</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Automatically copy contents into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Show metadata</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Show hex dump</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="really_remove_scan">真的要移除掃描記錄?</string>
|
||||
<string name="really_remove_all_scans">真的要移除所有掃描記錄?</string>
|
||||
<string name="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -77,11 +91,22 @@
|
||||
<string name="vevent_add">添加至行事曆</string>
|
||||
<string name="vevent_failed">不能添加至行事曆</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="open_with_url">Preferences</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="open_with_url">Open unknown data with URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="otpauth_add">Add 2FA</string>
|
||||
<string name="search_web">Search the web</string>
|
||||
<string name="search_scan">Search scan</string>
|
||||
<string name="export_to_file">Export to file</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Export as?</string>
|
||||
<string name="export_csv_comma">CSV with commas</string>
|
||||
<string name="export_csv_semicolon">CSV with semicolons</string>
|
||||
@@ -94,4 +119,5 @@
|
||||
<string name="shortcut_decode">Scan a barcode</string>
|
||||
<string name="shortcut_encode">Create a barcode</string>
|
||||
<string name="shortcut_preferences">Settings</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Binary Eye</string>
|
||||
<string name="open_with_url_hint" translatable="false">http://example.com?data=</string>
|
||||
<string name="url_hint" translatable="false">http://example.com?content=</string>
|
||||
<string name="project_url" translatable="false">https://github.com/markusfisch/BinaryEye</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<resources>
|
||||
<string-array name="send_type_names">
|
||||
<item>@string/send_type_get_add_content</item>
|
||||
<item>@string/send_type_get_query_string</item>
|
||||
<item>@string/send_type_post_form</item>
|
||||
<item>@string/send_type_post_json</item>
|
||||
</string-array>
|
||||
<string-array name="send_type_values">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
@@ -22,6 +22,7 @@
|
||||
<string name="share">Share</string>
|
||||
<string name="copy_to_clipboard">Copy to clipboard</string>
|
||||
<string name="copied_to_clipboard">Copied to clipboard</string>
|
||||
<string name="copy_password">Copy password into clipboard</string>
|
||||
<string name="copied_password_to_clipboard">Password copied to clipboard</string>
|
||||
<string name="open_url">Open url</string>
|
||||
<string name="cannot_resolve_action">No application can open that</string>
|
||||
@@ -36,19 +37,41 @@
|
||||
<string name="view_barcode">View barcode</string>
|
||||
<string name="info">Info</string>
|
||||
<string name="switch_camera">Switch camera</string>
|
||||
<string name="bulk_mode">Scan continuously</string>
|
||||
<string name="history">History</string>
|
||||
<string name="preferences">Preferences</string>
|
||||
<string name="scan_category">Scan</string>
|
||||
<string name="content_category">Content</string>
|
||||
<string name="show_crop_handle">Show cropping limiter</string>
|
||||
<string name="zoom_by_swiping">Zoom camera by swiping up/down</string>
|
||||
<string name="auto_rotate">Recognize 1D barcodes vertically</string>
|
||||
<string name="try_harder">Optimize reader for accuracy, not speed</string>
|
||||
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
|
||||
<string name="zoom_by_swiping">Swipe up/down to zoom</string>
|
||||
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
|
||||
<string name="auto_rotate">Recognize vertical 1D barcodes</string>
|
||||
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
|
||||
<string name="try_harder">Optimize reader for accuracy</string>
|
||||
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
|
||||
<string name="vibrate">Vibrate on detection</string>
|
||||
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
|
||||
<string name="use_history">Save scan history</string>
|
||||
<string name="ignore_consecutive_duplicates">Do not save consecutive duplicates</string>
|
||||
<string name="open_immediately">Skip inspection and open contents immediately</string>
|
||||
<string name="use_history_summary">Save recognized codes on your device.</string>
|
||||
<string name="ignore_consecutive_duplicates">Ignore duplicates</string>
|
||||
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
|
||||
<string name="open_immediately">Open immediately</string>
|
||||
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
|
||||
<string name="copy_immediately">Put into clipboard</string>
|
||||
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
|
||||
<string name="show_meta_data">Show metadata</string>
|
||||
<string name="show_meta_data_summary">Show additional data about the scanned barcoded.</string>
|
||||
<string name="show_hex_dump">Show hex dump</string>
|
||||
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
|
||||
<string name="open_with_url">Open unknown data with URL</string>
|
||||
<string name="send_category">Forwarding</string>
|
||||
<string name="send_scan_url">Send every scan to URL</string>
|
||||
<string name="send_scan_type">Type of request for every scan</string>
|
||||
<string name="send_type_get_add_content">GET and simply add content</string>
|
||||
<string name="send_type_get_query_string">GET with compelete query string</string>
|
||||
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
|
||||
<string name="send_type_post_json">POST application/json</string>
|
||||
<string name="really_remove_scan">Really remove scan?</string>
|
||||
<string name="really_remove_all_scans">Really remove all scans?</string>
|
||||
<string name="really_remove_selected_scans">Really remove selected scans?</string>
|
||||
@@ -83,6 +106,8 @@
|
||||
<string name="search_web">Search the web</string>
|
||||
<string name="search_scan">Search scan</string>
|
||||
<string name="export_to_file">Export to file</string>
|
||||
<string name="export_png">Export as PNG</string>
|
||||
<string name="export_svg">Export as SVG</string>
|
||||
<string name="export_as">Export as?</string>
|
||||
<string name="export_csv_comma">CSV with commas</string>
|
||||
<string name="export_csv_semicolon">CSV with semicolons</string>
|
||||
@@ -95,4 +120,5 @@
|
||||
<string name="shortcut_decode">Scan a barcode</string>
|
||||
<string name="shortcut_encode">Create a barcode</string>
|
||||
<string name="shortcut_preferences">Settings</string>
|
||||
<string name="background_request_failed">Background request failed</string>
|
||||
</resources>
|
||||
|
||||
@@ -6,19 +6,16 @@
|
||||
<item name="android:windowBackground">@drawable/background_window</item>
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="actionModeBackground">@color/accent</item>
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
|
||||
</style>
|
||||
<style name="SplashTheme" parent="@style/AppTheme">
|
||||
<item name="android:windowBackground">@drawable/background_splash</item>
|
||||
</style>
|
||||
<style
|
||||
name="SecondaryText"
|
||||
parent="@android:style/Widget.TextView">
|
||||
<style name="SecondaryText" parent="@android:style/Widget.TextView">
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
</style>
|
||||
<style
|
||||
name="Button"
|
||||
parent="@android:style/Widget.Button">
|
||||
<style name="Button" parent="@android:style/Widget.Button">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">48dp</item>
|
||||
<item name="android:layout_gravity">center_horizontal</item>
|
||||
@@ -29,9 +26,7 @@
|
||||
<item name="android:paddingRight">@dimen/button_padding</item>
|
||||
<item name="android:maxLines">1</item>
|
||||
</style>
|
||||
<style
|
||||
name="FAB"
|
||||
parent="Widget.Design.FloatingActionButton">
|
||||
<style name="FAB" parent="Widget.Design.FloatingActionButton">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_margin">20dp</item>
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/preferences"
|
||||
android:key="preferences">
|
||||
<PreferenceCategory android:title="@string/scan_category">
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="show_crop_handle"
|
||||
android:title="@string/show_crop_handle"
|
||||
android:summary="@string/show_crop_handle_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="zoom_by_swiping"
|
||||
android:title="@string/zoom_by_swiping"
|
||||
android:summary="@string/zoom_by_swiping_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="auto_rotate"
|
||||
android:title="@string/auto_rotate"
|
||||
android:summary="@string/auto_rotate_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="try_harder"
|
||||
android:title="@string/try_harder"
|
||||
android:summary="@string/try_harder_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="vibrate"
|
||||
android:title="@string/vibrate"
|
||||
android:summary="@string/vibrate_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="use_history"
|
||||
android:title="@string/use_history"
|
||||
android:summary="@string/use_history_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="ignore_consecutive_duplicates"
|
||||
android:title="@string/ignore_consecutive_duplicates"
|
||||
android:summary="@string/ignore_consecutive_duplicates_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="copy_immediately"
|
||||
android:title="@string/copy_immediately"
|
||||
android:summary="@string/copy_immediately_summary"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/send_category">
|
||||
<de.markusfisch.android.binaryeye.preference.UrlPreference
|
||||
android:key="send_scan_url"
|
||||
android:title="@string/send_scan_url"
|
||||
android:summary="@string/url_hint"/>
|
||||
<ListPreference
|
||||
android:key="send_scan_type"
|
||||
android:title="@string/send_scan_type"
|
||||
android:entries="@array/send_type_names"
|
||||
android:entryValues="@array/send_type_values"
|
||||
android:defaultValue="0"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/content_category">
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="open_immediately"
|
||||
android:title="@string/open_immediately"
|
||||
android:summary="@string/open_immediately_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="show_meta_data"
|
||||
android:title="@string/show_meta_data"
|
||||
android:summary="@string/show_meta_data_summary"/>
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="show_hex_dump"
|
||||
android:title="@string/show_hex_dump"
|
||||
android:summary="@string/show_hex_dump_summary"/>
|
||||
<de.markusfisch.android.binaryeye.preference.UrlPreference
|
||||
android:key="open_with_url"
|
||||
android:title="@string/open_with_url"
|
||||
android:summary="@string/url_hint"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
@@ -1,17 +1,17 @@
|
||||
#pragma version(1)
|
||||
#pragma rs java_package_name(de.markusfisch.android.binaryeye.renderscript)
|
||||
#pragma rs java_package_name(de.markusfisch.android.binaryeye.rs)
|
||||
#pragma rs_fp_relaxed
|
||||
|
||||
rs_allocation inImage;
|
||||
int inWidth;
|
||||
int inHeight;
|
||||
|
||||
uchar RS_KERNEL rotate90(uchar in, uint32_t x, uint32_t y) {
|
||||
uchar RS_KERNEL rotate90(const uchar in, uint32_t x, uint32_t y) {
|
||||
const uchar *out = rsGetElementAt(inImage, y, inHeight - 1 - x);
|
||||
return *out;
|
||||
}
|
||||
|
||||
uchar RS_KERNEL rotate180(uchar in, uint32_t x, uint32_t y) {
|
||||
uchar RS_KERNEL rotate180(const uchar in, uint32_t x, uint32_t y) {
|
||||
const uchar *out = rsGetElementAt(
|
||||
inImage,
|
||||
inWidth - 1 - x,
|
||||
@@ -19,7 +19,7 @@ uchar RS_KERNEL rotate180(uchar in, uint32_t x, uint32_t y) {
|
||||
return *out;
|
||||
}
|
||||
|
||||
uchar RS_KERNEL rotate270(uchar in, uint32_t x, uint32_t y) {
|
||||
uchar RS_KERNEL rotate270(const uchar in, uint32_t x, uint32_t y) {
|
||||
const uchar *out = rsGetElementAt(inImage, inWidth - 1 - y, x);
|
||||
return *out;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '1.3.72'
|
||||
tools_version = '4.0.0'
|
||||
tools_version = '4.0.1'
|
||||
build_tools_version = '29.0.3'
|
||||
sdk_version = 29
|
||||
support_version = '25.3.1'
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
* Export SQLite database
|
||||
* Improve order of preferences
|
||||
* Update Italian translation
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
* Update Russian translation
|
||||
* Force compat mode if native RenderScript crashed
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
* Share history as CSV and JSON too
|
||||
* Export history in JSON format
|
||||
* Update Indonesian translation
|
||||
* Fix initializing of RenderScript automatically
|
||||
* Fix highlighting after landscape to landscape rotations
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
* Add a setting to enable reading of vertical 1D barcodes
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
* Add a handle to define a region of interest
|
||||
* Add a setting to show/hide cropping limiter
|
||||
* Add support for VCALENDAR types
|
||||
* Add spanish translation
|
||||
* Add copy to clipboard button to context menu in history listing
|
||||
* Make history actions work on current listing only
|
||||
* Keep camera selection over orientation changes
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
* Improve usability of cropping limiter
|
||||
* Draw round corners around region of interest
|
||||
* Update Indonesian translation
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
* Stop detection while region of interest is modified
|
||||
* Fix resetting region of interest
|
||||
* Add Polish translation
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
* Add bulk mode
|
||||
* Remember region of interest permanently
|
||||
* Export generated barcode as SVG
|
||||
* Run detection on images in background
|
||||
* Remove a scan from result view
|
||||
* Update Indonesian translation
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
kotlin.code.style=official
|
||||
android.enableR8=true
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24 24H0V0h24v24z" fill="none"/>
|
||||
<path d="M 4.413 15.067 L 3.533 15.067 L 3.533 16.997 L 2.163 16.997 L 2.163 11.307 L 4.433 11.307 C 4.866 11.307 5.25 11.387 5.583 11.547 C 5.923 11.707 6.183 11.937 6.363 12.237 C 6.55 12.53 6.643 12.864 6.643 13.237 C 6.643 13.79 6.443 14.234 6.043 14.567 C 5.643 14.9 5.1 15.067 4.413 15.067 Z M 3.533 12.367 L 3.533 14.007 L 4.433 14.007 C 4.7 14.007 4.903 13.94 5.043 13.807 C 5.183 13.674 5.253 13.487 5.253 13.247 C 5.253 12.98 5.18 12.767 5.033 12.607 C 4.893 12.447 4.696 12.367 4.443 12.367 L 3.533 12.367 ZM 12.12 11.307 L 12.12 16.997 L 10.76 16.997 L 8.74 13.457 L 8.74 16.997 L 7.37 16.997 L 7.37 11.307 L 8.74 11.307 L 10.75 14.847 L 10.75 11.307 L 12.12 11.307 ZM 17.647 13.957 L 17.647 16.297 C 17.434 16.53 17.124 16.717 16.717 16.857 C 16.31 17.004 15.864 17.077 15.377 17.077 C 14.637 17.077 14.044 16.847 13.597 16.387 C 13.15 15.934 12.91 15.3 12.877 14.487 L 12.877 13.997 C 12.877 13.437 12.977 12.947 13.177 12.527 C 13.37 12.114 13.654 11.794 14.027 11.567 C 14.394 11.34 14.82 11.227 15.307 11.227 C 16.014 11.227 16.564 11.39 16.957 11.717 C 17.344 12.037 17.57 12.52 17.637 13.167 L 16.317 13.167 C 16.27 12.847 16.17 12.62 16.017 12.487 C 15.857 12.354 15.634 12.287 15.347 12.287 C 15.007 12.287 14.744 12.43 14.557 12.717 C 14.364 13.01 14.267 13.427 14.267 13.967 L 14.267 14.317 C 14.267 14.884 14.364 15.31 14.557 15.597 C 14.75 15.877 15.057 16.017 15.477 16.017 C 15.83 16.017 16.094 15.94 16.267 15.787 L 16.267 14.897 L 15.317 14.897 L 15.317 13.957 L 17.647 13.957 Z" transform="matrix(1, 0, 0, 1, 0, 0)" style="white-space: pre;"/>
|
||||
<path d="M 20.373 6.135 L 17.614 8.888 L 19.684 8.888 L 19.684 11.809 L 21.063 11.809 L 21.063 8.888 L 23.133 8.888 L 20.373 6.135 Z" style="" transform="matrix(0.707107, 0.707107, -0.707107, 0.707107, 12.311422, -11.778402)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24 24H0V0h24v24z" fill="none"/>
|
||||
<path d="M 5.45 15.487 C 5.45 15.287 5.38 15.13 5.24 15.017 C 5.1 14.904 4.85 14.787 4.49 14.667 C 4.137 14.547 3.847 14.43 3.62 14.317 C 2.88 13.957 2.51 13.46 2.51 12.827 C 2.51 12.514 2.603 12.237 2.79 11.997 C 2.97 11.757 3.23 11.57 3.57 11.437 C 3.903 11.297 4.28 11.227 4.7 11.227 C 5.107 11.227 5.473 11.3 5.8 11.447 C 6.127 11.594 6.377 11.804 6.55 12.077 C 6.73 12.344 6.82 12.65 6.82 12.997 L 5.46 12.997 C 5.46 12.764 5.387 12.584 5.24 12.457 C 5.1 12.33 4.91 12.267 4.67 12.267 C 4.423 12.267 4.23 12.32 4.09 12.427 C 3.95 12.534 3.88 12.67 3.88 12.837 C 3.88 12.984 3.957 13.117 4.11 13.237 C 4.263 13.357 4.537 13.48 4.93 13.607 C 5.323 13.734 5.647 13.87 5.9 14.017 C 6.513 14.37 6.82 14.857 6.82 15.477 C 6.82 15.977 6.633 16.367 6.26 16.647 C 5.887 16.934 5.373 17.077 4.72 17.077 C 4.26 17.077 3.843 16.994 3.47 16.827 C 3.097 16.66 2.813 16.434 2.62 16.147 C 2.433 15.86 2.34 15.53 2.34 15.157 L 3.72 15.157 C 3.72 15.457 3.797 15.68 3.95 15.827 C 4.11 15.974 4.367 16.047 4.72 16.047 C 4.947 16.047 5.127 15.997 5.26 15.897 C 5.387 15.797 5.45 15.66 5.45 15.487 ZM 8.608 11.307 L 9.738 15.447 L 10.868 11.307 L 12.398 11.307 L 10.488 16.997 L 8.988 16.997 L 7.088 11.307 L 8.608 11.307 ZM 17.422 13.957 L 17.422 16.297 C 17.209 16.53 16.899 16.717 16.492 16.857 C 16.085 17.004 15.639 17.077 15.152 17.077 C 14.412 17.077 13.819 16.847 13.372 16.387 C 12.925 15.934 12.685 15.3 12.652 14.487 L 12.652 13.997 C 12.652 13.437 12.752 12.947 12.952 12.527 C 13.145 12.114 13.429 11.794 13.802 11.567 C 14.169 11.34 14.595 11.227 15.082 11.227 C 15.789 11.227 16.339 11.39 16.732 11.717 C 17.119 12.037 17.345 12.52 17.412 13.167 L 16.092 13.167 C 16.045 12.847 15.945 12.62 15.792 12.487 C 15.632 12.354 15.409 12.287 15.122 12.287 C 14.782 12.287 14.519 12.43 14.332 12.717 C 14.139 13.01 14.042 13.427 14.042 13.967 L 14.042 14.317 C 14.042 14.884 14.139 15.31 14.332 15.597 C 14.525 15.877 14.832 16.017 15.252 16.017 C 15.605 16.017 15.869 15.94 16.042 15.787 L 16.042 14.897 L 15.092 14.897 L 15.092 13.957 L 17.422 13.957 Z" transform="matrix(1, 0, 0, 1, 0, 0)" style="white-space: pre;"/>
|
||||
<path d="M 19.58 6.075 L 16.821 8.828 L 18.891 8.828 L 18.891 11.749 L 20.27 11.749 L 20.27 8.828 L 22.34 8.828 L 19.58 6.075 Z" style="" transform="matrix(0.707107, 0.707107, -0.707107, 0.707107, 12.036731, -11.23524)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |