Skip to content

Commit

Permalink
Merge pull request #239 from SecUSo/development
Browse files Browse the repository at this point in the history
Update to version 4.6.1
  • Loading branch information
udenr authored Jul 26, 2024
2 parents 734efc5 + 8202fe5 commit 8b77268
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 45 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
compileSdk 34
targetSdkVersion 34
multiDexEnabled true
versionCode 42
versionName "4.6.0"
versionCode 43
versionName "4.6.1"
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
buildFeatures.dataBinding = true
vectorDrawables.useSupportLibrary = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();

assertEquals("com.secuso.privacyfriendlycodescanner.qrscanner", appContext.getPackageName());
assertEquals("com.secuso.privacyFriendlyCodeScanner", appContext.getPackageName());
}

@Before
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.CAMERA" />
Expand Down Expand Up @@ -193,4 +194,4 @@
<data android:mimeType="*/*" />
</intent>
</queries>
</manifest>
</manifest>
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.secuso.privacyfriendlycodescanner.qrscanner.generator;

import static android.content.Context.WINDOW_SERVICE;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.media.MediaScannerConnection;
import android.net.Uri;
Expand All @@ -15,14 +20,19 @@
import android.view.Display;
import android.view.WindowManager;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.google.zxing.qrcode.encoder.ByteMatrix;
import com.google.zxing.qrcode.encoder.Encoder;
import com.google.zxing.qrcode.encoder.QRCode;

import java.io.File;
import java.io.FileOutputStream;
Expand All @@ -31,9 +41,9 @@
import java.text.FieldPosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;

import static android.content.Context.WINDOW_SERVICE;
import java.util.Map;

public class QRGeneratorUtils {

Expand Down Expand Up @@ -85,36 +95,115 @@ public static Uri getCachedUri() {
return cache;
}

public static Uri createImage(Context context, String qrInputText, Contents.Type qrType, BarcodeFormat barcodeFormat, String errorCorrectionLevel) {

private static int getDimension(Context context) {
//Find screen size
WindowManager manager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
Point point = new Point();
display.getSize(point);
int width = point.x;
int height = point.y;
int smallerDimension = width < height ? width : height;
smallerDimension = smallerDimension * 3 / 4;

//Encode with a QR Code image
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrInputText,
null,
qrType,
barcodeFormat.toString(),
smallerDimension);
Bitmap bitmap_ = null;
try {
bitmap_ = qrCodeEncoder.encodeAsBitmap(errorCorrectionLevel);
// return bitmap_;
int smallerDimension = Math.min(width, height);
return smallerDimension * 3 / 4;
}

} catch (WriterException e) {
e.printStackTrace();
public static Uri createImage(Context context, String qrInputText, Contents.Type qrType, BarcodeFormat barcodeFormat, String errorCorrectionLevel, boolean dots) {
int smallerDimension = getDimension(context);

Bitmap bitmap_ = null;
if (!dots) {
//Encode with a QR Code image
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrInputText,
null,
qrType,
barcodeFormat.toString(),
smallerDimension);
try {
bitmap_ = qrCodeEncoder.encodeAsBitmap(errorCorrectionLevel);
} catch (WriterException e) {
e.printStackTrace();
}
} else {
final Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 1);
QRCode code;
try {
code = Encoder.encode(qrInputText, ErrorCorrectionLevel.valueOf(errorCorrectionLevel), hints);
} catch (WriterException e) {
throw new RuntimeException(e);
}
bitmap_ = createDotQRCode(code, smallerDimension, smallerDimension, Color.BLACK, Color.WHITE, 1);
}

return cacheImage(context, bitmap_);
}

private static Bitmap createDotQRCode(QRCode code, int width, int height, @ColorInt int color, @ColorInt int backgroundColor, int quietZone) {
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
canvas.drawColor(backgroundColor);
Paint paint = new Paint();
paint.setColor(color);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);


ByteMatrix input = code.getMatrix();
if (input == null) {
throw new IllegalArgumentException();
}

final int QR_WIDTH = input.getWidth() + (quietZone * 2);
final int QR_HEIGHT = input.getHeight() + (quietZone * 2);
final int OUTPUT_WIDTH = Math.max(width, QR_WIDTH);
final int OUTPUT_HEIGHT = Math.max(height, QR_HEIGHT);

final float SCALE = Math.min((float) OUTPUT_WIDTH / (float) QR_WIDTH, (float) OUTPUT_HEIGHT / (float) QR_HEIGHT); //scale from ByteMatrix to Canvas
final int POSITION_PATTERN_SIZE = 7; //size of the position pattern inside the ByteMatrix
final float POSITION_PATTERN_RADIUS = (SCALE * POSITION_PATTERN_SIZE) / 2f;
final float CIRCLE_RADIUS = (SCALE * 0.35f);
final float PADDING_LEFT = (OUTPUT_WIDTH - (input.getWidth() * SCALE)) / 2.0f + CIRCLE_RADIUS / 2.0f;
final float PADDING_TOP = (OUTPUT_HEIGHT - (input.getHeight() * SCALE)) / 2.0f + CIRCLE_RADIUS / 2.0f;

for (int y = 0; y < input.getHeight(); y++) {
for (int x = 0; x < input.getWidth(); x++) {
if (input.get(x, y) == 1) {
boolean isInPositionPatternArea = //do not draw anything inside the position pattern regions
x <= POSITION_PATTERN_SIZE && y <= POSITION_PATTERN_SIZE || //top left position pattern
x >= input.getWidth() - POSITION_PATTERN_SIZE && y <= POSITION_PATTERN_SIZE || //top right position pattern
x <= POSITION_PATTERN_SIZE && y >= input.getHeight() - POSITION_PATTERN_SIZE; //bottom left position pattern
if (!isInPositionPatternArea) {
float outputX = PADDING_LEFT + x * SCALE;
float outputY = PADDING_TOP + y * SCALE;
canvas.drawCircle(outputX + CIRCLE_RADIUS, outputY + CIRCLE_RADIUS, CIRCLE_RADIUS, paint);
}
}
}
}

//draw position patterns
drawPositionPattern(canvas, color, backgroundColor, PADDING_LEFT, PADDING_TOP, POSITION_PATTERN_RADIUS);
drawPositionPattern(canvas, color, backgroundColor, PADDING_LEFT + (input.getWidth() - POSITION_PATTERN_SIZE) * SCALE, PADDING_TOP, POSITION_PATTERN_RADIUS);
drawPositionPattern(canvas, color, backgroundColor, PADDING_LEFT, PADDING_TOP + (input.getHeight() - POSITION_PATTERN_SIZE) * SCALE, POSITION_PATTERN_RADIUS);

return image;
}

private static void drawPositionPattern(Canvas canvas, @ColorInt int color, @ColorInt int backgroundColor, float x, float y, float patternRadius) {
final float BACKGROUND_CIRCLE_RADIUS = patternRadius * 5f / 7f;
final float MIDDLE_DOT_RADIUS = patternRadius * 3f / 7f;

Paint paint = new Paint();
paint.setColor(color);
Paint bgPaint = new Paint();
bgPaint.setColor(backgroundColor);

canvas.drawCircle(x + patternRadius, y + patternRadius, patternRadius, paint);
canvas.drawCircle(x + patternRadius, y + patternRadius, BACKGROUND_CIRCLE_RADIUS, bgPaint);
canvas.drawCircle(x + patternRadius, y + patternRadius, MIDDLE_DOT_RADIUS, paint);
}

public static void saveCachedImageToExternalStorage(Context context) {
Bitmap bitmap = null;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ public static Bitmap generateCode(String data, BarcodeFormat original_format, in
if (!hints.containsKey(ERROR_CORRECTION) && metadata != null && metadata.containsKey(ERROR_CORRECTION_LEVEL) && format.equals(original_format)) {
Object ec = metadata.get(ERROR_CORRECTION_LEVEL);
if (ec != null) {
hints.put(ERROR_CORRECTION, ec);
String errorCorrection = ec.toString();
errorCorrection = errorCorrection.replace("%", ""); // Sometimes the error correction value contains a percent sign
hints.put(ERROR_CORRECTION, errorCorrection);
}
}
if (!hints.containsKey(ERROR_CORRECTION) && format != BarcodeFormat.AZTEC && format != BarcodeFormat.PDF_417) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,17 @@ public class QrGeneratorDisplayActivity extends AppCompatActivity {
String qrInputText = "";
Contents.Type qrInputType = Contents.Type.UNDEFINED;

private static final String BARCODE_FORMAT_QR_CODE_DOTS = BarcodeFormat.QR_CODE.name() + "_DOTS";
private String[] barcodeFormats = new String[]{
BarcodeFormat.QR_CODE.name(),
BARCODE_FORMAT_QR_CODE_DOTS,
BarcodeFormat.AZTEC.name(),
BarcodeFormat.DATA_MATRIX.name(),
BarcodeFormat.PDF_417.name(),
BarcodeFormat.CODE_128.name()};
private Integer[] barcodeFormatIcons = new Integer[]{
R.drawable.ic_baseline_qr_code_24dp,
R.drawable.ic_baseline_qr_code_dots_24dp,
R.drawable.ic_aztec_code_24dp,
R.drawable.ic_data_matrix_code_24dp,
R.drawable.ic_pdf_417_code_24dp,
Expand Down Expand Up @@ -137,7 +140,7 @@ private void initDropDownMenus() {
}

private void updateDropDownMenus() {
barcodeFormat = BarcodeFormat.valueOf(barcodeFormatMenu.getText().toString());
UpdateBarcodeFormatFromMenuValue();

if (barcodeFormat.equals(BarcodeFormat.QR_CODE)) {
currentErrorCorrections = errorCorrectionsQR;
Expand All @@ -151,7 +154,7 @@ private void updateDropDownMenus() {
updateErrorCorrectionMenu();
//Update icon
ImageView barcodeFormatIcon = findViewById(R.id.iconImageView);
Glide.with(this).load(AppCompatResources.getDrawable(this, barcodeFormatIcons[Arrays.asList(barcodeFormats).indexOf(barcodeFormat.name())])).into(barcodeFormatIcon);
Glide.with(this).load(AppCompatResources.getDrawable(this, barcodeFormatIcons[Arrays.asList(barcodeFormats).indexOf(barcodeFormatMenu.getText().toString())])).into(barcodeFormatIcon);

}

Expand All @@ -176,11 +179,15 @@ private void updateErrorCorrectionMenu() {
private void generateAndUpdateImage() {
ImageView myImage = findViewById(R.id.resultQRCodeImage);

barcodeFormat = BarcodeFormat.valueOf(barcodeFormatMenu.getText().toString());
UpdateBarcodeFormatFromMenuValue();
String errorCorrectionLevel = errorCorrectionMenu.getText().toString();
try {
Log.d(getClass().getSimpleName(), "Creating image...");
Glide.with(this).asBitmap().load(QRGeneratorUtils.createImage(this, qrInputText, qrInputType, barcodeFormat, errorCorrectionLevel)).into(new BitmapImageViewTarget(myImage));
if (barcodeFormatMenu.getText().toString().equals(BARCODE_FORMAT_QR_CODE_DOTS)) {
Glide.with(this).asBitmap().load(QRGeneratorUtils.createImage(this, qrInputText, qrInputType, barcodeFormat, errorCorrectionLevel, true)).into(new BitmapImageViewTarget(myImage));
} else {
Glide.with(this).asBitmap().load(QRGeneratorUtils.createImage(this, qrInputText, qrInputType, barcodeFormat, errorCorrectionLevel, false)).into(new BitmapImageViewTarget(myImage));
}
} catch (IllegalArgumentException e) {
Toast.makeText(this, R.string.code_generation_error, Toast.LENGTH_SHORT).show();
Log.d(getClass().getSimpleName(), "Error during code generation.", e);
Expand Down Expand Up @@ -263,6 +270,14 @@ protected void onDestroy() {
QRGeneratorUtils.purgeCacheFolder(this);
}

private void UpdateBarcodeFormatFromMenuValue() {
if (barcodeFormatMenu.getText().toString().equals(BARCODE_FORMAT_QR_CODE_DOTS)) {
barcodeFormat = BarcodeFormat.QR_CODE;
} else {
barcodeFormat = BarcodeFormat.valueOf(barcodeFormatMenu.getText().toString());
}
}

@Override
protected void onResume() {
super.onResume();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void onProceedPressed(Context context) {
Intent contact = new Intent(ContactsContract.Intents.Insert.ACTION);
contact.setType(ContactsContract.RawContacts.CONTENT_TYPE);

contact.putExtra(ContactsContract.Intents.Insert.NAME, result.getNames() != null ? result.getNames()[0] : null);
contact.putExtra(ContactsContract.Intents.Insert.NAME, result.getNames() != null && result.getNames().length > 0 ? result.getNames()[0] : null);
contact.putExtra(ContactsContract.Intents.Insert.COMPANY, result.getOrg());
contact.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, result.getTitle());
contact.putExtra(ContactsContract.Intents.Insert.NOTES, result.getNote());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.regex.Pattern;

public class URLResultFragment extends ResultFragment {
private static final String VALID_RFC3986_PROTOCOL_SCHEME = "^[a-zA-Z][a-zA-Z0-9+.-]*:.*$";

URIParsedResult result;

Expand Down Expand Up @@ -95,23 +96,14 @@ public void onProceedPressed(Context context) {
if (!checked) {
Toast.makeText(context, R.string.conform_url, Toast.LENGTH_LONG).show();
} else {
String caption;
String qrurl3;
final String lowercase_qrurl = qrurl.toLowerCase();
if (!lowercase_qrurl.startsWith("http://") && !lowercase_qrurl.startsWith("https://")) {
qrurl3 = "http://" + qrurl;

Intent url = new Intent(Intent.ACTION_VIEW);/// !!!!
url.setData(Uri.parse(qrurl3));
caption = getResources().getStringArray(R.array.url_array)[0];
startActivity(Intent.createChooser(url, caption));
} else {
Intent url = new Intent(Intent.ACTION_VIEW);/// !!!!
url.setData(Uri.parse(qrurl).normalizeScheme());
caption = getResources().getStringArray(R.array.url_array)[0];
startActivity(Intent.createChooser(url, caption));

String urlForIntentData = qrurl;
if (!qrurl.matches(VALID_RFC3986_PROTOCOL_SCHEME)) {
urlForIntentData = "http://" + qrurl;
}
Intent url = new Intent(Intent.ACTION_VIEW);/// !!!!
url.setData(Uri.parse(urlForIntentData).normalizeScheme());
String caption = getResources().getStringArray(R.array.url_array)[0];
startActivity(Intent.createChooser(url, caption));
}
}

Expand Down
55 changes: 55 additions & 0 deletions app/src/main/res/drawable/ic_baseline_qr_code_dots_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorIcons"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/white"
android:pathData="M5,7 a2,2 0 1,1 4,0
a2,2 0 1,1 -4,0
h-2
a4,4 0 1,0 8,0
a4,4 0 1,0 -8,0 Z" />

<path
android:fillColor="@color/white"
android:pathData="M5,17 a2,2 0 1,1 4,0
a2,2 0 1,1 -4,0
h-2
a4,4 0 1,0 8,0
a4,4 0 1,0 -8,0 Z" />

<path
android:fillColor="@color/white"
android:pathData="M15,7 a2,2 0 1,1 4,0
a2,2 0 1,1 -4,0
h-2
a4,4 0 1,0 8,0
a4,4 0 1,0 -8,0 Z" />

<path
android:fillColor="@android:color/white"
android:pathData="M19,20a1,1 0 1,1 2,0a1,1 0 1,1 -2,0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M13,14a1,1 0 1,1 2,0a1,1 0 1,1 -2,0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M15,16a1,1 0 1,1 2,0a1,1 0 1,1 -2,0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M13,18a1,1 0 1,1 2,0a1,1 0 1,1 -2,0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M15,20a1,1 0 1,1 2,0a1,1 0 1,1 -2,0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M17,18a1,1 0 1,1 2,0a1,1 0 1,1 -2,0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M17,14a1,1 0 1,1 2,0a1,1 0 1,1 -2,0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M19,16a1,1 0 1,1 2,0a1,1 0 1,1 -2,0z" />
</vector>

0 comments on commit 8b77268

Please sign in to comment.