commit 26a8c7f6e86c44c04ab24cb59b34bb822ffe9a76 Author: HeshamTB <38921037+HeshamTB@users.noreply.github.com> Date: Wed May 2 21:02:50 2018 +0300 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5edb4ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser new file mode 100644 index 0000000..30039a6 Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..c0f68ed --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + \ 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/README.md b/README.md new file mode 100644 index 0000000..38adf5a --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# BarcodeScanner2 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..b16d5ea --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "team3.kau.ie201.barcodescanner2" + minSdkVersion 16 + targetSdkVersion 16 + versionCode 1 + versionName '0.2' + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + productFlavors { + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support:appcompat-v7:27.1.0' + implementation 'com.android.support.constraint:constraint-layout:1.0.2' + implementation 'com.android.support:design:27.1.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.1' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' +} diff --git a/app/libs/activation.jar b/app/libs/activation.jar new file mode 100644 index 0000000..614a03c Binary files /dev/null and b/app/libs/activation.jar differ diff --git a/app/libs/additionnal.jar b/app/libs/additionnal.jar new file mode 100644 index 0000000..aeb9611 Binary files /dev/null and b/app/libs/additionnal.jar differ diff --git a/app/libs/mail.jar b/app/libs/mail.jar new file mode 100644 index 0000000..ea594fd Binary files /dev/null and b/app/libs/mail.jar differ 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/src/androidTest/java/team3/kau/ie201/barcodescanner2/ExampleInstrumentedTest.java b/app/src/androidTest/java/team3/kau/ie201/barcodescanner2/ExampleInstrumentedTest.java new file mode 100644 index 0000000..d10f137 --- /dev/null +++ b/app/src/androidTest/java/team3/kau/ie201/barcodescanner2/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package team3.kau.ie201.barcodescanner2; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.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.getTargetContext(); + + assertEquals("team3.kau.ie201.barcodescanner2", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..afd5428 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java b/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java new file mode 100644 index 0000000..cc2809a --- /dev/null +++ b/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java @@ -0,0 +1,510 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.integration.android; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.ActivityNotFoundException; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; + +/** + *

A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple + * way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the + * project's source code.

+ * + *

Initiating a barcode scan

+ * + *

To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait + * for the result in your app.

+ * + *

It does require that the Barcode Scanner (or work-alike) application is installed. The + * {@link #initiateScan()} method will prompt the user to download the application, if needed.

+ * + *

There are a few steps to using this integration. First, your {@link Activity} must implement + * the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:

+ * + *
{@code
+ * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ *   IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
+ *   if (scanResult != null) {
+ *     // handle scan result
+ *   }
+ *   // else continue with any other code you need in the method
+ *   ...
+ * }
+ * }
+ * + *

This is where you will handle a scan result.

+ * + *

Second, just call this in response to a user action somewhere to begin the scan process:

+ * + *
{@code
+ * IntentIntegrator integrator = new IntentIntegrator(yourActivity);
+ * integrator.initiateScan();
+ * }
+ * + *

Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the + * user was prompted to download the application. This lets the calling app potentially manage the dialog. + * In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()} + * method.

+ * + *

You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use + * {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and + * yes/no button labels can be changed.

+ * + *

Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used + * to invoke the scanner. This can be used to set additional options not directly exposed by this + * simplified API.

+ * + *

By default, this will only allow applications that are known to respond to this intent correctly + * do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}. + * For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.

+ * + *

Sharing text via barcode

+ * + *

To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.

+ * + *

Some code, particularly download integration, was contributed from the Anobiit application.

+ * + *

Enabling experimental barcode formats

+ * + *

Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as + * PDF417. Use {@link #initiateScan(Collection)} with + * a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such + * formats.

+ * + * @author Sean Owen + * @author Fred Lin + * @author Isaac Potoczny-Jones + * @author Brad Drehmer + * @author gcstang + */ +public class IntentIntegrator { + + public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits + private static final String TAG = IntentIntegrator.class.getSimpleName(); + + public static final String DEFAULT_TITLE = "Install Barcode Scanner?"; + public static final String DEFAULT_MESSAGE = + "This application requires Barcode Scanner. Would you like to install it?"; + public static final String DEFAULT_YES = "Yes"; + public static final String DEFAULT_NO = "No"; + + private static final String BS_PACKAGE = "com.google.zxing.client.android"; + private static final String BSPLUS_PACKAGE = "com.srowen.bs.android"; + + // supported barcode formats + public static final Collection PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14"); + public static final Collection ONE_D_CODE_TYPES = + list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128", + "ITF", "RSS_14", "RSS_EXPANDED"); + public static final Collection QR_CODE_TYPES = Collections.singleton("QR_CODE"); + public static final Collection DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX"); + + public static final Collection ALL_CODE_TYPES = null; + + public static final List TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE); + public static final List TARGET_ALL_KNOWN = list( + BSPLUS_PACKAGE, // Barcode Scanner+ + BSPLUS_PACKAGE + ".simple", // Barcode Scanner+ Simple + BS_PACKAGE // Barcode Scanner + // What else supports this intent? + ); + + // Should be FLAG_ACTIVITY_NEW_DOCUMENT in API 21+. + // Defined once here because the current value is deprecated, so generates just one warning + private static final int FLAG_NEW_DOC = Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET; + + private final Activity activity; + private final Fragment fragment; + + private String title; + private String message; + private String buttonYes; + private String buttonNo; + private List targetApplications; + private final Map moreExtras = new HashMap(3); + + /** + * @param activity {@link Activity} invoking the integration + */ + public IntentIntegrator(Activity activity) { + this.activity = activity; + this.fragment = null; + initializeConfiguration(); + } + + /** + * @param fragment {@link Fragment} invoking the integration. + * {@link #startActivityForResult(Intent, int)} will be called on the {@link Fragment} instead + * of an {@link Activity} + */ + public IntentIntegrator(Fragment fragment) { + this.activity = fragment.getActivity(); + this.fragment = fragment; + initializeConfiguration(); + } + + private void initializeConfiguration() { + title = DEFAULT_TITLE; + message = DEFAULT_MESSAGE; + buttonYes = DEFAULT_YES; + buttonNo = DEFAULT_NO; + targetApplications = TARGET_ALL_KNOWN; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setTitleByID(int titleID) { + title = activity.getString(titleID); + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setMessageByID(int messageID) { + message = activity.getString(messageID); + } + + public String getButtonYes() { + return buttonYes; + } + + public void setButtonYes(String buttonYes) { + this.buttonYes = buttonYes; + } + + public void setButtonYesByID(int buttonYesID) { + buttonYes = activity.getString(buttonYesID); + } + + public String getButtonNo() { + return buttonNo; + } + + public void setButtonNo(String buttonNo) { + this.buttonNo = buttonNo; + } + + public void setButtonNoByID(int buttonNoID) { + buttonNo = activity.getString(buttonNoID); + } + + public Collection getTargetApplications() { + return targetApplications; + } + + public final void setTargetApplications(List targetApplications) { + if (targetApplications.isEmpty()) { + throw new IllegalArgumentException("No target applications"); + } + this.targetApplications = targetApplications; + } + + public void setSingleTargetApplication(String targetApplication) { + this.targetApplications = Collections.singletonList(targetApplication); + } + + public Map getMoreExtras() { + return moreExtras; + } + + public final void addExtra(String key, Object value) { + moreExtras.put(key, value); + } + + /** + * Initiates a scan for all known barcode types with the default camera. + * + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan() { + return initiateScan(ALL_CODE_TYPES, -1); + } + + /** + * Initiates a scan for all known barcode types with the specified camera. + * + * @param cameraId camera ID of the camera to use. A negative value means "no preference". + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan(int cameraId) { + return initiateScan(ALL_CODE_TYPES, cameraId); + } + + /** + * Initiates a scan, using the default camera, only for a certain set of barcode types, given as strings corresponding + * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants + * like {@link #PRODUCT_CODE_TYPES} for example. + * + * @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan(Collection desiredBarcodeFormats) { + return initiateScan(desiredBarcodeFormats, -1); + } + + /** + * Initiates a scan, using the specified camera, only for a certain set of barcode types, given as strings corresponding + * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants + * like {@link #PRODUCT_CODE_TYPES} for example. + * + * @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for + * @param cameraId camera ID of the camera to use. A negative value means "no preference". + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + */ + public final AlertDialog initiateScan(Collection desiredBarcodeFormats, int cameraId) { + Intent intentScan = new Intent(BS_PACKAGE + ".SCAN"); + intentScan.addCategory(Intent.CATEGORY_DEFAULT); + + // check which types of codes to scan for + if (desiredBarcodeFormats != null) { + // set the desired barcode types + StringBuilder joinedByComma = new StringBuilder(); + for (String format : desiredBarcodeFormats) { + if (joinedByComma.length() > 0) { + joinedByComma.append(','); + } + joinedByComma.append(format); + } + intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString()); + } + + // check requested camera ID + if (cameraId >= 0) { + intentScan.putExtra("SCAN_CAMERA_ID", cameraId); + } + + String targetAppPackage = findTargetAppPackage(intentScan); + if (targetAppPackage == null) { + return showDownloadDialog(); + } + intentScan.setPackage(targetAppPackage); + intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intentScan.addFlags(FLAG_NEW_DOC); + attachMoreExtras(intentScan); + startActivityForResult(intentScan, REQUEST_CODE); + return null; + } + + /** + * Start an activity. This method is defined to allow different methods of activity starting for + * newer versions of Android and for compatibility library. + * + * @param intent Intent to start. + * @param code Request code for the activity + * @see Activity#startActivityForResult(Intent, int) + * @see Fragment#startActivityForResult(Intent, int) + */ + protected void startActivityForResult(Intent intent, int code) { + if (fragment == null) { + activity.startActivityForResult(intent, code); + } else { + fragment.startActivityForResult(intent, code); + } + } + + private String findTargetAppPackage(Intent intent) { + PackageManager pm = activity.getPackageManager(); + List availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + if (availableApps != null) { + for (String targetApp : targetApplications) { + if (contains(availableApps, targetApp)) { + return targetApp; + } + } + } + return null; + } + + private static boolean contains(Iterable availableApps, String targetApp) { + for (ResolveInfo availableApp : availableApps) { + String packageName = availableApp.activityInfo.packageName; + if (targetApp.equals(packageName)) { + return true; + } + } + return false; + } + + private AlertDialog showDownloadDialog() { + AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity); + downloadDialog.setTitle(title); + downloadDialog.setMessage(message); + downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + String packageName; + if (targetApplications.contains(BS_PACKAGE)) { + // Prefer to suggest download of BS if it's anywhere in the list + packageName = BS_PACKAGE; + } else { + // Otherwise, first option: + packageName = targetApplications.get(0); + } + Uri uri = Uri.parse("market://details?id=" + packageName); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + try { + if (fragment == null) { + activity.startActivity(intent); + } else { + fragment.startActivity(intent); + } + } catch (ActivityNotFoundException anfe) { + // Hmm, market is not installed + Log.w(TAG, "Google Play is not installed; cannot install " + packageName); + } + } + }); + downloadDialog.setNegativeButton(buttonNo, null); + downloadDialog.setCancelable(true); + return downloadDialog.show(); + } + + + /** + *

Call this from your {@link Activity}'s + * {@link Activity#onActivityResult(int, int, Intent)} method.

+ * + * @param requestCode request code from {@code onActivityResult()} + * @param resultCode result code from {@code onActivityResult()} + * @param intent {@link Intent} from {@code onActivityResult()} + * @return null if the event handled here was not related to this class, or + * else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning, + * the fields will be null. + */ + public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) { + if (requestCode == REQUEST_CODE) { + if (resultCode == Activity.RESULT_OK) { + String contents = intent.getStringExtra("SCAN_RESULT"); + String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT"); + byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES"); + int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE); + Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation; + String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL"); + return new IntentResult(contents, + formatName, + rawBytes, + orientation, + errorCorrectionLevel); + } + return new IntentResult(); + } + return null; + } + + + /** + * Defaults to type "TEXT_TYPE". + * + * @param text the text string to encode as a barcode + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + * @see #shareText(CharSequence, CharSequence) + */ + public final AlertDialog shareText(CharSequence text) { + return shareText(text, "TEXT_TYPE"); + } + + /** + * Shares the given text by encoding it as a barcode, such that another user can + * scan the text off the screen of the device. + * + * @param text the text string to encode as a barcode + * @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants. + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + */ + public final AlertDialog shareText(CharSequence text, CharSequence type) { + Intent intent = new Intent(); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setAction(BS_PACKAGE + ".ENCODE"); + intent.putExtra("ENCODE_TYPE", type); + intent.putExtra("ENCODE_DATA", text); + String targetAppPackage = findTargetAppPackage(intent); + if (targetAppPackage == null) { + return showDownloadDialog(); + } + intent.setPackage(targetAppPackage); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.addFlags(FLAG_NEW_DOC); + attachMoreExtras(intent); + if (fragment == null) { + activity.startActivity(intent); + } else { + fragment.startActivity(intent); + } + return null; + } + + private static List list(String... values) { + return Collections.unmodifiableList(Arrays.asList(values)); + } + + private void attachMoreExtras(Intent intent) { + for (Map.Entry entry : moreExtras.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + // Kind of hacky + if (value instanceof Integer) { + intent.putExtra(key, (Integer) value); + } else if (value instanceof Long) { + intent.putExtra(key, (Long) value); + } else if (value instanceof Boolean) { + intent.putExtra(key, (Boolean) value); + } else if (value instanceof Double) { + intent.putExtra(key, (Double) value); + } else if (value instanceof Float) { + intent.putExtra(key, (Float) value); + } else if (value instanceof Bundle) { + intent.putExtra(key, (Bundle) value); + } else { + intent.putExtra(key, value.toString()); + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/google/zxing/integration/android/IntentResult.java b/app/src/main/java/com/google/zxing/integration/android/IntentResult.java new file mode 100644 index 0000000..661c1d2 --- /dev/null +++ b/app/src/main/java/com/google/zxing/integration/android/IntentResult.java @@ -0,0 +1,95 @@ +package com.google.zxing.integration.android; + +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/** + *

Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.

+ * + * @author Sean Owen + */ +public final class IntentResult { + + private final String contents; + private final String formatName; + private final byte[] rawBytes; + private final Integer orientation; + private final String errorCorrectionLevel; + + IntentResult() { + this(null, null, null, null, null); + } + + IntentResult(String contents, + String formatName, + byte[] rawBytes, + Integer orientation, + String errorCorrectionLevel) { + this.contents = contents; + this.formatName = formatName; + this.rawBytes = rawBytes; + this.orientation = orientation; + this.errorCorrectionLevel = errorCorrectionLevel; + } + + /** + * @return raw content of barcode + */ + public String getContents() { + return contents; + } + + /** + * @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names. + */ + public String getFormatName() { + return formatName; + } + + /** + * @return raw bytes of the barcode content, if applicable, or null otherwise + */ + public byte[] getRawBytes() { + return rawBytes; + } + + /** + * @return rotation of the image, in degrees, which resulted in a successful scan. May be null. + */ + public Integer getOrientation() { + return orientation; + } + + /** + * @return name of the error correction level used in the barcode, if applicable + */ + public String getErrorCorrectionLevel() { + return errorCorrectionLevel; + } + + @Override + public String toString() { + int rawBytesLength = rawBytes == null ? 0 : rawBytes.length; + return "Format: " + formatName + '\n' + + "Contents: " + contents + '\n' + + "Raw bytes: (" + rawBytesLength + " bytes)\n" + + "Orientation: " + orientation + '\n' + + "EC level: " + errorCorrectionLevel + '\n'; + } + +} + diff --git a/app/src/main/java/team3/kau/ie201/barcodescanner2/FlashLightUtilForL.java b/app/src/main/java/team3/kau/ie201/barcodescanner2/FlashLightUtilForL.java new file mode 100644 index 0000000..8a2faa6 --- /dev/null +++ b/app/src/main/java/team3/kau/ie201/barcodescanner2/FlashLightUtilForL.java @@ -0,0 +1,141 @@ +package team3.kau.ie201.barcodescanner2; + +import android.annotation.TargetApi; +import android.graphics.SurfaceTexture; +import android.hardware.camera2.*; + +import android.content.Context; +import android.util.Size; +import android.view.Surface; +import android.widget.Toast; +import java.util.*; + +@TargetApi(23) +public class FlashLightUtilForL { + private CameraCaptureSession mSession; + private CaptureRequest.Builder mBuilder; + private CameraDevice mCameraDevice; + private CameraManager mCameraManager; + + public FlashLightUtilForL(Context context) { + try { + mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); + //here to judge if flash is available + CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics("0"); + boolean flashAvailable = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE); + if (flashAvailable) { + try {mCameraManager.openCamera("0", new MyCameraDeviceStateCallback(), null);} + catch (SecurityException e){e.printStackTrace();} + + + + } else { + //todo: throw Exception + } + //mCameraManager.openCamera("0", new MyCameraDeviceStateCallback(), null); + } catch (Exception e) { + e.printStackTrace(); + } + } + + class MyCameraDeviceStateCallback extends CameraDevice.StateCallback { + + @Override + public void onOpened(CameraDevice camera) { + mCameraDevice = camera; + //get builder + try { + mBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL); + //flash on, default is on + mBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO); + mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH); + List list = new ArrayList(); + SurfaceTexture mSurfaceTexture = new SurfaceTexture(1); + Size size = getSmallestSize(mCameraDevice.getId()); + mSurfaceTexture.setDefaultBufferSize(size.getWidth(), size.getHeight()); + Surface mSurface = new Surface(mSurfaceTexture); + list.add(mSurface); + mBuilder.addTarget(mSurface); + camera.createCaptureSession(list, new MyCameraCaptureSessionStateCallback(), null); + } catch (CameraAccessException e) { + e.printStackTrace(); + } + } + + @Override + public void onDisconnected(CameraDevice camera) { + + } + + @Override + public void onError(CameraDevice camera, int error) { + + } + } + + private Size getSmallestSize(String cameraId) throws CameraAccessException { + Size[] outputSizes = mCameraManager.getCameraCharacteristics(cameraId) + .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) + .getOutputSizes(SurfaceTexture.class); + if (outputSizes == null || outputSizes.length == 0) { + throw new IllegalStateException( + "Camera " + cameraId + "doesn't support any outputSize."); + } + Size chosen = outputSizes[0]; + for (Size s : outputSizes) { + if (chosen.getWidth() >= s.getWidth() && chosen.getHeight() >= s.getHeight()) { + chosen = s; + } + } + return chosen; + } + + /** + * session callback + */ + class MyCameraCaptureSessionStateCallback extends CameraCaptureSession.StateCallback { + + @Override + public void onConfigured(CameraCaptureSession session) { + mSession = session; + try { + mSession.setRepeatingRequest(mBuilder.build(), null, null); + } catch (CameraAccessException e) { + e.printStackTrace(); + } + } + + @Override + public void onConfigureFailed(CameraCaptureSession session) { + + } + } + + public void turnOnFlashLight() { + try { + mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH); + mSession.setRepeatingRequest(mBuilder.build(), null, null); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void turnOffFlashLight() { + try { + mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF); + mSession.setRepeatingRequest(mBuilder.build(), null, null); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void close() { + if (mCameraDevice == null || mSession == null) { + return; + } + mSession.close(); + mCameraDevice.close(); + mCameraDevice = null; + mSession = null; + } +} diff --git a/app/src/main/java/team3/kau/ie201/barcodescanner2/GMailSender.java b/app/src/main/java/team3/kau/ie201/barcodescanner2/GMailSender.java new file mode 100644 index 0000000..e8d7ee7 --- /dev/null +++ b/app/src/main/java/team3/kau/ie201/barcodescanner2/GMailSender.java @@ -0,0 +1,108 @@ +//stackoverflow.com/questions/2020088/sending-email-in-android-using-javamail-api-without-using-the-default-built-in-a + +package team3.kau.ie201.barcodescanner2; + +import java.io.IOException; +import javax.activation.DataHandler; +import javax.activation.DataSource; +import javax.mail.Message; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.Security; +import java.util.Properties; + + +public class GMailSender extends javax.mail.Authenticator { + private String mailhost = "smtp.gmail.com"; + private String user; + private String password; + private Session session; + + static { + //Security.addProvider(new com.provider.JSSEProvider());////////////////////////////////////////////////////////////////////////// + } + + public GMailSender(String user, String password) { + this.user = user; + this.password = password; + + Properties props = new Properties(); + props.setProperty("mail.transport.protocol", "smtp"); + props.setProperty("mail.host", mailhost); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.port", "465"); + props.put("mail.smtp.socketFactory.port", "465"); + props.put("mail.smtp.socketFactory.class", + "javax.net.ssl.SSLSocketFactory"); + props.put("mail.smtp.socketFactory.fallback", "false"); + props.setProperty("mail.smtp.quitwait", "false"); + + session = Session.getDefaultInstance(props, this); + } + + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(user, password); + } + + public synchronized void sendMail(String subject, String body, String sender, String recipients) throws Exception { + try{ + MimeMessage message = new MimeMessage(session); + DataHandler handler = new DataHandler(new ByteArrayDataSource(body.getBytes(), "text/plain")); + message.setSender(new InternetAddress(sender)); + message.setSubject(subject); + message.setDataHandler(handler); + if (recipients.indexOf(',') > 0) + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients)); + else + message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients)); + Transport.send(message); + }catch(Exception e){ + + } + } + + public class ByteArrayDataSource implements DataSource { + private byte[] data; + private String type; + + public ByteArrayDataSource(byte[] data, String type) { + super(); + this.data = data; + this.type = type; + } + + public ByteArrayDataSource(byte[] data) { + super(); + this.data = data; + } + + public void setType(String type) { + this.type = type; + } + + public String getContentType() { + if (type == null) + return "application/octet-stream"; + else + return type; + } + + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(data); + } + + public String getName() { + return "ByteArrayDataSource"; + } + + public OutputStream getOutputStream() throws IOException { + throw new IOException("Not Supported"); + } + } +} diff --git a/app/src/main/java/team3/kau/ie201/barcodescanner2/JSSEProvider.java b/app/src/main/java/team3/kau/ie201/barcodescanner2/JSSEProvider.java new file mode 100644 index 0000000..a0f2089 --- /dev/null +++ b/app/src/main/java/team3/kau/ie201/barcodescanner2/JSSEProvider.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Alexander Y. Kleymenov + * @version $Revision$ + */ +package team3.kau.ie201.barcodescanner2; + +import java.security.AccessController; +import java.security.Provider; + +public class JSSEProvider extends Provider { + + public JSSEProvider() { + super("HarmonyJSSE", 1.0, "Harmony JSSE Provider"); + AccessController.doPrivileged(new java.security.PrivilegedAction() { + public Void run() { + put("SSLContext.TLS", + "org.apache.harmony.xnet.provider.jsse.SSLContextImpl"); + put("Alg.Alias.SSLContext.TLSv1", "TLS"); + put("KeyManagerFactory.X509", + "org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl"); + put("TrustManagerFactory.X509", + "org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl"); + return null; + } + }); + } +} + + diff --git a/app/src/main/java/team3/kau/ie201/barcodescanner2/MainActivity.java b/app/src/main/java/team3/kau/ie201/barcodescanner2/MainActivity.java new file mode 100644 index 0000000..c8367a9 --- /dev/null +++ b/app/src/main/java/team3/kau/ie201/barcodescanner2/MainActivity.java @@ -0,0 +1,223 @@ + +//https://code.tutsplus.com/tutorials/android-sdk-create-a-barcode-reader--mobile-17162 +package team3.kau.ie201.barcodescanner2; + +import android.annotation.TargetApi; +import android.graphics.Camera; +import android.hardware.camera2.CameraManager; +import android.os.Bundle; +import android.util.Log; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.Snackbar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.view.Menu; +import android.view.MenuItem; +import android.app.Activity; +import android.content.Intent; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.Switch; +import android.widget.TextView; +import android.widget.Toast; +import android.content.Context; +import android.widget.ToggleButton; + + +import com.google.zxing.integration.android.IntentResult; +import com.google.zxing.integration.android.IntentIntegrator; + + + +public class MainActivity extends AppCompatActivity implements OnClickListener { + + private Button button; + boolean passed1, passed2 = false; + + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + }); + button = (Button)findViewById(R.id.button);// + button.setOnClickListener(this);// + + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + + //noinspection SimplifiableIfStatement + if (id == R.id.action_settings) { + return true; + } + + return super.onOptionsItemSelected(item); + } + + public void onClick(View v){ + + // if button clicked + if(v.getId()== R.id.button){ + //start barcode scan cam 1,2 + IntentIntegrator scanIntegrator = new IntentIntegrator(this); + scanIntegrator.initiateScan(0); + + } + } + //---------------------------------------------------------------------------------------------------------------------------- + //Starts after each scan + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + //below this point is our work + //TODO: Split into methods + try { + //get scan result + IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); + + // if not empty + if (scanningResult != null) { + String result = scanningResult.getContents(); + // if key is correct + if (result.equalsIgnoreCase("team3") + || result.equalsIgnoreCase("member1") + || result.equalsIgnoreCase("member2") + || result.equalsIgnoreCase("member3") + || result.equalsIgnoreCase("member4")) { + // if it is key 1 + if (result.equalsIgnoreCase("team3")) { + Toast toast = Toast.makeText(getApplicationContext(), "Key 1 Accepted", Toast.LENGTH_SHORT); + toast.show(); + passed1 = true; + + //take shot of barcode 2 + IntentIntegrator scanIntegrator = new IntentIntegrator(this); + scanIntegrator.initiateScan(0); + + } + + else if (result.equalsIgnoreCase("member1") + || result.equalsIgnoreCase("member1") + || result.equalsIgnoreCase("member2") + || result.equalsIgnoreCase("member3") + || result.equalsIgnoreCase("member4") + && passed1) { + + passed1 = false; + Toast toast = Toast.makeText(getApplicationContext(), "Opening lock", Toast.LENGTH_SHORT); + toast.show(); + + //flash LED + flashLightOn(); + + IntentIntegrator scanIntegrator = new IntentIntegrator(this); + scanIntegrator.initiateScan(0); + + + //Scan again if cont. is checked + //make flash on! + //open door + //FlashLightUtilForL flash = new FlashLightUtilForL(this); + //flash.turnOnFlashLight(); + } + + else { + Toast toast = Toast.makeText(getApplicationContext(), "Key not accepted", Toast.LENGTH_LONG); + toast.show(); + passed1 = false; + IntentIntegrator scanIntegrator = new IntentIntegrator(this); + scanIntegrator.initiateScan(0); + + + } + + } + + else { + Toast toast = Toast.makeText(getApplicationContext(), "Key not accepted", Toast.LENGTH_SHORT); + toast.show(); + passed1 = false; + IntentIntegrator scanIntegrator = new IntentIntegrator(this); + scanIntegrator.initiateScan(0); + + } + } + else { + Toast toast = Toast.makeText(getApplicationContext(), + "No scan data received!", Toast.LENGTH_SHORT); + toast.show(); + + + } + } + catch (Exception e){ + Toast tost = Toast.makeText(getApplicationContext(), e.toString(),Toast.LENGTH_SHORT); + tost.show(); + + } + } + + private void flashLightOn() { + try { + + //Camera settings from https://developer.android.com/reference/android/hardware/Camera.html + android.hardware.Camera.Parameters para; + + android.hardware.Camera cam = android.hardware.Camera.open(0); + para = cam.getParameters(); + para.setFlashMode(para.FLASH_MODE_TORCH); + cam.setParameters(para); + + //Flash on + cam.startPreview(); + + //Delay + int dum=0; + for (int i =0;i<999999;i++){ + i++; + dum = i + dum; + dum++; + for (int ii = 0;ii<99999999;i++){ + ii++; + dum = ii + i + dum; + for (int iii = 0;ii<99999999;i++){ + ii++; + dum = iii + i + dum; + } + } + } + //Flash off + cam.stopPreview(); + cam.release(); + + } + catch (Exception e) + { + + } + } +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..eed4d89 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml new file mode 100644 index 0000000..abb32a7 --- /dev/null +++ b/app/src/main/res/layout/content_main.xml @@ -0,0 +1,44 @@ + + + +