Compare commits

...
151 Commits
Author SHA1 Message Date
Markus Fisch 9abc01fc4f Advance version number to 1.58.2 2023-01-31 12:36:32 +01:00
Markus Fisch d10a33c1b7 Check string is not empty before calling last()
Because `String.last()` will throw a NoSuchElementException when
the string is empty.
2023-01-31 10:51:18 +01:00
Markus Fisch 357b2b5d59 Advance version number to 1.58.1 2023-01-31 10:51:18 +01:00
Markus Fisch dfd64405da Fix design of monochrome launcher icon
Monochrome icons don't use any color, not even black or white.
2023-01-30 18:41:56 +01:00
Markus Fisch 045daf9deb Remove committing preferences
This made only sense when this app used RenderScript, which could
cause the app to crash before settings were saved.
2023-01-25 20:31:11 +01:00
Tom XinandGitHub 46b9ef516c Update zh-rCn translation 2023-01-21 20:52:19 +01:00
Markus Fisch 0265909fd7 Advance version number to 1.58.0 2023-01-19 20:28:25 +01:00
Markus Fisch ceef92bb7c Alternate binarizers to improve detection
By default, ZXing uses LOCAL_AVERAGE, but this does not work well
with inverted barcodes on low-contrast backgrounds.

Of course, it would be better to improve ZXing's HybridBinarizer
(which is used for LOCAL_AVERAGE), but this is not trivial.
2023-01-19 20:16:49 +01:00
Markus Fisch 46785bab01 Update ZXing C++ wrapper for DecodeHints
The latest version makes all native `DecodeHints` available
to the JVM.
2023-01-19 20:12:54 +01:00
Markus Fisch ccbb0f9e8a Fix terminating string tag in italian translation 2023-01-19 18:01:27 +01:00
bovirusandGitHub 833d8e93d3 Update italian language 2023-01-19 17:53:41 +01:00
Markus Fisch 6dff9992d8 Remove META parameter from README
Since the migration to ZXing-C++ this parameter doesn't exist anymore.
2023-01-16 20:20:44 +01:00
Markus Fisch 0b3dfe93cf Silently try openUrl() for OpenOrSearchAction
Avoid using `execShareIntent()` for OpenOrSearchAction because it
will toast a message when it fails.
2023-01-11 19:21:54 +01:00
Markus Fisch e79ad49d15 Remove converting charset for PDF417
This is handled by ZXing C++ now.

Converting the text again destroys it.
2023-01-08 17:35:57 +01:00
chreddyandGitHub 38f7ba1ec6 Add Danish translation 2023-01-08 17:35:43 +01:00
NPLandGitHub 4d268240fd Update Japanese translation 2023-01-03 09:22:56 +01:00
Markus Fisch 1131f749a9 Make database migrations extension functions
Simpler and more Kotlin idiomatic.
2023-01-02 12:12:43 +01:00
Markus Fisch 93a3cd2620 Migrate version number to version string
Because ZXing C++ did switch to a String to support versions
with letters.
2023-01-02 12:10:02 +01:00
Mystery0 MandGitHub a866a2eab3 Add fillAlpha for monochrome icon 2022-12-29 13:58:22 +01:00
Markus Fisch c5d6bfa4b2 Respect setting to ignore duplicates for bulk scan
Before this, the previously scanned code was _always_ ignored for
bulk scans to avoid scanning the same code twice. But this isn't
always desirable, and the setting to ignore duplicates should have
an effect to give the user control over this behaviour.
2022-12-21 18:24:00 +01:00
Markus Fisch 6a63bc4e06 Increase the duration of the vibration
Because 100ms is too short for some devices and the vibration
cannot be felt.

This should fix https://github.com/markusfisch/BinaryEye/issues/334
2022-12-21 18:17:03 +01:00
Markus Fisch 09ff334c4c Update link on how to write a good commit message 2022-12-21 16:09:56 +01:00
solokotandGitHub 45a2ac0647 Update Russian translation 2022-12-20 13:06:40 +01:00
Markus Fisch 425f3a7b80 Advance version number to 1.57.0 2022-12-19 20:45:36 +01:00
Markus Fisch f895b42cfe Allow removing individual network suggestions
From Android R on, because `WifiManager.getNetworkSuggestions()`
is not available on Q.
2022-12-19 20:29:04 +01:00
Markus Fisch ecd4c487e3 Update pt-br translation
Thanks to m_s_
2022-12-18 12:39:05 +01:00
Markus Fisch 750671c408 Remove carriage returns from string resource 2022-12-17 13:27:24 +01:00
Markus Fisch ead856221f Update Kotlin version 2022-12-16 10:19:28 +01:00
Markus Fisch 34f14d0ff0 Update to latest ZXing C++ version 2022-12-16 10:19:28 +01:00
motive0604andGitHub 1b21297d83 Add Korean language 2022-12-13 09:38:34 +01:00
solokotandGitHub 53cb6fe007 Update Russian translation 2022-12-11 22:44:17 +01:00
Markus Fisch f1daa19056 Add optional audio feedback for scanning
And also support a couple of signal noises.
2022-12-10 13:52:39 +01:00
Markus Fisch bd9da5889c Add a semicolon to WIFI strings if it is missing
Because many generators don't terminate the expression.
2022-12-07 12:21:22 +01:00
Markus Fisch d5949e557a Add a RequiresApi annotation
To make clear `addNetworkFromBuilder` is only ever called
on Android Q+.
2022-12-06 20:09:41 +01:00
Markus Fisch 51079e5208 Update tools version 2022-12-06 20:07:55 +01:00
Markus Fisch 09f3368bf0 Update ScalingImageView library 2022-12-06 20:06:22 +01:00
Markus Fisch 84e03e3cc8 Fix typo in german translation 2022-12-06 20:03:20 +01:00
Markus Fisch cff299771a Remove resource references from vector drawables
Resource references will not work correctly in images generated
for vector icons for API < 24.
2022-12-06 20:00:43 +01:00
Markus Fisch 7a327ab7c4 Fix transferring shared text to encode fragment 2022-12-03 21:37:18 +01:00
Markus Fisch 72b8924574 Fix parsing a WiFi network on Android Q
`WifiConnector.parse()` still returned a `WifiNetworkSuggestion`
on Android Q but `WifiConnector.addNetwork()` is now expecting a
`WifiNetworkSuggestion.Builder` :8

Anyway, this code wasn't very good to start with. Having the exact
same check in two different places with the exact same meaning is
bad. This bug is a good example of that ;)

So now, `WifiConnector.addNetwork()` checks what type of object it
got and does the right thing with it.

Thanks to @JacobKochems who found this bug and made me aware of it.
2022-12-01 19:23:17 +01:00
Markus Fisch 527b7a6a59 Use deprecated WiFi API on Android Q
Because WifiManager.getNetworkSuggestions() is only available from
Android R (API level 30) on. So added network suggestions cannot be
queried on Android Q (API level 29) which will be important to allow
removing them individually.
2022-11-30 21:07:05 +01:00
Markus Fisch e9267e4e5a Accept lower case for E, PH and T in WiFi configs
While the spec demands upper case here, it's probably best to
be liberal and accept lower case values as well.
2022-11-30 12:11:29 +01:00
Tom XinandGitHub ac18733368 Update Chinese translation 2022-11-22 12:17:05 +01:00
Markus Fisch 300c3bfd26 Advance version number to 1.56.3 2022-11-21 13:04:19 +01:00
Markus Fisch 6449d9962d Simplify RegEx to recognize URLs
Because the current expression leads to an infinite loop for some
inputs. For example, this string was reported to make the app crash:
com.taobao.arthas.boot.ProcessUtils.findJavaHome(ProcessUtils.java:222)

The problem seems to be somehow related to case insensitivity as the
expression works when insensitivity is removed. Also, the infinite
loop only occurs on an Android device - not in unit tests.

Anyway, the current expression was too complex anyway, and this
simpler one should be good enough.
2022-11-21 12:37:15 +01:00
Markus Fisch 12554e63e2 Remove deep linking intent filter
Was just added to make Lint happy but is no longer necessary.
2022-11-17 19:21:28 +01:00
Markus Fisch af60ee6edb Fix indent in chinese translation 2022-11-17 16:17:20 +01:00
grenagitandGitHub fe31fc6df2 Update french translation 2022-11-17 14:07:36 +01:00
Markus Fisch 6d4f3cafbf Update pt-br translation 2022-11-14 18:06:17 +01:00
Oğuz ErsenandGitHub fa23b8078c Update Turkish translation 2022-11-13 12:49:20 +01:00
jhih_yuandGitHub e3c0fe8857 Update zh_TW 2022-11-11 09:45:58 +01:00
Markus Fisch fa568686b6 Advance version number to 1.56.2 2022-11-09 20:34:08 +01:00
Markus Fisch 304357b43c Update to latest ZXing C++ wrapper
To fix generating text output of 1D barcodes.
2022-11-09 18:27:06 +01:00
Markus Fisch 1e76b14038 Advance version number to 1.56.1 2022-11-08 20:33:08 +01:00
Markus Fisch d0777350a2 Allow pinching to size in device pixels
To allow small codes to be small on screen.

This makes it easier to use a generated barcode in place of a small
printed barcode. There are scanners out there that expect a barcode
to be of a certain (small) size.
2022-11-08 20:28:41 +01:00
Markus Fisch c7c1e74240 Update to latest ZXing C++ wrapper
To fix handling of tab characters.
2022-11-08 20:27:23 +01:00
Markus Fisch c793e1399b Fix view/frame transformation matrix
The view offset needs to be translated first - not last, where the
matrix is no longer in view space.
2022-11-08 20:27:23 +01:00
zmniandGitHub c550a6ff51 Update indonesian translation 2022-11-08 20:27:00 +01:00
solokotandGitHub 05b0f719e0 Updated Russian translation 2022-11-07 18:22:34 +01:00
Markus Fisch 4326df5069 Advance version number to 1.56.0 2022-11-03 19:05:06 +01:00
Markus Fisch ba24287f04 Update to latest ZXing C++ wrapper
To fix getting UTF-8 strings from the JVM.
2022-11-03 19:00:49 +01:00
Markus Fisch bd8f1b17dd Remove double action item for forward/next 2022-11-02 21:57:32 +01:00
Markus Fisch 2c21aeb83a Set FAB background to @null
To silence this warning:

> I/FloatingActionButton: Setting a custom background is not supported.

Details:
https://github.com/material-components/material-components-android/issues/283
2022-11-03 12:30:05 +01:00
Markus Fisch 9ccff808bc Replace properties with functions in Barcode
We should only prefer read-only properties over of functions if the
underlying algorithm…

* does not throw
* is cheap to calculate (or cached on the first run)
* returns the same result over invocations if the object state
  hasn't changed

See:
https://kotlinlang.org/docs/coding-conventions.html#functions-vs-properties

But `ZXing.encodeAs*` may throw and may also not be that cheap to
calculate. So functions are a better fit here.

Also, because these functions will always return the same result,
it makes sense to cache their outputs.
2022-11-02 21:49:08 +01:00
Markus Fisch 32e936dd71 Optimize new drawables with avocado 2022-11-02 21:06:17 +01:00
Markus Fisch 58eebacd4f Use forward arrow for FAB in picking activity
Hopefully this makes it more clear that you have to tap on the
FAB to actually read the found barcode.
2022-11-02 21:06:17 +01:00
Markus Fisch 75b945e842 Remove unused forceCompat preference
Obsolete since we use the ZXing C++ fork.
2022-11-02 21:06:17 +01:00
Markus Fisch a9ea77f74f Add an action item to lock/unlock free rotation
When scanning a barcode from an image.

Free rotation may not always be desirable.
2022-11-02 21:06:17 +01:00
Markus Fisch 3df658165b Support setting fore and background colors
When creating AZTEC, DATA MATRIX or QR Codes.
2022-11-02 21:06:17 +01:00
Markus Fisch 40a6a77b8d Advance version number to 1.55.0 2022-10-30 14:21:01 +01:00
Markus Fisch 301a33a176 Update to latest ZXing C++ wrapper 2022-10-30 14:17:18 +01:00
GiovanniandGitHub 8d6623786c Update an Italian string 2022-10-27 22:59:07 +02:00
Markus Fisch a225eab6f2 Make recreated barcode interactive
This way the barcode can easily be exported, too.

Also live update the data views and clean up the DecodeFragment.
2022-10-26 21:45:06 +02:00
Markus Fisch 9f2efeb001 Advance version number to 1.54.1 2022-10-25 22:51:11 +02:00
Markus Fisch 105c81d409 Treat GS1 and ISO15434 content types as text
And use the HRI formatted text ZxingCpp provides.
2022-10-25 22:05:29 +02:00
Markus Fisch 4e1eb28ca4 Enable auto rotate by default
With ZXingCpp this is hardly noticeable. So enable it for new users.
2022-10-24 22:07:00 +02:00
Markus Fisch b72ed746bf Go back to VIBRATOR_SERVICE for Android 4
Use the deprecated `VIBRATOR_SERVICE` on all versions to fix a
`VerifyError` on Android 4.

For reasons beyond my interests, compiling with `VIBRATOR_MANAGER_SERVICE`
leads to a very cryptic `java.lang.VerifyError: r0/b` on Android 4.
Even though this symbol is never actually used under SDK 31.

This is probably a Proguard/R8 issue, but I don't want to waste more
time just to get rid of the deprecation warning. So let's use the old
`VIBRATOR_SERVICE` and wait for Google to fix their stuff.
2022-10-24 21:57:00 +02:00
solokotandGitHub 1aaee3c85a Update Russian translation 2022-10-24 20:49:37 +02:00
Oğuz ErsenandGitHub eb0218e733 Update Turkish translation 2022-10-23 20:42:01 +02:00
GiovanniandGitHub bef7365f28 Update Italian translation 2022-10-22 21:25:50 +02:00
Markus Fisch c72b6a2e5f Advance version number to 1.54.0 2022-10-21 23:39:30 +02:00
Markus Fisch a7e358852c Complete search engines for fa locale 2022-10-21 23:33:34 +02:00
Markus Fisch 7cf8cbe6d8 Recreate barcode on result fragment
It's sometimes very helpful to easily recover read barcodes.
2022-10-21 23:31:30 +02:00
Markus Fisch e379e55570 Use new Html.fromHtml() on Nougat+ 2022-10-21 22:41:53 +02:00
Markus Fisch a55795a7b6 Use new getParcelable() method on Tiramisu+ 2022-10-21 22:40:34 +02:00
Markus Fisch 83c0cd0293 Only use EXTRA_IS_SENSITIVE on Tiramisu+
And clean up that Pyramid of Death.
2022-10-21 21:23:30 +02:00
Markus Fisch d138148cb8 Refactor string extension functions
And put them where they belong instead of having a dump file.

According to the Kotlin Coding Conventions we should avoid creating
files just to hold extensions.
2022-10-21 21:14:52 +02:00
Markus Fisch c3c08879e0 Move ellipsize() from Toast to Data
Because it's used in more than one place now.
2022-10-21 17:25:17 +02:00
Markus Fisch d0f02faca7 Add german domains for search engines
To open the .de domains for Google, ebay, Amazon, etc.
2022-10-21 19:33:01 +02:00
Markus Fisch c9db3514d1 Add ebay, Amazon and barcodelookup.com
To the list of search engines.
2022-10-21 19:31:35 +02:00
Markus Fisch f2a0e1a392 Add changelogs for F-Droid 2022-10-20 21:39:40 +02:00
Markus Fisch f4de041407 Advance version number to 1.53.1 2022-10-20 09:38:36 +02:00
Markus Fisch 73ba2914e8 Fix proguard configuration for ZXing C++ 2022-10-20 09:37:45 +02:00
Markus Fisch 2907c8c49c Advance version number to 1.53.0 2022-10-19 22:27:21 +02:00
Markus Fisch f28f956a8d Only generate barcode output when required 2022-10-19 21:45:15 +02:00
Markus Fisch 972eb6a0b0 Update to latest ZXing C++ wrapper 2022-10-19 21:43:48 +02:00
Markus Fisch 08bb3f2127 Replace RelativeLayout with LinearLayout
In decoding fragment.

All children were layed out linearly anyway and it's simpler
and more clear this way.
2022-10-19 19:54:33 +02:00
Markus Fisch b28e939f58 Refactor resolveFormat() and make it an extension 2022-10-19 13:04:48 +02:00
solokotandGitHub 2edb8112b7 Update Russian translation 2022-10-19 13:04:06 +02:00
Markus Fisch cf5a6dc8b8 Hide setting a custom locale from API 33 on
Android 13 allows to set per-app language preferences, so this
setting is no longer required from there on.

See:
https://developer.android.com/guide/topics/resources/app-languages
2022-10-15 18:43:40 +02:00
Markus Fisch 3ec6f18fe0 Hide sensitive content from clipboard
At the moment, this affects just the WiFi password.

See:
https://developer.android.com/about/versions/13/behavior-changes-all#copy-sensitive-content
2022-10-15 18:38:14 +02:00
Markus Fisch 3a8f6cb827 Target SDK 33, Android 13 2022-10-15 18:37:49 +02:00
Markus Fisch 65c7fe52ee Fix closing Cursor's below JELLY BEAN
Unfortunately, Cursor cannot be cast to Closeable below API level 16
JELLY BEAN. So we can't just use Kotlin's ".use" extension function
because it would implicitly cast Cursor to a Closeable.

So this adds a simple drop-in replacement that does exactly what ".use"
is doing but without casting Cursor.

Of course, this should be removed as soon as minSDK is increased to at
least JELLY_BEAN.
2022-10-13 23:02:32 +02:00
Markus Fisch 5d3b3eb195 Fix generating a date time string below API 18
Before API level 18, there was no 'H' but only 'k', which was
incorrectly implemented to produce what we now know as 'H'.
2022-10-13 22:39:52 +02:00
Markus Fisch 0e4c2963a5 Catch ParseException when parsing scan dates 2022-10-13 22:38:04 +02:00
Markus Fisch 791c50cd4a Update build tools 2022-10-13 22:37:00 +02:00
Markus Fisch c04b08ab87 Update to latest ZXing C++ wrapper
Which adds a ContentType so we can distinguish between text
and binary content.
2022-10-12 21:47:54 +02:00
Markus Fisch f07c4ac0f4 Update to latest Kotlin and coroutines version 2022-10-11 23:43:30 +02:00
Markus Fisch 05d63bd73f Fix vector image fill color for API < 21
`fillColor` cannot have Android resources below API 21.
2022-10-11 23:37:29 +02:00
Markus Fisch 558fd5212d Remove double support annotation 2022-10-11 23:34:54 +02:00
Markus Fisch b918be76e4 Fix getting version number from database 2022-10-11 23:33:59 +02:00
Markus Fisch 2136a8c73e Show version code for all supported barcodes
And the module count if it's a QR Code.
2022-10-11 23:29:59 +02:00
Markus Fisch 959c6e7d4d Always show QR Code version and remove setting
This comes no longer with a cost so it can be always there.
2022-10-11 23:02:47 +02:00
Markus Fisch 50930d07a6 Show binary data placeholder in edit name dialog
To show something instead of nothing in the dialog title.
Still not perfect, of course.
2022-10-11 22:47:14 +02:00
Markus Fisch 36e7aab27c Update to latest ZXing C++ AAR
Fixes getting HRI formatted result text instead of the real thing.
2022-10-11 22:39:14 +02:00
Markus Fisch bb4fc8ed08 Enable multi-select in history listing 2022-10-11 21:53:15 +02:00
Markus Fisch 7a33ebd1a3 Remove MicroQR from list of writable codes
ZXing C++ doesn't contain a writer for this format, yet.
2022-10-11 20:41:18 +02:00
solokotandGitHub c8444b8935 Update Russian translation 2022-10-10 12:22:06 +02:00
Markus Fisch 4c6d66a4aa Migrate to ZXing-C++
Replace the ZXing Java implementation with the C++ fork.

The C++ fork is faster, actively maintained and supports the MicroQR
Code barcode format.

The original Java implementation is in "Maintenance Mode Only",
what means that no new features or barcodes will be accepted.

Because the C++ fork is much faster, we can now drop RenderScript
which has been deprecated by Google anyway. Also, this removes a lot
of complications. RenderScript was never very robust.
2022-10-09 18:46:50 +02:00
Markus Fisch 39f95a1c04 Remove shortcut extra from EncodeFragment
And make it possible to open the EncodeFragment without content.
2022-10-04 21:19:47 +02:00
Markus Fisch 9e30b108e7 Reformat code and optimize imports
Let Android Studio clean up.
2022-09-29 18:42:00 +02:00
Markus Fisch 1b6b1cefe3 Convert charset for PDF417 in an extension
And run it from PickActivity too to apply this conversion when
scanning from still images too.
2022-09-29 18:39:01 +02:00
Mladen MilinkovicandGitHub b634370a0b Fix PDF-417 UTF-8 text encoding
This fixes reading PDF-417 barcodes containing international UTF-8 characters.
2022-09-29 18:23:07 +02:00
gonandGitHub f32d44c3a1 Update spanish translation 2022-09-27 20:59:12 +02:00
Markus Fisch 2e060d1ca8 Add Persian to list of custom languages
That can be changed in the app independently from the system settings.
2022-09-11 23:01:31 +02:00
Andreas KorbandGitHub 6acdce32f2 Add multidex dependency
Required on some systems/Android Studio versions.
2022-09-10 21:33:04 +02:00
Markus Fisch 092ec694f6 Fix terminating string tag in persian translation 2022-09-10 19:12:03 +02:00
7fed7877a0 Add persian translation
Co-authored-by: eshagh79 <eshagh094@gmail.com>
2022-09-10 19:09:05 +02:00
Markus Fisch b17393d5ef Invert plain text output
Because plain text will most likely end up being black text on a
white background on a mobile device.

But with night mode we can never be sure. So there's an "inverted"
parameter now if the text is bright on a dark background.
2022-08-21 00:36:49 +02:00
Markus Fisch 319ae53b3b Make conditional an argument
To avoid the repetition of the function invocation.

Also make bt a constant variable because it can be.
2022-08-20 19:03:29 +02:00
Markus Fisch 6a47a7e477 Fix indent of new code for generating text output
We're not mixing tabs and spaces.
2022-08-20 18:56:50 +02:00
Tom XinandGitHub 19fb733182 Improve plain text output of generated barcodes
Optimize the 'save as text' function to make its results more recognizable when
printing on the console.
2022-08-20 18:53:43 +02:00
Markus Fisch ce6c6f26d2 Advance version number to 1.52.0 2022-08-10 23:25:46 +02:00
Markus Fisch 3633af5e0a Fix parsing timezone in calendar dates
And add patterns for RFC 822 and ISO 8601 formats.

Before this 'Z' was quoted and therefore just a string in the pattern.
So the time zone was actually never really applied to the resulting date.
Now, it's pattern letter and the resulting date is adjusted accordingly.

This also fixes using dates without a time zone.
2022-08-10 23:07:17 +02:00
87502f7226 Update translation (#280)
* Syntax correction (omitted point)

* Update french translation

Co-authored-by: Grena <grena@grenabox.fr>
2022-06-22 13:30:53 +02:00
Markus Fisch f4af35ad46 Advance version number to 1.51.1 2022-06-16 16:51:39 +02:00
Markus Fisch 60f0d8bd87 Convert result text with ISO_8859_1 encoding
Important to suppress UTF-8 encoding.
2022-06-16 16:45:31 +02:00
Markus Fisch 1ccfcfcb8f Advance version number to 1.51.0 2022-06-16 13:37:44 +02:00
Markus Fisch 213689e9f9 Improve syntax for DP link generation 2022-06-16 13:30:07 +02:00
Markus Fisch 6e2f2cab92 Make drawing functions extensions in DetectorView
Because it's more idiomatic.
2022-06-16 13:20:32 +02:00
Markus Fisch 4b3d745154 Add and improve a few comments 2022-06-16 13:20:12 +02:00
Markus Fisch a2bcd67568 Use logical operator instead of bitwise 2022-06-16 13:19:14 +02:00
Markus Fisch 072eec5306 Simplify setting handleActive flag
And make sure it's false if handlePos is invalid.
2022-06-16 13:17:16 +02:00
ZahnstocherandGitHub d505c6b07d Add stamp tracking number 2022-06-14 18:41:41 +02:00
GiovanniandGitHub dbfbaab030 Update Italian translation 2022-06-14 14:26:07 +02:00
Markus Fisch 3d1402add4 Fix XML for zh-rCN translation 2022-06-12 20:29:20 +02:00
yzqzssandGitHub 1d2bd8d778 Update zh-rCN translation 2022-06-12 20:22:11 +02:00
Markus Fisch 2bb413e3e8 Add tests for MATMSG format 2022-06-07 20:43:15 +02:00
Markus Fisch 75a59bc3e9 Fix setting Intent.EXTRA_EMAIL for MatMsg contents
Remember, this must be an array.
2022-06-06 20:59:03 +02:00
inkhornandGitHub 9a15bf0871 Update ptbr translation including meta data 2022-05-31 20:28:03 +02:00
Markus Fisch 53248fd23d Allow free image rotation in pick activity
To make it easy to recognize barcodes at odd angles.
2022-05-23 23:33:23 +02:00
140 changed files with 3808 additions and 2449 deletions
+93
View File
@@ -1,5 +1,98 @@
# Change Log
## 1.58.2
* Fix parsing WiFi network suggestions
## 1.58.1
* Update zh-rCn translation
* Fix monochrome launcher icon
## 1.58.0
* Improve detection of inverted barcodes
* Optionally allow duplicates in bulk scan
* Add Danish translation
* Update Italian translation
* Update Japanese translation
* Update Russian translation
* Fix charset decoding for PDF 417
* Fix monochrome icon
## 1.57.0
* Add optional audio feedback for scanning
* Allow removing individual WiFi network suggestions
* Recognize incomplete and malformed WiFi barcodes
* Fix using shared text for encoding
* Add Korean language
* Update Chinese translation
* Update Português/Brasil translation
* Update Russian translation
## 1.56.3
* Fix parsing URLs in barcodes
* Update French, Portuguese, Turkish and Taiwan translation
## 1.56.2
* Fix generating 1D barcode text output
## 1.56.1
* Allow pinching a barcode to its generated size
* Fix view/frame transformation matrix
* Fix handling of tab characters
* Update Indonesian translation
* Update Russian translation
## 1.56.0
* Add an action item to lock/unlock free rotation
* Support setting fore and background colors when creating barcodes
* Fix creating barcodes with UTF-8 content
## 1.55.0
* Make recreated barcode interactive
* Update to latest ZXing C++
* Update Italian translation
## 1.54.1
* Update Russian translation
* Update Turkish translation
* Update Italian translation
* Fix handling GS1 and ISO15434 content types
* Fix VerifyError on Android 4
## 1.54.0
* Recreate and show barcode from read contents if possible
* Add ebay, Amazon and barcodelookup.com to search engines
## 1.53.1
* Fix proguard configuration
## 1.53.0
* Migrate to ZXing-C++ and add support for Micro QR Codes
* Multi-select scans in history listing
* Remove preset content for Encode shortcut
* Always show QR Code version and remove setting
* Fix PDF-417 UTF-8 text encoding
* Hide sensitive content from clipboard
* Remove setting a custom language on Android 13+
* Condense text output of generated barcodes
* Update Russian translation
* Update Spanish translation
* Add Persian translation
## 1.52.0
* Fix parsing timezone in calendar dates
* Update French translation
## 1.51.1
* Fix extraction of raw bytes for some barcodes
## 1.51.0
* Add support for Deutsche Post Matrixcode stamp
* Allow free image rotation for scanning from images
* Fix setting TO field in MATMSG format
* Update Italian translation
* Update zh-rCN translation
* Update pt-br translation
## 1.50.0
* Add support for MATMSG format
* Add a setting to show the QR Code version
+1 -1
View File
@@ -17,4 +17,4 @@ Then write a [good commit message][commit_messages] to keep the history
meaningful and useful. One feature, one commit.
[android_best_practices]: https://developer.android.com/distribute/best-practices/develop/
[commit_messages]: https://juffalow.com/other/write-good-git-commit-message
[commit_messages]: https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines
-3
View File
@@ -20,9 +20,6 @@ infer: clean
test:
./gradlew test
cat:
./gradlew test cAT
testview:
adb shell am start -W -a android.intent.action.VIEW -d 'binaryeye://scan'
+8 -3
View File
@@ -12,7 +12,7 @@ hesitate to contact me.
Required to add a WiFi network from a barcode (usually a QR Code).
Before Android Q, this feature requires using
[WifiManager.getConfiguredNetworks][configuredNetworks]
[WifiManager.getConfiguredNetworks][getConfiguredNetworks]
which requires `ACCESS_FINE_LOCATION`.
On Android Q an better, this permission is not requested nor required.
@@ -46,9 +46,13 @@ which requires `CHANGE_WIFI_STATE`.
Required to add a WiFi network from a barcode (usually a QR Code).
Before Android Q, this feature requires using
[WifiManager.getConfiguredNetworks][configuredNetworks]
[WifiManager.getConfiguredNetworks][getConfiguredNetworks]
which requires `ACCESS_WIFI_STATE`.
From Android R, `ACCESS_WIFI_STATE` is required for
[WifiManager.getNetworkSuggestions][getNetworkSuggestions]
which is used to remove individual network suggestions.
[ACCESS_FINE_LOCATION]: https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION
[CAMERA]: https://developer.android.com/reference/android/Manifest.permission#CAMERA
[INTERNET]: https://developer.android.com/reference/android/Manifest.permission#INTERNET
@@ -56,5 +60,6 @@ which requires `ACCESS_WIFI_STATE`.
[WRITE_EXTERNAL_STORAGE]: https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE
[CHANGE_WIFI_STATE]: https://developer.android.com/reference/android/Manifest.permission#CHANGE_WIFI_STATE
[ACCESS_WIFI_STATE]: https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION
[configuredNetworks]: https://developer.android.com/reference/android/net/wifi/WifiManager#getConfiguredNetworks()
[getConfiguredNetworks]: https://developer.android.com/reference/android/net/wifi/WifiManager#getConfiguredNetworks()
[addNetworkSuggestions]: https://developer.android.com/reference/android/net/wifi/WifiManager#addNetworkSuggestions(java.util.List%3Candroid.net.wifi.WifiNetworkSuggestion%3E)
[getNetworkSuggestions]: https://developer.android.com/reference/android/net/wifi/WifiManager#getNetworkSuggestions()
+6 -37
View File
@@ -7,8 +7,8 @@ This one is free, without any ads and open source.
Works in portrait and landscape orientation, can read inverted codes,
comes in Material Design and can also generate barcodes.
Binary Eye uses the [ZXing][zxing] ("Zebra Crossing") barcode scanning
library.
Binary Eye uses the [ZXing-C++][zxing_cpp] ("Zebra Crossing") barcode
scanning library.
## Screenshots
@@ -39,10 +39,10 @@ ZXing can read the following barcode formats:
* [EAN 8][ean_8]
* [EAN 13][ean_13]
* [ITF][itf]
* [MAXICODE][maxicode] (only when unrotated and unskewed, see [77][77],
because of which Binary Eye *cannot* read this barcode)
* [MAXICODE][maxicode] (partial)
* [PDF417][pdf417]
* [QR CODE][qr_code]
* [Micro QR Code][micro_qr_code]
* [RSS 14][rss]
* [RSS EXPANDED][rss]
* [UPC A][upc_a]
@@ -84,7 +84,6 @@ Supported symbols are:
* `RESULT` - scanned content
* `RESULT_BYTES` - raw result as a hex string
* `FORMAT` - barcode format
* `META` - the meta data, if available
### SCAN Intent
@@ -135,37 +134,8 @@ class YourActivity : Activity() {
}
```
## RenderScript
This app uses [RenderScript][rs] to resize and rotate the camera image.
Unfortunately, RenderScript has some nasty gotchas.
### RenderScript.forceCompat()
It's necessary to call `RenderScript.forceCompat()` on some devices/roms.
`RenderScript.forceCompat()` needs to be run before any other RenderScript
function and unfortunately there is no way to know if invoking `forceCompat()`
is necessary or not.
If `RenderScript.forceCompat()` is necessary, a `RSRuntimeException` will
be thrown and the only option is to restart the app, this time with calling
`forceCompat()` first.
Calling `RenderScript.forceCompat()` means the processing is done in
software so you probably don't want to enable it by default.
### 2D barcodes
If you want to fork this and are only interested in reading 2D barcodes
(like QR or Aztec), you may want to remove the custom rotation kernel
altogether as ZXing can read 2D barcodes in any orientation.
This will make your app a bit simpler and saves you from compiling a
custom RenderScript kernel for each architecture you want to support.
[play]: https://play.google.com/store/search?q=barcode%20scanner&c=apps
[zxing]: https://github.com/zxing/zxing
[zxing_cpp]: https://github.com/zxing-cpp/zxing-cpp
[kotlin]: http://kotlinlang.org/
[aztec]: https://en.wikipedia.org/wiki/Aztec_Code
[codabar]: https://en.wikipedia.org/wiki/Codabar
@@ -179,12 +149,11 @@ custom RenderScript kernel for each architecture you want to support.
[maxicode]: https://en.wikipedia.org/wiki/MaxiCode
[pdf417]: https://en.wikipedia.org/wiki/PDF417
[qr_code]: https://en.wikipedia.org/wiki/QR_code
[micro_qr_code]: https://en.wikipedia.org/wiki/QR_code#Micro_QR_code
[rss]: https://en.wikipedia.org/wiki/GS1_DataBar
[upc_a]: https://en.wikipedia.org/wiki/Universal_Product_Code
[upc_e]: https://en.wikipedia.org/wiki/Universal_Product_Code#UPC-E
[upc_ean]: https://en.wikipedia.org/wiki/Universal_Product_Code#EAN-13
[77]: https://github.com/markusfisch/BinaryEye/issues/77
[rs]: https://developer.android.com/guide/topics/renderscript/compute
[start_activity]: https://developer.android.com/reference/android/app/Activity#startActivityForResult(android.content.Intent,%20int)
[on_activity_result]: https://developer.android.com/reference/android/app/Activity#onActivityResult(int,%20int,%20android.content.Intent)
[intent_result]: https://developer.android.com/training/basics/intents/result
+5 -37
View File
@@ -9,19 +9,8 @@ android {
minSdkVersion 9
targetSdkVersion sdk_version
versionCode 97
versionName '1.50.0'
// Required for desugaring.
multiDexEnabled true
// 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'
versionCode 115
versionName '1.58.2'
}
signingConfigs {
@@ -64,39 +53,18 @@ android {
enableSplit = false
}
}
compileOptions {
// To desugar fancy Java features in ZXing 3.4.+ that don't
// work on SDK < 24. See:
// https://github.com/zxing/zxing/issues/1170
coreLibraryDesugaringEnabled true
}
lint {
// Because at the time of writing, even the latest version
// of RenderScript is raising this error no matter if
// renderscriptTargetApi matches targetSdkVersion.
disable 'GradleCompatible'
}
}
dependencies {
androidTestImplementation('com.android.support.test:runner:1.0.2') {
exclude module: 'support-annotations'
}
androidTestImplementation('com.android.support.test:rules:1.0.2') {
exclude module: 'support-annotations'
}
testImplementation 'junit:junit:4.13.2'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
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"
implementation 'com.google.zxing:core:3.5.0'
implementation 'com.github.markusfisch:CameraView:1.9.1'
implementation 'com.github.markusfisch:ScalingImageView:1.3.0'
implementation 'com.github.markusfisch:ScalingImageView:1.4.1'
implementation 'com.github.markusfisch:zxing-cpp:v2.0.0.0'
}
+2 -1
View File
@@ -3,4 +3,5 @@
-dontwarn android.support.v8.**
-keep class android.support.v7.widget.SearchView { *; }
-keep class android.support.v8.renderscript.** { *; }
-keep class de.markusfisch.android.zxingcpp.** { *; }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

@@ -1,107 +0,0 @@
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 android.support.v8.renderscript.RenderScript
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)
class PreprocessorTest {
@Test
fun processSamples() {
val assets = InstrumentationRegistry.getInstrumentation()
.context.assets
val samples = assets.list("samples")
checkNotNull(samples) { "no samples found" }
val pattern = Pattern.compile(
"[0-9]+-([0-9]+)deg.jpg"
)
val rs = RenderScript.create(
InstrumentationRegistry.getTargetContext(),
)
val zxing = Zxing()
for (sample in samples) {
val m = pattern.matcher(sample)
if (!m.find() || m.groupCount() < 1) {
fail("invalid sample: $sample")
}
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(
rs,
frameWidth,
frameHeight,
null
)
val outWidth: Int
val outHeight: Int
val orientation = frameOrientation.toInt()
if (orientation == 90 || orientation == 270) {
preprocessor.resizeAndRotate(frameData)
outWidth = preprocessor.outHeight
outHeight = preprocessor.outWidth
} else {
preprocessor.resizeOnly(frameData)
outWidth = preprocessor.outWidth
outHeight = preprocessor.outHeight
}
val result = zxing.decode(frameData, outWidth, outHeight)
preprocessor.destroy()
checkNotNull(result) { "no barcode found in $sample" }
}
rs.destroy()
}
}
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 (t in 0 until height) {
for (s 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 (t % 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
+1 -11
View File
@@ -12,8 +12,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"
android:maxSdkVersion="28"/>
<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"/>
@@ -64,15 +63,6 @@
<action android:name="com.google.zxing.client.android.SCAN"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:host="markusfisch.de"/>
<data android:pathPrefix="/BinaryEye"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
@@ -39,8 +39,10 @@ abstract class SchemeAction : IAction {
final override fun canExecuteOn(data: ByteArray): Boolean {
val content = String(data)
return if (buildRegex) {
content.matches("""^$scheme://[\w\W]+$""".toRegex(
RegexOption.IGNORE_CASE)
content.matches(
"""^$scheme://[\w\W]+$""".toRegex(
RegexOption.IGNORE_CASE
)
)
} else {
content.startsWith("$scheme://", ignoreCase = true)
@@ -19,31 +19,37 @@ object MatMsgAction : IntentAction() {
context: Context,
data: ByteArray
): Intent? {
val encoded = String(data)
// Allow arbitrary order.
val to = encoded.extractFirst("""[:;]TO:([\w.%@+-]+);""")
val sub = encoded.extractFirst("""[:;]SUB:([^;]+);""")
val body = encoded.extractFirst("""[:;]BODY:([^;]+);""")
val mm = MatMsg(String(data))
// Allow incomplete but not completely missing data.
if (to == null && sub == null && body == null) {
if (mm.isEmpty()) {
return null
}
return Intent(
Intent.ACTION_SENDTO,
Uri.parse("mailto:")
).apply {
to?.let {
putExtra(Intent.EXTRA_EMAIL, to)
mm.to?.let {
putExtra(Intent.EXTRA_EMAIL, arrayOf(mm.to))
}
sub?.let {
putExtra(Intent.EXTRA_SUBJECT, sub)
mm.sub?.let {
putExtra(Intent.EXTRA_SUBJECT, mm.sub)
}
body?.let {
putExtra(Intent.EXTRA_TEXT, body)
mm.body?.let {
putExtra(Intent.EXTRA_TEXT, mm.body)
}
}
}
}
// Public so this can be tested.
class MatMsg(encoded: String) {
// Allow arbitrary order.
val to = encoded.extractFirst("""[:;]TO:([\w.%@+-]+);""")
val sub = encoded.extractFirst("""[:;]SUB:([^;]+);""")
val body = encoded.extractFirst("""[:;]BODY:([^;]+);""")
fun isEmpty() = to == null && sub == null && body == null
}
private fun String.extractFirst(regex: String) =
regex.toRegex().find(this)?.groupValues?.get(1)
@@ -4,9 +4,9 @@ import android.content.Context
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.actions.IAction
import de.markusfisch.android.binaryeye.app.alertDialog
import de.markusfisch.android.binaryeye.app.urlEncode
import de.markusfisch.android.binaryeye.app.prefs
import de.markusfisch.android.binaryeye.content.openUrl
import de.markusfisch.android.binaryeye.net.urlEncode
object OpenOrSearchAction : IAction {
override val iconResId: Int = R.drawable.ic_action_search
@@ -23,7 +23,7 @@ object OpenOrSearchAction : IAction {
url: String,
search: Boolean
) {
if (!context.openUrl(url) && search) {
if (!context.openUrl(url, silent = true) && search) {
openSearch(context, url)
}
}
@@ -4,7 +4,7 @@ import android.content.Context
import android.content.Intent
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.actions.IntentAction
import de.markusfisch.android.binaryeye.app.parseAndNormalizeUri
import de.markusfisch.android.binaryeye.content.parseAndNormalizeUri
object TelAction : IntentAction() {
private val telRegex = """^tel:(\+?[0-9]+)$""".toRegex(
@@ -9,7 +9,6 @@ import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.actions.IntentAction
import de.markusfisch.android.binaryeye.actions.vtype.VTypeParser
import java.util.*
import kotlin.collections.ArrayList
object VCardAction : IntentAction() {
override val iconResId: Int
@@ -1,6 +1,5 @@
package de.markusfisch.android.binaryeye.actions.vtype.vevent
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Build
@@ -47,7 +46,7 @@ object VEventAction : IntentAction() {
dateFormats.simpleFindParse(eventStart.value)?.also {
putExtra(
CalendarContract.EXTRA_EVENT_BEGIN_TIME,
it.localTime()
it.time
)
}
}
@@ -55,37 +54,39 @@ object VEventAction : IntentAction() {
dateFormats.simpleFindParse(eventEnd.value)?.also {
putExtra(
CalendarContract.EXTRA_EVENT_END_TIME,
it.localTime()
it.time
)
}
}
}
}
// We definitely don't wan't the local format.
@SuppressLint("SimpleDateFormat")
private val dateFormats = listOf(
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"),
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"),
SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'"),
SimpleDateFormat("yyyyMMdd'T'HHmmss"),
SimpleDateFormat("yyyy-MM-dd"),
SimpleDateFormat("yyyyMMdd")
)
private fun List<SimpleDateFormat>.simpleFindParse(data: String): Date? {
for (simpleDataFormat in this) {
return simpleDataFormat.simpleParse(data) ?: continue
}
return null
}
private fun SimpleDateFormat.simpleParse(data: String): Date? = try {
this.parse(data)
} catch (e: Exception) {
null
}
}
private fun Date.localTime() = time - timezoneOffset * 60000L
private val dateFormats = listOf(
"yyyy-MM-dd'T'HH:mm:ssXXX",
"yyyy-MM-dd'T'HH:mm:ssZ",
"yyyy-MM-dd'T'HH:mm:ssz",
"yyyy-MM-dd'T'HH:mm:ss",
"yyyyMMdd'T'HHmmssXXX",
"yyyyMMdd'T'HHmmssZ",
"yyyyMMdd'T'HHmmssz",
"yyyyMMdd'T'HHmmss",
"yyyy-MM-dd",
"yyyyMMdd"
)
private fun List<String>.simpleFindParse(date: String): Date? {
for (pattern in this) {
return SimpleDateFormat(
pattern,
Locale.getDefault()
).simpleParse(date) ?: continue
}
return null
}
private fun SimpleDateFormat.simpleParse(date: String): Date? = try {
parse(date)
} catch (e: Exception) {
null
}
@@ -6,9 +6,8 @@ import de.markusfisch.android.binaryeye.actions.IAction
import de.markusfisch.android.binaryeye.content.openUrl
object WebAction : IAction {
private val colloquialRegex = """^(http[s]*://)*([a-z0-9]+[a-z0-9-]*[a-z0-9]+[.])+[a-z]{2,}([?#/]+[\w/=&;._-]*)*$""".toRegex(
RegexOption.IGNORE_CASE
)
private val colloquialRegex =
"^(http[s]*://)*[A-Za-z0-9]{3,}\\.[A-Za-z]{2,}[^ \t\r\n]*$".toRegex()
override val iconResId: Int = R.drawable.ic_action_open
override val titleResId: Int = R.string.open_url
@@ -10,12 +10,6 @@ import android.support.annotation.RequiresApi
import de.markusfisch.android.binaryeye.R
import java.util.*
@RequiresApi(Build.VERSION_CODES.Q)
fun removeNetworkSuggestions(context: Context): Int =
(context.applicationContext.getSystemService(
Context.WIFI_SERVICE
) as WifiManager).removeNetworkSuggestions(listOf())
/**
* Normal:
* WIFI:S:[network SSID];T:<WPA|WEP|nopass|>;P:[network password];H:<true|false|>;;
@@ -50,8 +44,10 @@ object WifiConnector {
passwordBlock?.apply {
invoke(parsedData.password)
}
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
// WifiConfiguration is deprecated in Android Q.
return if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
// WifiConfiguration is deprecated in Android Q but
// because it's only possible in R to query network
// suggestions, we still use the deprecated API on Q.
@Suppress("DEPRECATION")
WifiConfiguration().apply(parsedData)
} else {
@@ -63,33 +59,23 @@ object WifiConnector {
val wifiManager = context.applicationContext.getSystemService(
Context.WIFI_SERVICE
) as WifiManager
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
// WifiConfiguration is deprecated in Android Q.
@Suppress("DEPRECATION")
val wifiConfig = config as WifiConfiguration
if (wifiManager.enableWifi() &&
wifiManager.removeOldNetwork(wifiConfig) &&
wifiManager.enableNewNetwork(wifiConfig)
) {
R.string.wifi_added
} else {
R.string.wifi_config_failed
}
// WifiConfiguration is deprecated in Android Q.
@Suppress("DEPRECATION")
return if ((config is WifiConfiguration &&
wifiManager.enableWifi() &&
wifiManager.removeOldNetwork(config) &&
wifiManager.enableNewNetwork(config)) ||
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
config is WifiNetworkSuggestion.Builder &&
wifiManager.addNetworkFromBuilder(config))
) {
R.string.wifi_added
} else {
val suggestion = (config as WifiNetworkSuggestion.Builder).build()
val suggestions = listOf(suggestion)
// Remove previous conflicting network suggestion.
wifiManager.removeNetworkSuggestions(suggestions)
val result = wifiManager.addNetworkSuggestions(suggestions)
if (result == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
R.string.wifi_added
} else {
R.string.wifi_config_failed
}
R.string.wifi_config_failed
}
}
internal fun parseMap(string: String): Map<String, String>? {
internal fun parseMap(input: String): Map<String, String>? {
// Normally those codes should have the last semicolon, but many
// generators don't add it.
val wifiRegex = """^WIFI:((?:.+?:(?:[^\\;]|\\.)*;)+);?$""".toRegex()
@@ -97,7 +83,7 @@ object WifiConnector {
// and : because many QR Code creators don't escape properly.
val pairRegex = """(.+?):((?:[^\\;]|\\.)*);""".toRegex()
return wifiRegex.matchEntire(
string
input.trimAndTerminate()
)?.groupValues?.get(1)?.let { pairs ->
pairRegex.findAll(pairs).map { pair ->
pair.groupValues[1].uppercase(Locale.US) to pair.groupValues[2]
@@ -126,7 +112,7 @@ object WifiConnector {
requireSdk(Build.VERSION_CODES.JELLY_BEAN_MR2) {
WifiEnterpriseConfig.Eap.NONE
}
} else when (inputMap["E"]) {
} else when (inputMap["E"]?.uppercase()) {
"AKA" -> requireSdk(Build.VERSION_CODES.LOLLIPOP) { WifiEnterpriseConfig.Eap.AKA }
"AKA_PRIME" -> requireSdk(Build.VERSION_CODES.M) { WifiEnterpriseConfig.Eap.AKA_PRIME }
"NONE" -> requireSdk(Build.VERSION_CODES.JELLY_BEAN_MR2) { WifiEnterpriseConfig.Eap.NONE }
@@ -143,7 +129,7 @@ object WifiConnector {
requireSdk(Build.VERSION_CODES.JELLY_BEAN_MR2) {
WifiEnterpriseConfig.Phase2.NONE
}
} else when (inputMap["PH2"]) {
} else when (inputMap["PH2"]?.uppercase()) {
"AKA" -> requireSdk(Build.VERSION_CODES.O) { WifiEnterpriseConfig.Phase2.AKA }
"AKA_PRIME" -> requireSdk(Build.VERSION_CODES.O) { WifiEnterpriseConfig.Phase2.AKA_PRIME }
"GTC" -> requireSdk(Build.VERSION_CODES.JELLY_BEAN_MR2) { WifiEnterpriseConfig.Phase2.GTC }
@@ -179,7 +165,7 @@ object WifiConnector {
data: SimpleDataAccessor
): WifiNetworkSuggestion.Builder? {
try {
when (data.securityType) {
when (data.securityType.uppercase()) {
"WPA", "WPA2" -> {
data.password?.let { setWpa2Passphrase(it) }
}
@@ -240,8 +226,8 @@ object WifiConnector {
fun WifiConfiguration.applySecurity(
data: SimpleDataAccessor
): WifiConfiguration? {
when (data.securityType) {
"", "nopass" -> allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
when (data.securityType.uppercase()) {
"", "NOPASS" -> allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
"WEP" -> @Suppress("DEPRECATION") /* WEP as insecure */ {
passwordWithQuotes?.let {
wepKeys[0] = it
@@ -303,6 +289,27 @@ object WifiConnector {
}
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun WifiManager.addNetworkFromBuilder(
builder: WifiNetworkSuggestion.Builder
): Boolean {
val suggestion = builder.build()
val suggestions = listOf(suggestion)
// Remove previous conflicting network suggestion.
removeNetworkSuggestions(suggestions)
val result = addNetworkSuggestions(suggestions)
return result == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS
}
// Make sure the string ends with a semicolon.
private fun String.trimAndTerminate(): String {
var trimmed = trim()
if (trimmed.isNotEmpty() && trimmed.last() != ';') {
trimmed += ";"
}
return trimmed
}
// Keep possibility of wrongly unescaped \ by explicitly searching
// for special chars.
private val escapedRegex = """\\([\\;,":])""".toRegex()
@@ -7,76 +7,60 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Matrix
import android.graphics.Rect
import android.graphics.RectF
import android.hardware.Camera
import android.media.AudioManager
import android.media.ToneGenerator
import android.net.Uri
import android.os.Bundle
import android.os.Vibrator
import android.support.design.widget.FloatingActionButton
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.support.v8.renderscript.RSRuntimeException
import android.support.v8.renderscript.RenderScript
import android.view.Menu
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
import android.widget.SeekBar
import com.google.zxing.Result
import com.google.zxing.ResultMetadataType
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.adapter.prettifyFormatName
import de.markusfisch.android.binaryeye.app.*
import de.markusfisch.android.binaryeye.content.copyToClipboard
import de.markusfisch.android.binaryeye.content.execShareIntent
import de.markusfisch.android.binaryeye.content.openUrl
import de.markusfisch.android.binaryeye.content.toHexString
import de.markusfisch.android.binaryeye.database.toScan
import de.markusfisch.android.binaryeye.graphics.getFrameToViewMatrix
import de.markusfisch.android.binaryeye.graphics.map
import de.markusfisch.android.binaryeye.graphics.FrameMetrics
import de.markusfisch.android.binaryeye.graphics.mapPosition
import de.markusfisch.android.binaryeye.graphics.setFrameRoi
import de.markusfisch.android.binaryeye.graphics.setFrameToView
import de.markusfisch.android.binaryeye.media.releaseToneGenerators
import de.markusfisch.android.binaryeye.net.sendAsync
import de.markusfisch.android.binaryeye.os.error
import de.markusfisch.android.binaryeye.os.getVibrator
import de.markusfisch.android.binaryeye.os.vibrate
import de.markusfisch.android.binaryeye.rs.Preprocessor
import de.markusfisch.android.binaryeye.net.urlEncode
import de.markusfisch.android.binaryeye.view.errorFeedback
import de.markusfisch.android.binaryeye.view.initSystemBars
import de.markusfisch.android.binaryeye.view.scanFeedback
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 de.markusfisch.android.zxingcpp.ZxingCpp
import de.markusfisch.android.zxingcpp.ZxingCpp.Binarizer
import de.markusfisch.android.zxingcpp.ZxingCpp.DecodeHints
import de.markusfisch.android.zxingcpp.ZxingCpp.Format
import de.markusfisch.android.zxingcpp.ZxingCpp.Result
import java.nio.charset.Charset
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
class CameraActivity : AppCompatActivity() {
private val zxing = Zxing { point ->
point ?: return@Zxing
val matrix = getMappingMatrix() ?: return@Zxing
detectorView.post {
detectorView.update(
matrix.map(
arrayOf(point),
detectorView.coordinates
)
)
}
}
private val frameRoi = Rect()
private val matrix = Matrix()
private lateinit var rs: RenderScript
private lateinit var vibrator: Vibrator
private lateinit var cameraView: CameraView
private lateinit var detectorView: DetectorView
private lateinit var zoomBar: SeekBar
private lateinit var flashFab: FloatingActionButton
private var preprocessor: Preprocessor? = null
private var nativeMappingMatrix: Matrix? = null
private var rotatedMappingMatrix: Matrix? = null
private var recreatePreprocessor = false
private var rotate = false
private var invert = false
private var formatsToRead = setOf<String>()
private var frameMetrics = FrameMetrics()
private var decoding = true
private var returnResult = false
private var returnUrlTemplate: String? = null
@@ -132,9 +116,6 @@ class CameraActivity : AppCompatActivity() {
// custom locale.
setTitle(R.string.scan_code)
rs = RenderScript.create(this)
vibrator = getVibrator()
initSystemBars(this)
setSupportActionBar(findViewById(R.id.toolbar) as Toolbar)
@@ -156,11 +137,10 @@ class CameraActivity : AppCompatActivity() {
override fun onDestroy() {
super.onDestroy()
resetPreProcessor()
fallbackBuffer = null
saveZoom()
detectorView.saveCropHandlePos()
rs.destroy()
releaseToneGenerators()
}
override fun onResume() {
@@ -180,7 +160,7 @@ class CameraActivity : AppCompatActivity() {
private fun updateHints() {
val restriction = restrictFormat
val formats = if (restriction != null) {
formatsToRead = if (restriction != null) {
title = getString(
R.string.scan_format,
prettifyFormatName(restriction)
@@ -190,7 +170,6 @@ class CameraActivity : AppCompatActivity() {
setTitle(R.string.scan_code)
prefs.barcodeFormats
}
zxing.updateHints(prefs.tryHarder, formats)
}
private fun setReturnTarget(intent: Intent?) {
@@ -205,11 +184,6 @@ class CameraActivity : AppCompatActivity() {
}
}
private fun resetPreProcessor() {
preprocessor?.destroy()
preprocessor = null
}
private fun openCamera() {
cameraView.openAsync(
CameraView.findCameraId(
@@ -441,22 +415,42 @@ class CameraActivity : AppCompatActivity() {
}
override fun onCameraReady(camera: Camera) {
// Reset preprocessor to make sure it always fits the current
// frame orientation. Important for landscape to landscape
// orientation changes.
resetPreProcessor()
val frameWidth = cameraView.frameWidth
val frameHeight = cameraView.frameHeight
val frameOrientation = cameraView.frameOrientation
frameMetrics = FrameMetrics(
cameraView.frameWidth,
cameraView.frameHeight,
cameraView.frameOrientation
)
updateFrameRoiAndMappingMatrix()
ignoreNext = null
decoding = true
// These settings can't change while the camera is open.
val decodeHints = DecodeHints(
tryHarder = prefs.tryHarder,
tryRotate = prefs.autoRotate,
tryInvert = true,
tryDownscale = true
)
var useLocalAverage = false
camera.setPreviewCallback { frameData, _ ->
if (decoding) {
decodeFrame(
useLocalAverage = useLocalAverage xor true
ZxingCpp.readByteArray(
frameData,
frameWidth,
frameHeight,
frameOrientation
frameMetrics.width,
frameRoi.left, frameRoi.top,
frameRoi.width(), frameRoi.height(),
frameMetrics.orientation,
decodeHints.apply {
// By default, ZXing uses LOCAL_AVERAGE, but
// this does not work well with inverted
// barcodes on low-contrast backgrounds.
binarizer = if (useLocalAverage) {
Binarizer.LOCAL_AVERAGE
} else {
Binarizer.GLOBAL_HISTOGRAM
}
formats = formatsToRead.joinToString()
}
)?.let { result ->
if (result.text != ignoreNext) {
postResult(result)
@@ -526,12 +520,23 @@ class CameraActivity : AppCompatActivity() {
}
detectorView.onRoiChanged = {
decoding = true
recreatePreprocessor = true
updateFrameRoiAndMappingMatrix()
}
detectorView.setPaddingFromWindowInsets()
detectorView.restoreCropHandlePos()
}
private fun updateFrameRoiAndMappingMatrix() {
val viewRect = cameraView.previewRect
val viewRoi = if (detectorView.roi.width() < 1) {
viewRect
} else {
detectorView.roi
}
frameRoi.setFrameRoi(frameMetrics, viewRect, viewRoi)
matrix.setFrameToView(frameMetrics, viewRect, viewRoi)
}
private fun updateFlashFab(unavailable: Boolean) {
if (unavailable) {
flashFab.setImageResource(R.drawable.ic_action_create)
@@ -560,162 +565,15 @@ class CameraActivity : AppCompatActivity() {
}
}
private fun decodeFrame(
frameData: ByteArray?,
frameWidth: Int,
frameHeight: Int,
frameOrientation: Int
): Result? {
frameData ?: return null
rotate = if (prefs.autoRotate) {
rotate xor true
} else {
invert = invert xor true
isPortrait(frameOrientation)
}
return try {
if (recreatePreprocessor) {
resetPreProcessor()
recreatePreprocessor = false
}
val pp = preprocessor ?: createPreprocessorAndMapping(
frameWidth,
frameHeight,
frameOrientation
)
val w: Int
val h: Int
if (rotate) {
pp.resizeAndRotate(frameData)
w = pp.outHeight
h = pp.outWidth
} else {
invert = invert xor true
pp.resizeOnly(frameData)
w = pp.outWidth
h = pp.outHeight
}
preprocessor = pp
zxing.decode(frameData, w, h, invert)
} catch (e: RSRuntimeException) {
prefs.forceCompat = prefs.forceCompat xor true
// Now the only option is to restart the app because
// RenderScript.forceCompat() needs to be called before
// RenderScript is initialized.
restartApp()
null
}
}
private fun createPreprocessorAndMapping(
frameWidth: Int,
frameHeight: Int,
frameOrientation: Int
): Preprocessor {
val frameRoi = calculateFrameRect(
frameWidth,
frameHeight,
frameOrientation
)
val pp = Preprocessor(
rs,
frameWidth,
frameHeight,
frameRoi
)
val viewRect = if (frameRoi != null) {
detectorView.roi
} else {
cameraView.previewRect
}
nativeMappingMatrix = getFrameToViewMatrix(
pp.outWidth,
pp.outHeight,
frameOrientation,
viewRect
)
rotatedMappingMatrix = getFrameToViewMatrix(
pp.outHeight,
pp.outWidth,
(frameOrientation - 90 + 360) % 360,
viewRect
)
return pp
}
private fun calculateFrameRect(
frameWidth: Int,
frameHeight: Int,
frameOrientation: Int
): Rect? {
val viewRoi = detectorView.roi
return if (
viewRoi.width() == 0 ||
viewRoi.height() == 0
) {
null
} else {
// 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(
previewLeft + viewRoi.left,
previewTop + viewRoi.top,
previewLeft + viewRoi.right,
previewTop + viewRoi.bottom
)
val previewRectWidth = previewRect.width().toFloat()
val previewRectHeight = previewRect.height().toFloat()
val normalizedRoi = RectF(
previewRoi.left.toFloat() / previewRectWidth,
previewRoi.top.toFloat() / previewRectHeight,
previewRoi.right.toFloat() / previewRectWidth,
previewRoi.bottom.toFloat() / previewRectHeight
)
// Since the ROI is always centered and symmetric, we don't
// need to distinguish between 0 and 180 or 90 and 270 degree.
val errectedRoi = if (isPortrait(frameOrientation)) {
RectF(
normalizedRoi.top,
normalizedRoi.left,
normalizedRoi.bottom,
normalizedRoi.right
)
} else {
normalizedRoi
}
Rect(
(errectedRoi.left * frameWidth.toFloat()).roundToInt(),
(errectedRoi.top * frameHeight.toFloat()).roundToInt(),
(errectedRoi.right * frameWidth.toFloat()).roundToInt(),
(errectedRoi.bottom * frameHeight.toFloat()).roundToInt()
)
}
}
private fun postResult(result: Result) {
// Get matrix for the current rotate value.
val matrix = getMappingMatrix()
val resultPoints = result.resultPoints
if (matrix == null ||
resultPoints == null ||
resultPoints.isEmpty()
) {
return
}
cameraView.post {
detectorView.update(
matrix.map(
resultPoints,
matrix.mapPosition(
result.position,
detectorView.coordinates
)
)
vibrator.vibrate()
scanFeedback()
val returnUri = returnUrlTemplate?.let {
try {
completeUrl(it, result)
@@ -738,7 +596,6 @@ class CameraActivity : AppCompatActivity() {
showResult(
this@CameraActivity,
result,
vibrator,
bulkMode
)
// If this app was invoked via a deep link but without
@@ -750,7 +607,9 @@ class CameraActivity : AppCompatActivity() {
}
}
if (bulkMode) {
ignoreNext = result.text
if (prefs.ignoreConsecutiveDuplicates) {
ignoreNext = result.text
}
if (prefs.showToastInBulkMode) {
toast(result.text)
}
@@ -761,12 +620,6 @@ class CameraActivity : AppCompatActivity() {
}
}
private fun getMappingMatrix() = if (rotate) {
rotatedMappingMatrix
} else {
nativeMappingMatrix
}
companion object {
private const val PICK_FILE_RESULT_CODE = 1
private const val ZOOM_MAX = "zoom_max"
@@ -780,7 +633,6 @@ class CameraActivity : AppCompatActivity() {
fun showResult(
activity: Activity,
result: Result,
vibrator: Vibrator,
bulkMode: Boolean = false,
) {
if (prefs.copyImmediately) {
@@ -802,10 +654,7 @@ fun showResult(
prefs.sendScanType
) { code, body ->
if (code == null || code < 200 || code > 299) {
vibrator.error()
if (!activity.isSilent()) {
beepBeepBeep()
}
activity.errorFeedback()
}
if (body != null && body.isNotEmpty()) {
activity.toast(body)
@@ -821,45 +670,14 @@ fun showResult(
}
}
fun getReturnIntent(result: Result): Intent {
val intent = Intent()
intent.putExtra("SCAN_RESULT", result.text)
intent.putExtra(
"SCAN_RESULT_FORMAT",
result.barcodeFormat.toString()
)
if (result.rawBytes?.isNotEmpty() == true) {
intent.putExtra("SCAN_RESULT_BYTES", result.rawBytes)
private fun getReturnIntent(result: Result) = Intent().apply {
putExtra("SCAN_RESULT", result.text)
putExtra("SCAN_RESULT_FORMAT", result.format)
putExtra("SCAN_RESULT_ORIENTATION", result.orientation)
putExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL", result.ecLevel)
if (result.rawBytes.isNotEmpty()) {
putExtra("SCAN_RESULT_BYTES", result.rawBytes)
}
result.resultMetadata?.let { metadata ->
metadata[ResultMetadataType.ORIENTATION]?.let {
intent.putExtra(
"SCAN_RESULT_ORIENTATION",
it.toString()
)
}
metadata[ResultMetadataType.ERROR_CORRECTION_LEVEL]?.let {
intent.putExtra(
"SCAN_RESULT_ERROR_CORRECTION_LEVEL",
it.toString()
)
}
metadata[ResultMetadataType.UPC_EAN_EXTENSION]?.let {
intent.putExtra(
"SCAN_RESULT_UPC_EAN_EXTENSION",
it.toString()
)
}
metadata[ResultMetadataType.BYTE_SEGMENTS]?.let {
var i = 0
@Suppress("UNCHECKED_CAST")
for (seg in it as Iterable<ByteArray>) {
intent.putExtra("SCAN_RESULT_BYTE_SEGMENTS_$i", seg)
++i
}
}
}
return intent
}
private fun String.isReturnUrl() = listOf(
@@ -871,33 +689,10 @@ private fun String.isReturnUrl() = listOf(
private fun completeUrl(urlTemplate: String, result: Result) = Uri.parse(
urlTemplate
.replace("{RESULT}", result.text.urlEncode())
.replace("{RESULT_BYTES}", result.rawBytes?.toHexString() ?: "")
.replace("{RESULT_BYTES}", result.rawBytes.toHexString())
.replace(
"{FORMAT}", result.barcodeFormat.toString().urlEncode()
)
.replace(
"{META}", result.resultMetadata?.toString()?.urlEncode() ?: ""
"{FORMAT}", result.format.urlEncode()
)
// And support {CODE} from the old ZXing app, too.
.replace("{CODE}", result.text.urlEncode())
)
private fun Context.isSilent(): Boolean {
val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager
return when (am.ringerMode) {
AudioManager.RINGER_MODE_SILENT,
AudioManager.RINGER_MODE_VIBRATE -> true
else -> false
}
}
private fun beepBeepBeep() {
ToneGenerator(AudioManager.STREAM_ALARM, 100).startTone(
ToneGenerator.TONE_CDMA_CONFIRM,
1000
)
}
private fun isPortrait(
orientation: Int
) = orientation == 90 || orientation == 270
@@ -81,7 +81,7 @@ class MainActivity : AppCompatActivity() {
intent.hasExtra(PREFERENCES) -> PreferencesFragment()
intent.hasExtra(HISTORY) -> HistoryFragment()
intent.hasExtra(ENCODE) -> EncodeFragment.newInstance(
intent.getStringExtra(ENCODE)!!
intent.getStringExtra(ENCODE)
)
intent.hasExtra(DECODED) -> DecodeFragment.newInstance(
intent.getParcelableExtra(DECODED)!!
@@ -3,46 +3,52 @@ package de.markusfisch.android.binaryeye.activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Matrix
import android.graphics.Rect
import android.graphics.RectF
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
import android.os.Vibrator
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.support.v8.renderscript.RenderScript
import android.view.Menu
import android.view.MenuItem
import com.google.zxing.Result
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.app.applyLocale
import de.markusfisch.android.binaryeye.app.prefs
import de.markusfisch.android.binaryeye.graphics.crop
import de.markusfisch.android.binaryeye.graphics.fixTransparency
import de.markusfisch.android.binaryeye.graphics.loadImageUri
import de.markusfisch.android.binaryeye.graphics.mapResultToView
import de.markusfisch.android.binaryeye.os.getVibrator
import de.markusfisch.android.binaryeye.os.vibrate
import de.markusfisch.android.binaryeye.rs.fixTransparency
import de.markusfisch.android.binaryeye.view.colorSystemAndToolBars
import de.markusfisch.android.binaryeye.view.initSystemBars
import de.markusfisch.android.binaryeye.view.recordToolbarHeight
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
import de.markusfisch.android.binaryeye.graphics.mapPosition
import de.markusfisch.android.binaryeye.media.releaseToneGenerators
import de.markusfisch.android.binaryeye.view.*
import de.markusfisch.android.binaryeye.widget.CropImageView
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.zxingcpp.ZxingCpp
import de.markusfisch.android.zxingcpp.ZxingCpp.Binarizer
import de.markusfisch.android.zxingcpp.ZxingCpp.DecodeHints
import de.markusfisch.android.zxingcpp.ZxingCpp.Result
import kotlinx.coroutines.*
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
class PickActivity : AppCompatActivity() {
private val zxing = Zxing()
private val matrix = Matrix()
private val parentJob = Job()
private val scope = CoroutineScope(Dispatchers.IO + parentJob)
private val decodeHints = DecodeHints(
tryHarder = true,
tryRotate = true,
tryInvert = true,
tryDownscale = true,
formats = prefs.barcodeFormats.joinToString()
)
private lateinit var rs: RenderScript
private lateinit var vibrator: Vibrator
private lateinit var cropImageView: CropImageView
private lateinit var detectorView: DetectorView
private lateinit var freeRotationItem: MenuItem
private var result: Result? = null
@@ -59,13 +65,6 @@ class PickActivity : AppCompatActivity() {
// locale.
setTitle(R.string.pick_code_to_scan)
zxing.updateHints(
true,
prefs.barcodeFormats
)
rs = RenderScript.create(this)
vibrator = getVibrator()
initSystemBars(this)
val toolbar = findViewById(R.id.toolbar) as Toolbar
recordToolbarHeight(toolbar)
@@ -75,7 +74,7 @@ class PickActivity : AppCompatActivity() {
colorSystemAndToolBars(this@PickActivity)
}
val bitmap = fixTransparency(rs, getBitmapFromIntent())
val bitmap = getBitmapFromIntent()?.fixTransparency()
if (bitmap == null) {
applicationContext.toast(R.string.error_no_content)
finish()
@@ -84,6 +83,7 @@ class PickActivity : AppCompatActivity() {
cropImageView = findViewById(R.id.image) as CropImageView
cropImageView.restrictTranslation = false
cropImageView.freeRotation = prefs.freeRotation
cropImageView.setImageBitmap(bitmap)
cropImageView.onScan = {
scanWithinBounds(bitmap)
@@ -116,38 +116,45 @@ class PickActivity : AppCompatActivity() {
}
private fun scanWithinBounds(bitmap: Bitmap) {
val roi = Rect(detectorView.roi)
val rectInView = if (roi.width() < 1) {
val viewRoi = if (detectorView.roi.width() < 1) {
cropImageView.getBoundsRect()
} else {
roi
detectorView.roi
}
val imageRect = cropImageView.mappedRect
val rectInImage = normalizeRoi(imageRect, rectInView)
val mappedRect = cropImageView.mappedRect
val cropped = bitmap.crop(
rectInImage,
cropImageView.imageRotation
getNormalizedRoi(mappedRect, viewRoi),
cropImageView.imageRotation,
cropImageView.pivotX,
cropImageView.pivotY
) ?: return
val croppedInView = Rect(
max(viewRoi.left, mappedRect.left.roundToInt()),
max(viewRoi.top, mappedRect.top.roundToInt()),
min(viewRoi.right, mappedRect.right.roundToInt()),
min(viewRoi.bottom, mappedRect.bottom.roundToInt())
)
matrix.apply {
setScale(
croppedInView.width().toFloat() / cropped.width,
croppedInView.height().toFloat() / cropped.height
)
postTranslate(
croppedInView.left.toFloat(),
croppedInView.top.toFloat()
)
}
scope.launch {
result = zxing.decodePositiveNegative(cropped)
result?.let {
cropped.decode()?.let {
withContext(Dispatchers.Main) {
if (isFinishing) {
return@withContext
}
vibrator.vibrate()
val rc = Rect()
imageRect.round(rc)
if (!rectInView.intersect(rc)) {
return@withContext
}
result = it
scanFeedback()
detectorView.update(
mapResultToView(
cropped.width,
cropped.height,
0,
rectInView,
it.resultPoints,
matrix.mapPosition(
it.position,
detectorView.coordinates
)
)
@@ -156,15 +163,38 @@ class PickActivity : AppCompatActivity() {
}
}
// By default, ZXing uses LOCAL_AVERAGE, but this does not work
// well with inverted barcodes on low-contrast backgrounds.
private fun Bitmap.decode() = ZxingCpp.readBitmap(
this,
0, 0,
width, height,
0,
decodeHints.apply {
binarizer = Binarizer.LOCAL_AVERAGE
}
) ?: ZxingCpp.readBitmap(
this,
0, 0,
width, height,
0,
decodeHints.apply {
binarizer = Binarizer.GLOBAL_HISTOGRAM
}
)
override fun onDestroy() {
super.onDestroy()
detectorView.saveCropHandlePos()
rs.destroy()
parentJob.cancel()
releaseToneGenerators()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.activity_pick, menu)
freeRotationItem = menu.findItem(R.id.toggle_free).apply {
updateFreeRotationIcon()
}
return true
}
@@ -174,10 +204,26 @@ class PickActivity : AppCompatActivity() {
rotateClockwise()
true
}
R.id.toggle_free -> {
prefs.freeRotation = prefs.freeRotation xor true
cropImageView.freeRotation = prefs.freeRotation
freeRotationItem.updateFreeRotationIcon()
true
}
else -> super.onOptionsItemSelected(item)
}
}
private fun MenuItem.updateFreeRotationIcon() {
setIcon(
if (prefs.freeRotation) {
R.drawable.ic_action_rotation_unlocked
} else {
R.drawable.ic_action_rotation_locked
}
)
}
private fun rotateClockwise() {
cropImageView.imageRotation = cropImageView.imageRotation + 90 % 360
}
@@ -197,7 +243,7 @@ class PickActivity : AppCompatActivity() {
private fun showResult() {
val r = result
if (r != null) {
showResult(this, r, vibrator)
showResult(this, r)
finish()
} else {
applicationContext.toast(R.string.no_barcode_found)
@@ -205,7 +251,7 @@ class PickActivity : AppCompatActivity() {
}
}
private fun normalizeRoi(imageRect: RectF, roi: Rect): RectF {
private fun getNormalizedRoi(imageRect: RectF, roi: Rect): RectF {
val w = imageRect.width()
val h = imageRect.height()
return RectF(
@@ -3,7 +3,6 @@ package de.markusfisch.android.binaryeye.activity
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import de.markusfisch.android.binaryeye.app.setRestartCount
class SplashActivity : AppCompatActivity() {
override fun onCreate(state: Bundle?) {
@@ -13,7 +12,6 @@ class SplashActivity : AppCompatActivity() {
// because that would happen after the app is fully
// initialized what is too late.
intent?.setRestartCount()
startActivity(Intent(applicationContext, CameraActivity::class.java))
finish()
}
@@ -2,6 +2,7 @@ package de.markusfisch.android.binaryeye.adapter
import android.content.Context
import android.database.Cursor
import android.support.v4.content.ContextCompat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -10,41 +11,71 @@ import android.widget.TextView
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.database.Database
import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
class ScansAdapter(context: Context, cursor: Cursor) :
CursorAdapter(context, cursor, false) {
var selectedScanId = 0L
var selectedScanPosition = -1
private val idIndex = cursor.getColumnIndex(Database.SCANS_ID)
private val timeIndex = cursor.getColumnIndex(Database.SCANS_DATETIME)
private val nameIndex = cursor.getColumnIndex(Database.SCANS_NAME)
private val contentIndex = cursor.getColumnIndex(Database.SCANS_CONTENT)
private val formatIndex = cursor.getColumnIndex(Database.SCANS_FORMAT)
private val selections = mutableMapOf<Long, Int>()
private val selectedColor = ContextCompat.getColor(
context, R.color.selected_row
)
fun select(id: Long, position: Int) {
selectedScanId = id
selectedScanPosition = position
fun select(view: View, id: Long, position: Int) {
view.select(
if (selections[id] == null) {
selections[id] = position
true
} else {
selections.remove(id)
false
}
)
}
fun clearSelection() {
selectedScanId = 0L
selectedScanPosition = -1
selections.clear()
}
fun getSelectedContent() = if (selectedScanPosition < 0) {
null
} else {
val cursor = getItem(selectedScanPosition)
if (cursor is Cursor) {
cursor.getString(contentIndex)
} else {
null
fun forSelection(callback: (Long, Int) -> Unit) {
selections.forEach {
callback.invoke(it.key, it.value)
}
}
fun getSelectedIds(): List<Long> = mutableListOf<Long>().apply {
forSelection { id, _ ->
add(id)
}
}
fun getSelectedContent(separator: String): String {
val sb = StringBuilder()
forSelection { _, position ->
getContent(position)?.let {
if (sb.isNotEmpty()) {
sb.append(separator)
}
sb.append(it)
}
}
return sb.toString()
}
fun getName(
position: Int
) = (getItem(position) as Cursor?)?.getString(nameIndex)
fun getContent(
position: Int
) = (getItem(position) as Cursor?)?.getString(contentIndex)
override fun newView(
context: Context,
cursor: Cursor,
@@ -78,13 +109,17 @@ class ScansAdapter(context: Context, cursor: Cursor) :
)
formatView.text = prettifyFormatName(cursor.getString(formatIndex))
}
// view.isSelected needs to be put on the queue to work.
val selected = cursor.getLong(idIndex) == selectedScanId
val selected = selections[cursor.getLong(idIndex)] != null
view.post {
view.isSelected = selected
// Needs to be put on the queue to work.
view.select(selected)
}
}
private fun View.select(selected: Boolean) {
setBackgroundColor(if (selected) selectedColor else 0)
}
private fun getViewHolder(
view: View
): ViewHolder = view.tag as ViewHolder? ?: ViewHolder(
@@ -105,11 +140,15 @@ class ScansAdapter(context: Context, cursor: Cursor) :
fun prettifyFormatName(format: String) = format.replace("_", " ")
private fun formatDateTime(rfc: String): String {
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).parse(rfc)?.let {
return DateFormat.getDateTimeInstance(
DateFormat.LONG,
DateFormat.SHORT
).format(it)
try {
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).parse(rfc)?.let {
return DateFormat.getDateTimeInstance(
DateFormat.LONG,
DateFormat.SHORT
).format(it)
}
} catch (e: ParseException) {
// Ignore and fall through.
}
return rfc
}
@@ -1,7 +1,7 @@
package de.markusfisch.android.binaryeye.app
import android.content.Context
import android.app.AlertDialog
import android.content.Context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlin.coroutines.resume
@@ -1,21 +1,16 @@
package de.markusfisch.android.binaryeye.app
import android.support.multidex.MultiDexApplication;
import android.support.v8.renderscript.RenderScript
import android.app.Application
import de.markusfisch.android.binaryeye.database.Database
import de.markusfisch.android.binaryeye.preference.Preferences
val db = Database()
val prefs = Preferences()
class BinaryEyeApp : MultiDexApplication() {
class BinaryEyeApp : Application() {
override fun onCreate() {
super.onCreate()
db.open(this)
prefs.init(this)
if (prefs.forceCompat) {
RenderScript.forceCompat()
}
}
}
@@ -1,30 +0,0 @@
package de.markusfisch.android.binaryeye.app
import android.net.Uri
import android.os.Build
import java.io.UnsupportedEncodingException
import java.net.URLEncoder
private val nonPrintable = "[\\x00-\\x08\\x0e-\\x1f]".toRegex()
fun String.hasNonPrintableCharacters() = nonPrintable.containsMatchIn(this)
private val nonAlNum = "[^a-zA-Z0-9]".toRegex()
private val multipleDots = "[…]+".toRegex()
fun String.foldNonAlNum() = replace(nonAlNum, "")
.replace(multipleDots, "")
fun String.urlEncode(): String = try {
URLEncoder.encode(this, "UTF-8")
} catch (e: UnsupportedEncodingException) {
this
}
fun String.parseAndNormalizeUri(): Uri = Uri.parse(this).let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
it.normalizeScheme()
} else {
it
}
}
fun ByteArray.toHexString() = joinToString("") { "%02X".format(it) }
@@ -1,24 +0,0 @@
package de.markusfisch.android.binaryeye.app
import android.app.Activity
import android.content.Intent
import de.markusfisch.android.binaryeye.activity.SplashActivity
private const val RESTART_COUNT = "restart_count"
private var restartCount = 0
fun Intent.setRestartCount() {
restartCount = getIntExtra(RESTART_COUNT, restartCount)
}
fun Activity.restartApp() {
if (restartCount < 3) {
startActivity(Intent(this, SplashActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(RESTART_COUNT, ++restartCount)
})
finish()
}
Runtime.getRuntime().exit(0)
}
@@ -1,17 +1,37 @@
package de.markusfisch.android.binaryeye.content
import android.content.ClipData
import android.content.ClipDescription
import android.content.Context
import android.os.Build
import android.os.PersistableBundle
fun Context.copyToClipboard(text: String) {
fun Context.copyToClipboard(text: String, isSensitive: Boolean = false) {
val service = getSystemService(Context.CLIPBOARD_SERVICE)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
@Suppress("DEPRECATION")
(service as android.text.ClipboardManager).text = text
} else {
(service as android.content.ClipboardManager).setPrimaryClip(
ClipData.newPlainText("plain text", text)
ClipData.newPlainText("plain text", text).apply {
setSensitive(isSensitive)
}
)
}
}
}
private fun ClipData.setSensitive(isSensitive: Boolean) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
description.extras = PersistableBundle().apply {
putBoolean(EXTRA_IS_SENSITIVE, isSensitive)
}
}
}
private val EXTRA_IS_SENSITIVE = if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
) {
ClipDescription.EXTRA_IS_SENSITIVE
} else {
"android.content.extra.IS_SENSITIVE"
}
@@ -0,0 +1,3 @@
package de.markusfisch.android.binaryeye.content
fun ByteArray.toHexString() = joinToString("") { "%02X".format(it) }
@@ -8,7 +8,6 @@ import android.os.Build
import android.support.v4.content.FileProvider
import de.markusfisch.android.binaryeye.BuildConfig
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.app.parseAndNormalizeUri
import de.markusfisch.android.binaryeye.widget.toast
import java.io.File
@@ -36,11 +35,22 @@ fun Context.startIntent(intent: Intent): Boolean = try {
false
}
fun Context.openUrl(url: String): Boolean = openUri(url.parseAndNormalizeUri())
fun Context.openUrl(url: String, silent: Boolean = false): Boolean {
val intent = Intent(Intent.ACTION_VIEW, url.parseAndNormalizeUri())
return if (silent) {
startIntent(intent)
} else {
execShareIntent(intent)
}
}
fun Context.openUri(uri: Uri): Boolean = execShareIntent(
Intent(Intent.ACTION_VIEW, uri)
)
fun String.parseAndNormalizeUri(): Uri = Uri.parse(this).let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
it.normalizeScheme()
} else {
it
}
}
fun Context.shareText(text: String, mimeType: String = "text/plain") {
execShareIntent(Intent(Intent.ACTION_SEND).apply {
@@ -2,7 +2,7 @@ package de.markusfisch.android.binaryeye.database
import android.content.Context
import android.database.Cursor
import de.markusfisch.android.binaryeye.app.toHexString
import de.markusfisch.android.binaryeye.content.toHexString
import de.markusfisch.android.binaryeye.io.writeExternalFile
import java.io.ByteArrayOutputStream
import java.io.OutputStream
@@ -34,13 +34,14 @@ private fun exportCsv(
Database.SCANS_FORMAT,
Database.SCANS_CONTENT,
Database.SCANS_ERROR_CORRECTION_LEVEL,
Database.SCANS_ISSUE_NUMBER,
Database.SCANS_ORIENTATION,
Database.SCANS_OTHER_META_DATA,
Database.SCANS_PDF417_EXTRA_METADATA,
Database.SCANS_POSSIBLE_COUNTRY,
Database.SCANS_SUGGESTED_PRICE,
Database.SCANS_UPC_EAN_EXTENSION
Database.SCANS_VERSION,
Database.SCANS_SEQUENCE_SIZE,
Database.SCANS_SEQUENCE_INDEX,
Database.SCANS_SEQUENCE_ID,
Database.SCANS_GTIN_COUNTRY,
Database.SCANS_GTIN_ADD_ON,
Database.SCANS_GTIN_PRICE,
Database.SCANS_GTIN_ISSUE_NUMBER
)
val indices = columns.map {
cursor.getColumnIndex(it)
@@ -2,6 +2,25 @@ package de.markusfisch.android.binaryeye.database
import android.database.Cursor
// Overwrite Kotlin's ".use" function for Cursor because Cursor cannot
// be cast to Closeable below API level 16. This should be removed when
// the minSDK is increased to at least JELLY_BEAN (16).
inline fun <R> Cursor.use(block: (Cursor) -> R): R = try {
block.invoke(this)
} finally {
close()
}
fun Cursor.getInt(name: String): Int {
val idx = getColumnIndex(name)
return if (idx < 0) 0 else getInt(idx)
}
fun Cursor.getLong(name: String): Long {
val idx = getColumnIndex(name)
return if (idx < 0) 0L else getLong(idx)
}
fun Cursor.getString(name: String): String {
val idx = getColumnIndex(name)
return if (idx < 0) "" else getString(idx) ?: ""
@@ -11,8 +30,3 @@ fun Cursor.getBlob(name: String): ByteArray? {
val idx = getColumnIndex(name)
return if (idx < 0) null else getBlob(idx)
}
fun Cursor.getLong(name: String): Long {
val idx = getColumnIndex(name)
return if (idx < 0) 0L else getLong(idx)
}
@@ -36,13 +36,14 @@ class Database {
$SCANS_RAW,
$SCANS_FORMAT,
$SCANS_ERROR_CORRECTION_LEVEL,
$SCANS_ISSUE_NUMBER,
$SCANS_ORIENTATION,
$SCANS_OTHER_META_DATA,
$SCANS_PDF417_EXTRA_METADATA,
$SCANS_POSSIBLE_COUNTRY,
$SCANS_SUGGESTED_PRICE,
$SCANS_UPC_EAN_EXTENSION
$SCANS_VERSION,
$SCANS_SEQUENCE_SIZE,
$SCANS_SEQUENCE_INDEX,
$SCANS_SEQUENCE_ID,
$SCANS_GTIN_COUNTRY,
$SCANS_GTIN_ADD_ON,
$SCANS_GTIN_PRICE,
$SCANS_GTIN_ISSUE_NUMBER
FROM $SCANS
${getWhereClause(query)}
ORDER BY $SCANS_DATETIME DESC
@@ -77,13 +78,14 @@ class Database {
$SCANS_RAW,
$SCANS_FORMAT,
$SCANS_ERROR_CORRECTION_LEVEL,
$SCANS_ISSUE_NUMBER,
$SCANS_ORIENTATION,
$SCANS_OTHER_META_DATA,
$SCANS_PDF417_EXTRA_METADATA,
$SCANS_POSSIBLE_COUNTRY,
$SCANS_SUGGESTED_PRICE,
$SCANS_UPC_EAN_EXTENSION
$SCANS_VERSION,
$SCANS_SEQUENCE_SIZE,
$SCANS_SEQUENCE_INDEX,
$SCANS_SEQUENCE_ID,
$SCANS_GTIN_COUNTRY,
$SCANS_GTIN_ADD_ON,
$SCANS_GTIN_PRICE,
$SCANS_GTIN_ISSUE_NUMBER
FROM $SCANS
WHERE $SCANS_ID = ?
""".trimMargin(), arrayOf("$id")
@@ -94,13 +96,14 @@ class Database {
it.getBlob(SCANS_RAW),
it.getString(SCANS_FORMAT),
it.getString(SCANS_ERROR_CORRECTION_LEVEL),
it.getString(SCANS_ISSUE_NUMBER),
it.getString(SCANS_ORIENTATION),
it.getString(SCANS_OTHER_META_DATA),
it.getString(SCANS_PDF417_EXTRA_METADATA),
it.getString(SCANS_POSSIBLE_COUNTRY),
it.getString(SCANS_SUGGESTED_PRICE),
it.getString(SCANS_UPC_EAN_EXTENSION),
it.getString(SCANS_VERSION),
it.getInt(SCANS_SEQUENCE_SIZE),
it.getInt(SCANS_SEQUENCE_INDEX),
it.getString(SCANS_SEQUENCE_ID),
it.getString(SCANS_GTIN_COUNTRY),
it.getString(SCANS_GTIN_ADD_ON),
it.getString(SCANS_GTIN_PRICE),
it.getString(SCANS_GTIN_ISSUE_NUMBER),
it.getString(SCANS_DATETIME),
it.getLong(SCANS_ID)
)
@@ -125,13 +128,14 @@ class Database {
scan.errorCorrectionLevel?.let {
put(SCANS_ERROR_CORRECTION_LEVEL, it)
}
scan.issueNumber?.let { put(SCANS_ISSUE_NUMBER, it) }
scan.orientation?.let { put(SCANS_ORIENTATION, it) }
scan.otherMetaData?.let { put(SCANS_OTHER_META_DATA, it) }
scan.pdf417ExtraMetaData?.let { put(SCANS_PDF417_EXTRA_METADATA, it) }
scan.possibleCountry?.let { put(SCANS_POSSIBLE_COUNTRY, it) }
scan.suggestedPrice?.let { put(SCANS_SUGGESTED_PRICE, it) }
scan.upcEanExtension?.let { put(SCANS_UPC_EAN_EXTENSION, it) }
put(SCANS_VERSION, scan.version)
put(SCANS_SEQUENCE_SIZE, scan.sequenceSize)
put(SCANS_SEQUENCE_INDEX, scan.sequenceIndex)
put(SCANS_SEQUENCE_ID, scan.sequenceId)
scan.country?.let { put(SCANS_GTIN_COUNTRY, it) }
scan.addOn?.let { put(SCANS_GTIN_ADD_ON, it) }
scan.price?.let { put(SCANS_GTIN_PRICE, it) }
scan.issueNumber?.let { put(SCANS_GTIN_ISSUE_NUMBER, it) }
if (prefs.ignoreConsecutiveDuplicates) {
val id = getIdOfLastScan(
get(SCANS_CONTENT) as String,
@@ -188,9 +192,9 @@ class Database {
}
private class OpenHelper(context: Context) :
SQLiteOpenHelper(context, FILE_NAME, null, 4) {
SQLiteOpenHelper(context, FILE_NAME, null, 6) {
override fun onCreate(db: SQLiteDatabase) {
createScans(db)
db.createScans()
}
override fun onUpgrade(
@@ -199,13 +203,19 @@ class Database {
newVersion: Int
) {
if (oldVersion < 2) {
addRawColumn(db)
db.addRawColumn()
}
if (oldVersion < 3) {
addMetaDataColumns(db)
db.addMetaDataColumns()
}
if (oldVersion < 4) {
addNameColumn(db)
db.addNameColumn()
}
if (oldVersion < 5) {
db.migrateToZxingCpp()
}
if (oldVersion < 6) {
db.migrateToVersionString()
}
}
}
@@ -220,6 +230,8 @@ class Database {
const val SCANS_RAW = "raw"
const val SCANS_FORMAT = "format"
const val SCANS_ERROR_CORRECTION_LEVEL = "error_correction_level"
const val SCANS_VERSION_NUMBER = "version_number"
const val SCANS_VERSION = "version"
const val SCANS_ISSUE_NUMBER = "issue_number"
const val SCANS_ORIENTATION = "orientation"
const val SCANS_OTHER_META_DATA = "other_meta_data"
@@ -227,10 +239,17 @@ class Database {
const val SCANS_POSSIBLE_COUNTRY = "possible_country"
const val SCANS_SUGGESTED_PRICE = "suggested_price"
const val SCANS_UPC_EAN_EXTENSION = "upc_ean_extension"
const val SCANS_SEQUENCE_SIZE = "sequence_size"
const val SCANS_SEQUENCE_INDEX = "sequence_index"
const val SCANS_SEQUENCE_ID = "sequence_id"
const val SCANS_GTIN_COUNTRY = "gtin_country"
const val SCANS_GTIN_ADD_ON = "gtin_add_on"
const val SCANS_GTIN_PRICE = "gtin_price"
const val SCANS_GTIN_ISSUE_NUMBER = "gtin_issue_number"
private fun createScans(db: SQLiteDatabase) {
db.execSQL("DROP TABLE IF EXISTS $SCANS".trimMargin())
db.execSQL(
private fun SQLiteDatabase.createScans() {
execSQL("DROP TABLE IF EXISTS $SCANS".trimMargin())
execSQL(
"""CREATE TABLE $SCANS (
$SCANS_ID INTEGER PRIMARY KEY AUTOINCREMENT,
$SCANS_DATETIME DATETIME NOT NULL,
@@ -239,36 +258,57 @@ class Database {
$SCANS_RAW BLOB,
$SCANS_FORMAT TEXT NOT NULL,
$SCANS_ERROR_CORRECTION_LEVEL TEXT,
$SCANS_ISSUE_NUMBER INT,
$SCANS_ORIENTATION INT,
$SCANS_OTHER_META_DATA TEXT,
$SCANS_PDF417_EXTRA_METADATA TEXT,
$SCANS_POSSIBLE_COUNTRY TEXT,
$SCANS_SUGGESTED_PRICE TEXT,
$SCANS_UPC_EAN_EXTENSION TEXT
$SCANS_VERSION TEXT,
$SCANS_SEQUENCE_SIZE INTEGER,
$SCANS_SEQUENCE_INDEX INTEGER,
$SCANS_SEQUENCE_ID TEXT,
$SCANS_GTIN_COUNTRY TEXT,
$SCANS_GTIN_ADD_ON TEXT,
$SCANS_GTIN_PRICE TEXT,
$SCANS_GTIN_ISSUE_NUMBER TEXT
)""".trimMargin()
)
}
private fun addRawColumn(db: SQLiteDatabase) {
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_RAW BLOB".trimMargin())
private fun SQLiteDatabase.addRawColumn() {
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_RAW BLOB".trimMargin())
}
private fun addMetaDataColumns(db: SQLiteDatabase) {
db.apply {
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ERROR_CORRECTION_LEVEL TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ISSUE_NUMBER INT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ORIENTATION INT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_OTHER_META_DATA TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_PDF417_EXTRA_METADATA TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_POSSIBLE_COUNTRY TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_SUGGESTED_PRICE TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_UPC_EAN_EXTENSION TEXT".trimMargin())
}
private fun SQLiteDatabase.addMetaDataColumns() {
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ERROR_CORRECTION_LEVEL TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ISSUE_NUMBER INT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ORIENTATION INT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_OTHER_META_DATA TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_PDF417_EXTRA_METADATA TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_POSSIBLE_COUNTRY TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_SUGGESTED_PRICE TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_UPC_EAN_EXTENSION TEXT".trimMargin())
}
private fun addNameColumn(db: SQLiteDatabase) {
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_NAME TEXT".trimMargin())
private fun SQLiteDatabase.addNameColumn() {
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_NAME TEXT".trimMargin())
}
private fun SQLiteDatabase.migrateToZxingCpp() {
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_VERSION_NUMBER INTEGER".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_SEQUENCE_SIZE INTEGER".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_SEQUENCE_INDEX INTEGER".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_SEQUENCE_ID TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_GTIN_COUNTRY TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_GTIN_ADD_ON TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_GTIN_PRICE TEXT".trimMargin())
execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_GTIN_ISSUE_NUMBER TEXT".trimMargin())
execSQL("UPDATE $SCANS SET $SCANS_SEQUENCE_SIZE = -1")
execSQL("UPDATE $SCANS SET $SCANS_SEQUENCE_INDEX = -1")
execSQL("UPDATE $SCANS SET $SCANS_GTIN_COUNTRY = $SCANS_POSSIBLE_COUNTRY")
execSQL("UPDATE $SCANS SET $SCANS_GTIN_ADD_ON = $SCANS_UPC_EAN_EXTENSION")
execSQL("UPDATE $SCANS SET $SCANS_GTIN_PRICE = $SCANS_SUGGESTED_PRICE")
execSQL("UPDATE $SCANS SET $SCANS_GTIN_ISSUE_NUMBER = $SCANS_ISSUE_NUMBER")
}
private fun SQLiteDatabase.migrateToVersionString() {
execSQL("ALTER TABLE $SCANS ADD $SCANS_VERSION TEXT")
execSQL("UPDATE $SCANS SET $SCANS_VERSION = $SCANS_VERSION_NUMBER")
}
}
}
@@ -2,7 +2,7 @@ package de.markusfisch.android.binaryeye.database
import android.content.Context
import android.database.Cursor
import de.markusfisch.android.binaryeye.app.toHexString
import de.markusfisch.android.binaryeye.content.toHexString
import de.markusfisch.android.binaryeye.io.writeExternalFile
import org.json.JSONArray
import org.json.JSONException
@@ -26,13 +26,14 @@ fun Cursor.exportJson(): String? {
Database.SCANS_FORMAT,
Database.SCANS_CONTENT,
Database.SCANS_ERROR_CORRECTION_LEVEL,
Database.SCANS_ISSUE_NUMBER,
Database.SCANS_ORIENTATION,
Database.SCANS_OTHER_META_DATA,
Database.SCANS_PDF417_EXTRA_METADATA,
Database.SCANS_POSSIBLE_COUNTRY,
Database.SCANS_SUGGESTED_PRICE,
Database.SCANS_UPC_EAN_EXTENSION
Database.SCANS_VERSION,
Database.SCANS_SEQUENCE_SIZE,
Database.SCANS_SEQUENCE_INDEX,
Database.SCANS_SEQUENCE_ID,
Database.SCANS_GTIN_COUNTRY,
Database.SCANS_GTIN_ADD_ON,
Database.SCANS_GTIN_PRICE,
Database.SCANS_GTIN_ISSUE_NUMBER
)
val indices = columns.map {
Pair(getColumnIndex(it), it)
@@ -1,29 +1,33 @@
package de.markusfisch.android.binaryeye.database
import android.graphics.Bitmap
import android.os.Build
import android.os.Parcel
import android.os.Parcelable
import android.text.format.DateFormat
import com.google.zxing.Result
import com.google.zxing.ResultMetadataType
import de.markusfisch.android.binaryeye.app.hasNonPrintableCharacters
import de.markusfisch.android.zxingcpp.ZxingCpp
import de.markusfisch.android.zxingcpp.ZxingCpp.ContentType
import de.markusfisch.android.zxingcpp.ZxingCpp.Format
import de.markusfisch.android.zxingcpp.ZxingCpp.Result
data class Scan(
val content: String,
val raw: ByteArray?,
val format: String,
val errorCorrectionLevel: String?,
val issueNumber: String?,
val orientation: String?,
val otherMetaData: String?,
val pdf417ExtraMetaData: String?,
val possibleCountry: String?,
val suggestedPrice: String?,
val upcEanExtension: String?,
val errorCorrectionLevel: String? = null,
val version: String? = null,
val sequenceSize: Int = -1,
val sequenceIndex: Int = -1,
val sequenceId: String = "",
val country: String? = null,
val addOn: String? = null,
val price: String? = null,
val issueNumber: String? = null,
val dateTime: String = getDateTime(),
var id: Long = 0L
) : Parcelable {
// Needs to be overwritten manually, as ByteArray is an array and
// this isn't handled well by Kotlin
// this isn't handled well by Kotlin.
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
@@ -41,17 +45,18 @@ data class Scan(
(raw != null && other.raw != null && raw.contentEquals(other.raw))) &&
format == other.format &&
errorCorrectionLevel == other.errorCorrectionLevel &&
issueNumber == other.issueNumber &&
orientation == other.orientation &&
otherMetaData == other.otherMetaData &&
pdf417ExtraMetaData == other.pdf417ExtraMetaData &&
possibleCountry == other.possibleCountry &&
suggestedPrice == other.suggestedPrice &&
upcEanExtension == other.upcEanExtension
version == other.version &&
sequenceSize == other.sequenceSize &&
sequenceIndex == other.sequenceIndex &&
sequenceId == other.sequenceId &&
country == other.country &&
addOn == other.addOn &&
price == other.price &&
issueNumber == other.issueNumber
}
// Needs to be overwritten manually, as ByteArray is an array and
// this isn't handled well by Kotlin
// this isn't handled well by Kotlin.
override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + dateTime.hashCode()
@@ -59,13 +64,14 @@ data class Scan(
result = 31 * result + (raw?.contentHashCode() ?: 0)
result = 31 * result + format.hashCode()
result = 31 * result + (errorCorrectionLevel?.hashCode() ?: 0)
result = 31 * result + version.hashCode()
result = 31 * result + sequenceSize
result = 31 * result + sequenceIndex
result = 31 * result + sequenceId.hashCode()
result = 31 * result + (country?.hashCode() ?: 0)
result = 31 * result + (addOn?.hashCode() ?: 0)
result = 31 * result + (price?.hashCode() ?: 0)
result = 31 * result + (issueNumber?.hashCode() ?: 0)
result = 31 * result + (orientation?.hashCode() ?: 0)
result = 31 * result + (otherMetaData?.hashCode() ?: 0)
result = 31 * result + (pdf417ExtraMetaData?.hashCode() ?: 0)
result = 31 * result + (possibleCountry?.hashCode() ?: 0)
result = 31 * result + (suggestedPrice?.hashCode() ?: 0)
result = 31 * result + (upcEanExtension?.hashCode() ?: 0)
return result
}
@@ -74,13 +80,14 @@ data class Scan(
raw = parcel.readSizedByteArray(),
format = parcel.readString() ?: "",
errorCorrectionLevel = parcel.readString(),
version = parcel.readString(),
sequenceSize = parcel.readInt(),
sequenceIndex = parcel.readInt(),
sequenceId = parcel.readString() ?: "",
country = parcel.readString(),
addOn = parcel.readString(),
price = parcel.readString(),
issueNumber = parcel.readString(),
orientation = parcel.readString(),
otherMetaData = parcel.readString(),
pdf417ExtraMetaData = parcel.readString(),
possibleCountry = parcel.readString(),
suggestedPrice = parcel.readString(),
upcEanExtension = parcel.readString(),
dateTime = parcel.readString() ?: "",
id = parcel.readLong()
)
@@ -91,13 +98,14 @@ data class Scan(
writeSizedByteArray(raw)
writeString(format)
writeString(errorCorrectionLevel)
writeString(version)
writeInt(sequenceSize)
writeInt(sequenceIndex)
writeString(sequenceId)
writeString(country)
writeString(addOn)
writeString(price)
writeString(issueNumber)
writeString(orientation)
writeString(otherMetaData)
writeString(pdf417ExtraMetaData)
writeString(possibleCountry)
writeString(suggestedPrice)
writeString(upcEanExtension)
writeString(dateTime)
writeLong(id)
}
@@ -114,8 +122,82 @@ data class Scan(
}
}
private fun getDateTime(time: Long = System.currentTimeMillis()) = DateFormat.format(
"yyyy-MM-dd HH:mm:ss",
fun Result.toScan(): Scan {
val content: String
val raw: ByteArray?
when (contentType) {
ContentType.GS1,
ContentType.ISO15434,
ContentType.TEXT -> {
content = text
raw = null
}
else -> {
content = ""
raw = rawBytes
}
}
return Scan(
content,
raw,
format,
ecLevel,
version,
sequenceSize,
sequenceIndex,
sequenceId,
gtin?.country,
gtin?.addOn,
gtin?.price,
gtin?.issueNumber
)
}
data class Recreation(
val format: Format,
val ecLevel: Int,
val size: Int,
val margin: Int
) {
fun encode(content: String): Bitmap? = try {
ZxingCpp.encodeAsBitmap(
content, format, size, size, margin, ecLevel
)
} catch (_: RuntimeException) {
null
}
}
fun Scan.toRecreation(
size: Int = 128,
margin: Int = -1
) = if (content.isEmpty()) {
null
} else {
Recreation(
Format.valueOf(format),
when (errorCorrectionLevel) {
"L" -> 0
"M" -> 1
"Q" -> 2
"H" -> 3
else -> -1
},
size,
margin
)
}
private fun getDateTime(
time: Long = System.currentTimeMillis()
) = DateFormat.format(
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
// Up to API level 17, 'k' was interpreted as 'H', which wasn't
// implemented until API level 18.
"yyyy-MM-dd kk:mm:ss"
} else {
"yyyy-MM-dd HH:mm:ss"
},
time
).toString()
@@ -137,51 +219,3 @@ private fun Parcel.readSizedByteArray(): ByteArray? {
null
}
}
fun Result.toScan(): Scan {
val content: String
val raw: ByteArray?
if (text.hasNonPrintableCharacters()) {
content = ""
raw = getRawData() ?: text.toByteArray()
} else {
content = text
raw = null
}
return Scan(
content,
raw,
barcodeFormat.toString(),
getMetaString(ResultMetadataType.ERROR_CORRECTION_LEVEL),
getMetaString(ResultMetadataType.ISSUE_NUMBER),
getMetaString(ResultMetadataType.ORIENTATION),
getMetaString(ResultMetadataType.OTHER),
getMetaString(ResultMetadataType.PDF417_EXTRA_METADATA),
getMetaString(ResultMetadataType.POSSIBLE_COUNTRY),
getMetaString(ResultMetadataType.SUGGESTED_PRICE),
getMetaString(ResultMetadataType.UPC_EAN_EXTENSION)
)
}
private fun Result.getRawData(): ByteArray? {
val metadata = resultMetadata ?: return null
val segments = metadata[ResultMetadataType.BYTE_SEGMENTS] ?: return null
var bytes = ByteArray(0)
@Suppress("UNCHECKED_CAST")
for (seg in segments as Iterable<ByteArray>) {
bytes += seg
}
// If the byte segments are shorter than the converted string, the
// content of the QR Code has been encoded with different encoding
// modes (e.g. some parts in alphanumeric, some in byte encoding).
// This is because Zxing only records byte segments for byte encoded
// parts. Please note the byte segments can actually be longer than
// the string because Zxing cuts off prefixes like "WIFI:".
return if (bytes.size >= text.length) bytes else null
}
private fun Result.getMetaString(
key: ResultMetadataType
): String? = this.resultMetadata?.let {
it[key]?.toString()
}
@@ -9,13 +9,13 @@ import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.*
import android.widget.EditText
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.app.hasWritePermission
import de.markusfisch.android.binaryeye.content.copyToClipboard
import de.markusfisch.android.binaryeye.content.shareFile
import de.markusfisch.android.binaryeye.content.shareText
import de.markusfisch.android.binaryeye.graphics.COLOR_BLACK
import de.markusfisch.android.binaryeye.graphics.COLOR_WHITE
import de.markusfisch.android.binaryeye.io.addSuffixIfNotGiven
import de.markusfisch.android.binaryeye.io.toSaveResult
import de.markusfisch.android.binaryeye.io.writeExternalFile
@@ -23,15 +23,15 @@ import de.markusfisch.android.binaryeye.view.doOnApplyWindowInsets
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
import de.markusfisch.android.binaryeye.widget.ConfinedScalingImageView
import de.markusfisch.android.binaryeye.widget.toast
import de.markusfisch.android.binaryeye.zxing.encodeAsBitmap
import de.markusfisch.android.binaryeye.zxing.encodeAsSvg
import de.markusfisch.android.binaryeye.zxing.encodeAsText
import de.markusfisch.android.zxingcpp.ZxingCpp
import de.markusfisch.android.zxingcpp.ZxingCpp.Format
import kotlinx.coroutines.*
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStream
import java.util.*
import kotlin.math.min
class BarcodeFragment : Fragment() {
private enum class FileType {
@@ -41,11 +41,7 @@ class BarcodeFragment : Fragment() {
private val parentJob = Job()
private val scope = CoroutineScope(Dispatchers.IO + parentJob)
private var barcodeBitmap: Bitmap? = null
private var barcodeSvg: String? = null
private var barcodeTxt: String? = null
private var content: String = ""
private var format: BarcodeFormat? = null
private lateinit var barcode: Barcode
override fun onCreate(state: Bundle?) {
super.onCreate(state)
@@ -66,15 +62,13 @@ class BarcodeFragment : Fragment() {
false
)
val args = arguments ?: return view
val content = args.getString(CONTENT) ?: return view
val format = args.getSerializable(FORMAT) as BarcodeFormat? ?: return view
val hints = args.getSerializable(HINTS) as EnumMap<EncodeHintType, Any>?
val size = args.getInt(SIZE)
val bitmap: Bitmap
try {
barcodeBitmap = encodeAsBitmap(content, format, size, size, hints)
barcodeSvg = encodeAsSvg(content, format, hints)
barcodeTxt = encodeAsText(content, format, hints)
barcode = arguments?.toBarcode() ?: throw IllegalArgumentException(
"Illegal arguments"
)
// Catch exceptions from encoding.
bitmap = barcode.bitmap()
} catch (e: Exception) {
var message = e.message
if (message == null || message.isEmpty()) {
@@ -86,16 +80,17 @@ class BarcodeFragment : Fragment() {
fragmentManager.popBackStack()
return null
}
this.content = content
this.format = format
val imageView = view.findViewById<ConfinedScalingImageView>(
R.id.barcode
)
imageView.setImageBitmap(barcodeBitmap)
imageView.setImageBitmap(bitmap)
imageView.post {
// Make sure to invoke this after ScalingImageView.onLayout().
imageView.minWidth /= 2f
imageView.minWidth = min(
imageView.minWidth / 2f,
barcode.size.toFloat()
)
}
view.findViewById<View>(R.id.share).setOnClickListener {
@@ -114,6 +109,20 @@ class BarcodeFragment : Fragment() {
return view
}
private fun Bundle.toBarcode() = Barcode(
getString(CONTENT) ?: throw IllegalArgumentException(
"content cannot be null"
),
Format.valueOf(
getString(FORMAT) ?: throw IllegalArgumentException(
"format cannot be null"
)
),
getInt(SIZE),
getInt(EC_LEVEL),
Colors.values()[getInt(COLORS)]
)
override fun onDestroyView() {
super.onDestroyView()
parentJob.cancel()
@@ -126,9 +135,9 @@ class BarcodeFragment : Fragment() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.copy_to_clipboard -> {
barcodeTxt?.let {
context.copyToClipboard(it)
context.toast(R.string.copied_to_clipboard)
context.apply {
copyToClipboard(barcode.text())
toast(R.string.copied_to_clipboard)
}
true
}
@@ -167,7 +176,9 @@ class BarcodeFragment : Fragment() {
}
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"))
editText.setText(
encodeFileName("${barcode.format}_${barcode.content}")
)
AlertDialog.Builder(ac)
.setView(view)
.setPositiveButton(android.R.string.ok) { _, _ ->
@@ -177,23 +188,19 @@ class BarcodeFragment : Fragment() {
addSuffixIfNotGiven(fileName, ".png"),
MIME_PNG
) {
barcodeBitmap?.saveAsPng(it)
barcode.bitmap().saveAsPng(it)
}
FileType.SVG -> saveAs(
addSuffixIfNotGiven(fileName, ".svg"),
MIME_SVG
) { outputStream ->
barcodeSvg?.let {
outputStream.write(it.toByteArray())
}
outputStream.write(barcode.svg().toByteArray())
}
FileType.TXT -> saveAs(
addSuffixIfNotGiven(fileName, ".txt"),
MIME_TXT
) { outputStream ->
barcodeTxt?.let {
outputStream.write(it.toByteArray())
}
outputStream.write(barcode.text().toByteArray())
}
}
}
@@ -218,9 +225,9 @@ class BarcodeFragment : Fragment() {
private fun Context.shareAs(fileType: FileType) {
when (fileType) {
FileType.PNG -> barcodeBitmap?.let { share(it) }
FileType.SVG -> barcodeSvg?.let { shareText(it, MIME_SVG) }
FileType.TXT -> barcodeTxt?.let { shareText(it) }
FileType.PNG -> share(barcode.bitmap())
FileType.SVG -> shareText(barcode.svg(), MIME_SVG)
FileType.TXT -> shareText(barcode.text())
}
}
@@ -251,25 +258,26 @@ class BarcodeFragment : Fragment() {
companion object {
private const val CONTENT = "content"
private const val FORMAT = "format"
private const val HINTS = "hints"
private const val SIZE = "size"
private const val EC_LEVEL = "ec_level"
private const val COLORS = "colors"
private const val MIME_PNG = "image/png"
private const val MIME_SVG = "image/svg+xmg"
private const val MIME_TXT = "text/plain"
fun newInstance(
content: String,
format: BarcodeFormat,
format: Format,
size: Int,
hints: EnumMap<EncodeHintType, Any>? = null
ecLevel: Int = -1,
colors: Int = 0
): Fragment {
val args = Bundle()
args.putString(CONTENT, content)
args.putSerializable(FORMAT, format)
hints?.let {
args.putSerializable(HINTS, it)
}
args.putString(FORMAT, format.name)
args.putInt(SIZE, size)
args.putInt(EC_LEVEL, ecLevel)
args.putInt(COLORS, colors)
val fragment = BarcodeFragment()
fragment.arguments = args
return fragment
@@ -277,6 +285,65 @@ class BarcodeFragment : Fragment() {
}
}
private data class Barcode(
val content: String,
val format: Format,
val size: Int,
val ecLevel: Int,
val colors: Colors
) {
private var _bitmap: Bitmap? = null
fun bitmap(): Bitmap {
val b = _bitmap ?: ZxingCpp.encodeAsBitmap(
content, format, size, size, -1, ecLevel,
setColor = colors.foregroundColor(),
unsetColor = colors.backgroundColor()
)
_bitmap = b
return b
}
private var _svg: String? = null
fun svg(): String {
val s = _svg ?: ZxingCpp.encodeAsSvg(
content, format, -1, ecLevel
)
_svg = s
return s
}
private var _text: String? = null
fun text(): String {
val t = _text ?: ZxingCpp.encodeAsText(
content, format, -1, ecLevel,
inverted = colors == Colors.BLACK_ON_WHITE
)
_text = t
return t
}
}
private enum class Colors {
BLACK_ON_WHITE,
WHITE_ON_BLACK,
BLACK_ON_TRANSPARENT,
WHITE_ON_TRANSPARENT;
fun foregroundColor(): Int = when (this) {
BLACK_ON_WHITE,
BLACK_ON_TRANSPARENT -> COLOR_BLACK
WHITE_ON_BLACK,
WHITE_ON_TRANSPARENT -> COLOR_WHITE
}
fun backgroundColor(): Int = when (this) {
BLACK_ON_WHITE -> COLOR_WHITE
WHITE_ON_BLACK -> COLOR_BLACK
BLACK_ON_TRANSPARENT,
WHITE_ON_TRANSPARENT -> 0
}
}
private fun Bitmap.saveAsPng(outputStream: OutputStream, quality: Int = 90) =
compress(Bitmap.CompressFormat.PNG, quality, outputStream)
@@ -5,16 +5,14 @@ import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.v4.app.Fragment
import android.text.Editable
import android.text.Html
import android.text.TextWatcher
import android.text.method.LinkMovementMethod
import android.view.*
import android.widget.EditText
import android.widget.TableLayout
import android.widget.TableRow
import android.widget.TextView
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import com.google.zxing.qrcode.encoder.Encoder
import android.widget.*
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.actions.ActionRegistry
import de.markusfisch.android.binaryeye.actions.IAction
import de.markusfisch.android.binaryeye.actions.wifi.WifiAction
import de.markusfisch.android.binaryeye.actions.wifi.WifiConnector
import de.markusfisch.android.binaryeye.activity.MainActivity
@@ -22,16 +20,17 @@ import de.markusfisch.android.binaryeye.adapter.prettifyFormatName
import de.markusfisch.android.binaryeye.app.*
import de.markusfisch.android.binaryeye.content.copyToClipboard
import de.markusfisch.android.binaryeye.content.shareText
import de.markusfisch.android.binaryeye.content.toHexString
import de.markusfisch.android.binaryeye.database.Recreation
import de.markusfisch.android.binaryeye.database.Scan
import de.markusfisch.android.binaryeye.database.toRecreation
import de.markusfisch.android.binaryeye.io.askForFileName
import de.markusfisch.android.binaryeye.io.toSaveResult
import de.markusfisch.android.binaryeye.io.writeExternalFile
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
import de.markusfisch.android.binaryeye.widget.toast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
import kotlin.math.roundToInt
class DecodeFragment : Fragment() {
private lateinit var contentView: EditText
@@ -39,19 +38,24 @@ class DecodeFragment : Fragment() {
private lateinit var dataView: TableLayout
private lateinit var metaView: TableLayout
private lateinit var hexView: TextView
private lateinit var format: String
private lateinit var stampView: TextView
private lateinit var recreationView: ImageView
private lateinit var fab: FloatingActionButton
private lateinit var format: String
private val parentJob = Job()
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Main + parentJob)
private val dp: Float
get() = resources.displayMetrics.density
private val content: String
get() = contentView.text.toString()
private var closeAutomatically = false
private var action = ActionRegistry.DEFAULT_ACTION
private var isBinary = false
private var raw: ByteArray = ByteArray(0)
private var originalBytes: ByteArray = ByteArray(0)
private var id = 0L
private var recreation: Recreation? = null
override fun onCreate(state: Bundle?) {
super.onCreate(state)
@@ -74,70 +78,42 @@ class DecodeFragment : Fragment() {
closeAutomatically = prefs.closeAutomatically &&
activity?.intent?.hasExtra(MainActivity.DECODED) == true
val scan = arguments?.getParcelable(SCAN) as Scan?
?: throw IllegalArgumentException("DecodeFragment needs a Scan")
val scan = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
arguments?.getParcelable(SCAN, Scan::class.java)
} else {
@Suppress("DEPRECATION")
arguments?.getParcelable(SCAN) as Scan?
} ?: throw IllegalArgumentException("DecodeFragment needs a Scan")
val originalContent = scan.content
isBinary = scan.raw != null
originalBytes = scan.raw ?: originalContent.toByteArray()
format = scan.format
id = scan.id
val inputContent = scan.content
isBinary = scan.raw != null
raw = scan.raw ?: inputContent.toByteArray()
format = scan.format
contentView = view.findViewById(R.id.content)
fab = view.findViewById(R.id.open)
if (!isBinary) {
contentView.setText(inputContent)
contentView.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
updateViewsAndAction(content.toByteArray())
}
override fun beforeTextChanged(
s: CharSequence?,
start: Int,
count: Int,
after: Int
) {
}
override fun onTextChanged(
s: CharSequence?,
start: Int,
before: Int,
count: Int
) {
}
})
fab.setOnClickListener {
executeAction(content.toByteArray())
}
if (prefs.openImmediately) {
executeAction(content.toByteArray())
}
} else {
contentView.setText(String(raw).foldNonAlNum())
contentView.isEnabled = false
fab.setImageResource(R.drawable.ic_action_save)
fab.setOnClickListener {
askForFileNameAndSave(raw)
}
}
formatView = view.findViewById(R.id.format)
dataView = view.findViewById(R.id.data)
metaView = view.findViewById(R.id.meta)
hexView = view.findViewById(R.id.hex)
stampView = view.findViewById(R.id.stamp)
recreationView = view.findViewById(R.id.recreation)
fab = view.findViewById(R.id.open)
updateViewsAndAction(raw)
if (!isBinary) {
fillDataView(dataView, inputContent)
}
initContentAndFab(originalContent)
if (prefs.showMetaData) {
fillMetaView(metaView, scan)
metaView.fillMetaView(scan)
} else {
metaView.visibility = View.GONE
}
if (prefs.showRecreation) {
recreation = scan.toRecreation(
(200f * dp).roundToInt()
)
}
updateViewsAndFab(originalContent, originalBytes)
(view.findViewById(R.id.inset_layout) as View).setPaddingFromWindowInsets()
(view.findViewById(R.id.scroll_view) as View).setPaddingFromWindowInsets()
@@ -150,35 +126,104 @@ class DecodeFragment : Fragment() {
parentJob.cancel()
}
private fun updateViewsAndAction(bytes: ByteArray) {
private fun initContentAndFab(originalContent: String) {
if (isBinary) {
contentView.setText(String(originalBytes).foldNonAlNum())
contentView.isEnabled = false
fab.setImageResource(R.drawable.ic_action_save)
fab.setOnClickListener {
askForFileNameAndSave(originalBytes)
}
} else {
contentView.setText(originalContent)
contentView.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
updateViewsAndFab(s?.toString() ?: "")
}
override fun beforeTextChanged(
s: CharSequence?,
start: Int,
count: Int,
after: Int
) = Unit
override fun onTextChanged(
s: CharSequence?,
start: Int,
before: Int,
count: Int
) = Unit
})
fab.setOnClickListener {
executeAction(content)
}
if (prefs.openImmediately) {
executeAction(content)
}
}
}
private fun updateViewsAndFab(text: String, bytes: ByteArray? = null) {
val b = bytes ?: text.toByteArray()
resolveActionAndUpdateFab(b)
updateViews(text, b)
}
private fun resolveActionAndUpdateFab(bytes: ByteArray) {
val prevAction = action
if (!prevAction.canExecuteOn(bytes)) {
action = ActionRegistry.getAction(bytes)
}
if (prevAction !== action) {
updateFab(action)
}
}
private fun updateFab(action: IAction) {
fab.setImageResource(action.iconResId)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
fab.setOnLongClickListener { v ->
v.context.toast(action.titleResId)
true
}
} else {
fab.tooltipText = getString(action.titleResId)
}
}
private fun updateViews(text: String, bytes: ByteArray) {
formatView.text = resources.getQuantityString(
R.plurals.barcode_info,
bytes.size,
prettifyFormatName(format),
bytes.size
)
hexView.text = if (prefs.showHexDump) hexDump(bytes) else ""
if (prevAction !== action) {
fab.setImageResource(action.iconResId)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
fab.setOnLongClickListener { v ->
v.context.toast(action.titleResId)
true
}
} else {
fab.tooltipText = getString(action.titleResId)
hexView.showIf(prefs.showHexDump) { v ->
v.text = hexDump(bytes)
}
recreationView.showIf(prefs.showRecreation) { v ->
val r = recreation ?: return@showIf
v.setImageBitmap(r.encode(text))
v.setOnClickListener {
fragmentManager?.addFragment(
BarcodeFragment.newInstance(
text,
r.format,
r.size,
r.ecLevel
)
)
}
}
dataView.fillDataView(text)
stampView.setTrackingLink(bytes, format)
}
private fun fillDataView(tableLayout: TableLayout, content: String) {
private fun TableLayout.fillDataView(text: String) {
val items = LinkedHashMap<Int, String?>()
if (action is WifiAction) {
WifiConnector.parseMap(content)?.let { wifiData ->
WifiConnector.parseMap(text)?.let { wifiData ->
items.putAll(
linkedMapOf(
R.string.entry_type to getString(R.string.wifi_network),
@@ -194,52 +239,61 @@ class DecodeFragment : Fragment() {
)
}
}
fillDataTable(tableLayout, items)
fill(items)
}
private fun fillMetaView(tableLayout: TableLayout, scan: Scan) {
private fun TableLayout.fillMetaView(scan: Scan) {
val items = linkedMapOf(
R.string.error_correction_level to scan.errorCorrectionLevel,
R.string.issue_number to scan.issueNumber,
R.string.orientation to scan.orientation,
R.string.other_meta_data to scan.otherMetaData,
R.string.pdf417_extra_metadata to scan.pdf417ExtraMetaData,
R.string.possible_country to scan.possibleCountry,
R.string.suggested_price to scan.suggestedPrice,
R.string.upc_ean_extension to scan.upcEanExtension
R.string.sequence_size to scan.sequenceSize.positiveToString(),
R.string.sequence_index to scan.sequenceIndex.positiveToString(),
R.string.sequence_id to scan.sequenceId,
R.string.gtin_country to scan.country,
R.string.gtin_add_on to scan.addOn,
R.string.gtin_price to scan.price,
R.string.gtin_issue_number to scan.issueNumber,
)
if (prefs.showQrVersion && scan.format == "QR_CODE") {
if (!scan.version.isNullOrBlank()) {
val versionString = if (scan.format == "QR_CODE") {
getString(
R.string.qr_version_and_modules,
scan.version,
(scan.version.toIntOrNull() ?: 0) * 4 + 17
)
} else {
scan.version
}
items.putAll(
linkedMapOf(
R.string.qr_version to "${scan.version()}"
R.string.barcode_version_number to versionString
)
)
}
fillDataTable(tableLayout, items)
fill(items)
}
private fun fillDataTable(
tableLayout: TableLayout,
private fun TableLayout.fill(
items: LinkedHashMap<Int, String?>
) {
val ctx = tableLayout.context
val spaceBetween = (16f * ctx.resources.displayMetrics.density).toInt()
items.forEach { item ->
val text = item.value
if (!text.isNullOrBlank()) {
val tr = TableRow(ctx)
val keyView = TextView(ctx)
keyView.setText(item.key)
val valueView = TextView(ctx)
valueView.setPadding(spaceBetween, 0, 0, 0)
valueView.text = text
tr.addView(keyView)
tr.addView(valueView)
tableLayout.addView(tr)
removeAllViews()
visibility = if (items.isEmpty()) View.GONE else {
val ctx = context
val spaceBetween = (16f * dp).roundToInt()
items.forEach { item ->
val text = item.value
if (!text.isNullOrBlank()) {
val tr = TableRow(ctx)
val keyView = TextView(ctx)
keyView.setText(item.key)
val valueView = TextView(ctx)
valueView.setPadding(spaceBetween, 0, 0, 0)
valueView.text = text
tr.addView(keyView)
tr.addView(valueView)
addView(tr)
}
}
}
if (tableLayout.childCount > 0) {
tableLayout.setPadding(0, 0, 0, spaceBetween)
View.VISIBLE
}
}
@@ -292,7 +346,7 @@ class DecodeFragment : Fragment() {
}
private fun textOrHex() = if (isBinary) {
raw.toHexString()
originalBytes.toHexString()
} else {
content
}
@@ -302,16 +356,16 @@ class DecodeFragment : Fragment() {
if (ac is WifiAction) {
ac.password?.let { password ->
activity?.apply {
copyToClipboard(password)
copyToClipboard(password, isSensitive = true)
toast(R.string.copied_password_to_clipboard)
}
}
}
}
private fun copyToClipboard(text: String) {
private fun copyToClipboard(text: String, isSensitive: Boolean = false) {
activity?.apply {
copyToClipboard(text)
copyToClipboard(text, isSensitive)
toast(R.string.copied_to_clipboard)
}
}
@@ -331,7 +385,7 @@ class DecodeFragment : Fragment() {
}
}
private fun executeAction(content: ByteArray) {
private fun executeAction(content: String) {
val ac = activity ?: return
if (content.isNotEmpty()) {
if (action is WifiAction &&
@@ -341,7 +395,7 @@ class DecodeFragment : Fragment() {
return
}
scope.launch {
action.execute(ac, content)
action.execute(ac, content.toByteArray())
maybeBackOrFinish()
}
}
@@ -357,13 +411,17 @@ class DecodeFragment : Fragment() {
}
scope.launch(Dispatchers.Main) {
val name = ac.askForFileName() ?: return@launch
val message = ac.writeExternalFile(
name,
"application/octet-stream"
) {
it.write(raw)
}.toSaveResult()
ac.toast(message)
withContext(Dispatchers.IO) {
val message = ac.writeExternalFile(
name,
"application/octet-stream"
) {
it.write(raw)
}.toSaveResult()
withContext(Dispatchers.Main) {
ac.toast(message)
}
}
}
}
@@ -380,6 +438,23 @@ class DecodeFragment : Fragment() {
}
}
private inline fun <T : View> T.showIf(
visible: Boolean,
block: (T) -> Unit
) {
visibility = if (visible) {
block.invoke(this)
View.VISIBLE
} else {
View.GONE
}
}
private val nonAlNum = "[^a-zA-Z0-9]".toRegex()
private val multipleDots = "[…]+".toRegex()
private fun String.foldNonAlNum() = replace(nonAlNum, "")
.replace(multipleDots, "")
private fun hexDump(bytes: ByteArray, charsPerLine: Int = 33): String {
if (charsPerLine < 4 || bytes.isEmpty()) {
return ""
@@ -419,7 +494,91 @@ private fun hexDump(bytes: ByteArray, charsPerLine: Int = 33): String {
return dump.toString()
}
private fun Scan.version(): Int = Encoder.encode(
content,
ErrorCorrectionLevel.valueOf(errorCorrectionLevel ?: "L")
).version.versionNumber
private fun Int.positiveToString() = if (this > -1) this.toString() else ""
private fun TextView.setTrackingLink(bytes: ByteArray, format: String) {
val trackingLink = generateDpTrackingLink(bytes, format)
if (trackingLink != null) {
text = trackingLink.fromHtml()
isClickable = true
movementMethod = LinkMovementMethod.getInstance()
} else {
visibility = View.GONE
}
}
private fun generateDpTrackingLink(bytes: ByteArray, format: String): String? {
// Check for Deutsche Post Matrixcode stamp.
var isStamp = false
var rawData = bytes
if (format == "DATA_MATRIX" &&
bytes.toString(Charsets.ISO_8859_1).startsWith("DEA5")
) {
if (bytes.size == 47) {
isStamp = true
} else if (bytes.size > 47) {
// Transform back to original data.
rawData = bytes.toString(Charsets.UTF_8).toByteArray(
Charsets.ISO_8859_1
)
if (rawData.size == 47) {
isStamp = true
}
}
}
if (!isStamp) {
return null
}
val hex = StringBuilder()
hex.append(String.format("%02X", rawData[9]))
hex.append(String.format("%02X", rawData[10]))
hex.append(String.format("%02X", rawData[11]))
hex.append(String.format("%02X", rawData[12]))
hex.append(String.format("%02X", rawData[13]))
hex.append(String.format("%X", (rawData[4].toInt() and 0x0f).toByte()))
hex.append(String.format("%02X", rawData[5]))
hex.append(String.format("%02X", rawData[6]))
hex.append(String.format("%02X", rawData[7]))
hex.append(String.format("%02X", rawData[8]))
val hexString = hex.toString()
val trackingNumber = hexString + String.format(
"%X",
crc4(hexString.toByteArray(Charsets.ISO_8859_1))
)
return "<a href=\"https://www.deutschepost.de/de/s/sendungsverfolgung/verfolgen.html?piececode=$trackingNumber\">Deutsche Post: $trackingNumber</a>"
}
// CRC-4 with polynomial x^4 + x + 1.
private fun crc4(input: ByteArray): Int {
var crc = 0
var i = 0
while (i < input.size) {
val c = input[i].toInt()
var j = 0x80
while (j != 0) {
var bit = crc and 0x8
crc = crc shl 1
if (c and j != 0) {
bit = bit xor 0x8
}
if (bit != 0) {
crc = crc xor 0x3
}
j = j ushr 1
}
++i
}
crc = crc and 0xF
return crc
}
private fun String.fromHtml() = if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
) {
Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
} else {
@Suppress("DEPRECATION")
Html.fromHtml(this)
}
@@ -1,42 +1,43 @@
package de.markusfisch.android.binaryeye.fragment
import android.content.Context
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.adapter.prettifyFormatName
import de.markusfisch.android.binaryeye.app.addFragment
import de.markusfisch.android.binaryeye.app.prefs
import de.markusfisch.android.binaryeye.view.hideSoftKeyboard
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
import java.util.*
import de.markusfisch.android.binaryeye.widget.toast
import de.markusfisch.android.zxingcpp.ZxingCpp.Format
class EncodeFragment : Fragment() {
private lateinit var formatView: Spinner
private lateinit var errorCorrectionLabel: TextView
private lateinit var errorCorrectionLevel: Spinner
private lateinit var ecLabel: TextView
private lateinit var ecSpinner: Spinner
private lateinit var colorsLabel: TextView
private lateinit var colorsSpinner: Spinner
private lateinit var sizeView: TextView
private lateinit var sizeBarView: SeekBar
private lateinit var contentView: EditText
private val writers = arrayListOf(
BarcodeFormat.AZTEC,
BarcodeFormat.CODABAR,
BarcodeFormat.CODE_39,
BarcodeFormat.CODE_128,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.EAN_8,
BarcodeFormat.EAN_13,
BarcodeFormat.ITF,
BarcodeFormat.PDF_417,
BarcodeFormat.QR_CODE,
BarcodeFormat.UPC_A
Format.AZTEC,
Format.CODABAR,
Format.CODE_39,
Format.CODE_128,
Format.DATA_MATRIX,
Format.EAN_8,
Format.EAN_13,
Format.ITF,
Format.PDF_417,
Format.QR_CODE,
Format.UPC_A
)
override fun onCreateView(
@@ -70,22 +71,26 @@ class EncodeFragment : Fragment() {
position: Int,
id: Long
) {
val visibility = if (
writers[position] == BarcodeFormat.QR_CODE
) {
View.VISIBLE
} else {
View.GONE
}
errorCorrectionLabel.visibility = visibility
errorCorrectionLevel.visibility = visibility
val ecVisibility = if (
writers[position] == Format.QR_CODE
) View.VISIBLE else View.GONE
ecLabel.visibility = ecVisibility
ecSpinner.visibility = ecVisibility
val colorsVisibility = if (
writers[position].canBeInverted()
) View.VISIBLE else View.GONE
colorsLabel.visibility = colorsVisibility
colorsSpinner.visibility = colorsVisibility
}
override fun onNothingSelected(parentView: AdapterView<*>?) {}
}
errorCorrectionLabel = view.findViewById(R.id.error_correction_label)
errorCorrectionLevel = view.findViewById(R.id.error_correction_level)
ecLabel = view.findViewById(R.id.error_correction_label)
ecSpinner = view.findViewById(R.id.error_correction_level)
colorsLabel = view.findViewById(R.id.colors_label)
colorsSpinner = view.findViewById(R.id.colors)
sizeView = view.findViewById(R.id.size_display)
sizeBarView = view.findViewById(R.id.size_bar)
@@ -94,14 +99,14 @@ class EncodeFragment : Fragment() {
contentView = view.findViewById(R.id.content)
val args = arguments
args?.also {
contentView.setText(it.getString(CONTENT))
args?.getString(CONTENT)?.let {
contentView.setText(it)
}
val barcodeFormat = args?.getString(FORMAT)
if (barcodeFormat != null) {
formatView.setSelection(
writers.indexOf(resolveFormat(barcodeFormat))
writers.indexOf(barcodeFormat.toFormat())
)
} else if (state == null) {
formatView.post {
@@ -110,7 +115,7 @@ class EncodeFragment : Fragment() {
}
view.findViewById<View>(R.id.encode).setOnClickListener {
encode()
it.context.encode()
}
(view.findViewById(R.id.inset_layout) as View).setPaddingFromWindowInsets()
@@ -124,31 +129,25 @@ class EncodeFragment : Fragment() {
prefs.indexOfLastSelectedFormat = formatView.selectedItemPosition
}
private fun encode() {
val hints = EnumMap<EncodeHintType, Any>(EncodeHintType::class.java)
val format = writers[formatView.selectedItemPosition]
if (format == BarcodeFormat.QR_CODE) {
hints[EncodeHintType.ERROR_CORRECTION] = arrayListOf(
ErrorCorrectionLevel.L,
ErrorCorrectionLevel.M,
ErrorCorrectionLevel.Q,
ErrorCorrectionLevel.H
)[errorCorrectionLevel.selectedItemPosition]
}
val size = getSize(sizeBarView.progress)
private fun Context.encode() {
val content = contentView.text.toString()
if (content.isEmpty()) {
Toast.makeText(
context,
R.string.error_no_content,
Toast.LENGTH_SHORT
).show()
} else {
activity?.hideSoftKeyboard(contentView)
fragmentManager?.addFragment(
BarcodeFragment.newInstance(content, format, size, hints)
)
toast(R.string.error_no_content)
return
}
hideSoftKeyboard(contentView)
val writer = writers[formatView.selectedItemPosition]
fragmentManager?.addFragment(
BarcodeFragment.newInstance(
content,
writer,
getSize(sizeBarView.progress),
ecSpinner.selectedItemPosition,
if (writer.canBeInverted()) {
colorsSpinner.selectedItemPosition
} else 0
)
)
}
private fun initSizeBar() {
@@ -181,11 +180,11 @@ class EncodeFragment : Fragment() {
private const val FORMAT = "format"
fun newInstance(
content: String,
content: String? = null,
format: String? = null
): Fragment {
val args = Bundle()
args.putString(CONTENT, content)
content?.let { args.putString(CONTENT, content) }
format?.let { args.putString(FORMAT, it) }
val fragment = EncodeFragment()
fragment.arguments = args
@@ -194,8 +193,15 @@ class EncodeFragment : Fragment() {
}
}
private fun resolveFormat(name: String): BarcodeFormat = try {
BarcodeFormat.valueOf(name)
} catch (_: IllegalArgumentException) {
BarcodeFormat.QR_CODE
private fun Format.canBeInverted() = when (this) {
Format.AZTEC,
Format.DATA_MATRIX,
Format.QR_CODE -> true
else -> false
}
private fun String.toFormat(default: Format = Format.QR_CODE): Format = try {
Format.valueOf(this)
} catch (_: IllegalArgumentException) {
default
}
@@ -23,11 +23,7 @@ import de.markusfisch.android.binaryeye.adapter.ScansAdapter
import de.markusfisch.android.binaryeye.app.*
import de.markusfisch.android.binaryeye.content.copyToClipboard
import de.markusfisch.android.binaryeye.content.shareText
import de.markusfisch.android.binaryeye.database.Database
import de.markusfisch.android.binaryeye.database.getString
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.database.*
import de.markusfisch.android.binaryeye.io.askForFileName
import de.markusfisch.android.binaryeye.io.toSaveResult
import de.markusfisch.android.binaryeye.view.*
@@ -76,7 +72,7 @@ class HistoryFragment : Fragment() {
val ac = activity ?: return false
return when (item.itemId) {
R.id.copy_scan -> {
scansAdapter?.getSelectedContent()?.let {
scansAdapter?.getSelectedContent("\n")?.let {
ac.copyToClipboard(it)
ac.toast(R.string.copied_to_clipboard)
}
@@ -84,19 +80,21 @@ class HistoryFragment : Fragment() {
true
}
R.id.edit_scan -> {
scansAdapter?.let {
askForName(
ac,
it.selectedScanId,
getScanName(it.selectedScanPosition)
scansAdapter?.forSelection { id, position ->
ac.askForName(
id,
scansAdapter?.getName(position),
scansAdapter?.getContent(position)
)
}
closeActionMode()
true
}
R.id.remove_scan -> {
scansAdapter?.let {
askToRemoveScan(ac, it.selectedScanId)
scansAdapter?.getSelectedIds()?.let {
if (it.isNotEmpty()) {
ac.askToRemoveScans(it)
}
}
closeActionMode()
true
@@ -146,8 +144,7 @@ class HistoryFragment : Fragment() {
showScan(id)
}
listView.setOnItemLongClickListener { _, v, position, id ->
v.isSelected = true
scansAdapter?.select(id, position)
scansAdapter?.select(v, id, position)
if (actionMode == null && ac is AppCompatActivity) {
actionMode = ac.delegate.startSupportActionMode(
actionModeCallback
@@ -159,7 +156,7 @@ class HistoryFragment : Fragment() {
fab = view.findViewById(R.id.share)
fab.setOnClickListener { v ->
pickListSeparatorAndShare(v.context)
v.context.pickListSeparatorAndShare()
}
progressView = view.findViewById(R.id.progress_view)
@@ -221,7 +218,7 @@ class HistoryFragment : Fragment() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.clear -> {
askToRemoveScans(context)
context.askToRemoveScans()
true
}
R.id.export_history -> {
@@ -300,20 +297,22 @@ class HistoryFragment : Fragment() {
}
}
private fun getScanName(position: Int): String? {
val cursor = scansAdapter?.getItem(position) as Cursor?
return cursor?.getString(Database.SCANS_NAME)
}
// Dialogs don't have a parent layout.
@SuppressLint("InflateParams")
private fun askForName(context: Context, id: Long, text: String?) {
val view = LayoutInflater.from(context).inflate(
private fun Context.askForName(id: Long, text: String?, content: String?) {
val view = LayoutInflater.from(this).inflate(
R.layout.dialog_enter_name, null
)
val nameView = view.findViewById<EditText>(R.id.name)
nameView.setText(text)
AlertDialog.Builder(context)
AlertDialog.Builder(this)
.setTitle(
if (content.isNullOrEmpty()) {
getString(R.string.binary_data)
} else {
content
}
)
.setView(view)
.setPositiveButton(android.R.string.ok) { _, _ ->
val name = nameView.text.toString()
@@ -324,11 +323,17 @@ class HistoryFragment : Fragment() {
.show()
}
private fun askToRemoveScan(context: Context, id: Long) {
AlertDialog.Builder(context)
.setMessage(R.string.really_remove_scan)
private fun Context.askToRemoveScans(ids: List<Long>) {
AlertDialog.Builder(this)
.setMessage(
if (ids.size > 1) {
R.string.really_remove_selected_scans
} else {
R.string.really_remove_scan
}
)
.setPositiveButton(android.R.string.ok) { _, _ ->
db.removeScan(id)
ids.forEach { db.removeScan(it) }
if (scansAdapter?.count == 1) {
updateAndClearFilter()
} else {
@@ -340,8 +345,8 @@ class HistoryFragment : Fragment() {
.show()
}
private fun askToRemoveScans(context: Context) {
AlertDialog.Builder(context)
private fun Context.askToRemoveScans() {
AlertDialog.Builder(this)
.setMessage(
if (filter == null) {
R.string.really_remove_all_scans
@@ -402,11 +407,11 @@ class HistoryFragment : Fragment() {
}
}
private fun pickListSeparatorAndShare(context: Context) {
val separators = context.resources.getStringArray(
private fun Context.pickListSeparatorAndShare() {
val separators = resources.getStringArray(
R.array.list_separators_values
)
AlertDialog.Builder(context)
AlertDialog.Builder(this)
.setTitle(R.string.pick_list_separator)
.setItems(R.array.list_separators_names) { _, which ->
shareScans(separators[which])
@@ -0,0 +1,92 @@
package de.markusfisch.android.binaryeye.fragment
import android.content.Context
import android.net.wifi.WifiManager
import android.net.wifi.WifiNetworkSuggestion
import android.os.Build
import android.os.Bundle
import android.support.annotation.RequiresApi
import android.support.v4.app.Fragment
import android.view.*
import android.widget.ArrayAdapter
import android.widget.ListView
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
import de.markusfisch.android.binaryeye.view.systemBarListViewScrollListener
import de.markusfisch.android.binaryeye.widget.toast
class NetworkSuggestionsFragment : Fragment() {
@RequiresApi(Build.VERSION_CODES.R)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
state: Bundle?
): View? {
val ac = activity ?: return null
ac.setTitle(R.string.network_suggestions)
val view = inflater.inflate(
R.layout.fragment_network_suggestions,
container,
false
)
val wm = ac.applicationContext.getSystemService(
Context.WIFI_SERVICE
) as WifiManager
val suggestionArrayAdapter = ArrayAdapter(
ac,
android.R.layout.simple_list_item_checked,
wm.networkSuggestions.map {
Suggestion(
it.ssid ?: it.toString(),
it
)
}
)
val listView = view.findViewById<ListView>(R.id.suggestions)
listView.emptyView = view.findViewById(R.id.no_suggestions)
listView.adapter = suggestionArrayAdapter
listView.setOnScrollListener(systemBarListViewScrollListener)
(view.findViewById(R.id.inset_layout) as View).setPaddingFromWindowInsets()
listView.setPaddingFromWindowInsets()
view.findViewById<View>(R.id.remove).setOnClickListener {
val removeList = ArrayList<WifiNetworkSuggestion>()
val removeFromAdapter = ArrayList<Suggestion>()
val checked = listView.checkedItemPositions
val size = checked.size()
for (i in 0 until size) {
if (checked.valueAt(i)) {
val pos = checked.keyAt(i)
listView.setItemChecked(pos, false)
val suggestion = listView.getItemAtPosition(
pos
) as Suggestion
removeList.add(suggestion.suggestion)
removeFromAdapter.add(suggestion)
}
}
if (removeList.isNotEmpty()) {
removeFromAdapter.forEach {
suggestionArrayAdapter.remove(it)
}
wm.removeNetworkSuggestions(removeList)
} else {
ac.toast(
R.string.clear_network_suggestions_nothing_to_remove
)
}
}
return view
}
}
private data class Suggestion(
val label: String,
val suggestion: WifiNetworkSuggestion
) {
override fun toString() = label
}
@@ -16,9 +16,10 @@ 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.actions.wifi.removeNetworkSuggestions
import de.markusfisch.android.binaryeye.activity.SplashActivity
import de.markusfisch.android.binaryeye.app.addFragment
import de.markusfisch.android.binaryeye.app.prefs
import de.markusfisch.android.binaryeye.media.beepConfirm
import de.markusfisch.android.binaryeye.preference.UrlPreference
import de.markusfisch.android.binaryeye.view.setPaddingFromWindowInsets
import de.markusfisch.android.binaryeye.view.systemBarRecyclerViewScrollListener
@@ -32,48 +33,63 @@ class PreferencesFragment : PreferenceFragmentCompat() {
) {
val preference = findPreference(key) ?: return
prefs.update()
if (preference.key == "custom_locale") {
activity?.restartApp()
} else {
setSummary(preference)
when (preference.key) {
"custom_locale" -> activity?.restartApp()
"beep_tone_name" -> {
beepConfirm()
setSummary(preference)
}
else -> setSummary(preference)
}
}
}
override fun onCreatePreferences(state: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences)
activity?.setTitle(R.string.preferences)
wireClearNetworkPreferences()
}
private fun wireClearNetworkPreferences() {
val pref = findPreference("clear_network_suggestions") ?: return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
pref.isVisible = false
} else {
pref.setOnPreferenceClickListener {
askToClearNetworkSuggestions(context)
true
findPreference("clear_network_suggestions").apply {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
// From R+ we can query past network suggestions and
// make them editable.
setOnPreferenceClickListener {
fragmentManager.addFragment(NetworkSuggestionsFragment())
true
}
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
// On Q, we can only clear *all* suggestions.
// Note that previous versions of this app allowed
// adding network suggestions on Q as well, so we
// need to keep this option.
setOnPreferenceClickListener {
context.askToClearNetworkSuggestions()
true
}
} else {
// There are no network suggestions below Q.
isVisible = false
}
}
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun askToClearNetworkSuggestions(context: Context) {
AlertDialog.Builder(context)
private fun Context.askToClearNetworkSuggestions() {
AlertDialog.Builder(this)
.setMessage(R.string.really_remove_all_networks)
.setPositiveButton(android.R.string.ok) { _, _ ->
clearNetworkSuggestions(context)
clearNetworkSuggestions()
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun clearNetworkSuggestions(context: Context) {
context.toast(
if (
removeNetworkSuggestions(context) == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS
private fun Context.clearNetworkSuggestions() {
toast(
if (removeAllNetworkSuggestions() ==
WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS
) {
R.string.clear_network_suggestions_success
} else {
@@ -84,6 +100,7 @@ class PreferencesFragment : PreferenceFragmentCompat() {
override fun onResume() {
super.onResume()
activity?.setTitle(R.string.preferences)
listView.setPaddingFromWindowInsets()
listView.removeOnScrollListener(systemBarRecyclerViewScrollListener)
listView.addOnScrollListener(systemBarRecyclerViewScrollListener)
@@ -152,3 +169,9 @@ private fun Activity.restartApp() {
// Restart to begin with an unmodified Locale to follow system settings.
Runtime.getRuntime().exit(0)
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun Context.removeAllNetworkSuggestions(): Int =
(applicationContext.getSystemService(
Context.WIFI_SERVICE
) as WifiManager).removeNetworkSuggestions(listOf())
@@ -50,15 +50,7 @@ class UrlDialogFragment : PreferenceDialogFragmentCompat() {
Scan(
"test",
null,
"none",
null,
null,
null,
null,
null,
null,
null,
null
"none"
).sendAsync(url, prefs.sendScanType) { code, body ->
textView.text = when {
code != null -> "$code"
@@ -49,8 +49,13 @@ private fun calculateInSampleSize(
return inSampleSize
}
fun Bitmap.crop(rect: RectF, rotation: Float) = try {
val erected = erect(rotation)
fun Bitmap.crop(
rect: RectF,
rotation: Float,
pivotX: Float,
pivotY: Float
) = try {
val erected = erect(rotation, pivotX, pivotY)
val w = erected.width
val h = erected.height
val x = max(0, (rect.left * w).roundToInt())
@@ -68,7 +73,11 @@ fun Bitmap.crop(rect: RectF, rotation: Float) = try {
null
}
private fun Bitmap.erect(rotation: Float): Bitmap = if (
private fun Bitmap.erect(
rotation: Float,
pivotX: Float,
pivotY: Float
): Bitmap = if (
rotation % 360f != 0f
) {
Bitmap.createBitmap(
@@ -78,7 +87,7 @@ private fun Bitmap.erect(rotation: Float): Bitmap = if (
width,
height,
Matrix().apply {
setRotate(rotation)
setRotate(rotation, pivotX, pivotY)
},
true
)
@@ -0,0 +1,4 @@
package de.markusfisch.android.binaryeye.graphics
const val COLOR_BLACK = 0xff000000.toInt()
const val COLOR_WHITE = 0xffffffff.toInt()
@@ -2,61 +2,86 @@ package de.markusfisch.android.binaryeye.graphics
import android.graphics.Matrix
import android.graphics.Rect
import com.google.zxing.ResultPoint
import android.graphics.RectF
import de.markusfisch.android.zxingcpp.ZxingCpp.Position
import kotlin.math.roundToInt
fun mapResultToView(
frameWidth: Int,
frameHeight: Int,
frameOrientation: Int,
viewRect: Rect,
resultPoints: Array<ResultPoint?>,
targetArray: FloatArray
): Int = getFrameToViewMatrix(
frameWidth,
frameHeight,
frameOrientation,
viewRect
).map(
resultPoints,
targetArray
data class FrameMetrics(
var width: Int = 0,
var height: Int = 0,
var orientation: Int = 0
)
fun getFrameToViewMatrix(
frameWidth: Int,
frameHeight: Int,
frameOrientation: Int,
viewRect: Rect
) = Matrix().apply {
// Normalize to frame dimensions for rotation.
postScale(
1f / frameWidth,
1f / frameHeight
)
// Rotate around center.
postRotate(frameOrientation.toFloat(), 0.5f, 0.5f)
// Scale up to view size.
postScale(viewRect.width().toFloat(), viewRect.height().toFloat())
// Apply view displacement.
postTranslate(viewRect.left.toFloat(), viewRect.top.toFloat())
fun Rect.setFrameRoi(
frameMetrics: FrameMetrics,
viewRect: Rect,
viewRoi: Rect
) {
Matrix().apply {
// Map ROI from view coordinates to frame coordinates.
setTranslate(-viewRect.left.toFloat(), -viewRect.top.toFloat())
postScale(1f / viewRect.width(), 1f / viewRect.height())
postRotate(-frameMetrics.orientation.toFloat(), .5f, .5f)
postScale(frameMetrics.width.toFloat(), frameMetrics.height.toFloat())
val frameRoiF = RectF()
val viewRoiF = RectF(
viewRoi.left.toFloat(),
viewRoi.top.toFloat(),
viewRoi.right.toFloat(),
viewRoi.bottom.toFloat()
)
mapRect(frameRoiF, viewRoiF)
set(
frameRoiF.left.roundToInt(),
frameRoiF.top.roundToInt(),
frameRoiF.right.roundToInt(),
frameRoiF.bottom.roundToInt()
)
}
}
fun Matrix.map(
resultPoints: Array<ResultPoint?>,
targetArray: FloatArray
): Int {
val max = targetArray.size
var i = 0
for (resultPoint in resultPoints) {
// Because ZXing apparently returns null in this array sometimes.
if (resultPoint == null) {
continue
fun Matrix.setFrameToView(
frameMetrics: FrameMetrics,
viewRect: Rect,
viewRoi: Rect? = null
) {
// Configure this matrix to map points in frame coordinates to
// view coordinates.
val uprightWidth: Int
val uprightHeight: Int
when (frameMetrics.orientation) {
90, 270 -> {
uprightWidth = frameMetrics.height
uprightHeight = frameMetrics.width
}
targetArray[i++] = resultPoint.x
targetArray[i++] = resultPoint.y
if (i >= max) {
break
else -> {
uprightWidth = frameMetrics.width
uprightHeight = frameMetrics.height
}
}
mapPoints(targetArray, 0, targetArray, 0, i)
setScale(
viewRect.width().toFloat() / uprightWidth,
viewRect.height().toFloat() / uprightHeight
)
viewRoi?.let {
postTranslate(viewRoi.left.toFloat(), viewRoi.top.toFloat())
}
}
fun Matrix.mapPosition(
position: Position,
coords: FloatArray
): Int {
var i = 0
setOf(
position.topLeft,
position.topRight,
position.bottomRight,
position.bottomLeft
).forEach {
coords[i++] = it.x.toFloat()
coords[i++] = it.y.toFloat()
}
mapPoints(coords)
return i
}
@@ -0,0 +1,57 @@
package de.markusfisch.android.binaryeye.graphics
import android.graphics.Bitmap
import android.graphics.Canvas
fun Bitmap.fixTransparency(): Bitmap {
val result = analyzeTransparency()
return if (result.hasTransparentPixels) {
val copy = Bitmap.createBitmap(
width,
height,
config
)
Canvas(copy).apply {
drawColor(result.backgroundColor)
drawBitmap(this@fixTransparency, 0f, 0f, null)
}
copy
} else {
this
}
}
private fun Bitmap.analyzeTransparency(): Result {
val pixels = IntArray(width * height)
getPixels(pixels, 0, width, 0, 0, width, height)
var transparent = 0
var visible = 0
var bright = 0
for (pixel in pixels) {
val alpha = (pixel shr 24) and 0xff
if (alpha < 0xff) {
++transparent
}
if (alpha > 0) {
++visible
if (
((pixel shr 16) and 0xff) +
((pixel shr 8) and 0xff) +
(pixel and 0xff) > 128
) ++bright
}
}
return Result(
transparent > 0,
if (bright > 0 && visible / bright < 2) {
COLOR_BLACK
} else {
COLOR_WHITE
}
)
}
private data class Result(
val hasTransparentPixels: Boolean,
val backgroundColor: Int
)
@@ -0,0 +1,33 @@
package de.markusfisch.android.binaryeye.media
import android.media.AudioManager
import android.media.ToneGenerator
import de.markusfisch.android.binaryeye.app.prefs
private var confirmToneGenerator: ToneGenerator? = null
private var errorToneGenerator: ToneGenerator? = null
fun beepConfirm() {
val tg = confirmToneGenerator ?: ToneGenerator(
AudioManager.STREAM_NOTIFICATION,
ToneGenerator.MAX_VOLUME
)
confirmToneGenerator = tg
tg.startTone(prefs.beepTone())
}
fun beepError() {
val tg = errorToneGenerator ?: ToneGenerator(
AudioManager.STREAM_ALARM,
ToneGenerator.MAX_VOLUME
)
errorToneGenerator = tg
tg.startTone(ToneGenerator.TONE_SUP_ERROR)
}
fun releaseToneGenerators() {
confirmToneGenerator?.release()
confirmToneGenerator = null
errorToneGenerator?.release()
errorToneGenerator = null
}
@@ -1,7 +1,6 @@
package de.markusfisch.android.binaryeye.net
import de.markusfisch.android.binaryeye.app.toHexString
import de.markusfisch.android.binaryeye.app.urlEncode
import de.markusfisch.android.binaryeye.content.toHexString
import de.markusfisch.android.binaryeye.database.Scan
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -69,13 +68,14 @@ private fun Scan.getMap(): Map<String, String> = mapOf(
"raw" to raw?.toHexString(),
"format" to format,
"errorCorrectionLevel" to errorCorrectionLevel,
"version" to version,
"sequenceSize" to sequenceSize.toString(),
"sequenceIndex" to sequenceIndex.toString(),
"sequenceId" to sequenceId,
"country" to country,
"addOn" to addOn,
"price" to price,
"issueNumber" to issueNumber,
"orientation" to orientation,
"otherMetaData" to otherMetaData,
"pdf417ExtraMetaData" to pdf417ExtraMetaData,
"possibleCountry" to possibleCountry,
"suggestedPrice" to suggestedPrice,
"upcEanExtension" to upcEanExtension,
"timestamp" to dateTime
).filterNullValues()
@@ -0,0 +1,10 @@
package de.markusfisch.android.binaryeye.net
import java.io.UnsupportedEncodingException
import java.net.URLEncoder
fun String.urlEncode(): String = try {
URLEncoder.encode(this, "UTF-8")
} catch (e: UnsupportedEncodingException) {
this
}
@@ -4,10 +4,8 @@ import android.content.Context
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.os.VibratorManager
import de.markusfisch.android.binaryeye.app.prefs
private const val DURATION_IN_MS = 100L
private const val DURATION_IN_MS = 250L
private val beforeO = Build.VERSION.SDK_INT < Build.VERSION_CODES.O
private val errorPatternTimings = longArrayOf(
@@ -17,7 +15,9 @@ private val errorPatternAmplitudes = intArrayOf(
255, 0, 255, 0, 255
)
fun Context.getVibrator(): Vibrator = if (
// On SDK 31 and better, we should ask the `VIBRATOR_MANAGER_SERVICE`
// for the default vibrator. This was implemented here before:
/*fun Context.getVibrator(): Vibrator = if (
Build.VERSION.SDK_INT < Build.VERSION_CODES.S
) {
@Suppress("DEPRECATION")
@@ -26,12 +26,18 @@ fun Context.getVibrator(): Vibrator = if (
(getSystemService(
Context.VIBRATOR_MANAGER_SERVICE
) as VibratorManager).defaultVibrator
}
}*/
// But for reasons beyond my interests, using `VIBRATOR_MANAGER_SERVICE`
// leads to a very cryptic `java.lang.VerifyError: r0/b` on Android 4.
// This is probably a Proguard/R8 issue, but I don't want to waste more
// time just to get rid of the deprecation warning. So let's use the old
// `VIBRATOR_SERVICE` and wait for Google to fix their stuff.
fun Context.getVibrator(): Vibrator = getSystemService(
Context.VIBRATOR_SERVICE
) as Vibrator
fun Vibrator.vibrate() {
if (!prefs.vibrate) {
return
} else if (beforeO) {
if (beforeO) {
@Suppress("DEPRECATION")
vibrate(DURATION_IN_MS)
} else {
@@ -45,9 +51,7 @@ fun Vibrator.vibrate() {
}
fun Vibrator.error() {
if (!prefs.vibrate) {
return
} else if (beforeO) {
if (beforeO) {
@Suppress("DEPRECATION")
vibrate(errorPatternTimings, -1)
} else {
@@ -2,31 +2,33 @@ package de.markusfisch.android.binaryeye.preference
import android.content.Context
import android.content.SharedPreferences
import android.media.ToneGenerator
import android.os.Build
import android.preference.PreferenceManager
import android.support.annotation.RequiresApi
import de.markusfisch.android.zxingcpp.ZxingCpp.Format
class Preferences {
lateinit var preferences: SharedPreferences
var barcodeFormats = setOf(
"AZTEC",
"CODABAR",
"CODE_39",
"CODE_93",
"CODE_128",
"DATA_MATRIX",
"EAN_8",
"EAN_13",
"ITF",
"MAXICODE",
"PDF_417",
"QR_CODE",
"RSS_14",
"RSS_EXPANDED",
"UPC_A",
"UPC_E",
"UPC_EAN_EXTENSION"
Format.AZTEC.name,
Format.CODABAR.name,
Format.CODE_39.name,
Format.CODE_93.name,
Format.CODE_128.name,
Format.DATA_BAR.name,
Format.DATA_BAR_EXPANDED.name,
Format.DATA_MATRIX.name,
Format.EAN_8.name,
Format.EAN_13.name,
Format.ITF.name,
Format.MAXICODE.name,
Format.PDF_417.name,
Format.QR_CODE.name,
Format.MICRO_QR_CODE.name,
Format.UPC_A.name,
Format.UPC_E.name,
)
@RequiresApi(Build.VERSION_CODES.HONEYCOMB)
set(value) {
@@ -58,39 +60,29 @@ class Preferences {
apply(ZOOM_BY_SWIPING, value)
field = value
}
var autoRotate = false
var autoRotate = true
set(value) {
// Immediately save this setting before it shouldn't change
// on the fly while scanning.
commit(AUTO_ROTATE, value)
apply(AUTO_ROTATE, value)
field = value
}
var tryHarder = false
set(value) {
// Immediately save this setting because it's only ever read
// before the camera is opened.
commit(TRY_HARDER, value)
apply(TRY_HARDER, value)
field = value
}
var bulkMode = false
set(value) {
// Immediately save this setting because it's only ever read
// before the camera is opened.
commit(BULK_MODE, value)
apply(BULK_MODE, value)
field = value
}
var bulkModeDelay = "500"
set(value) {
// Immediately save this setting because it's only ever read
// before the camera is opened.
commit(BULK_MODE_DELAY, value)
apply(BULK_MODE_DELAY, value)
field = value
}
var showToastInBulkMode = true
set(value) {
// Immediately save this setting because it's only ever read
// before the camera is opened.
commit(SHOW_TOAST_IN_BULK_MODE, value)
apply(SHOW_TOAST_IN_BULK_MODE, value)
field = value
}
var vibrate = true
@@ -98,6 +90,16 @@ class Preferences {
apply(VIBRATE, value)
field = value
}
var beep = false
set(value) {
apply(BEEP, value)
field = value
}
var beepToneName = "tone_prop_beep"
set(value) {
apply(BEEP_TONE_NAME, value)
field = value
}
var useHistory = false
set(value) {
apply(USE_HISTORY, value)
@@ -123,16 +125,16 @@ class Preferences {
apply(SHOW_META_DATA, value)
field = value
}
var showQrVersion = false
set(value) {
apply(SHOW_QR_VERSION, value)
field = value
}
var showHexDump = true
set(value) {
apply(SHOW_HEX_DUMP, value)
field = value
}
var showRecreation = true
set(value) {
apply(SHOW_RECREATION, value)
field = value
}
var closeAutomatically = false
set(value) {
apply(CLOSE_AUTOMATICALLY, value)
@@ -173,11 +175,9 @@ class Preferences {
apply(INDEX_OF_LAST_SELECTED_FORMAT, value)
field = value
}
var forceCompat = false
var freeRotation = true
set(value) {
// Since the app may be about to crash when forceCompat is set,
// it's necessary to `commit()` this synchronously.
commit(FORCE_COMPAT, value)
apply(FREE_ROTATION, value)
field = value
}
@@ -215,6 +215,10 @@ class Preferences {
showToastInBulkMode
)
vibrate = preferences.getBoolean(VIBRATE, vibrate)
beep = preferences.getBoolean(BEEP, beep)
preferences.getString(BEEP_TONE_NAME, beepToneName)?.also {
beepToneName = it
}
useHistory = preferences.getBoolean(USE_HISTORY, useHistory)
ignoreConsecutiveDuplicates = preferences.getBoolean(
IGNORE_CONSECUTIVE_DUPLICATES,
@@ -229,8 +233,8 @@ class Preferences {
openImmediately
)
showMetaData = preferences.getBoolean(SHOW_META_DATA, showMetaData)
showQrVersion = preferences.getBoolean(SHOW_QR_VERSION, showQrVersion)
showHexDump = preferences.getBoolean(SHOW_HEX_DUMP, showHexDump)
showRecreation = preferences.getBoolean(SHOW_RECREATION, showRecreation)
closeAutomatically = preferences.getBoolean(
CLOSE_AUTOMATICALLY,
closeAutomatically
@@ -258,7 +262,16 @@ class Preferences {
INDEX_OF_LAST_SELECTED_FORMAT,
indexOfLastSelectedFormat
)
forceCompat = preferences.getBoolean(FORCE_COMPAT, forceCompat)
freeRotation = preferences.getBoolean(FREE_ROTATION, freeRotation)
}
fun beepTone() = when (beepToneName) {
"tone_cdma_confirm" -> ToneGenerator.TONE_CDMA_CONFIRM
"tone_sup_radio_ack" -> ToneGenerator.TONE_SUP_RADIO_ACK
"tone_prop_ack" -> ToneGenerator.TONE_PROP_ACK
"tone_prop_beep" -> ToneGenerator.TONE_PROP_BEEP
"tone_prop_beep2" -> ToneGenerator.TONE_PROP_BEEP2
else -> ToneGenerator.TONE_PROP_BEEP
}
private fun put(label: String, value: Boolean) =
@@ -267,14 +280,6 @@ class Preferences {
private fun put(label: String, value: String) =
preferences.edit().putString(label, value)
private fun commit(label: String, value: Boolean) {
put(label, value).commit()
}
private fun commit(label: String, value: String) {
put(label, value).commit()
}
private fun apply(label: String, value: Boolean) {
put(label, value).apply()
}
@@ -293,7 +298,7 @@ class Preferences {
}
companion object {
private const val BARCODE_FORMATS = "barcode_formats"
private const val BARCODE_FORMATS = "formats"
private const val CROP_HANDLE_X = "crop_handle_x"
private const val CROP_HANDLE_Y = "crop_handle_y"
private const val CROP_HANDLE_ORIENTATION = "crop_handle_orientation"
@@ -305,13 +310,15 @@ class Preferences {
private const val BULK_MODE_DELAY = "bulk_mode_delay"
private const val SHOW_TOAST_IN_BULK_MODE = "show_toast_in_bulk_mode"
private const val VIBRATE = "vibrate"
private const val BEEP = "beep"
private const val BEEP_TONE_NAME = "beep_tone_name"
private const val USE_HISTORY = "use_history"
private const val IGNORE_CONSECUTIVE_DUPLICATES = "ignore_consecutive_duplicates"
private const val OPEN_IMMEDIATELY = "open_immediately"
private const val COPY_IMMEDIATELY = "copy_immediately"
private const val SHOW_META_DATA = "show_meta_data"
private const val SHOW_QR_VERSION = "show_qr_version"
private const val SHOW_HEX_DUMP = "show_hex_dump"
private const val SHOW_RECREATION = "show_recreation"
private const val CLOSE_AUTOMATICALLY = "close_automatically"
private const val DEFAULT_SEARCH_URL = "default_search_url"
private const val OPEN_WITH_URL = "open_with_url"
@@ -320,6 +327,6 @@ class Preferences {
private const val SEND_SCAN_TYPE = "send_scan_type"
private const val CUSTOM_LOCALE = "custom_locale"
private const val INDEX_OF_LAST_SELECTED_FORMAT = "index_of_last_selected_format"
private const val FORCE_COMPAT = "force_compat"
private const val FREE_ROTATION = "free_rotation"
}
}
@@ -1,42 +0,0 @@
package de.markusfisch.android.binaryeye.rs
import android.graphics.Bitmap
import android.graphics.Canvas
import android.support.v8.renderscript.Allocation
import android.support.v8.renderscript.RenderScript
fun fixTransparency(rs: RenderScript, bitmap: Bitmap?): Bitmap? {
bitmap ?: return null
val result = analyze(rs, bitmap)
return if (result.hasTransparentPixels) {
val copy = Bitmap.createBitmap(
bitmap.width,
bitmap.height,
bitmap.config
)
Canvas(copy).apply {
drawColor(result.backgroundColor)
drawBitmap(bitmap, 0f, 0f, null)
}
copy
} else {
bitmap
}
}
private fun analyze(rs: RenderScript, bitmap: Bitmap): Result {
val analyzeScript = ScriptC_analyze(rs)
val bitmapAllocation = Allocation.createFromBitmap(rs, bitmap)
val result = analyzeScript.reduce_analyze(bitmapAllocation).get()
bitmapAllocation.destroy()
analyzeScript.destroy()
return Result(
result.x > 0,
if (result.y > 0) 0xff000000.toInt() else 0xffffffff.toInt()
)
}
private data class Result(
val hasTransparentPixels: Boolean,
val backgroundColor: Int
)
@@ -1,156 +0,0 @@
package de.markusfisch.android.binaryeye.rs
import android.graphics.Rect
import android.support.v8.renderscript.*
import kotlin.math.max
import kotlin.math.roundToInt
private const val SCALE_FACTOR = .75f
class Preprocessor(
rs: RenderScript,
width: Int,
height: Int,
private val roi: Rect?
) {
var outWidth = 0
var outHeight = 0
private val resizeScript = ScriptIntrinsicResize.create(rs)
private val rotateScript = ScriptC_rotate(rs)
private var yuvType: Type? = null
private var yuvAlloc: Allocation? = null
private var roiType: Type? = null
private var roiAlloc: Allocation? = null
private var resizedType: Type? = null
private var resizedAlloc: Allocation? = null
private var rotatedType: Type? = null
private var rotatedAlloc: Allocation? = null
init {
yuvType = Type.createXY(
rs,
Element.U8(rs),
width,
height // use only grayscale part
)
yuvAlloc = Allocation.createTyped(
rs,
yuvType,
Allocation.USAGE_SCRIPT
)
if (roi != null) {
val roiWidth = roi.width()
val roiHeight = roi.height()
roiType = Type.createXY(
rs,
Element.U8(rs),
roiWidth,
roiHeight
)
roiAlloc = Allocation.createTyped(
rs,
roiType,
Allocation.USAGE_SCRIPT
)
outWidth = (roiWidth * SCALE_FACTOR).roundToInt()
outHeight = (roiHeight * SCALE_FACTOR).roundToInt()
// 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()
}
resizedType = Type.createXY(
rs,
Element.U8(rs),
outWidth,
outHeight
)
resizedAlloc = Allocation.createTyped(
rs,
resizedType,
Allocation.USAGE_SCRIPT
)
rotatedType = Type.createXY(
rs,
Element.U8(rs),
outHeight,
outWidth
)
rotatedAlloc = Allocation.createTyped(
rs,
rotatedType,
Allocation.USAGE_SCRIPT
)
}
fun destroy() {
yuvType?.destroy()
yuvType = null
yuvAlloc?.destroy()
yuvAlloc = null
roiType?.destroy()
roiType = null
roiAlloc?.destroy()
roiAlloc = null
resizedType?.destroy()
resizedType = null
resizedAlloc?.destroy()
resizedAlloc = null
rotatedType?.destroy()
rotatedType = null
rotatedAlloc?.destroy()
rotatedAlloc = null
resizeScript.destroy()
rotateScript.destroy()
}
fun resizeOnly(frame: ByteArray) {
resize(frame)
resizedAlloc?.copyTo(frame)
}
fun resizeAndRotate(frame: ByteArray) {
resize(frame)
val t = resizedType ?: return
rotateScript._inImage = resizedAlloc
rotateScript._inWidth = t.x
rotateScript._inHeight = t.y
rotateScript.forEach_rotate90(
rotatedAlloc, // Ignored in kernel, just to satisfy forEach.
rotatedAlloc
)
rotatedAlloc?.copyTo(frame)
}
private fun resize(frame: ByteArray) {
yuvAlloc?.copyFrom(frame)
resizeScript.setInput(
if (roi != null) {
roiAlloc?.copy2DRangeFrom(
0, 0,
roi.width(), roi.height(),
yuvAlloc,
max(0, roi.left), max(0, roi.top)
)
roiAlloc
} else {
yuvAlloc
}
)
resizeScript.forEach_bicubic(resizedAlloc)
}
}
@@ -8,11 +8,10 @@ import de.markusfisch.android.binaryeye.activity.CameraActivity
@RequiresApi(Build.VERSION_CODES.N)
class ScanTileService : TileService() {
@RequiresApi(Build.VERSION_CODES.N)
override fun onClick() {
super.onClick()
val intent = Intent(applicationContext, CameraActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivityAndCollapse(intent)
}
}
}
@@ -0,0 +1,37 @@
package de.markusfisch.android.binaryeye.view
import android.content.Context
import android.media.AudioManager
import de.markusfisch.android.binaryeye.app.prefs
import de.markusfisch.android.binaryeye.media.beepConfirm
import de.markusfisch.android.binaryeye.media.beepError
import de.markusfisch.android.binaryeye.os.error
import de.markusfisch.android.binaryeye.os.getVibrator
import de.markusfisch.android.binaryeye.os.vibrate
fun Context.scanFeedback() {
if (prefs.vibrate) {
getVibrator().vibrate()
}
if (prefs.beep && !isSilent()) {
beepConfirm()
}
}
fun Context.errorFeedback() {
if (prefs.vibrate) {
getVibrator().error()
}
if (!isSilent()) {
beepError()
}
}
private fun Context.isSilent(): Boolean {
val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager
return when (am.ringerMode) {
AudioManager.RINGER_MODE_SILENT,
AudioManager.RINGER_MODE_VIBRATE -> true
else -> false
}
}
@@ -100,14 +100,15 @@ class DetectorView : View {
}
private fun setCropHandlePos(x: Int, y: Int, orientation: Int) {
// Always set handlePos even if it's invalid because
// handlePos.x may be -2 which is a signal to set the
// default ROI.
if (orientation == currentOrientation) {
handlePos.set(x, y)
} else {
handlePos.set(y, x)
}
if (x > -1) {
handleActive = true
}
handleActive = handlePos.x > -1
}
fun update(numberOfCoordinates: Int) {
@@ -164,8 +165,8 @@ class DetectorView : View {
MotionEvent.ACTION_MOVE -> {
if (handleGrabbed) {
handlePos.set(x, y)
handleActive =
handleActive or (distSq(handlePos, touchDown) > minMoveThresholdSq)
handleActive = handleActive ||
distSq(handlePos, touchDown) > minMoveThresholdSq
if (handleActive) {
updateClipRect()
invalidate()
@@ -216,10 +217,10 @@ class DetectorView : View {
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
// 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
// Check if handle is close to a screen corner.
((abs(cy - minY) < distToFull || abs(maxY - cy) < distToFull) &&
abs(dx - center.x) < distToFull)
) {
@@ -260,23 +261,18 @@ class DetectorView : View {
override fun onDraw(canvas: Canvas) {
if (handleActive) {
drawClip(canvas)
canvas.drawClip()
}
drawDots(canvas)
canvas.drawDots()
if (prefs.showCropHandle) {
canvas.drawBitmap(
handleBitmap,
(handlePos.x - handleXRadius).toFloat(),
(handlePos.y - handleYRadius).toFloat(),
null
)
canvas.drawHandle()
}
}
private fun drawDots(canvas: Canvas) {
private fun Canvas.drawDots() {
var i = 0
while (i < coordinatesLast) {
canvas.drawCircle(
drawCircle(
coordinates[i++],
coordinates[i++],
dotRadius,
@@ -285,15 +281,15 @@ class DetectorView : View {
}
}
private fun drawClip(canvas: Canvas) {
private fun Canvas.drawClip() {
if (minDist < 1) {
return
}
// canvas.clipRect() doesn't work reliably below KITKAT.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val radius = min(minDist / 2, cornerRadius).toFloat()
canvas.save()
canvas.clipOutPathCompat(
save()
clipOutPathCompat(
calculateRoundedRectPath(
roi.left.toFloat(),
roi.top.toFloat(),
@@ -303,13 +299,22 @@ class DetectorView : View {
radius
)
)
canvas.drawColor(shadeColor)
canvas.restore()
drawColor(shadeColor)
restore()
} else {
canvas.drawRect(roi, roiPaint)
drawRect(roi, roiPaint)
}
}
private fun Canvas.drawHandle() {
drawBitmap(
handleBitmap,
(handlePos.x - handleXRadius).toFloat(),
(handlePos.y - handleYRadius).toFloat(),
null
)
}
private fun updateClipRect() {
clampHandlePos()
val dx = abs(handlePos.x - center.x)
@@ -1,196 +0,0 @@
package de.markusfisch.android.binaryeye.zxing
import android.graphics.Bitmap
import com.google.zxing.*
import com.google.zxing.common.BitMatrix
import com.google.zxing.common.HybridBinarizer
import java.util.*
class Zxing(possibleResultPoint: ResultPointCallback? = null) {
private val hints = EnumMap<DecodeHintType, Any>(DecodeHintType::class.java)
private val multiFormatReader = MultiFormatReader()
init {
possibleResultPoint?.let {
hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK] = it
}
}
fun updateHints(tryHarder: Boolean, formats: Set<String>) {
if (tryHarder) {
hints[DecodeHintType.TRY_HARDER] = java.lang.Boolean.TRUE
} else {
hints.remove(DecodeHintType.TRY_HARDER)
}
setDecodeFormats(formats)
}
private fun setDecodeFormats(formats: Set<String>) {
hints[DecodeHintType.POSSIBLE_FORMATS] = EnumSet.noneOf(
BarcodeFormat::class.java
).apply {
addAll(
EnumSet.copyOf(
formats.map { BarcodeFormat.valueOf(it) }
)
)
}
}
fun decode(
yuvData: ByteArray,
width: Int,
height: Int,
invert: Boolean = false
): Result? = decodeLuminanceSource(
PlanarYUVLuminanceSource(
yuvData,
width,
height,
0,
0,
width,
height,
false
),
invert
)
fun decodePositiveNegative(bitmap: Bitmap): Result? =
decode(bitmap, false) ?: decode(bitmap, true)
private fun decode(
bitmap: Bitmap,
invert: Boolean = false
): Result? {
val width = bitmap.width
val height = bitmap.height
val pixels = IntArray(width * height)
if (bitmap.config != Bitmap.Config.ARGB_8888) {
bitmap.copy(Bitmap.Config.ARGB_8888, true)
} else {
bitmap
}.getPixels(pixels, 0, width, 0, 0, width, height)
return decodeLuminanceSource(
RGBLuminanceSource(width, height, pixels),
invert
)
}
private fun decodeLuminanceSource(
source: LuminanceSource,
invert: Boolean
): Result? = decodeLuminanceSource(
if (invert) {
source.invert()
} else {
source
}
)
private fun decodeLuminanceSource(source: LuminanceSource): Result? = try {
multiFormatReader.decode(
BinaryBitmap(HybridBinarizer(source)),
hints
)
} catch (e: Exception) {
// Usually it's bad practice to blindly catch *all* exceptions
// because this can hide problems we want to know about. But
// since ZXing has some errors (like all software) and I don't
// want this app to break in the hands of my users, which won't
// see the stack trace anyway, it's better to just catch all
// exceptions here and live on.
null
} finally {
multiFormatReader.reset()
}
}
private const val BLACK = 0xff000000.toInt()
private const val WHITE = 0xffffffff.toInt()
fun encodeAsBitmap(
text: String,
format: BarcodeFormat,
width: Int,
height: Int,
hints: EnumMap<EncodeHintType, Any>? = null
): Bitmap? {
val bitMatrix = encode(text, format, hints, width, height)
val w = bitMatrix.width
val h = bitMatrix.height
val pixels = IntArray(w * h)
var offset = 0
for (y in 0 until h) {
for (x in 0 until w) {
pixels[offset + x] = if (bitMatrix.get(x, y)) {
BLACK
} else {
WHITE
}
}
offset += w
}
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
bitmap.setPixels(pixels, 0, w, 0, 0, w, h)
return bitmap
}
fun encodeAsSvg(
text: String,
format: BarcodeFormat,
hints: EnumMap<EncodeHintType, Any>? = null
): String {
val bitMatrix = encode(text, format, hints)
val sb = StringBuilder()
val w = bitMatrix.width
var h = bitMatrix.height
val moduleHeight = if (h == 1) w / 2 else 1
for (y in 0 until h) {
for (x in 0 until w) {
if (bitMatrix.get(x, y)) {
sb.append(" M${x},${y}h1v${moduleHeight}h-1z")
}
}
}
h *= moduleHeight
return """<svg width="$w" height="$h"
viewBox="0 0 $w $h"
xmlns="http://www.w3.org/2000/svg">
<path d="$sb"/>
</svg>
"""
}
fun encodeAsText(
text: String,
format: BarcodeFormat,
hints: EnumMap<EncodeHintType, Any>? = null
): String {
val bitMatrix = encode(text, format, hints)
val w = bitMatrix.width
val h = bitMatrix.height
val sb = StringBuilder()
for (y in 0 until h) {
for (x in 0 until w) {
sb.append(if (bitMatrix.get(x, y)) "" else " ")
}
sb.append("\n")
}
return sb.toString()
}
private fun encode(
text: String,
format: BarcodeFormat,
encodeHints: EnumMap<EncodeHintType, Any>? = null,
width: Int = 0,
height: Int = 0
): BitMatrix = MultiFormatWriter().encode(
text, format, width, height,
(encodeHints ?: EnumMap<EncodeHintType, Any>(EncodeHintType::class.java)).apply {
if (!contains(EncodeHintType.CHARACTER_SET)) {
this[EncodeHintType.CHARACTER_SET] = "utf-8"
}
}
)
@@ -1,3 +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="M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zm8-12v8h8V3h-8zm6 6h-4V5h4v4zm0 10h2v2h-2zm-6-6h2v2h-2zm2 2h2v2h-2zm-2 2h2v2h-2zm2 2h2v2h-2zm2-2h2v2h-2zm0-4h2v2h-2zm2 2h2v2h-2z"/>
<path android:fillColor="#FF000000" android:pathData="M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zm8-12v8h8V3h-8zm6 6h-4V5h4v4zm0 10h2v2h-2zm-6-6h2v2h-2zm2 2h2v2h-2zm-2 2h2v2h-2zm2 2h2v2h-2zm2-2h2v2h-2zm0-4h2v2h-2zm2 2h2v2h-2z"/>
</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="#ffffff" android:pathData="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 0.9-2 2v10c0 1.1 0.9 2 2 2h12c1.1 0 2-0.9 2-2V10c0-1.1-0.9-2-2-2zm-6 9c-1.1 0-2-0.9-2-2s0.9-2 2-2 2 0.9 2 2-0.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/>
</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="#ffffff" android:pathData="M12 17c1.1 0 2-0.9 2-2s-0.9-2-2-2-2 0.9-2 2 0.9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 0.9-2 2v10c0 1.1 0.9 2 2 2h12c1.1 0 2-0.9 2-2V10c0-1.1-0.9-2-2-2zm0 12H6V10h12v10z"/>
</vector>
@@ -1,5 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="90dp" android:height="90dp" android:viewportWidth="90" android:viewportHeight="90">
<path android:fillColor="#FF000000" android:pathData="M27 45a18 18 0 1 1 36 0 18 18 0 1 1-36 0" android:strokeWidth="4"/>
<path android:pathData="M31.738 45a13.262 13.262 0 1 1 26.524 0 13.262 13.262 0 1 1-26.524 0" android:strokeWidth="4" android:fillColor="#ffffff"/>
<path android:pathData="M54.41 45c0 2.303-0.827 4.412-2.201 6.048V38.952c1.374 1.636 2.201 3.745 2.201 6.048zM45 54.41c-0.27 0-0.537-0.012-0.801-0.034V35.624C44.463 35.602 44.73 35.59 45 35.59s0.537 0.012 0.801 0.034v18.752C45.537 54.398 45.27 54.41 45 54.41zM35.59 45c0-2.303 0.827-4.412 2.201-6.048v12.096C36.417 49.412 35.59 47.303 35.59 45zm13.415 8.517c-0.511 0.241-1.046 0.437-1.602 0.583V35.9c0.556 0.146 1.091 0.342 1.602 0.583v17.034zM42.597 54.1c-1.173-0.309-2.257-0.839-3.204-1.542V37.442c0.947-0.703 2.031-1.233 3.204-1.542v18.2z" android:strokeWidth="4" android:fillColor="#000000"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="90dp"
android:height="90dp"
android:viewportWidth="90"
android:viewportHeight="90">
<path
android:fillColor="#FF000000"
android:pathData="M58.262,45C58.262,52.324 52.324,58.262 45,58.262C37.676,58.262 31.738,52.324 31.738,45C31.738,37.676 37.676,31.738 45,31.738C52.324,31.738 58.262,37.676 58.262,45ZM45,27C35.059,27 27,35.059 27,45C27,54.941 35.059,63 45,63C54.941,63 63,54.941 63,45C63,35.059 54.941,27 45,27Z"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:strokeColor="#00000000"
android:strokeLineCap="butt"/>
<path
android:pathData="M54.41,45C54.41,47.303 53.583,49.412 52.209,51.048L52.209,38.952C53.583,40.588 54.41,42.697 54.41,45ZM45,54.41C44.73,54.41 44.463,54.398 44.199,54.376L44.199,35.624C44.463,35.602 44.73,35.59 45,35.59C45.27,35.59 45.537,35.602 45.801,35.624L45.801,54.376C45.537,54.398 45.27,54.41 45,54.41ZM35.59,45C35.59,42.697 36.417,40.588 37.791,38.952L37.791,51.048C36.417,49.412 35.59,47.303 35.59,45ZM49.005,53.517C48.494,53.758 47.959,53.954 47.403,54.1L47.403,35.9C47.959,36.046 48.494,36.242 49.005,36.483L49.005,53.517ZM42.597,54.1C41.424,53.791 40.34,53.261 39.393,52.558L39.393,37.442C40.34,36.739 41.424,36.209 42.597,35.9L42.597,54.1Z"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:strokeLineCap="butt"/>
</vector>
+1 -3
View File
@@ -1,7 +1,5 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/selected_row"
<item android:drawable="@color/pressed_row"
android:state_pressed="true"/>
<item android:drawable="@color/selected_row"
android:state_selected="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>
+1 -1
View File
@@ -17,6 +17,6 @@
style="@style/FAB"
android:id="@+id/scan"
android:contentDescription="@string/scan_code"
android:src="@drawable/ic_action_search"/>
android:src="@drawable/ic_action_next"/>
</android.support.design.widget.CoordinatorLayout>
</merge>
+22 -26
View File
@@ -8,18 +8,15 @@
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:gravity="start|top"
android:hint="@string/content"
android:imeOptions="flagNoExtractUi"
@@ -32,43 +29,42 @@
android:id="@+id/format"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/content"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:gravity="end|top"/>
<TableLayout
android:id="@+id/data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/format"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"/>
android:layout_marginBottom="16dp"/>
<TableLayout
android:id="@+id/meta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/data"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"/>
android:layout_marginBottom="16dp"/>
<TextView
android:id="@+id/hex"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/meta"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:typeface="monospace"
android:textSize="12sp"
tools:text="54 65 73 74 20 51 52 20 Test QR\n43 6F 64 65 Code"/>
</RelativeLayout>
<TextView
android:id="@+id/stamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textSize="12sp"
android:typeface="monospace"/>
<ImageView
android:id="@+id/recreation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="@string/view_barcode"/>
</LinearLayout>
</de.markusfisch.android.binaryeye.widget.ConfinedScrollView>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/inset_layout"
@@ -35,6 +35,18 @@
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:entries="@array/error_correction_levels"/>
<TextView
android:id="@+id/colors_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@string/colors"/>
<Spinner
android:id="@+id/colors"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:entries="@array/colors"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
+1 -1
View File
@@ -6,7 +6,7 @@
android:id="@+id/scans"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="singleChoice"
android:choiceMode="multipleChoice"
android:clipToPadding="false"
android:divider="@color/separator"
android:dividerHeight="1px"/>
@@ -0,0 +1,32 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/suggestions"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="multipleChoice"
android:clipToPadding="false"
android:divider="@color/separator"
android:dividerHeight="1px"/>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/inset_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:visibility="gone"
android:id="@+id/no_suggestions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:padding="32dp"
android:text="@string/clear_network_suggestions_nothing_to_remove"/>
<android.support.design.widget.FloatingActionButton
style="@style/FAB"
android:id="@+id/remove"
android:contentDescription="@string/remove_suggestion"
android:src="@drawable/ic_action_remove"/>
</android.support.design.widget.CoordinatorLayout>
</FrameLayout>
+5
View File
@@ -1,6 +1,11 @@
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:material="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/toggle_free"
android:title="@string/toggle_free_rotation"
android:icon="@drawable/ic_action_rotation_unlocked"
material:showAsAction="ifRoom"/>
<item
android:id="@+id/rotate"
android:title="@string/rotate_image_cw"
+28 -10
View File
@@ -15,14 +15,20 @@
<string name="error_correction_level_m" formatted="false">মধ্যম (~১৫&#37; ঠিককরণ)</string>
<string name="error_correction_level_q" formatted="false">বেশি (~২৫&#37; ঠিককরণ)</string>
<string name="error_correction_level_h" formatted="false">অনেক বেশি (~৩০&#37; ঠিককরণ)</string>
<string name="issue_number">সমস্যা ক্রম</string>
<string name="orientation">দিক</string>
<string name="other_meta_data">মেটাতথ্য</string>
<string name="pdf417_extra_metadata">পিডিএফ৪১৭ মেটাতথ্য</string>
<string name="possible_country">তৈরির সম্ভাব্য দেশ</string>
<string name="suggested_price">প্রস্তসবিত দাম</string>
<string name="upc_ean_extension">ইউপিসি ইএএন বর্ধিত</string>
<string name="qr_version">QR version</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">সমস্যা ক্রম</string>
<string name="gtin_country">তৈরির সম্ভাব্য দেশ</string>
<string name="gtin_price">প্রস্তসবিত দাম</string>
<string name="gtin_add_on">ইউপিসি ইএএন বর্ধিত</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">আলো</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">ভাগ করো</string>
@@ -75,6 +81,15 @@
<string name="show_toast_in_bulk_mode_summary">ধারাবাহিকভাবে তথ্য দেখানোর সময় মুহূর্তের জন্য তথ্য দেখাও।</string>
<string name="vibrate">চিনলে কাঁপো</string>
<string name="vibrate_summary">এটা সক্ষম রাখলে সংকেত চিনার সাথে সাথে কাঁপবে।</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">ইতিহাস সংরক্ষণ করো।</string>
<string name="use_history_summary">সনাক্তকৃত সংকেত যন্ত্রে সংরক্ষণ করো।</string>
<string name="ignore_consecutive_duplicates">দ্বিত্ব উপেক্ষা করো</string>
@@ -85,10 +100,10 @@
<string name="copy_immediately_summary">স্বয়ংক্রিয়ভাবে ক্লিপবোর্ডে অনুলিপি করো। বিশেষ দ্রষ্টব্য অন্য অ্যাপ পটভূমিতে এই তথ্য দেখে ফেলতে পারে।</string>
<string name="show_meta_data">মেটাতথ্য দেখাও</string>
<string name="show_meta_data_summary">সনাক্তকৃত বারকোড নিয়ে অতিরিক্ত তথ্য দেখাও।</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">ষড়(hex) সংকেত দেখাও</string>
<string name="show_hex_dump_summary">পড়া তথ্যের ষড় সংকেত দেখাও</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">অনুলিপি/ভাগ করার পরে পিছনে যাও</string>
<string name="close_automatically_summary">তথ্য অনুলিপি/ভাগ করার পরে স্বয়ংক্রিয়ভাবে পিছনে যাও।</string>
<string name="default_search_engine">Open unknown data in</string>
@@ -151,6 +166,7 @@
<string name="export_database">এসকিউলাইট তথ্যভিত্তি</string>
<string name="saved_in_downloads">ডাউনলোডে সংরক্ষিত</string>
<string name="rotate_image_cw">ছবি ঘড়ির দিকে ঘুরাও</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">ছবি নাও</string>
<string name="pick_code_to_scan">খুঁজার জন্য কোড নাও</string>
<string name="shortcut_decode">বারকোড খুজো</string>
@@ -167,4 +183,6 @@
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+28 -10
View File
@@ -17,14 +17,20 @@
<string name="error_correction_level_m" formatted="false">Střední (~15&#37; korekce)</string>
<string name="error_correction_level_q" formatted="false">Čtvrtinový (~25&#37; korekce)</string>
<string name="error_correction_level_h" formatted="false">Vysoký (~30&#37; korekce)</string>
<string name="issue_number">Číslo edice</string>
<string name="orientation">Orientace</string>
<string name="other_meta_data">Metadata</string>
<string name="pdf417_extra_metadata">PDF417 metadata</string>
<string name="possible_country">Možná země původu</string>
<string name="suggested_price">Doporučená cena</string>
<string name="upc_ean_extension">rozšíření UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">Číslo edice</string>
<string name="gtin_country">Možná země původu</string>
<string name="gtin_price">Doporučená cena</string>
<string name="gtin_add_on">rozšíření UPC EAN</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Zap/vyp blesk</string>
<string name="error_flash">Zapnutí/vypnutí blesku selhalo</string>
<string name="share">Sdílet</string>
@@ -77,6 +83,15 @@
<string name="show_toast_in_bulk_mode_summary">Krátce zobrazit data v módu nepřetržitého skenování.</string>
<string name="vibrate">Zavibrovat při detekování</string>
<string name="vibrate_summary">Zařízení zavibruje, když rozpozná čárový kód.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Ukládat historii skenování</string>
<string name="use_history_summary">Rozpoznané kódy se uloží do zařízení.</string>
<string name="ignore_consecutive_duplicates">Ignorovat duplikáty</string>
@@ -87,10 +102,10 @@
<string name="copy_immediately_summary">Automaticky zkopírovat naskenovaný obsah do schránky. Pozor, jiné aplikace jej mohou ze schránky přečíst, i když neběží.</string>
<string name="show_meta_data">Zobrazit metadata</string>
<string name="show_meta_data_summary">Zobrazí další data o naskenovaném čárovém kódu.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Zobrazit hex dump</string>
<string name="show_hex_dump_summary">Zobrazí hex dump naskenovaného obsahu.</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Vrátit se po zkopírování/sdílení</string>
<string name="close_automatically_summary">Po zkopírovaní či sdílení se automaticky vrátí na skenovací obrazovku.</string>
<string name="default_search_engine">Nerozpoznaná data otevřít v</string>
@@ -153,6 +168,7 @@
<string name="export_database">SQLite databáze</string>
<string name="saved_in_downloads">Uloženo do složky Stahování</string>
<string name="rotate_image_cw">Otočit obrázek po směru hodinových ručiček</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">Vybrat obrázek</string>
<string name="pick_code_to_scan">Vyberte kód k naskenování</string>
<string name="shortcut_decode">Skenovat čárový kód</string>
@@ -169,4 +185,6 @@
<string name="wifi_anonymous_identity">Anonymní identita</string>
<string name="wifi_identity">Identita</string>
<string name="wifi_phase2">Ověření Phase 2</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+188
View File
@@ -0,0 +1,188 @@
<resources>
<string name="no_camera_no_fun">Denne app giver ingen mening uden adgang til kameraet. Farvel.</string>
<string name="camera_error">Kan ikke få adgang til kamera, prøv igen</string>
<string name="scan_code">Scan kode</string>
<string name="compose_barcode">Opret stregkode</string>
<string name="decode_barcode">Afkod stregkode</string>
<string name="content">Indhold</string>
<string name="binary_data">(binære data)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d karakter, %1$s</item>
<item quantity="other">%2$d karakterer, %1$s</item>
</plurals>
<string name="error_correction_level">Fejlkorrektionsniveau</string>
<string name="error_correction_level_l" formatted="false">Lav (~7&#37; korrigering)</string>
<string name="error_correction_level_m" formatted="false">Medium (~15&#37; korrigering)</string>
<string name="error_correction_level_q" formatted="false">Kvartil (~25&#37; korrigering)</string>
<string name="error_correction_level_h" formatted="false">Høj (~30&#37; korrigering)</string>
<string name="colors">For- og baggrund</string>
<string name="colors_black_on_white">Sort på hvidt</string>
<string name="colors_white_on_black">Hvid på sort</string>
<string name="colors_black_on_transparent">Sort på gennemsigtig</string>
<string name="colors_white_on_transparent">Hvid på gennemsigtig</string>
<string name="sequence_size">Sekvens størrelse</string>
<string name="sequence_index">Sekvens indeks</string>
<string name="sequence_id">Sekvens ID</string>
<string name="gtin_issue_number">Udstedelsesnummer</string>
<string name="gtin_country">Muligt fremstillingsland</string>
<string name="gtin_price">Vejledende pris</string>
<string name="gtin_add_on">UPC EAN udvidelse</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d moduler)</string>
<string name="toggle_flash">Slå blitz til/fra</string>
<string name="error_flash">Der opstod en fejl ved at slå blitz til/fra</string>
<string name="share">Del</string>
<string name="share_as">Del som?</string>
<string name="copy_to_clipboard">Kopier til udklipsholder</string>
<string name="copied_to_clipboard">Kopieret til udklipsholder</string>
<string name="copy_password">Kopier adgangskode til udklipsholderen</string>
<string name="copied_password_to_clipboard">Adgangskode kopieret til udklipsholderen</string>
<string name="open_url">Åbn URL</string>
<string name="cannot_resolve_action">Inge applikation kan åbne det</string>
<string name="pick_search_engine">Vælg en søgemaskine</string>
<string name="format">Format</string>
<string name="size">Størrelse i pixels</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">Indtast indhold her</string>
<string name="encode">INDKOD</string>
<string name="error_no_content">Manglende indhold</string>
<string name="error_encoding_barcode">Stregkode kan ikke genereres</string>
<string name="view_barcode">Vis stregkode</string>
<string name="info">Info</string>
<string name="switch_camera">Skift kamera</string>
<string name="bulk_mode">Scan kontinuerligt</string>
<string name="bulk_mode_summary">Begynd altid ved at scanne kontinuerligt.</string>
<string name="bulk_mode_delay">Forsinkelse mellem kontinuerlige scanninger</string>
<string name="restrict_format">Begræns format</string>
<string name="remove_restriction">Fjern begrænsningen</string>
<string name="scan_format">Scan %s</string>
<string name="quarter_second">Et kvart sekund</string>
<string name="half_second">Et halvt sekund</string>
<string name="a_second">Et sekund</string>
<string name="two_seconds">To sekunder</string>
<string name="five_seconds">Fem sekunder</string>
<string name="history">Historik</string>
<string name="preferences">Præferencer</string>
<string name="scan_category">Scan</string>
<string name="content_category">Indhold</string>
<string name="locale_category">Sprog</string>
<string name="custom_locale">Brugerdefineret sprog</string>
<string name="follow_system_settings">Følg systemindstillingerne</string>
<string name="show_crop_handle">Vis beskæringsbegrænser</string>
<string name="show_crop_handle_summary">Begræns scanning til et område, der kan tilpasses.</string>
<string name="barcode_formats">Stregkode formater</string>
<string name="zoom_by_swiping">Stryg op/ned for at zoome</string>
<string name="zoom_by_swiping_summary">Stryg op eller ned på kameraskærmen for at styre kameraets zoom.</string>
<string name="auto_rotate">Genkend lodrette 1D stregkoder</string>
<string name="auto_rotate_summary">Roter automatisk kamerarammen for at genkende lodrette 1D stregkoder. Afhængigt af enheden kan dette påvirke ydeevnen.</string>
<string name="try_harder">Optimer læseren for nøjagtighed</string>
<string name="try_harder_summary">Aktiver denne mulighed for koder som er meget svære at læse. Vil påvirke ydeevnen.</string>
<string name="show_toast_in_bulk_mode">Vis data i kontinuerlig tilstand</string>
<string name="show_toast_in_bulk_mode_summary">Vis kort de scannede data, når du scanner kontinuerligt.</string>
<string name="vibrate">Vibrer ved registrering</string>
<string name="vibrate_summary">Aktiver dette, hvis du vil have din enhed til at vibrere, når en kode genkendes.</string>
<string name="beep">Bip ved registrering</string>
<string name="beep_summary">Aktiver dette, hvis du vil have din enhed til at bippe, når en kode genkendes.</string>
<string name="beep_tone">Bip tone</string>
<string name="tone_cdma_confirm">CDMA bekræftelse</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positiv anerkendelse</string>
<string name="tone_prop_beep">Generelt bip</string>
<string name="tone_prop_beep2">Generelt dobbelt bip</string>
<string name="use_history">Gem scanningshistorik</string>
<string name="use_history_summary">Gem genkendte koder på din enhed.</string>
<string name="ignore_consecutive_duplicates">Ignorer dubletter</string>
<string name="ignore_consecutive_duplicates_summary">Gem ikke fortløbende dubletter i scanningshistorikken.</string>
<string name="open_immediately">Åbn straks</string>
<string name="open_immediately_summary">Spring inspektion over og åbn indholdet med det samme. Kan åbne skadeligt indhold, hvis det er aktiveret.</string>
<string name="copy_immediately">Læg i udklipsholderen</string>
<string name="copy_immediately_summary">Kopier automatisk scannet indhold til udklipsholder. Bemærk at andre apps kan holde øje med din udklipsholder i baggrunden.</string>
<string name="show_meta_data">Vis metadata</string>
<string name="show_meta_data_summary">Vis yderligere data om den scannede stregkode.</string>
<string name="show_hex_dump">Vis hex-dump</string>
<string name="show_hex_dump_summary">Vis et hex-dump af det scannede indhold.</string>
<string name="show_recreation">Vis genskabt stregkode</string>
<string name="show_recreation_summary">Genskab og vis stregkode fra læst indhold, hvis det er muligt.</string>
<string name="close_automatically">Gå tilbage efter Kopier/Del</string>
<string name="close_automatically_summary">Vend automatisk tilbage til scanningsskærmen efter kopiering eller deling af det læste indhold.</string>
<string name="default_search_engine">Åbn ukendte data i</string>
<string name="always_ask">Spørg altid</string>
<string name="open_with_url">Åbn ukendte data med URL</string>
<string name="clear_network_suggestions">Fjern netværksforslag</string>
<string name="clear_network_suggestions_summary">Fjern netværksforslag, der tidligere blev tilføjet med denne app.</string>
<string name="really_remove_all_networks">Vil du virkelig fjerne alle netværk?</string>
<string name="clear_network_suggestions_success">Netværksforslag ryddet</string>
<string name="clear_network_suggestions_nothing_to_remove">Der er intet at fjerne</string>
<string name="send_category">Videresendelse</string>
<string name="send_scan_active">Videresend scanninger</string>
<string name="send_scan_active_summary">Aktiver for at videresende scanninger til en given URL.</string>
<string name="send_scan_url">URL at videresende til</string>
<string name="send_scan_type">Forespørgsels type</string>
<string name="send_type_get_add_content">GET og tilføj blot indhold</string>
<string name="send_type_get_query_string">GET med komplet forespørgselsstreng</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="send_type_external_browser">Åbn i ekstern browser</string>
<string name="test_url">Test URL</string>
<string name="really_remove_scan">Vil du virkelig fjerne scanningen?</string>
<string name="really_remove_all_scans">Vil du virkelig fjerne alle scanninger?</string>
<string name="really_remove_selected_scans">Vil du virkelig fjerne valgte scanninger?</string>
<string name="clear_history">Ryd historik</string>
<string name="copy_scan">Kopier scanning</string>
<string name="edit_scan">Rediger etiket</string>
<string name="remove_scan">Fjern scanning</string>
<string name="enter_name">Indtast et navn for at beskrive scanningen</string>
<string name="enter_name_hint">Navn på scanningen</string>
<string name="no_barcode_found">Ingen stregkode fundet</string>
<string name="pick_list_separator">Hvordan adskiller man listeelementer?</string>
<string name="separator_line_break">Linjeskift</string>
<string name="separator_ruler">Lineal</string>
<string name="save_as_file_name">Vil du gemme som i downloads?</string>
<string name="file_name">Filnavn</string>
<string name="error_saving_file">Kan ikke gemme filen</string>
<string name="error_file_exists">Filen findes allerede</string>
<string name="connect_to_wifi">Opret forbindelse til WiFi</string>
<string name="wifi_config_failed">Kunne ikke konfigurere WiFi</string>
<string name="wifi_added">WiFi tilføjet</string>
<string name="sms_send">Send SMS</string>
<string name="sms_error">Kunne ikke sende SMS</string>
<string name="tel_dial">Ring til nummer</string>
<string name="tel_error">Kunne ikke ringe til nummeret</string>
<string name="mail_send">Send mail</string>
<string name="mail_error">Kunne ikke sende mail</string>
<string name="vcard_add">Tilføj til kontakter</string>
<string name="vcard_failed">Kunne ikke føje til kontakter</string>
<string name="vevent_add">Tilføj til kalender</string>
<string name="vevent_failed">Kunne ikke føje til kalenderen</string>
<string name="otpauth_add">Tilføj 2FA</string>
<string name="search_web">Søg på nettet</string>
<string name="search_scan">Søg scanning</string>
<string name="export_to_file">Eksporter til fil</string>
<string name="export_as">Eksporter som?</string>
<string name="export_csv_comma">CSV-fil med kommaer</string>
<string name="export_csv_semicolon">CSV-fil med semikoloner</string>
<string name="export_json">JSON fil</string>
<string name="export_database">SQLite database</string>
<string name="saved_in_downloads">Gemt i downloads</string>
<string name="rotate_image_cw">Roter billedet med uret</string>
<string name="toggle_free_rotation">Slå fri rotation til/fra</string>
<string name="pick_file">Vælg billedfil</string>
<string name="pick_code_to_scan">Vælg kode til at scanne</string>
<string name="shortcut_decode">Scan en stregkode</string>
<string name="shortcut_encode">Opret en stregkode</string>
<string name="shortcut_preferences">Indstillinger</string>
<string name="background_request_failed">Baggrundsanmodning mislykkedes</string>
<string name="entry_type">Type</string>
<string name="wifi_network">WiFi netværk</string>
<string name="wifi_ssid">Navn</string>
<string name="wifi_type">Godkendelsestype</string>
<string name="wifi_password">Adgangskode</string>
<string name="wifi_hidden">Skjult netværk</string>
<string name="wifi_eap">EAP metode</string>
<string name="wifi_anonymous_identity">Anonym identitet</string>
<string name="wifi_identity">Identitet</string>
<string name="wifi_phase2">Fase 2 metode</string>
<string name="network_suggestions">Netværksforslag</string>
<string name="remove_suggestion">Fjern forslag</string>
</resources>
@@ -0,0 +1,30 @@
<resources>
<string-array name="search_engines_names">
<item>@string/always_ask</item>
<item>Google</item>
<item>DuckDuckGo</item>
<item>Qwant</item>
<item>Bing</item>
<item>Yandex</item>
<item>ebay</item>
<item>Amazon</item>
<item>OpenFoodFacts.org</item>
<item>OpenBeautyFacts.org</item>
<item>OpenPetFoodFacts.org</item>
<item>Barcode Lookup</item>
</string-array>
<string-array name="search_engines_values">
<item></item>
<item>https://www.google.de/search?q=</item>
<item>https://duckduckgo.com/?q=</item>
<item>https://www.qwant.com/?q=</item>
<item>https://bing.com/?q=</item>
<item>https://yandex.com/?q=</item>
<item>https://www.ebay.de/sch/i.html?_nkw=</item>
<item>https://www.amazon.de/s?k=</item>
<item>https://world.openfoodfacts.org/cgi/search.pl?search_terms=</item>
<item>https://world.openbeautyfacts.org/cgi/search.pl?search_terms=</item>
<item>https://world.openpetfoodfacts.org/cgi/search.pl?search_terms=</item>
<item>https://www.barcodelookup.com/</item>
</string-array>
</resources>
+31 -13
View File
@@ -15,14 +15,20 @@
<string name="error_correction_level_m" formatted="false">Medium (~15&#37; wiederherstellbar)</string>
<string name="error_correction_level_q" formatted="false">Quartile (~25&#37; wiederherstellbar)</string>
<string name="error_correction_level_h" formatted="false">High (~30&#37; wiederherstellbar)</string>
<string name="issue_number">Ausgabe Nummer</string>
<string name="orientation">Orientierung</string>
<string name="other_meta_data">Metadaten</string>
<string name="pdf417_extra_metadata">PDF417 Metadaten</string>
<string name="possible_country">Mögliches Ursprungsland</string>
<string name="suggested_price">Preisvorschlag</string>
<string name="upc_ean_extension">UPC EAN Erweiterung</string>
<string name="qr_version">QR Version</string>
<string name="colors">Vor und Hintergrund</string>
<string name="colors_black_on_white">Schwarz auf Weiß</string>
<string name="colors_white_on_black">Weiß auf Schwarz</string>
<string name="colors_black_on_transparent">Schwarz auf Transparent</string>
<string name="colors_white_on_transparent">Weiß auf Transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">Ausgabe Nummer</string>
<string name="gtin_country">Mögliches Ursprungsland</string>
<string name="gtin_price">Preisvorschlag</string>
<string name="gtin_add_on">UPC EAN Erweiterung</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d Module)</string>
<string name="toggle_flash">Licht an/ausschalten</string>
<string name="error_flash">Fehler beim ein/ausschalten des Lichts</string>
<string name="share">Teilen</string>
@@ -73,8 +79,17 @@
<string name="try_harder_summary">Aktivieren Sie diese Option für sehr schwer lesbare Codes. Beeinträchtigt die Leistung.</string>
<string name="show_toast_in_bulk_mode">Daten einblenden</string>
<string name="show_toast_in_bulk_mode_summary">Die gescannten Daten werden kurz eingeblendet, wenn fortlaufend gescannt wird.</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="vibrate">Vibration bei Erkennung</string>
<string name="vibrate_summary">Bei Erkennung eines Codes soll das Gerät vibrieren.</string>
<string name="beep">Signalton bei Erkennung</string>
<string name="beep_summary">Bei Erkennung eines Codes soll ein Signalton abgespielt werden.</string>
<string name="beep_tone">Signalton</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Codes speichern</string>
<string name="use_history_summary">Eingelesene Barcodes auf dem Gerät speichern.</string>
<string name="ignore_consecutive_duplicates">Duplikate ignorieren</string>
@@ -85,17 +100,17 @@
<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_qr_version">QR Version anzeigen</string>
<string name="show_qr_version_summary">Versionsnummer für QR Codes 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="show_recreation">Wiederhergestellten Barcode anzeigen</string>
<string name="show_recreation_summary">Barcode aus dem gelesenen Inhalt wiederherstellen und anzeigen, wenn möglich.</string>
<string name="close_automatically">Automatisch zurückkehren</string>
<string name="close_automatically_summary">Nach dem Kopieren/Teilen automatisch zum Scanbildschirm zurückkehren.</string>
<string name="default_search_engine">Unbekannte Daten öffnen mit</string>
<string name="always_ask">Immer fragen</string>
<string name="open_with_url">URL zum Öffnen unbekannter Daten</string>
<string name="clear_network_suggestions">WiFi Netzwerkvorschläge entfernen</string>
<string name="clear_network_suggestions_summary">Betrifft alle WiFi Netzwerke, die zuvor mit dieser App bereitgestellt wurden.</string>
<string name="clear_network_suggestions_summary">Betrifft nur Netzwerke, die zuvor mit dieser App bereitgestellt wurden.</string>
<string name="really_remove_all_networks">Alle Netzwerkvorschläge entfernen?</string>
<string name="clear_network_suggestions_success">Netzwerkvorschläge entfernt</string>
<string name="clear_network_suggestions_nothing_to_remove">Nichts zu entfernen</string>
@@ -151,6 +166,7 @@
<string name="export_database">SQLite Datenbank</string>
<string name="saved_in_downloads">In den Downloads gespeichert</string>
<string name="rotate_image_cw">Bild im Uhrzeigersinn rotieren</string>
<string name="toggle_free_rotation">Freie Rotation ein/ausschalten</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 lesen</string>
@@ -167,4 +183,6 @@
<string name="wifi_anonymous_identity">Anonyme Identität</string>
<string name="wifi_identity">Identität</string>
<string name="wifi_phase2">Phase 2 Methode</string>
<string name="network_suggestions">WiFi Netzwerkvorschläge</string>
<string name="remove_suggestion">Vorschlag entfernen</string>
</resources>
+48 -30
View File
@@ -1,5 +1,5 @@
<resources>
<string name="no_camera_no_fun">Esta aplicación no tiene sentido usar sin acceso a la cámara. Adiós.</string>
<string name="no_camera_no_fun">No tiene sentido usar esta aplicación sin acceso a la cámara. Adiós.</string>
<string name="camera_error">No se puede acceder a la cámara, por favor, inténtelo de nuevo</string>
<string name="scan_code">Escanear código de barras</string>
<string name="compose_barcode">Componer código de barras</string>
@@ -15,15 +15,21 @@
<string name="error_correction_level_m" formatted="false">Medio (~15&#37; de correción)</string>
<string name="error_correction_level_q" formatted="false">Cuartil (~25&#37; de correción)</string>
<string name="error_correction_level_h" formatted="false">Alto (~30&#37; de correción)</string>
<string name="issue_number">Número de emisión</string>
<string name="orientation">Orientación</string>
<string name="other_meta_data">Metadatos</string>
<string name="pdf417_extra_metadata">Metadatos PDF417</string>
<string name="possible_country">Posible país de fabricación</string>
<string name="suggested_price">Precio sugerido</string>
<string name="upc_ean_extension">Extensión UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="toggle_flash">Activar la linterna</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">Número de emisión</string>
<string name="gtin_country">Posible país de fabricación</string>
<string name="gtin_price">Precio sugerido</string>
<string name="gtin_add_on">Extensión UPC EAN</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Activar el flash</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Compartir</string>
<string name="share_as">¿Compartir como?</string>
@@ -46,15 +52,15 @@
<string name="switch_camera">Cambiar cámara</string>
<string name="bulk_mode">Escanear constantemente</string>
<string name="bulk_mode_summary">Siempre iniciar escaneando constantemente</string>
<string name="bulk_mode_delay">Delay between continuous scans</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="scan_format">Scan %s</string>
<string name="quarter_second">A quarter second</string>
<string name="half_second">Half a second</string>
<string name="a_second">One second</string>
<string name="two_seconds">Two seconds</string>
<string name="five_seconds">Five seconds</string>
<string name="bulk_mode_delay">Demora entre escaneos continuos</string>
<string name="restrict_format">Restringir formato</string>
<string name="remove_restriction">Eliminar restricción</string>
<string name="scan_format">Escanear %s</string>
<string name="quarter_second">Un cuarto de segundo</string>
<string name="half_second">Medio segundo</string>
<string name="a_second">Un segundo</string>
<string name="two_seconds">Dos segundos</string>
<string name="five_seconds">Cinco segundos</string>
<string name="history">Historial</string>
<string name="preferences">Configuración</string>
<string name="scan_category">Escanear</string>
@@ -75,6 +81,15 @@
<string name="show_toast_in_bulk_mode_summary">Mostrar brevemente los datos escaneados al escanear constantemente. </string>
<string name="vibrate">Vibrar al detectar</string>
<string name="vibrate_summary">Active esta opción si desea que su dispositivo vibre cuando se reconozca un código.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Guardar historial de escaneo</string>
<string name="use_history_summary">Guardar códigos reconocidos en su dispositivo.</string>
<string name="ignore_consecutive_duplicates">Ignorar duplicados</string>
@@ -85,10 +100,10 @@
<string name="copy_immediately_summary">Copiar contenido al portapapeles automáticamente. Ten en cuenta que otras aplicaciones pueden husmear en tu portapapeles en segundo plano.</string>
<string name="show_meta_data">Mostrar metadatos</string>
<string name="show_meta_data_summary">Mostrar datos adicionales del código escaneado.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Mostrar dump hexadecimal</string>
<string name="show_hex_dump_summary">Mostrar un dump hexadecimal del contenido escaneado.</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Retroceder luego de Copiar/Compartir</string>
<string name="close_automatically_summary">Regresar automáticamente a la pantalla de escaneo luego de copiar o compartir el contenido leído.</string>
<string name="default_search_engine">Abrir datos desconocidos en</string>
@@ -108,7 +123,7 @@
<string name="send_type_get_query_string">GET con consulta completa</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="send_type_external_browser">Open in external browser</string>
<string name="send_type_external_browser">Abrir en el navegador</string>
<string name="test_url">URL de prueba</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>
@@ -151,6 +166,7 @@
<string name="export_database">Base de datos SQLite</string>
<string name="saved_in_downloads">Guardado en Descargas</string>
<string name="rotate_image_cw">Rotar la imagen en sentido horario</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">Seleccionar imagen</string>
<string name="pick_code_to_scan">Seleccione el código a escanear</string>
<string name="shortcut_decode">Escanear un código</string>
@@ -158,13 +174,15 @@
<string name="shortcut_preferences">Ajustes</string>
<string name="background_request_failed">Solicitud de fondo fallida</string>
<string name="entry_type">Type</string>
<string name="wifi_network">Wi-Fi network</string>
<string name="wifi_ssid">Name</string>
<string name="wifi_type">Authentication type</string>
<string name="wifi_password">Password</string>
<string name="wifi_hidden">Hidden network</string>
<string name="wifi_eap">EAP method</string>
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_network">Red wi-fi</string>
<string name="wifi_ssid">Nombre</string>
<string name="wifi_type">Tipo de autenticación</string>
<string name="wifi_password">Contraseña</string>
<string name="wifi_hidden">Red oculta</string>
<string name="wifi_eap">Método EAP</string>
<string name="wifi_anonymous_identity">Identidad anónima</string>
<string name="wifi_identity">Identidad</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
@@ -0,0 +1,30 @@
<resources>
<string-array name="search_engines_names">
<item>@string/always_ask</item>
<item>گوگل</item>
<item>داک‌داک‌گو</item>
<item>Qwant</item>
<item>بینگ</item>
<item>یاندکس</item>
<item>ebay</item>
<item>Amazon</item>
<item>OpenFoodFacts.org</item>
<item>OpenBeautyFacts.org</item>
<item>OpenPetFoodFacts.org</item>
<item>Barcode Lookup</item>
</string-array>
<string-array name="search_engines_values">
<item></item>
<item>https://www.google.com/search?q=</item>
<item>https://duckduckgo.com/?q=</item>
<item>https://www.qwant.com/?q=</item>
<item>https://bing.com/?q=</item>
<item>https://yandex.com/?q=</item>
<item>https://www.ebay.com/sch/i.html?_nkw=</item>
<item>https://www.amazon.com/s?k=</item>
<item>https://world.openfoodfacts.org/cgi/search.pl?search_terms=</item>
<item>https://world.openbeautyfacts.org/cgi/search.pl?search_terms=</item>
<item>https://world.openpetfoodfacts.org/cgi/search.pl?search_terms=</item>
<item>https://www.barcodelookup.com/</item>
</string-array>
</resources>
+188
View File
@@ -0,0 +1,188 @@
<resources>
<string name="no_camera_no_fun">این برنامه بدون دسترسی به دوربین هیچ کارایی ندارد. خدانگهدار.</string>
<string name="camera_error">نمی‌توان به دوربین دسترسی داشت، لطفاً دوباره تلاش کنید</string>
<string name="scan_code">پویش کد</string>
<string name="compose_barcode">ایجاد بارکد</string>
<string name="decode_barcode">رمزگشایی بارکد</string>
<string name="content">محتویات</string>
<string name="binary_data">(دادهٔ دودویی)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d نویسه، %1$s</item>
<item quantity="other">%2$d نویسه، %1$s</item>
</plurals>
<string name="error_correction_level">سطح تصحیح خطا</string>
<string name="error_correction_level_l" formatted="false">کم (~۷٪⁩ تصحیح)</string>
<string name="error_correction_level_m" formatted="false">متوسط (⁦~۱۵٪⁩ تصحیح)</string>
<string name="error_correction_level_q" formatted="false">یک‌چهارم (⁦~۲۵٪⁩ تصحیح)</string>
<string name="error_correction_level_h" formatted="false">زیاد (~۳۰٪⁩ تصحیح)</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">شمارهٔ اشکال</string>
<string name="gtin_country">کشور احتمالی سازنده</string>
<string name="gtin_price">قیمت پیشنهادی</string>
<string name="gtin_add_on">UPC EAN extension</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">روشن/خاموش کردن چراغ</string>
<string name="error_flash">خطا هنگام روشن/خاموش کردن چراغ</string>
<string name="share">هم‌رسانی</string>
<string name="share_as">هم‌رسانی به عنوان؟</string>
<string name="copy_to_clipboard">رونوشت به تخه‌گیره</string>
<string name="copied_to_clipboard">به تخته‌گیره رونوشت شد</string>
<string name="copy_password">رونوشت گذرواژه به تخته‌گیره</string>
<string name="copied_password_to_clipboard">گذرواژه به تخته‌گیره رونوشت شد</string>
<string name="open_url">گشودن نشانی</string>
<string name="cannot_resolve_action">هیچ برنامه‌ای نمی‌تواند آن را بگشاید</string>
<string name="pick_search_engine">یک موتور جست‌وجو برگزینید</string>
<string name="format">قالب</string>
<string name="size">اندازه به پیکسل</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">محتویات ورودی را اینجا بنویسید</string>
<string name="encode">رمزگذاری</string>
<string name="error_no_content">محتویاتی نیست</string>
<string name="error_encoding_barcode">بارکد نمی‌تواند ایجاد شود</string>
<string name="view_barcode">نمایش بارکد</string>
<string name="info">اطّلاعات</string>
<string name="switch_camera">تغییر دوربین</string>
<string name="bulk_mode">به طور مداوم پویش کن</string>
<string name="bulk_mode_summary">همیشه پویش را به طور مداوم شروع می‌کند.</string>
<string name="bulk_mode_delay">تأخیر بین پویش‌های مداوم</string>
<string name="restrict_format">محدود کردن قالب</string>
<string name="remove_restriction">برداشتن محدودیت</string>
<string name="scan_format">پویش %s</string>
<string name="quarter_second">یک‌چهارم ثانیه</string>
<string name="half_second">نیم ثانیه</string>
<string name="a_second">یک ثانیه</string>
<string name="two_seconds">دو ثانیه</string>
<string name="five_seconds">پنج ثانیه</string>
<string name="history">تاریخچه</string>
<string name="preferences">ترجیحات</string>
<string name="scan_category">پویش</string>
<string name="content_category">محتویات</string>
<string name="locale_category">زبان</string>
<string name="custom_locale">زبان سفارشی</string>
<string name="follow_system_settings">پیروی از زبان سامانه</string>
<string name="show_crop_handle">نمایش محدود کننده برش</string>
<string name="show_crop_handle_summary">پویش را به یک منطقه قابل تنظیم محدود می‌کند.</string>
<string name="barcode_formats">قالب‌های بارکد</string>
<string name="zoom_by_swiping">برای بزرگنمایی به بالا یا پایین بکشید</string>
<string name="zoom_by_swiping_summary">برای کنترل بزرگنمایی دوربین، در صفحهٔ دوربین به بالا یا پایین بکشید.</string>
<string name="auto_rotate">تشخیص بارکدهای یک بعدی عمودی</string>
<string name="auto_rotate_summary">قاب دوربین را به صورت خودکار بچرخانید تا بارکدهای یک بعدی عمودی را تشخیص دهید. بسته به دستگاه، این ممکن است بر عملکرد تأثیر بگذارد.</string>
<string name="try_harder">بهینه کردن خواننده برای دقت بیشتر</string>
<string name="try_harder_summary">این گزینه را برای کدهایی که بسیار سخت خوانده می‌شوند، فعال کنید. بر عملکرد تأثیر خواهد گذاشت.</string>
<string name="show_toast_in_bulk_mode">نمایش داده‌ها در حالت پیوسته</string>
<string name="show_toast_in_bulk_mode_summary">هنگام پویش مداوم، داده‌های پویش شده را به طور خلاصه نشان می‌دهید.</string>
<string name="vibrate">لرزش هنگام تشخیص</string>
<string name="vibrate_summary">اگر می‌خواهید دستگاهتان هنگام شناسایی کد بلرزد، این را فعال کنید.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">ذخیرهٔ تاریخچهٔ پویش</string>
<string name="use_history_summary">کدهای شناسایی شده را در همین دستگاه ذخیره می‌کند.</string>
<string name="ignore_consecutive_duplicates">نادیده گرفتن موارد تکراری</string>
<string name="ignore_consecutive_duplicates_summary">موارد تکراری متوالی را در تاریخچهٔ پویش ذخیره نمی‌کند.</string>
<string name="open_immediately">گشودن بلافاصله</string>
<string name="open_immediately_summary">بازرسی را رها کنید و محتویات را فورا باز کنید. در صورت فعال بودن ممکن است محتوای مضر را باز کند.</string>
<string name="copy_immediately">قرار دادن در تخته‌گیره</string>
<string name="copy_immediately_summary">به طور خودکار محتوای پویش شده را در تخته‌گیره رونوشت می‌کند. لطفاً توجه داشته باشید که برنامه‌های دیگر ممکن است در پس‌زمینه تخته‌گیرهٔ شما را شنود کنند.</string>
<string name="show_meta_data">نمایش فراداده</string>
<string name="show_meta_data_summary">نمایش داده‌های اضافی در مورد بارکد پویش شده.</string>
<string name="show_hex_dump">نمایش کد هگز استخراج شده</string>
<string name="show_hex_dump_summary">نمایش کد هگز استخراج شده از محتویات پویش شده.</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">بازگشت پس از رونوشت یا هم‌رسانی</string>
<string name="close_automatically_summary">پس از رونوشت یا هم‌رسانی مطالب خوانده شده، به طور خودکار به صفحهٔ پویش بازگردید.</string>
<string name="default_search_engine">گشودن دادهٔ نامشخص در</string>
<string name="always_ask">همیشه بپرس</string>
<string name="open_with_url">داده‌های ناشناخته را با URL باز کنید</string>
<string name="clear_network_suggestions">پاک کردن پیشنهادات شبکه</string>
<string name="clear_network_suggestions_summary">همه پیشنهادات شبکه را که قبلاً توسط این برنامه ارائه شده است حذف کنید.</string>
<string name="really_remove_all_networks">واقعاً همه شبکه‌ها را حذف می‌کنید؟</string>
<string name="clear_network_suggestions_success">پیشنهادات شبکه پاک شد</string>
<string name="clear_network_suggestions_nothing_to_remove">چیزی برای حذف نیست</string>
<string name="send_category">هدایت کردن</string>
<string name="send_scan_active">هدایت پویش‌ها</string>
<string name="send_scan_active_summary">برای هدایت پویش‌ها به نشانی مشخص شده، آن را به کار بیاندازید.</string>
<string name="send_scan_url">نشانی برای هدایت به آن</string>
<string name="send_scan_type">گونهٔ درخواست</string>
<string name="send_type_get_add_content">GET و به سادگی محتوا را اضافه کنید</string>
<string name="send_type_get_query_string">GET با رشته پرس‌وجو کامل</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="send_type_external_browser">گشودن در مرورگر خارجی</string>
<string name="test_url">آزمودن نشانی</string>
<string name="really_remove_scan">برای برداشتن پویش مطمئنید؟</string>
<string name="really_remove_all_scans">برای برداشتن همهٔ پویش‌ها مطمئنید؟</string>
<string name="really_remove_selected_scans">برای برداشتن پویش‌های برگزیده شده مطمئنید؟</string>
<string name="clear_history">پاک کردن تاریخچه</string>
<string name="copy_scan">رونوشت پویش</string>
<string name="edit_scan">ویرایش عنوان</string>
<string name="remove_scan">برداشتن پویش</string>
<string name="enter_name">یک نام برای توضیح پویش وارد کنید</string>
<string name="enter_name_hint">نام پویش</string>
<string name="no_barcode_found">بارکدی یافت نشد</string>
<string name="pick_list_separator">چگونه موارد فهرست را جدا کنیم؟</string>
<string name="separator_line_break">خط بعدی</string>
<string name="separator_ruler">خط كش</string>
<string name="save_as_file_name">به عنوان پرونده در بارگیری‌ها ذخیره شود؟</string>
<string name="file_name">نام پرونده</string>
<string name="error_saving_file">نمی‌توان پرونده را ذخیره کرد</string>
<string name="error_file_exists">پرونده هم‌اکنون وجود دارد</string>
<string name="connect_to_wifi">اتّصال به وای‌فای</string>
<string name="wifi_config_failed">نمی‌توان وای‌فای را پیکربندی کرد</string>
<string name="wifi_added">وای‌فای اضافه شد</string>
<string name="sms_send">ارسال اس‌ام‌اس</string>
<string name="sms_error">نمی‌توان اس‌ام‌اس فرستاد</string>
<string name="tel_dial">تماس با شماره</string>
<string name="tel_error">نمی‌توان با شماره تماس گرفت</string>
<string name="mail_send">ارسال رایانامه</string>
<string name="mail_error">نمی‌توان رایانامه فرستاد</string>
<string name="vcard_add">افزودن به مخاطبین</string>
<string name="vcard_failed">نمی‌توان به مخاطبین اضافه کرد</string>
<string name="vevent_add">افزودن به تقویم</string>
<string name="vevent_failed">نمی‌توان به تقویم اضافه کرد</string>
<string name="otpauth_add">افزودن احراز هویت چندعاملی(2FA)</string>
<string name="search_web">جست‌وجوی وب</string>
<string name="search_scan">جست‌وجوی پویش</string>
<string name="export_to_file">برون‌ریزی به پرونده</string>
<string name="export_as">برون‌ریزی به عنوان؟</string>
<string name="export_csv_comma">پروندهٔ سی‌اس‌وی با ویرگول</string>
<string name="export_csv_semicolon">پروندهٔ سی‌اس‌وی با نقطه‌ویرگول</string>
<string name="export_json">پروندهٔ جی‌سون</string>
<string name="export_database">پایگاه‌دادهٔ اس‌کیولایت</string>
<string name="saved_in_downloads">در بارگیری‌ها ذخیره شد</string>
<string name="rotate_image_cw">تصویر را در جهت ساعتگرد بچرخانید</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">پروندهٔ تصویری را برگزینید</string>
<string name="pick_code_to_scan">کدی را برای پویش برگزینید</string>
<string name="shortcut_decode">پویش یک بارکد</string>
<string name="shortcut_encode">ایجاد یک بارکد</string>
<string name="shortcut_preferences">تنظیمات</string>
<string name="background_request_failed">درخواست پس‌زمینه انجام نشد</string>
<string name="entry_type">گونه</string>
<string name="wifi_network">شبکهٔ وای‌فای</string>
<string name="wifi_ssid">نام</string>
<string name="wifi_type">گونهٔ تأیید اعتبار</string>
<string name="wifi_password">گذرواژه</string>
<string name="wifi_hidden">شبکهٔ پنهان</string>
<string name="wifi_eap">روش EAP</string>
<string name="wifi_anonymous_identity">هویت ناشناس</string>
<string name="wifi_identity">هویت</string>
<string name="wifi_phase2">روش دو مرحله‌ای</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+46 -28
View File
@@ -16,16 +16,22 @@
<string name="error_correction_level_m" formatted="false">Moyen (~15% de correction)</string>
<string name="error_correction_level_q" formatted="false">Quartile (~25% de correction)</string>
<string name="error_correction_level_h" formatted="false">Élevé (~30% de correction)</string>
<string name="issue_number">Issue number</string>
<string name="orientation">Orientation</string>
<string name="other_meta_data">Métadonnées</string>
<string name="pdf417_extra_metadata">Métadonnées PDF417</string>
<string name="possible_country">Pays de fabrication possible</string>
<string name="suggested_price">Prix suggéré</string>
<string name="upc_ean_extension">Extension UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="colors">Premier plan et arrière-plan</string>
<string name="colors_black_on_white">Noir sur blanc</string>
<string name="colors_white_on_black">Blanc sur noir</string>
<string name="colors_black_on_transparent">Noir sur transparent</string>
<string name="colors_white_on_transparent">Blanc sur transparent</string>
<string name="sequence_size">Taille de la séquence</string>
<string name="sequence_index">Index de la séquence</string>
<string name="sequence_id">ID de la séquence</string>
<string name="gtin_issue_number">Numéro du problème</string>
<string name="gtin_country">Pays de fabrication possible</string>
<string name="gtin_price">Prix suggéré</string>
<string name="gtin_add_on">Extension UPC EAN</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Activer le flash</string>
<string name="error_flash">Error toggling flash</string>
<string name="error_flash">Erreur de basculement du flash</string>
<string name="share">Partager</string>
<string name="share_as">Partager comme ?</string>
<string name="copy_to_clipboard">Copier dans le presse-papiers</string>
@@ -46,10 +52,10 @@
<string name="info">Info</string>
<string name="switch_camera">Changer de camera</string>
<string name="bulk_mode">Scan continu</string>
<string name="bulk_mode_summary">Toujours démarrer en scannant en continu.</string>
<string name="bulk_mode_summary">Démarre toujours en scan continu.</string>
<string name="bulk_mode_delay">Délai entre les scans continus</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="restrict_format">Restreindre le format</string>
<string name="remove_restriction">Supprimer la restriction</string>
<string name="scan_format">Scan %s</string>
<string name="quarter_second">Un quart de seconde</string>
<string name="half_second">Une demi-seconde</string>
@@ -64,47 +70,56 @@
<string name="custom_locale">Langue personnalisée</string>
<string name="follow_system_settings">Suivre les réglages du système</string>
<string name="show_crop_handle">Afficher le bouton de rognage</string>
<string name="show_crop_handle_summary">Restreindre le scan à une région personnalisée.</string>
<string name="show_crop_handle_summary">Restreint le scan à une région personnalisée.</string>
<string name="barcode_formats">Formats de codes-barres</string>
<string name="zoom_by_swiping">Balayage haut/bas pour zoomer</string>
<string name="zoom_by_swiping_summary">Balayez vers le haut ou vers le bas dans l’écran de la caméra pour contrôler le zoom de la caméra.</string>
<string name="auto_rotate">Reconnaître les codes-barres 1D verticaux</string>
<string name="auto_rotate_summary">Tourner automatiquement le cadre de la caméra pour reconnaître les codes-barres 1D verticaux. En fonction de l\'appareil, cela peut affecter les performances.</string>
<string name="auto_rotate_summary">Tourne automatiquement le cadre de la caméra pour reconnaître les codes-barres 1D verticaux. En fonction de l\'appareil, cela peut affecter les performances.</string>
<string name="try_harder">Optimiser la précision du lecteur</string>
<string name="try_harder_summary">Activez cette option pour les codes très difficiles à lire. Affectera les performances.</string>
<string name="show_toast_in_bulk_mode">Afficher les données en mode continu</string>
<string name="show_toast_in_bulk_mode_summary">Afficher brièvement les données lors d\'un scan en continu.</string>
<string name="vibrate">Vibrer à la détection</string>
<string name="vibrate_summary">Activez ceci si vous voulez que votre appareil vibre lorsquun code est reconnu.</string>
<string name="vibrate_summary">Fait vibrer l\'appareil lorsqu\'un code est reconnu.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Sauvegarder l\'historique des scans</string>
<string name="use_history_summary">Sauvegarder les codes reconnus sur votre appareil.</string>
<string name="use_history_summary">Sauvegarde les codes reconnus sur votre appareil.</string>
<string name="ignore_consecutive_duplicates">Ignorer les doublons</string>
<string name="ignore_consecutive_duplicates_summary">Ne pas sauvegarder les doublons dans l\'historique des scans.</string>
<string name="ignore_consecutive_duplicates_summary">Ne sauvegarde pas les doublons dans l\'historique des scans.</string>
<string name="open_immediately">Ouvrir immédiatement</string>
<string name="open_immediately_summary">Sauter l\'inspection et ouvrir le contenu immédiatement. Si activé, cela peut ouvrir un contenu nocif.</string>
<string name="open_immediately_summary">Saute l\'inspection et ouvre le contenu immédiatement. Si activé, cela peut ouvrir un contenu nocif.</string>
<string name="copy_immediately">Mettre dans le presse-papiers</string>
<string name="copy_immediately_summary">Copier automatiquement les contenus scannés dans le presse-papiers. Veuillez noter que les autres applications peuvent fouiner dans votre presse-papiers en arrière-plan.</string>
<string name="copy_immediately_summary">Copie automatiquement les contenus scannés dans le presse-papiers. Veuillez noter que les autres applications peuvent fouiner dans votre presse-papiers en arrière-plan.</string>
<string name="show_meta_data">Afficher les méta-données</string>
<string name="show_meta_data_summary">Afficher les données supplémentaires sur le code-barres scanné.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_meta_data_summary">Affiche les données supplémentaires sur le code-barres scanné.</string>
<string name="show_hex_dump">Afficher le dump hexa</string>
<string name="show_hex_dump_summary">Affiche un dump hexadécimal du contenu scanné.</string>
<string name="show_hex_dump_summary">Affiche le dump hexadécimal du contenu scanné.</string>
<string name="show_recreation">Afficher le code-barres recréé</string>
<string name="show_recreation_summary">Recrée et affiche, si possible, le code-barres à partir du contenu lu.</string>
<string name="close_automatically">Revenir après une copie/partage</string>
<string name="close_automatically_summary">Revient automatiquement sur l\'écran de scan après avoir copié ou partagé le contenu lu.</string>
<string name="default_search_engine">Ouvrir les données inconnues dans</string>
<string name="always_ask">Toujours demander</string>
<string name="open_with_url">Ouvrir des données inconnues avec lURL</string>
<string name="clear_network_suggestions">Supprimer les suggestions de réseau</string>
<string name="clear_network_suggestions_summary">Supprimez toutes les suggestions de réseau précédemment fournies par cette application.</string>
<string name="clear_network_suggestions_summary">Supprime toutes les suggestions de réseau précédemment fournies par cette application.</string>
<string name="really_remove_all_networks">Supprimer vraiment tous les réseaux ?</string>
<string name="clear_network_suggestions_success">Suggestions de réseau supprimées</string>
<string name="clear_network_suggestions_nothing_to_remove">Rien à supprimer</string>
<string name="send_category">Transfert</string>
<string name="send_scan_active">Forward scans</string>
<string name="send_scan_active_summary">Enable to forward scans to a the given URL</string>
<string name="send_scan_url">Envoyer chaque scan vers une URL</string>
<string name="send_scan_type">Type de requête pour chaque scan</string>
<string name="send_scan_active">Transférer les scans</string>
<string name="send_scan_active_summary">Transfère les scans vers une URL donnée.</string>
<string name="send_scan_url">URL de transfert</string>
<string name="send_scan_type">Type de requête</string>
<string name="send_type_get_add_content">GET et ajouter simplement le contenu</string>
<string name="send_type_get_query_string">GET avec chaîne de requête complète</string>
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
@@ -152,6 +167,7 @@
<string name="export_database">Exporter la base de données SQLite</string>
<string name="saved_in_downloads">Sauvegardé dans les Téléchargements</string>
<string name="rotate_image_cw">Tourner l\'image dans le sens horaire</string>
<string name="toggle_free_rotation">Activer la rotation libre</string>
<string name="pick_file">Choisir un fichier image</string>
<string name="pick_code_to_scan">Choisissez le code à scanner</string>
<string name="shortcut_decode">Scanner un code-barres</string>
@@ -168,4 +184,6 @@
<string name="wifi_anonymous_identity">Identité anonyme</string>
<string name="wifi_identity">Identité</string>
<string name="wifi_phase2">Méthode de la phase 2</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+28 -10
View File
@@ -15,14 +15,20 @@
<string name="error_correction_level_m" formatted="false">Közepes (~15&#37; javítás)</string>
<string name="error_correction_level_q" formatted="false">Kvartilis (~25&#37; javítás)</string>
<string name="error_correction_level_h" formatted="false">Magas (~30&#37; javítás)</string>
<string name="issue_number">Hibaszám</string>
<string name="orientation">Tájolás</string>
<string name="other_meta_data">Metaadat</string>
<string name="pdf417_extra_metadata">PDF417 metaadat</string>
<string name="possible_country">Gyártó lehetséges országa</string>
<string name="suggested_price">Ajánlott ár</string>
<string name="upc_ean_extension">UPC EAN kiterjesztés</string>
<string name="qr_version">QR version</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">Hibaszám</string>
<string name="gtin_country">Gyártó lehetséges országa</string>
<string name="gtin_price">Ajánlott ár</string>
<string name="gtin_add_on">UPC EAN kiterjesztés</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Vaku be- vagy kikapcsolása</string>
<string name="error_flash">Hiba a vaku be- vagy kikapcsolásakor</string>
<string name="share">Megosztás</string>
@@ -75,6 +81,15 @@
<string name="show_toast_in_bulk_mode_summary">A beolvasott adatok gyors megjelenítése folyamatos beolvasáskor.</string>
<string name="vibrate">Rezgetés felismeréskor</string>
<string name="vibrate_summary">Akkor engedélyezze ezt, ha rezgetni szeretné az eszközét egy kód felismerésekor.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Beolvasási előzmények mentése</string>
<string name="use_history_summary">Felismert kódok mentése a saját eszközén.</string>
<string name="ignore_consecutive_duplicates">Ne mentsen egymást követő azonos adatokat</string>
@@ -85,10 +100,10 @@
<string name="copy_immediately_summary">Beolvasott tartalom automatikus másolása a vágólapra. Ne feledje, hogy más alkalmazások megfigyelhetik a vágólapját a háttérben.</string>
<string name="show_meta_data">Metaadatok megjelenítése</string>
<string name="show_meta_data_summary">További adatok megjelenítése a beolvasott vonalkódokról.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Hexakiírás megjelenítése</string>
<string name="show_hex_dump_summary">A beolvasott tartalom hexakiírásának megjelenítése.</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Ugrás vissza másolás vagy megosztás után</string>
<string name="close_automatically_summary">Automatikus visszatérés a beolvasási képernyőre a beolvasott tartalom másolása vagy megosztása után.</string>
<string name="default_search_engine">Ismeretlen adatok megnyitása ebben</string>
@@ -151,6 +166,7 @@
<string name="export_database">SQLite adatbázis</string>
<string name="saved_in_downloads">Elmentve a letöltésekbe</string>
<string name="rotate_image_cw">Kép forgatása jobbra</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">Képfájl kiválasztása</string>
<string name="pick_code_to_scan">Kód kiválasztása a beolvasáshoz</string>
<string name="shortcut_decode">Vonalkód beolvasása</string>
@@ -167,4 +183,6 @@
<string name="wifi_anonymous_identity">Névtelen személyazonosság</string>
<string name="wifi_identity">Személyazonosság</string>
<string name="wifi_phase2">Phase 2 módszer</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+65 -47
View File
@@ -14,16 +14,22 @@
<string name="error_correction_level_m" formatted="false">Medium (~15&#37; koreksi)</string>
<string name="error_correction_level_q" formatted="false">Kuartil (~25&#37; koreksi)</string>
<string name="error_correction_level_h" formatted="false">Tinggi (~30&#37; koreksi)</string>
<string name="issue_number">Nomor pindaian</string>
<string name="orientation">Orientasi</string>
<string name="other_meta_data">Metadata</string>
<string name="pdf417_extra_metadata">Metadata PDF417</string>
<string name="possible_country">Kemungkinan negara pembuat</string>
<string name="suggested_price">Harga yang disarankan</string>
<string name="upc_ean_extension">Ekstensi UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="colors">Muka dan latar belakang</string>
<string name="colors_black_on_white">Hitam di atas putih</string>
<string name="colors_white_on_black">Putih di atas hitam</string>
<string name="colors_black_on_transparent">Hitam di atas tansparan</string>
<string name="colors_white_on_transparent">Putih di atas tansparan</string>
<string name="sequence_size">Ukuran sekuens</string>
<string name="sequence_index">Indeks sekuens</string>
<string name="sequence_id">ID Sekuens</string>
<string name="gtin_issue_number">Nomor pindaian</string>
<string name="gtin_country">Kemungkinan negara pembuat</string>
<string name="gtin_price">Harga yang disarankan</string>
<string name="gtin_add_on">Ekstensi UPC EAN</string>
<string name="barcode_version_number">Versi</string>
<string name="qr_version_and_modules">%1$s (%2$d modul)</string>
<string name="toggle_flash">Nyala/matikan blitz</string>
<string name="error_flash">Error toggling flash</string>
<string name="error_flash">Galat nyala/matikan blitz</string>
<string name="share">Bagikan</string>
<string name="share_as">Bagikan sebagai?</string>
<string name="copy_to_clipboard">Salin ke clipboard</string>
@@ -44,16 +50,16 @@
<string name="info">Info</string>
<string name="switch_camera">Ganti kamera</string>
<string name="bulk_mode">Pindai tanpa henti</string>
<string name="bulk_mode_summary">Always start scanning continuously.</string>
<string name="bulk_mode_delay">Delay between continuous scans</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="scan_format">Scan %s</string>
<string name="quarter_second">A quarter second</string>
<string name="half_second">Half a second</string>
<string name="a_second">One second</string>
<string name="two_seconds">Two seconds</string>
<string name="five_seconds">Five seconds</string>
<string name="bulk_mode_summary">Selalu mulai pemindaian tanpa henti.</string>
<string name="bulk_mode_delay">Tundaan antara pemindaian tanpa henti</string>
<string name="restrict_format">Batasi format</string>
<string name="remove_restriction">Hapus pembatasan</string>
<string name="scan_format">Pindai %s</string>
<string name="quarter_second">Seperempat detik</string>
<string name="half_second">Setengah detik</string>
<string name="a_second">Satu detik</string>
<string name="two_seconds">Dua detik</string>
<string name="five_seconds">Lima detik</string>
<string name="history">Riwayat</string>
<string name="preferences">Preferensi</string>
<string name="scan_category">Pemindaian</string>
@@ -63,17 +69,26 @@
<string name="follow_system_settings">Ikuti pengaturan sistem</string>
<string name="show_crop_handle">Tampilkan pembatas pemotongan</string>
<string name="show_crop_handle_summary">Batasi pemindaian ke batas area tertentu.</string>
<string name="barcode_formats">Barcode formats</string>
<string name="barcode_formats">Format barcode</string>
<string name="zoom_by_swiping">Geser ke atas/bawah untuk memperbesar</string>
<string name="zoom_by_swiping_summary">Geser layar kamera ke atas atau ke bawah untuk mengontrol perbesaran gambar.</string>
<string name="auto_rotate">Kenali barcode vertikal 1D</string>
<string name="auto_rotate_summary">Otomatis putar frame kamera mengenali barcode vertikal 1D. Tergantung pada perangkat, mungkin akan berpengaruh pada performa.</string>
<string name="try_harder">Optimalkan akurasi pembaca</string>
<string name="try_harder_summary">Aktifkan opsi ini untuk kode yang susah dibaca. Akan berpengaruh pada performa.</string>
<string name="show_toast_in_bulk_mode">Show data in continuous mode</string>
<string name="show_toast_in_bulk_mode_summary">Briefly show the scanned data when scanning continuously.</string>
<string name="show_toast_in_bulk_mode">Tampilkan data dalam mode tanpa henti</string>
<string name="show_toast_in_bulk_mode_summary">Tampilkan data secara singkat saat memindai tanpa henti.</string>
<string name="vibrate">Bergetar saat mendeteksi</string>
<string name="vibrate_summary">Aktifkan opsi ini jika anda ingin perangkat anda bergetar ketika kode berhasil dipindai.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Simpan riwayat pemindaian</string>
<string name="use_history_summary">Simpan kode yang berhasil dipindai pada perangkat anda.</string>
<string name="ignore_consecutive_duplicates">Abaikan duplikat</string>
@@ -84,31 +99,31 @@
<string name="copy_immediately_summary">Otomatis menyalin konten yang dipindai ke dalam clipboard. Harap diingat bahwa apl lain bisa melihat isi dari clipboard anda di latar belakang.</string>
<string name="show_meta_data">Tampilkan metadata</string>
<string name="show_meta_data_summary">Tampilkan data tambahan tentang barcode yang dipindai.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Tampilkan hex dump</string>
<string name="show_hex_dump_summary">Tampilkan hex dump dari konten hasil pemindaian.</string>
<string name="close_automatically">Go back after Copy/Share</string>
<string name="close_automatically_summary">Automatically return to the scan screen after copying or sharing the read contents.</string>
<string name="default_search_engine">Open unknown data in</string>
<string name="always_ask">Always ask</string>
<string name="show_recreation">Tampilkan barcode yang dibuat ulang</string>
<string name="show_recreation_summary">Buat ulang dan tampilkan barcode dari isi konten jika memungkinkan.</string>
<string name="close_automatically">Kembali setelah Salin/Berbagi</string>
<string name="close_automatically_summary">Otomatis kembali ke layar pemindaian setelah menyalin atau berbagi isi konten.</string>
<string name="default_search_engine">Buka data tak dikenal di</string>
<string name="always_ask">Selalu tanya</string>
<string name="open_with_url">Buka data tak dikenal dengan URL</string>
<string name="clear_network_suggestions">Clear network suggestions</string>
<string name="clear_network_suggestions_summary">Remove all of the network suggestions that were previously provided by this app.</string>
<string name="really_remove_all_networks">Really remove all networks?</string>
<string name="clear_network_suggestions_success">Network suggestions cleared</string>
<string name="clear_network_suggestions_nothing_to_remove">Nothing to remove</string>
<string name="clear_network_suggestions">Hapus saran jaringan</string>
<string name="clear_network_suggestions_summary">Hapus semua saran jaringan yang sebelumnya disediakan oleh aplikasi ini.</string>
<string name="really_remove_all_networks">Yakin menghapus semua jaringan?</string>
<string name="clear_network_suggestions_success">Saran jaringan dihapus</string>
<string name="clear_network_suggestions_nothing_to_remove">Tidak ada yang perlu dihapus</string>
<string name="send_category">Penerusan</string>
<string name="send_scan_active">Forward scans</string>
<string name="send_scan_active_summary">Enable to forward scans to a the given URL</string>
<string name="send_scan_active">Teruskan pemindaian</string>
<string name="send_scan_active_summary">Aktifkan penerusan pemindaian ke URL berikut</string>
<string name="send_scan_url">Kirim setiap pindaian ke URL</string>
<string name="send_scan_type">Tipe permintaan untuk setiap pindaian</string>
<string name="send_type_get_add_content">GET dan tambahkan konten</string>
<string name="send_type_get_query_string">GET dengan kueri lema lengkap</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="send_type_external_browser">Open in external browser</string>
<string name="test_url">Test URL</string>
<string name="send_type_external_browser">Buka di peramban eksternal</string>
<string name="test_url">URL Tes</string>
<string name="really_remove_scan">Yakin menghapus pindaian?</string>
<string name="really_remove_all_scans">Yakin menghapus semua pindaian?</string>
<string name="really_remove_selected_scans">Yakin menghapus pindaian yang dipilih?</string>
@@ -150,20 +165,23 @@
<string name="export_database">Ekspor basis data SQLite</string>
<string name="saved_in_downloads">Simpan di dalam unduhan</string>
<string name="rotate_image_cw">Putar gambar searah jarum jam</string>
<string name="toggle_free_rotation">Nyala/matikan rotasi bebas</string>
<string name="pick_file">Pilih berkas gambar</string>
<string name="pick_code_to_scan">Pilih kode untuk dipindai</string>
<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">Permintaan latar belakang gagal</string>
<string name="entry_type">Type</string>
<string name="wifi_network">Wi-Fi network</string>
<string name="wifi_ssid">Name</string>
<string name="wifi_type">Authentication type</string>
<string name="wifi_password">Password</string>
<string name="wifi_hidden">Hidden network</string>
<string name="wifi_eap">EAP method</string>
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="entry_type">Tipe</string>
<string name="wifi_network">Jaringan Wi-Fi</string>
<string name="wifi_ssid">Nama</string>
<string name="wifi_type">Tipe otentikasi</string>
<string name="wifi_password">Sandi</string>
<string name="wifi_hidden">Jaringan tersembunyi</string>
<string name="wifi_eap">Metode EAP</string>
<string name="wifi_anonymous_identity">Identitas anonim</string>
<string name="wifi_identity">Identitas</string>
<string name="wifi_phase2">Metode fase 2</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+112 -94
View File
@@ -1,6 +1,6 @@
<resources>
<string name="no_camera_no_fun">Quest\'app non ha alcun senso senza l\'accesso alla fotocamera. Ciao.</string>
<string name="camera_error">Impossibile accedere alla fotocamera, riprova</string>
<string name="camera_error">Impossibile accedere alla fotocamera. Riprova</string>
<string name="scan_code">Scansiona codice</string>
<string name="compose_barcode">Crea codice a barre</string>
<string name="decode_barcode">Decodifica codice a barre</string>
@@ -10,34 +10,40 @@
<item quantity="one">%2$d carattere, %1$s</item>
<item quantity="other">%2$d caratteri, %1$s</item>
</plurals>
<string name="error_correction_level">Livello di correzione errori</string>
<string name="error_correction_level_l" formatted="false">Low (~7&#37; correction)</string>
<string name="error_correction_level_m" formatted="false">Medium (~15&#37; correction)</string>
<string name="error_correction_level_q" formatted="false">Quartile (~25&#37; correction)</string>
<string name="error_correction_level_h" formatted="false">High (~30&#37; correction)</string>
<string name="issue_number">Numero di edizione</string>
<string name="orientation">Orientamento</string>
<string name="other_meta_data">Metadati</string>
<string name="pdf417_extra_metadata">Metadati PDF417</string>
<string name="possible_country">Probabile Paese di fabbricazione</string>
<string name="suggested_price">Prezzo consigliato</string>
<string name="upc_ean_extension">Estensione UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="toggle_flash">Flash</string>
<string name="error_flash">Error toggling flash</string>
<string name="error_correction_level">Livello correzione errori</string>
<string name="error_correction_level_l" formatted="false">Basso (correzione del ~7&#37;)</string>
<string name="error_correction_level_m" formatted="false">Medio (correzione del ~15&#37;)</string>
<string name="error_correction_level_q" formatted="false">Quartile (correzione del ~25&#37;)</string>
<string name="error_correction_level_h" formatted="false">Alto (correzione del ~30&#37;)</string>
<string name="colors">Colore primo piano/sfondo</string>
<string name="colors_black_on_white">Nero su bianco</string>
<string name="colors_white_on_black">Bianco su nero</string>
<string name="colors_black_on_transparent">Nero su trasparente</string>
<string name="colors_white_on_transparent">Bianco su trasparente</string>
<string name="sequence_size">Dimensione sequenza</string>
<string name="sequence_index">Indice sequenza</string>
<string name="sequence_id">ID sequenza</string>
<string name="gtin_issue_number">Numero edizione</string>
<string name="gtin_country">Probabile nazione fabbricazione</string>
<string name="gtin_price">Prezzo consigliato</string>
<string name="gtin_add_on">Estensione UPC EAN</string>
<string name="barcode_version_number">Versione</string>
<string name="qr_version_and_modules">%1$s (%2$d moduli)</string>
<string name="toggle_flash">Attiva/disattiva flash</string>
<string name="error_flash">Errore durante l\'attivazione/disattivazione del flash</string>
<string name="share">Condividi</string>
<string name="share_as">Share as?</string>
<string name="copy_to_clipboard">Copia negli appunti</string>
<string name="copied_to_clipboard">Copiato negli appunti</string>
<string name="copy_password">Copia password negli appunti</string>
<string name="copied_password_to_clipboard">Password copiata negli appunti</string>
<string name="share_as">Condividi come?</string>
<string name="copy_to_clipboard">Copia negli Appunti</string>
<string name="copied_to_clipboard">Copiato negli Appunti</string>
<string name="copy_password">Copia password negli Appunti</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>
<string name="pick_search_engine">Scegli un motore di ricerca</string>
<string name="pick_search_engine">Scegli motore di ricerca</string>
<string name="format">Formato</string>
<string name="size">Dimensioni in pixel</string>
<string name="size">Dimensioni (pixel)</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">Inserisci il contenuto qui</string>
<string name="input_content_here">Inserisci qui il contenuto</string>
<string name="encode">CODIFICA</string>
<string name="error_no_content">Contenuto mancante</string>
<string name="error_encoding_barcode">Il codice a barre non può essere generato</string>
@@ -45,86 +51,95 @@
<string name="info">Info</string>
<string name="switch_camera">Cambia fotocamera</string>
<string name="bulk_mode">Scansione continua</string>
<string name="bulk_mode_summary">Always start scanning continuously.</string>
<string name="bulk_mode_delay">Delay between continuous scans</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="scan_format">Scan %s</string>
<string name="quarter_second">A quarter second</string>
<string name="half_second">Half a second</string>
<string name="a_second">One second</string>
<string name="two_seconds">Two seconds</string>
<string name="five_seconds">Five seconds</string>
<string name="bulk_mode_summary">Avvia sempre la scansione in modo continuo.</string>
<string name="bulk_mode_delay">Ritardo tra scansioni continue</string>
<string name="restrict_format">Limita formato</string>
<string name="remove_restriction">Rimuovi la limitazione</string>
<string name="scan_format">Scansiona %s</string>
<string name="quarter_second">Un quarto di secondo</string>
<string name="half_second">Mezzo secondo</string>
<string name="a_second">Un secondo</string>
<string name="two_seconds">Due secondi</string>
<string name="five_seconds">Cinque secondi</string>
<string name="history">Cronologia</string>
<string name="preferences">Preferenze</string>
<string name="scan_category">Scansione</string>
<string name="content_category">Contenuto</string>
<string name="locale_category">Language</string>
<string name="custom_locale">Custom language</string>
<string name="follow_system_settings">Follow system settings</string>
<string name="show_crop_handle">Mostra riquadro di limite</string>
<string name="locale_category">Lingua</string>
<string name="custom_locale">Lingua personalizzata</string>
<string name="follow_system_settings">Usa le impostazioni di sistema</string>
<string name="show_crop_handle">Visualizza riquadro limite</string>
<string name="show_crop_handle_summary">Limita la scansione ad una regione personalizzata.</string>
<string name="barcode_formats">Barcode formats</string>
<string name="barcode_formats">Formati codici a barre</string>
<string name="zoom_by_swiping">Zoom fotocamera scorrendo su/giù</string>
<string name="zoom_by_swiping_summary">Scorri su o giù per controllare lo zoom della fotocamera.</string>
<string name="auto_rotate">Riconosci i codici a barre 1D verticalmente</string>
<string name="auto_rotate_summary">Ruota automaticamente la fotocamera per riconoscere i codici a barre 1D verticali. In base al dispositivo, potrebbe ridurre le prestazioni.</string>
<string name="try_harder">Ottimizza il lettore per accuratezza, non velocità</string>
<string name="auto_rotate">Riconosci codici a barre verticali</string>
<string name="auto_rotate_summary">Ruota automaticamente la fotocamera per riconoscere i codici a barre verticali. In base al dispositivo, potrebbe ridurre le prestazioni.</string>
<string name="try_harder">Ottimizza il lettore per accuratezza</string>
<string name="try_harder_summary">Attiva questa opzione per codici molto difficili da leggere. Riduce le prestazioni.</string>
<string name="show_toast_in_bulk_mode">Show data in continuous mode</string>
<string name="show_toast_in_bulk_mode_summary">Briefly show the scanned data when scanning continuously.</string>
<string name="show_toast_in_bulk_mode">Visualizza i dati in modalità continua</string>
<string name="show_toast_in_bulk_mode_summary">Durante la scansione continua vsualizza brevemente i dati scansionati.</string>
<string name="vibrate">Vibra quando rilevato</string>
<string name="vibrate_summary">Attivalo se vuoi che il dispositivo vibri quando viene riconosciuto un codice.</string>
<string name="use_history">Salva cronologia delle scansioni</string>
<string name="use_history_summary">Salva i codici riconosciuti sul dispositivo.</string>
<string name="ignore_consecutive_duplicates">Non salvare doppi consecutivi</string>
<string name="ignore_consecutive_duplicates_summary">Non salvare doppi consecutivi nella cronologia di scansione.</string>
<string name="open_immediately">Salta l\'analisi e apri i contenuti direttamente</string>
<string name="open_immediately_summary">Salta l\'analisi e apri i contenuti direttamente. Se attivo potrebbe aprire contenuti dannosi.</string>
<string name="copy_immediately">Copia negli appunti</string>
<string name="copy_immediately_summary">Copia automaticamente i contenuti scansionati negli appunti. Nota che altre app potrebbero leggere gli appunti in secondo piano.</string>
<string name="show_meta_data">Mostra metadati</string>
<string name="show_meta_data_summary">Mostra dati aggiuntivi sul codice a barre scansionato.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Mostra dump esadecimale</string>
<string name="show_hex_dump_summary">Mostra un dump esadecimale dei contenuti scansionati.</string>
<string name="close_automatically">Go back after Copy/Share</string>
<string name="close_automatically_summary">Automatically return to the scan screen after copying or sharing the read contents.</string>
<string name="default_search_engine">Open unknown data in</string>
<string name="always_ask">Always ask</string>
<string name="beep">Beep al rilevamento</string>
<string name="beep_summary">Abilita questa opzione se vuoi che il dispositivo emetta un beep quando viene riconosciuto un codice.</string>
<string name="beep_tone">Tono beep</string>
<string name="tone_cdma_confirm">Conferma CDMA</string>
<string name="tone_sup_confirm">Conferma supervisione chiamata</string>
<string name="tone_sup_radio_ack">Riconoscimento percorso radio supervisione chiamata</string>
<string name="tone_prop_ack">Riconoscimento positivo</string>
<string name="tone_prop_beep">Beep generale</string>
<string name="tone_prop_beep2">Doppio beep generale</string>
<string name="use_history">Salva cronologia scansioni</string>
<string name="use_history_summary">Salva i codici riconosciuti nel dispositivo.</string>
<string name="ignore_consecutive_duplicates">Ignora i duplicati</string>
<string name="ignore_consecutive_duplicates_summary">Non salvare duplicati consecutivi nella cronologia di scansione.</string>
<string name="open_immediately">Apri subito</string>
<string name="open_immediately_summary">Salta l\'ispezione e apri i contenuti immediatamente. Se abilitato può aprire contenuti dannosi.</string>
<string name="copy_immediately">Copia negli Appunti</string>
<string name="copy_immediately_summary">Copia automaticamente i contenuti scansionati negli Appunti. Nota che altre app potrebbero leggere gli Appunti in secondo piano.</string>
<string name="show_meta_data">Visualizza metadati</string>
<string name="show_meta_data_summary">Visualizza dati aggiuntivi sul codice a barre scansionato.</string>
<string name="show_hex_dump">Visualizza dump esadecimale</string>
<string name="show_hex_dump_summary">Visualizza un dump esadecimale dei contenuti scansionati.</string>
<string name="show_recreation">Visualizza il codice a barre ricreato</string>
<string name="show_recreation_summary">Ricrea e visualizza, se possibile, il codice a barre dal contenuto letto.</string>
<string name="close_automatically">Vai indietro dopo la copia/condivisione</string>
<string name="close_automatically_summary">Dopo aver copiato o condiviso i contenuti letti torna automaticamente alla schermata di scansione.</string>
<string name="default_search_engine">Apri dati sconosciuti in</string>
<string name="always_ask">Chiedi sempre</string>
<string name="open_with_url">Apri dati sconosciuti con URL</string>
<string name="clear_network_suggestions">Clear network suggestions</string>
<string name="clear_network_suggestions_summary">Remove all of the network suggestions that were previously provided by this app.</string>
<string name="really_remove_all_networks">Really remove all networks?</string>
<string name="clear_network_suggestions_success">Network suggestions cleared</string>
<string name="clear_network_suggestions_nothing_to_remove">Nothing to remove</string>
<string name="clear_network_suggestions">Cancella suggerimenti di rete</string>
<string name="clear_network_suggestions_summary">Cancella tutti i suggerimenti di rete precedentemente forniti da questa app.</string>
<string name="really_remove_all_networks">Vuoi rimuovere tutte le reti?</string>
<string name="clear_network_suggestions_success">Suggerimenti di rete cancellati</string>
<string name="clear_network_suggestions_nothing_to_remove">Niente da rimuovere</string>
<string name="send_category">Inoltro</string>
<string name="send_scan_active">Forward scans</string>
<string name="send_scan_active_summary">Enable to forward scans to a the given URL</string>
<string name="send_scan_url">Invia ogni scansione ad un URL</string>
<string name="send_scan_type">Tipo di richiesta per ogni scansione</string>
<string name="send_type_get_add_content">GET e aggiungi il contenuto</string>
<string name="send_type_get_query_string">GET con stringa completa della richiesta</string>
<string name="send_scan_active">Inoltra le scansioni</string>
<string name="send_scan_active_summary">Abilita per inoltrare le scansioni a un URL specificato</string>
<string name="send_scan_url">URL a cui inoltrare</string>
<string name="send_scan_type">Tipo di richiesta</string>
<string name="send_type_get_add_content">OTTIENI e aggiungi il contenuto</string>
<string name="send_type_get_query_string">OTTIENI con stringa completa della richiesta</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="send_type_external_browser">Open in external browser</string>
<string name="test_url">Test URL</string>
<string name="really_remove_scan">Vuoi veramente rimuovere la scansione?</string>
<string name="really_remove_all_scans">Vuoi veramente rimuovere tutte le scansioni?</string>
<string name="really_remove_selected_scans">Vuoi veramente rimuovere le scansioni selezionate?</string>
<string name="clear_history">Pulisci cronologia</string>
<string name="send_type_external_browser">Apri nel browser esterno</string>
<string name="test_url">Prova URL</string>
<string name="really_remove_scan">Vuoi rimuovere la scansione?</string>
<string name="really_remove_all_scans">Vuoi rimuovere tutte le scansioni?</string>
<string name="really_remove_selected_scans">Vuoi rimuovere le scansioni selezionate?</string>
<string name="clear_history">Azzera cronologia</string>
<string name="copy_scan">Copia scansione</string>
<string name="edit_scan">Modifica etichetta</string>
<string name="remove_scan">Rimuovi scansione</string>
<string name="enter_name">Inserisci un nome per descrivere la scansione</string>
<string name="enter_name_hint">Nome della scansione</string>
<string name="enter_name_hint">Nome scansione</string>
<string name="no_barcode_found">Nessun codice a barre trovato</string>
<string name="pick_list_separator">Come separare elementi della lista?</string>
<string name="separator_line_break">Interruzione di linea</string>
<string name="separator_ruler">Righello</string>
<string name="save_as_file_name">Salvare come file?</string>
<string name="file_name">Nome del file</string>
<string name="save_as_file_name">Salva come file nei Download?</string>
<string name="file_name">Nome file</string>
<string name="error_saving_file">Impossibile salvare il file</string>
<string name="error_file_exists">Il file esiste già</string>
<string name="connect_to_wifi">Connetti al WiFi</string>
@@ -144,27 +159,30 @@
<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_as">Esportare come?</string>
<string name="export_as">Come esportare?</string>
<string name="export_csv_comma">CSV con virgole</string>
<string name="export_csv_semicolon">CSV con punti e virgola</string>
<string name="export_json">Esporta come JSON</string>
<string name="export_database">Esporta database SQLite</string>
<string name="export_json">File JSON</string>
<string name="export_database">Database SQLite</string>
<string name="saved_in_downloads">Salvato nei download</string>
<string name="rotate_image_cw">Ruota immagine in senso orario</string>
<string name="toggle_free_rotation">Abilita/disabilita rotazione libera</string>
<string name="pick_file">Scegli file immagine</string>
<string name="pick_code_to_scan">Scegli codice da scansionare</string>
<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">Richiesta in secondo piano fallita</string>
<string name="entry_type">Type</string>
<string name="wifi_network">Wi-Fi network</string>
<string name="wifi_ssid">Name</string>
<string name="wifi_type">Authentication type</string>
<string name="entry_type">Tipo</string>
<string name="wifi_network">Rete WiFi</string>
<string name="wifi_ssid">Nome</string>
<string name="wifi_type">Tipo di autenticazione</string>
<string name="wifi_password">Password</string>
<string name="wifi_hidden">Hidden network</string>
<string name="wifi_eap">EAP method</string>
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="wifi_hidden">Rete nascosta</string>
<string name="wifi_eap">Metodo EAP</string>
<string name="wifi_anonymous_identity">Identità anonima</string>
<string name="wifi_identity">Identità</string>
<string name="wifi_phase2">Metodo fase 2</string>
<string name="network_suggestions">Suggerimenti di rete</string>
<string name="remove_suggestion">Cancella suggerimento</string>
</resources>
+30 -12
View File
@@ -14,14 +14,20 @@
<string name="error_correction_level_m" formatted="false">中 (~15&#37; の正確性)</string>
<string name="error_correction_level_q" formatted="false">高 (~25&#37; の正確性)</string>
<string name="error_correction_level_h" formatted="false">最高 (~30&#37; の正確性)</string>
<string name="issue_number">発行番号</string>
<string name="orientation">方向</string>
<string name="other_meta_data">メタデータ</string>
<string name="pdf417_extra_metadata">PDF417 メタデータ</string>
<string name="possible_country">製造国</string>
<string name="suggested_price">価格</string>
<string name="upc_ean_extension">UPC/EAN 拡張型</string>
<string name="qr_version">QR version</string>
<string name="colors">背面と前面</string>
<string name="colors_black_on_white">白地に黒色</string>
<string name="colors_white_on_black">黒地に白色</string>
<string name="colors_black_on_transparent">透明に黒色</string>
<string name="colors_white_on_transparent">透明に白色</string>
<string name="sequence_size">配列寸法</string>
<string name="sequence_index">配列番号</string>
<string name="sequence_id">配列ID</string>
<string name="gtin_issue_number">発行番号</string>
<string name="gtin_country">製造国</string>
<string name="gtin_price">価格</string>
<string name="gtin_add_on">UPC/EAN 拡張型</string>
<string name="barcode_version_number">バージョン</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">フラッシュの切り替え</string>
<string name="error_flash">フラッシュの切り替えエラー</string>
<string name="share">共有</string>
@@ -74,6 +80,15 @@
<string name="show_toast_in_bulk_mode_summary">「まとめてスキャンする」オプションが有効の際、スキャンしたデータを簡潔に表示するようにします。</string>
<string name="vibrate">認識時に振動する</string>
<string name="vibrate_summary">バーコードが認識されたときにバイブレーションを行います。</string>
<string name="beep">検出時にビープ音を鳴らす</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">ビープ音</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">一般的なビープ音</string>
<string name="tone_prop_beep2">一般的なダブルビープ音</string>
<string name="use_history">スキャン履歴を保存する</string>
<string name="use_history_summary">認識されたバーコードを端末に保存しておきます。</string>
<string name="ignore_consecutive_duplicates">重複を破棄する</string>
@@ -84,10 +99,10 @@
<string name="copy_immediately_summary">スキャンされたコンテンツを自動的にクリップボードにコピーします。他のアプリはクリップボードの内容を見ることができることにご注意ください。</string>
<string name="show_meta_data">メタデータを表示</string>
<string name="show_meta_data_summary">スキャンされたバーコードの追加データを確認できるようにします。</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">16進数を表示</string>
<string name="show_hex_dump_summary">スキャンされたコンテンツの16進数データを確認できるようにします。</string>
<string name="show_recreation">再生成したバーコードを表示</string>
<string name="show_recreation_summary">可能であれば、読み取ったコンテンツからバーコードを再生成して表示します。</string>
<string name="close_automatically">コピー/共有後に戻る</string>
<string name="close_automatically_summary">コンテンツをコピー/共有した後、自動的にスキャン画面に戻るようにします。</string>
<string name="default_search_engine">未知のデータの表示方法</string>
@@ -150,6 +165,7 @@
<string name="export_database">SQLiteデータベース</string>
<string name="saved_in_downloads">ダウンロードフォルダに保存されました</string>
<string name="rotate_image_cw">時計回りに回転</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">画像を選択して読み込み</string>
<string name="pick_code_to_scan">スキャンするバーコードを選択</string>
<string name="shortcut_decode">バーコードをスキャン</string>
@@ -162,8 +178,10 @@
<string name="wifi_type">認証方式</string>
<string name="wifi_password">パスワード</string>
<string name="wifi_hidden">非表示のネットワーク</string>
<string name="wifi_eap">EAP method</string>
<string name="wifi_eap">EAP方式</string>
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="wifi_phase2">フェーズ2方式</string>
<string name="network_suggestions">ネットワークに関する提案</string>
<string name="remove_suggestion">提案の削除</string>
</resources>
+188 -170
View File
@@ -1,170 +1,188 @@
<resources>
<string name="no_camera_no_fun">ამ აპლიკაციის გამოყენება შეუძლებელია კამერაზე ნებართვის მინიჭების გარეშე</string>
<string name="camera_error">კამერაზე წვდომის მოპოვება ვერ ხერხდება, გთხოვთ, კიდევ სცადეთ</string>
<string name="scan_code">შტრიხ-კოდის სკანირება</string>
<string name="compose_barcode">შტრიხ-კოდის შექმნა</string>
<string name="decode_barcode">შტრიხ-კოდის დეკოდირება</string>
<string name="content">ტექსტი</string>
<string name="binary_data">(ორობითი მონაცემები)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d სიმბოლო, %1$s</item>
<item quantity="other">%2$d სიმბოლო, %1$s</item>
</plurals>
<string name="error_correction_level">შეცდომების კორექციის დონე</string>
<string name="error_correction_level_l" formatted="false">Low (~7&#37; correction)</string>
<string name="error_correction_level_m" formatted="false">Medium (~15&#37; correction)</string>
<string name="error_correction_level_q" formatted="false">Quartile (~25&#37; correction)</string>
<string name="error_correction_level_h" formatted="false">High (~30&#37; correction)</string>
<string name="issue_number">გამოშვების ნომერი</string>
<string name="orientation">ორიენტაცია</string>
<string name="other_meta_data">მეტამონაცემები</string>
<string name="pdf417_extra_metadata">PDF417 მეტამონაცემები</string>
<string name="possible_country">შესაძლო მწარმოებელი ქვეყანა</string>
<string name="suggested_price">დაახლოებითი ფასი</string>
<string name="upc_ean_extension">UPC EAN გაფართოება</string>
<string name="qr_version">QR version</string>
<string name="toggle_flash">განათების ჩართვა</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">გაზიარება</string>
<string name="share_as">Share as?</string>
<string name="copy_to_clipboard">გაცვლის ბუფერში კოპირება</string>
<string name="copied_to_clipboard">კოპირებულია გაცვლის ბუფერში</string>
<string name="copy_password">პაროლის გაცვლით ბუფერში კოპირებ</string>
<string name="copied_password_to_clipboard">პაროლი კოპირებულია გაცვლის ბუფერში</string>
<string name="open_url">ბმულის გახსნ</string>
<string name="cannot_resolve_action">ამ მოქმედებისთვის აპლიკაცია ნაპოვნი არაა</string>
<string name="pick_search_engine">აირჩიეთ საძიებო სისტემ</string>
<string name="format">ფორმატ</string>
<string name="size">ზომა პიქსელებში</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">შეიყვანეთ ტექსტი აქ</string>
<string name="encode">შექმნა"</string>
<string name="error_no_content">მონაცემები არა</string>
<string name="error_encoding_barcode">შტრიხ-კოდის შექმნა შეუძლებელია</string>
<string name="view_barcode">შტრიხ-კოდის ნახვა</string>
<string name="info">ინფორმაცია</string>
<string name="switch_camera">კამერის გადართვა</string>
<string name="bulk_mode">სკანირება უწყვეტად</string>
<string name="bulk_mode_summary">Always start scanning continuously.</string>
<string name="bulk_mode_delay">Delay between continuous scans</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="scan_format">Scan %s</string>
<string name="quarter_second">A quarter second</string>
<string name="half_second">Half a second</string>
<string name="a_second">One second</string>
<string name="two_seconds">Two seconds</string>
<string name="five_seconds">Five seconds</string>
<string name="history">ისტორია</string>
<string name="preferences">პარამეტრები</string>
<string name="scan_category">სკანირება</string>
<string name="content_category">კონტენტი</string>
<string name="locale_category">Language</string>
<string name="custom_locale">Custom language</string>
<string name="follow_system_settings">Follow system settings</string>
<string name="show_crop_handle">სკანირების არეალის ჩვენება</string>
<string name="show_crop_handle_summary">სკანირების შეზღუდვა შერჩეული არეალით.</string>
<string name="barcode_formats">Barcode formats</string>
<string name="zoom_by_swiping">მასშტაბირება თითის მოძრაობით მაღლა/დაბლა</string>
<string name="zoom_by_swiping_summary">გაატარეთ თითი მაღლა ან დაბლა კამერის მასშტაბირების სამართავად.</string>
<string name="auto_rotate">1D ვერტიკალური შტრიხ-კოდების ამოცნობა</string>
<string name="auto_rotate_summary">კამერის ავტომატური შეტრიალება ვერტიკალური 1D შტრიხ-კოდების ამოსაცნობად. მოწყობილობიდან გამომდინარე, შესაძლოა იმოქმედოს წარმადობაზე.</string>
<string name="try_harder">წაკითხვის ოპტიმიზირება სიზუსტეზე და არა სისწრაფეზე</string>
<string name="try_harder_summary">ეს პარამეტრი ჩართეთ იმ შტრიხ-კოდებისთვის, რომელთა ამოცნობაც ძალიან ძნელია. მოქმედებს წარმადობაზე.</string>
<string name="show_toast_in_bulk_mode">Show data in continuous mode</string>
<string name="show_toast_in_bulk_mode_summary">Briefly show the scanned data when scanning continuously.</string>
<string name="vibrate">ვიბრირება პოვნისას</string>
<string name="vibrate_summary">ჩართეთ ეს პარამეტრი, თუ გსურთ მოწყობილობის ვიბრირება,როდესაც შტრიხ-კოდ ამოცნობილი იქნება.</string>
<string name="use_history">სკანირების ისტორიის შენახვა</string>
<string name="use_history_summary">ამოცნობილი შტრიხ-კოდების მოწყობილობაზე შენახვა.</string>
<string name="ignore_consecutive_duplicates">არ შევინახოთ შემდგომი ასლები</string>
<string name="ignore_consecutive_duplicates_summary">არ შევინახოთ შემდგომი ასლები სკანირების ისტორიაში.</string>
<string name="open_immediately">შემოწმების გამოტოვება და მყისიერი გახსნა</string>
<string name="open_immediately_summary">შემოწმების გამოტოვება და მყისიერი გახსნა. შესაძლოა გამოიწვიოს არასასარგებლო კონტენტის ჩვენება.</string>
<string name="copy_immediately">გაცვლის ბუფერში ავტომატური კოპირება</string>
<string name="copy_immediately_summary">სკანირებული შტრიხ-კოდის კონტენტის ავტომატური კოპირება გაცვლის ბუფერში. გთხოვთ გაითვალისწინოთ,ზოგიერთ პროგრამას შესაძლოა ჰქონდეს ფონური წვდომა გაცვლის ბუფერთან.</string>
<string name="show_meta_data">მეტამონაცემების ჩვენება</string>
<string name="show_meta_data_summary">სკანირებულ შტრიხ-კოდებზე დამატებითი ინფორმაციის ჩვენება.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">თექვსმეტობითი dump-ის ჩვენება</string>
<string name="show_hex_dump_summary">სკანირებული შტრიხ-კოდის კონტენტის თექვსმეტობითი dump-ის ჩვენება.</string>
<string name="close_automatically">Go back after Copy/Share</string>
<string name="close_automatically_summary">Automatically return to the scan screen after copying or sharing the read contents.</string>
<string name="default_search_engine">Open unknown data in</string>
<string name="always_ask">Always ask</string>
<string name="open_with_url">უცნობი მონაცემების ამ ბმულის საშუალებით გახსნა</string>
<string name="clear_network_suggestions">Clear network suggestions</string>
<string name="clear_network_suggestions_summary">Remove all of the network suggestions that were previously provided by this app.</string>
<string name="really_remove_all_networks">Really remove all networks?</string>
<string name="clear_network_suggestions_success">Network suggestions cleared</string>
<string name="clear_network_suggestions_nothing_to_remove">Nothing to remove</string>
<string name="send_category">გადაგზავნა</string>
<string name="send_scan_active">Forward scans</string>
<string name="send_scan_active_summary">Enable to forward scans to a the given URL</string>
<string name="send_scan_url">ყოველი სკანირებული შტრიხ-კოდის ბმულის საშუალებით გახსნა</string>
<string name="send_scan_type">მოთხოვნის ტიპი ყოველი სკანირებული შტრიხ-კოდისთვის</string>
<string name="send_type_get_add_content">GET კონტენტის დამატებით</string>
<string name="send_type_get_query_string">GET მოთხოვნის სრული პარამეტრებით</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="send_type_external_browser">Open in external browser</string>
<string name="test_url">Test URL</string>
<string name="really_remove_scan">ნამდვილად გსურთ სკანირების წაშლა?</string>
<string name="really_remove_all_scans">ნამდვილად გსურთ ყველაფრის წაშლა?</string>
<string name="really_remove_selected_scans">ნამდვილად გსურთ შერჩეული შტრიხ-კოდების წაშლა?</string>
<string name="clear_history">ისტორიის გასუფთავება</string>
<string name="copy_scan">კოპირებ</string>
<string name="edit_scan">რედაქტირება</string>
<string name="remove_scan">სკანირების წაშლა</string>
<string name="enter_name">მიანიჭეთ სახელი სკანირებას</string>
<string name="enter_name_hint">სკანირების სახელი</string>
<string name="no_barcode_found">შტრიხ-კოდი ვერ მოიძებნა</string>
<string name="pick_list_separator">რითი გავყოთ სიის ელემენტები?</string>
<string name="separator_line_break">ხაზის გამყოფი</string>
<string name="separator_ruler">ჰორიზონტალური ხაზი</string>
<string name="save_as_file_name">ფაილის შენახვა როგორც</string>
<string name="file_name">ფაილის სახელი</string>
<string name="error_saving_file">ფაილის შენახვა ვერ ხერხდება</string>
<string name="error_file_exists">ფაილი უკვე არსებობს</string>
<string name="connect_to_wifi">დაკავშირება WiFi-სთან</string>
<string name="wifi_config_failed">WiFi კონფიგურაცია ვერ მოხერხდ</string>
<string name="wifi_added">WiFi დამატებული</string>
<string name="sms_send">შეტყობინების გაგზავნ</string>
<string name="sms_error">შეტყობინების გაგზავნა ვერ მოხერხდ</string>
<string name="tel_dial">ნომრის აკრეფა</string>
<string name="tel_error">ნომრის აკრეფა ვერ მოხერხდა</string>
<string name="mail_send">წერილის გაგზავნა</string>
<string name="mail_error">წერივერ გაიგზავნა</string>
<string name="vcard_add">კონტაქტებში დამატება</string>
<string name="vcard_failed">კონტაქტებში დამატება ვერ მოხერხდა</string>
<string name="vevent_add">კალენდარში დამატება</string>
<string name="vevent_failed">კალენდარში დამატება ვერ მოხერხდა</string>
<string name="otpauth_add">დავამატოთ 2FA</string>
<string name="search_web">ქსელში მოძებნა</string>
<string name="search_scan">სკანირების ძიება</string>
<string name="export_to_file">ექსპორტი ფაილში</string>
<string name="export_as">შესანახი ფაილის ფორმატი</string>
<string name="export_csv_comma">CSV (გამყოფი - მძიმე)</string>
<string name="export_csv_semicolon">CSV (გამყოფი - წერტილ-მძიმე,)</string>
<string name="export_json">JSON</string>
<string name="export_database">SQLite მონაცემთა ბაზ</string>
<string name="saved_in_downloads">შენახულია გადმოწერებში</string>
<string name="rotate_image_cw">გამოსახულების შემობრუნება საათის ისრის მიხედვით</string>
<string name="pick_file">აირჩიეთ ფაილამოსახულებით</string>
<string name="pick_code_to_scan">აირჩიეთ შტრიხ-კოდი სკანირებისთვის</string>
<string name="shortcut_decode">შტრიხ-კოდის სკანირება</string>
<string name="shortcut_encode">შტრიხ-კოდის შექმნ</string>
<string name="shortcut_preferences">პარამეტრები</string>
<string name="background_request_failed">ფონური მოთხოვნა ვერ მოხერხდ</string>
<string name="entry_type">Type</string>
<string name="wifi_network">Wi-Fi network</string>
<string name="wifi_ssid">Name</string>
<string name="wifi_type">Authentication type</string>
<string name="wifi_password">Password</string>
<string name="wifi_hidden">Hidden network</string>
<string name="wifi_eap">EAP method</string>
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_phase2">Phase 2 method</string>
</resources>
<resources>
<string name="no_camera_no_fun">ამ აპლიკაციის გამოყენება შეუძლებელია კამერაზე ნებართვის მინიჭების გარეშე</string>
<string name="camera_error">კამერაზე წვდომის მოპოვება ვერ ხერხდება, გთხოვთ, კიდევ სცადეთ</string>
<string name="scan_code">შტრიხ-კოდის სკანირება</string>
<string name="compose_barcode">შტრიხ-კოდის შექმნა</string>
<string name="decode_barcode">შტრიხ-კოდის დეკოდირება</string>
<string name="content">ტექსტი</string>
<string name="binary_data">(ორობითი მონაცემები)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d სიმბოლო, %1$s</item>
<item quantity="other">%2$d სიმბოლო, %1$s</item>
</plurals>
<string name="error_correction_level">შეცდომების კორექციის დონე</string>
<string name="error_correction_level_l" formatted="false">Low (~7&#37; correction)</string>
<string name="error_correction_level_m" formatted="false">Medium (~15&#37; correction)</string>
<string name="error_correction_level_q" formatted="false">Quartile (~25&#37; correction)</string>
<string name="error_correction_level_h" formatted="false">High (~30&#37; correction)</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">გამოშვების ნომერი</string>
<string name="gtin_country">შესაძლო მწარმოებელი ქვეყანა</string>
<string name="gtin_price">დაახლოებითი ფასი</string>
<string name="gtin_add_on">UPC EAN გაფართოება</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">განათების ჩართვ</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">გაზიარებ</string>
<string name="share_as">Share as?</string>
<string name="copy_to_clipboard">გაცვლის ბუფერში კოპირებ</string>
<string name="copied_to_clipboard">კოპირებულია გაცვლის ბუფერშ</string>
<string name="copy_password">პაროლის გაცვლით ბუფერში კოპირება</string>
<string name="copied_password_to_clipboard">პაროლი კოპირებულია გაცვლის ბუფერში</string>
<string name="open_url">ბმულის გახსნა</string>
<string name="cannot_resolve_action">ამ მოქმედებისთვის აპლიკაცია ნაპოვნი არაა</string>
<string name="pick_search_engine">აირჩიეთ საძიებო სისტემ</string>
<string name="format">ფორმატი</string>
<string name="size">ზომა პიქსელებში</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">შეიყვანეთ ტექსტი აქ</string>
<string name="encode">შექმნა"</string>
<string name="error_no_content">მონაცემები არაა</string>
<string name="error_encoding_barcode">შტრიხ-კოდის შექმნა შეუძლებელია</string>
<string name="view_barcode">შტრიხ-კოდის ნახვა</string>
<string name="info">ინფორმაცია</string>
<string name="switch_camera">კამერის გადართვა</string>
<string name="bulk_mode">სკანირება უწყვეტად</string>
<string name="bulk_mode_summary">Always start scanning continuously.</string>
<string name="bulk_mode_delay">Delay between continuous scans</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="scan_format">Scan %s</string>
<string name="quarter_second">A quarter second</string>
<string name="half_second">Half a second</string>
<string name="a_second">One second</string>
<string name="two_seconds">Two seconds</string>
<string name="five_seconds">Five seconds</string>
<string name="history">ისტორია</string>
<string name="preferences">პარამეტრები</string>
<string name="scan_category">სკანირება</string>
<string name="content_category">კონტენტი</string>
<string name="locale_category">Language</string>
<string name="custom_locale">Custom language</string>
<string name="follow_system_settings">Follow system settings</string>
<string name="show_crop_handle">სკანირების არეალის ჩვენება</string>
<string name="show_crop_handle_summary">სკანირების შეზღუდვა შერჩეული არეალით.</string>
<string name="barcode_formats">Barcode formats</string>
<string name="zoom_by_swiping">მასშტაბირება თითის მოძრაობით მაღლა/დაბლა</string>
<string name="zoom_by_swiping_summary">გაატარეთ თითი მაღლა ან დაბლა კამერის მასშტაბირების სამართავად.</string>
<string name="auto_rotate">1D ვერტიკალური შტრიხ-კოდების ამოცნობა</string>
<string name="auto_rotate_summary">კამერის ავტომატური შეტრიალება ვერტიკალური 1D შტრიხ-კოდების ამოსაცნობად. მოწყობილობიდან გამომდინარე, შესაძლოა იმოქმედოს წარმადობაზე.</string>
<string name="try_harder">წაკითხვის ოპტიმიზირება სიზუსტეზე და არა სისწრაფეზე</string>
<string name="try_harder_summary">ეს პარამეტრი ჩართეთ იმ შტრიხ-კოდებისთვის, რომელთა ამოცნობაც ძალიან ძნელია. მოქმედებს წარმადობაზე.</string>
<string name="show_toast_in_bulk_mode">Show data in continuous mode</string>
<string name="show_toast_in_bulk_mode_summary">Briefly show the scanned data when scanning continuously.</string>
<string name="vibrate">ვიბრირება პოვნისას</string>
<string name="vibrate_summary">ჩართეთ ეს პარამეტრი, თუ გსურთ მოწყობილობის ვიბრირება,როდესაც შტრიხ-კოდი ამოცნობილი იქნება.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">სკანირების ისტორიის შენახვა</string>
<string name="use_history_summary">ამოცნობილი შტრიხ-კოდების მოწყობილობაზე შენახვა.</string>
<string name="ignore_consecutive_duplicates">არ შევინახოთ შემდგომი ასლები</string>
<string name="ignore_consecutive_duplicates_summary">არ შევინახოთ შემდგომი ასლები სკანირების ისტორიაში.</string>
<string name="open_immediately">შემოწმების გამოტოვება და მყისიერი გახსნა</string>
<string name="open_immediately_summary">შემოწმების გამოტოვება და მყისიერი გახსნა. შესაძლოა გამოიწვიოს არასასარგებლო კონტენტის ჩვენება.</string>
<string name="copy_immediately">გაცვლის ბუფერში ავტომატური კოპირება</string>
<string name="copy_immediately_summary">სკანირებული შტრიხ-კოდის კონტენტის ავტომატური კოპირება გაცვლის ბუფერში. გთხოვთ გაითვალისწინოთ,ზოგიერთ პროგრამას შესაძლოა ჰქონდეს ფონური წვდომა გაცვლის ბუფერთან.</string>
<string name="show_meta_data">მეტამონაცემების ჩვენება</string>
<string name="show_meta_data_summary">სკანირებულ შტრიხ-კოდებზე დამატებითი ინფორმაციის ჩვენება.</string>
<string name="show_hex_dump">თექვსმეტობითი dump-ის ჩვენება</string>
<string name="show_hex_dump_summary">სკანირებული შტრიხ-კოდის კონტენტის თექვსმეტობითი dump-ის ჩვენება.</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Go back after Copy/Share</string>
<string name="close_automatically_summary">Automatically return to the scan screen after copying or sharing the read contents.</string>
<string name="default_search_engine">Open unknown data in</string>
<string name="always_ask">Always ask</string>
<string name="open_with_url">უცნობი მონაცემების ამ ბმულის საშუალებით გახსნა</string>
<string name="clear_network_suggestions">Remove network suggestions</string>
<string name="clear_network_suggestions_summary">Remove network suggestions that were previously added with this app.</string>
<string name="really_remove_all_networks">Really remove all networks?</string>
<string name="clear_network_suggestions_success">Network suggestions cleared</string>
<string name="clear_network_suggestions_nothing_to_remove">Nothing to remove</string>
<string name="send_category">გადაგზავნ</string>
<string name="send_scan_active">Forward scans</string>
<string name="send_scan_active_summary">Enable to forward scans to a the given URL</string>
<string name="send_scan_url">ყოველი სკანირებული შტრიხ-კოდის ბმულიაშუალებით გახსნა</string>
<string name="send_scan_type">მოთხოვნის ტიპი ყოველი სკანირებული შტრიხ-კოდისთვის</string>
<string name="send_type_get_add_content">GET კონტენტის დამატებით</string>
<string name="send_type_get_query_string">GET მოთხოვნის სრული პარამეტრები</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="send_type_external_browser">Open in external browser</string>
<string name="test_url">Test URL</string>
<string name="really_remove_scan">ნამდვილად გსურთ სკანირების წაშლა?</string>
<string name="really_remove_all_scans">ნამდვილად გსურთ ყველაფრის წაშლა?</string>
<string name="really_remove_selected_scans">ნამდვილად გსურთ შერჩეული შტრიხ-კოდების წაშლა?</string>
<string name="clear_history">ისტორიის გასუფთავებ</string>
<string name="copy_scan">კოპირებ</string>
<string name="edit_scan">რედაქტირებ</string>
<string name="remove_scan">სკანირების წაშლ</string>
<string name="enter_name">მიანიჭეთ სახელი სკანირებას</string>
<string name="enter_name_hint">სკანირების სახელი</string>
<string name="no_barcode_found">შტრიხ-კოდი ვერ მოიძებნა</string>
<string name="pick_list_separator">რიგავყოთ სიის ელემენტები?</string>
<string name="separator_line_break">ხაზის გამყოფი</string>
<string name="separator_ruler">ჰორიზონტალური ხაზი</string>
<string name="save_as_file_name">ფაილის შენახვა როგორც</string>
<string name="file_name">ფაილის სახელი</string>
<string name="error_saving_file">ფაილის შენახვა ვერ ხერხდება</string>
<string name="error_file_exists">ფაილი უკვე არსებობს</string>
<string name="connect_to_wifi">დაკავშირება WiFi-სთან</string>
<string name="wifi_config_failed">WiFi კონფიგურაცია ვერ მოხერხდა</string>
<string name="wifi_added">WiFi დამატებულია</string>
<string name="sms_send">შეტყობინების გაგზავნა</string>
<string name="sms_error">შეტყობინების გაგზავნა ვერ მოხერხდა</string>
<string name="tel_dial">ნომრის აკრეფა</string>
<string name="tel_error">ნომრის აკრეფა ვერ მოხერხდ</string>
<string name="mail_send">წერილის გაგზავნა</string>
<string name="mail_error">წერილი ვერ გაიგზავნა</string>
<string name="vcard_add">კონტაქტებშამატება</string>
<string name="vcard_failed">კონტაქტებში დამატება ვერ მოხერხდა</string>
<string name="vevent_add">კალენდარში დამატება</string>
<string name="vevent_failed">კალენდარში დამატება ვერ მოხერხდ</string>
<string name="otpauth_add">დავამატოთ 2FA</string>
<string name="search_web">ქსელში მოძებნ</string>
<string name="search_scan">სკანირების ძიება</string>
<string name="export_to_file">ექსპორტი ფაილში</string>
<string name="export_as">შესანახი ფაილის ფორმატი</string>
<string name="export_csv_comma">CSV (გამყოფი - მძიმე)</string>
<string name="export_csv_semicolon">CSV (გამყოფი - წერტილ-მძიმე,)</string>
<string name="export_json">JSON</string>
<string name="export_database">SQLite მონაცემთა ბაზა</string>
<string name="saved_in_downloads">შენახულია გადმოწერებში</string>
<string name="rotate_image_cw">გამოსახულების შემობრუნება საათის ისრის მიხედვით</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">აირჩიეთ ფაილი გამოსახულებით</string>
<string name="pick_code_to_scan">აირჩიეთ შტრიხ-კოდი სკანირებისთვის</string>
<string name="shortcut_decode">შტრიხ-კოდის სკანირება</string>
<string name="shortcut_encode">შტრიხ-კოდის შექმნა</string>
<string name="shortcut_preferences">პარამეტრები</string>
<string name="background_request_failed">ფონური მოთხოვნა ვერ მოხერხდა</string>
<string name="entry_type">Type</string>
<string name="wifi_network">Wi-Fi network</string>
<string name="wifi_ssid">Name</string>
<string name="wifi_type">Authentication type</string>
<string name="wifi_password">Password</string>
<string name="wifi_hidden">Hidden network</string>
<string name="wifi_eap">EAP method</string>
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+188
View File
@@ -0,0 +1,188 @@
<resources>
<string name="no_camera_no_fun">This app does not make any sense without camera access. Good bye.</string>
<string name="camera_error">카메라를 접근할 수 없습니다. 다시 시도하세요</string>
<string name="scan_code">Scan code</string>
<string name="compose_barcode">Compose barcode</string>
<string name="decode_barcode">Decode barcode</string>
<string name="content">Content</string>
<string name="binary_data">(binary data)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d character, %1$s</item>
<item quantity="other">%2$d characters, %1$s</item>
</plurals>
<string name="error_correction_level">Error correction level</string>
<string name="error_correction_level_l" formatted="false">Low (~7&#37; correction)</string>
<string name="error_correction_level_m" formatted="false">Medium (~15&#37; correction)</string>
<string name="error_correction_level_q" formatted="false">Quartile (~25&#37; correction)</string>
<string name="error_correction_level_h" formatted="false">High (~30&#37; correction)</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">이슈번호</string>
<string name="gtin_country">Possible country of manufacture</string>
<string name="gtin_price">Suggested price</string>
<string name="gtin_add_on">UPC EAN extension</string>
<string name="barcode_version_number">버전</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Toggle flash</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Share</string>
<string name="share_as">Share as?</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>
<string name="pick_search_engine">Pick a search engine</string>
<string name="format">Format</string>
<string name="size">Size in pixels</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">Input content here</string>
<string name="encode">ENCODE</string>
<string name="error_no_content">Missing content</string>
<string name="error_encoding_barcode">Barcode cannot be generated</string>
<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="bulk_mode_summary">Always start scanning continuously.</string>
<string name="bulk_mode_delay">Delay between continuous scans</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="scan_format">Scan %s</string>
<string name="quarter_second">A quarter second</string>
<string name="half_second">Half a second</string>
<string name="a_second">One second</string>
<string name="two_seconds">Two seconds</string>
<string name="five_seconds">Five seconds</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="locale_category">Language</string>
<string name="custom_locale">Custom language</string>
<string name="follow_system_settings">Follow system settings</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="barcode_formats">Barcode formats</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="show_toast_in_bulk_mode">Show data in continuous mode</string>
<string name="show_toast_in_bulk_mode_summary">Briefly show the scanned data when scanning continuously.</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="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Save scan history</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 barcode.</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="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Go back after Copy/Share</string>
<string name="close_automatically_summary">Automatically return to the scan screen after copying or sharing the read contents.</string>
<string name="default_search_engine">Open unknown data in</string>
<string name="always_ask">Always ask</string>
<string name="open_with_url">Open unknown data with URL</string>
<string name="clear_network_suggestions">Remove network suggestions</string>
<string name="clear_network_suggestions_summary">Remove network suggestions that were previously added with this app.</string>
<string name="really_remove_all_networks">Really remove all networks?</string>
<string name="clear_network_suggestions_success">Network suggestions cleared</string>
<string name="clear_network_suggestions_nothing_to_remove">Nothing to remove</string>
<string name="send_category">Forwarding</string>
<string name="send_scan_active">Forward scans</string>
<string name="send_scan_active_summary">Enable to forward scans to a the given URL.</string>
<string name="send_scan_url">URL to forward to</string>
<string name="send_scan_type">Request type</string>
<string name="send_type_get_add_content">GET and simply add content</string>
<string name="send_type_get_query_string">GET with complete 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="send_type_external_browser">Open in external browser</string>
<string name="test_url">Test URL</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>
<string name="clear_history">Clear history</string>
<string name="copy_scan">Copy scan</string>
<string name="edit_scan">Edit label</string>
<string name="remove_scan">Remove scan</string>
<string name="enter_name">Enter a name to describe the scan</string>
<string name="enter_name_hint">Name of the scan</string>
<string name="no_barcode_found">No barcode found</string>
<string name="pick_list_separator">How to separate list items?</string>
<string name="separator_line_break">Line break</string>
<string name="separator_ruler">Ruler</string>
<string name="save_as_file_name">Save as in Downloads file?</string>
<string name="file_name">File name</string>
<string name="error_saving_file">Cannot save file</string>
<string name="error_file_exists">File already exists</string>
<string name="connect_to_wifi">Connect to WiFi</string>
<string name="wifi_config_failed">Could not configure WiFi</string>
<string name="wifi_added">WiFi added</string>
<string name="sms_send">Send SMS</string>
<string name="sms_error">Could not send SMS</string>
<string name="tel_dial">Dial number</string>
<string name="tel_error">Could not dial number</string>
<string name="mail_send">Send mail</string>
<string name="mail_error">Could not send mail</string>
<string name="vcard_add">Add to contacts</string>
<string name="vcard_failed">Could not add to contacts</string>
<string name="vevent_add">Add to calendar</string>
<string name="vevent_failed">Could not add to calendar</string>
<string name="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_as">Export as?</string>
<string name="export_csv_comma">CSV file with commas</string>
<string name="export_csv_semicolon">CSV file with semicolons</string>
<string name="export_json">JSON file</string>
<string name="export_database">SQLite database</string>
<string name="saved_in_downloads">Saved in downloads</string>
<string name="rotate_image_cw">Rotate image clockwise</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">Pick image file</string>
<string name="pick_code_to_scan">Pick code to scan</string>
<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>
<string name="entry_type">Type</string>
<string name="wifi_network">Wi-Fi network</string>
<string name="wifi_ssid">Name</string>
<string name="wifi_type">Authentication type</string>
<string name="wifi_password">Password</string>
<string name="wifi_hidden">Hidden network</string>
<string name="wifi_eap">EAP method</string>
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+28 -10
View File
@@ -15,14 +15,20 @@
<string name="error_correction_level_m" formatted="false">Middelhoog (~15&#37; correction)</string>
<string name="error_correction_level_q" formatted="false">Kwartiel (~25&#37; correction)</string>
<string name="error_correction_level_h" formatted="false">Hoog (~30&#37; correction)</string>
<string name="issue_number">Uitgiftenummer</string>
<string name="orientation">Oriëntatie</string>
<string name="other_meta_data">Metadata</string>
<string name="pdf417_extra_metadata">PDF417 metadata</string>
<string name="possible_country">Mogelijk land van fabricage</string>
<string name="suggested_price">Adviesprijs</string>
<string name="upc_ean_extension">UPC EAN extensie</string>
<string name="qr_version">QR version</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">Uitgiftenummer</string>
<string name="gtin_country">Mogelijk land van fabricage</string>
<string name="gtin_price">Adviesprijs</string>
<string name="gtin_add_on">UPC EAN extensie</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Zaklamp aan/uit</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Delen</string>
@@ -75,6 +81,15 @@
<string name="show_toast_in_bulk_mode_summary">Kort de gescande gegevens tonen bij continu scannen.</string>
<string name="vibrate">Trillen bij herkennen</string>
<string name="vibrate_summary">Schakel dit in als u wilt dat uw toestel trilt wanneer een code wordt herkend.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Scancodes bewaren</string>
<string name="use_history_summary">Bewaar herkende codes op je toestel.</string>
<string name="ignore_consecutive_duplicates">Duplicaten negeren</string>
@@ -85,10 +100,10 @@
<string name="copy_immediately_summary">Kopieer de gescande inhoud automatisch naar het klembord. Let op: andere apps kunnen mogelijk meelezen op de achtergrond.</string>
<string name="show_meta_data">Metadata tonen</string>
<string name="show_meta_data_summary">Toon extra gegevens over de gescande barcode.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Hex-dump tonen</string>
<string name="show_hex_dump_summary">Hex-dump van de gescande inhoud tonen.</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Teruggaan na kopiëren/delen</string>
<string name="close_automatically_summary">Automatisch terugkeren naar het scanscherm na het kopiëren of delen van de gelezen inhoud.</string>
<string name="default_search_engine">Onbekende data openen in</string>
@@ -151,6 +166,7 @@
<string name="export_database">SQLite database</string>
<string name="saved_in_downloads">Opgeslagen in downloads</string>
<string name="rotate_image_cw">Afbeelding rechtsom draaien</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">Beeldbestand kiezen</string>
<string name="pick_code_to_scan">Kies code om te scannen</string>
<string name="shortcut_decode">Een barcode scannen</string>
@@ -167,4 +183,6 @@
<string name="wifi_anonymous_identity">Anonieme identiteit</string>
<string name="wifi_identity">Identiteit</string>
<string name="wifi_phase2">Phase 2 methode</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+28 -10
View File
@@ -30,6 +30,14 @@
<string name="error_correction_level_m" formatted="false">Średni (~15&#37; korekcji)</string>
<string name="error_correction_level_q" formatted="false">Kwartyl (~25&#37; korekcji)</string>
<string name="error_correction_level_h" formatted="false">Wysoki (~30&#37; korekcji)</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="export_csv_comma">CSV z przecinkami</string>
<string name="export_csv_semicolon">CSV ze średnikami</string>
<string name="shortcut_encode">Stwórz kod kreskowy</string>
@@ -43,6 +51,7 @@
<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="toggle_free_rotation">Toggle free rotation</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>
@@ -57,12 +66,12 @@
<string name="binary_data">(dane binarne)</string>
<string name="show_hex_dump">Pokazuj zrzut szesnastkowy</string>
<string name="show_hex_dump_summary">Pokaż zeskanowaną zawartośc w postaci szesnastkowej</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Wróć po skopiowaniu/udostępnieniu</string>
<string name="close_automatically_summary">Automatycznie powracaj do ekranu skanowania po skopiowaniu lub udostępnieniu przeczytanej zawartości.</string>
<string name="show_meta_data">Pokazuj metadane</string>
<string name="show_meta_data_summary">Pokaż dodatkowe dane o zeskanowanym kodzie kreskowym.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="switch_camera">Przełącz aparat</string>
<string name="bulk_mode">Skanuj w sposób ciągły</string>
<string name="bulk_mode_summary">Zawsze rozpoczynaj skanowanie w sposób ciągły.</string>
@@ -81,10 +90,8 @@
<string name="zoom_by_swiping">Przybliżaj kamerę, przesuwając w górę/dół</string>
<string name="zoom_by_swiping_summary">Przesuń palcem w górę lub w dół na ekranie aparatu, aby sterować powiększeniem aparatu.</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>
@@ -92,6 +99,15 @@
<string name="use_history_summary">Zapisz rozpoznane kody na swoim urządzeniu.</string>
<string name="vibrate">Wibruj po wykryciu</string>
<string name="vibrate_summary">Włącz tę opcję, jeśli chcesz, aby urządzenie wibrowało po rozpoznaniu kodu.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="open_immediately">Pomiń kontrolę i natychmiast otwórz zawartość</string>
<string name="open_immediately_summary">Pomiń kontrolę i natychmiast otwórz zawartość. Może otwierać szkodliwą zawartość, jeśli jest włączona.</string>
<string name="copy_immediately">Automatycznie skopiuj zawartość do schowka</string>
@@ -125,8 +141,7 @@
<string name="test_url">Testuj URL</string>
<string name="copy_password">Skopiuj hasło do schowka</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="gtin_price">Sugerowana cena</string>
<string name="preferences">Ustawienia</string>
<string name="scan_category">Skanowanie</string>
<string name="content_category">Zawarość</string>
@@ -134,9 +149,10 @@
<string name="custom_locale">Język niestandardowy</string>
<string name="follow_system_settings">Zgodny z ustawieniami systemu</string>
<string name="decode_barcode">Dekoduj kod kreskowy</string>
<string name="upc_ean_extension">Dodatek UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="possible_country">Możliwy kraj produkcji</string>
<string name="gtin_add_on">Dodatek UPC EAN</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="gtin_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>
@@ -151,7 +167,7 @@
<string name="auto_rotate">Rozpoznawaj kody kreskowe 1D pionowo</string>
<string name="auto_rotate_summary">Automatycznie obracaj ramkę aparatu, aby rozpoznać pionowe kody kreskowe 1D. W zależności od urządzenia może to mieć wpływ na wydajność.</string>
<string name="save_as_file_name">Jak zapisać plik w pobranych?</string>
<string name="issue_number">Numer wydania</string>
<string name="gtin_issue_number">Numer wydania</string>
<string name="background_request_failed">Żądanie w tle nie powiodło się</string>
<string name="entry_type">Typ</string>
<string name="wifi_network">Sieć Wi-Fi</string>
@@ -163,4 +179,6 @@
<string name="wifi_anonymous_identity">Anonimowa tożsamość</string>
<string name="wifi_identity">Tożsamość</string>
<string name="wifi_phase2">Metoda fazy 2</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+74 -56
View File
@@ -1,7 +1,7 @@
<resources>
<string name="no_camera_no_fun">Infelizmente você não poderá usar este app sem acesso à câmera.</string>
<string name="no_camera_no_fun">Infelizmente você não poderá usar este app sem conceder acesso à câmera.</string>
<string name="camera_error">Não foi possível acessar a câmera, por favor tente novamente</string>
<string name="scan_code">Escaneie código</string>
<string name="scan_code">Aponte ao código</string>
<string name="compose_barcode">Criar código</string>
<string name="decode_barcode">Reconhecer código</string>
<string name="content">Conteúdo</string>
@@ -15,46 +15,52 @@
<string name="error_correction_level_m" formatted="false">Médio (~15&#37; correção)</string>
<string name="error_correction_level_q" formatted="false">Quartil (~25&#37; correção)</string>
<string name="error_correction_level_h" formatted="false">Alto (~30&#37; correção)</string>
<string name="issue_number">Número de emissão</string>
<string name="orientation">Orientação</string>
<string name="other_meta_data">Metadados</string>
<string name="pdf417_extra_metadata">Metadados PDF417</string>
<string name="possible_country">Possível país de fabricação</string>
<string name="suggested_price">Preço sugerido</string>
<string name="upc_ean_extension">Extensão UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="toggle_flash">Ativar lanterna</string>
<string name="colors">Modo de exibição</string>
<string name="colors_black_on_white">Preto sobre fundo branco</string>
<string name="colors_white_on_black">Branco sobre fundo preto</string>
<string name="colors_black_on_transparent">Preto sobre fundo transparente</string>
<string name="colors_white_on_transparent">Branco sobre fundo transparente</string>
<string name="sequence_size">Tamanho de sequência</string>
<string name="sequence_index">Índice de sequência</string>
<string name="sequence_id">ID de sequência</string>
<string name="gtin_issue_number">Número de emissão</string>
<string name="gtin_country">Possível país de fabricação</string>
<string name="gtin_price">Preço sugerido</string>
<string name="gtin_add_on">Extensão UPC EAN</string>
<string name="barcode_version_number">Versão</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Ligar lanterna</string>
<string name="error_flash">Falha ao ligar a lanterna</string>
<string name="share">Compartilhar</string>
<string name="share_as">Compartilhar como?</string>
<string name="share">Compartilhe</string>
<string name="share_as">Compartilhar em qual formato?</string>
<string name="copy_to_clipboard">Copiar ao clipboard</string>
<string name="copied_to_clipboard">Copiado ao clipboard</string>
<string name="copy_password">Copiar senha ao clipboard</string>
<string name="copied_password_to_clipboard">Senha copiada ao clipboard</string>
<string name="open_url">Abrir a URL</string>
<string name="cannot_resolve_action">Nenhum app pode abrir isto</string>
<string name="cannot_resolve_action">Nenhum app consegue abrir isto</string>
<string name="pick_search_engine">Escolha site de busca</string>
<string name="format">Formato</string>
<string name="size">Tamanho em píxeis</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">Digite conteúdo aqui</string>
<string name="input_content_here">Digite algum conteúdo aqui</string>
<string name="encode">CODIFICAR</string>
<string name="error_no_content">Conteúdo indisponível</string>
<string name="error_encoding_barcode">Não foi possível gerar o código</string>
<string name="error_no_content">Digite algum conteúdo acima</string>
<string name="error_encoding_barcode">Não foi possível gerar este código</string>
<string name="view_barcode">Ver código</string>
<string name="info">Detalhes</string>
<string name="switch_camera">Alterar câmera</string>
<string name="bulk_mode">Digitalização contínua</string>
<string name="bulk_mode_summary">Sempre executar em modo contínuo.</string>
<string name="bulk_mode_delay">Adiar em escaneamentos contínuos</string>
<string name="bulk_mode_delay">Adiar durante digitalização contínua</string>
<string name="restrict_format">Limitar formato</string>
<string name="remove_restriction">Remover limitação</string>
<string name="scan_format">Escanear %s</string>
<string name="quarter_second">Um quarto de segundo</string>
<string name="half_second">Meio segundo</string>
<string name="a_second">Um segundo</string>
<string name="two_seconds">Dois segundos</string>
<string name="five_seconds">Cinco segundos</string>
<string name="a_second">1 segundo</string>
<string name="two_seconds">2 segundos</string>
<string name="five_seconds">5 segundos</string>
<string name="history">Histórico</string>
<string name="preferences">Preferências</string>
<string name="scan_category">Digitalização</string>
@@ -62,95 +68,105 @@
<string name="locale_category">Idioma</string>
<string name="custom_locale">Idioma da interface</string>
<string name="follow_system_settings">Adaptar do sistema</string>
<string name="show_crop_handle">Mostrar limitador de corte</string>
<string name="show_crop_handle_summary">Limitar a uma área personalizável.</string>
<string name="barcode_formats">Tipos de código</string>
<string name="zoom_by_swiping">Deslize para baixo/cima para ajustar zoom</string>
<string name="show_crop_handle">Mostrar limitador customizável</string>
<string name="show_crop_handle_summary">Permite limitar a uma área específica.</string>
<string name="barcode_formats">Tipo de código</string>
<string name="zoom_by_swiping">Deslize para ajustar zoom</string>
<string name="zoom_by_swiping_summary">Deslize para baixo/cima na tela para ajustar zoom da câmera.</string>
<string name="auto_rotate">Reconhecer códigos 1D verticais</string>
<string name="auto_rotate_summary">Girar automaticamente a câmera para reconhecer códigos 1D verticais. Dependendo do dispositivo, isto pode afetar o desempenho.</string>
<string name="try_harder">Otimizar o leitor para precisão</string>
<string name="try_harder">Otimizar leitor para precisão</string>
<string name="try_harder_summary">Ative esta opção para códigos muito difíceis de ler. Isto afetará o desempenho.</string>
<string name="show_toast_in_bulk_mode">Mostrar dados em modo contínuo</string>
<string name="show_toast_in_bulk_mode_summary">Mostrar brevemente os dados durante digitalização contínua.</string>
<string name="vibrate">Vibrar ao reconhecer</string>
<string name="vibrate_summary">Ative a opção se quiser que seu dispositivo vibre quando um código for reconhecido.</string>
<string name="use_history">Salvar histórico de escaneamentos</string>
<string name="vibrate_summary">Ative esta opção se quiser que seu dispositivo vibre ao reconhecer um código.</string>
<string name="beep">Bipar ao reconhecer</string>
<string name="beep_summary">Ative esta opção se quiser ouvir um bip ao reconhecer um código.</string>
<string name="beep_tone">Sinal sonoro</string>
<string name="tone_cdma_confirm">Confirmação do CDMA</string>
<string name="tone_sup_confirm">Solicitar confirmação de controle</string>
<string name="tone_sup_radio_ack">Solicitar confirmação do caminho de rádio</string>
<string name="tone_prop_ack">Reconhecimento positivo</string>
<string name="tone_prop_beep">Bip geral</string>
<string name="tone_prop_beep2">Bip duplo geral</string>
<string name="use_history">Ativar histórico de digitalizações</string>
<string name="use_history_summary">Salve códigos reconhecidos no seu dispositivo.</string>
<string name="ignore_consecutive_duplicates">Ignorar duplicações</string>
<string name="ignore_consecutive_duplicates_summary">Não salvar duplicações consecutivas no histórico de escaneamentos.</string>
<string name="ignore_consecutive_duplicates_summary">Não salvar duplicações consecutivas no histórico de digitalizações.</string>
<string name="open_immediately">Abrir imediatamente</string>
<string name="open_immediately_summary">Pular a inspeção e abrir o conteúdo imediatamente. Se ativado pode abrir conteúdo perigoso.</string>
<string name="open_immediately_summary">Pular a inspeção e abrir um conteúdo no mesmo instante. Quando ativado, pode abrir conteúdo perigoso.</string>
<string name="copy_immediately">Copiar ao clipboard</string>
<string name="copy_immediately_summary">Copiar automaticamente o conteúdo escaneado ao clipboard. Tem cuidado porque outros apps podem examinar seu clipboard em segundo plano.</string>
<string name="copy_immediately_summary">Copiar automaticamente um conteúdo digitalizado ao clipboard. Tem cuidado porque outros apps podem examinar seu clipboard em segundo plano.</string>
<string name="show_meta_data">Mostrar metadados</string>
<string name="show_meta_data_summary">Mostrar dados adicionais de código escaneado.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_meta_data_summary">Mostrar dados adicionais de código digitalizado.</string>
<string name="show_hex_dump">Mostrar impressão hexadecimal</string>
<string name="show_hex_dump_summary">Mostrar a impressão hexadecimal de conteúdo escaneado.</string>
<string name="show_hex_dump_summary">Mostrar impressão hexadecimal de conteúdo digitalizado.</string>
<string name="show_recreation">Mostrar código recriado</string>
<string name="show_recreation_summary">Se possível, recriar e mostrar código de conteúdo lido.</string>
<string name="close_automatically">Voltar após copiar/compartilhar</string>
<string name="close_automatically_summary">Voltar automaticamente à tela de digitalização após copiar ou compartilhar o código consultado.</string>
<string name="close_automatically_summary">Voltar automaticamente à tela de digitalização após copiar ou compartilhar um código examinado.</string>
<string name="default_search_engine">Abrir dados desconhecidos em</string>
<string name="always_ask">Sempre perguntar</string>
<string name="open_with_url">Abrir dados desconhecidos via URL</string>
<string name="clear_network_suggestions">Remover sugestões da rede</string>
<string name="clear_network_suggestions_summary">Remover todas as sugestões da rede que foram anteriormente fornecidas pelo app.</string>
<string name="really_remove_all_networks">Realmente remover todas as redes?</string>
<string name="clear_network_suggestions_success">Sugestões da rede removidas</string>
<string name="really_remove_all_networks">Deseja remover todas as redes?</string>
<string name="clear_network_suggestions_success">Sugestões da rede foram removidas</string>
<string name="clear_network_suggestions_nothing_to_remove">Nada para remover</string>
<string name="send_category">Encaminhamento</string>
<string name="send_scan_active">Encaminhar escaneamentos</string>
<string name="send_scan_active_summary">Ativar para encaminhar escaneamentos à URL definida</string>
<string name="send_scan_active">Encaminhar conteúdo digitalizado</string>
<string name="send_scan_active_summary">Ative para encaminhar conteúdo digitalizado à URL definida</string>
<string name="send_scan_url">URL à qual encaminhar</string>
<string name="send_scan_type">Tipo de solicitação</string>
<string name="send_type_get_add_content">GET e apenas adicionar o conteúdo</string>
<string name="send_type_get_query_string">GET com sequência completa da consulta</string>
<string name="send_type_get_add_content">GET e somente adicionar um conteúdo</string>
<string name="send_type_get_query_string">GET com sequência completa de consulta</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="send_type_external_browser">Abrir num navegador externo</string>
<string name="send_type_external_browser">Abrir em navegador externo</string>
<string name="test_url">Testar a URL</string>
<string name="really_remove_scan">Realmente quer remover este escaneamento?</string>
<string name="really_remove_all_scans">Realmente quer remover todos os escaneamentos?</string>
<string name="really_remove_selected_scans">Realmente remover escaneamentos selecionados?</string>
<string name="really_remove_scan">Deseja remover esta digitalização?</string>
<string name="really_remove_all_scans">Deseja remover todas as digitalizações?</string>
<string name="really_remove_selected_scans">Deseja remover digitalizações selecionados?</string>
<string name="clear_history">Limpar histórico</string>
<string name="copy_scan">Copiar digitalização</string>
<string name="edit_scan">Editar identificação</string>
<string name="remove_scan">Remover digitalização</string>
<string name="enter_name">Digite nome para identificar a digitalização</string>
<string name="enter_name">Digite nome para identificar esta digitalização</string>
<string name="enter_name_hint">Nome da digitalização</string>
<string name="no_barcode_found">Nenhum código encontrado</string>
<string name="pick_list_separator">Como separar itens da lista?</string>
<string name="separator_line_break">Quebra de linha</string>
<string name="separator_ruler">Régua</string>
<string name="save_as_file_name">Salvar em Downloads?</string>
<string name="save_as_file_name">Salvar para Downloads?</string>
<string name="file_name">Nome do arquivo</string>
<string name="error_saving_file">Não foi possível salvar o arquivo</string>
<string name="error_saving_file">Não foi possível salvar este arquivo</string>
<string name="error_file_exists">Arquivo já existe</string>
<string name="connect_to_wifi">Conectar via WiFi</string>
<string name="connect_to_wifi">Conectar a WiFi</string>
<string name="wifi_config_failed">Não foi possível configurar WiFi</string>
<string name="wifi_added">WiFi adicionado</string>
<string name="sms_send">Envie SMS</string>
<string name="sms_error">Não foi possível enviar SMS</string>
<string name="tel_dial">Disque número</string>
<string name="tel_error">Não foi possível discar número</string>
<string name="tel_error">Não foi possível discar este número</string>
<string name="mail_send">Envie e-mail</string>
<string name="mail_error">Não foi possível enviar e-mail</string>
<string name="vcard_add">Adicionar para contatos</string>
<string name="mail_error">Não foi possível enviar este e-mail</string>
<string name="vcard_add">Adicionar aos contatos</string>
<string name="vcard_failed">Não foi possível adicionar aos contatos</string>
<string name="vevent_add">Adicionar ao calendário</string>
<string name="vevent_failed">Não foi possível adicionar ao calendário</string>
<string name="otpauth_add">Adicionar 2FA</string>
<string name="search_web">Pesquisar na internet</string>
<string name="search_scan">Pesquisar em conteúdo já digitalizado</string>
<string name="search_web">Buscar na internet</string>
<string name="search_scan">Buscar em digitalizações feitas</string>
<string name="export_to_file">Exportar para arquivo</string>
<string name="export_as">Exportar como?</string>
<string name="export_as">Exportar em qual formato?</string>
<string name="export_csv_comma">Arquivo CSV com vírgulas</string>
<string name="export_csv_semicolon">Arquivo CSV com ponto-e-vírgula</string>
<string name="export_json">Arquivo JSON</string>
<string name="export_database">Base de dados SQLite</string>
<string name="saved_in_downloads">Salvo em Downloads</string>
<string name="rotate_image_cw">Girar a imagem no sentido horário</string>
<string name="toggle_free_rotation">Ativar rotação livre</string>
<string name="pick_file">Escolha imagem</string>
<string name="pick_code_to_scan">Escolha código para digitalizar</string>
<string name="shortcut_decode">Escaneie código</string>
@@ -167,4 +183,6 @@
<string name="wifi_anonymous_identity">Identidade anônima</string>
<string name="wifi_identity">Identidade</string>
<string name="wifi_phase2">Método Phase 2</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+33 -15
View File
@@ -17,14 +17,20 @@
<string name="error_correction_level_m" formatted="false">Средний (≈15&#37; исправлений)</string>
<string name="error_correction_level_q" formatted="false">Квартиль (≈25&#37; исправлений)</string>
<string name="error_correction_level_h" formatted="false">Высокий (≈30&#37; исправлений)</string>
<string name="issue_number">Номер выпуска</string>
<string name="orientation">Ориентация</string>
<string name="other_meta_data">Метаданные</string>
<string name="pdf417_extra_metadata">Метаданные PDF417</string>
<string name="possible_country">Возможная страна изготовления</string>
<string name="suggested_price">Предположительная цена</string>
<string name="upc_ean_extension">Расширение UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="colors">Цвета</string>
<string name="colors_black_on_white">Чёрный на белом</string>
<string name="colors_white_on_black">Белый на чёрном</string>
<string name="colors_black_on_transparent">Чёрный на прозрачном</string>
<string name="colors_white_on_transparent">Белый на прозрачном</string>
<string name="sequence_size">Размер последовательности</string>
<string name="sequence_index">Индекс последовательности</string>
<string name="sequence_id">Идентификатор последовательности</string>
<string name="gtin_issue_number">Номер выпуска</string>
<string name="gtin_country">Возможная страна изготовления</string>
<string name="gtin_price">Предположительная цена</string>
<string name="gtin_add_on">Расширение UPC EAN</string>
<string name="barcode_version_number">Версия</string>
<string name="qr_version_and_modules">%1$s (модули: %2$d)</string>
<string name="toggle_flash">Включить вспышку</string>
<string name="error_flash">Ошибка при переключении вспышки</string>
<string name="share">Поделиться</string>
@@ -68,15 +74,24 @@
<string name="show_crop_handle_summary">Ограничить сканирование изменяемой областью.</string>
<string name="barcode_formats">Форматы штрих-кодов</string>
<string name="zoom_by_swiping">Масштабировать жестом вверх/вниз</string>
<string name="zoom_by_swiping_summary">Проведите пальцем вверх или вниз для управления масштабированием камеры.</string>
<string name="zoom_by_swiping_summary">Жест пальцем вверх или вниз для управления масштабированием камеры.</string>
<string name="auto_rotate">Распознавать 1D штрих-коды вертикально</string>
<string name="auto_rotate_summary">Автоматически поворачивать камеру для распознавания вертикальных 1D штрих-кодов. В зависимости от устройства, это может повлиять на производительность.</string>
<string name="try_harder">Приоритет точности считывания</string>
<string name="try_harder_summary">Включите эту настройку для штрих-кодов, которые очень сложно прочитать. Влияет на производительность.</string>
<string name="try_harder_summary">Включайте для сложно распознаваемых штрих-кодов. Влияет на производительность.</string>
<string name="show_toast_in_bulk_mode">Показывать данные в непрерывном режиме</string>
<string name="show_toast_in_bulk_mode_summary">Кратко показывать считанные данные в режиме непрерывного сканирования.</string>
<string name="vibrate">Вибрация при обнаружении</string>
<string name="vibrate_summary">Включите эту настройку, если хотите, чтобы устройство вибрировало после распознавания штрих-кода.</string>
<string name="vibrate_summary">Если включено, устройство будет вибрировать после распознавания штрих-кода.</string>
<string name="beep">Звук при обнаружении</string>
<string name="beep_summary">Если включено, устройство издаст звуковой сигнал после распознавания штрих-кода.</string>
<string name="beep_tone">Тон звука</string>
<string name="tone_cdma_confirm">Подтверждение CDMA</string>
<string name="tone_sup_confirm">Подтверждение диспетчерского вызова</string>
<string name="tone_sup_radio_ack">Подтверждение приёма по радиоканалу</string>
<string name="tone_prop_ack">Положительное подтверждение</string>
<string name="tone_prop_beep">Обычный сигнал</string>
<string name="tone_prop_beep2">Обычный двойной сигнал</string>
<string name="use_history">Сохранять историю сканирования</string>
<string name="use_history_summary">Сохранять распознанные штрих-коды на устройстве.</string>
<string name="ignore_consecutive_duplicates">Не хранить дубликаты</string>
@@ -87,17 +102,17 @@
<string name="copy_immediately_summary">Автоматически копировать содержимое считанного штрих-кода в буфер обмена. Имейте в виду, что другие приложения могут иметь доступ к буферу обмена в фоне.</string>
<string name="show_meta_data">Показывать метаданные</string>
<string name="show_meta_data_summary">Показывать дополнительную информацию о считанных штрих-кодах.</string>
<string name="show_qr_version">Показывать версию QR</string>
<string name="show_qr_version_summary">Показывать номер версии QR-кода.</string>
<string name="show_hex_dump">Показывать шестнадцатеричный дамп</string>
<string name="show_hex_dump_summary">Показывать шестнадцатеричный дамп содержимого считанного штрих-кода.</string>
<string name="show_recreation">Показывать восстановленный штрих-код</string>
<string name="show_recreation_summary">Показывать штрих-код, восстановленный из считанного содержимого.</string>
<string name="close_automatically">Возврат после копирования/обмена</string>
<string name="close_automatically_summary">Автоматически возвращаться к экрану сканирования после копирования или передачу через функцию «Поделиться» считанного содержимого.</string>
<string name="default_search_engine">Поиск неизвестных данных в</string>
<string name="always_ask">Всегда спрашивать</string>
<string name="open_with_url">Открывать неизвестные данные по URL</string>
<string name="clear_network_suggestions">Очистить сетевые предложения</string>
<string name="clear_network_suggestions_summary">Удалить все сетевые предложения, ранее предложенные этим приложением.</string>
<string name="clear_network_suggestions">Удалить сетевые предложения</string>
<string name="clear_network_suggestions_summary">Удалить все сетевые предложения, ранее добавленные этим приложением.</string>
<string name="really_remove_all_networks">Удалить все сетевые предложения?</string>
<string name="clear_network_suggestions_success">Сетевые предложения удалены</string>
<string name="clear_network_suggestions_nothing_to_remove">Нечего удалять</string>
@@ -153,6 +168,7 @@
<string name="export_database">База данных SQLite</string>
<string name="saved_in_downloads">Сохранено в загрузках</string>
<string name="rotate_image_cw">Повернуть изображение по часовой стрелке</string>
<string name="toggle_free_rotation">Переключить свободный поворот</string>
<string name="pick_file">Открыть файл с изображением</string>
<string name="pick_code_to_scan">Выберите штрих-код для сканирования</string>
<string name="shortcut_decode">Сканировать штрих-код</string>
@@ -169,4 +185,6 @@
<string name="wifi_anonymous_identity">Аноним</string>
<string name="wifi_identity">Пользователь</string>
<string name="wifi_phase2">Двухэтапный метод</string>
<string name="network_suggestions">Сетевые предложения</string>
<string name="remove_suggestion">Удалить предложение</string>
</resources>
@@ -0,0 +1,30 @@
<resources>
<string-array name="search_engines_names">
<item>@string/always_ask</item>
<item>Google</item>
<item>DuckDuckGo</item>
<item>Qwant</item>
<item>Bing</item>
<item>Yandex</item>
<item>ebay</item>
<item>Amazon</item>
<item>OpenFoodFacts.org</item>
<item>OpenBeautyFacts.org</item>
<item>OpenPetFoodFacts.org</item>
<item>Barcode Lookup</item>
</string-array>
<string-array name="search_engines_values">
<item></item>
<item>https://www.google.com.tr/search?q=</item>
<item>https://duckduckgo.com/?q=</item>
<item>https://www.qwant.com/?q=</item>
<item>https://bing.com/?q=</item>
<item>https://yandex.com.tr/search/?text=</item>
<item>https://www.ebay.com/sch/i.html?_nkw=</item>
<item>https://www.amazon.com.tr/s?k=</item>
<item>https://world.openfoodfacts.org/cgi/search.pl?search_terms=</item>
<item>https://world.openbeautyfacts.org/cgi/search.pl?search_terms=</item>
<item>https://world.openpetfoodfacts.org/cgi/search.pl?search_terms=</item>
<item>https://www.barcodelookup.com/</item>
</string-array>
</resources>
+34 -16
View File
@@ -15,16 +15,22 @@
<string name="error_correction_level_m" formatted="false">Orta (~&#37;15 düzeltim)</string>
<string name="error_correction_level_q" formatted="false">Dörtte Bir (~&#37;25 düzeltim)</string>
<string name="error_correction_level_h" formatted="false">Yüksek (~&#37;30 düzeltim)</string>
<string name="issue_number">Basım sayısı</string>
<string name="orientation">Yönelim</string>
<string name="other_meta_data">Üst veri</string>
<string name="pdf417_extra_metadata">PDF417 üst verisi</string>
<string name="possible_country">Olası üretim yeri</string>
<string name="suggested_price">Önerilen fiyat</string>
<string name="upc_ean_extension">UPC EAN eklentisi</string>
<string name="qr_version">QR version</string>
<string name="colors">Ön ve arka plan</string>
<string name="colors_black_on_white">Beyaz üzerine siyah</string>
<string name="colors_white_on_black">Siyah üzerine beyaz</string>
<string name="colors_black_on_transparent">Şeffaf üzerine siyah</string>
<string name="colors_white_on_transparent">Şeffaf üzerine beyaz</string>
<string name="sequence_size">Dizi boyutu</string>
<string name="sequence_index">Dizi indeksi</string>
<string name="sequence_id">Dizi kimliği</string>
<string name="gtin_issue_number">Basım sayısı</string>
<string name="gtin_country">Olası üretim yeri</string>
<string name="gtin_price">Önerilen fiyat</string>
<string name="gtin_add_on">UPC EAN eklentisi</string>
<string name="barcode_version_number">Sürüm</string>
<string name="qr_version_and_modules">%1$s (%2$d modül)</string>
<string name="toggle_flash">Flaşı aç</string>
<string name="error_flash">Error toggling flash</string>
<string name="error_flash">Flaş açılırken hata oluştu</string>
<string name="share">Paylaş</string>
<string name="share_as">Şöyle paylaş:</string>
<string name="copy_to_clipboard">Panoya kopyala</string>
@@ -47,9 +53,9 @@
<string name="bulk_mode">Sürekli tara</string>
<string name="bulk_mode_summary">Her zaman sürekli taramaya başla.</string>
<string name="bulk_mode_delay">Sürekli taramalar arasındaki gecikme</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="scan_format">Scan %s</string>
<string name="restrict_format">Biçimi kısıtla</string>
<string name="remove_restriction">Kısıtlamayı kaldır</string>
<string name="scan_format">%s tara</string>
<string name="quarter_second">Çeyrek saniye</string>
<string name="half_second">Yarım saniye</string>
<string name="a_second">Bir saniye</string>
@@ -75,6 +81,15 @@
<string name="show_toast_in_bulk_mode_summary">Sürekli tarama yaparken taranan verileri kısaca göster.</string>
<string name="vibrate">Tanıyınca titre</string>
<string name="vibrate_summary">Kod tanındığında aygıtınızın titremesini istiyorsanız bunu etkinleştirin.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Tarama geçmişini kaydet</string>
<string name="use_history_summary">Tanınan kodları aygıtınızda saklayın.</string>
<string name="ignore_consecutive_duplicates">Yinelemeleri göz ardı et</string>
@@ -85,10 +100,10 @@
<string name="copy_immediately_summary">Taranan içerikleri kendiliğinden panoya kopyala. Unutmayın ki, diğer uygulamalar arka planda panonuzu gözetleyebilir.</string>
<string name="show_meta_data">Üst veriyi göster</string>
<string name="show_meta_data_summary">Taranan barkod ile ilgili ek veriyi göster</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Hex yığınını göster</string>
<string name="show_hex_dump_summary">Taranan içeriklerin hex yığınını göster.</string>
<string name="show_recreation">Yeniden oluşturulan barkodu göster</string>
<string name="show_recreation_summary">Mümkünse okunan içerikten barkodu yeniden oluştur ve göster.</string>
<string name="close_automatically">Kopyala/Paylaş\'tan sonra geri dön</string>
<string name="close_automatically_summary">Okunan içeriği kopyaladıktan veya paylaştıktan sonra kendiliğinden tarama ekranına dön.</string>
<string name="default_search_engine">Bilinmeyen verileri şurada aç</string>
@@ -100,8 +115,8 @@
<string name="clear_network_suggestions_success">Ağ önerileri temizlendi</string>
<string name="clear_network_suggestions_nothing_to_remove">Kaldırılacak bir şey yok</string>
<string name="send_category">Yönlendirme</string>
<string name="send_scan_active">Forward scans</string>
<string name="send_scan_active_summary">Enable to forward scans to a the given URL</string>
<string name="send_scan_active">Taramaları gönder</string>
<string name="send_scan_active_summary">Taramaları belirtilen URL\'ye göndermeyi etkinleştir</string>
<string name="send_scan_url">Her taramayı URL\'ye gönder</string>
<string name="send_scan_type">Her tarama için isteğin türü</string>
<string name="send_type_get_add_content">GET ve basitçe içeriği ekle</string>
@@ -151,6 +166,7 @@
<string name="export_database">SQLite veri tabanı olarak dışa aktar</string>
<string name="saved_in_downloads">İndirilenlere kaydedildi</string>
<string name="rotate_image_cw">Görüntüyü saat yönünde döndür</string>
<string name="toggle_free_rotation">Serbest dönüşü değiştir</string>
<string name="pick_file">Görüntü dosyası seç</string>
<string name="pick_code_to_scan">Taranacak kod seç</string>
<string name="shortcut_decode">Barkod tara</string>
@@ -167,4 +183,6 @@
<string name="wifi_anonymous_identity">Anonim kimlik</string>
<string name="wifi_identity">Kimlik</string>
<string name="wifi_phase2">2. aşama yöntemi</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+28 -10
View File
@@ -16,14 +16,20 @@
<string name="error_correction_level_m" formatted="false">Середній (~15&#37; виправлення)</string>
<string name="error_correction_level_q" formatted="false">Квартиль (~25&#37; виправлення)</string>
<string name="error_correction_level_h" formatted="false">Високий (~30&#37; виправлення)</string>
<string name="issue_number">Номер випуску</string>
<string name="orientation">Орієнтація</string>
<string name="other_meta_data">Метадані</string>
<string name="pdf417_extra_metadata">Метадані PDF417</string>
<string name="possible_country">Можлива країна-виробник</string>
<string name="suggested_price">Рекомендована ціна</string>
<string name="upc_ean_extension">Розширення UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">Номер випуску</string>
<string name="gtin_country">Можлива країна-виробник</string>
<string name="gtin_price">Рекомендована ціна</string>
<string name="gtin_add_on">Розширення UPC EAN</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Увімкнути спалах</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Поділитися</string>
@@ -76,6 +82,15 @@
<string name="show_toast_in_bulk_mode_summary">Коротко показати відскановані дані під час безперервного сканування.</string>
<string name="vibrate">Вібрувати при виявленні</string>
<string name="vibrate_summary">Увімкніть це, якщо хочете, щоб пристрій вібрував, коли код розпізнано.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Зберігати історію сканування</string>
<string name="use_history_summary">Збережіть розпізнані коди на своєму пристрої.</string>
<string name="ignore_consecutive_duplicates">Ігнорувати дублікати</string>
@@ -86,10 +101,10 @@
<string name="copy_immediately_summary">Автоматично копіювати відсканований вміст у буфер обміну. Зверніть увагу, що інші програми можуть стежити за буфером обміну в фоновому режимі.</string>
<string name="show_meta_data">Показувати метадані</string>
<string name="show_meta_data_summary">Показувати додаткові дані про відскановані штрих-коди.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Показувати шістнадцятковий дамп</string>
<string name="show_hex_dump_summary">Показувати шістнадцятковий дамп відсканованого вмісту.</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Повернутися після копіювання/поширення</string>
<string name="close_automatically_summary">Автоматично повернутися на екран сканування після копіювання або поширення прочитаного вмісту.</string>
<string name="default_search_engine">Відкривати невідомі дані в</string>
@@ -152,6 +167,7 @@
<string name="export_database">Експортувати базу даних SQLite</string>
<string name="saved_in_downloads">Збережено в Завантаженнях</string>
<string name="rotate_image_cw">Повернути зображення за годинниковою стрілкою</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">Вибрати файл зображення</string>
<string name="pick_code_to_scan">Вибрати код для сканування</string>
<string name="shortcut_decode">Сканувати штрих-код</string>
@@ -168,4 +184,6 @@
<string name="wifi_anonymous_identity">Анонімна особа</string>
<string name="wifi_identity">Користувач</string>
<string name="wifi_phase2">Phase 2 метод</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+28 -10
View File
@@ -14,14 +14,20 @@
<string name="error_correction_level_m" formatted="false">Trung bình (sửa ~15&#37;)</string>
<string name="error_correction_level_q" formatted="false">Một phần tư (sửa ~25&#37;)</string>
<string name="error_correction_level_h" formatted="false">Cao (sửa ~30&#37;)</string>
<string name="issue_number">Số</string>
<string name="orientation">Hướng</string>
<string name="other_meta_data">Dữ liệu</string>
<string name="pdf417_extra_metadata">Dữ liệu PDF417</string>
<string name="possible_country">Có thể được sản xuất ở nước</string>
<string name="suggested_price">Giá được gợi ý</string>
<string name="upc_ean_extension">Phần mở rộng UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="colors">Fore and background</string>
<string name="colors_black_on_white">Black on white</string>
<string name="colors_white_on_black">White on black</string>
<string name="colors_black_on_transparent">Black on transparent</string>
<string name="colors_white_on_transparent">White on transparent</string>
<string name="sequence_size">Sequence size</string>
<string name="sequence_index">Sequence index</string>
<string name="sequence_id">Sequence ID</string>
<string name="gtin_issue_number">Số</string>
<string name="gtin_country">Có thể được sản xuất ở nước</string>
<string name="gtin_price">Giá được gợi ý</string>
<string name="gtin_add_on">Phần mở rộng UPC EAN</string>
<string name="barcode_version_number">Version</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">Bật/tắt đèn</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Chia sẻ</string>
@@ -74,6 +80,15 @@
<string name="show_toast_in_bulk_mode_summary">Hiện nhanh dữ liệu trong khi quét liên tục.</string>
<string name="vibrate">Rung khi xác định được mã</string>
<string name="vibrate_summary">Kích hoạt nếu bạn muốn máy của bạn rung khi nhận dạng được mã.</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">Lưu lịch sử quét</string>
<string name="use_history_summary">Lưu mã đã nhận dạng được trên máy của bạn.</string>
<string name="ignore_consecutive_duplicates">Bỏ qua trùng lặp</string>
@@ -84,10 +99,10 @@
<string name="copy_immediately_summary">Tự động sao chép kết quả. Lưu ý: ứng dụng khác có thể xem nội dung bạn đã sao chép.</string>
<string name="show_meta_data">Hiện dữ liệu</string>
<string name="show_meta_data_summary">Hiện thêm thông tin về mã vạch quét được.</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">Hiện mã thập lục phân</string>
<string name="show_hex_dump_summary">Hiện mã thập lục phân từ mã quét được.</string>
<string name="show_recreation">Show recreated barcode</string>
<string name="show_recreation_summary">Recreate and show barcode from read content if possible.</string>
<string name="close_automatically">Quay lại sau khi Sao chép/Chia sẻ</string>
<string name="close_automatically_summary">Tự động quay trở về màn hình quét sao khi sao chép hoặc chia sẻ nội dung đọc được.</string>
<string name="default_search_engine">Mở dữ liệu không xác định bằng</string>
@@ -150,6 +165,7 @@
<string name="export_database">Cơ sở dữ liệu SQLite</string>
<string name="saved_in_downloads">Lưu vào Downloads</string>
<string name="rotate_image_cw">Quay ảnh theo chiều kim đồng hồ</string>
<string name="toggle_free_rotation">Toggle free rotation</string>
<string name="pick_file">Chọn tệp ảnh</string>
<string name="pick_code_to_scan">Chọn mã để quét</string>
<string name="shortcut_decode">Quét mã vạch</string>
@@ -166,4 +182,6 @@
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
+34 -16
View File
@@ -10,18 +10,24 @@
<item quantity="other">%2$d 字符, %1$s</item>
</plurals>
<string name="error_correction_level">纠错级别</string>
<string name="error_correction_level_l" formatted="false">Low (~7&#37; 准确度)</string>
<string name="error_correction_level_m" formatted="false">Medium (~15&#37; 准确度)</string>
<string name="error_correction_level_q" formatted="false">Quartile (~25&#37; 准确度)</string>
<string name="error_correction_level_h" formatted="false">High (~30&#37; 准确度)</string>
<string name="issue_number">发行编号</string>
<string name="orientation">方向</string>
<string name="other_meta_data">元数据</string>
<string name="pdf417_extra_metadata">PDF417 元数据</string>
<string name="possible_country">可能产地</string>
<string name="suggested_price">建议价格</string>
<string name="upc_ean_extension">UPC EAN 扩展</string>
<string name="qr_version">QR version</string>
<string name="error_correction_level_l" formatted="false"> (~7&#37; 准确度)</string>
<string name="error_correction_level_m" formatted="false"> (~15&#37; 准确度)</string>
<string name="error_correction_level_q" formatted="false">较高 (~25&#37; 准确度)</string>
<string name="error_correction_level_h" formatted="false"> (~30&#37; 准确度)</string>
<string name="colors">前景和背景</string>
<string name="colors_black_on_white">白底黑字</string>
<string name="colors_white_on_black">黑底白字</string>
<string name="colors_black_on_transparent">透明底黑字</string>
<string name="colors_white_on_transparent">透明底白字</string>
<string name="sequence_size">序列大小</string>
<string name="sequence_index">序列索引</string>
<string name="sequence_id">序列 ID</string>
<string name="gtin_issue_number">发行编号</string>
<string name="gtin_country">可能产地</string>
<string name="gtin_price">建议价格</string>
<string name="gtin_add_on">UPC EAN 扩展</string>
<string name="barcode_version_number">版本</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">开关闪光灯</string>
<string name="error_flash">开关闪光灯出错</string>
<string name="share">分享</string>
@@ -46,7 +52,7 @@
<string name="bulk_mode">连续扫描</string>
<string name="bulk_mode_summary">始终开启连续扫描</string>
<string name="bulk_mode_delay">连续扫描之间的延迟</string>
<string name="restrict_format">受限格式</string>
<string name="restrict_format">严格模式(扫描指定编码格式)</string>
<string name="remove_restriction">解除限制</string>
<string name="scan_format">扫描 %s</string>
<string name="quarter_second">四分之一秒</string>
@@ -74,6 +80,15 @@
<string name="show_toast_in_bulk_mode_summary">连续扫描时简要显示扫描数据。</string>
<string name="vibrate">识别时震动</string>
<string name="vibrate_summary">如果你希望在识别到条码后震动设备,请启用该选项。</string>
<string name="beep">识别时提示音</string>
<string name="beep_summary">如果你希望在识别到条码后发出提示音,请启用该选项。</string>
<string name="beep_tone">选择提示音</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">保存扫描历史</string>
<string name="use_history_summary">在本地保存扫描历史</string>
<string name="ignore_consecutive_duplicates">不保存重复历史</string>
@@ -84,10 +99,10 @@
<string name="copy_immediately_summary">注意其他 APP 可能会在后台监控剪贴板</string>
<string name="show_meta_data">显示元数据</string>
<string name="show_meta_data_summary">显示已扫描条码的额外数据</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">显示16进制数据</string>
<string name="show_hex_dump_summary">显示已扫描条码的16进制数据</string>
<string name="show_recreation">显示重新创建的条码</string>
<string name="show_recreation_summary">如果可以,就从读取内容中重新创建并显示条码。</string>
<string name="close_automatically">复制/分享后自动返回</string>
<string name="close_automatically_summary">复制或分享读取的内容后自动返回扫描主界面。</string>
<string name="default_search_engine">打开未知数据方式</string>
@@ -149,7 +164,8 @@
<string name="export_json">JSON</string>
<string name="export_database">导出 SQLite 数据库</string>
<string name="saved_in_downloads">已保存到下载目录</string>
<string name="rotate_image_cw">旋转图片</string>
<string name="rotate_image_cw">顺时针旋转图片</string>
<string name="toggle_free_rotation">切换自由旋转</string>
<string name="pick_file">选择图片文件</string>
<string name="pick_code_to_scan">选择扫描编码</string>
<string name="shortcut_decode">扫描条码</string>
@@ -166,4 +182,6 @@
<string name="wifi_anonymous_identity">匿名身份</string>
<string name="wifi_identity">身份</string>
<string name="wifi_phase2">阶段 2 方法</string>
<string name="network_suggestions">网络建议</string>
<string name="remove_suggestion">删除建议</string>
</resources>
+38 -20
View File
@@ -12,18 +12,24 @@
<string name="error_correction_level">糾錯等級</string>
<string name="error_correction_level_l" formatted="false">低 (~7&#37; 準確度)</string>
<string name="error_correction_level_m" formatted="false">中 (~15&#37; 準確度)</string>
<string name="error_correction_level_q" formatted="false">Quartile (~25&#37; 準確度)</string>
<string name="error_correction_level_q" formatted="false">較高 (~25&#37; 準確度)</string>
<string name="error_correction_level_h" formatted="false">高 (~30&#37; 準確度)</string>
<string name="issue_number">發行編號</string>
<string name="orientation">方向</string>
<string name="other_meta_data">Metadata</string>
<string name="pdf417_extra_metadata">PDF417 metadata</string>
<string name="possible_country">可能製作國家</string>
<string name="suggested_price">建議價格</string>
<string name="upc_ean_extension">UPC EAN 擴充</string>
<string name="qr_version">QR version</string>
<string name="colors">前景和背景</string>
<string name="colors_black_on_white">白底黑字</string>
<string name="colors_white_on_black">黑底白字</string>
<string name="colors_black_on_transparent">透明底黑字</string>
<string name="colors_white_on_transparent">透明底白字</string>
<string name="sequence_size">序列大小</string>
<string name="sequence_index">序列索引</string>
<string name="sequence_id">序列 ID</string>
<string name="gtin_issue_number">發行編號</string>
<string name="gtin_country">可能製作國家</string>
<string name="gtin_price">建議價格</string>
<string name="gtin_add_on">UPC EAN 擴充</string>
<string name="barcode_version_number">版本</string>
<string name="qr_version_and_modules">%1$s (%2$d modules)</string>
<string name="toggle_flash">開關閃光燈</string>
<string name="error_flash">Error toggling flash</string>
<string name="error_flash">開關閃光燈時發生錯誤</string>
<string name="share">分享</string>
<string name="share_as">以何種方式分享?</string>
<string name="copy_to_clipboard">複製到剪貼簿</string>
@@ -46,9 +52,9 @@
<string name="bulk_mode">連續掃描</string>
<string name="bulk_mode_summary">始終開啟連續掃描。</string>
<string name="bulk_mode_delay">連續掃描間的延遲</string>
<string name="restrict_format">Restrict format</string>
<string name="remove_restriction">Remove restriction</string>
<string name="scan_format">Scan %s</string>
<string name="restrict_format">限制格式</string>
<string name="remove_restriction">刪除限制</string>
<string name="scan_format">掃描 %s</string>
<string name="quarter_second">四分之一秒</string>
<string name="half_second">半秒</string>
<string name="a_second">一秒</string>
@@ -58,7 +64,7 @@
<string name="preferences">偏好設定</string>
<string name="scan_category">掃描</string>
<string name="content_category">內容</string>
<string name="locale_category">語言</string>
<string name="locale_category">語言</string>
<string name="custom_locale">設定語言</string>
<string name="follow_system_settings">跟隨系統設定</string>
<string name="show_crop_handle">顯示裁切範圍選擇器</string>
@@ -74,6 +80,15 @@
<string name="show_toast_in_bulk_mode_summary">連續掃描時簡要顯示掃描資料。</string>
<string name="vibrate">振動提示</string>
<string name="vibrate_summary">識別條碼時振動提示。</string>
<string name="beep">Beep on detection</string>
<string name="beep_summary">Enable this if you want your device to beep when a code is recognized.</string>
<string name="beep_tone">Beep tone</string>
<string name="tone_cdma_confirm">CDMA confirm</string>
<string name="tone_sup_confirm">Call supervisory confirm</string>
<string name="tone_sup_radio_ack">Call supervisory radio path acknowledgment</string>
<string name="tone_prop_ack">Positive acknowledgment</string>
<string name="tone_prop_beep">General beep</string>
<string name="tone_prop_beep2">General double beep</string>
<string name="use_history">儲存掃描記錄</string>
<string name="use_history_summary">在本機儲存掃描記錄。</string>
<string name="ignore_consecutive_duplicates">不儲存重複歷史記錄</string>
@@ -84,10 +99,10 @@
<string name="copy_immediately_summary">自動將掃描的內容複製到剪貼簿。請注意,其他 App 可能會在背景監控剪貼簿。</string>
<string name="show_meta_data">顯示 Metadata</string>
<string name="show_meta_data_summary">顯示已掃描條碼的額外資訊。</string>
<string name="show_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</string>
<string name="show_hex_dump">顯示 Hex dump</string>
<string name="show_hex_dump_summary">顯示已掃描條碼的 Hex dump。</string>
<string name="show_recreation">顯示重新創建的條碼</string>
<string name="show_recreation_summary">如果可以,就從讀取內容中重新創建並顯示條碼。</string>
<string name="close_automatically">複製/分享後自動返回</string>
<string name="close_automatically_summary">複製或分享讀取的內容後自動返回掃描主要界面。</string>
<string name="default_search_engine">使用何種方式開啟未知資料</string>
@@ -99,15 +114,15 @@
<string name="clear_network_suggestions_success">網路建議已清除</string>
<string name="clear_network_suggestions_nothing_to_remove">沒有什麼可以移除的</string>
<string name="send_category">轉發</string>
<string name="send_scan_active">Forward scans</string>
<string name="send_scan_active_summary">Enable to forward scans to a the given URL</string>
<string name="send_scan_active">轉發掃描</string>
<string name="send_scan_active_summary">啟用以將掃描轉發到給定的 URL</string>
<string name="send_scan_url">將每個掃描結果傳送到 URL</string>
<string name="send_scan_type">每次掃描的請求類型</string>
<string name="send_type_get_add_content">GET 簡單附加資料</string>
<string name="send_type_get_query_string">GET 完整查詢資料</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="send_type_external_browser">Open in external browser</string>
<string name="send_type_external_browser">在外部瀏覽器中開啟</string>
<string name="test_url">測試 URL</string>
<string name="really_remove_scan">確定刪除記錄?</string>
<string name="really_remove_all_scans">確定刪除全部掃描記錄?</string>
@@ -147,9 +162,10 @@
<string name="export_csv_comma">逗號分隔的 CSV 檔案</string>
<string name="export_csv_semicolon">分號分隔的 CSV 檔案</string>
<string name="export_json">JSON 檔案</string>
<string name="export_database">SQLite 資料庫</string>
<string name="export_database">導出 SQLite 資料庫</string>
<string name="saved_in_downloads">已儲存到下載目錄</string>
<string name="rotate_image_cw">順時針旋轉圖片</string>
<string name="toggle_free_rotation">切換自由旋轉</string>
<string name="pick_file">選擇圖片檔案</string>
<string name="pick_code_to_scan">選擇要掃描的條碼</string>
<string name="shortcut_decode">掃描條碼</string>
@@ -166,4 +182,6 @@
<string name="wifi_anonymous_identity">匿名身分</string>
<string name="wifi_identity">身分</string>
<string name="wifi_phase2">Phase 2 method</string>
<string name="network_suggestions">Network suggestions</string>
<string name="remove_suggestion">Remove suggestion</string>
</resources>
@@ -0,0 +1,8 @@
<resources>
<string-array name="colors">
<item>@string/colors_black_on_white</item>
<item>@string/colors_white_on_black</item>
<item>@string/colors_black_on_transparent</item>
<item>@string/colors_white_on_transparent</item>
</string-array>
</resources>
+6 -6
View File
@@ -5,6 +5,8 @@
<item>CODE 39</item>
<item>CODE 93</item>
<item>CODE 128</item>
<item>DATA BAR</item>
<item>DATA BAR EXPANDED</item>
<item>DATA MATRIX</item>
<item>EAN 8</item>
<item>EAN 13</item>
@@ -12,11 +14,9 @@
<item>MAXICODE</item>
<item>PDF 417</item>
<item>QR CODE</item>
<item>RSS 14</item>
<item>RSS EXPANDED</item>
<item>MICRO QR CODE</item>
<item>UPC A</item>
<item>UPC E</item>
<item>UPC EAN EXTENSION</item>
</string-array>
<string-array name="barcode_formats_values">
<item>AZTEC</item>
@@ -24,6 +24,8 @@
<item>CODE_39</item>
<item>CODE_93</item>
<item>CODE_128</item>
<item>DATA_BAR</item>
<item>DATA_BAR_EXPANDED</item>
<item>DATA_MATRIX</item>
<item>EAN_8</item>
<item>EAN_13</item>
@@ -31,10 +33,8 @@
<item>MAXICODE</item>
<item>PDF_417</item>
<item>QR_CODE</item>
<item>RSS_14</item>
<item>RSS_EXPANDED</item>
<item>MICRO_QR_CODE</item>
<item>UPC_A</item>
<item>UPC_E</item>
<item>UPC_EAN_EXTENSION</item>
</string-array>
</resources>

Some files were not shown because too many files have changed in this diff Show More