Compare commits

...

113 Commits

Author SHA1 Message Date
Renovate Bot
83e2cf733e Update plugin com.autonomousapps.dependency-analysis to v2.7.0 2025-01-12 01:02:04 +00:00
Renovate Bot
3214d772b2 Update plugin com.android.library to v8.8.0 2025-01-11 01:02:20 +00:00
Renovate Bot
40c3f39c49 Update plugin com.android.application to v8.8.0 2025-01-10 01:01:23 +00:00
Renovate Bot
6215ffa7b6 Update dependency com.android.tools:desugar_jdk_libs_nio to v2.1.4 2024-12-21 01:03:13 +00:00
Renovate Bot
bf073da67b Update dependency gradle to v8.12 2024-12-21 01:03:03 +00:00
Renovate Bot
49fe5ca037 Update dependency androidx.camera:camera-view to v1.4.1 2024-12-15 01:02:20 +00:00
Renovate Bot
62f854db27 Update plugin com.autonomousapps.dependency-analysis to v2.6.1 2024-12-15 01:02:08 +00:00
Renovate Bot
aea6fa6c69 Update dependency androidx.camera:camera-lifecycle to v1.4.1 2024-12-14 07:46:37 +00:00
Renovate Bot
029a1fcde7 Update dependency androidx.camera:camera-camera2 to v1.4.1 2024-12-12 01:01:07 +00:00
Renovate Bot
92c99bec22 Update plugin com.android.library to v8.7.3 2024-12-08 01:02:45 +00:00
Renovate Bot
663c1236a4 Update plugin com.autonomousapps.dependency-analysis to v2.6.0 2024-12-07 01:05:26 +00:00
Renovate Bot
a9582ffb05 Update plugin com.android.application to v8.7.3 2024-12-03 03:27:24 +00:00
Renovate Bot
b11fb89bd9 Update plugin org.jetbrains.kotlin.plugin.serialization to v2.1.0 2024-11-30 01:05:21 +00:00
Renovate Bot
1e6bebe853 Update plugin org.jetbrains.kotlin.android to v2.1.0 2024-11-28 01:05:00 +00:00
Renovate Bot
96904bce79 Update plugin com.autonomousapps.dependency-analysis to v2.5.0 2024-11-23 01:05:21 +00:00
Renovate Bot
08675a5fc3 Update dependency gradle to v8.11.1 2024-11-21 01:02:54 +00:00
Renovate Bot
019046474c Update dependency gradle to v8.11 2024-11-12 01:03:36 +00:00
Renovate Bot
0e63b6a50d Update plugin com.autonomousapps.dependency-analysis to v2.4.2 2024-11-09 01:05:30 +00:00
Renovate Bot
608ff610d8 Update dependency com.android.tools:desugar_jdk_libs_nio to v2.1.3 2024-11-08 01:02:13 +00:00
a009ce0c15 Merge pull request 'Update dependency androidx.camera:camera-view to v1.4.0' (#64) from renovate/androidx.camera-camera-view-1.x into main
Reviewed-on: #64
2024-11-07 07:56:07 +01:00
Renovate Bot
1ba95c54a2 Update dependency androidx.camera:camera-view to v1.4.0 2024-11-04 01:01:06 +00:00
Renovate Bot
51987f54e1 Update dependency androidx.camera:camera-lifecycle to v1.4.0 2024-11-03 01:05:52 +00:00
Renovate Bot
efb3a436c4 Update plugin com.android.library to v8.7.2 2024-11-03 01:05:40 +00:00
Renovate Bot
8a22d3b66e Update dependency androidx.camera:camera-camera2 to v1.4.0 2024-11-02 01:06:00 +00:00
Renovate Bot
c404d498d5 Update plugin com.android.application to v8.7.2 2024-11-01 01:01:30 +00:00
Renovate Bot
10d35956b3 Update plugin com.autonomousapps.dependency-analysis to v2.3.0 2024-10-25 00:01:26 +00:00
Renovate Bot
1de639dc46 Update plugin com.android.library to v8.7.1 2024-10-20 00:04:05 +00:00
Renovate Bot
a297988d33 Update plugin com.autonomousapps.dependency-analysis to v2.2.0 2024-10-19 00:04:49 +00:00
Renovate Bot
e788d064a5 Update plugin com.android.application to v8.7.1 2024-10-15 00:01:19 +00:00
Renovate Bot
d6692b5b7c Update plugin org.jetbrains.kotlin.plugin.serialization to v2.0.21 2024-10-12 00:08:35 +00:00
Renovate Bot
5ac4ba1d43 Update plugin org.jetbrains.kotlin.android to v2.0.21 2024-10-11 00:05:14 +00:00
Renovate Bot
50573a37c4 Update plugin com.android.application to v8.7.0 2024-10-05 00:06:34 +00:00
Renovate Bot
2528b7df5d Update plugin com.autonomousapps.dependency-analysis to v2.1.4 2024-10-05 00:06:20 +00:00
Renovate Bot
e6159f6f42 Update plugin com.autonomousapps.dependency-analysis to v2.1.1 2024-09-28 00:06:00 +00:00
Renovate Bot
f2982be549 Update dependency gradle to v8.10.2 2024-09-24 00:05:38 +00:00
Renovate Bot
0c5f7a658f Update plugin com.android.library to v8.6.1 2024-09-21 00:06:47 +00:00
Renovate Bot
9b90057f85 Update plugin com.android.application to v8.6.1 2024-09-18 00:03:41 +00:00
Renovate Bot
a9192314de Update plugin com.autonomousapps.dependency-analysis to v2.0.2 2024-09-14 00:05:24 +00:00
Renovate Bot
aa08418109 Update dependency gradle to v8.10.1 2024-09-10 00:04:35 +00:00
Renovate Bot
5b239ace83 Update dependency com.android.tools:desugar_jdk_libs_nio to v2.1.2 2024-09-05 00:02:36 +00:00
Renovate Bot
555cd8ada2 Update plugin com.android.library to v8.6.0 2024-09-01 00:03:21 +00:00
Renovate Bot
b188313eb9 Update plugin com.autonomousapps.dependency-analysis to v2 2024-09-01 00:03:09 +00:00
Renovate Bot
74ea62e8cd Update plugin com.android.application to v8.6.0 2024-08-31 00:06:45 +00:00
Renovate Bot
a59d79aa0e Update dependency com.android.tools:desugar_jdk_libs_nio to v2.1.1 2024-08-29 00:05:45 +00:00
Renovate Bot
e8021f37dd Update plugin org.jetbrains.kotlin.plugin.serialization to v2.0.20 2024-08-24 00:06:43 +00:00
Renovate Bot
4e179d8698 Update plugin org.jetbrains.kotlin.android to v2.0.20 2024-08-23 00:05:23 +00:00
Renovate Bot
a91f8545b0 Update dependency gradle to v8.10 2024-08-15 00:03:43 +00:00
Renovate Bot
94642047fb Update plugin org.jetbrains.kotlin.android to v2.0.10 2024-08-11 00:06:35 +00:00
Renovate Bot
e99f615fcd Update plugin com.android.application to v8.5.2 2024-08-11 00:06:26 +00:00
Renovate Bot
3ba61e87f9 Update plugin org.jetbrains.kotlin.plugin.serialization to v2.0.10 2024-08-10 00:07:09 +00:00
Renovate Bot
b798200883 Update plugin com.android.library to v8.5.2 2024-08-10 00:06:58 +00:00
Renovate Bot
2998362518 Update plugin com.autonomousapps.dependency-analysis to v1.33.0 2024-07-28 00:04:38 +00:00
Renovate Bot
73e3add4a8 Update plugin com.android.library to v8.5.1 2024-07-14 00:05:29 +00:00
Renovate Bot
5b43db3ebd Update plugin com.android.application to v8.5.1 2024-07-13 00:06:16 +00:00
Renovate Bot
f9535fe2da Update dependency gradle to v8.9 2024-07-12 00:04:09 +00:00
soraefir
aa20ec5a06
Version bump 2024-06-28 22:35:59 +02:00
soraefir
917a01b2ed
Updates and fixes 2024-06-28 22:21:02 +02:00
Renovate Bot
e7f55c2be2 Update plugin com.android.library to v8.5.0 2024-06-17 00:02:36 +00:00
Renovate Bot
eb765e09e7 Update dependency androidx.camera:camera-view to v1.3.4 2024-06-16 00:03:56 +00:00
Renovate Bot
1cf4a6bc36 Update plugin com.android.application to v8.5.0 2024-06-16 00:03:49 +00:00
Renovate Bot
7f0212fc5d Update dependency androidx.camera:camera-lifecycle to v1.3.4 2024-06-15 00:05:06 +00:00
Renovate Bot
413d8bd7bf Update dependency androidx.camera:camera-camera2 to v1.3.4 2024-06-13 00:02:43 +00:00
Renovate Bot
931adbb4dd Update dependency gradle to v8.8 2024-06-01 00:06:27 +00:00
Renovate Bot
e6b2dfe37a Update plugin org.jetbrains.kotlin.android to v2 2024-05-26 00:07:56 +00:00
Renovate Bot
f73f9b5acf Update plugin org.jetbrains.kotlin.plugin.serialization to v2 2024-05-25 13:50:32 +00:00
Renovate Bot
ba2d0ac024 Update plugin com.android.library to v8.4.1 2024-05-25 13:47:04 +00:00
Renovate Bot
f33b4672b0 Update plugin com.autonomousapps.dependency-analysis to v1.32.0 2024-05-25 00:05:43 +00:00
Renovate Bot
b6b69587fa Update plugin com.android.application to v8.4.1 2024-05-21 00:02:49 +00:00
06a006c0a2 Merge pull request 'Update dependency com.google.code.gson:gson to v2.11.0' (#18) from renovate/com.google.code.gson-gson-2.x into main
Reviewed-on: #18
2024-05-20 10:34:47 +02:00
Renovate Bot
8ae38f4250 Update dependency com.google.code.gson:gson to v2.11.0 2024-05-20 00:02:26 +00:00
Renovate Bot
3e1252cc0a Update plugin com.android.library to v8.4.0 2024-05-12 00:11:36 +00:00
Renovate Bot
e4357a66e0 Update plugin org.jetbrains.kotlin.plugin.serialization to v1.9.24 2024-05-11 00:11:39 +00:00
Renovate Bot
21f2c0d69f Update plugin org.jetbrains.kotlin.android to v1.9.24 2024-05-08 00:09:57 +00:00
Renovate Bot
340789989c Update plugin com.android.application to v8.4.0 2024-05-04 00:04:58 +00:00
Renovate Bot
2428f4e50b Update dependency com.google.android.material:material to v1.12.0 2024-05-03 00:02:26 +00:00
f4c9eddd22 Merge pull request 'Update dependency androidx.camera:camera-view to v1.3.3' (#12) from renovate/androidx.camera-camera-view-1.x into main
Reviewed-on: #12
2024-04-21 02:36:39 +02:00
Renovate Bot
6a5e971619 Update dependency androidx.camera:camera-view to v1.3.3 2024-04-21 00:04:40 +00:00
Renovate Bot
5829f18908 Update dependency androidx.camera:camera-lifecycle to v1.3.3 2024-04-20 00:04:38 +00:00
Renovate Bot
426d94ba81 Update dependency androidx.camera:camera-camera2 to v1.3.3 2024-04-17 19:25:16 +00:00
a58d208d49 Merge pull request 'Update plugin com.android.application to v8.3.2' (#7) from renovate/com.android.application-8.x into main
Reviewed-on: #7
2024-04-13 01:08:03 +02:00
Renovate Bot
069edaf6a2 Update plugin com.android.application to v8.3.2 2024-04-12 23:07:08 +00:00
d0aa2fbeb9 Merge pull request 'Update plugin com.android.library to v8.3.2' (#8) from renovate/com.android.library-8.x into main
Reviewed-on: #8
2024-04-13 01:05:24 +02:00
17c75f27bc Merge pull request 'Update gradle/wrapper-validation-action action to v3' (#9) from renovate/gradle-wrapper-validation-action-3.x into main
Reviewed-on: #9
2024-04-13 01:05:09 +02:00
Renovate Bot
1738664f83 Update gradle/wrapper-validation-action action to v3 2024-04-12 23:02:34 +00:00
Renovate Bot
a5b55fe214 Update plugin com.android.library to v8.3.2 2024-04-11 00:01:50 +00:00
0cd90413d1 Update app/src/main/AndroidManifest.xml 2024-04-06 19:26:33 +02:00
soraefir
653ee1ccc1
Fix camera crash & autosave 2024-04-06 19:24:59 +02:00
Renovate Bot
9b6a69e227 Update plugin com.autonomousapps.dependency-analysis to v1.31.0 2024-04-05 00:02:16 +00:00
soraefir
e40305b680
Updated icon and permissions 2024-03-29 15:49:10 +01:00
soraefir
668e9d653f
Scaled icon down 2024-03-29 13:47:22 +01:00
bcfcb85121 Update README.md 2024-03-29 13:29:40 +01:00
49c650c8a9 Update README.md 2024-03-29 13:29:19 +01:00
soraefir
b5f52c7e13
Release 1.2a prep 2024-03-29 13:28:30 +01:00
soraefir
d81922d2c9
File Scanner & Metadata 2024-03-29 13:27:27 +01:00
84b2c2c455 Update README.md 2024-03-25 07:13:58 +01:00
841c3dea24 Update README.md 2024-03-24 15:45:28 +01:00
soraefir
6596f347a1
Updated icon 2024-03-24 15:41:26 +01:00
soraefir
a2dd009533
Fixed versioning 2024-03-24 13:29:13 +01:00
soraefir
4104104b16
minor release 2024-03-24 13:17:09 +01:00
soraefir
0d838b6209
Removed missing encoder 2024-03-24 13:11:15 +01:00
soraefir
1d41671fb6
prep 1.1 2024-03-24 13:01:46 +01:00
soraefir
84ebdcc9a8
Support more formats & cleanup 2024-03-24 13:00:22 +01:00
soraefir
8181da421e
Deleted GoogleML usage 2024-03-24 12:40:33 +01:00
soraefir
af97381bdb
Fix Readme 2024-03-24 11:37:28 +01:00
soraefir
ba94beab37
Fix Readme 2024-03-24 11:36:35 +01:00
19b0f91852 Update README.md 2024-03-24 11:32:34 +01:00
soraefir
3b0bf2097e
Github images 2024-03-24 11:16:26 +01:00
455c95021b LICENSE 2024-03-24 10:45:37 +01:00
soraefir
78ad7f983f
CI Fix 2024-03-24 10:34:02 +01:00
soraefir
0a0b55294f
Fix CI 2024-03-24 10:28:30 +01:00
soraefir
040b9c3af4
Fix CI 2024-03-24 10:26:31 +01:00
soraefir
796c76f36c
CI Signing 2024-03-24 10:23:30 +01:00
soraefir
517f0240e3
CI release 2024-03-23 15:12:15 +01:00
54 changed files with 904 additions and 170 deletions

BIN
.github/images/apk.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
.github/images/izzy.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,3 +1,4 @@
#file: noinspection SpellCheckingInspection
name: CI-Android APK
@ -7,21 +8,31 @@ env:
on:
push:
branches: [ release ]
branches: [ main ]
tags:
- '**'
pull_request:
branches: [ release ]
branches: [ main ]
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v2
- name: set up secrets
run: |
echo "${{ secrets.RELEASE_KEYSTORE }}" > keystore.asc
echo "${{ secrets.RELEASE_KEY}}" > key.asc
gpg -d --passphrase "${{ secrets.RELEASE_KEYSTORE_PASSWORD }}" --batch keystore.asc > app/keystore.properties
gpg -d --passphrase "${{ secrets.RELEASE_KEYSTORE_PASSWORD }}" --batch key.asc > app/key.jks
- uses: gradle/wrapper-validation-action@v3
- name: create and checkout branch
if: github.event_name == 'pull_request'
@ -39,15 +50,15 @@ jobs:
- name: Build APK
run: ./gradlew assemble
- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: app.apk
path: app/build/outputs/apk/release/app-release-unsigned.apk
# - name: Upload APK
# uses: actions/upload-artifact@v4
# with:
# name: app.apk
# path: app/build/outputs/apk/release/app-release.apk
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
app.apk
app/build/outputs/apk/release/app-release-unsigned.apk
app/build/outputs/apk/release/app-release.apk

2
.gitignore vendored
View File

@ -13,3 +13,5 @@ captures/
.externalNativeBuild
.cxx
local.properties
keystore.properties
key.jks

24
LICENSE Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

View File

@ -0,0 +1,73 @@
<!--suppress ALL -->
<div align="center">
<h1>Keepass Fidelity</h1>
<img width="100px" src="./metadata/en-US/images/icon.png" alt="Logo">
<p>A minimalist fidelity/loyalty card plugin</p>
<img src="https://forthebadge.com/images/badges/built-for-android.svg" alt="Built for Android">
<img src="https://forthebadge.com/images/badges/built-with-love.svg" alt="Built with love">
<br>
<a href="https://github.com/choelzl/keepass-fidelity/actions/workflows/build.yml">
<img src="https://github.com/choelzl/keepass-fidelity/actions/workflows/build.yml/badge.svg?branch=main" alt="Build Status">
</a>
</div>
## 🌄 Screenshots
<div align="center">
<table>
<tr>
<td style="width: 33%; height: 100px;"><img src="./metadata/en-US/images/phoneScreenshots/launcher.jpg" alt="Launcher" style="width: 100%; height: 100%;"></td>
<td style="width: 33%; height: 100px;"><img src="./metadata/en-US/images/phoneScreenshots/view.jpg" alt="View" style="width: 100%; height: 100%;"></td>
<td style="width: 33%; height: 100px;"><img src="./metadata/en-US/images/phoneScreenshots/edit.jpg" alt="Edit" style="width: 100%; height: 100%;"></td>
</tr>
</table>
</div>
## ⭐ Features
- Search entries in [Keepass2Android](https://github.com/PhilippC/keepass2android/)
- Scan & Create entries
- Recently used history for fast access
- Protect entries from caching
- Minimalist design and features
- Supported Formats: CODE_39, CODE_93, CODE_128, EAN_8, EAN_13, UPC_A, UPC_E, CODE_QR, PDF_417, AZTEC, CODABAR, DATA_MATRIX, ITF
## 📳 Installation
<div style="display: flex; justify-content: center; align-items: center; flex-direction: row;">
<a href="https://apt.izzysoft.de/fdroid/index/apk/net.helcel.fidelity">
<img width="200" height="80" alt="Izzy Download" src=".github/images/izzy.png">
</a>
<a href="https://github.com/choelzl/keepass-fidelity/releases/latest">
<img width="200" height="84" alt="APK Download" src=".github/images/apk.png">
</a>
</div>
## ⚙️ Permissions
- `CAMERA`: necessary for importing barcodes from camera
- `READ_MEDIA_VISUAL_USER_SELECTED`: necessary for the importing barcode from images
## 📝 Contribute
Keepass-Fidelity is a user-driven project. We welcome any contribution, big or small.
- **🖥️ Development:** Fix bugs, implement features, or research issues. Open a PR for review.
- **🍥 Design:** Improve interfaces, including accessibility and usability.
- **📂 Issue Reporting:** Report bugs and edge cases with relevant info.
- **🌍 Localization:** Translate if it doesn't support your language.
## ✏️ Acknowledgements
Thanks to all contributors, the developers of our dependencies, and our users.
## 📝 License
```
Copyright (C) 2024 Helcel
Licensed under the Unlicense
For more information, please refer to <https://unlicense.org>
```

View File

@ -1,31 +1,46 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.23'
id 'org.jetbrains.kotlin.plugin.serialization' version '2.1.0'
}
def keystorePropertiesFile = rootProject.file("app/keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
namespace 'net.helcel.fidelity'
compileSdk 34
defaultConfig {
applicationId 'net.helcel.fidelity'
resValue "string", "app_name", "Keepass Fideity"
resValue "string", "app_name", "Keepass Fidelity"
minSdk 28
targetSdk 34
versionCode 1
versionName "1.0"
}
signingConfigs {
create("release") {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
debug {
debuggable true
signingConfig = signingConfigs.getByName("release")
}
release {
minifyEnabled true
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig = signingConfigs.getByName("release")
}
}
@ -45,22 +60,25 @@ android {
buildFeatures {
viewBinding true
}
dependenciesInfo {
// Disables dependency metadata when building APKs.
includeInApk = false
// Disables dependency metadata when building Android App Bundles.
includeInBundle = false
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.1.4'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.4'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.camera:camera-camera2:1.3.2'
implementation 'androidx.camera:camera-lifecycle:1.3.2'
implementation 'androidx.camera:camera-view:1.3.2'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.camera:camera-lifecycle:1.4.1'
implementation 'androidx.camera:camera-view:1.4.1'
runtimeOnly 'androidx.camera:camera-camera2:1.4.1'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'com.google.zxing:core:3.5.3'
implementation 'com.google.mlkit:barcode-scanning:17.2.0'
}

13
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,13 @@
# Gson uses generic type information stored in a class file when working with
# fields. Proguard removes such information by default, keep it.
-keepattributes Signature
# This is also needed for R8 in compat mode since multiple
# optimizations will remove the generic signature such as class
# merging and argument removal. See:
# https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md#troubleshooting-gson-gson
-keep class com.google.gson.reflect.TypeToken { *; }
-keep class * extends com.google.gson.reflect.TypeToken
# Optional. For using GSON @Expose annotation
-keepattributes AnnotationDefault,RuntimeVisibleAnnotations

View File

@ -1,13 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="1"
android:versionName="1.0">
android:versionCode="8"
android:versionName="1.2c">
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<application
android:icon="@drawable/logo"
android:icon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:supportsRtl="true">
<activity

BIN
app/src/main/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -31,7 +31,6 @@ class MainActivity : AppCompatActivity() {
binding = ActMainBinding.inflate(layoutInflater)
setContentView(binding.root)
onBackPressedDispatcher.addCallback(this) {
if (supportFragmentManager.backStackEntryCount > 0) {
supportFragmentManager.popBackStackImmediate()

View File

@ -156,6 +156,11 @@ class CreateEntry : Fragment() {
} catch (e: Exception) {
e.printStackTrace()
}
if (!binding.checkboxProtected.isChecked) {
val r = KeepassWrapper.entryExtract(kpEntry.first)
CacheManager.addFidelity(r)
}
activity?.supportFragmentManager?.popBackStack()
}
}

View File

@ -0,0 +1,107 @@
package net.helcel.fidelity.activity.fragment
import android.Manifest
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import net.helcel.fidelity.R
import net.helcel.fidelity.tools.BarcodeScanner
import net.helcel.fidelity.tools.ErrorToaster
import net.helcel.fidelity.tools.KeepassWrapper
import java.io.FileNotFoundException
class FileScanner : Fragment() {
private var code: String = ""
private var fmt: String = ""
private val resultPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
resultLauncherOpenMediaPick.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
private val resultLauncherOpenMediaBase =
registerForActivityResult(ActivityResultContracts.GetContent()) {
loadUri(it)
}
private val resultLauncherOpenMediaPick =
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) {
loadUri(it)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
println(Build.VERSION.SDK_INT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
resultPermission.launch(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
} else {
// resultLauncherOpenMediaBase.launch("image/*")
resultLauncherOpenMediaPick.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
return View(context)
}
private fun startCreateEntry() {
val createEntryFragment = CreateEntry()
createEntryFragment.arguments =
KeepassWrapper.bundleCreate(null, this.code, this.fmt)
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.container, createEntryFragment)
.commit()
}
private fun scannerResult(code: String?, format: String?) {
if (!code.isNullOrEmpty() && !format.isNullOrEmpty()) {
this.code = code
this.fmt = format
}
val isDone = this.code.isNotEmpty() && this.fmt.isNotEmpty()
requireActivity().runOnUiThread {
if (isDone) {
startCreateEntry()
} else {
parentFragmentManager.popBackStack()
ErrorToaster.nothingFound(context)
}
}
}
private fun loadUri(it: Uri?) {
try {
run {
require(it != null)
val file = requireContext().contentResolver.openInputStream(it)
val image = BitmapFactory.decodeStream(file)
BarcodeScanner.bitmapUseCase(image) { code, format ->
scannerResult(code, format)
}
}
} catch (e: FileNotFoundException) {
e.printStackTrace()
println(e.message)
println(it)
ErrorToaster.noPermission(context)
parentFragmentManager.popBackStack()
} catch (e: IllegalArgumentException) {
ErrorToaster.nothingFound(context)
parentFragmentManager.popBackStack()
} catch (e: SecurityException) {
ErrorToaster.noPermission(context)
parentFragmentManager.popBackStack()
}
}
}

View File

@ -49,6 +49,11 @@ class Launcher : Fragment() {
startScanner()
hideMenuAdd()
}
binding.btnOpen.setOnClickListener {
startFileScanner()
hideMenuAdd()
}
binding.btnManual.setOnClickListener {
startCreateEntry()
@ -96,6 +101,10 @@ class Launcher : Fragment() {
startFragment(Scanner())
}
private fun startFileScanner() {
startFragment(FileScanner())
}
private fun startCreateEntry() {
startFragment(CreateEntry())
}

View File

@ -2,25 +2,23 @@ package net.helcel.fidelity.activity.fragment
import android.Manifest
import android.content.ContentValues
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import net.helcel.fidelity.R
import net.helcel.fidelity.databinding.FragScannerBinding
import net.helcel.fidelity.tools.BarcodeScanner.getAnalysisUseCase
import net.helcel.fidelity.tools.BarcodeScanner.analysisUseCase
import net.helcel.fidelity.tools.ErrorToaster
import net.helcel.fidelity.tools.KeepassWrapper
private const val CAMERA_PERMISSION_REQUEST_CODE = 1
class Scanner : Fragment() {
private lateinit var binding: FragScannerBinding
@ -28,6 +26,17 @@ class Scanner : Fragment() {
private var code: String = ""
private var fmt: String = ""
private val resultPermissionRequest =
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
if (it) {
bindCameraUseCases()
} else {
parentFragmentManager.popBackStack()
ErrorToaster.noPermission(context)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -37,14 +46,12 @@ class Scanner : Fragment() {
binding.btnScanDone.setOnClickListener {
startCreateEntry()
}
when (hasCameraPermission()) {
true -> bindCameraUseCases()
else -> requestPermission()
}
binding.btnScanDone.isEnabled = false
resultPermissionRequest.launch(Manifest.permission.CAMERA)
return binding.root
}
private fun startCreateEntry() {
val createEntryFragment = CreateEntry()
createEntryFragment.arguments =
@ -54,26 +61,16 @@ class Scanner : Fragment() {
.commit()
}
private fun hasCameraPermission() =
ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
private fun requestPermission() {
ActivityCompat.requestPermissions(
requireActivity(),
arrayOf(Manifest.permission.CAMERA),
CAMERA_PERMISSION_REQUEST_CODE
)
ActivityCompat.OnRequestPermissionsResultCallback { c, p, i ->
require(c == CAMERA_PERMISSION_REQUEST_CODE)
require(p.contains(Manifest.permission.CAMERA))
val el = i[p.indexOf(Manifest.permission.CAMERA)]
if (el != PackageManager.PERMISSION_GRANTED) {
startCreateEntry()
}
private fun scannerResult(code: String?, format: String?) {
if (!code.isNullOrEmpty() && !format.isNullOrEmpty()) {
this.code = code
this.fmt = format
}
val isDone = this.code.isNotEmpty() && this.fmt.isNotEmpty()
activity?.runOnUiThread {
binding.btnScanDone.isEnabled = isDone
binding.ScanActive.isEnabled = !isDone
}
}
@ -88,15 +85,8 @@ class Scanner : Fragment() {
it.setSurfaceProvider(binding.cameraView.surfaceProvider)
}
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
val analysisUseCase = getAnalysisUseCase { code, format ->
if (code != null && format != null) {
this.code = code
this.fmt = format
binding.btnScanDone.isEnabled = true
} else {
binding.btnScanDone.isEnabled = false
}
val analysisUseCase = analysisUseCase { code, format ->
scannerResult(code, format)
}
try {
cameraProvider.bindToLifecycle(

View File

@ -80,7 +80,7 @@ class ViewEntry : Fragment() {
return (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE)
}
private fun setScreenBrightness(brightness: Float?) {
private fun setScreenBrightness(brightness: Float) {
requireActivity().window?.attributes?.screenBrightness = brightness
}
}

View File

@ -7,15 +7,15 @@ import org.json.JSONObject
object Kp2aControl {
fun getAddEntryIntent(
fields: HashMap<String?, String?>,
protectedFields: ArrayList<String?>?
fields: HashMap<String, String>,
protectedFields: ArrayList<String>?
): Intent {
val outputData = JSONObject((fields as Map<*, *>)).toString()
val startKp2aIntent = Intent(Strings.ACTION_START_WITH_TASK)
startKp2aIntent.addCategory(Intent.CATEGORY_DEFAULT)
startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
startKp2aIntent.putExtra("KP2A_APPTASK", "CreateEntryThenCloseTask")
startKp2aIntent.putExtra("ShowUserNotifications", "false")
startKp2aIntent.putExtra("ShowUserNotifications", "true")
startKp2aIntent.putExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA, outputData)
if (protectedFields != null)
startKp2aIntent.putStringArrayListExtra(

View File

@ -7,6 +7,7 @@ object Strings {
const val SCOPE_CURRENT_ENTRY = "keepass2android.SCOPE_CURRENT_ENTRY"
const val SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE =
"keepass2android.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE"
const val SCOPE_QUERY_CREDENTIALS = "keepass2android.SCOPE_QUERY_CREDENTIALS"
const val EXTRA_SCOPES = "keepass2android.EXTRA_SCOPES"
const val EXTRA_PLUGIN_PACKAGE = "keepass2android.EXTRA_PLUGIN_PACKAGE"

View File

@ -1,6 +1,5 @@
package net.helcel.fidelity.tools
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.zxing.BarcodeFormat
object BarcodeFormatConverter {
@ -16,21 +15,39 @@ object BarcodeFormatConverter {
"UPC_A" -> BarcodeFormat.UPC_A
"UPC_E" -> BarcodeFormat.UPC_E
"PDF_417" -> BarcodeFormat.PDF_417
"AZTEC" -> BarcodeFormat.AZTEC
"CODABAR" -> BarcodeFormat.CODABAR
"MAXICODE" -> BarcodeFormat.MAXICODE
"DATA_MATRIX" -> BarcodeFormat.DATA_MATRIX
"ITF" -> BarcodeFormat.ITF
"RSS_14" -> BarcodeFormat.RSS_14
"RSS_EXPANDED" -> BarcodeFormat.RSS_EXPANDED
"UPC_EAN" -> BarcodeFormat.UPC_EAN_EXTENSION
else -> throw Exception("Unsupported Format: $f")
}
}
fun formatToString(f: Int): String {
fun formatToString(f: BarcodeFormat): String {
return when (f) {
Barcode.FORMAT_CODE_128 -> "CODE_128"
Barcode.FORMAT_CODE_39 -> "CODE_39"
Barcode.FORMAT_CODE_93 -> "CODE_93"
Barcode.FORMAT_EAN_8 -> "EAN_8"
Barcode.FORMAT_EAN_13 -> "EAN_13"
Barcode.FORMAT_QR_CODE -> "CODE_QR"
Barcode.FORMAT_UPC_A -> "UPC_A"
Barcode.FORMAT_UPC_E -> "UPC_E"
Barcode.FORMAT_PDF417 -> "PDF_417"
BarcodeFormat.CODE_39 -> "CODE_39"
BarcodeFormat.CODE_93 -> "CODE_93"
BarcodeFormat.CODE_128 -> "CODE_128"
BarcodeFormat.EAN_8 -> "EAN_8"
BarcodeFormat.EAN_13 -> "EAN_13"
BarcodeFormat.QR_CODE -> "CODE_QR"
BarcodeFormat.UPC_A -> "UPC_A"
BarcodeFormat.UPC_E -> "UPC_E"
BarcodeFormat.PDF_417 -> "PDF_417"
BarcodeFormat.AZTEC -> "AZTEC"
BarcodeFormat.CODABAR -> "CODABAR"
BarcodeFormat.MAXICODE -> "MAXICODE"
BarcodeFormat.DATA_MATRIX -> "DATA_MATRIX"
BarcodeFormat.ITF -> "ITF"
BarcodeFormat.RSS_14 -> "RSS_14"
BarcodeFormat.RSS_EXPANDED -> "RSS_EXPANDED"
BarcodeFormat.UPC_EAN_EXTENSION -> "UPC_EAN"
else -> throw Exception("Unsupported Format: $f")
}
}

View File

@ -1,75 +1,61 @@
package net.helcel.fidelity.tools
import android.content.ContentValues
import android.util.Log
import android.graphics.Bitmap
import androidx.annotation.OptIn
import androidx.camera.core.ExperimentalGetImage
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.mlkit.vision.barcode.BarcodeScanner
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage
import com.google.zxing.BinaryBitmap
import com.google.zxing.MultiFormatReader
import com.google.zxing.NotFoundException
import com.google.zxing.RGBLuminanceSource
import com.google.zxing.ReaderException
import com.google.zxing.common.HybridBinarizer
import net.helcel.fidelity.tools.BarcodeFormatConverter.formatToString
import java.util.concurrent.Executors
@OptIn(ExperimentalGetImage::class)
object BarcodeScanner {
@OptIn(ExperimentalGetImage::class)
private fun processImageProxy(
barcodeScanner: BarcodeScanner,
imageProxy: ImageProxy,
private fun processImage(
bitmap: Bitmap,
cb: (String?, String?) -> Unit
) {
imageProxy.image?.let { image ->
val inputImage =
InputImage.fromMediaImage(
image,
imageProxy.imageInfo.rotationDegrees
)
barcodeScanner.process(inputImage)
.addOnSuccessListener { barcodeList ->
val barcode =
barcodeList.getOrNull(0)
if (barcode != null)
cb(barcode.displayValue, formatToString(barcode.format))
}
.addOnFailureListener {
Log.e(ContentValues.TAG, it.message.orEmpty())
}.addOnCompleteListener {
imageProxy.image?.close()
imageProxy.close()
}
val binaryBitmap = createBinaryBitmap(bitmap)
val reader = MultiFormatReader()
try {
val result = reader.decode(binaryBitmap)
cb(result.text, formatToString(result.barcodeFormat))
} catch (e: NotFoundException) {
cb(null, null)
} catch (e: ReaderException) {
cb(null, null)
}
}
fun getAnalysisUseCase(cb: (String?, String?) -> Unit): ImageAnalysis {
val options = BarcodeScannerOptions.Builder().setBarcodeFormats(
Barcode.FORMAT_CODE_128,
Barcode.FORMAT_CODE_39,
Barcode.FORMAT_CODE_93,
Barcode.FORMAT_EAN_8,
Barcode.FORMAT_EAN_13,
Barcode.FORMAT_QR_CODE,
Barcode.FORMAT_UPC_A,
Barcode.FORMAT_UPC_E,
Barcode.FORMAT_PDF417
).build()
val scanner = BarcodeScanning.getClient(options)
val analysisUseCase = ImageAnalysis.Builder()
.build()
private fun createBinaryBitmap(bitmap: Bitmap): BinaryBitmap {
val pixels = IntArray(bitmap.width * bitmap.height)
bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
val source =
RGBLuminanceSource(bitmap.width, bitmap.height, pixels)
return BinaryBitmap(HybridBinarizer(source))
}
fun analysisUseCase(cb: (String?, String?) -> Unit): ImageAnalysis {
val analysisUseCase = ImageAnalysis.Builder().build()
analysisUseCase.setAnalyzer(
Executors.newSingleThreadExecutor()
) { imageProxy ->
processImageProxy(scanner, imageProxy, cb)
val bitmap = imageProxy.toBitmap()
imageProxy.close()
bitmapUseCase(bitmap, cb)
}
return analysisUseCase
}
fun bitmapUseCase(bitmap: Bitmap, cb: (String?, String?) -> Unit) {
processImage(bitmap, cb)
}
}

View File

@ -20,4 +20,12 @@ object ErrorToaster {
fun invalidFormat(activity: Context?) {
helper(activity, "Invalid Format", Toast.LENGTH_SHORT)
}
fun nothingFound(activity: Context?) {
helper(activity, "Nothing Found", Toast.LENGTH_SHORT)
}
fun noPermission(activity: Context?) {
helper(activity, "Missing Permission", Toast.LENGTH_LONG)
}
}

View File

@ -21,10 +21,10 @@ object KeepassWrapper {
code: String,
format: String,
protectCode: Boolean,
): Pair<HashMap<String?, String?>, ArrayList<String?>> {
): Pair<HashMap<String, String>, ArrayList<String>> {
val fields = HashMap<String?, String?>()
val protected = ArrayList<String?>()
val fields = HashMap<String, String>()
val protected = ArrayList<String>()
fields[KeepassDef.TitleField] = title
fields[KeepassDef.UrlField] =
"androidapp://" + fragment.requireActivity().packageName

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group android:scaleX="1.2833333"
android:scaleY="1.2833333"
android:translateX="-16.612345"
android:translateY="-16.612345">
<group
android:translateX="34"
android:translateY="26">
<group
android:scaleX="0.8"
android:scaleY="1.0"
android:translateX="0"
android:translateY="0">
<path
android:fillColor="@color/blue"
android:pathData="M59.959,52.794H12.041c-0.552,0 -1,-0.448 -1,-1v-29.547c0,-0.552 0.448,-1 1,-1h47.918c0.552,0 1,0.448 1,1v29.547C60.959,52.347 60.511,52.794 59.959,52.794z"
android:strokeWidth="2"
android:strokeColor="#000000" />
</group>
<group
android:scaleX="0.4"
android:scaleY="0.5"
android:translateX="27"
android:translateY="15.75">
<path
android:fillColor="@color/red"
android:pathData="M46.5,56l-10,-11l-10,11l0,-45l20,0z"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="@color/red2"
android:fillAlpha="1.0"
android:pathData="M41.5,11l0,39l5,6l0,-45z"
android:strokeColor="#00000000" />
</group>
<group
android:scaleX="0.75"
android:scaleY="0.75"
android:translateX="6"
android:translateY="10">
<path
android:fillColor="#00000000"
android:pathData="M9,21V52 M12,21V52 M20,21V50 M28,21V50 M15,50V21H17V50H15 M23,50V21H25V50H23 M31,50V21H32V50H31 M35,21V52 M38,21V52"
android:strokeWidth="2"
android:strokeColor="#000"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</group>
</group>
</group>
</vector>

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="128dp"
android:height="128dp"
android:gravity="center"
android:drawable="@drawable/card" />
<item
android:width="64dp"
android:height="64dp"
android:drawable="@drawable/barcode"
android:gravity="center"
android:right="32dp" />
<item
android:width="52dp"
android:height="52dp"
android:drawable="@drawable/bookmark"
android:gravity="center"
android:left="72dp"
android:bottom="20dp" />
</layer-list>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:translateX="34"
android:translateY="26">
<group
android:scaleX="0.8"
android:scaleY="1.0"
android:translateX="0"
android:translateY="0">
<path
android:fillColor="@color/blue"
android:pathData="M59.959,52.794H12.041c-0.552,0 -1,-0.448 -1,-1v-29.547c0,-0.552 0.448,-1 1,-1h47.918c0.552,0 1,0.448 1,1v29.547C60.959,52.347 60.511,52.794 59.959,52.794z"
android:strokeWidth="2"
android:strokeColor="#000000" />
</group>
<group
android:scaleX="0.4"
android:scaleY="0.5"
android:translateX="27"
android:translateY="15.75">
<path
android:fillColor="@color/red"
android:pathData="M46.5,56l-10,-11l-10,11l0,-45l20,0z"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="@color/red2"
android:fillAlpha="1.0"
android:pathData="M41.5,11l0,39l5,6l0,-45z"
android:strokeColor="#00000000" />
</group>
<group
android:scaleX="0.75"
android:scaleY="0.75"
android:translateX="6"
android:translateY="10">
<path
android:fillColor="#00000000"
android:pathData="M9,21V52 M12,21V52 M20,21V50 M28,21V50 M15,50V21H17V50H15 M23,50V21H25V50H23 M31,50V21H32V50H31 M35,21V52 M38,21V52"
android:strokeWidth="2"
android:strokeColor="#000"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</group>
</group>
</vector>

View File

@ -0,0 +1,22 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="72dp"
android:height="72dp"
android:viewportWidth="58"
android:viewportHeight="58">
<group android:translateX="-10" android:translateY="-8">
<path
android:pathData="m57.008,20.304v-3.356l-27.338,-0.002c-0.198,0 -0.359,-0.165 -0.359,-0.368l-0.069,-1.517c-0.116,-1.788 -1.34,-3.003 -2.997,-3.003h-11.287c-1.657,0 -3,1.343 -3,3v40.943"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="m17.027,55.568c-0.59,1.954 -2.972,4.139 -4.646,4.394l44.665,0.011c1.657,0 2.323,-0.439 3,-3s7,-31.657 7,-31.657c0,-0.552 -0.448,-1 -1,-1H24.965c-0.552,0 -1,0.448 -1,1 0,0 -6.348,28.299 -6.938,30.253Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
</group>
</vector>

View File

@ -0,0 +1,302 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="72dp"
android:height="72dp"
android:viewportWidth="58"
android:viewportHeight="58">
<group android:translateX="-8" android:translateY="-8">
<path
android:pathData="M20,20h4v4h-4z"
android:fillColor="#000"/>
<path
android:pathData="M20,48h4v4h-4z"
android:fillColor="#000"/>
<path
android:pathData="M48,20h4v4h-4z"
android:fillColor="#000"/>
<path
android:pathData="M18,40m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M16,38m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M20,38m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M34,46m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M40,38m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M40,28m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M32,16m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M46,32m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M52,32m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M52,44m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M54,48m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M56,56m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M32,56m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M44,56m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M46,54m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M44,52m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M16,32m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M40,54m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"
android:fillColor="#000"/>
<path
android:pathData="M12,12h48v48h-48z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"/>
<path
android:pathData="M16,16h12v12h-12z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"/>
<path
android:pathData="M20,20h4v4h-4z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"/>
<path
android:pathData="M16,44h12v12h-12z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"/>
<path
android:pathData="M20,48h4v4h-4z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"/>
<path
android:pathData="M44,16h12v12h-12z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"/>
<path
android:pathData="M48,20h4v4h-4z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"/>
<path
android:pathData="M18,36V34H26"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M20,34V32"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M24,34V40"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M24,38H26"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M38,32V30"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M56,34H54"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M42,42H44V40"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M28,32H30"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M34,32H40"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M38,16V20H36V28"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M36,26H32V28"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M36,20H32"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M36,22H34V18"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M28,36H36"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M30,36V40H28"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M34,36V38"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M32,44V42H38V48H42V46H50V56"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M36,40V44H42M46,40H42V48H44"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M48,34V38H50V42H48V46"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M50,38V36H52"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M52,50H48V52"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M32,52H34V54H36V50"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M56,32V38H54"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M44,36V34"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M56,42V44"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M54,52H56"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M40,22V24"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
</group>
</vector>

View File

@ -11,6 +11,7 @@
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:ignore="MergeRootFrame" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:orientation="vertical"
tools:context=".activity.fragment.Launcher">
@ -56,6 +57,16 @@
app:maxImageSize="32dp"
app:srcCompat="@drawable/camera" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnOpen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:contentDescription="@string/open"
app:fabCustomSize="46dp"
app:maxImageSize="32dp"
app:srcCompat="@drawable/open" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnManual"
android:layout_width="wrap_content"

View File

@ -25,6 +25,7 @@
android:contentDescription="@string/manual" />
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/ScanActive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="darkgray">#FF0C1D2E</color>
<color name="gray">#425F7C</color>
<color name="lightgray">#FF93A9BE</color>
<color name="white">#FFF0F3F7</color>
<color name="blue">#7DB9F5</color>
<color name="blue2">#3193F5</color>
<color name="red">#F57D7D</color>
<color name="red2">#F53131</color>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#0C1D2E</color>
</resources>

View File

@ -15,15 +15,20 @@
<string name="code">Code</string>
<string name="format">Format</string>
<string name="save">Save</string>
<string name="open">Open</string>
<string-array name="format_array">
<item>CODE_128</item>
<item>CODE_39</item>
<item>CODE_93</item>
<item>CODE_128</item>
<item>EAN_8</item>
<item>EAN_13</item>
<item>CODE_QR</item>
<item>UPC_A</item>
<item>UPC_E</item>
<item>PDF_417</item>
<item>AZTEC</item>
<item>CODABAR</item>
<item>DATA_MATRIX</item>
<item>ITF</item>
</string-array>
</resources>

View File

@ -2,11 +2,10 @@
<resources>
<style name="Theme.Fidelity" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">#7DB9F5</item>
<item name="colorPrimaryVariant">#7DB9F5</item>
<item name="colorSecondary">#7DB9F5</item>
<item name="colorSecondaryVariant">#7DB9F5</item>
<item name="colorOnPrimary">#030B12</item>
<item name="colorPrimary">@color/blue</item>
<item name="colorPrimaryVariant">@color/blue</item>
<item name="colorSecondary">@color/blue</item>
<item name="colorSecondaryVariant">@color/blue</item>
<item name="colorOnPrimary">@color/darkgray</item>
</style>
</resources>

View File

@ -1,7 +1,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.3.1' apply false
id 'com.android.library' version '8.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.9.23' apply false
id 'com.android.application' version '8.8.0' apply false
id 'com.android.library' version '8.8.0' apply false
id 'org.jetbrains.kotlin.android' version '2.1.0' apply false
id 'com.autonomousapps.dependency-analysis' version '2.7.0' apply true
}

Binary file not shown.

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

6
gradlew vendored
View File

@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -84,7 +86,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum

2
gradlew.bat vendored
View File

@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################

View File

@ -0,0 +1 @@
<p><i>Keepass-Fidelity</i> adds an interface to view/save barcodes (QR included) to Keepass through the plugin interface of the Keepass2Android app.</p><p><br></p><ul><li><b>Launcher:</b> view and launch recent entries (a per entry flag can disable this behaviour)</li><li><b>View:</b> view entries from the history or queried from Keepass2Android</li><li><b>Create:</b> add entries from the camera, an image of by filling out a form. The entry is then created in the Keepass2Android app</li><li><b>Data:</b> the app uses the following data Title (entry name), barcode type (QR, UPC, ...), barcode content (number/text content) and a "secure" flag (enable/disable caching the entry).</li></ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1 @@
<ul><li><b>CAMERA:</b> necessary for importing barcodes from camera</li><li><b>READ_MEDIA_VISUAL_USER_SELECTED:</b> necessary for the importing barcode from images</li></ul>

View File

@ -0,0 +1 @@
Fidelity (Membership/Loyalty) Card plugin for Keepass2Android

View File

@ -14,5 +14,6 @@ dependencyResolutionManagement {
maven { url 'https://jitpack.io' }
}
}
rootProject.name = "Fidelity"
include ':app'