Compare commits

...
148 Commits
Author SHA1 Message Date
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
Markus Fisch 1dde8c2817 Advance version number to 1.50.0 2022-05-18 22:48:58 +02:00
Markus Fisch 57fea95b9b Add support for MATMSG format 2022-05-18 22:37:56 +02:00
solokotandGitHub 806dafbecd Updated Russian translation 2022-05-18 12:11:14 +02:00
Markus Fisch 44b788fa74 Add a setting to show the QR Code version
Which is determined by recreating the QR Code.

Knowing the exact version of a given QR Code can be useful sometimes.
2022-05-17 19:03:03 +02:00
ss11mikandGitHub 9f167e7a2b Update Czech translation
Add Czech translation for new strings and update some old ones
2022-05-15 13:25:46 +02:00
Markus Fisch 6852b65239 Recognize URLs in colloquial, incomplete form too
So "google.com" is recognized as web action.
2022-05-14 12:50:22 +02:00
Markus Fisch 3d7c9be7ba Update Kotlin version 2022-05-12 22:40:03 +02:00
Markus Fisch f9401a9dda Migrate to lint from lintOptions 2022-05-12 22:40:03 +02:00
Markus Fisch 79dd48b07a Move package from Android manifest to build files
Declaration of a project's namespace using the package attribute
of the Android manifest is deprecated in favour of a namespace
declaration in build files.
2022-05-12 22:40:03 +02:00
Markus Fisch 6a7ab2c6e5 Update build tools and gradle wrapper 2022-05-12 22:40:03 +02:00
NickoriginalandGitHub c76d96cbe4 Update Russian translation 2022-05-12 22:39:23 +02:00
Markus Fisch e1b3935659 Add timezone offset in calendar dates
VCalendar/VEvent dates may contain a timezone that was not actually
used, as Date.getTime() returns the number of milliseconds (since
January 1, 1970, 00:00:00 GMT) without taking the timezone into
account.
2022-05-09 21:47:51 +02:00
Markus Fisch b7a4db5f4b Update to latest ZXing version 2022-05-02 18:54:30 +02:00
Markus Fisch f23414b003 Remove unused getLinks() function
No longer used.
2022-04-30 20:25:06 +02:00
Markus Fisch 282d2499a8 Shorten encoding a barcode 2022-04-25 20:17:53 +02:00
Markus Fisch a6cc8ed32f Add sample for AndroidX Activity's to README
Because `startActivityForResult()` is deprecated there.
2022-04-25 18:11:12 +02:00
Markus Fisch 7b155369fd Fix closing end tag in Japanese translation 2022-04-24 15:16:54 +02:00
NPLandGitHub 55a69db2c5 Update Japanese translation 2022-04-24 15:14:17 +02:00
Balázs ÚrandGitHub 170878a795 Update Hungarian translation 2022-04-17 11:15:11 +02:00
Markus Fisch 18ade0fe33 Update icon and feature graphic for F-Droid 2022-04-10 13:30:37 +02:00
Markus Fisch 4565848344 Add changelog for latest version for f-droid 2022-04-08 12:12:37 +02:00
Markus Fisch 353e1b5494 Update tools version 2022-04-08 12:11:25 +02:00
Markus Fisch 9986a4ffb5 Advance version number to 1.49.2 2022-04-08 12:09:43 +02:00
Markus Fisch c464b7de02 Optimize latest vector drawables with avocado 2022-04-07 22:48:46 +02:00
Markus Fisch e588405413 Change icon design
Because Google thinks my original design would "impersonate someone
else".

I have absolutely no idea.

Well, in order to make the app available again as soon as possible,
and because there have already been complaints about the icon not
being "intuitive", and because it's probably pointless to argue with
Google's bots and minions, I'm just changing the design a bit.
2022-04-07 22:47:31 +02:00
mezy sincandMarkus Fisch fdaf20fd45 Fix pt-br translation 2022-04-02 19:32:33 +02:00
mezy sincandMarkus Fisch 7c8fdb8ea1 Update pt-br translation 2022-04-02 13:53:54 +02:00
Markus Fisch bb9d556c16 Advance version number to 1.49.1 2022-03-31 20:50:50 +02:00
VixbandGitHub 9e395d1928 Update Simplified Chinese translation 2022-03-31 19:11:01 +02:00
Markus Fisch 95f12e7c31 Return directly to caller for deep links
If this app was invoked via a deep link, but without a return URI,
we never want to return to the camera screen after scanning, but
to the caller.
2022-03-30 20:11:44 +02:00
Markus Fisch 9dac0b13fb Fix getting ORIENTATION member from meta data
Was UPC_EAN_EXTENSION instead.
2022-03-30 19:57:00 +02:00
Markus Fisch 7939a728bc Make isReturnUrl() a String extension
And thereby remove Intent from the scope of the function.
2022-03-30 19:51:19 +02:00
Markus Fisch b6ca20d813 Move Cursor extensions to a separate file 2022-03-30 19:48:43 +02:00
Markus Fisch fe7e36804e Advance version number to 1.49.0 2022-03-29 19:56:31 +02:00
Markus Fisch 8cf1c35029 Enable forwarding by default
To keep forwarding intact when updating an app.

This has no effect for new installations because initially there's
no forwarding URL set. Forwarding works only when this toggle is
enabled *and* if there was a forwarding URL set.
2022-03-29 19:44:05 +02:00
Markus Fisch 62ca2299a0 Clean up preprocessor test
And move creating RenderScript out of loop.

No need to re-create this for every sample.
2022-03-25 20:10:43 +01:00
Markus Fisch 2423586c8c Make Y in encodeYUV420SP() lower case
To comply with the Kotlin style guide.

And simply use s/t for x/y.
2022-03-24 19:49:21 +01:00
Markus Fisch 29b1f44bb9 Update getting Vibrator on Android S+
VIBRATOR_SERVICE is deprecated.
2022-03-24 19:18:36 +01:00
Markus Fisch acee18e016 Replace context getter with local variable
It's there anyway and we shouldn't run a function multiple times
where it's enough to do it once and go with the result.
2022-03-21 22:39:21 +01:00
Markus Fisch f798dce832 Make setZoom() a Camera extension 2022-03-21 22:31:09 +01:00
Markus Fisch 97838ec7c4 Remove unnecessary type declarations 2022-03-22 13:51:27 +01:00
Markus Fisch 767860ab07 Remove body of decodeLuminanceSource()
And use the single expression syntax instead.
2022-03-22 13:51:27 +01:00
Markus Fisch f8fd00f21b Use apply scope function to set ContentValues
A bit more elegant.
2022-03-22 13:51:27 +01:00
solokotandGitHub 2cf6aa0812 Update Russian translation 2022-03-22 12:00:31 +01:00
Markus Fisch 197554fd1b Add a toggle to quickly enable/disable forwarding
Easier than clearing the URL, especially if you want to keep the
URL for later.
2022-03-21 21:56:06 +01:00
Markus Fisch 3dc35ac60d Only play error peep when not in silent mode
The app shouldn't play any sound when the phone is set to silent.
2022-03-21 21:33:42 +01:00
Markus Fisch fd05209f57 Enable/disable torch mode according to parameters
And show an error toast in case setting flash parameters fails.
2022-03-21 19:48:59 +01:00
Markus Fisch 6d5aed816f Break very long lines in IAction
Improves readability for my taste.
2022-03-18 20:44:55 +01:00
Markus Fisch 268c395043 Configure new Intent with apply scope function
Instead of declaring a variable beforehand.
2022-03-18 20:41:36 +01:00
Markus Fisch 867dc36811 Desugar Java 8 language features for ZXing 3.4
Add desugaring support to reverse translate Java 8 language features
in order to use the latest ZXing without having to increase minSdk.

ZXing 3.4 doesn't work on SDK levels below 24 anymore, see:
https://github.com/zxing/zxing/issues/1170

Many thanks to @TheLastProject for showing me the way:
https://github.com/CatimaLoyalty/Android/commit/cbcf1bcd998b9a5fdf7354a4287c64e95f2c3845
2022-03-16 21:44:20 +01:00
Markus Fisch e6e9b912b6 Improve german translation 2022-03-15 20:15:15 +01:00
Markus Fisch 152b4e50fc Update Kotlin version 2022-03-15 20:15:02 +01:00
Markus Fisch 93070f38c9 Update Kotlin coroutines library 2022-03-15 20:14:39 +01:00
Markus Fisch 7a162d6fb0 Update JUnit version 2022-03-15 20:14:15 +01:00
solokotandGitHub 9c03e83d3a Update Russian translation 2022-03-15 09:28:44 +01:00
Markus Fisch 4be9421b44 Advance version number to 1.48.1 2022-03-11 15:21:16 +01:00
Markus Fisch b895997967 Fix broken detection of binary content
And simplify detection and handling of binary data.
2022-03-11 15:16:43 +01:00
Markus Fisch b5bbe659db Advance version number to 1.48.0 2022-03-10 12:04:34 +01:00
Markus Fisch bb7715455a Add an item to remove the format restriction
If it is set.
2022-03-09 19:53:37 +01:00
Markus Fisch 5283acee8f Add a menu item to restrict recognized formats
Only temporarily as long as the instance is used.

This allows to quickly restrict scanning to a certain format
without having to fiddle with all the formats in settings.
2022-03-09 19:47:33 +01:00
Markus Fisch 315abfb1dd Show alnum characters in binary data
And condense all non-alnum characters to just "…".

This may give a glimpse at the readable content and is probably
better to read than the hex dump for non-technical users.
2022-03-09 18:57:58 +01:00
Markus Fisch 05c776168e Make parseAndNormalizeUri() an extension function 2022-03-09 18:46:58 +01:00
Markus Fisch 880b8e0b24 Catch unsupported encodings in urlEncode()
And just return the original string in that case.

Invalid data shouldn't crash the app.
2022-03-09 18:43:33 +01:00
Markus Fisch 1597adb284 Fix showing binary data label for history scans
A scan's (String) "content" will be an empty string when read
from the database because I don't want to save the content twice
(binary data is already saved in the "raw" field).
2022-03-09 18:39:32 +01:00
Markus Fisch 1c356aeaed Update tools version 2022-03-09 18:37:16 +01:00
Markus Fisch fe934c5d6e Use AlertDialog from base SDK
Instead of the support variant.

There's no need to use the special variant from the support library.
2022-03-09 18:34:17 +01:00
Markus Fisch 5091565ff0 Make preference constants private
Because they can be.
2022-02-26 12:48:22 +01:00
Markus Fisch c7eb664958 Add a monochome launcher icon
As required for SDK 32, Android 13.
2022-02-21 19:48:08 +01:00
Markus Fisch c763c522e7 Update to SDK 32 2022-02-21 19:47:53 +01:00
Markus Fisch dc1beb5f28 Add new data extraction rules configuration
There's a new XML format for Android 12+.
2022-02-21 19:43:07 +01:00
Markus Fisch 76ea46cea8 Split data tag for VIEW intent filter
According to lint, it's better to have multiple tags with
individual attributes because it better "communicates the
combining behavior and is clearer".
2022-02-21 19:35:00 +01:00
Markus Fisch 0991fb85f0 Remove redundant label from activities 2022-02-21 19:30:57 +01:00
Markus Fisch 09f0d2e1db Remove unused quantity translations
According to lint, these quantities are not relevant.
2022-02-21 19:29:27 +01:00
Markus Fisch bc0655788c Add "many" plural for french translation
As required by the linter.
2022-02-21 19:24:57 +01:00
Markus Fisch 739a801cb4 Add "many" plural for czech translation
As required by the linter.
2022-02-21 19:23:50 +01:00
Markus Fisch c18f1b8770 Simplify Bitmap.saveAsPng() function 2022-02-19 18:37:13 +01:00
Markus Fisch b0df09d76f Simplify the execShareIntent function 2022-02-19 18:36:14 +01:00
Markus Fisch e8b8e578cb Fix handling empty meta strings
Check if the data is empty and not just null.

And prepare WiFi info like we do it for meta info.
2022-02-10 22:20:54 +01:00
Markus Fisch 09ce14125e Use apply scope function to use ViewHolder
And thereby avoid a temporary variable.

Also make getViewHolder() a bit more compact by using the
single-expression function syntax.
2022-02-10 19:48:12 +01:00
Markus Fisch 446d1543c3 Refactor Scan.timestamp to Scan.dateTime
Because it's really just a string containing the date and time
and not a timestamp in the sense of a Unix timestamp.
2022-02-08 19:23:33 +01:00
Markus Fisch 02a360beaf Refactor getRawBytes() to getRawData()
And make it an extension of Result.
2022-02-08 19:19:49 +01:00
Markus Fisch 9742e5b790 Give signing configuration a proper name
"config" isn't a very good name for a configuration.

These is the release configuration, so we should name it accordingly.
2022-02-07 20:38:55 +01:00
Markus Fisch 9c08aa1184 Update build tools 2022-01-27 23:01:57 +01:00
Markus Fisch ce8a5f89cd Remove buildToolsVersion as it's optional now
Since Gradle 3.0, the specification of "buildToolsVersion" in
"app/build.gradle" is optional.
2022-01-27 23:01:57 +01:00
Oğuz ErsenandGitHub 50795afeb4 Update Turkish translation 2022-01-27 23:01:40 +01:00
Markus Fisch b8c941ee62 Make sure to return a String and not null
Cursor.getString(int) may return null so this case needs
to be dealt with.
2022-01-26 16:44:40 +01:00
Markus Fisch 5b1738342d Ignore lint warning about the custom splash screen
Androidx SplashScreen compat library would require minSdk 21,
make the app unnecessarily larger and Android 12 automatically
replaces our custom splash screen anyway, which is exactly what
we want. So there is no reason to complain.

The migration guide says about our kind of splash screen:

> If your existing splash screen is implemented using a custom
> theme that overrides android:windowBackground, the system replaces
> your custom splash screen with a default Android system splash
> screen on Android 12 and higher (which may not be your app’s
> intended experience).

Source:
https://developer.android.com/guide/topics/ui/splash-screen/migrate

This is not only the intended but desired experience for this app.
2022-01-26 11:28:37 +01:00
Markus Fisch 004738440c Check return value of getColumnIndex() before use
To silence the Range lint error.

getColumnIndex() can return -1 which isn't suitable for
Cursor.get[Blob|Long|String]().

IMHO this is a quite useless, maybe even dangerous, lint error.
This kind of error should only happen in development where I
want to break things to see the problem. Now, using a wrong
name or asking for a non-existent column doesn't result in an
exception and is masking the problem.
2022-01-26 11:04:05 +01:00
Markus Fisch a90aee570a Ignore lint warning about ACCESS_COARSE_LOCATION
Android 12 requires apps that request ACCESS_FINE_LOCATION
to also request ACCESS_COARSE_LOCATION. But this app doesn't
request nor requires ACCESS_FINE_LOCATION above SDK 28.

So this is a false positive and we're ignoring it.
Hopefully, this will be fixed in future updates.
2022-01-25 18:38:12 +01:00
Markus Fisch 17f2f88b7f Update to SDK 31 2022-01-25 18:35:47 +01:00
Markus Fisch 071ea1500f Replace fraction string with fraction character
Using dedicated characters makes the text more readable.
2022-01-25 18:33:36 +01:00
Markus Fisch 25b142407b Explicitly set android:exported
As of Android 12, android:exported must be set.
2022-01-25 18:33:22 +01:00
Markus Fisch 848b4bbaa8 Upgrade gradle wrapper 2022-01-18 21:37:24 +01:00
Markus Fisch c2dc8984c1 Update syntax of zxing auxiliary functions 2022-01-18 21:23:09 +01:00
Sergiy StuparandGitHub e37a4d21ea Update Ukrainian translation 2022-01-13 18:41:49 +01:00
MastiggiaandGitHub da2a20ba1f Update the French translation 2021-12-29 22:32:44 +01:00
kwiateuszandGitHub 5fe69e5a3d Update Polish translation
And fix typo in english texts.
2021-12-27 16:19:30 +01:00
solokotandGitHub f50e1dab0a Updated Russian translation 2021-12-25 19:20:44 +01:00
Markus Fisch b165192377 Advance version number to 1.47.0 2021-12-23 20:34:15 +01:00
Markus Fisch c0a4d67cc5 Add new scan type to open data directly in browser
This way Binary Eye can also be used as a front-end to your own
website that deals with the scanned content directly.

This is of course the same as adding a URL for unknown content and
picking it from the dialog. However, this requires two taps and is
therefore more suitable for unusual use.
2021-12-23 18:32:23 +01:00
Markus Fisch ef36a2f7e0 Unify URL encoding with a String extension 2021-12-23 18:26:01 +01:00
Markus Fisch 40b90e0be2 Make hasNonPrintableCharacters() an extension 2021-12-23 17:49:46 +01:00
Markus Fisch 680030e89e Simplify opening URLs in external browser
So we can use `openUrl()` from anywhere now.
2021-12-23 17:49:46 +01:00
Markus Fisch b4fefad54f Improve readability with a traditional null check
Sure, this can be expressed more briefly, but not more comprehensibly.
2021-12-23 17:49:46 +01:00
Markus Fisch f65e942100 Break long expressions
For better comprehensibility. Should've done this a long time ago.
2021-12-23 17:49:46 +01:00
Markus Fisch 95d7a84648 Reset visibility of zoom bar
It needs to be made visible again after making it invisible.

Happens when one of the cameras doesn't support zooming.
2021-12-20 19:57:14 +01:00
Markus Fisch 1e4a0fde7a Make links to permissions references
So PRIVACY can be read in the shell.
2021-12-16 22:44:33 +01:00
Markus Fisch a6785d500e Update changelogs for F-Droid 2021-12-15 21:22:03 +01:00
Markus Fisch d77e464554 Advance version number to 1.46.3 2021-12-15 21:20:49 +01:00
Markus Fisch d7198934d7 Make fragment functions extension functions 2021-12-15 19:05:51 +01:00
Markus Fisch 1a3b3f263f Make bitmap editor functions extensions 2021-12-15 10:30:22 +01:00
Markus Fisch d4c5c6a1dc Fix cropping still images
Can't use Rect.width()/.height() with negative left/top values
because these get cropped at 0/0 of course.

Before this commit, the cropped image was larger than it should be.
2021-12-15 10:27:15 +01:00
Markus Fisch 8618a5b482 Avoid modifying ROI when scanning in PickActivity
detectorView.roi was modified by Rect.intersect() so we
need to make a copy to keep the currently selected ROI.
2021-12-15 10:22:42 +01:00
Markus Fisch 6cb65635e3 Update changelogs for F-Droid 2021-12-14 21:40:30 +01:00
Markus Fisch 5e37ff41d6 Make r/w byte array functions of Scan extensions 2021-12-14 21:37:23 +01:00
Markus Fisch 03ac3ff0e9 Make export and file saving functions extensions 2021-12-14 21:36:28 +01:00
Markus Fisch 480a248e71 Make restart functions extensions 2021-12-14 21:31:01 +01:00
Markus Fisch b4060d70ce Make permission functions extensions too 2021-12-14 21:30:37 +01:00
Markus Fisch 7ceb97e942 Make sharing functions Context extensions
Makes things simpler and more clear.
2021-12-14 21:27:37 +01:00
Markus Fisch 7100f79efc Use explicit CoroutineScope instead of GlobalScope
We shouldn't use GlobalScope directly because it can't be cancelled.
2021-12-14 18:56:23 +01:00
Markus Fisch 00a1ec877b Explicitly trim margin of SQL queries
And clean up helper functions.
2021-12-14 18:55:23 +01:00
Markus Fisch 89e029687b Cancel scanning if rectangles do not overlap
When scanning from an image. In reality, the rectangles will
always overlap but Android Studio can't know that so it's better
to add a safe guard.
2021-12-14 18:53:38 +01:00
Markus Fisch 5f4f18a062 Move zoom slider up and increase spacing around it
And center it with the FAB.

This should improve the usability because the slider should
now be a bit easier to grab. Also, it should interfere less
likely with gesture navigation.
2021-12-14 18:53:17 +01:00
Klaas SwartandMarkus Fisch 69ec2cda04 Update Dutch translation 2021-12-14 18:51:50 +01:00
anenasaandGitHub 4aba885fb6 Update zh-TW translation 2021-12-13 20:30:01 +01:00
Markus Fisch 9dbb78ce67 Advance version number to 1.46.2 2021-12-10 19:52:21 +01:00
Markus Fisch 47c252ab18 Fix requesting write permissions on Q and above
Requesting WRITE_EXTERNAL_STORAGE is only required before Android Q.
2021-12-10 19:45:50 +01:00
Markus Fisch 10e02b3164 Update tools version 2021-12-10 19:45:45 +01:00
Markus Fisch 7e82dbe730 Update changelogs for F-Droid 2021-12-06 19:43:55 +01:00
130 changed files with 2270 additions and 2682 deletions
+71
View File
@@ -1,5 +1,76 @@
# Change Log
## 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
* Add timezone offset in calendar dates
* Recognize colloquial incomplete URLs
* Update ZXing library to latest version
* Update Czech translation
* Update Russian translation
* Update Japanese translation
* Update Hungarian translation
## 1.49.2
* Update design of app icon
* Update pt-br translation
## 1.49.1
* Update Simplified Chinese translation
* Return directly to caller for deep links
* Fix metadata for deep links
## 1.49.0
* Add a setting to quickly enable/disable forwarding
* Stop playing error beep when in silent mode
* Improve enabling/disabling torch mode
* Update to latest ZXing version
* Update German translation
* Update Russian translation
## 1.48.1
* Fix broken detection of binary content
## 1.48.0
* Add a menu item to temporarily scan a certain format only
* Add a monochome launcher icon for Android 13
* Show alpha numeric characters in binary data
* Fix showing binary data label for scans from the history
* Fix handling empty meta strings
* Update Turkish translation
* Update Ukrainian translation
* Update French translation
* Update Polish translation
* Update Russian translation
## 1.47.0
* Add forwarding into external browser
* Fix visibility of zoom slider when switching cameras
## 1.46.3
* Fix cropping still images
* Improve usability of zoom slider
* Update Dutch translation
* Update Chinese translation
## 1.46.2
* Fix saving external files on Android Q and newer
## 1.46.1
* Use cropping limiter settings for image picking too
* Remove extra link on result screen
+14 -7
View File
@@ -7,7 +7,7 @@ hesitate to contact me.
## Permissions
### [ACCESS_FINE_LOCATION](https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION)
### [ACCESS_FINE_LOCATION][ACCESS_FINE_LOCATION]
Required to add a WiFi network from a barcode (usually a QR Code).
@@ -17,23 +17,23 @@ which requires `ACCESS_FINE_LOCATION`.
On Android Q an better, this permission is not requested nor required.
### [CAMERA](https://developer.android.com/reference/android/Manifest.permission#CAMERA)
### [CAMERA][CAMERA]
Required to read a barcode from the camera image.
### [INTERNET](https://developer.android.com/reference/android/Manifest.permission#INTERNET)
### [INTERNET][INTERNET]
Required to send a scanned code to a custom URL you can specify in settings.
### [VIBRATE](https://developer.android.com/reference/android/Manifest.permission#VIBRATE)
### [VIBRATE][VIBRATE]
Required to vibrate on detection.
### [WRITE_EXTERNAL_STORAGE](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE)
### [WRITE_EXTERNAL_STORAGE][WRITE_EXTERNAL_STORAGE]
Required to save generated barcodes as files before Android Q.
### [CHANGE_WIFI_STATE](https://developer.android.com/reference/android/Manifest.permission#CHANGE_WIFI_STATE)
### [CHANGE_WIFI_STATE][CHANGE_WIFI_STATE]
Required to add a WiFi network from a barcode (usually a QR Code).
@@ -41,7 +41,7 @@ On Android Q and better, this feature requires using
[WifiManager.addNetworkSuggestions][addNetworkSuggestions]
which requires `CHANGE_WIFI_STATE`.
### [ACCESS_WIFI_STATE](https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION)
### [ACCESS_WIFI_STATE][ACCESS_FINE_LOCATION]
Required to add a WiFi network from a barcode (usually a QR Code).
@@ -49,5 +49,12 @@ Before Android Q, this feature requires using
[WifiManager.getConfiguredNetworks][configuredNetworks]
which requires `ACCESS_WIFI_STATE`.
[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
[VIBRATE]: https://developer.android.com/reference/android/Manifest.permission#VIBRATE
[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()
[addNetworkSuggestions]: https://developer.android.com/reference/android/net/wifi/WifiManager#addNetworkSuggestions(java.util.List%3Candroid.net.wifi.WifiNetworkSuggestion%3E)
+43 -17
View File
@@ -89,28 +89,51 @@ Supported symbols are:
### SCAN Intent
You can also use Binary Eye from other apps by using the
`com.google.zxing.client.android.SCAN` Intent with `startActivityForResult()`
like this:
`com.google.zxing.client.android.SCAN` Intent with
[startActivityForResult()][start_activity] like this:
startActivityForResult(
Intent("com.google.zxing.client.android.SCAN"),
SOME_NUMBER
)
```kotlin
startActivityForResult(
Intent("com.google.zxing.client.android.SCAN"),
SOME_NUMBER
)
```
And process the result in `onActivityResult()` of your `Activity`:
And process the result in [onActivityResult()][on_activity_result] of your
`Activity`:
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
when (requestCode) {
SOME_NUMBER -> if (resultCode == RESULT_OK) {
val result = data.getStringExtra("SCAN_RESULT")
}
```kotlin
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
when (requestCode) {
SOME_NUMBER -> if (resultCode == RESULT_OK) {
val result = data.getStringExtra("SCAN_RESULT")
}
}
}
```
If you're using AndroidX, this would be the new,
[recommended way][intent_result]:
```kotlin
class YourActivity : Activity() {
private val resultLauncher = registerForActivityResult(StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val scan = result.data?.getStringExtra("SCAN_RESULT")
}
}
fun openScanner() {
resultLauncher.launch(Intent("com.google.zxing.client.android.SCAN"))
}
}
```
## RenderScript
@@ -162,3 +185,6 @@ custom RenderScript kernel for each architecture you want to support.
[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
+21 -12
View File
@@ -2,15 +2,18 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
namespace 'de.markusfisch.android.binaryeye'
compileSdkVersion sdk_version
buildToolsVersion build_tools_version
defaultConfig {
minSdkVersion 9
targetSdkVersion sdk_version
versionCode 88
versionName '1.46.1'
versionCode 100
versionName '1.52.0'
// Required for desugaring.
multiDexEnabled true
// It's recommended to set this value to the lowest API level
// able to provide all the functionality.
@@ -22,7 +25,7 @@ android {
}
signingConfigs {
config {
release {
keyAlias System.getenv('ANDROID_KEY_ALIAS')
keyPassword System.getenv('ANDROID_KEY_PASSWORD')
storePassword System.getenv('ANDROID_STORE_PASSWORD')
@@ -46,7 +49,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.config
signingConfig signingConfigs.release
}
}
@@ -62,7 +65,14 @@ android {
}
}
lintOptions {
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.
@@ -77,17 +87,16 @@ dependencies {
androidTestImplementation('com.android.support.test:rules:1.0.2') {
exclude module: 'support-annotations'
}
testImplementation 'junit:junit:4.12'
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.3.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
implementation "com.android.support:appcompat-v7:$support_version"
implementation "com.android.support:design:$support_version"
implementation "com.android.support:preference-v7:$support_version"
implementation "com.android.support:preference-v14:$support_version"
// Do NOT upgrade ZXing because newer versions won't work on API < 24
// https://github.com/zxing/zxing/issues/1170
implementation 'com.google.zxing:core:3.3.3'
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.0'
}
+10
View File
@@ -9,4 +9,14 @@
<issue id="UnusedResources">
<ignore path="*/res/rs/debug/raw/bc*" />
</issue>
<!-- Android 12 requires apps that request ACCESS_FINE_LOCATION
to also request ACCESS_COARSE_LOCATION. But this app doesn't
request nor requires ACCESS_FINE_LOCATION above SDK 28. So
this is a false positive. -->
<issue id="CoarseFineLocation" severity="ignore"/>
<!-- Androidx SplashScreen compat library would require minSdk 21,
make the app unnecessarily larger and Android 12 automatically
replaces our custom splash screen anyway, which is exactly what
we want. So there is no reason to complain. -->
<issue id="CustomSplashScreen" severity="ignore"/>
</lint>
@@ -16,14 +16,17 @@ import java.util.regex.Pattern
class PreprocessorTest {
@Test
fun processSamples() {
val zxing = Zxing()
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 samples = assets.list("samples")
checkNotNull(samples) { "no samples found" }
val rs = RenderScript.create(
InstrumentationRegistry.getTargetContext(),
)
val zxing = Zxing()
for (sample in samples) {
val m = pattern.matcher(sample)
if (!m.find() || m.groupCount() < 1) {
@@ -36,9 +39,6 @@ class PreprocessorTest {
val frameWidth = bitmap.width
val frameHeight = bitmap.height
val frameOrientation = m.group(1) ?: return
val rs = RenderScript.create(
InstrumentationRegistry.getTargetContext(),
)
val preprocessor = Preprocessor(
rs,
frameWidth,
@@ -59,10 +59,9 @@ class PreprocessorTest {
}
val result = zxing.decode(frameData, outWidth, outHeight)
preprocessor.destroy()
rs.destroy()
checkNotNull(result) { "no barcode found in $sample" }
}
rs.destroy()
}
}
@@ -81,21 +80,21 @@ private fun encodeYUV420SP(argb: IntArray, width: Int, height: Int): ByteArray {
var r: Int
var g: Int
var b: Int
var Y: Int
var y: Int
var u: Int
var v: Int
var index = 0
for (y in 0 until height) {
for (x in 0 until width) {
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
y = (66 * r + 129 * g + 25 * b + 128 shr 8) + 16
u = (-38 * r - 74 * g + 112 * b + 128 shr 8) + 128
v = (112 * r - 94 * g - 18 * b + 128 shr 8) + 128
yuv[yIndex++] = (if (Y < 0) 0 else if (Y > 255) 255 else Y).toByte()
if (y % 2 == 0 && index % 2 == 0) {
yuv[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()
}
@@ -4,35 +4,7 @@
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M32.002,-24.974h3.127v7.656h-3.127z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:pathData="m54.826,27.893c-6.851,0 -13.701,2.581 -18.924,7.745 -10.445,10.328 -10.413,27.062 0,37.423l36.218,36.036 37.879,0.902 -0.07,-38.363 -36.18,-35.998c-5.207,-5.18 -12.073,-7.745 -18.924,-7.745z"
android:strokeAlpha="1"
android:pathData="M54.826,27.894C47.976,27.894 41.125,30.475 35.903,35.639C25.457,45.967 25.489,62.701 35.903,73.062L72.121,109.098L108,108L109.93,71.637L73.75,35.639C68.543,30.459 61.677,27.894 54.826,27.894Z"
android:strokeLineJoin="miter"
android:strokeWidth="8.60725021"
android:fillColor="#000000"
@@ -41,43 +13,25 @@
android:fillAlpha="0.1254902"
android:strokeLineCap="butt"/>
<path
android:pathData="M28.001,54.118a26.525,26.227 0,1 0,53.049 0a26.525,26.227 0,1 0,-53.049 0z"
android:strokeAlpha="1"
android:pathData="M27.475,54a26.525,26.5 0,1 0,53.05 0a26.525,26.5 0,1 0,-53.05 0z"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
<path
android:pathData="M39.26,54.988a14.509,14.346 0,1 0,29.019 0a14.509,14.346 0,1 0,-29.019 0z"
android:strokeAlpha="1"
android:pathData="M72.745,54.001C72.745,58.588 71.099,62.791 68.362,66.049L68.362,41.953C71.099,45.21 72.745,49.412 72.745,54.001ZM54.001,72.745C53.463,72.745 52.931,72.723 52.406,72.679L52.406,35.322C52.931,35.278 53.463,35.255 54.001,35.255C54.538,35.255 55.071,35.278 55.596,35.322L55.596,72.679C55.071,72.723 54.538,72.745 54.001,72.745ZM35.255,54.001C35.255,49.412 36.903,45.21 39.638,41.953L39.638,66.049C36.903,62.791 35.255,58.588 35.255,54.001ZM61.98,70.969C60.961,71.447 59.895,71.838 58.789,72.13L58.789,35.873C59.895,36.164 60.961,36.553 61.98,37.032L61.98,70.969ZM49.213,72.13C46.877,71.514 44.717,70.458 42.831,69.056L42.831,38.945C44.717,37.543 46.877,36.487 49.213,35.873L49.213,72.13Z"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
<path
android:pathData="M54.034,44.513a9.535,9.428 0,1 0,19.07 0a9.535,9.428 0,1 0,-19.07 0z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="10"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:pathData="m62.745,24.783c-2.055,1.011 -2.87,3.415 -1.847,5.446 0.588,1.168 1.642,1.916 2.839,2.168 -0.564,0.884 -0.835,1.972 -0.925,3.156 -1.782,-0.45 -3.735,-0.191 -5.25,0.639a0.799,0.808 90,0 0,-0.132 0.172,0.799 0.808,90 0,0 -0.132,0.172 0.799,0.808 90,0 0,-0.132 0.39,0.799 0.808,90 0,0 0.044,0.304 0.799,0.808 90,0 0,0.437 0.433,0.799 0.808,90 0,0 0.131,0.043 0.799,0.808 90,0 0,0.131 0.043,0.799 0.808,90 0,0 0.218,-0 0.799,0.808 90,0 0,0.263 -0.129c1.29,-0.707 2.97,-0.892 4.375,-0.425 0.096,0.882 0.341,1.782 0.695,2.683 -0.456,0.072 -0.936,0.177 -1.357,0.343 -1.207,0.48 -2.245,1.302 -3.022,2.244a0.799,0.808 90,0 0,-0.044 0.129,0.799 0.808,90 0,0 -0.088,0.258 0.799,0.808 90,0 0,0.044 0.304,0.799 0.808,90 0,0 0.393,0.563 0.799,0.808 90,0 0,0.394 0.131,0.799 0.808,90 0,0 0.175,-0.086 0.799,0.808 90,0 0,0.175 -0.086,0.799 0.808,90 0,0 0.219,-0.215c0.922,-1.115 2.409,-1.925 3.897,-2.025 0.494,0.845 1.016,1.575 1.658,2.209 -1.232,1.149 -2.043,2.664 -2.239,4.234a0.799,0.808 90,0 0,-0.001 0.215,0.799 0.808,90 0,0 0.174,0.346 0.799,0.808 90,0 0,0.043 0.086,0.799 0.808,90 0,0 0.219,0.217 0.799,0.808 90,0 0,0.131 0.043,0.799 0.808,90 0,0 0.131,0.043 0.799,0.808 90,0 0,0.218 -0,0.799 0.808,90 0,0 0.218,-0 0.799,0.808 90,0 0,0.132 -0.172,0.799 0.808,90 0,0 0.175,-0.086 0.799,0.808 90,0 0,0.044 -0.129,0.799 0.808,90 0,0 0.088,-0.258 0.799,0.808 90,0 0,0.044 -0.129c0.159,-1.272 0.816,-2.493 1.799,-3.371 1.966,1.394 4.252,1.797 6.122,0.876 1.892,-0.931 2.903,-3.018 2.941,-5.444 1.327,-0.259 2.813,0.014 3.936,0.656a0.799,0.808 90,0 0,0.174 0.129,0.799 0.808,90 0,0 0.131,0.043 0.799,0.808 90,0 0,0.088 -0.043,0.799 0.808,90 0,0 0.218,-0 0.799,0.808 90,0 0,0.087 -0.043,0.799 0.808,90 0,0 0.175,-0.086 0.799,0.808 90,0 0,0.132 -0.172,0.799 0.808,90 0,0 0.132,-0.172 0.799,0.808 90,0 0,0.045 -0.562,0.799 0.808,90 0,0 -0.043,-0.086 0.799,0.808 90,0 0,-0.262 -0.303,0.799 0.808,90 0,0 -0.131,-0.043c-1.386,-0.792 -3.097,-1.066 -4.766,-0.787 -0.125,-0.89 -0.309,-1.783 -0.695,-2.683 0.982,-1.073 2.47,-1.756 3.896,-1.81a0.799,0.808 90,0 0,0.131 0.043,0.799 0.808,90 0,0 0.087,-0.043 0.799,0.808 90,0 0,0.482 -0.345,0.799 0.808,90 0,0 0.044,-0.129 0.799,0.808 90,0 0,0.088 -0.476,0.799 0.808,90 0,0 -0.043,-0.086 0.799,0.808 90,0 0,-0.262 -0.303,0.799 0.808,90 0,0 -0.043,-0.086 0.799,0.808 90,0 0,-0.394 -0.131,0.799 0.808,90 0,0 -0.131,-0.043c-1.227,0.048 -2.518,0.369 -3.633,1.031 -0.388,0.233 -0.762,0.548 -1.095,0.864 -0.513,-0.821 -1.093,-1.559 -1.746,-2.166 0.47,-1.39 1.632,-2.605 2.98,-3.195a0.799,0.808 90,0 0,0.175 -0.086,0.799 0.808,90 0,0 0.132,-0.172 0.799,0.808 90,0 0,0.132 -0.172,0.799 0.808,90 0,0 0.132,-0.39 0.799,0.808 90,0 0,-0.043 -0.086,0.799 0.808,90 0,0 -0.174,-0.346 0.799,0.808 90,0 0,-0.043 -0.086,0.799 0.808,90 0,0 -0.437,-0.217 0.799,0.808 90,0 0,-0.175 0.086,0.799 0.808,90 0,0 -0.131,-0.043 0.799,0.808 90,0 0,-0.087 0.043,0.799 0.808,90 0,0 -0.131,-0.043c-1.584,0.694 -2.97,2.079 -3.681,3.756 -1.012,-0.644 -2.048,-1.087 -3.104,-1.173 0.53,-1.101 0.642,-2.414 0.05,-3.59 -1.023,-2.031 -3.541,-2.795 -5.596,-1.783z"
android:pathData="m62.745,28.783c-2.055,1.011 -2.87,3.415 -1.847,5.446 0.588,1.168 1.642,1.916 2.839,2.168 -0.564,0.884 -0.835,1.972 -0.925,3.156 -1.782,-0.45 -3.735,-0.191 -5.25,0.639a0.799,0.808 90.001,0 0,-0.132 0.172,0.799 0.808,90.001 0,0 -0.132,0.172 0.799,0.808 90.001,0 0,-0.132 0.39,0.799 0.808,90.001 0,0 0.044,0.304 0.799,0.808 90.001,0 0,0.437 0.433,0.799 0.808,90.001 0,0 0.131,0.043 0.799,0.808 90.001,0 0,0.131 0.043,0.799 0.808,90.001 0,0 0.218,-0 0.799,0.808 90.001,0 0,0.263 -0.129c1.29,-0.707 2.97,-0.892 4.375,-0.425 0.096,0.882 0.341,1.782 0.695,2.683 -0.456,0.072 -0.936,0.177 -1.357,0.343 -1.207,0.48 -2.245,1.302 -3.022,2.244a0.799,0.808 90.001,0 0,-0.044 0.129,0.799 0.808,90.001 0,0 -0.088,0.258 0.799,0.808 90.001,0 0,0.044 0.304,0.799 0.808,90.001 0,0 0.393,0.563 0.799,0.808 90.001,0 0,0.394 0.131,0.799 0.808,90.001 0,0 0.175,-0.086 0.799,0.808 90.001,0 0,0.175 -0.086,0.799 0.808,90.001 0,0 0.219,-0.215c0.922,-1.115 2.409,-1.925 3.897,-2.025 0.494,0.845 1.016,1.575 1.658,2.209 -1.232,1.149 -2.043,2.664 -2.239,4.234a0.799,0.808 90.001,0 0,-0.001 0.215,0.799 0.808,90.001 0,0 0.174,0.346 0.799,0.808 90.001,0 0,0.043 0.086,0.799 0.808,90.001 0,0 0.219,0.217 0.799,0.808 90.001,0 0,0.131 0.043,0.799 0.808,90.001 0,0 0.131,0.043 0.799,0.808 90.001,0 0,0.218 -0,0.799 0.808,90.001 0,0 0.218,-0 0.799,0.808 90.001,0 0,0.132 -0.172,0.799 0.808,90.001 0,0 0.175,-0.086 0.799,0.808 90.001,0 0,0.044 -0.129,0.799 0.808,90.001 0,0 0.088,-0.258 0.799,0.808 90.001,0 0,0.044 -0.129c0.159,-1.272 0.816,-2.493 1.799,-3.371 1.966,1.394 4.252,1.797 6.122,0.876 1.892,-0.931 2.903,-3.018 2.941,-5.444 1.327,-0.259 2.813,0.014 3.936,0.656a0.799,0.808 90.001,0 0,0.174 0.129,0.799 0.808,90.001 0,0 0.131,0.043 0.799,0.808 90.001,0 0,0.088 -0.043,0.799 0.808,90.001 0,0 0.218,-0 0.799,0.808 90.001,0 0,0.087 -0.043,0.799 0.808,90.001 0,0 0.175,-0.086 0.799,0.808 90.001,0 0,0.132 -0.172,0.799 0.808,90.001 0,0 0.132,-0.172 0.799,0.808 90.001,0 0,0.045 -0.562,0.799 0.808,90.001 0,0 -0.043,-0.086 0.799,0.808 90.001,0 0,-0.262 -0.303,0.799 0.808,90.001 0,0 -0.131,-0.043c-1.386,-0.792 -3.097,-1.066 -4.766,-0.787 -0.125,-0.89 -0.309,-1.783 -0.695,-2.683 0.982,-1.073 2.47,-1.756 3.896,-1.81a0.799,0.808 90.001,0 0,0.131 0.043,0.799 0.808,90.001 0,0 0.087,-0.043 0.799,0.808 90.001,0 0,0.482 -0.345,0.799 0.808,90.001 0,0 0.044,-0.129 0.799,0.808 90.001,0 0,0.088 -0.476,0.799 0.808,90.001 0,0 -0.043,-0.086 0.799,0.808 90.001,0 0,-0.262 -0.303,0.799 0.808,90.001 0,0 -0.043,-0.086 0.799,0.808 90.001,0 0,-0.394 -0.131,0.799 0.808,90.001 0,0 -0.131,-0.043c-1.227,0.048 -2.518,0.369 -3.633,1.031 -0.388,0.233 -0.762,0.548 -1.095,0.864 -0.513,-0.821 -1.093,-1.559 -1.746,-2.166 0.47,-1.39 1.632,-2.605 2.98,-3.195a0.799,0.808 90.001,0 0,0.175 -0.086,0.799 0.808,90.001 0,0 0.132,-0.172 0.799,0.808 90.001,0 0,0.132 -0.172,0.799 0.808,90.001 0,0 0.132,-0.39 0.799,0.808 90.001,0 0,-0.043 -0.086,0.799 0.808,90.001 0,0 -0.174,-0.346 0.799,0.808 90.001,0 0,-0.043 -0.086,0.799 0.808,90.001 0,0 -0.437,-0.217 0.799,0.808 90.001,0 0,-0.175 0.086,0.799 0.808,90.001 0,0 -0.131,-0.043 0.799,0.808 90.001,0 0,-0.087 0.043,0.799 0.808,90.001 0,0 -0.131,-0.043c-1.584,0.694 -2.97,2.079 -3.681,3.756 -1.012,-0.644 -2.048,-1.087 -3.104,-1.173 0.53,-1.101 0.642,-2.414 0.05,-3.59 -1.023,-2.031 -3.541,-2.795 -5.596,-1.783z"
android:fillColor="#ff2a2a"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
android:strokeColor="#00000000"/>
<path
android:pathData="m66.624,32.489c0.281,-0.138 1.896,2.465 3.62,5.889 1.724,3.424 2.893,6.354 2.613,6.492 -0.281,0.138 -1.94,-2.551 -3.663,-5.975 -1.724,-3.424 -2.85,-6.268 -2.569,-6.406z"
android:pathData="m66.624,36.489c0.281,-0.138 1.896,2.465 3.62,5.889 1.724,3.424 2.893,6.354 2.613,6.492 -0.281,0.138 -1.94,-2.551 -3.663,-5.975 -1.724,-3.424 -2.85,-6.268 -2.569,-6.406z"
android:fillColor="#d40000"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
android:strokeColor="#00000000"/>
</vector>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+11 -9
View File
@@ -1,6 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="de.markusfisch.android.binaryeye"
android:installLocation="auto">
<supports-screens
android:largeScreens="true"
@@ -34,6 +33,7 @@
android:usesCleartextTraffic="true"
android:allowBackup="true"
android:fullBackupContent="@xml/backup_rules"
android:dataExtractionRules="@xml/extraction_rules"
android:supportsRtl="true"
android:resizeableActivity="true"
android:label="@string/app_name"
@@ -41,8 +41,8 @@
android:theme="@style/AppTheme">
<activity
android:name=".activity.SplashActivity"
android:label="@string/app_name"
android:theme="@style/SplashTheme">
android:theme="@style/SplashTheme"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
@@ -53,7 +53,8 @@
</activity>
<activity
android:name=".activity.CameraActivity"
android:label="@string/scan_code">
android:label="@string/scan_code"
android:exported="true">
<intent-filter android:label="@string/compose_barcode">
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
@@ -67,10 +68,10 @@
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"
android:host="markusfisch.de"
android:pathPrefix="/BinaryEye"/>
<data android:scheme="https" />
<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"/>
@@ -82,6 +83,7 @@
<activity
android:name=".activity.PickActivity"
android:label="@string/pick_code_to_scan"
android:exported="true"
tools:ignore="AppLinkUrlError">
<intent-filter android:label="@string/decode_barcode">
<action android:name="android.intent.action.SEND"/>
@@ -96,12 +98,12 @@
</activity>
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:exported="true"/>
<service
android:name=".service.ScanTileService"
android:icon="@drawable/ic_action_scan"
android:label="@string/scan_code"
android:exported="true"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE"/>
@@ -1,6 +1,7 @@
package de.markusfisch.android.binaryeye.actions
import de.markusfisch.android.binaryeye.actions.mail.MailAction
import de.markusfisch.android.binaryeye.actions.mail.MatMsgAction
import de.markusfisch.android.binaryeye.actions.otpauth.OtpauthAction
import de.markusfisch.android.binaryeye.actions.search.OpenOrSearchAction
import de.markusfisch.android.binaryeye.actions.sms.SmsAction
@@ -15,13 +16,16 @@ object ActionRegistry {
private val REGISTRY: Set<IAction> = setOf(
MailAction,
MatMsgAction,
OtpauthAction,
SmsAction,
TelAction,
VCardAction,
VEventAction,
WebAction,
WifiAction
WifiAction,
// Try WebAction last because recognizing colloquial URLs is
// very aggressive.
WebAction
)
fun getAction(data: ByteArray): IAction = REGISTRY.find {
@@ -2,8 +2,8 @@ package de.markusfisch.android.binaryeye.actions
import android.content.Context
import android.content.Intent
import de.markusfisch.android.binaryeye.app.parseAndNormalizeUri
import de.markusfisch.android.binaryeye.content.execShareIntent
import de.markusfisch.android.binaryeye.content.openUrl
import de.markusfisch.android.binaryeye.widget.toast
interface IAction {
@@ -18,31 +18,36 @@ abstract class IntentAction : IAction {
abstract val errorMsg: Int
final override suspend fun execute(context: Context, data: ByteArray) {
val intent = createIntent(context, data) ?: return context.toast(
errorMsg
)
context.execShareIntent(intent)
val intent = createIntent(context, data)
if (intent == null) {
context.toast(errorMsg)
} else {
context.execShareIntent(intent)
}
}
abstract suspend fun createIntent(context: Context, data: ByteArray): Intent?
abstract suspend fun createIntent(
context: Context,
data: ByteArray
): Intent?
}
abstract class SchemeAction : IAction {
abstract val scheme: String
open val intentAction: String = Intent.ACTION_VIEW
open val buildRegex: Boolean = false
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)
}
}
final override suspend fun execute(context: Context, data: ByteArray) {
val uri = parseAndNormalizeUri(String(data))
context.execShareIntent(Intent(intentAction, uri))
context.openUrl(String(data))
}
}
@@ -0,0 +1,55 @@
package de.markusfisch.android.binaryeye.actions.mail
import android.content.Context
import android.content.Intent
import android.net.Uri
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.actions.IntentAction
object MatMsgAction : IntentAction() {
override val iconResId: Int = R.drawable.ic_action_mail
override val titleResId: Int = R.string.mail_send
override val errorMsg: Int = R.string.mail_error
override fun canExecuteOn(data: ByteArray): Boolean {
return String(data).startsWith("MATMSG:")
}
override suspend fun createIntent(
context: Context,
data: ByteArray
): Intent? {
val mm = MatMsg(String(data))
// Allow incomplete but not completely missing data.
if (mm.isEmpty()) {
return null
}
return Intent(
Intent.ACTION_SENDTO,
Uri.parse("mailto:")
).apply {
mm.to?.let {
putExtra(Intent.EXTRA_EMAIL, arrayOf(mm.to))
}
mm.sub?.let {
putExtra(Intent.EXTRA_SUBJECT, mm.sub)
}
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)
@@ -1,14 +1,12 @@
package de.markusfisch.android.binaryeye.actions.search
import android.content.Context
import android.content.Intent
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.parseAndNormalizeUri
import de.markusfisch.android.binaryeye.app.urlEncode
import de.markusfisch.android.binaryeye.app.prefs
import de.markusfisch.android.binaryeye.content.startIntent
import java.net.URLEncoder
import de.markusfisch.android.binaryeye.content.openUrl
object OpenOrSearchAction : IAction {
override val iconResId: Int = R.drawable.ic_action_search
@@ -20,10 +18,13 @@ object OpenOrSearchAction : IAction {
view(context, String(data), true)
}
private suspend fun view(context: Context, s: String, search: Boolean) {
val intent = Intent(Intent.ACTION_VIEW, parseAndNormalizeUri(s))
if (!context.startIntent(intent) && search) {
openSearch(context, s)
private suspend fun view(
context: Context,
url: String,
search: Boolean
) {
if (!context.openUrl(url) && search) {
openSearch(context, url)
}
}
@@ -32,7 +33,7 @@ object OpenOrSearchAction : IAction {
if (defaultSearchUrl.isNotEmpty()) {
view(
context,
defaultSearchUrl + URLEncoder.encode(query, "utf-8"),
defaultSearchUrl + query.urlEncode(),
false
)
return
@@ -54,7 +55,7 @@ object OpenOrSearchAction : IAction {
val queryUri = alertDialog<String>(context) { resume ->
setTitle(R.string.pick_search_engine)
setItems(names.toTypedArray()) { _, which ->
resume(urls[which] + URLEncoder.encode(query, "utf-8"))
resume(urls[which] + query.urlEncode())
}
} ?: return
view(context, queryUri, false)
@@ -7,8 +7,9 @@ import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.actions.IntentAction
object SmsAction : IntentAction() {
private val smsRegex =
"""^sms(?:to)?:(\+?[0-9]+)(?::([\S\s]*))?$""".toRegex(RegexOption.IGNORE_CASE)
private val smsRegex = """^sms(?:to)?:(\+?[0-9]+)(?::([\S\s]*))?$""".toRegex(
RegexOption.IGNORE_CASE
)
override val iconResId: Int = R.drawable.ic_action_sms
override val titleResId: Int = R.string.sms_send
@@ -28,7 +29,9 @@ object SmsAction : IntentAction() {
Intent.ACTION_SENDTO,
Uri.parse("smsto:$number")
).apply {
if (message.isNotEmpty()) putExtra("sms_body", message)
if (message.isNotEmpty()) {
putExtra("sms_body", message)
}
}
}
}
@@ -7,7 +7,9 @@ import de.markusfisch.android.binaryeye.actions.IntentAction
import de.markusfisch.android.binaryeye.app.parseAndNormalizeUri
object TelAction : IntentAction() {
private val telRegex = """^tel:(\+?[0-9]+)$""".toRegex(RegexOption.IGNORE_CASE)
private val telRegex = """^tel:(\+?[0-9]+)$""".toRegex(
RegexOption.IGNORE_CASE
)
override val iconResId: Int = R.drawable.ic_action_tel
override val titleResId: Int = R.string.tel_dial
@@ -17,7 +19,11 @@ object TelAction : IntentAction() {
return String(data).matches(telRegex)
}
override suspend fun createIntent(context: Context, data: ByteArray): Intent {
return Intent(Intent.ACTION_DIAL, parseAndNormalizeUri(String(data)))
}
override suspend fun createIntent(
context: Context,
data: ByteArray
): Intent = Intent(
Intent.ACTION_DIAL,
String(data).parseAndNormalizeUri()
)
}
@@ -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
@@ -45,38 +44,49 @@ object VEventAction : IntentAction() {
}
info["DTSTART"]?.singleOrNull()?.also { eventStart ->
dateFormats.simpleFindParse(eventStart.value)?.also {
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, it.time)
putExtra(
CalendarContract.EXTRA_EVENT_BEGIN_TIME,
it.time
)
}
}
info["DTEND"]?.singleOrNull()?.also { eventEnd ->
dateFormats.simpleFindParse(eventEnd.value)?.also {
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, it.time)
putExtra(
CalendarContract.EXTRA_EVENT_END_TIME,
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 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
}
@@ -1,11 +1,27 @@
package de.markusfisch.android.binaryeye.actions.web
import android.content.Context
import de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.actions.SchemeAction
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
)
object WebAction : SchemeAction() {
override val iconResId: Int = R.drawable.ic_action_open
override val titleResId: Int = R.string.open_url
override val scheme: String = "https?"
override val buildRegex: Boolean = true
override fun canExecuteOn(data: ByteArray): Boolean {
return String(data).trim().matches(colloquialRegex)
}
override suspend fun execute(context: Context, data: ByteArray) {
var url = String(data).trim()
if (!url.startsWith("http") && !url.startsWith("ftp")) {
url = "http://${url}"
}
context.openUrl(url)
}
}
@@ -1,6 +1,7 @@
package de.markusfisch.android.binaryeye.activity
import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@@ -26,14 +27,17 @@ 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.database.Scan
import de.markusfisch.android.binaryeye.content.openUrl
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.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.view.initSystemBars
@@ -42,7 +46,6 @@ 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 java.net.URLEncoder
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
@@ -74,12 +77,13 @@ class CameraActivity : AppCompatActivity() {
private var recreatePreprocessor = false
private var rotate = false
private var invert = false
private var flash = false
private var decoding = true
private var returnResult = false
private var returnUrlTemplate: String? = null
private var finishAfterShowingResult = false
private var frontFacing = false
private var bulkMode = prefs.bulkMode
private var restrictFormat: String? = null
private var ignoreNext: String? = null
private var fallbackBuffer: IntArray? = null
@@ -129,7 +133,7 @@ class CameraActivity : AppCompatActivity() {
setTitle(R.string.scan_code)
rs = RenderScript.create(this)
vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator = getVibrator()
initSystemBars(this)
setSupportActionBar(findViewById(R.id.toolbar) as Toolbar)
@@ -162,28 +166,41 @@ class CameraActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
System.gc()
zxing.updateHints(
prefs.tryHarder,
prefs.barcodeFormats
)
updateHints()
if (prefs.bulkMode && bulkMode != prefs.bulkMode) {
bulkMode = prefs.bulkMode
invalidateOptionsMenu()
ignoreNext = null
}
setReturnTarget(intent)
if (hasCameraPermission(this)) {
if (hasCameraPermission()) {
openCamera()
}
}
private fun updateHints() {
val restriction = restrictFormat
val formats = if (restriction != null) {
title = getString(
R.string.scan_format,
prettifyFormatName(restriction)
)
setOf(restriction)
} else {
setTitle(R.string.scan_code)
prefs.barcodeFormats
}
zxing.updateHints(prefs.tryHarder, formats)
}
private fun setReturnTarget(intent: Intent?) {
when {
intent?.action == "com.google.zxing.client.android.SCAN" -> {
returnResult = true
}
isReturnUrl(intent) -> intent?.data?.let {
returnUrlTemplate = it.getQueryParameter("ret")
intent?.dataString?.isReturnUrl() == true -> {
finishAfterShowingResult = true
returnUrlTemplate = intent.data?.getQueryParameter("ret")
}
}
}
@@ -213,8 +230,6 @@ class CameraActivity : AppCompatActivity() {
private fun closeCamera() {
cameraView.close()
// Closing the camera will also shut off the flash.
flash = false
}
override fun onRestoreInstanceState(savedState: Bundle) {
@@ -223,6 +238,7 @@ class CameraActivity : AppCompatActivity() {
zoomBar.progress = savedState.getInt(ZOOM_LEVEL)
frontFacing = savedState.getBoolean(FRONT_FACING)
bulkMode = savedState.getBoolean(BULK_MODE)
restrictFormat = savedState.getString(RESTRICT_FORMAT)
}
override fun onSaveInstanceState(outState: Bundle) {
@@ -230,6 +246,7 @@ class CameraActivity : AppCompatActivity() {
outState.putInt(ZOOM_LEVEL, zoomBar.progress)
outState.putBoolean(FRONT_FACING, frontFacing)
outState.putBoolean(BULK_MODE, bulkMode)
outState.putString(RESTRICT_FORMAT, restrictFormat)
super.onSaveInstanceState(outState)
}
@@ -259,11 +276,11 @@ class CameraActivity : AppCompatActivity() {
true
}
R.id.pick_file -> {
val chooseFile = Intent(Intent.ACTION_GET_CONTENT)
chooseFile.type = "image/*"
startActivityForResult(
Intent.createChooser(
chooseFile,
Intent(Intent.ACTION_GET_CONTENT).apply {
type = "image/*"
},
getString(R.string.pick_file)
),
PICK_FILE_RESULT_CODE
@@ -280,6 +297,10 @@ class CameraActivity : AppCompatActivity() {
ignoreNext = null
true
}
R.id.restrict_format -> {
showRestrictionDialog()
true
}
R.id.preferences -> {
startActivity(MainActivity.getPreferencesIntent(this))
true
@@ -302,6 +323,27 @@ class CameraActivity : AppCompatActivity() {
openCamera()
}
private fun showRestrictionDialog() {
val names = resources.getStringArray(
R.array.barcode_formats_names
).toMutableList()
val formats = resources.getStringArray(
R.array.barcode_formats_values
).toMutableList()
if (restrictFormat != null) {
names.add(0, getString(R.string.remove_restriction))
formats.add(0, null)
}
AlertDialog.Builder(this).apply {
setTitle(R.string.restrict_format)
setItems(names.toTypedArray()) { _, which ->
restrictFormat = formats[which]
updateHints()
}
show()
}
}
private fun openReadme() {
val intent = Intent(
Intent.ACTION_VIEW,
@@ -368,7 +410,7 @@ class CameraActivity : AppCompatActivity() {
override fun onConfigureParameters(
parameters: Camera.Parameters
) {
if (parameters.isZoomSupported) {
zoomBar.visibility = if (parameters.isZoomSupported) {
val max = parameters.maxZoom
if (zoomBar.max != max) {
zoomBar.max = max
@@ -376,8 +418,9 @@ class CameraActivity : AppCompatActivity() {
saveZoom()
}
parameters.zoom = zoomBar.progress
View.VISIBLE
} else {
zoomBar.visibility = View.GONE
View.GONE
}
val sceneModes = parameters.supportedSceneModes
sceneModes?.let {
@@ -441,7 +484,7 @@ class CameraActivity : AppCompatActivity() {
progress: Int,
fromUser: Boolean
) {
setZoom(progress)
cameraView.camera?.setZoom(progress)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
@@ -452,16 +495,13 @@ class CameraActivity : AppCompatActivity() {
}
@Suppress("DEPRECATION")
private fun setZoom(zoom: Int) {
val camera: Camera? = cameraView.camera
camera?.let {
try {
val params = camera.parameters
params.zoom = zoom
camera.parameters = params
} catch (e: RuntimeException) {
// Ignore. There's nothing we can do.
}
private fun Camera.setZoom(zoom: Int) {
try {
val params = parameters
params.zoom = zoom
parameters = params
} catch (e: RuntimeException) {
// Ignore. There's nothing we can do.
}
}
@@ -504,20 +544,19 @@ class CameraActivity : AppCompatActivity() {
@Suppress("DEPRECATION")
private fun toggleTorchMode() {
val camera = cameraView.camera
val parameters = camera?.parameters
parameters?.flashMode = if (flash) {
val camera = cameraView.camera ?: return
val parameters = camera.parameters ?: return
parameters.flashMode = if (
parameters.flashMode != Camera.Parameters.FLASH_MODE_OFF
) {
Camera.Parameters.FLASH_MODE_OFF
} else {
Camera.Parameters.FLASH_MODE_TORCH
}
parameters?.let {
try {
camera.parameters = parameters
flash = flash xor true
} catch (e: RuntimeException) {
// Ignore. There's nothing we can do.
}
try {
camera.parameters = parameters
} catch (e: RuntimeException) {
toast(e.message ?: getString(R.string.error_flash))
}
}
@@ -563,7 +602,7 @@ class CameraActivity : AppCompatActivity() {
// Now the only option is to restart the app because
// RenderScript.forceCompat() needs to be called before
// RenderScript is initialized.
restartApp(this)
restartApp()
null
}
}
@@ -695,12 +734,20 @@ class CameraActivity : AppCompatActivity() {
returnUri != null -> execShareIntent(
Intent(Intent.ACTION_VIEW, returnUri)
)
else -> showResult(
this@CameraActivity,
result,
vibrator,
bulkMode
)
else -> {
showResult(
this@CameraActivity,
result,
vibrator,
bulkMode
)
// If this app was invoked via a deep link but without
// a return URI, we probably don't want to return to
// the camera screen after scanning, but to the caller.
if (finishAfterShowingResult) {
finish()
}
}
}
if (bulkMode) {
ignoreNext = result.text
@@ -726,6 +773,7 @@ class CameraActivity : AppCompatActivity() {
private const val ZOOM_LEVEL = "zoom_level"
private const val FRONT_FACING = "front_facing"
private const val BULK_MODE = "bulk_mode"
private const val RESTRICT_FORMAT = "restrict_format"
}
}
@@ -738,15 +786,26 @@ fun showResult(
if (prefs.copyImmediately) {
activity.copyToClipboard(result.text)
}
val scan = Scan(result)
if (prefs.sendScanUrl.isNotEmpty()) {
val scan = result.toScan()
if (prefs.useHistory) {
scan.id = db.insertScan(scan)
}
if (prefs.sendScanActive && prefs.sendScanUrl.isNotEmpty()) {
if (prefs.sendScanType == "4") {
activity.openUrl(
prefs.sendScanUrl + scan.content.urlEncode()
)
return
}
scan.sendAsync(
prefs.sendScanUrl,
prefs.sendScanType
) { code, body ->
if (code == null || code < 200 || code > 299) {
vibrator.error()
beepBeepBeep()
if (!activity.isSilent()) {
beepBeepBeep()
}
}
if (body != null && body.isNotEmpty()) {
activity.toast(body)
@@ -755,9 +814,6 @@ fun showResult(
}
}
}
if (prefs.useHistory) {
scan.id = db.insertScan(scan)
}
if (!bulkMode) {
activity.startActivity(
MainActivity.getDecodeIntent(activity, scan)
@@ -776,7 +832,7 @@ fun getReturnIntent(result: Result): Intent {
intent.putExtra("SCAN_RESULT_BYTES", result.rawBytes)
}
result.resultMetadata?.let { metadata ->
metadata[ResultMetadataType.UPC_EAN_EXTENSION]?.let {
metadata[ResultMetadataType.ORIENTATION]?.let {
intent.putExtra(
"SCAN_RESULT_ORIENTATION",
it.toString()
@@ -806,36 +862,35 @@ fun getReturnIntent(result: Result): Intent {
return intent
}
private fun isReturnUrl(intent: Intent?): Boolean {
val dataString = intent?.dataString
return listOf(
"binaryeye://scan",
"http://markusfisch.de/BinaryEye",
"https://markusfisch.de/BinaryEye"
).firstOrNull {
val result = dataString?.startsWith(it) == true
result
} != null
}
private fun String.isReturnUrl() = listOf(
"binaryeye://scan",
"http://markusfisch.de/BinaryEye",
"https://markusfisch.de/BinaryEye"
).firstOrNull { startsWith(it) } != null
private fun completeUrl(urlTemplate: String, result: Result) = Uri.parse(
urlTemplate
.replace("{RESULT}", URLEncoder.encode(result.text, "UTF-8"))
.replace("{RESULT}", result.text.urlEncode())
.replace("{RESULT_BYTES}", result.rawBytes?.toHexString() ?: "")
.replace(
"{FORMAT}", URLEncoder.encode(
result.barcodeFormat.toString(), "UTF-8"
)
"{FORMAT}", result.barcodeFormat.toString().urlEncode()
)
.replace(
"{META}", URLEncoder.encode(
result.resultMetadata?.toString() ?: "", "UTF-8"
)
"{META}", result.resultMetadata?.toString()?.urlEncode() ?: ""
)
// And support {CODE} from the old ZXing app, too.
.replace("{CODE}", URLEncoder.encode(result.text, "UTF-8"))
.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,
@@ -65,7 +65,7 @@ class MainActivity : AppCompatActivity() {
}
if (state == null) {
setFragment(supportFragmentManager, getFragmentForIntent(intent))
supportFragmentManager?.setFragment(getFragmentForIntent(intent))
}
}
@@ -16,10 +16,12 @@ 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.*
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.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
@@ -30,13 +32,13 @@ 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 kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import de.markusfisch.android.scalingimageview.widget.ScalingImageView
import kotlinx.coroutines.*
class PickActivity : AppCompatActivity() {
private val zxing = Zxing()
private val parentJob = Job()
private val scope = CoroutineScope(Dispatchers.IO + parentJob)
private lateinit var rs: RenderScript
private lateinit var vibrator: Vibrator
@@ -63,7 +65,7 @@ class PickActivity : AppCompatActivity() {
prefs.barcodeFormats
)
rs = RenderScript.create(this)
vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator = getVibrator()
initSystemBars(this)
val toolbar = findViewById(R.id.toolbar) as Toolbar
@@ -83,6 +85,7 @@ class PickActivity : AppCompatActivity() {
cropImageView = findViewById(R.id.image) as CropImageView
cropImageView.restrictTranslation = false
cropImageView.freeRotation = true
cropImageView.setImageBitmap(bitmap)
cropImageView.onScan = {
scanWithinBounds(bitmap)
@@ -115,7 +118,7 @@ class PickActivity : AppCompatActivity() {
}
private fun scanWithinBounds(bitmap: Bitmap) {
val roi = detectorView.roi
val roi = Rect(detectorView.roi)
val rectInView = if (roi.width() < 1) {
cropImageView.getBoundsRect()
} else {
@@ -123,12 +126,13 @@ class PickActivity : AppCompatActivity() {
}
val imageRect = cropImageView.mappedRect
val rectInImage = normalizeRoi(imageRect, rectInView)
val cropped = crop(
bitmap,
val cropped = bitmap.crop(
rectInImage,
cropImageView.imageRotation
cropImageView.imageRotation,
cropImageView.pivotX,
cropImageView.pivotY
) ?: return
CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
scope.launch {
result = zxing.decodePositiveNegative(cropped)
result?.let {
withContext(Dispatchers.Main) {
@@ -138,7 +142,9 @@ class PickActivity : AppCompatActivity() {
vibrator.vibrate()
val rc = Rect()
imageRect.round(rc)
rectInView.intersect(rc)
if (!rectInView.intersect(rc)) {
return@withContext
}
detectorView.update(
mapResultToView(
cropped.width,
@@ -158,6 +164,7 @@ class PickActivity : AppCompatActivity() {
super.onDestroy()
detectorView.saveCropHandlePos()
rs.destroy()
parentJob.cancel()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -183,12 +190,12 @@ class PickActivity : AppCompatActivity() {
val uri = intent.getParcelableExtra<Parcelable>(
Intent.EXTRA_STREAM
) as? Uri ?: return null
return loadImageUri(contentResolver, uri)
return contentResolver.loadImageUri(uri)
}
private fun loadImageToOpen(intent: Intent): Bitmap? {
val uri = intent.data ?: return null
return loadImageUri(contentResolver, uri)
return contentResolver.loadImageUri(uri)
}
private fun showResult() {
@@ -13,7 +13,7 @@ class SplashActivity : AppCompatActivity() {
// because that would happen after the app is fully
// initialized what is too late.
setRestartCount(intent)
intent?.setRestartCount()
startActivity(Intent(applicationContext, CameraActivity::class.java))
finish()
}
@@ -58,23 +58,26 @@ class ScansAdapter(context: Context, cursor: Cursor) :
context: Context,
cursor: Cursor
) {
val holder = getViewHolder(view)
holder.timeView.text = formatDateTime(cursor.getString(timeIndex))
val name = cursor.getString(nameIndex)
val content = cursor.getString(contentIndex)
var icon = 0
holder.contentView.text = when {
name?.isNotEmpty() == true -> {
icon = R.drawable.ic_label
name
getViewHolder(view).apply {
timeView.text = formatDateTime(cursor.getString(timeIndex))
val name = cursor.getString(nameIndex)
val content = cursor.getString(contentIndex)
var icon = 0
contentView.text = when {
name?.isNotEmpty() == true -> {
icon = R.drawable.ic_label
name
}
content?.isEmpty() == true -> context.getString(
R.string.binary_data
)
else -> content
}
content?.isEmpty() == true -> context.getString(R.string.binary_data)
else -> content
contentView.setCompoundDrawablesWithIntrinsicBounds(
icon, 0, 0, 0
)
formatView.text = prettifyFormatName(cursor.getString(formatIndex))
}
holder.contentView.setCompoundDrawablesWithIntrinsicBounds(
icon, 0, 0, 0
)
holder.formatView.text = prettifyFormatName(cursor.getString(formatIndex))
// view.isSelected needs to be put on the queue to work.
val selected = cursor.getLong(idIndex) == selectedScanId
view.post {
@@ -82,14 +85,14 @@ class ScansAdapter(context: Context, cursor: Cursor) :
}
}
private fun getViewHolder(view: View): ViewHolder {
return view.tag as ViewHolder? ?: ViewHolder(
view.findViewById(R.id.time),
view.findViewById(R.id.content),
view.findViewById(R.id.format)
).also {
view.tag = it
}
private fun getViewHolder(
view: View
): ViewHolder = view.tag as ViewHolder? ?: ViewHolder(
view.findViewById(R.id.time),
view.findViewById(R.id.content),
view.findViewById(R.id.format)
).also {
view.tag = it
}
private data class ViewHolder(
@@ -1,7 +1,7 @@
package de.markusfisch.android.binaryeye.app
import android.content.Context
import android.support.v7.app.AlertDialog
import android.app.AlertDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlin.coroutines.resume
@@ -1,6 +1,6 @@
package de.markusfisch.android.binaryeye.app
import android.app.Application
import android.support.multidex.MultiDexApplication;
import android.support.v8.renderscript.RenderScript
import de.markusfisch.android.binaryeye.database.Database
import de.markusfisch.android.binaryeye.preference.Preferences
@@ -8,7 +8,7 @@ import de.markusfisch.android.binaryeye.preference.Preferences
val db = Database()
val prefs = Preferences()
class BinaryEyeApp : Application() {
class BinaryEyeApp : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
db.open(this)
@@ -2,13 +2,29 @@ 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)
fun hasNonPrintableCharacters(s: String) = nonPrintable.containsMatchIn(s)
private val nonAlNum = "[^a-zA-Z0-9]".toRegex()
private val multipleDots = "[…]+".toRegex()
fun String.foldNonAlNum() = replace(nonAlNum, "")
.replace(multipleDots, "")
fun parseAndNormalizeUri(input: String): Uri = Uri.parse(input).let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) it.normalizeScheme() else it
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) }
@@ -5,16 +5,15 @@ import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import de.markusfisch.android.binaryeye.R
fun setFragment(fm: FragmentManager?, fragment: Fragment) {
fm?.let { getTransaction(fm, fragment).commit() }
fun FragmentManager.setFragment(fragment: Fragment) {
getTransaction(fragment).commit()
}
fun addFragment(fm: FragmentManager?, fragment: Fragment) {
fm?.let { getTransaction(fm, fragment).addToBackStack(null).commit() }
fun FragmentManager.addFragment(fragment: Fragment) {
getTransaction(fragment).addToBackStack(null).commit()
}
@SuppressLint("CommitTransaction")
private fun getTransaction(
fm: FragmentManager,
private fun FragmentManager.getTransaction(
fragment: Fragment
) = fm.beginTransaction().replace(R.id.content_frame, fragment)
) = beginTransaction().replace(R.id.content_frame, fragment)
@@ -1,29 +0,0 @@
package de.markusfisch.android.binaryeye.app
import java.util.regex.Pattern
private val urlPattern: Pattern = Pattern.compile(
"(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)" +
"(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*" +
"[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
Pattern.CASE_INSENSITIVE or Pattern.MULTILINE or Pattern.DOTALL
)
fun getLinks(text: String): List<String> {
val matcher = urlPattern.matcher(text)
val urls = mutableListOf<String>()
while (matcher.find()) {
val matchStart = matcher.start(1)
val matchEnd = matcher.end()
var url = text.substring(matchStart, matchEnd)
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = "https://$url"
}
urls.add(url)
}
return urls
}
@@ -9,43 +9,39 @@ import android.support.v4.content.ContextCompat
var permissionGrantedCallback: (() -> Any)? = null
const val PERMISSION_CAMERA = 1
fun hasCameraPermission(activity: Activity) = hasPermission(
activity,
fun Activity.hasCameraPermission() = hasPermission(
Manifest.permission.CAMERA,
PERMISSION_CAMERA
)
const val PERMISSION_WRITE = 2
fun hasWritePermission(activity: Activity, callback: () -> Any): Boolean {
fun Activity.hasWritePermission(callback: () -> Any): Boolean {
permissionGrantedCallback = callback
return hasPermission(
activity,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
PERMISSION_WRITE
)
}
const val PERMISSION_LOCATION = 3
fun hasLocationPermission(activity: Activity, callback: () -> Any): Boolean {
fun Activity.hasLocationPermission(callback: () -> Any): Boolean {
permissionGrantedCallback = callback
return hasPermission(
activity,
Manifest.permission.ACCESS_FINE_LOCATION,
PERMISSION_LOCATION
)
}
private fun hasPermission(
activity: Activity,
private fun Activity.hasPermission(
permission: String,
requestCode: Int
) = if (ContextCompat.checkSelfPermission(
activity,
this,
permission
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
activity,
this,
arrayOf(permission),
requestCode
)
@@ -8,19 +8,17 @@ private const val RESTART_COUNT = "restart_count"
private var restartCount = 0
fun setRestartCount(intent: Intent?) {
intent?.let {
restartCount = intent.getIntExtra(RESTART_COUNT, restartCount)
}
fun Intent.setRestartCount() {
restartCount = getIntExtra(RESTART_COUNT, restartCount)
}
fun restartApp(activity: Activity? = null) {
if (activity != null && restartCount < 3) {
val intent = Intent(activity, SplashActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra(RESTART_COUNT, ++restartCount)
activity.startActivity(intent)
activity.finish()
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)
}
@@ -8,16 +8,20 @@ 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
fun Context.execShareIntent(intent: Intent) {
if (!startIntent(intent)) {
toast(R.string.cannot_resolve_action)
}
fun Context.execShareIntent(intent: Intent): Boolean = if (
!startIntent(intent)
) {
toast(R.string.cannot_resolve_action)
false
} else {
true
}
fun Context.startIntent(intent: Intent) = try {
fun Context.startIntent(intent: Intent): Boolean = try {
// Avoid using `intent.resolveActivity()` at API level 30+ due
// to the new package visibility restrictions. In order for
// `resolveActivity()` to "see" another package, we would need
@@ -32,35 +36,41 @@ fun Context.startIntent(intent: Intent) = try {
false
}
fun shareText(context: Context, text: String, type: String = "text/plain") {
val intent = Intent(Intent.ACTION_SEND)
intent.putExtra(Intent.EXTRA_TEXT, text)
intent.type = type
context.execShareIntent(intent)
fun Context.openUrl(url: String): Boolean = openUri(url.parseAndNormalizeUri())
fun Context.openUri(uri: Uri): Boolean = execShareIntent(
Intent(Intent.ACTION_VIEW, uri)
)
fun Context.shareText(text: String, mimeType: String = "text/plain") {
execShareIntent(Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_TEXT, text)
type = mimeType
})
}
fun shareUri(context: Context, uri: Uri, type: String) {
val intent = Intent(Intent.ACTION_SEND)
intent.putExtra(Intent.EXTRA_STREAM, uri)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.type = type
context.execShareIntent(intent)
}
fun shareFile(context: Context, file: File, type: String) {
getUriForFile(context, file)?.let {
shareUri(context, it, type)
fun Context.shareFile(file: File, mimeType: String) {
getUriForFile(file)?.let {
shareUri(it, mimeType)
}
}
fun getUriForFile(context: Context, file: File): Uri? {
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
Uri.fromFile(file)
} else {
FileProvider.getUriForFile(
context,
BuildConfig.APPLICATION_ID + ".provider",
file
)
}
private fun Context.getUriForFile(file: File): Uri? = if (
Build.VERSION.SDK_INT < Build.VERSION_CODES.N
) {
Uri.fromFile(file)
} else {
FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID + ".provider",
file
)
}
private fun Context.shareUri(uri: Uri, mimeType: String) {
execShareIntent(Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, uri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
type = mimeType
})
}
@@ -7,18 +7,17 @@ import de.markusfisch.android.binaryeye.io.writeExternalFile
import java.io.ByteArrayOutputStream
import java.io.OutputStream
fun exportCsv(
context: Context,
fun Context.exportCsv(
name: String,
cursor: Cursor,
delimiter: String
) = writeExternalFile(context, name, "text/csv") { outputStream ->
) = writeExternalFile(name, "text/csv") { outputStream ->
exportCsv(outputStream, cursor, delimiter)
}
fun exportCsv(cursor: Cursor, delimiter: String): String {
fun Cursor.exportCsv(delimiter: String): String {
val outputStream = ByteArrayOutputStream()
exportCsv(outputStream, cursor, delimiter)
exportCsv(outputStream, this, delimiter)
return outputStream.toString()
}
@@ -0,0 +1,18 @@
package de.markusfisch.android.binaryeye.database
import android.database.Cursor
fun Cursor.getString(name: String): String {
val idx = getColumnIndex(name)
return if (idx < 0) "" else getString(idx) ?: ""
}
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)
}
@@ -5,7 +5,6 @@ import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import de.markusfisch.android.binaryeye.app.hasNonPrintableCharacters
import de.markusfisch.android.binaryeye.app.prefs
class Database {
@@ -25,7 +24,7 @@ class Database {
FROM $SCANS
${getWhereClause(query)}
ORDER BY $SCANS_DATETIME DESC
""", getWhereArguments(query)
""".trimMargin(), getWhereArguments(query)
)
fun getScansDetailed(query: String? = null): Cursor? = db.rawQuery(
@@ -47,7 +46,7 @@ class Database {
FROM $SCANS
${getWhereClause(query)}
ORDER BY $SCANS_DATETIME DESC
""", getWhereArguments(query)
""".trimMargin(), getWhereArguments(query)
)
private fun getWhereClause(
@@ -87,7 +86,7 @@ class Database {
$SCANS_UPC_EAN_EXTENSION
FROM $SCANS
WHERE $SCANS_ID = ?
""", arrayOf("$id")
""".trimMargin(), arrayOf("$id")
)?.use {
if (it.moveToFirst()) {
Scan(
@@ -110,47 +109,48 @@ class Database {
}
}
fun insertScan(scan: Scan): Long {
val cv = ContentValues()
cv.put(SCANS_DATETIME, scan.timestamp)
val isRaw = hasNonPrintableCharacters(scan.content)
if (isRaw) {
cv.put(SCANS_CONTENT, "")
cv.put(SCANS_RAW, scan.raw ?: scan.content.toByteArray())
} else {
cv.put(SCANS_CONTENT, scan.content)
}
cv.put(SCANS_FORMAT, scan.format)
scan.errorCorrectionLevel?.let {
cv.put(SCANS_ERROR_CORRECTION_LEVEL, it)
}
scan.issueNumber?.let { cv.put(SCANS_ISSUE_NUMBER, it) }
scan.orientation?.let { cv.put(SCANS_ORIENTATION, it) }
scan.otherMetaData?.let { cv.put(SCANS_OTHER_META_DATA, it) }
scan.pdf417ExtraMetaData?.let { cv.put(SCANS_PDF417_EXTRA_METADATA, it) }
scan.possibleCountry?.let { cv.put(SCANS_POSSIBLE_COUNTRY, it) }
scan.suggestedPrice?.let { cv.put(SCANS_SUGGESTED_PRICE, it) }
scan.upcEanExtension?.let { cv.put(SCANS_UPC_EAN_EXTENSION, it) }
if (prefs.ignoreConsecutiveDuplicates) {
val id = getIdOfLastScan(
cv.get(SCANS_CONTENT) as String,
if (isRaw) cv.get(SCANS_RAW) as ByteArray else null,
scan.format
)
if (id > 0L) {
return id
fun insertScan(scan: Scan): Long = db.insert(
SCANS,
null,
ContentValues().apply {
put(SCANS_DATETIME, scan.dateTime)
val isRaw = scan.raw != null
if (isRaw) {
put(SCANS_CONTENT, "")
put(SCANS_RAW, scan.raw)
} else {
put(SCANS_CONTENT, scan.content)
}
put(SCANS_FORMAT, scan.format)
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) }
if (prefs.ignoreConsecutiveDuplicates) {
val id = getIdOfLastScan(
get(SCANS_CONTENT) as String,
if (isRaw) get(SCANS_RAW) as ByteArray else null,
scan.format
)
if (id > 0L) {
return id
}
}
}
return db.insert(SCANS, null, cv)
}
)
private fun getIdOfLastScan(
content: String,
raw: ByteArray?,
format: String
): Long {
return db.rawQuery(
"""SELECT
): Long = db.rawQuery(
"""SELECT
$SCANS_ID,
$SCANS_CONTENT,
$SCANS_RAW,
@@ -158,21 +158,20 @@ class Database {
FROM $SCANS
ORDER BY $SCANS_ID DESC
LIMIT 1
""", null
)?.use {
if (it.count > 0 &&
it.moveToFirst() &&
it.getString(it.getColumnIndex(SCANS_CONTENT)) == content &&
(raw == null || it.getBlob(it.getColumnIndex(SCANS_RAW))
?.contentEquals(raw) == true) &&
it.getString(it.getColumnIndex(SCANS_FORMAT)) == format
) {
it.getLong(it.getColumnIndex(SCANS_ID))
} else {
0L
}
} ?: 0L
}
""".trimMargin(), null
)?.use {
if (it.count > 0 &&
it.moveToFirst() &&
it.getString(SCANS_CONTENT) == content &&
(raw == null || it.getBlob(SCANS_RAW)
?.contentEquals(raw) == true) &&
it.getString(SCANS_FORMAT) == format
) {
it.getLong(SCANS_ID)
} else {
0L
}
} ?: 0L
fun removeScan(id: Long) {
db.delete(SCANS, "$SCANS_ID = ?", arrayOf("$id"))
@@ -230,7 +229,7 @@ class Database {
const val SCANS_UPC_EAN_EXTENSION = "upc_ean_extension"
private fun createScans(db: SQLiteDatabase) {
db.execSQL("DROP TABLE IF EXISTS $SCANS")
db.execSQL("DROP TABLE IF EXISTS $SCANS".trimMargin())
db.execSQL(
"""CREATE TABLE $SCANS (
$SCANS_ID INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -247,39 +246,29 @@ class Database {
$SCANS_POSSIBLE_COUNTRY TEXT,
$SCANS_SUGGESTED_PRICE TEXT,
$SCANS_UPC_EAN_EXTENSION TEXT
)"""
)""".trimMargin()
)
}
private fun addRawColumn(db: SQLiteDatabase) {
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_RAW BLOB")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_RAW BLOB".trimMargin())
}
private fun addMetaDataColumns(db: SQLiteDatabase) {
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ERROR_CORRECTION_LEVEL TEXT")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ISSUE_NUMBER INT")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_ORIENTATION INT")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_OTHER_META_DATA TEXT")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_PDF417_EXTRA_METADATA TEXT")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_POSSIBLE_COUNTRY TEXT")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_SUGGESTED_PRICE TEXT")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_UPC_EAN_EXTENSION TEXT")
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 addNameColumn(db: SQLiteDatabase) {
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_NAME TEXT")
db.execSQL("ALTER TABLE $SCANS ADD COLUMN $SCANS_NAME TEXT".trimMargin())
}
}
}
private fun Cursor.getString(name: String) = this.getString(
this.getColumnIndex(name)
)
private fun Cursor.getBlob(name: String) = this.getBlob(
this.getColumnIndex(name)
)
private fun Cursor.getLong(name: String) = this.getLong(
this.getColumnIndex(name)
)
@@ -6,16 +6,15 @@ import de.markusfisch.android.binaryeye.io.writeExternalFile
import java.io.File
import java.io.FileInputStream
fun exportDatabase(activity: Activity, fileName: String): Boolean {
fun Activity.exportDatabase(fileName: String): Boolean {
val dbFile = File(
Environment.getDataDirectory(),
"//data//${activity.packageName}//databases//${Database.FILE_NAME}"
"//data//${packageName}//databases//${Database.FILE_NAME}"
)
if (!dbFile.exists()) {
return false
}
return writeExternalFile(
activity,
fileName,
"application/vnd.sqlite3"
) {
@@ -8,18 +8,17 @@ import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
fun exportJson(
context: Context,
fun Context.exportJson(
name: String,
cursor: Cursor
) = writeExternalFile(context, name, "application/json") { outputStream ->
exportJson(cursor)?.let {
) = writeExternalFile(name, "application/json") { outputStream ->
cursor.exportJson()?.let {
outputStream.write(it.toByteArray())
}
}
fun exportJson(cursor: Cursor): String? {
if (!cursor.moveToFirst()) {
fun Cursor.exportJson(): String? {
if (!moveToFirst()) {
return null
}
val columns = arrayOf(
@@ -36,21 +35,21 @@ fun exportJson(cursor: Cursor): String? {
Database.SCANS_UPC_EAN_EXTENSION
)
val indices = columns.map {
Pair(cursor.getColumnIndex(it), it)
Pair(getColumnIndex(it), it)
}
val contentIndex = cursor.getColumnIndex(Database.SCANS_CONTENT)
val rawIndex = cursor.getColumnIndex(Database.SCANS_RAW)
val contentIndex = getColumnIndex(Database.SCANS_CONTENT)
val rawIndex = getColumnIndex(Database.SCANS_RAW)
val root = JSONArray()
do {
var deviation: Pair<Int, String>? = null
if (cursor.getString(contentIndex)?.isEmpty() == true) {
if (getString(contentIndex)?.isEmpty() == true) {
deviation = Pair(
contentIndex,
cursor.getBlob(rawIndex).toHexString()
getBlob(rawIndex).toHexString()
)
}
root.put(cursor.toJsonObject(indices, deviation))
} while (cursor.moveToNext())
root.put(toJsonObject(indices, deviation))
} while (moveToNext())
return root.toString()
}
@@ -5,6 +5,7 @@ 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
data class Scan(
val content: String,
@@ -18,23 +19,9 @@ data class Scan(
val possibleCountry: String?,
val suggestedPrice: String?,
val upcEanExtension: String?,
val timestamp: String = getDateTime(),
val dateTime: String = getDateTime(),
var id: Long = 0L
) : Parcelable {
constructor(result: Result) : this(
result.text,
getRawBytes(result),
result.barcodeFormat.toString(),
result.getMetaString(ResultMetadataType.ERROR_CORRECTION_LEVEL),
result.getMetaString(ResultMetadataType.ISSUE_NUMBER),
result.getMetaString(ResultMetadataType.ORIENTATION),
result.getMetaString(ResultMetadataType.OTHER),
result.getMetaString(ResultMetadataType.PDF417_EXTRA_METADATA),
result.getMetaString(ResultMetadataType.POSSIBLE_COUNTRY),
result.getMetaString(ResultMetadataType.SUGGESTED_PRICE),
result.getMetaString(ResultMetadataType.UPC_EAN_EXTENSION)
)
// Needs to be overwritten manually, as ByteArray is an array and
// this isn't handled well by Kotlin
override fun equals(other: Any?): Boolean {
@@ -48,7 +35,7 @@ data class Scan(
other as Scan
return id == other.id &&
timestamp == other.timestamp &&
dateTime == other.dateTime &&
content == other.content &&
((raw == null && other.raw == null) ||
(raw != null && other.raw != null && raw.contentEquals(other.raw))) &&
@@ -67,7 +54,7 @@ data class Scan(
// this isn't handled well by Kotlin
override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + timestamp.hashCode()
result = 31 * result + dateTime.hashCode()
result = 31 * result + content.hashCode()
result = 31 * result + (raw?.contentHashCode() ?: 0)
result = 31 * result + format.hashCode()
@@ -84,7 +71,7 @@ data class Scan(
private constructor(parcel: Parcel) : this(
content = parcel.readString() ?: "",
raw = readByteArray(parcel),
raw = parcel.readSizedByteArray(),
format = parcel.readString() ?: "",
errorCorrectionLevel = parcel.readString(),
issueNumber = parcel.readString(),
@@ -94,24 +81,26 @@ data class Scan(
possibleCountry = parcel.readString(),
suggestedPrice = parcel.readString(),
upcEanExtension = parcel.readString(),
timestamp = parcel.readString() ?: "",
dateTime = parcel.readString() ?: "",
id = parcel.readLong()
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(content)
writeByteArray(parcel, raw)
parcel.writeString(format)
parcel.writeString(errorCorrectionLevel)
parcel.writeString(issueNumber)
parcel.writeString(orientation)
parcel.writeString(otherMetaData)
parcel.writeString(pdf417ExtraMetaData)
parcel.writeString(possibleCountry)
parcel.writeString(suggestedPrice)
parcel.writeString(upcEanExtension)
parcel.writeString(timestamp)
parcel.writeLong(id)
parcel.apply {
writeString(content)
writeSizedByteArray(raw)
writeString(format)
writeString(errorCorrectionLevel)
writeString(issueNumber)
writeString(orientation)
writeString(otherMetaData)
writeString(pdf417ExtraMetaData)
writeString(possibleCountry)
writeString(suggestedPrice)
writeString(upcEanExtension)
writeString(dateTime)
writeLong(id)
}
}
override fun describeContents() = 0
@@ -130,8 +119,53 @@ private fun getDateTime(time: Long = System.currentTimeMillis()) = DateFormat.fo
time
).toString()
private fun getRawBytes(result: Result): ByteArray? {
val metadata = result.resultMetadata ?: return null
private fun Parcel.writeSizedByteArray(array: ByteArray?) {
val size = array?.size ?: 0
writeInt(size)
if (size > 0) {
writeByteArray(array)
}
}
private fun Parcel.readSizedByteArray(): ByteArray? {
val size = readInt()
return if (size > 0) {
val array = ByteArray(size)
readByteArray(array)
array
} else {
null
}
}
fun Result.toScan(): Scan {
val content: String
val raw: ByteArray?
if (text.hasNonPrintableCharacters()) {
content = ""
// ISO_8859_1 is important to suppress UTF-8 encoding.
raw = getRawData() ?: text.toByteArray(Charsets.ISO_8859_1)
} 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")
@@ -144,7 +178,7 @@ private fun getRawBytes(result: Result): ByteArray? {
// 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 >= result.text.length) bytes else null
return if (bytes.size >= text.length) bytes else null
}
private fun Result.getMetaString(
@@ -152,22 +186,3 @@ private fun Result.getMetaString(
): String? = this.resultMetadata?.let {
it[key]?.toString()
}
private fun writeByteArray(parcel: Parcel, array: ByteArray?) {
val size = array?.size ?: 0
parcel.writeInt(size)
if (size > 0) {
parcel.writeByteArray(array)
}
}
private fun readByteArray(parcel: Parcel): ByteArray? {
val size = parcel.readInt()
return if (size > 0) {
val array = ByteArray(size)
parcel.readByteArray(array)
array
} else {
null
}
}
@@ -26,9 +26,7 @@ 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 kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
@@ -40,6 +38,9 @@ class BarcodeFragment : Fragment() {
PNG, SVG, TXT
}
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
@@ -98,8 +99,10 @@ class BarcodeFragment : Fragment() {
}
view.findViewById<View>(R.id.share).setOnClickListener {
pickFileType(context, R.string.share_as) {
shareAs(it)
it.context?.apply {
pickFileType(R.string.share_as) { fileType ->
shareAs(fileType)
}
}
}
@@ -111,6 +114,11 @@ class BarcodeFragment : Fragment() {
return view
}
override fun onDestroyView() {
super.onDestroyView()
parentJob.cancel()
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.fragment_barcode, menu)
}
@@ -125,7 +133,7 @@ class BarcodeFragment : Fragment() {
true
}
R.id.export_to_file -> {
pickFileType(context, R.string.export_as) {
context.pickFileType(R.string.export_as) {
askForFileNameAndSave(it)
}
true
@@ -134,13 +142,12 @@ class BarcodeFragment : Fragment() {
}
}
private fun pickFileType(
context: Context,
private fun Context.pickFileType(
title: Int,
action: (FileType) -> Unit
) {
val fileTypes = FileType.values()
AlertDialog.Builder(context)
AlertDialog.Builder(this)
.setTitle(title)
.setItems(fileTypes.map { it.name }.toTypedArray()) { _, which ->
action(fileTypes[which])
@@ -152,9 +159,9 @@ class BarcodeFragment : Fragment() {
@SuppressLint("InflateParams")
private fun askForFileNameAndSave(fileType: FileType) {
val ac = activity ?: return
// write permission is only required before Android Q
// Write permission is only required before Android Q.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
!hasWritePermission(ac) { askForFileNameAndSave(fileType) }
!ac.hasWritePermission { askForFileNameAndSave(fileType) }
) {
return
}
@@ -201,27 +208,26 @@ class BarcodeFragment : Fragment() {
write: (outputStream: OutputStream) -> Unit
) {
val ac = activity ?: return
GlobalScope.launch(Dispatchers.IO) {
val message = writeExternalFile(ac, fileName, mimeType, write).toSaveResult()
launch(Dispatchers.Main) {
scope.launch(Dispatchers.IO) {
val message = ac.writeExternalFile(fileName, mimeType, write).toSaveResult()
withContext(Dispatchers.Main) {
ac.toast(message)
}
}
}
private fun shareAs(fileType: FileType) {
private fun Context.shareAs(fileType: FileType) {
when (fileType) {
FileType.PNG -> barcodeBitmap?.let { share(it) }
FileType.SVG -> barcodeSvg?.let { shareText(context, it, MIME_SVG) }
FileType.TXT -> barcodeTxt?.let { shareText(context, it) }
FileType.SVG -> barcodeSvg?.let { shareText(it, MIME_SVG) }
FileType.TXT -> barcodeTxt?.let { shareText(it) }
}
}
private fun share(bitmap: Bitmap) {
val ctx = context ?: return
GlobalScope.launch(Dispatchers.IO) {
private fun Context.share(bitmap: Bitmap) {
scope.launch(Dispatchers.IO) {
val file = File(
ctx.externalCacheDir,
externalCacheDir,
"shared_barcode.png"
)
val success = try {
@@ -232,11 +238,11 @@ class BarcodeFragment : Fragment() {
} catch (e: IOException) {
false
}
launch(Dispatchers.Main) {
withContext(Dispatchers.Main) {
if (success) {
shareFile(ctx, file, "image/png")
shareFile(file, "image/png")
} else {
ctx.toast(R.string.error_saving_file)
toast(R.string.error_saving_file)
}
}
}
@@ -271,9 +277,8 @@ class BarcodeFragment : Fragment() {
}
}
private fun Bitmap.saveAsPng(outputStream: OutputStream, quality: Int = 90) {
this.compress(Bitmap.CompressFormat.PNG, quality, outputStream)
}
private fun Bitmap.saveAsPng(outputStream: OutputStream, quality: Int = 90) =
compress(Bitmap.CompressFormat.PNG, quality, outputStream)
private val fileNameCharacters = "[^A-Za-z0-9]".toRegex()
private fun encodeFileName(name: String): String =
@@ -5,12 +5,16 @@ 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 de.markusfisch.android.binaryeye.R
import de.markusfisch.android.binaryeye.actions.ActionRegistry
import de.markusfisch.android.binaryeye.actions.wifi.WifiAction
@@ -38,6 +42,7 @@ class DecodeFragment : Fragment() {
private lateinit var metaView: TableLayout
private lateinit var hexView: TextView
private lateinit var format: String
private lateinit var stampView: TextView
private lateinit var fab: FloatingActionButton
private val parentJob = Job()
@@ -77,13 +82,12 @@ class DecodeFragment : Fragment() {
id = scan.id
val inputContent = scan.content
isBinary = hasNonPrintableCharacters(
inputContent
) or inputContent.isEmpty()
isBinary = scan.raw != null
raw = scan.raw ?: inputContent.toByteArray()
format = scan.format
contentView = view.findViewById(R.id.content)
stampView = view.findViewById(R.id.stamp)
fab = view.findViewById(R.id.open)
if (!isBinary) {
@@ -116,7 +120,7 @@ class DecodeFragment : Fragment() {
executeAction(content.toByteArray())
}
} else {
contentView.setText(R.string.binary_data)
contentView.setText(String(raw).foldNonAlNum())
contentView.isEnabled = false
fab.setImageResource(R.drawable.ic_action_save)
fab.setOnClickListener {
@@ -124,6 +128,17 @@ class DecodeFragment : Fragment() {
}
}
val trackingLink = generateDpTrackingLink(raw, scan.format)
if (trackingLink != null) {
stampView.apply {
text = Html.fromHtml(trackingLink)
isClickable = true
movementMethod = LinkMovementMethod.getInstance()
}
} else {
stampView.visibility = View.GONE
}
formatView = view.findViewById(R.id.format)
dataView = view.findViewById(R.id.data)
metaView = view.findViewById(R.id.meta)
@@ -175,68 +190,74 @@ class DecodeFragment : Fragment() {
}
}
private fun fillDataTable(tableLayout: TableLayout, items: LinkedHashMap<Int, String?>?) {
private fun fillDataView(tableLayout: TableLayout, content: String) {
val items = LinkedHashMap<Int, String?>()
if (action is WifiAction) {
WifiConnector.parseMap(content)?.let { wifiData ->
items.putAll(
linkedMapOf(
R.string.entry_type to getString(R.string.wifi_network),
R.string.wifi_ssid to wifiData["S"],
R.string.wifi_password to wifiData["P"],
R.string.wifi_type to wifiData["T"],
R.string.wifi_hidden to wifiData["H"],
R.string.wifi_eap to wifiData["E"],
R.string.wifi_identity to wifiData["I"],
R.string.wifi_anonymous_identity to wifiData["A"],
R.string.wifi_phase2 to wifiData["PH2"]
)
)
}
}
fillDataTable(tableLayout, items)
}
private fun fillMetaView(tableLayout: TableLayout, 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
)
if (prefs.showQrVersion && scan.format == "QR_CODE") {
items.putAll(
linkedMapOf(
R.string.qr_version to "${scan.version()}"
)
)
}
fillDataTable(tableLayout, items)
}
private fun fillDataTable(
tableLayout: TableLayout,
items: LinkedHashMap<Int, String?>
) {
val ctx = tableLayout.context
val spaceBetween = (16f * ctx.resources.displayMetrics.density).toInt()
var hasEntries = false
items?.forEach { item ->
item.value?.let {
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 = it
valueView.text = text
tr.addView(keyView)
tr.addView(valueView)
tableLayout.addView(tr)
hasEntries = true
}
}
if (hasEntries) {
if (tableLayout.childCount > 0) {
tableLayout.setPadding(0, 0, 0, spaceBetween)
}
}
private fun fillDataView(tableLayout: TableLayout, content: String) {
val items = LinkedHashMap<Int, String?>()
if (action is WifiAction) {
val wifiData = WifiConnector.parseMap(content)
if (wifiData != null) {
items[R.string.entry_type] = getString(R.string.wifi_network)
items[R.string.wifi_ssid] = wifiData["S"]
items[R.string.wifi_password] = wifiData["P"]
items[R.string.wifi_type] = wifiData["T"]
items[R.string.wifi_hidden] = wifiData["H"]
items[R.string.wifi_eap] = wifiData["E"]
items[R.string.wifi_identity] = wifiData["I"]
items[R.string.wifi_anonymous_identity] = wifiData["A"]
items[R.string.wifi_phase2] = wifiData["PH2"]
}
}
fillDataTable(tableLayout, items)
}
private fun fillMetaView(tableLayout: TableLayout, scan: Scan) {
fillDataTable(
tableLayout, 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
)
)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.fragment_decode, menu)
if (isBinary) {
@@ -264,15 +285,14 @@ class DecodeFragment : Fragment() {
true
}
R.id.share -> {
context?.also {
shareText(it, textOrHex())
context?.apply {
shareText(textOrHex())
maybeBackOrFinish()
}
true
}
R.id.create -> {
addFragment(
fragmentManager,
fragmentManager?.addFragment(
EncodeFragment.newInstance(content, format)
)
true
@@ -331,7 +351,7 @@ class DecodeFragment : Fragment() {
if (content.isNotEmpty()) {
if (action is WifiAction &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
!hasLocationPermission(ac) { executeAction(content) }
!ac.hasLocationPermission { executeAction(content) }
) {
return
}
@@ -344,13 +364,15 @@ class DecodeFragment : Fragment() {
private fun askForFileNameAndSave(raw: ByteArray) {
val ac = activity ?: return
if (!hasWritePermission(ac) { askForFileNameAndSave(raw) }) {
// Write permission is only required before Android Q.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
!ac.hasWritePermission { askForFileNameAndSave(raw) }
) {
return
}
scope.launch(Dispatchers.Main) {
val name = ac.askForFileName() ?: return@launch
val message = writeExternalFile(
ac,
val message = ac.writeExternalFile(
name,
"application/octet-stream"
) {
@@ -411,3 +433,75 @@ private fun hexDump(bytes: ByteArray, charsPerLine: Int = 33): String {
}
return dump.toString()
}
private fun generateDpTrackingLink(raw: ByteArray, format: String): String? {
// Check for Deutsche Post Matrixcode stamp.
var isStamp = false
var rawData = raw
if (format == "DATA_MATRIX" &&
raw.toString(Charsets.ISO_8859_1).startsWith("DEA5")
) {
if (raw.size == 47) {
isStamp = true
} else if (raw.size > 47) {
// Transform back to original data.
rawData = raw.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 Scan.version(): Int = Encoder.encode(
content,
ErrorCorrectionLevel.valueOf(errorCorrectionLevel ?: "L")
).version.versionNumber
@@ -145,8 +145,7 @@ class EncodeFragment : Fragment() {
).show()
} else {
activity?.hideSoftKeyboard(contentView)
addFragment(
fragmentManager,
fragmentManager?.addFragment(
BarcodeFragment.newInstance(content, format, size, hints)
)
}
@@ -24,6 +24,7 @@ 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
@@ -293,10 +294,7 @@ class HistoryFragment : Fragment() {
private fun showScan(id: Long) = db.getScan(id)?.also { scan ->
closeActionMode()
try {
addFragment(
fragmentManager,
DecodeFragment.newInstance(scan)
)
fragmentManager?.addFragment(DecodeFragment.newInstance(scan))
} catch (e: IllegalArgumentException) {
// Ignore, can never happen.
}
@@ -304,7 +302,7 @@ class HistoryFragment : Fragment() {
private fun getScanName(position: Int): String? {
val cursor = scansAdapter?.getItem(position) as Cursor?
return cursor?.getString(cursor.getColumnIndex(Database.SCANS_NAME))
return cursor?.getString(Database.SCANS_NAME)
}
// Dialogs don't have a parent layout.
@@ -364,13 +362,16 @@ class HistoryFragment : Fragment() {
scope.launch {
val ac = activity ?: return@launch
progressView.useVisibility {
if (!hasWritePermission(ac) { askToExportToFile() }) {
// Write permission is only required before Android Q.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
!ac.hasWritePermission { askToExportToFile() }
) {
return@useVisibility
}
val options = context.resources.getStringArray(
val options = ac.resources.getStringArray(
R.array.export_options_values
)
val delimiter = alertDialog<String>(context) { resume ->
val delimiter = alertDialog<String>(ac) { resume ->
setTitle(R.string.export_as)
setItems(R.array.export_options_names) { _, which ->
resume(options[which])
@@ -386,11 +387,11 @@ class HistoryFragment : Fragment() {
)
} ?: return@useVisibility
val message = when (delimiter) {
"db" -> exportDatabase(ac, name)
"db" -> ac.exportDatabase(name)
else -> db.getScansDetailed(filter)?.use {
when (delimiter) {
"json" -> exportJson(context, name, it)
else -> exportCsv(context, name, it, delimiter)
"json" -> ac.exportJson(name, it)
else -> ac.exportCsv(name, it, delimiter)
}
} ?: false
}.toSaveResult()
@@ -419,31 +420,31 @@ class HistoryFragment : Fragment() {
db.getScansDetailed(filter)?.use { cursor ->
val details = format.split(":")
text = when (details[0]) {
"text" -> exportText(cursor, details[1])
"csv" -> exportCsv(cursor, details[1])
else -> exportJson(cursor)
"text" -> cursor.exportText(details[1])
"csv" -> cursor.exportCsv(details[1])
else -> cursor.exportJson()
}
}
text?.let {
withContext(Dispatchers.Main) {
shareText(context, it)
context.shareText(it)
}
}
}
}
}
private fun exportText(cursor: Cursor, separator: String): String {
private fun Cursor.exportText(separator: String): String {
val sb = StringBuilder()
val contentIndex = cursor.getColumnIndex(Database.SCANS_CONTENT)
if (cursor.moveToFirst()) {
val contentIndex = getColumnIndex(Database.SCANS_CONTENT)
if (contentIndex > -1 && moveToFirst()) {
do {
val content = cursor.getString(contentIndex)
val content = getString(contentIndex)
if (content?.isNotEmpty() == true) {
sb.append(content)
sb.append(separator)
}
} while (cursor.moveToNext())
} while (moveToNext())
}
return sb.toString()
}
@@ -11,9 +11,9 @@ import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
fun loadImageUri(cr: ContentResolver, uri: Uri): Bitmap? = try {
fun ContentResolver.loadImageUri(uri: Uri): Bitmap? = try {
val options = BitmapFactory.Options()
cr.openInputStream(uri)?.use {
openInputStream(uri)?.use {
options.inJustDecodeBounds = true
BitmapFactory.decodeStream(it, null, options)
options.inSampleSize = calculateInSampleSize(
@@ -22,7 +22,7 @@ fun loadImageUri(cr: ContentResolver, uri: Uri): Bitmap? = try {
)
options.inJustDecodeBounds = false
}
cr.openInputStream(uri)?.use {
openInputStream(uri)?.use {
BitmapFactory.decodeStream(it, null, options)
}
} catch (e: IOException) {
@@ -49,8 +49,13 @@ private fun calculateInSampleSize(
return inSampleSize
}
fun crop(bitmap: Bitmap, rect: RectF, rotation: Float) = try {
val erected = erect(bitmap, 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())
@@ -59,8 +64,8 @@ fun crop(bitmap: Bitmap, rect: RectF, rotation: Float) = try {
erected,
x,
y,
min(w - x, (rect.width() * w).roundToInt()),
min(h - y, (rect.height() * h).roundToInt())
min(w - x, (rect.right * w).roundToInt() - x),
min(h - y, (rect.bottom * h).roundToInt() - y)
)
} catch (e: OutOfMemoryError) {
null
@@ -68,20 +73,24 @@ fun crop(bitmap: Bitmap, rect: RectF, rotation: Float) = try {
null
}
private fun erect(bitmap: Bitmap, rotation: Float): Bitmap = if (
private fun Bitmap.erect(
rotation: Float,
pivotX: Float,
pivotY: Float
): Bitmap = if (
rotation % 360f != 0f
) {
val matrix = Matrix()
matrix.setRotate(rotation)
Bitmap.createBitmap(
bitmap,
this,
0,
0,
bitmap.width,
bitmap.height,
matrix,
width,
height,
Matrix().apply {
setRotate(rotation, pivotX, pivotY)
},
true
)
} else {
bitmap
this
}
@@ -46,20 +46,18 @@ fun Boolean.toSaveResult() = if (this) {
R.string.error_saving_file
}
fun writeExternalFile(
context: Context,
fun Context.writeExternalFile(
fileName: String,
mimeType: String,
write: (outputStream: OutputStream) -> Unit
): Boolean = try {
openExternalOutputStream(context, fileName, mimeType).use { write(it) }
openExternalOutputStream(fileName, mimeType).use { write(it) }
true
} catch (e: IOException) {
false
}
private fun openExternalOutputStream(
context: Context,
private fun Context.openExternalOutputStream(
fileName: String,
mimeType: String
): OutputStream = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
@@ -75,7 +73,7 @@ private fun openExternalOutputStream(
}
FileOutputStream(file)
} else {
val resolver = context.contentResolver
val resolver = contentResolver
val uri = resolver.insert(
MediaStore.Downloads.EXTERNAL_CONTENT_URI,
ContentValues().apply {
@@ -1,6 +1,7 @@
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.database.Scan
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -14,9 +15,12 @@ import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.ProtocolException
import java.net.URL
import java.net.URLEncoder
fun Scan.sendAsync(url: String, type: String, callback: (Int?, String?) -> Unit) {
fun Scan.sendAsync(
url: String,
type: String,
callback: (Int?, String?) -> Unit
) {
CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
val response = send(url, type)
withContext(Dispatchers.Main) {
@@ -47,21 +51,19 @@ private fun Scan.send(url: String, type: String): Response {
}
}
else -> request(
url + urlEncode(content)
url + content.urlEncode()
)
}
}
private fun Scan.asUrlArguments(): String = getMap().map { (k, v) ->
"${k}=${urlEncode(v)}"
"${k}=${v.urlEncode()}"
}.joinToString("&")
private fun Scan.asJson() = JSONObject().apply {
getMap().forEach { (k, v) -> put(k, v) }
}
private fun urlEncode(s: String) = URLEncoder.encode(s, "utf-8")
private fun Scan.getMap(): Map<String, String> = mapOf(
"content" to content,
"raw" to raw?.toHexString(),
@@ -74,7 +76,7 @@ private fun Scan.getMap(): Map<String, String> = mapOf(
"possibleCountry" to possibleCountry,
"suggestedPrice" to suggestedPrice,
"upcEanExtension" to upcEanExtension,
"timestamp" to timestamp
"timestamp" to dateTime
).filterNullValues()
private fun Map<String, String?>.filterNullValues() =
@@ -1,11 +1,15 @@
package de.markusfisch.android.binaryeye.os
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 MILLISECONDS = 100L
private const val DURATION_IN_MS = 100L
private val beforeO = Build.VERSION.SDK_INT < Build.VERSION_CODES.O
private val errorPatternTimings = longArrayOf(
50L, 100L, 50L, 100L, 50L
)
@@ -13,17 +17,27 @@ private val errorPatternAmplitudes = intArrayOf(
255, 0, 255, 0, 255
)
fun Context.getVibrator(): Vibrator = if (
Build.VERSION.SDK_INT < Build.VERSION_CODES.S
) {
@Suppress("DEPRECATION")
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
} else {
(getSystemService(
Context.VIBRATOR_MANAGER_SERVICE
) as VibratorManager).defaultVibrator
}
fun Vibrator.vibrate() {
if (!prefs.vibrate) {
return
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
} else if (beforeO) {
@Suppress("DEPRECATION")
vibrate(MILLISECONDS)
vibrate(DURATION_IN_MS)
} else {
vibrate(
VibrationEffect.createOneShot(
MILLISECONDS,
DURATION_IN_MS,
VibrationEffect.DEFAULT_AMPLITUDE
)
)
@@ -33,8 +47,7 @@ fun Vibrator.vibrate() {
fun Vibrator.error() {
if (!prefs.vibrate) {
return
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
} else if (beforeO) {
@Suppress("DEPRECATION")
vibrate(errorPatternTimings, -1)
} else {
@@ -123,6 +123,11 @@ 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)
@@ -143,6 +148,11 @@ class Preferences {
apply(OPEN_WITH_URL, value)
field = value
}
var sendScanActive = true
set(value) {
apply(SEND_SCAN_ACTIVE, value)
field = value
}
var sendScanUrl: String = ""
set(value) {
apply(SEND_SCAN_URL, value)
@@ -163,7 +173,7 @@ class Preferences {
apply(INDEX_OF_LAST_SELECTED_FORMAT, value)
field = value
}
var forceCompat: Boolean = false
var forceCompat = false
set(value) {
// Since the app may be about to crash when forceCompat is set,
// it's necessary to `commit()` this synchronously.
@@ -219,6 +229,7 @@ class Preferences {
openImmediately
)
showMetaData = preferences.getBoolean(SHOW_META_DATA, showMetaData)
showQrVersion = preferences.getBoolean(SHOW_QR_VERSION, showQrVersion)
showHexDump = preferences.getBoolean(SHOW_HEX_DUMP, showHexDump)
closeAutomatically = preferences.getBoolean(
CLOSE_AUTOMATICALLY,
@@ -230,6 +241,10 @@ class Preferences {
preferences.getString(OPEN_WITH_URL, openWithUrl)?.also {
openWithUrl = it
}
sendScanActive = preferences.getBoolean(
SEND_SCAN_ACTIVE,
sendScanActive
)
preferences.getString(SEND_SCAN_URL, sendScanUrl)?.also {
sendScanUrl = it
}
@@ -278,31 +293,33 @@ class Preferences {
}
companion object {
const val BARCODE_FORMATS = "barcode_formats"
const val CROP_HANDLE_X = "crop_handle_x"
const val CROP_HANDLE_Y = "crop_handle_y"
const val CROP_HANDLE_ORIENTATION = "crop_handle_orientation"
const val SHOW_CROP_HANDLE = "show_crop_handle"
const val ZOOM_BY_SWIPING = "zoom_by_swiping"
const val AUTO_ROTATE = "auto_rotate"
const val TRY_HARDER = "try_harder"
const val BULK_MODE = "bulk_mode"
const val BULK_MODE_DELAY = "bulk_mode_delay"
const val SHOW_TOAST_IN_BULK_MODE = "show_toast_in_bulk_mode"
const val VIBRATE = "vibrate"
const val USE_HISTORY = "use_history"
const val IGNORE_CONSECUTIVE_DUPLICATES = "ignore_consecutive_duplicates"
const val OPEN_IMMEDIATELY = "open_immediately"
const val COPY_IMMEDIATELY = "copy_immediately"
const val SHOW_META_DATA = "show_meta_data"
const val SHOW_HEX_DUMP = "show_hex_dump"
const val CLOSE_AUTOMATICALLY = "close_automatically"
const val DEFAULT_SEARCH_URL = "default_search_url"
const val OPEN_WITH_URL = "open_with_url"
const val SEND_SCAN_URL = "send_scan_url"
const val SEND_SCAN_TYPE = "send_scan_type"
const val CUSTOM_LOCALE = "custom_locale"
const val INDEX_OF_LAST_SELECTED_FORMAT = "index_of_last_selected_format"
const val FORCE_COMPAT = "force_compat"
private const val BARCODE_FORMATS = "barcode_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"
private const val SHOW_CROP_HANDLE = "show_crop_handle"
private const val ZOOM_BY_SWIPING = "zoom_by_swiping"
private const val AUTO_ROTATE = "auto_rotate"
private const val TRY_HARDER = "try_harder"
private const val BULK_MODE = "bulk_mode"
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 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 CLOSE_AUTOMATICALLY = "close_automatically"
private const val DEFAULT_SEARCH_URL = "default_search_url"
private const val OPEN_WITH_URL = "open_with_url"
private const val SEND_SCAN_ACTIVE = "send_scan_active"
private const val SEND_SCAN_URL = "send_scan_url"
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"
}
}
@@ -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)
@@ -26,15 +26,15 @@ class Zxing(possibleResultPoint: ResultPointCallback? = null) {
}
private fun setDecodeFormats(formats: Set<String>) {
val decodeFormats = EnumSet.noneOf(
hints[DecodeHintType.POSSIBLE_FORMATS] = EnumSet.noneOf(
BarcodeFormat::class.java
)
decodeFormats.addAll(
EnumSet.copyOf(
formats.map { BarcodeFormat.valueOf(it) }
).apply {
addAll(
EnumSet.copyOf(
formats.map { BarcodeFormat.valueOf(it) }
)
)
)
hints[DecodeHintType.POSSIBLE_FORMATS] = decodeFormats
}
}
fun decode(
@@ -42,8 +42,8 @@ class Zxing(possibleResultPoint: ResultPointCallback? = null) {
width: Int,
height: Int,
invert: Boolean = false
): Result? {
val source = PlanarYUVLuminanceSource(
): Result? = decodeLuminanceSource(
PlanarYUVLuminanceSource(
yuvData,
width,
height,
@@ -52,25 +52,20 @@ class Zxing(possibleResultPoint: ResultPointCallback? = null) {
width,
height,
false
)
return decodeLuminanceSource(source, invert)
}
),
invert
)
fun decodePositiveNegative(bitmap: Bitmap): Result? =
decode(bitmap, false) ?: decode(bitmap, true)
private fun decode(bitmap: Bitmap, invert: Boolean = false): Result? {
val pixels = IntArray(bitmap.width * bitmap.height)
return decode(pixels, bitmap, invert)
}
private fun decode(
pixels: IntArray,
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 {
@@ -85,31 +80,29 @@ class Zxing(possibleResultPoint: ResultPointCallback? = null) {
private fun decodeLuminanceSource(
source: LuminanceSource,
invert: Boolean
): Result? {
return decodeLuminanceSource(
if (invert) {
source.invert()
} else {
source
}
)
}
private fun decodeLuminanceSource(source: LuminanceSource): Result? {
val bitmap = BinaryBitmap(HybridBinarizer(source))
return try {
multiFormatReader.decode(bitmap, 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()
): 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()
}
}
@@ -193,16 +186,11 @@ private fun encode(
encodeHints: EnumMap<EncodeHintType, Any>? = null,
width: Int = 0,
height: Int = 0
): BitMatrix {
val hints = encodeHints ?: EnumMap<EncodeHintType, Any>(EncodeHintType::class.java)
if (!hints.contains(EncodeHintType.CHARACTER_SET)) {
hints[EncodeHintType.CHARACTER_SET] = "utf-8"
): 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"
}
}
return MultiFormatWriter().encode(
text,
format,
width,
height,
hints
)
}
)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

@@ -0,0 +1,3 @@
<vector android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="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>
@@ -1,14 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="108dp" android:height="108dp" android:viewportWidth="108" android:viewportHeight="108">
<path android:fillColor="#FF000000" android:pathData="M52-884.362h29v71H52z"/>
<path android:fillColor="#FF000000" android:pathData="M52-884.362h29v71H52z"/>
<path android:fillColor="#FF000000" android:pathData="M52-884.362h29v71H52zM32.002-24.974h3.127v7.656h-3.127z"/>
<path android:fillColor="#FF000000" android:pathData="M52-884.362h29v71H52z"/>
<path android:fillColor="#FF000000" android:pathData="M52-884.362h29v71H52z"/>
<path android:fillColor="#FF000000" android:pathData="M52-884.362h29v71H52z"/>
<path android:fillColor="#FF000000" android:pathData="M52-884.362h29v71H52z"/>
<path android:fillColor="#FF000000" android:pathData="M52-884.362h29v71H52z"/>
<path android:pathData="M54.826 27.893c-6.851 0-13.701 2.581-18.924 7.745-10.445 10.328-10.413 27.062 0 37.423l36.218 36.036 37.879 0.902-0.07-38.363-36.18-35.998c-5.207-5.18-12.073-7.745-18.924-7.745z" android:strokeWidth="8.60725021" android:fillColor="#000000" android:fillAlpha="0.1254902"/>
<path android:pathData="M28.001 54.118a26.525 26.227 0 1 0 53.049 0 26.525 26.227 0 1 0-53.049 0z" android:strokeWidth="4" android:fillColor="#ffffff"/>
<path android:pathData="M39.26 54.988a14.509 14.346 0 1 0 29.019 0 14.509 14.346 0 1 0-29.019 0z" android:strokeWidth="4" android:fillColor="#000000"/>
<path android:pathData="M54.034 44.513a9.535 9.428 0 1 0 19.07 0 9.535 9.428 0 1 0-19.07 0z" android:strokeWidth="10" android:fillColor="#ffffff"/>
<path android:pathData="M54.723 28.295c-6.85 0-13.701 2.581-18.923 7.745-10.446 10.328-10.414 27.062 0 37.423l36.218 36.036L108 108l1.827-35.962-36.18-35.998c-5.207-5.18-12.073-7.745-18.924-7.745z" android:strokeWidth="8.60725021" android:fillColor="#000000" android:fillAlpha="0.1254902"/>
<path android:pathData="M80.5 54a26.5 26.5 0 1 1-53 0 26.5 26.5 0 1 1 53 0" android:strokeWidth="4" android:fillColor="#FFFFFF"/>
<path android:pathData="M35.179 54c0-4.605 1.656-8.824 4.402-12.095v24.19c-2.746-3.271-4.402-7.49-4.402-12.095zM54 35.181c0.539 0 1.074 0.023 1.601 0.066v37.506c-0.527 0.044-1.062 0.066-1.601 0.066-0.54 0-1.074-0.022-1.602-0.066V35.247c0.528-0.043 1.062-0.066 1.602-0.066zM72.819 54c0 4.605-1.654 8.824-4.401 12.095v-24.19c2.747 3.271 4.401 7.49 4.401 12.095zM45.99 36.965c1.02-0.481 2.093-0.873 3.204-1.166v36.402c-1.111-0.293-2.184-0.685-3.204-1.166v-34.07zm12.816-1.166c2.347 0.619 4.514 1.679 6.408 3.086v30.23c-1.894 1.408-4.061 2.467-6.408 3.086V35.799z" android:strokeWidth="4" android:fillColor="#000000"/>
</vector>
@@ -0,0 +1,5 @@
<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>
+6 -4
View File
@@ -17,10 +17,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_marginBottom="8dp"
android:layout_marginRight="80dp"
android:layout_marginEnd="80dp"
android:padding="16dp"/>
android:layout_marginBottom="16dp"
android:layout_marginRight="88dp"
android:layout_marginEnd="88dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:padding="24dp"/>
<android.support.design.widget.FloatingActionButton
style="@style/FAB"
android:id="@+id/flash"
@@ -68,6 +68,18 @@
android:typeface="monospace"
android:textSize="12sp"
tools:text="54 65 73 74 20 51 52 20 Test QR\n43 6F 64 65 Code"/>
<TextView
android:id="@+id/stamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/hex"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:textSize="12sp"
android:typeface="monospace"/>
</RelativeLayout>
</de.markusfisch.android.binaryeye.widget.ConfinedScrollView>
<android.support.design.widget.CoordinatorLayout
@@ -27,6 +27,11 @@
android:icon="@drawable/ic_action_bulk_mode"
android:checkable="true"
material:showAsAction="ifRoom"/>
<item
android:id="@+id/restrict_format"
android:title="@string/restrict_format"
android:icon="@drawable/ic_action_restrict_format"
material:showAsAction="ifRoom"/>
<item
android:id="@+id/preferences"
android:title="@string/preferences"
@@ -1,4 +1,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/accent"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

+10
View File
@@ -22,7 +22,9 @@
<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="toggle_flash">আলো</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">ভাগ করো</string>
<string name="share_as">ভাগ করার মাধ্যম</string>
<string name="copy_to_clipboard">ক্লিপবোর্ডে অনুলিপি</string>
@@ -45,6 +47,9 @@
<string name="bulk_mode">ধারাবাহিকভাবে খুঁজো</string>
<string name="bulk_mode_summary">শুরুতে সবসময় ধারাবাহিকভাবে খুঁজো</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>
@@ -80,6 +85,8 @@
<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="close_automatically">অনুলিপি/ভাগ করার পরে পিছনে যাও</string>
@@ -93,12 +100,15 @@
<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">পরীক্ষার জন্য ইউআরএল</string>
<string name="really_remove_scan">আসলেই এটা মুছবে?</string>
<string name="really_remove_all_scans">আসলেই সব মুছবে?</string>
+48 -37
View File
@@ -1,7 +1,7 @@
<resources>
<string name="no_camera_no_fun">Bez oprávnění k fotoaparátu tato aplikace nemá smysl. Na viděnou.</string>
<string name="camera_error">Nepodařilo se otevřít fotoaparát, prosím zkuste to znovu</string>
<string name="scan_code">Skenovat kód</string>
<string name="scan_code">Naskenovat kód</string>
<string name="compose_barcode">Vytvořit čárový kód</string>
<string name="decode_barcode">Dekódovat čárový kód</string>
<string name="content">Obsah</string>
@@ -9,6 +9,7 @@
<plurals name="barcode_info">
<item quantity="one">%2$d znak, %1$s</item>
<item quantity="few">%2$d znaky, %1$s</item>
<item quantity="many">%2$d znaků, %1$s</item>
<item quantity="other">%2$d znaků, %1$s</item>
</plurals>
<string name="error_correction_level">Stupeň korekce chyb</string>
@@ -16,14 +17,16 @@
<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">Issue number</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="toggle_flash">Zap/vyp blesk</string>
<string name="error_flash">Zapnutí/vypnutí blesku selhalo</string>
<string name="share">Sdílet</string>
<string name="share_as">Sdílet jako</string>
<string name="copy_to_clipboard">Zkopírovat do schránky</string>
@@ -31,7 +34,7 @@
<string name="copy_password">Zkopírovat heslo do schránky</string>
<string name="copied_password_to_clipboard">Heslo zkopírováno do schránky</string>
<string name="open_url">Otevřít URL</string>
<string name="cannot_resolve_action">Nemáte aplikaci, která by to uměla otevřít</string>
<string name="cannot_resolve_action">Nemáte aplikaci, která by toto uměla otevřít</string>
<string name="pick_search_engine">Zvolte vyhledávač</string>
<string name="format">Formát</string>
<string name="size">Velikost v pixelech</string>
@@ -44,31 +47,34 @@
<string name="info">Info</string>
<string name="switch_camera">Přepnout kameru</string>
<string name="bulk_mode">Skenovat nepřetržitě</string>
<string name="bulk_mode_summary">Always start scanning continuously.</string>
<string name="bulk_mode_delay">Delay between continuous scans</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">Vždy začít v módu nepřetržitého skenování.</string>
<string name="bulk_mode_delay">Prodleva mezi skeny</string>
<string name="restrict_format">Omezit na formát</string>
<string name="remove_restriction">Zrušit omezení formátu</string>
<string name="scan_format">Naskenovat %s</string>
<string name="quarter_second">Čtvrt sekundy</string>
<string name="half_second">Půl sekundy</string>
<string name="a_second">Jedna sekunda</string>
<string name="two_seconds">Dvě sekundy</string>
<string name="five_seconds">Pět sekund</string>
<string name="history">Historie</string>
<string name="preferences">Nastavení</string>
<string name="scan_category">Skenování</string>
<string name="content_category">Obsah</string>
<string name="locale_category">Jazyk</string>
<string name="custom_locale">Zvolit jazyk</string>
<string name="follow_system_settings">Řídit se nastavením systému</string>
<string name="custom_locale">Nastavit jazyk</string>
<string name="follow_system_settings">Podle systému</string>
<string name="show_crop_handle">Zobrazovat hrany výřezu</string>
<string name="show_crop_handle_summary">Omezí skenování na zvolenou oblast.</string>
<string name="barcode_formats">Barcode formats</string>
<string name="barcode_formats">Formáty čárových kódů</string>
<string name="zoom_by_swiping">Potáhnutím nahoru/dolů přiblížit</string>
<string name="zoom_by_swiping_summary">Přetáhnutím nahoru nebo dolů se zvětší / zmenší úroveň přiblížení.</string>
<string name="auto_rotate">Rozpoznávat otočené 1D čárové kódy</string>
<string name="auto_rotate_summary">Automaticky otočí obraz a tak detekuje 1D čárové kódy na výšku. Na některých zařízeních může snížit výkonnost.</string>
<string name="try_harder">Optimalizovat pro přesnost</string>
<string name="try_harder_summary">Použijte pro velmi nečitelné kódy. Sníží výkonnost.</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">Zobrazovat data v módu nepřetržitého skenování</string>
<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="use_history">Ukládat historii skenování</string>
@@ -81,25 +87,30 @@
<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="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">Open unknown data in</string>
<string name="always_ask">Always ask</string>
<string name="open_with_url">Otevřít neznámá data pomocí 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">Přesměrování</string>
<string name="default_search_engine">Nerozpoznaná data otevřít v</string>
<string name="always_ask">Vždy se zeptat</string>
<string name="open_with_url">Otevřít nerozpoznaná data pomocí URL</string>
<string name="clear_network_suggestions">Smazat navrhované sítě</string>
<string name="clear_network_suggestions_summary">Smazat všechny sítě, které byly navrženy touto aplikací.</string>
<string name="really_remove_all_networks">Opravdu smazat všechny sítě?</string>
<string name="clear_network_suggestions_success">Navrhované sítě smazány</string>
<string name="clear_network_suggestions_nothing_to_remove">Nic k smazání</string>
<string name="send_category">Převání</string>
<string name="send_scan_active">Předávat skeny</string>
<string name="send_scan_active_summary">Zapnout předávání skenů na danou URL</string>
<string name="send_scan_url">Posílat každý sken na URL</string>
<string name="send_scan_type">Typ requestu pro každý sken</string>
<string name="send_type_get_add_content">GET a simply add content</string>
<string name="send_type_get_query_string">GET with compelete query string</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">Otevřít v prohlížeči</string>
<string name="test_url">Otestovat URL</string>
<string name="really_remove_scan">Opravdu odstranit sken?</string>
<string name="really_remove_all_scans">Opravdu odstranit všechny skeny?</string>
@@ -142,20 +153,20 @@
<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="pick_file">Zvolte obrázek</string>
<string name="pick_code_to_scan">Zvolte kód k naskenování</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>
<string name="shortcut_encode">Vytvořit čárový kód</string>
<string name="shortcut_preferences">Nastavení</string>
<string name="background_request_failed">Požadavek na pozadí selhal</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">Typ</string>
<string name="wifi_network">Wi-Fi síť</string>
<string name="wifi_ssid">Název</string>
<string name="wifi_type">Zabezpečení</string>
<string name="wifi_password">Heslo</string>
<string name="wifi_hidden">Skrytá síť</string>
<string name="wifi_eap">Metoda EAP</string>
<string name="wifi_anonymous_identity">Anonym identita</string>
<string name="wifi_identity">Identita</string>
<string name="wifi_phase2">Ověření Phase 2</string>
</resources>
+13 -3
View File
@@ -22,7 +22,9 @@
<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="toggle_flash">Licht an/ausschalten</string>
<string name="error_flash">Fehler beim ein/ausschalten des Lichts</string>
<string name="share">Teilen</string>
<string name="share_as">Teilen als?</string>
<string name="copy_to_clipboard">In die Zwischenablage kopieren</string>
@@ -45,6 +47,9 @@
<string name="bulk_mode">Fortlaufend Scannen</string>
<string name="bulk_mode_summary">Immer mit fortlaufendem Scannen starten.</string>
<string name="bulk_mode_delay">Pause zwischen fortlaufenden Scans</string>
<string name="restrict_format">Format eingrenzen</string>
<string name="remove_restriction">Einschränkung entfernen</string>
<string name="scan_format">%s scannen</string>
<string name="quarter_second">Eine Viertelsekunde</string>
<string name="half_second">Eine halbe Sekunde</string>
<string name="a_second">Eine Sekunde</string>
@@ -67,7 +72,7 @@
<string name="try_harder">Gründliche Suche</string>
<string name="try_harder_summary">Aktivieren Sie diese Option für sehr schwer lesbare Codes. Beeinträchtigt die Leistung.</string>
<string name="show_toast_in_bulk_mode">Daten einblenden</string>
<string name="show_toast_in_bulk_mode_summary">Die gescannten Daten werden kurz eingeblenet, wenn fortlaufend gescannt wird.</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="use_history">Codes speichern</string>
@@ -80,6 +85,8 @@
<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="close_automatically">Automatisch zurückkehren</string>
@@ -93,12 +100,15 @@
<string name="clear_network_suggestions_success">Netzwerkvorschläge entfernt</string>
<string name="clear_network_suggestions_nothing_to_remove">Nichts zu entfernen</string>
<string name="send_category">Weiterleitung</string>
<string name="send_scan_url">URL die für jeden Scan aufgerufen werden soll</string>
<string name="send_scan_type">Typ des Requests für jeden Scan</string>
<string name="send_scan_active">Scans weiterleiten</string>
<string name="send_scan_active_summary">Aktivieren Sie diese Option, um Scans an die angegebene URL weiterzuleiten.</string>
<string name="send_scan_url">URL, an die weitergeleitet werden soll</string>
<string name="send_scan_type">Requesttyp</string>
<string name="send_type_get_add_content">GET mit an die URL angehängtem Inhalt</string>
<string name="send_type_get_query_string">GET mit vollständigem Query-String</string>
<string name="send_type_post_form">POST application/x-www-form-urlencoded</string>
<string name="send_type_post_json">POST application/json</string>
<string name="send_type_external_browser">In externem Browser öffnen</string>
<string name="test_url">Test URL</string>
<string name="really_remove_scan">Code wirklich entfernen?</string>
<string name="really_remove_all_scans">Alle Codes entfernen?</string>
+10
View File
@@ -22,7 +22,9 @@
<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="error_flash">Error toggling flash</string>
<string name="share">Compartir</string>
<string name="share_as">¿Compartir como?</string>
<string name="copy_to_clipboard">Copiar al portapapeles</string>
@@ -45,6 +47,9 @@
<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>
@@ -80,6 +85,8 @@
<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="close_automatically">Retroceder luego de Copiar/Compartir</string>
@@ -93,12 +100,15 @@
<string name="clear_network_suggestions_success">Sugerencias de red eliminadas</string>
<string name="clear_network_suggestions_nothing_to_remove">Nada que eliminar</string>
<string name="send_category">Reenvío</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">Enviar todo escaneo a la URL</string>
<string name="send_scan_type">Tipo de solicitud para cada escaneo</string>
<string name="send_type_get_add_content">GET y solo añadir contenido</string>
<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="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>
+51 -41
View File
@@ -8,6 +8,7 @@
<string name="binary_data">(données binaires)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d caractère, %1$s</item>
<item quantity="many">%2$d caractères, %1$s</item>
<item quantity="other">%2$d caractères, %1$s</item>
</plurals>
<string name="error_correction_level">Niveau de correction d\'erreur</string>
@@ -15,14 +16,16 @@
<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="issue_number">Numéro du problème</string>
<string name="orientation">Orientation</string>
<string name="other_meta_data">Métadonnées</string>
<string name="pdf417_extra_metadata">PDF417 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">UPC EAN extension</string>
<string name="upc_ean_extension">Extension UPC EAN</string>
<string name="qr_version">QR version</string>
<string name="toggle_flash">Activer le 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>
@@ -43,13 +46,16 @@
<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">Always start scanning continuously.</string>
<string name="bulk_mode_delay">Delay between continuous scans</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">Démarre toujours en scan continu.</string>
<string name="bulk_mode_delay">Délai entre les scans continus</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>
<string name="a_second">Une seconde</string>
<string name="two_seconds">Deux secondes</string>
<string name="five_seconds">Cinq secondes</string>
<string name="history">Historique</string>
<string name="preferences">Préférences</string>
<string name="scan_category">Scan</string>
@@ -58,47 +64,52 @@
<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="barcode_formats">Barcode formats</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">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">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="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_meta_data_summary">Affiche les données supplémentaires sur le code-barres scanné.</string>
<string name="show_qr_version">Afficher la version QR</string>
<string name="show_qr_version_summary">Affiche le numéro de version QR.</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="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">Open unknown data in</string>
<string name="always_ask">Always ask</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">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">Supprimer les suggestions de réseau</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_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>
<string name="send_type_post_json">POST application/json</string>
<string name="send_type_external_browser">Ouvrir dans un navigateur externe</string>
<string name="test_url">Tester l\'URL</string>
<string name="really_remove_scan">Supprimer le scan ?</string>
<string name="really_remove_all_scans">Supprimer tous les scans ?</string>
@@ -148,14 +159,13 @@
<string name="shortcut_preferences">Réglages</string>
<string name="background_request_failed">Échec de la requête d\'arrière-plan</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="wifi_network">Réseau Wi-Fi</string>
<string name="wifi_ssid">Nom</string>
<string name="wifi_type">Type d\'identification</string>
<string name="wifi_password">Mot de passe</string>
<string name="wifi_hidden">Réseau caché</string>
<string name="wifi_eap">Méthode EAP</string>
<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>
</resources>
+11 -1
View File
@@ -22,7 +22,9 @@
<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="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>
<string name="share_as">Megosztja másként?</string>
<string name="copy_to_clipboard">Másolás a vágólapra</string>
@@ -45,6 +47,9 @@
<string name="bulk_mode">Beolvasás folyamatosan</string>
<string name="bulk_mode_summary">Mindig folyamatos beolvasást indítson.</string>
<string name="bulk_mode_delay">Folyamatos beolvasások közti késleltetés</string>
<string name="restrict_format">Formátum korlátozása</string>
<string name="remove_restriction">Korlátozás eltávolítása</string>
<string name="scan_format">%s beolvasása</string>
<string name="quarter_second">Negyed másodperc</string>
<string name="half_second">Fél másodperc</string>
<string name="a_second">Egy másodperc</string>
@@ -80,6 +85,8 @@
<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="close_automatically">Ugrás vissza másolás vagy megosztás után</string>
@@ -93,13 +100,16 @@
<string name="clear_network_suggestions_success">Hálózati javaslatok törölve</string>
<string name="clear_network_suggestions_nothing_to_remove">Nincs mit eltávolítani</string>
<string name="send_category">Továbbítás</string>
<string name="send_scan_active">Beolvasások továbbítása</string>
<string name="send_scan_active_summary">A beolvasásoknak az adott URL-re történő továbbításának engedélyezése</string>
<string name="send_scan_url">Összes beolvasás küldése egy URL-re</string>
<string name="send_scan_type">Kérés típusa az egyes beolvasásoknál</string>
<string name="send_type_get_add_content">GET és a tartalom egyszerű hozzáadása</string>
<string name="send_type_get_query_string">GET a teljes lekérdezési karakterlánccal</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="test_url">Test URL</string>
<string name="send_type_external_browser">Megnyitás külső böngészőben</string>
<string name="test_url">Teszt URL</string>
<string name="really_remove_scan">Valóban eltávolítja a beolvasást?</string>
<string name="really_remove_all_scans">Valóban eltávolítja az összes beolvasását?</string>
<string name="really_remove_selected_scans">Valóban eltávolítja a kijelölt beolvasásokat?</string>
+10
View File
@@ -21,7 +21,9 @@
<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="toggle_flash">Nyala/matikan blitz</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Bagikan</string>
<string name="share_as">Bagikan sebagai?</string>
<string name="copy_to_clipboard">Salin ke clipboard</string>
@@ -44,6 +46,9 @@
<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>
@@ -79,6 +84,8 @@
<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>
@@ -92,12 +99,15 @@
<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">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_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="really_remove_scan">Yakin menghapus pindaian?</string>
<string name="really_remove_all_scans">Yakin menghapus semua pindaian?</string>
+57 -47
View File
@@ -10,11 +10,11 @@
<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="error_correction_level">Livello di correzione degli 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="issue_number">Numero di edizione</string>
<string name="orientation">Orientamento</string>
<string name="other_meta_data">Metadati</string>
@@ -22,9 +22,11 @@
<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="toggle_flash">Flash</string>
<string name="qr_version">Versione QR</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="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>
@@ -43,62 +45,70 @@
<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="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="locale_category">Lingua</string>
<string name="custom_locale">Lingua personalizzata</string>
<string name="follow_system_settings">Segui le impostazioni di sistema</string>
<string name="show_crop_handle">Mostra riquadro di 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 di 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="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">Mostra i dati in modalità continua</string>
<string name="show_toast_in_bulk_mode_summary">Mostra brevemente i dati scansionati durante la scansione continua.</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="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">Mostra metadati</string>
<string name="show_meta_data_summary">Mostra dati aggiuntivi sul codice a barre scansionato.</string>
<string name="show_qr_version">Mostra versione QR</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="close_automatically">Vai indietro dopo la Copia/Condivisione</string>
<string name="close_automatically_summary">Ritorna automaticamente alla schermata di scansione dopo aver copiato o condiviso i contenuti letti.</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">Rimuovi tutti i suggerimenti di rete precedentemente forniti da questa app.</string>
<string name="really_remove_all_networks">Rimuovere davvero 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_url">Invia ogni scansione ad un URL</string>
<string name="send_scan_type">Tipo di richiesta per ogni scansione</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">GET e aggiungi il contenuto</string>
<string name="send_type_get_query_string">GET 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">Apri nel browser esterno</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>
@@ -113,7 +123,7 @@
<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="save_as_file_name">Salvare come file nei Download?</string>
<string name="file_name">Nome del file</string>
<string name="error_saving_file">Impossibile salvare il file</string>
<string name="error_file_exists">Il file esiste già</string>
@@ -137,8 +147,8 @@
<string name="export_as">Esportare come?</string>
<string name="export_csv_comma">CSV con virgole</string>
<string name="export_csv_semicolon">CSV con punti e virgola</string>
<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="pick_file">Scegli file immagine</string>
@@ -147,14 +157,14 @@
<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 Wi-Fi</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_hidden">Rete nascosta</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_anonymous_identity">Identità anonima</string>
<string name="wifi_identity">Identità</string>
<string name="wifi_phase2">Metodo di fase 2</string>
</resources>
+23 -14
View File
@@ -7,7 +7,6 @@
<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>
@@ -22,7 +21,9 @@
<string name="possible_country">製造国</string>
<string name="suggested_price">価格</string>
<string name="upc_ean_extension">UPC/EAN 拡張型</string>
<string name="toggle_flash">フラッシュを切り替え</string>
<string name="qr_version">QR version</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>
@@ -44,12 +45,15 @@
<string name="switch_camera">カメラを切り替え</string>
<string name="bulk_mode">まとめてスキャンする</string>
<string name="bulk_mode_summary">常に連続してスキャンを行います。</string>
<string name="bulk_mode_delay">Delay between continuous scans</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">連続スキャンの間隔</string>
<string name="restrict_format">フォーマットの制限</string>
<string name="remove_restriction">制限を解除</string>
<string name="scan_format">%sをスキャン</string>
<string name="quarter_second">0.25秒</string>
<string name="half_second">0.5秒</string>
<string name="a_second">1秒</string>
<string name="two_seconds">2秒</string>
<string name="five_seconds">5秒</string>
<string name="history">履歴</string>
<string name="preferences">設定</string>
<string name="scan_category">スキャン</string>
@@ -80,6 +84,8 @@
<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="close_automatically">コピー/共有後に戻る</string>
@@ -93,12 +99,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">スキャンしたデータを転送</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">外部ブラウザで開く</string>
<string name="test_url">URLをテスト</string>
<string name="really_remove_scan">このスキャン履歴を削除しても宜しいですか?</string>
<string name="really_remove_all_scans">全てのスキャン履歴を削除しても宜しいですか?</string>
@@ -147,12 +156,12 @@
<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="entry_type">種類</string>
<string name="wifi_network">Wi-Fiネットワーク</string>
<string name="wifi_ssid">SSID</string>
<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_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
+10 -2
View File
@@ -8,8 +8,6 @@
<string name="binary_data">(ორობითი მონაცემები)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d სიმბოლო, %1$s</item>
<item quantity="few">%2$d სიმბოლო, %1$s</item>
<item quantity="many">%2$d სიმბოლო, %1$s</item>
<item quantity="other">%2$d სიმბოლო, %1$s</item>
</plurals>
<string name="error_correction_level">შეცდომების კორექციის დონე</string>
@@ -24,7 +22,9 @@
<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>
@@ -47,6 +47,9 @@
<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>
@@ -82,6 +85,8 @@
<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>
@@ -95,12 +100,15 @@
<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>
+132 -122
View File
@@ -1,8 +1,8 @@
<resources>
<string name="no_camera_no_fun">Deze app kan niet werken zonder cameratoegang. Tot ziens.</string>
<string name="camera_error">De camera kan niet worden geopend. Probeer het opnieuw.</string>
<string name="camera_error">Geen toegang tot camera, probeer opnieuw.</string>
<string name="scan_code">Scan een code</string>
<string name="compose_barcode">Scan een barcode</string>
<string name="compose_barcode">Barcode scannen</string>
<string name="decode_barcode">Barcode decoderen</string>
<string name="content">Inhoud</string>
<string name="binary_data">(binaire data)</string>
@@ -10,151 +10,161 @@
<item quantity="one">%2$d teken, %1$s</item>
<item quantity="other">%2$d tekens, %1$s</item>
</plurals>
<string name="error_correction_level">Foutcorrectieniveau</string>
<string name="error_correction_level">Foutcorrectie niveau</string>
<string name="error_correction_level_l" formatted="false">Laag (~7&#37; correction)</string>
<string name="error_correction_level_m" formatted="false">Gemiddeld (~15&#37; correction)</string>
<string name="error_correction_level_q" formatted="false">Hoger (~25&#37; correction)</string>
<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">Getal toekennen</string>
<string name="issue_number">Uitgiftenummer</string>
<string name="orientation">Oriëntatie</string>
<string name="other_meta_data">Metagegevens</string>
<string name="pdf417_extra_metadata">PDF417-metagegevens</string>
<string name="possible_country">Mogelijk land van herkomst</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="toggle_flash">Flits aan/uit</string>
<string name="upc_ean_extension">UPC EAN extensie</string>
<string name="qr_version">QR version</string>
<string name="toggle_flash">Zaklamp aan/uit</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Delen</string>
<string name="share_as">Delen als?</string>
<string name="copy_to_clipboard">Kopiëren naar klembord</string>
<string name="copied_to_clipboard">De inhoud is gekopieerd naar het klembord</string>
<string name="copy_password">Wachtwoord kopiëren naar klembord</string>
<string name="copied_password_to_clipboard">Het wachtwoord is gekopieerd naar het klembord</string>
<string name="copy_to_clipboard">Naar klembord kopiëren</string>
<string name="copied_to_clipboard">Naar klembord gekopieerd</string>
<string name="copy_password">Kopieer wachtwoord naar klembord</string>
<string name="copied_password_to_clipboard">Wachtwoord gekopieerd naar klembord</string>
<string name="open_url">URL openen</string>
<string name="cannot_resolve_action">Er is geen app aangetroffen die dit kan openen</string>
<string name="cannot_resolve_action">Geen enkele toepassing kan dat openen</string>
<string name="pick_search_engine">Zoekmachine kiezen</string>
<string name="format">Formaat</string>
<string name="size">Grootte, in pixels</string>
<string name="format">Format</string>
<string name="size">Afmeting in pixels</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">Voer hier de inhoud in</string>
<string name="encode">CODEREN</string>
<string name="error_no_content">De inhoud ontbreekt</string>
<string name="error_encoding_barcode">De barcode kan niet worden gegenereerd</string>
<string name="encode">Coderen</string>
<string name="error_no_content">Inhoud ontbreekt</string>
<string name="error_encoding_barcode">Kan geen barcode aanmaken</string>
<string name="view_barcode">Barcode bekijken</string>
<string name="info">Informatie</string>
<string name="switch_camera">Andere camera</string>
<string name="info">Info</string>
<string name="switch_camera">Camera wisselen</string>
<string name="bulk_mode">Continu scannen</string>
<string name="bulk_mode_summary">Blijf continu scannen.</string>
<string name="bulk_mode_delay">Delay between continuous scans</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">Geschiedenis</string>
<string name="preferences">Instellingen</string>
<string name="bulk_mode_summary">Begin altijd continu te scannen</string>
<string name="bulk_mode_delay">Vertraging tussen ononderbroken 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">¼ seconde</string>
<string name="half_second">½ seconde</string>
<string name="a_second">1 seconde</string>
<string name="two_seconds">2 seconden</string>
<string name="five_seconds">5 seconden</string>
<string name="history">Opgeslagen codes</string>
<string name="preferences">Voorkeuren</string>
<string name="scan_category">Scannen</string>
<string name="content_category">Inhoud</string>
<string name="locale_category">Taal</string>
<string name="custom_locale">Andere taal</string>
<string name="follow_system_settings">Systeeminstellingen gebruiken</string>
<string name="show_crop_handle">Bijsnijdhulpmiddel tonen</string>
<string name="show_crop_handle_summary">Beperk scannen tot een aanpasbaar gebied.</string>
<string name="custom_locale">Taal instelling</string>
<string name="follow_system_settings">Systeeminstellingen volgen</string>
<string name="show_crop_handle">Bijsnijd-begrenzer tonen</string>
<string name="show_crop_handle_summary">Scannen beperken tot een aanpasbaar gebied</string>
<string name="barcode_formats">Barcode formats</string>
<string name="zoom_by_swiping">Camera zoomen door omhoog/omlaag te vegen</string>
<string name="zoom_by_swiping_summary">Veeg omhoog of omlaag op het camerascherm om in en uit te zoomen.</string>
<string name="auto_rotate">1D-barcodes verticaal scannen</string>
<string name="auto_rotate_summary">Draai de camera automatisch 1D-barcodes verticaal te scannen. Let op: dit kan van invloed zijn op de prestaties.</string>
<string name="try_harder">Scanner optimaliseren voor juistheid i.p.v. snelheid</string>
<string name="try_harder_summary">Schakel deze optie in voor moeilijk afleesbare codes. Let op: de prestaties leiden hieronder.</string>
<string name="show_toast_in_bulk_mode">Data tonen in continumodus</string>
<string name="show_toast_in_bulk_mode_summary">Toon de gescande data in continumodus.</string>
<string name="vibrate">Trillen na herkennen</string>
<string name="vibrate_summary">Schakel deze optie in als je wilt dat je apparaat trilt na het herkennen van een barcode.</string>
<string name="use_history">Scangeschiedenis bewaren</string>
<string name="use_history_summary">Bewaar herkende codes op je apparaat.</string>
<string name="ignore_consecutive_duplicates">Opeenvolgende duplicaten niet bewaren</string>
<string name="ignore_consecutive_duplicates_summary">Bewaar opeenvolgende duplicaten niet in de scangeschiedenis.</string>
<string name="open_immediately">Inspectie overslaan en inhoud direct tonen</string>
<string name="open_immediately_summary">Sla de inspectie over en open de inhoud direct. Let op: sommige inhoud kan schadelijk zijn.</string>
<string name="copy_immediately">Inhoud automatisch kopiëren naar klembord</string>
<string name="zoom_by_swiping_summary">De zoom van de camera bedienen door in het camerascherm omhoog of omlaag te vegen.</string>
<string name="auto_rotate">1D-barcodes verticaal herkennen</string>
<string name="auto_rotate_summary">Automatisch camerakader draaien om verticale 1D-barcodes te herkennen. Afhankelijk van het toestel beinvloedt dit de prestaties.</string>
<string name="try_harder">Optimaliseer de scanner voor nauwkeurigheid</string>
<string name="try_harder_summary">Activeer deze optie voor zeer moeilijk te lezen codes. Beïnvloedt de prestaties.</string>
<string name="show_toast_in_bulk_mode">Data tonen in continue modus</string>
<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="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>
<string name="ignore_consecutive_duplicates_summary">Bewaar geen opeenvolgende duplicaten in de scangeschiedenis.</string>
<string name="open_immediately">Inhoud direct tonen, zonder inspectie</string>
<string name="open_immediately_summary">Sla inspectie over en open meteen de inhoud. Indien geactiveerd, kan schadelijke inhoud worden geopend.</string>
<string name="copy_immediately">Meteen op klembord zetten</string>
<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">Metagegevens tonen</string>
<string name="show_meta_data_summary">Toon aanvullende gegevens over de gescande barcode.</string>
<string name="show_hex_dump">Hexdump tonen</string>
<string name="show_hex_dump_summary">Toon een hexdump van de gescande inhoud.</string>
<string name="close_automatically">Terugkeren na kopiëren/delen</string>
<string name="close_automatically_summary">Keer automatisch terug naar naar het scanscherm na het kopiëren/delen van een item.</string>
<string name="really_remove_scan">Weet je zeker dat je de scan wilt verwijderen?</string>
<string name="really_remove_all_scans">Weet je zeker dat je de scans wilt verwijderen?</string>
<string name="really_remove_selected_scans">Weet je zeker dat je de selectie wilt verwijderen?</string>
<string name="clear_history">Geschiedenis wissen</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="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>
<string name="always_ask">Altijd vragen</string>
<string name="open_with_url">URL om niet bekende data te openen</string>
<string name="clear_network_suggestions">Network suggesties wissen</string>
<string name="clear_network_suggestions_summary">Verwijder alle netwerksuggesties die eerder door deze app werden gegeven.</string>
<string name="really_remove_all_networks">Echt alle netwerken verwijderen?</string>
<string name="clear_network_suggestions_success">Netwerksuggesties gewist</string>
<string name="clear_network_suggestions_nothing_to_remove">Niets te wissen</string>
<string name="send_category">Doorsturen</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">Stuur elke scan naar URL</string>
<string name="send_scan_type">Type aanvraag voor elke scan</string>
<string name="send_type_get_add_content">GET en gewoon inhoud toevoegen</string>
<string name="send_type_get_query_string">GET met volledige query string</string>
<string name="send_type_post_form">POST toepassing/x-www-form-urlencoded</string>
<string name="send_type_post_json">POST toepassing/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">Scan echt verwijderen?</string>
<string name="really_remove_all_scans">Alle scans echt verwijderen?</string>
<string name="really_remove_selected_scans">Geselecteerde scans verwijderen?</string>
<string name="clear_history">Wis opgeslagen codes</string>
<string name="copy_scan">Scan kopiëren</string>
<string name="edit_scan">Label aanpassen</string>
<string name="edit_scan">Label bewerken</string>
<string name="remove_scan">Scan verwijderen</string>
<string name="enter_name">Geef de scan een naam</string>
<string name="enter_name_hint">Naam</string>
<string name="no_barcode_found">Geen barcode aangetroffen</string>
<string name="separator_line_break">Nieuwe regel</string>
<string name="separator_ruler">Horizontale streep</string>
<string name="save_as_file_name">Opslaan als bestand?</string>
<string name="enter_name">Naam van de scan</string>
<string name="enter_name_hint">Voer een naam in om de scan te beschrijven</string>
<string name="no_barcode_found">Geen barcode gevonden</string>
<string name="pick_list_separator">Hoe lijstitems te scheiden?</string>
<string name="separator_line_break">Regeleinde</string>
<string name="separator_ruler">Koppelteken</string>
<string name="save_as_file_name">Opslaan in Downloads als?</string>
<string name="file_name">Bestandsnaam</string>
<string name="error_file_exists">Het bestand bestaat al</string>
<string name="connect_to_wifi">Verbinden met wifi-netwerk</string>
<string name="wifi_config_failed">Het wifi-netwerk kan niet worden ingesteld</string>
<string name="wifi_added">Het wifi-netwerk is toegevoegd</string>
<string name="sms_send">SMS versturen</string>
<string name="sms_error">De sms kan niet worden verstuurd</string>
<string name="error_saving_file">Kan bestand niet opslaan</string>
<string name="error_file_exists">Bestand bestaat al</string>
<string name="connect_to_wifi">Verbinden met WiFi</string>
<string name="wifi_config_failed">Kan WiFi niet configureren</string>
<string name="wifi_added">WiFi toegevoegd</string>
<string name="sms_send">SMS verzenden</string>
<string name="sms_error">Kan geen SMS verzenden</string>
<string name="tel_dial">Nummer bellen</string>
<string name="tel_error">Het nummer kan niet worden gebeld</string>
<string name="mail_send">E-mail versturen</string>
<string name="mail_error">De e-mail kan niet worden verstuurd</string>
<string name="vcard_add">Toevoegen aan contactpersoon</string>
<string name="vcard_failed">Het toevoegen is mislukt</string>
<string name="vevent_add">Toevoegen aan kalender</string>
<string name="tel_error">Kan geen nummer bellen</string>
<string name="mail_send">E-mail zenden</string>
<string name="mail_error">Kan geen e-mail zenden</string>
<string name="vcard_add">Toevoegen aan contacten</string>
<string name="vcard_failed">Kan niet aan contacten toevoegen</string>
<string name="vevent_add">In kalender zetten</string>
<string name="vevent_failed">Kan niet in kalender gezet</string>
<string name="otpauth_add">2FA toevoegen</string>
<string name="search_web">Zoeken op internet</string>
<string name="search_scan">Scan zoeken</string>
<string name="export_to_file">Exporteren naar bestand</string>
<string name="search_scan">Scan op internet zoeken</string>
<string name="export_to_file">Uitvoer naar bestand</string>
<string name="export_as">Exporteren als?</string>
<string name="export_csv_comma">Kommagescheiden csv-bestand</string>
<string name="export_csv_semicolon">Puntkommagescheiden csv-bestand</string>
<string name="export_json">JSON-bestand</string>
<string name="export_database">SQLite-databank</string>
<string name="error_saving_file">Het bestand kan niet worden opgeslagen</string>
<string name="default_search_engine">Onbekende data openen in</string>
<string name="always_ask">Always ask</string>
<string name="open_with_url">Niet-herkende data met url openen</string>
<string name="clear_network_suggestions">Netwerksuggesties wissen</string>
<string name="clear_network_suggestions_summary">Wis alle eerder getoonde netwerksuggesties.</string>
<string name="really_remove_all_networks">Weet je zeker dat je alle netwerken wilt verwijderen?</string>
<string name="clear_network_suggestions_success">De netwersuggesties zijn gewist</string>
<string name="clear_network_suggestions_nothing_to_remove">Er valt niks te wissen</string>
<string name="send_category">Doorsturen</string>
<string name="send_scan_url">Elke scan doorsturen naar url</string>
<string name="send_scan_type">Soort verzoek van elke scan</string>
<string name="send_type_get_add_content">GET met toegevoegde inhoud</string>
<string name="send_type_get_query_string">GET met volledige opvraging</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="test_url">URL testen</string>
<string name="pick_list_separator">Hoe moeten lijstonderdelen worden gescheiden?</string>
<string name="saved_in_downloads">Opgeslagen in downloadmap</string>
<string name="vevent_failed">Toevoegen mislukt</string>
<string name="export_csv_comma">CSV bestand met komma\'s</string>
<string name="export_csv_semicolon">CSV bestand met puntkomma\'s</string>
<string name="export_json">JSON bestand</string>
<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="pick_file">Kies een afbeeldingsbestand</string>
<string name="pick_code_to_scan">Kies de te scannen code</string>
<string name="shortcut_decode">Barcode scannen</string>
<string name="shortcut_encode">Barcode genereren</string>
<string name="shortcut_preferences">Instellingen</string>
<string name="background_request_failed">Het achtergrondverzoek is mislukt</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>
<string name="shortcut_encode">Een barcode aanmaken</string>
<string name="shortcut_preferences">Voorkeuren</string>
<string name="background_request_failed">Achtergrondverzoek mislukt</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="wifi_network">WiFi netwerk</string>
<string name="wifi_ssid">Naam</string>
<string name="wifi_type">Authenticatie type</string>
<string name="wifi_password">Wachtwoord</string>
<string name="wifi_hidden">Verborgen netwerk</string>
<string name="wifi_eap">EAP methode</string>
<string name="wifi_anonymous_identity">Anonieme identiteit</string>
<string name="wifi_identity">Identiteit</string>
<string name="wifi_phase2">Phase 2 methode</string>
</resources>
+71 -61
View File
@@ -8,7 +8,7 @@
<string name="vevent_add">Dodaj do kalendarza</string>
<string name="shortcut_preferences">Ustawienia</string>
<string name="share">Udostępnij</string>
<string name="share_as">Share as?</string>
<string name="share_as">Udostępnij jako?</string>
<string name="error_saving_file">Nie można zapisać pliku</string>
<string name="clear_history">Wyczyść historię</string>
<string name="compose_barcode">Utwórz kod kreskowy</string>
@@ -26,12 +26,12 @@
<string name="separator_ruler">Linijka</string>
<string name="scan_code">Skanuj kod</string>
<string name="error_correction_level">Poziom korekcji błędów</string>
<string name="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="error_correction_level_l" formatted="false">Niski (~7&#37; korekcji)</string>
<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="export_csv_comma">CSV z przecinkami</string>
<string name="export_csv_semicolon">CSV z średnikami</string>
<string name="export_csv_semicolon">CSV ze średnikami</string>
<string name="shortcut_encode">Stwórz kod kreskowy</string>
<string name="error_file_exists">Plik już istnieje</string>
<string name="no_barcode_found">Nie znaleziono kodu kreskowego</string>
@@ -56,24 +56,30 @@
<string name="really_remove_selected_scans">Czy naprawdę usunąć wybrane skany?</string>
<string name="binary_data">(dane binarne)</string>
<string name="show_hex_dump">Pokazuj zrzut szesnastkowy</string>
<string name="show_hex_dump_summary">Show a hex dump of the scanned contents.</string>
<string name="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="show_hex_dump_summary">Pokaż zeskanowaną zawartośc w postaci szesnastkowej</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">Show additional data about the scanned barcoded.</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">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="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">Skanuj w sposób ciągły</string>
<string name="bulk_mode_summary">Zawsze rozpoczynaj skanowanie w sposób ciągły.</string>
<string name="bulk_mode_delay">Opóźnienie między kolejnymi skanami</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">Ćwierć sekundy</string>
<string name="half_second">Pół sekundy</string>
<string name="a_second">Sekunda</string>
<string name="two_seconds">Dwie sekundy</string>
<string name="five_seconds">Pięć sekund</string>
<string name="toggle_flash">Przełącz lampę błyskową</string>
<string name="error_flash">Error toggling flash</string>
<string name="wifi_added">Wi-Fi dodane</string>
<string name="zoom_by_swiping">Przybliżaj kamerę, przesuwając w górę/dół</string>
<string name="zoom_by_swiping_summary">Swipe up or down in camera screen to control the camera zoom.</string>
<string name="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>
@@ -83,74 +89,78 @@
<string name="separator_line_break">Przerwanie linii</string>
<string name="shortcut_decode">Zeskanuj kod kreskowy</string>
<string name="use_history">Zapisuj historię skanowania</string>
<string name="use_history_summary">Save recognized codes on your device.</string>
<string name="use_history_summary">Zapisz rozpoznane kody na swoim urządzeniu.</string>
<string name="vibrate">Wibruj po wykryciu</string>
<string name="vibrate_summary">Enable this if you want your device to vibrate when a code is recognized.</string>
<string name="vibrate_summary">Włącz tę opcję, jeśli chcesz, aby urządzenie wibrowało po rozpoznaniu kodu.</string>
<string name="open_immediately">Pomiń kontrolę i natychmiast otwórz zawartość</string>
<string name="open_immediately_summary">Skip inspection and open contents immediately. May open harmful content if enabled.</string>
<string name="copy_immediately">Automatically copy contents into clipboard</string>
<string name="copy_immediately_summary">Automatically copy scanned contents into clipboard. Please note that other apps may snoop on your clipboard in the background.</string>
<string name="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>
<string name="copy_immediately_summary">Automatycznie skopiuj zeskanowaną zawartość do schowka. Pamiętaj, że inne aplikacje mogą szpiegować Twój schowek w tle.</string>
<string name="show_crop_handle">Pokazuj ogranicznik przycinania</string>
<string name="show_crop_handle_summary">Restrict scanning to a customizable region.</string>
<string name="barcode_formats">Barcode formats</string>
<string name="show_crop_handle_summary">Ogranicz skanowanie do konfigurowalnego regionu.</string>
<string name="barcode_formats">Formaty kodów</string>
<string name="search_web">Szukaj w sieci</string>
<string name="search_scan">Szukaj skanu</string>
<string name="export_database">Eksportuj do bazy danych SQLite</string>
<string name="ignore_consecutive_duplicates">Nie zapisuj kolejnych duplikatów</string>
<string name="ignore_consecutive_duplicates_summary">Do not save consecutive duplicates in the scan history.</string>
<string name="default_search_engine">Open unknown data in</string>
<string name="always_ask">Always ask</string>
<string name="ignore_consecutive_duplicates_summary">Nie zapisuj kolejnych duplikatów w historii skanowania.</string>
<string name="default_search_engine">Otwórz nieznane dane w</string>
<string name="always_ask">Zawsze pytaj</string>
<string name="open_with_url">Otwieraj nieznane dane za pomocą adresu 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">Forwarding</string>
<string name="send_scan_url">Send every scan to URL</string>
<string name="send_scan_type">Type of request for every scan</string>
<string name="send_type_get_add_content">GET and simply add content</string>
<string name="send_type_get_query_string">GET with compelete query string</string>
<string name="clear_network_suggestions">Wyczyść sugestie z sieci</string>
<string name="clear_network_suggestions_summary">Usuń wszystkie sugestie z sieci, które były wcześniej dostarczane przez tę aplikację.</string>
<string name="really_remove_all_networks">Naprawdę usunąć wszystkie sieci?</string>
<string name="clear_network_suggestions_success">Sugestie dotyczące sieci zostały usunięte</string>
<string name="clear_network_suggestions_nothing_to_remove">Nie ma nic do usunięcia</string>
<string name="send_category">Przekazywanie</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">Wyślij każdy skan na adres URL</string>
<string name="send_scan_type">Rodzaj requestu dla każdego skanu</string>
<string name="send_type_get_add_content">GET i po prostu dodaj zawartość</string>
<string name="send_type_get_query_string">GET z kompletnym query</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="test_url">Test URL</string>
<string name="copy_password">Copy password into clipboard</string>
<string name="send_type_external_browser">Otwórz w zewnętrznej przeglądarce</string>
<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="preferences">Ustawienia</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="scan_category">Skanowanie</string>
<string name="content_category">Zawarość</string>
<string name="locale_category">Język</string>
<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="encode">ZAKODUJ</string>
<string name="error_no_content">Brak zawartości</string>
<string name="try_harder">Zoptymalizuj czytnik pod kątem dokładności, a nie prędkości</string>
<string name="try_harder_summary">Enable this option for very hard to read codes. Will affect performance.</string>
<string name="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="try_harder_summary">Włącz tę opcję w przypadku bardzo trudnych do odczytania kodów. Wpłynie na wydajność.</string>
<string name="show_toast_in_bulk_mode">Pokaż dane w trybie ciągłym</string>
<string name="show_toast_in_bulk_mode_summary">Zwięźle pokazuje zeskanowane dane podczas skanowania ciągłego.</string>
<string name="cannot_resolve_action">Żadna aplikacja nie może tego otworzyć</string>
<string name="width_by_height">%1$d×%2$d</string>
<string name="input_content_here">Wprowadź zawartość tutaj</string>
<string name="pick_list_separator">Jak oddzielić elementy listy?</string>
<string name="enter_name">Wprowadź nazwę opisującą skan</string>
<string name="auto_rotate">Rozpoznawaj kody kreskowe 1D pionowo</string>
<string name="auto_rotate_summary">Automatically rotate the camera frame to recognize vertical 1D barcodes. Depending on the device, this may affect performance.</string>
<string name="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="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="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>
<string name="wifi_ssid">Nazwa</string>
<string name="wifi_type">Typ uwierzytelnienia</string>
<string name="wifi_password">Hasło</string>
<string name="wifi_hidden">Sieć ukryta</string>
<string name="wifi_eap">Metoda EAP</string>
<string name="wifi_anonymous_identity">Anonimowa tożsamość</string>
<string name="wifi_identity">Tożsamość</string>
<string name="wifi_phase2">Metoda fazy 2</string>
</resources>
+87 -77
View File
@@ -1,11 +1,11 @@
<resources>
<string name="no_camera_no_fun">Não faz nenhum sentido usar este aplicativo sem acesso à câmera. Tchau.</string>
<string name="no_camera_no_fun">Infelizmente você não poderá usar este app sem conceder o 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="compose_barcode">Criar código</string>
<string name="decode_barcode">Decodificar código de barras</string>
<string name="decode_barcode">Reconhecer código</string>
<string name="content">Conteúdo</string>
<string name="binary_data">(binários)</string>
<string name="binary_data">(dados binários)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d caractere, %1$s</item>
<item quantity="other">%2$d caracteres, %1$s</item>
@@ -22,29 +22,34 @@
<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">Versão do QR</string>
<string name="toggle_flash">Ativar 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="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 URL</string>
<string name="cannot_resolve_action">Nenhuma aplicativo pode abrir isso</string>
<string name="pick_search_engine">Escolha um site de busca</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="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 um conteúdo aqui</string>
<string name="input_content_here">Digite 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 de barras</string>
<string name="view_barcode">Ver código de barras</string>
<string name="info">Informações</string>
<string name="error_encoding_barcode">Não foi possível gerar o 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">Escanear continuamente</string>
<string name="bulk_mode_summary">Sempre comece em modo contínuo.</string>
<string name="bulk_mode_delay">Atrasar em escaneamentos contínuos</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 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>
@@ -52,101 +57,106 @@
<string name="five_seconds">Cinco segundos</string>
<string name="history">Histórico</string>
<string name="preferences">Preferências</string>
<string name="scan_category">Escanear</string>
<string name="scan_category">Digitalização</string>
<string name="content_category">Conteúdo</string>
<string name="locale_category">Idioma</string>
<string name="custom_locale">Idioma personalizado</string>
<string name="follow_system_settings">Seguir configurações do sistema</string>
<string name="show_crop_handle">Mostrar limitador de corte</string>
<string name="show_crop_handle_summary">Restringir escaneamento a uma área personalizável.</string>
<string name="barcode_formats">Formatos de código de barras</string>
<string name="zoom_by_swiping">Deslize para baixo/cima para usar zoom</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 customizável</string>
<string name="show_crop_handle_summary">Permite limitar a uma área específica.</string>
<string name="barcode_formats">Tipos 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ódigo de barras 1D vertical</string>
<string name="auto_rotate_summary">Girar automaticamente a posição da câmera para reconhecer código de barras 1D vertical. Dependendo do dispositivo, isto pode afetar o desempenho.</string>
<string name="try_harder">Otimizar o leitor para precisão, não velocidade</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_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 escaneados durante escaneamento contínuo.</string>
<string name="vibrate">Vibrar na detecção</string>
<string name="vibrate_summary">Ative isto 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="use_history_summary">Salve códigos reconhecidos em seu dispositivo.</string>
<string name="ignore_consecutive_duplicates">Ignorar duplicatas consecutivas</string>
<string name="ignore_consecutive_duplicates_summary">Não salvar duplicatas consecutivas no histórico de escaneamentos.</string>
<string name="open_immediately">Abrir conteúdo imediatamente</string>
<string name="open_immediately_summary">Pular a inspeção e abrir o conteúdo imediatamente. Pode abrir conteúdo nocivo, se ativado.</string>
<string name="copy_immediately">Copiar ao Clipboard</string>
<string name="copy_immediately_summary">Copiar automaticamente o conteúdo escaneado ao Clipboard. Observe que outros aplicativos podem examinar seu Clipboard em segundo plano.</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 esta opção se quiser que seu dispositivo vibre quando um código for reconhecido.</string>
<string name="use_history">Salvar 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 digitalizações.</string>
<string name="open_immediately">Abrir imediatamente</string>
<string name="open_immediately_summary">Pular a inspeção e abrir o 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 ao clipboard o conteúdo digitalizado. 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 sobre o código de barras escaneado.</string>
<string name="show_meta_data_summary">Mostrar dados adicionais de código digitalizado.</string>
<string name="show_qr_version">Mostrar a versão do QR</string>
<string name="show_qr_version_summary">Mostrar o número de versão do código QR.</string>
<string name="show_hex_dump">Mostrar impressão hexadecimal</string>
<string name="show_hex_dump_summary">Mostrar uma impressão hexadecimal do conteúdo escaneado.</string>
<string name="close_automatically">Voltar depois de Copiar/Compartilhar</string>
<string name="close_automatically_summary">Voltar automaticamente à tela de digitalização após copiar ou compartilhar o conteúdo visualizado.</string>
<string name="show_hex_dump_summary">Mostrar a impressão hexadecimal do conteúdo digitalizado.</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 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 com URL</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 fornecidas anteriormente por este aplicativo.</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="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">Encaminhar</string>
<string name="send_scan_url">Enviar cada escaneamento para URL</string>
<string name="send_scan_type">Tipo de pedido para cada escaneamento</string>
<string name="send_type_get_add_content">GET e simplesmente adicionar conteúdo</string>
<string name="send_type_get_query_string">GET com cadeia de consulta completa</string>
<string name="send_category">Encaminhamento</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 somente adicionar o conteúdo</string>
<string name="send_type_get_query_string">GET com sequência completa da 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="test_url">Testar URL</string>
<string name="really_remove_scan">Realmente quer remover o 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="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 esta digitalização?</string>
<string name="really_remove_all_scans">Realmente quer remover todas as digitalizações?</string>
<string name="really_remove_selected_scans">Realmente remover digitalizações selecionados?</string>
<string name="clear_history">Limpar histórico</string>
<string name="copy_scan">Copiar escaneamento</string>
<string name="edit_scan">Editar ID</string>
<string name="remove_scan">Remover escaneamento</string>
<string name="enter_name">Digite um nome para descrever o escaneamento</string>
<string name="enter_name_hint">Nome do escaneamento</string>
<string name="no_barcode_found">Nenhum código de barras encontrado</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_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 arquivo 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_file_exists">Arquivo já existe</string>
<string name="connect_to_wifi">Conectar para o WiFi</string>
<string name="wifi_config_failed">Não foi possível configurar o WiFi</string>
<string name="connect_to_wifi">Conectar via 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">Enviar SMS</string>
<string name="sms_error">Não foi possível enviar o SMS</string>
<string name="tel_dial">Discar número</string>
<string name="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 o número</string>
<string name="mail_send">Enviar e-mail</string>
<string name="mail_send">Envie e-mail</string>
<string name="mail_error">Não foi possível enviar o e-mail</string>
<string name="vcard_add">Adicionar para os contatos</string>
<string name="vcard_failed">Não foi possível adicionar para os contatos</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 escaneamentos</string>
<string name="search_scan">Pesquisar em conteúdo já digitalizado</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="pick_file">Escolha um arquivo de imagem</string>
<string name="pick_code_to_scan">Escolha o código para escanear</string>
<string name="shortcut_decode">Escanear um código de barras</string>
<string name="shortcut_encode">Criar um código</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>
<string name="shortcut_encode">Criar código</string>
<string name="shortcut_preferences">Configurações</string>
<string name="background_request_failed">A solicitação de segundo plano falhou</string>
<string name="background_request_failed">A solicitação em segundo plano falhou</string>
<string name="entry_type">Tipo</string>
<string name="wifi_network">Rede Wi-Fi</string>
<string name="wifi_ssid">Nome</string>
+15 -5
View File
@@ -24,7 +24,9 @@
<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">Ошибка при переключении вспышки</string>
<string name="share">Поделиться</string>
<string name="share_as">Поделиться как?</string>
<string name="copy_to_clipboard">Скопировать в буфер обмена</string>
@@ -47,6 +49,9 @@
<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>
@@ -74,14 +79,16 @@
<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="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">Показывать версию 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="close_automatically">Возврат после копирования/обмена</string>
@@ -95,12 +102,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_url">Отправлять сканированные штрих-коды на 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_post_form">POST-приложение/x-www-form-urlencoded</string>
<string name="send_type_post_json">POST-приложение/json</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>
+10
View File
@@ -22,7 +22,9 @@
<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="toggle_flash">Flaşı aç</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Paylaş</string>
<string name="share_as">Şöyle paylaş:</string>
<string name="copy_to_clipboard">Panoya kopyala</string>
@@ -45,6 +47,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="quarter_second">Çeyrek saniye</string>
<string name="half_second">Yarım saniye</string>
<string name="a_second">Bir saniye</string>
@@ -80,6 +85,8 @@
<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="close_automatically">Kopyala/Paylaş\'tan sonra geri dön</string>
@@ -93,12 +100,15 @@
<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_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>
<string name="send_type_get_query_string">GET ile tam sorgu dizgesi</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">Harici tarayıcıda aç</string>
<string name="test_url">URL\'yi sına</string>
<string name="really_remove_scan">Tarama gerçekten silinsin mi?</string>
<string name="really_remove_all_scans">Tüm taramalar gerçekten silinsin mi?</string>
+10
View File
@@ -23,7 +23,9 @@
<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">Поділитися як?</string>
<string name="copy_to_clipboard">Копіювати у буфер обміну</string>
@@ -46,6 +48,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="quarter_second">Чверть секунди</string>
<string name="half_second">Півсекунди</string>
<string name="a_second">Одна секунда</string>
@@ -81,6 +86,8 @@
<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="close_automatically">Повернутися після копіювання/поширення</string>
@@ -94,12 +101,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_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">Відкрити у зовнішньому браузері</string>
<string name="test_url">Перевірити URL</string>
<string name="really_remove_scan">Дійсно видалити сканування?</string>
<string name="really_remove_all_scans">Дійсно видалити всі сканування?</string>
+10 -1
View File
@@ -7,7 +7,6 @@
<string name="content">Nội dung</string>
<string name="binary_data">(thông tin dạng nhị phân)</string>
<plurals name="barcode_info">
<item quantity="one">%2$d ký tự, %1$s</item>
<item quantity="other">%2$d ký tự, %1$s</item>
</plurals>
<string name="error_correction_level">Mức độ tự sửa mã</string>
@@ -22,7 +21,9 @@
<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="toggle_flash">Bật/tắt đèn</string>
<string name="error_flash">Error toggling flash</string>
<string name="share">Chia sẻ</string>
<string name="share_as">Chia sẻ dưới định dạng?</string>
<string name="copy_to_clipboard">Sao chép</string>
@@ -45,6 +46,9 @@
<string name="bulk_mode">Quét liên tục</string>
<string name="bulk_mode_summary">Luôn quét liên tục.</string>
<string name="bulk_mode_delay">Thời gian giữa các lần quét</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">Một phần tư giây</string>
<string name="half_second">Nửa giây</string>
<string name="a_second">Một giây</string>
@@ -80,6 +84,8 @@
<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="close_automatically">Quay lại sau khi Sao chép/Chia sẻ</string>
@@ -93,12 +99,15 @@
<string name="clear_network_suggestions_success">Gợi ý mạng đã xoá</string>
<string name="clear_network_suggestions_nothing_to_remove">Không còn gì để xoá</string>
<string name="send_category">Chuyển tới</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">Gửi tất cả mã quét được đến URL</string>
<string name="send_scan_type">Kiểu yêu cầu đối với mỗi lần quét</string>
<string name="send_type_get_add_content">GET và chỉ thêm nội dung</string>
<string name="send_type_get_query_string">GET với xâu truy vấn đầy đủ</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">URL thử</string>
<string name="really_remove_scan">Thật sự xoá lần quét này?</string>
<string name="really_remove_all_scans">Thật sự xoá tất cả các lần quét?</string>
+67 -57
View File
@@ -1,35 +1,37 @@
<resources>
<string name="no_camera_no_fun">给我相机权限,不给你扫了,哼</string>
<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="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="other">%2$d 字符, %1$s</item>
</plurals>
<string name="error_correction_level">纠错级别</string>
<string name="error_correction_level_l" formatted="false"> (~7&#37; correction)</string>
<string name="error_correction_level_m" formatted="false"> (~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"> (~30&#37; correction)</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="suggested_price">建议价格</string>
<string name="upc_ean_extension">UPC EAN 扩展</string>
<string name="qr_version">QR 版本</string>
<string name="toggle_flash">开关闪光灯</string>
<string name="error_flash">开关闪光灯出错</string>
<string name="share">分享</string>
<string name="share_as">以何种方式分享?</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">没有相关APP可以打开它</string>
<string name="cannot_resolve_action">没有应用可以打开它</string>
<string name="pick_search_engine">选择一个搜索引擎</string>
<string name="format">编码格式</string>
<string name="size">图片尺寸</string>
@@ -37,18 +39,21 @@
<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="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">Delay between continuous scans</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">连续扫描之间的延迟</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>
@@ -56,19 +61,19 @@
<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">限制扫描范围</string>
<string name="show_crop_handle_summary">把扫描区域限制在选定范围内</string>
<string name="barcode_formats">Barcode formats</string>
<string name="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="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">识别时震动</string>
<string name="vibrate_summary">如果你希望在识别到条码后震动设备,请启用该选项。</string>
<string name="use_history">保存扫描历史</string>
<string name="use_history_summary">在本地保存扫描历史</string>
<string name="ignore_consecutive_duplicates">不保存重复历史</string>
@@ -76,28 +81,33 @@
<string name="open_immediately">不查看内容立即打开</string>
<string name="open_immediately_summary">可能会打开有害内容</string>
<string name="copy_immediately">自动复制扫描结果到剪贴板</string>
<string name="copy_immediately_summary">注意其他APP可能会在后台监控剪贴板</string>
<string name="copy_immediately_summary">注意其他 APP 可能会在后台监控剪贴板</string>
<string name="show_meta_data">显示元数据</string>
<string name="show_meta_data_summary">显示已扫描条码的额外数据</string>
<string name="show_meta_data_summary">显示已扫描条码的额外数据</string>
<string name="show_qr_version">显示 QR 版本</string>
<string name="show_qr_version_summary">显示 QR Code 的版本号</string>
<string name="show_hex_dump">显示16进制数据</string>
<string name="show_hex_dump_summary">显示已扫描条码的16进制数据</string>
<string name="show_hex_dump_summary">显示已扫描条码的16进制数据</string>
<string name="close_automatically">复制/分享后自动返回</string>
<string name="close_automatically_summary">复制或分享读取的内容后自动返回扫描主界面。</string>
<string name="default_search_engine">Open unknown data in</string>
<string name="always_ask">Always ask</string>
<string name="open_with_url">使用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="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_url">将每个扫描结果发送到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">在外部浏览器中打开</string>
<string name="test_url">测试 URL</string>
<string name="really_remove_scan">确定删除记录?</string>
<string name="really_remove_all_scans">确定删除全部记录?</string>
@@ -108,7 +118,7 @@
<string name="remove_scan">删除所选记录</string>
<string name="enter_name">输入名称</string>
<string name="enter_name_hint">扫描描述</string>
<string name="no_barcode_found">未找到条</string>
<string name="no_barcode_found">未找到条码</string>
<string name="pick_list_separator">如何分隔列表项?</string>
<string name="separator_line_break">换行符</string>
<string name="separator_ruler">分割线</string>
@@ -116,9 +126,9 @@
<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="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>
@@ -134,26 +144,26 @@
<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_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="pick_file">选择图片文件</string>
<string name="pick_code_to_scan">选择扫描编码</string>
<string name="shortcut_decode">扫描条</string>
<string name="shortcut_encode">创建条</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="entry_type">类型</string>
<string name="wifi_network">Wi-Fi 网络</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">阶段 2 方法</string>
</resources>
+54 -45
View File
@@ -1,14 +1,13 @@
<resources>
<string name="no_camera_no_fun">沒有相機權限的話,這個程式根本什麽都做不了。 再見!</string>
<string name="no_camera_no_fun">沒有相機權限的話,這個程式根本什麽都做不了。再見!</string>
<string name="camera_error">不能開啓相機,請重試</string>
<string name="scan_code">掃描條碼</string>
<string name="compose_barcode">製作條碼</string>
<string name="decode_barcode">解讀條碼</string>
<string name="content">内容</string>
<string name="binary_data">(2 進制碼)</string>
<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>
<item quantity="other">%2$d 個字元,%1$s</item>
</plurals>
<string name="error_correction_level">糾錯等級</string>
<string name="error_correction_level_l" formatted="false">低 (~7&#37; 準確度)</string>
@@ -19,10 +18,12 @@
<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="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">以何種方式分享?</string>
<string name="copy_to_clipboard">複製到剪貼簿</string>
@@ -43,13 +44,16 @@
<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">Delay between continuous scans</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">始終開啟連續掃描</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="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>
@@ -57,34 +61,36 @@
<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">Barcode formats</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="zoom_by_swiping_summary">通過上下滑動在掃描界面控制相機縮放</string>
<string name="auto_rotate">識別豎直的 1D 條碼</string>
<string name="auto_rotate_summary">自動旋轉相機以識別豎直的 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="use_history">儲存掃描記錄</string>
<string name="use_history_summary">在本機儲存掃描記錄</string>
<string name="use_history_summary">在本機儲存掃描記錄</string>
<string name="ignore_consecutive_duplicates">不儲存重複歷史記錄</string>
<string name="ignore_consecutive_duplicates_summary">在掃描歷史中不儲存重複項目</string>
<string name="ignore_consecutive_duplicates_summary">在掃描歷史中不儲存連續的重複項目</string>
<string name="open_immediately">立即開啟</string>
<string name="open_immediately_summary">跳過檢查並立即開啟內容。 如果啟用,可能會開啟有害內容。</string>
<string name="open_immediately_summary">跳過檢查並立即開啟內容。如果啟用,可能會開啟有害內容。</string>
<string name="copy_immediately">自動複製掃描結果到剪貼簿</string>
<string name="copy_immediately_summary">自動將掃描的內容複製到剪貼簿。 請注意,其他 App 可能會在背景監控剪貼簿。</string>
<string name="copy_immediately_summary">自動將掃描的內容複製到剪貼簿。請注意,其他 App 可能會在背景監控剪貼簿。</string>
<string name="show_meta_data">顯示 Metadata</string>
<string name="show_meta_data_summary">顯示已掃描條碼的額外資訊</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_hex_dump_summary">顯示已掃描條碼的 Hex dump</string>
<string name="close_automatically">複製/分享後自動返回</string>
<string name="close_automatically_summary">複製或分享讀取的內容後自動返回掃描主要界面。</string>
<string name="default_search_engine">開啟未知資料</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>
@@ -93,12 +99,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_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="test_url">測試 URL</string>
<string name="really_remove_scan">確定刪除記錄?</string>
<string name="really_remove_all_scans">確定刪除全部掃描記錄?</string>
@@ -111,9 +120,9 @@
<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_line_break">換行符</string>
<string name="separator_ruler">分割線</string>
<string name="save_as_file_name">儲存為檔案?</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>
@@ -128,33 +137,33 @@
<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="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="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="rotate_image_cw">順時針旋轉圖片</string>
<string name="pick_file">選擇圖片檔案</string>
<string name="pick_code_to_scan">選擇掃描</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="entry_type">類型</string>
<string name="wifi_network">Wi-Fi 網路</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 method</string>
<string name="wifi_anonymous_identity">Anonymous identity</string>
<string name="wifi_identity">Identity</string>
<string name="wifi_anonymous_identity">匿名身分</string>
<string name="wifi_identity">身分</string>
<string name="wifi_phase2">Phase 2 method</string>
</resources>
+2 -2
View File
@@ -10,8 +10,8 @@
<item>Italian</item>
<item>Georgian</item>
<item>Dutch</item>
<item>Polish</item>
<item>Portuguese (Brazil)</item>
<item>Polski</item>
<item>Português do Brasil</item>
<item>Russian</item>
<item>Turkish</item>
<item>Ukrainian</item>
+2
View File
@@ -4,11 +4,13 @@
<item>@string/send_type_get_query_string</item>
<item>@string/send_type_post_form</item>
<item>@string/send_type_post_json</item>
<item>@string/send_type_external_browser</item>
</string-array>
<string-array name="send_type_values">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
</string-array>
</resources>
+13 -3
View File
@@ -22,7 +22,9 @@
<string name="possible_country">Possible country of manufacture</string>
<string name="suggested_price">Suggested price</string>
<string name="upc_ean_extension">UPC EAN extension</string>
<string name="qr_version">QR version</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>
@@ -45,6 +47,9 @@
<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>
@@ -80,6 +85,8 @@
<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_qr_version">Show QR version</string>
<string name="show_qr_version_summary">Show QR version number.</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="close_automatically">Go back after Copy/Share</string>
@@ -93,12 +100,15 @@
<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_url">Send every scan to URL</string>
<string name="send_scan_type">Type of request for every scan</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 compelete query string</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>
+10
View File
@@ -66,6 +66,11 @@
android:summary="@string/copy_immediately_summary"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/send_category">
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="send_scan_active"
android:title="@string/send_scan_active"
android:summary="@string/send_scan_active_summary"/>
<de.markusfisch.android.binaryeye.preference.UrlPreference
android:key="send_scan_url"
android:title="@string/send_scan_url"/>
@@ -87,6 +92,11 @@
android:key="show_meta_data"
android:title="@string/show_meta_data"
android:summary="@string/show_meta_data_summary"/>
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="false"
android:key="show_qr_version"
android:title="@string/show_qr_version"
android:summary="@string/show_qr_version_summary"/>
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="show_hex_dump"
@@ -0,0 +1,8 @@
<data-extraction-rules>
<cloud-backup>
<include domain="root" path="."/>
</cloud-backup>
<device-transfer>
<include domain="root" path="."/>
</device-transfer>
</data-extraction-rules>
+10
View File
@@ -61,6 +61,11 @@
android:summary="@string/copy_immediately_summary"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/send_category">
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="send_scan_active"
android:title="@string/send_scan_active"
android:summary="@string/send_scan_active_summary"/>
<de.markusfisch.android.binaryeye.preference.UrlPreference
android:key="send_scan_url"
android:title="@string/send_scan_url"/>
@@ -82,6 +87,11 @@
android:key="show_meta_data"
android:title="@string/show_meta_data"
android:summary="@string/show_meta_data_summary"/>
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="false"
android:key="show_qr_version"
android:title="@string/show_qr_version"
android:summary="@string/show_qr_version_summary"/>
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="show_hex_dump"
@@ -0,0 +1,43 @@
package de.markusfisch.android.binaryeye.actions.mail
import junit.framework.TestCase.assertEquals
import org.junit.Test
class MatMsgTest {
@Test
fun to() {
val mm = MatMsg(
"MATMSG:TO:someone@example.org;;"
)
assertEquals(mm.to, "someone@example.org")
}
@Test
fun toSub() {
val mm = MatMsg(
"MATMSG:TO:someone@example.org;SUB:Stuff;;"
)
assertEquals(mm.to, "someone@example.org")
assertEquals(mm.sub, "Stuff")
}
@Test
fun toSubBody() {
val mm = MatMsg(
"MATMSG:TO:someone@example.org;SUB:Stuff;BODY:This is some text;;"
)
assertEquals(mm.to, "someone@example.org")
assertEquals(mm.sub, "Stuff")
assertEquals(mm.body, "This is some text")
}
@Test
fun differentOrder() {
val mm = MatMsg(
"MATMSG:SUB:Stuff;BODY:This is some text;TO:someone@example.org;;"
)
assertEquals(mm.to, "someone@example.org")
assertEquals(mm.sub, "Stuff")
assertEquals(mm.body, "This is some text")
}
}
@@ -1,6 +1,5 @@
package de.markusfisch.android.binaryeye.actions.vtype
import de.markusfisch.android.binaryeye.simpleFail
import junit.framework.TestCase.*
import org.junit.Test
@@ -0,0 +1,74 @@
package de.markusfisch.android.binaryeye.actions.web
import junit.framework.TestCase.*
import org.junit.Test
class WebTest {
@Test
fun correct() {
val urls = listOf(
"https://google.com",
"https://markusfisch.de",
"http://markusfisch.de",
"http://www.markusfisch.de",
"http://www.markusfisch.de/",
"http://www.markusfisch.de/?",
"http://www.markusfisch.de/?foo=bar",
"https://markusfisch.de/foo",
"https://markusfisch.de/foo#bar",
"https://foo.example.com/",
"http://example.com/",
)
for (url in urls) {
assertEquals(url, resolve(url))
}
}
@Test
fun colloquial() {
val urls = listOf(
"google.com",
"GOOGLE.com",
"GOOGLE.COM",
" foo.com",
"foo.com ",
" foo.com ",
" foo.com ",
"foo.com",
"foo.com/bar",
"foo.com?bar",
"foo.com#bar",
)
for (url in urls) {
assertEquals(url, resolve(url))
}
}
@Test
fun noUrls() {
val urls = listOf(
"",
"foo",
"foo . bar",
"exa mple.com",
"example.co m",
"some string",
"some string.",
".foo",
"..foo",
"...foo",
"foo.",
"foo..",
"foo...",
"foo. foo",
)
for (url in urls) {
assertEquals(null, resolve(url))
}
}
}
private fun resolve(s: String) = if (
WebAction.canExecuteOn(s.toByteArray())
) s else null
+3 -4
View File
@@ -1,9 +1,8 @@
buildscript {
ext {
kotlin_version = '1.6.0'
tools_version = '7.0.3'
build_tools_version = '30.0.2'
sdk_version = 30
kotlin_version = '1.6.21'
tools_version = '7.2.0'
sdk_version = 32
support_version = '25.3.1'
}

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