From 4917e7a6163404898cc7eeca7bc0de4bcac060f3 Mon Sep 17 00:00:00 2001 From: Marc Ole Bulling Date: Thu, 9 Apr 2020 10:57:34 +0200 Subject: [PATCH] Initial commit --- .gitignore | 16 ++ .idea/.name | 1 + .idea/codeStyles/Project.xml | 116 +++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/encodings.xml | 6 + .idea/misc.xml | 14 ++ .idea/runConfigurations.xml | 12 ++ app/.gitignore | 1 + app/build.gradle | 41 ++++ app/proguard-rules.pro | 21 ++ app/release/output.json | 1 + .../ExampleInstrumentedTest.java | 27 +++ app/src/main/AndroidManifest.xml | 34 +++ .../barcodebuddyscanner/Api/BBApi.java | 82 ++++++++ .../Api/BBApiCallback.java | 17 ++ .../barcodebuddyscanner/Api/BBService.java | 21 ++ .../ContinuousCaptureActivity.java | 121 +++++++++++ .../barcodebuddyscanner/DebugActivity.java | 19 ++ .../Helper/BeepManager.java | 89 ++++++++ .../Helper/SharedPrefHelper.java | 20 ++ .../barcodebuddyscanner/MainActivity.java | 48 +++++ .../barcodebuddyscanner/SetupActivity.java | 195 ++++++++++++++++++ .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 2888 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 1763 bytes app/src/main/res/drawable-v24/vectorpaint.png | Bin 0 -> 14955 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 4436 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 7459 bytes .../main/res/drawable-xxxhdpi/ic_launcher.png | Bin 0 -> 10362 bytes app/src/main/res/layout/activity_debug.xml | 18 ++ app/src/main/res/layout/activity_main.xml | 43 ++++ app/src/main/res/layout/activity_setup.xml | 121 +++++++++++ app/src/main/res/layout/continuous_scan.xml | 29 +++ app/src/main/res/values/colors.xml | 6 + app/src/main/res/values/dimens.xml | 3 + app/src/main/res/values/strings.xml | 18 ++ app/src/main/res/values/styles.xml | 20 ++ .../barcodebuddyscanner/ExampleUnitTest.java | 17 ++ build.gradle | 27 +++ gradle.properties | 20 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 +++++++++++++++ gradlew.bat | 84 ++++++++ settings.gradle | 2 + 44 files changed, 1493 insertions(+) create mode 100644 .idea/.name create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/release/output.json create mode 100644 app/src/androidTest/java/de/bulling/barcodebuddyscanner/ExampleInstrumentedTest.java create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBApi.java create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBApiCallback.java create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBService.java create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/ContinuousCaptureActivity.java create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/DebugActivity.java create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/Helper/BeepManager.java create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/Helper/SharedPrefHelper.java create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/MainActivity.java create mode 100644 app/src/main/java/de/bulling/barcodebuddyscanner/SetupActivity.java create mode 100644 app/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-v24/vectorpaint.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/layout/activity_debug.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/activity_setup.xml create mode 100644 app/src/main/res/layout/continuous_scan.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/test/java/de/bulling/barcodebuddyscanner/ExampleUnitTest.java create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore index 56cc642..2f9ade1 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,19 @@ lint/generated/ lint/outputs/ lint/tmp/ # lint/reports/ + +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +/logo/ diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..18b279f --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Barcode Buddy Scanner \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..681f41a --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,116 @@ + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..8f1a3b7 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..703e5d4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..2631ef5 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,41 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "de.bulling.barcodebuddyscanner" + minSdkVersion 24 + targetSdkVersion 28 + versionCode 3 + versionName "0.1" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +repositories { + jcenter() +} + +dependencies { + implementation 'com.squareup.retrofit2:retrofit:2.8.1' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.android.material:material:1.1.0' + implementation 'com.journeyapps:zxing-android-embedded:4.1.0' + implementation 'com.google.android.material:material:1.1.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'com.android.support:design:28.0.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/release/output.json b/app/release/output.json new file mode 100644 index 0000000..46c65cf --- /dev/null +++ b/app/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":3,"versionName":"0.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/src/androidTest/java/de/bulling/barcodebuddyscanner/ExampleInstrumentedTest.java b/app/src/androidTest/java/de/bulling/barcodebuddyscanner/ExampleInstrumentedTest.java new file mode 100644 index 0000000..52733f8 --- /dev/null +++ b/app/src/androidTest/java/de/bulling/barcodebuddyscanner/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package de.bulling.barcodebuddyscanner; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("de.bulling.barcodebuddyscanner", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ce2c6c3 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBApi.java b/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBApi.java new file mode 100644 index 0000000..92220d1 --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBApi.java @@ -0,0 +1,82 @@ +package de.bulling.barcodebuddyscanner.Api; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class BBApi { + + private final BBService bbApi; + private final String apiKey; + + private final static int REQUEST_SYSTEM_INFO = 0; + private final static int REQUEST_ACTION_BARCODE = 1; + + public BBApi(final String url, final String apiKey) { + Retrofit retrofit = new Retrofit.Builder() + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl(url) + .build(); + this.apiKey = apiKey; + this.bbApi = retrofit.create(BBService.class); + } + + private void processResponse(final int request, final Call result, final BBApiCallback callback) { + result.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + Object result = null; + try { + JsonObject responseBody = response.body().getAsJsonObject(); + switch (request) { + case REQUEST_SYSTEM_INFO: + result = (Integer) responseBody.get("data").getAsJsonObject().get("version_int").getAsInt(); + break; + case REQUEST_ACTION_BARCODE: + result = (String) responseBody.get("data").getAsJsonObject().get("result").getAsString(); + break; + } + } catch (Exception e) { + e.printStackTrace(); + callback.onError(BBApiCallback.ERROR_OTHER, e.getMessage(), response); + } + callback.onResult(result); + } else { + switch (response.raw().code()) { + case 401: + callback.onError(BBApiCallback.ERROR_UNAUTHORIZED, "Invalid API key", response); + break; + case 404: + callback.onError(BBApiCallback.ERROR_OTHER, "Invalid URL. Please make sure that the URL is correct and URL rewriting enabled.", response); + break; + case 500: + callback.onError(BBApiCallback.ERROR_OTHER, "Server error", response); + break; + default: + callback.onError(BBApiCallback.ERROR_OTHER, "Unknown error occurred. Please check URL.", response); + break; + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + callback.onError(BBApiCallback.ERROR_NETWORK, t.getMessage(), null); + } + }); + } + + public void getVersionInfo(final BBApiCallback callback) { + processResponse(REQUEST_SYSTEM_INFO, this.bbApi.getSystemInfo(this.apiKey), callback); + } + + public void postBarcode(String barcode, final BBApiCallback callback) { + processResponse(REQUEST_ACTION_BARCODE, this.bbApi.postBarcode(this.apiKey, barcode), callback); + } +} diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBApiCallback.java b/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBApiCallback.java new file mode 100644 index 0000000..7218f90 --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBApiCallback.java @@ -0,0 +1,17 @@ +package de.bulling.barcodebuddyscanner.Api; + +import com.google.gson.JsonElement; + +import retrofit2.Response; + +public interface BBApiCallback { + + int ERROR_NETWORK = 0; + int ERROR_UNAUTHORIZED = 1; + int ERROR_OTHER = 2; + + void onResult(Object result); + + void onError(int errorCode, String errorMessage, Response response); + +} diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBService.java b/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBService.java new file mode 100644 index 0000000..e001642 --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/Api/BBService.java @@ -0,0 +1,21 @@ +package de.bulling.barcodebuddyscanner.Api; + +import com.google.gson.JsonElement; + +import retrofit2.Call; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.Header; +import retrofit2.http.POST; + +public interface BBService { + + @GET("system/info") + Call getSystemInfo(@Header("BBUDDY-API-KEY") String authorization); + + @FormUrlEncoded + @POST("action/scan") + Call postBarcode(@Header("BBUDDY-API-KEY") String authorization, @Field("barcode") String barcode); + +} diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/ContinuousCaptureActivity.java b/app/src/main/java/de/bulling/barcodebuddyscanner/ContinuousCaptureActivity.java new file mode 100644 index 0000000..102e387 --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/ContinuousCaptureActivity.java @@ -0,0 +1,121 @@ +package de.bulling.barcodebuddyscanner; + + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.view.View; +import android.view.WindowManager; +import android.widget.Toast; + +import com.google.gson.JsonElement; +import com.google.zxing.ResultPoint; +import com.journeyapps.barcodescanner.BarcodeCallback; +import com.journeyapps.barcodescanner.BarcodeResult; +import com.journeyapps.barcodescanner.DecoratedBarcodeView; + +import java.util.List; + +import de.bulling.barcodebuddyscanner.Api.BBApi; +import de.bulling.barcodebuddyscanner.Api.BBApiCallback; +import de.bulling.barcodebuddyscanner.Helper.BeepManager; +import retrofit2.Response; + + +public class ContinuousCaptureActivity extends Activity { + private DecoratedBarcodeView barcodeView; + private BeepManager beepManager; + private long lastScanTime = 0; + private String lastBarcode = null; + private BBApi bbApi = null; + + private final boolean IS_DEBUG = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.continuous_scan); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + bbApi = new BBApi(preferences.getString("url", null), preferences.getString("key", null)); + + barcodeView = findViewById(R.id.barcode_scanner); + barcodeView.initializeFromIntent(getIntent()); + barcodeView.decodeContinuous(callback); + + beepManager = new BeepManager(this); + } + + + private BarcodeCallback callback = new BarcodeCallback() { + @Override + public void barcodeResult(BarcodeResult result) { + long millisSinceLastScan = (System.currentTimeMillis() - lastScanTime); + if (result.getText() == null || (result.getText().equals(lastBarcode) && millisSinceLastScan < 1500)) { + // Prevent duplicate scans + return; + } + + lastScanTime = System.currentTimeMillis(); + lastBarcode = result.getText(); + barcodeView.setStatusText(result.getText()); + beepManager.playBeepSoundAndVibrate(); + bbApi.postBarcode(result.getText(), new BBApiCallback() { + @Override + public void onResult(Object result) { + if (result instanceof String) + Toast.makeText(ContinuousCaptureActivity.this, + (String) result, Toast.LENGTH_SHORT).show(); + else + Toast.makeText(ContinuousCaptureActivity.this, + R.string.error_unex, Toast.LENGTH_LONG).show(); + } + + @Override + public void onError(int errorCode, String errorMessage, Response response) { + Toast.makeText(ContinuousCaptureActivity.this, + getString(R.string.error) + errorMessage, + Toast.LENGTH_LONG).show(); + if (IS_DEBUG) { + String debugMessage = errorMessage + "\n"; + if (response != null) { + debugMessage = debugMessage + "Received:\n" + response.raw().body(); + } + Intent i = new Intent(ContinuousCaptureActivity.this, DebugActivity.class); + i.putExtra("debug", debugMessage); + ContinuousCaptureActivity.this.startActivity(i); + } + } + }); + + } + + @Override + public void possibleResultPoints(List resultPoints) { + } + }; + + @Override + protected void onResume() { + super.onResume(); + + barcodeView.resume(); + } + + @Override + protected void onPause() { + super.onPause(); + + barcodeView.pause(); + } + + + public void triggerScan(View view) { + barcodeView.decodeSingle(callback); + } + +} \ No newline at end of file diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/DebugActivity.java b/app/src/main/java/de/bulling/barcodebuddyscanner/DebugActivity.java new file mode 100644 index 0000000..3b7e163 --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/DebugActivity.java @@ -0,0 +1,19 @@ +package de.bulling.barcodebuddyscanner; + +import android.os.Bundle; +import android.widget.EditText; + +import androidx.appcompat.app.AppCompatActivity; + +public class DebugActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_debug); + if (getIntent().getStringExtra("debug") != null) { + EditText debugtext = findViewById(R.id.editText3); + debugtext.setText(getIntent().getStringExtra("debug")); + } + } +} diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/Helper/BeepManager.java b/app/src/main/java/de/bulling/barcodebuddyscanner/Helper/BeepManager.java new file mode 100644 index 0000000..6ed2756 --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/Helper/BeepManager.java @@ -0,0 +1,89 @@ +package de.bulling.barcodebuddyscanner.Helper; + +import android.app.Activity; +import android.content.Context; +import android.media.AudioAttributes; +import android.media.AudioManager; +import android.media.SoundPool; +import android.os.Vibrator; + +import de.bulling.barcodebuddyscanner.R; + +/** + * Manages beeps and vibrations. + */ +public final class BeepManager { + + private static final String TAG = BeepManager.class.getSimpleName(); + + private static final float BEEP_VOLUME = 0.10f; + private static final long VIBRATE_DURATION = 200L; + + private final Context context; + + private boolean beepEnabled = true; + private boolean vibrateEnabled = false; + + private SoundPool soundPool; + private int beepSound; + + public BeepManager(Activity activity) { + activity.setVolumeControlStream(AudioManager.STREAM_MUSIC); + + // We do not keep a reference to the Activity itself, to prevent leaks + this.context = activity.getApplicationContext(); + + AudioAttributes attributes = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .build(); + soundPool = new SoundPool.Builder() + .setAudioAttributes(attributes) + .build(); + + beepSound = soundPool.load(context, R.raw.zxing_beep, 1); + } + + public boolean isBeepEnabled() { + return beepEnabled; + } + + /** + * Call updatePrefs() after setting this. + *

+ * If the device is in silent mode, it will not beep. + * + * @param beepEnabled true to enable beep + */ + public void setBeepEnabled(boolean beepEnabled) { + this.beepEnabled = beepEnabled; + } + + public boolean isVibrateEnabled() { + return vibrateEnabled; + } + + /** + * Call updatePrefs() after setting this. + * + * @param vibrateEnabled true to enable vibrate + */ + public void setVibrateEnabled(boolean vibrateEnabled) { + this.vibrateEnabled = vibrateEnabled; + } + + public synchronized void playBeepSoundAndVibrate() { + if (beepEnabled) { + playBeepSound(); + } + if (vibrateEnabled) { + Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + vibrator.vibrate(VIBRATE_DURATION); + } + } + + + public void playBeepSound() { + soundPool.play(beepSound, 1, 1, 1, 0, 1); + } +} diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/Helper/SharedPrefHelper.java b/app/src/main/java/de/bulling/barcodebuddyscanner/Helper/SharedPrefHelper.java new file mode 100644 index 0000000..bb400b6 --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/Helper/SharedPrefHelper.java @@ -0,0 +1,20 @@ +package de.bulling.barcodebuddyscanner.Helper; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +public class SharedPrefHelper { + public static boolean noApiDetailsSaved(Context context) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + return preferences.getBoolean("needsSetup", true); + } + + public static void saveApiDetails(Context context, String url, String key) { + SharedPreferences.Editor preferences = PreferenceManager.getDefaultSharedPreferences(context).edit(); + preferences.putBoolean("needsSetup", false); + preferences.putString("url", url); + preferences.putString("key", key); + preferences.apply(); + } +} diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/MainActivity.java b/app/src/main/java/de/bulling/barcodebuddyscanner/MainActivity.java new file mode 100644 index 0000000..4a959fc --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/MainActivity.java @@ -0,0 +1,48 @@ +package de.bulling.barcodebuddyscanner; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import de.bulling.barcodebuddyscanner.Helper.SharedPrefHelper; + +public class MainActivity extends AppCompatActivity { + + private final int RESULT_SETUP_COMPLETE = 0; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + setupUI(); + + if (SharedPrefHelper.noApiDetailsSaved(this)) + startActivityForResult(new Intent(MainActivity.this, SetupActivity.class), RESULT_SETUP_COMPLETE); + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == RESULT_SETUP_COMPLETE) { + if (SharedPrefHelper.noApiDetailsSaved(this)) + finish(); + } + } + + private void setupUI() { + ImageView image = findViewById(R.id.imageView2); + image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(MainActivity.this, ContinuousCaptureActivity.class)); + } + }); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + } + +} diff --git a/app/src/main/java/de/bulling/barcodebuddyscanner/SetupActivity.java b/app/src/main/java/de/bulling/barcodebuddyscanner/SetupActivity.java new file mode 100644 index 0000000..3b5136e --- /dev/null +++ b/app/src/main/java/de/bulling/barcodebuddyscanner/SetupActivity.java @@ -0,0 +1,195 @@ +package de.bulling.barcodebuddyscanner; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.gson.JsonElement; +import com.google.zxing.integration.android.IntentIntegrator; +import com.google.zxing.integration.android.IntentResult; + +import org.json.JSONException; +import org.json.JSONObject; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import de.bulling.barcodebuddyscanner.Api.BBApi; +import de.bulling.barcodebuddyscanner.Api.BBApiCallback; +import de.bulling.barcodebuddyscanner.Helper.SharedPrefHelper; +import retrofit2.Response; + +import static de.bulling.barcodebuddyscanner.Api.BBApiCallback.ERROR_NETWORK; +import static de.bulling.barcodebuddyscanner.Api.BBApiCallback.ERROR_OTHER; +import static de.bulling.barcodebuddyscanner.Api.BBApiCallback.ERROR_UNAUTHORIZED; + +public class SetupActivity extends AppCompatActivity { + + private Button buttonScan; + private Button buttonConnect; + private ProgressBar progressBar; + private EditText editTextUrl; + private EditText editTextApi; + + private final int MIN_BBUDDY_VERSION = 1500; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_setup); + setupUi(); + } + + //When setup QR code is scanned + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); + if (result != null) { + if (result.getContents() != null) { + parseQrData(result.getContents()); + } + } else { + super.onActivityResult(requestCode, resultCode, data); + } + } + + private void parseQrData(String qrCodeContent) { + if (!qrCodeContent.contains("issetup")) { + Toast.makeText(SetupActivity.this, R.string.e_invalidqr, Toast.LENGTH_LONG).show(); + processError(ERROR_OTHER, null); + buttonConnect.setVisibility(View.INVISIBLE); + } else { + try { + JSONObject setupData = new JSONObject(qrCodeContent); + String url = setupData.getString("url"); + String key = setupData.getString("key"); + processConnection(url, key); + } catch (JSONException e) { + e.printStackTrace(); + processError(ERROR_OTHER, e.getMessage()); + } + } + } + + + private void processConnection(final String url, final String key) { + buttonScan.setEnabled(false); + progressBar.setVisibility(View.VISIBLE); + editTextUrl.setText(url); + editTextUrl.setVisibility(View.VISIBLE); + editTextApi.setText(key); + editTextApi.setVisibility(View.VISIBLE); + BBApi api; + try { + api = new BBApi(url, key); + } catch (IllegalArgumentException e) { + processError(ERROR_OTHER, e.getMessage()); + return; + } + api.getVersionInfo(new BBApiCallback() { + @Override + public void onResult(Object result) { + if (result instanceof Integer) { + if ((Integer) result >= MIN_BBUDDY_VERSION) { + Toast.makeText(SetupActivity.this, + SetupActivity.this.getString(R.string.tut_connected), + Toast.LENGTH_LONG).show(); + + SharedPrefHelper.saveApiDetails(SetupActivity.this, url, key); + SetupActivity.this.finish(); + } else + processError(ERROR_OTHER, SetupActivity.this.getString(R.string.error_too_old)); + } else + processError(ERROR_OTHER, SetupActivity.this.getString(R.string.error_unex)); + } + + @Override + public void onError(int errorCode, String errorMessage, Response response) { + processError(errorCode, errorMessage); + } + }); + } + + private void setupUi() { + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + progressBar = findViewById(R.id.progressBar); + editTextUrl = findViewById(R.id.editText); + editTextApi = findViewById(R.id.editText2); + buttonConnect = findViewById(R.id.button2); + buttonScan = findViewById(R.id.button); + setUpButtons(); + } + + private void setUpButtons() { + TextView privacyPolicy = findViewById(R.id.textView3); + buttonScan.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + IntentIntegrator integrator = new IntentIntegrator(SetupActivity.this); + integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE); + integrator.setPrompt(getString(R.string.tut_scan)); + integrator.setOrientationLocked(false); + integrator.setBeepEnabled(true); + integrator.setBarcodeImageEnabled(true); + integrator.initiateScan(); + } + }); + buttonConnect.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + buttonConnect.setEnabled(false); + editTextApi.setEnabled(false); + editTextUrl.setEnabled(false); + ensureTrailingSlashExists(editTextUrl); + processConnection(editTextUrl.getText().toString(), editTextApi.getText().toString()); + } + }); + + privacyPolicy.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String url = "https://www.bulling.mobi/en/privacypolicy.html"; + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse(url)); + startActivity(i); + } + }); + } + + + private void processError(int errorCode, String errorMessage) { + //TODO + switch (errorCode) { + case ERROR_NETWORK: + break; + case ERROR_UNAUTHORIZED: + break; + case ERROR_OTHER: + break; + } + progressBar.setVisibility(View.GONE); + buttonConnect.setEnabled(true); + buttonConnect.setVisibility(View.VISIBLE); + editTextUrl.setEnabled(true); + editTextApi.setEnabled(true); + if (errorMessage != null) + Toast.makeText(SetupActivity.this, + SetupActivity.this.getString(R.string.error_cnc) + errorMessage, + Toast.LENGTH_LONG).show(); + } + + + @SuppressLint("SetTextI18n") + private static void ensureTrailingSlashExists(EditText editText) { + String text = editText.getText().toString(); + if (!text.endsWith("/")) + editText.setText(text + "/"); + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a3d65e9f7766a23b45598fb02bb137c0284458 GIT binary patch literal 2888 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 FV1j7VJ6!+( literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-v24/vectorpaint.png b/app/src/main/res/drawable-v24/vectorpaint.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce8aac8f5dab8afc38d2ac17ebb98186832c50e GIT binary patch literal 14955 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ec726eb005b6bd6b029c7ce19a80fe26cfbcfa17 GIT binary patch literal 10362 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_debug.xml b/app/src/main/res/layout/activity_debug.xml new file mode 100644 index 0000000..e72fce3 --- /dev/null +++ b/app/src/main/res/layout/activity_debug.xml @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..802e451 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_setup.xml b/app/src/main/res/layout/activity_setup.xml new file mode 100644 index 0000000..1c1b0a8 --- /dev/null +++ b/app/src/main/res/layout/activity_setup.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + +