├── .github ├── dependabot.yml ├── release.yml └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── LICENSE.md ├── QRGenearator ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── androidmads │ │ └── library │ │ └── qrgenearator │ │ ├── BarcodeEncoder.java │ │ ├── BarcodeFormat.java │ │ ├── QRGContents.java │ │ ├── QRGEncoder.java │ │ └── QRGSaver.java │ └── res │ └── values │ └── strings.xml ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── androidmads │ │ └── example │ │ ├── GenDataActivity.java │ │ ├── GenQRActivity.java │ │ └── MainActivity.java │ └── res │ ├── layout │ ├── activity_gen_data.xml │ ├── activity_gen_q_r.xml │ └── activity_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── settings.gradle └── vCardQRGenerator ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── kodobit │ └── vcardqrgenerator │ └── ExampleInstrumentedTest.java ├── main └── AndroidManifest.xml └── test └── java └── com └── kodobit └── vcardqrgenerator └── ExampleUnitTest.java /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gradle" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" # Location of package manifests 14 | schedule: 15 | interval: "weekly" -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - ignore-for-release 5 | authors: 6 | - someuser 7 | categories: 8 | - title: Breaking Changes 🛠 9 | labels: 10 | - breaking-change 11 | - title: Exciting New Features 🎉 12 | labels: 13 | - enhancement 14 | - title: Other Changes 15 | labels: 16 | - "*" -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | name: Build 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - uses: actions/setup-java@v1 17 | with: 18 | java-version: 17 19 | - name: Build with Gradle 20 | run: ./gradlew build 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | name: Publish release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | - name: Find Tag 18 | id: tagger 19 | uses: jimschubert/query-tag-action@v2 20 | with: 21 | skip-unshallow: 'true' 22 | commit-ish: HEAD 23 | - name: Check pre-release 24 | run: | 25 | echo "tag=${{steps.tagger.outputs.tag}}" 26 | if [[ ${{ steps.tagger.outputs.tag }} == *alpha* || ${{ steps.tagger.outputs.tag }} == *beta* ]] 27 | then 28 | prerelease=true 29 | else 30 | prerelease=false 31 | fi 32 | echo "PRE_RELEASE=$prerelease" >> $GITHUB_ENV 33 | echo "prerelease=$prerelease" 34 | - name: Install JDK 35 | uses: actions/setup-java@v3 36 | with: 37 | distribution: 'adopt' 38 | java-version: 17 39 | - name: Install Android SDK 40 | uses: hannesa2/action-android/install-sdk@0.1.4.10 41 | - name: Build project 42 | run: ./gradlew assembleRelease 43 | env: 44 | VERSION: ${{steps.tagger.outputs.tag}} 45 | - name: Create Release 46 | uses: softprops/action-gh-release@v1 47 | with: 48 | tag_name: ${{steps.tagger.outputs.tag}} 49 | generate_release_notes: true 50 | prerelease: ${{ env.PRE_RELEASE }} 51 | name: ${{steps.tagger.outputs.tag}} 52 | files: | 53 | ./QRGenearator/build/outputs/aar/QRGenearator-release.aar 54 | env: 55 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | local.properties 4 | .idea 5 | .DS_Store 6 | build 7 | captures 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 AndroidMad / Mushtaq M A 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QRGenearator/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'maven-publish' 3 | 4 | android { 5 | defaultConfig { 6 | minSdkVersion 19 7 | compileSdk 34 8 | targetSdk 34 9 | } 10 | buildTypes { 11 | release { 12 | minifyEnabled false 13 | consumerProguardFile('proguard-sdk.pro') 14 | } 15 | } 16 | namespace 'androidmads.library.qrgenearator' 17 | 18 | publishing { 19 | singleVariant("release") { 20 | withSourcesJar() 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation 'com.google.zxing:core:3.5.0' 27 | } 28 | 29 | afterEvaluate { 30 | publishing { 31 | publications { 32 | release(MavenPublication) { 33 | from components.release 34 | groupId = 'com.github.androidmads' 35 | artifactId = 'QRGenearator' 36 | version = '1.0.4' 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /QRGenearator/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in F:\Dev_Tools\Android_Studio\sdk\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /QRGenearator/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /QRGenearator/src/main/java/androidmads/library/qrgenearator/BarcodeEncoder.java: -------------------------------------------------------------------------------- 1 | package androidmads.library.qrgenearator; 2 | 3 | import android.graphics.Bitmap; 4 | import com.google.zxing.BarcodeFormat; 5 | import com.google.zxing.EncodeHintType; 6 | import com.google.zxing.MultiFormatWriter; 7 | import com.google.zxing.WriterException; 8 | import com.google.zxing.common.BitMatrix; 9 | 10 | import java.util.EnumMap; 11 | import java.util.Map; 12 | 13 | public class BarcodeEncoder { 14 | 15 | private int WHITE = 0xFFFFFFFF; 16 | private int BLACK = 0xFF000000; 17 | private int dimension = 500; // Default size 18 | private String contents = null; 19 | private androidmads.library.qrgenearator.BarcodeFormat format = androidmads.library.qrgenearator.BarcodeFormat.CODE_128; // Default to CODE_128 20 | 21 | public void setColorWhite(int color) { 22 | this.WHITE = color; 23 | } 24 | 25 | public void setColorBlack(int color) { 26 | this.BLACK = color; 27 | } 28 | 29 | public int getColorWhite() { 30 | return this.WHITE; 31 | } 32 | 33 | public int getColorBlack() { 34 | return this.BLACK; 35 | } 36 | 37 | public BarcodeEncoder(String data, androidmads.library.qrgenearator.BarcodeFormat format) { 38 | this.contents = data; 39 | this.format = format; 40 | } 41 | 42 | public BarcodeEncoder(String data, androidmads.library.qrgenearator.BarcodeFormat format, int dimension) { 43 | this.contents = data; 44 | this.format = format; 45 | this.dimension = dimension; 46 | } 47 | 48 | public Bitmap getBitmap() { 49 | return getBitmap(0); 50 | } 51 | 52 | public Bitmap getBitmap(int margin) { 53 | if (contents == null || contents.isEmpty()) return null; 54 | try { 55 | Map hints = new EnumMap<>(EncodeHintType.class); 56 | hints.put(EncodeHintType.MARGIN, margin); 57 | MultiFormatWriter writer = new MultiFormatWriter(); 58 | BitMatrix result = writer.encode(contents, convertToZXingFormat(format), dimension, dimension, hints); 59 | int width = result.getWidth(); 60 | int height = result.getHeight(); 61 | int[] pixels = new int[width * height]; 62 | 63 | for (int y = 0; y < height; y++) { 64 | int offset = y * width; 65 | for (int x = 0; x < width; x++) { 66 | pixels[offset + x] = result.get(x, y) ? getColorBlack() : getColorWhite(); 67 | } 68 | } 69 | 70 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 71 | bitmap.setPixels(pixels, 0, width, 0, 0, width, height); 72 | return bitmap; 73 | } catch (WriterException e) { 74 | e.printStackTrace(); 75 | return null; 76 | } 77 | } 78 | 79 | public static BarcodeFormat convertToZXingFormat(androidmads.library.qrgenearator.BarcodeFormat aFormat) { 80 | if (aFormat == null) { 81 | throw new IllegalArgumentException("Format cannot be null"); 82 | } 83 | 84 | switch (aFormat) { 85 | case AZTEC: 86 | return BarcodeFormat.AZTEC; 87 | case CODABAR: 88 | return BarcodeFormat.CODABAR; 89 | case CODE_39: 90 | return BarcodeFormat.CODE_39; 91 | case CODE_93: 92 | return BarcodeFormat.CODE_93; 93 | case CODE_128: 94 | return BarcodeFormat.CODE_128; 95 | case DATA_MATRIX: 96 | return BarcodeFormat.DATA_MATRIX; 97 | case EAN_8: 98 | return BarcodeFormat.EAN_8; 99 | case EAN_13: 100 | return BarcodeFormat.EAN_13; 101 | case ITF: 102 | return BarcodeFormat.ITF; 103 | case MAXICODE: 104 | return BarcodeFormat.MAXICODE; 105 | case PDF_417: 106 | return BarcodeFormat.PDF_417; 107 | case QR_CODE: 108 | return BarcodeFormat.QR_CODE; 109 | case RSS_14: 110 | return BarcodeFormat.RSS_14; 111 | case RSS_EXPANDED: 112 | return BarcodeFormat.RSS_EXPANDED; 113 | case UPC_A: 114 | return BarcodeFormat.UPC_A; 115 | case UPC_E: 116 | return BarcodeFormat.UPC_E; 117 | case UPC_EAN_EXTENSION: 118 | return BarcodeFormat.UPC_EAN_EXTENSION; 119 | default: 120 | throw new IllegalArgumentException("Unsupported format: " + aFormat); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /QRGenearator/src/main/java/androidmads/library/qrgenearator/BarcodeFormat.java: -------------------------------------------------------------------------------- 1 | package androidmads.library.qrgenearator; 2 | 3 | public enum BarcodeFormat { 4 | 5 | /** Aztec 2D barcode format. */ 6 | AZTEC, 7 | 8 | /** CODABAR 1D format. */ 9 | CODABAR, 10 | 11 | /** Code 39 1D format. */ 12 | CODE_39, 13 | 14 | /** Code 93 1D format. */ 15 | CODE_93, 16 | 17 | /** Code 128 1D format. */ 18 | CODE_128, 19 | 20 | /** Data Matrix 2D barcode format. */ 21 | DATA_MATRIX, 22 | 23 | /** EAN-8 1D format. */ 24 | EAN_8, 25 | 26 | /** EAN-13 1D format. */ 27 | EAN_13, 28 | 29 | /** ITF (Interleaved Two of Five) 1D format. */ 30 | ITF, 31 | 32 | /** MaxiCode 2D barcode format. */ 33 | MAXICODE, 34 | 35 | /** PDF417 format. */ 36 | PDF_417, 37 | 38 | /** QR Code 2D barcode format. */ 39 | QR_CODE, 40 | 41 | /** RSS 14 */ 42 | RSS_14, 43 | 44 | /** RSS EXPANDED */ 45 | RSS_EXPANDED, 46 | 47 | /** UPC-A 1D format. */ 48 | UPC_A, 49 | 50 | /** UPC-E 1D format. */ 51 | UPC_E, 52 | 53 | /** UPC/EAN extension format. Not a stand-alone format. */ 54 | UPC_EAN_EXTENSION 55 | 56 | } 57 | -------------------------------------------------------------------------------- /QRGenearator/src/main/java/androidmads/library/qrgenearator/QRGContents.java: -------------------------------------------------------------------------------- 1 | package androidmads.library.qrgenearator; 2 | 3 | import android.provider.ContactsContract; 4 | 5 | public class QRGContents { 6 | 7 | public static final class ImageType { 8 | public static int IMAGE_PNG = 0; 9 | public static int IMAGE_JPEG = 1; 10 | public static int IMAGE_WEBP = 2; 11 | } 12 | 13 | public static final class Type { 14 | 15 | // Plain text. Use Intent.putExtra(DATA, string). This can be used for URLs too, but string 16 | // must include "http://" or "https://". 17 | public static final String TEXT = "TEXT_TYPE"; 18 | 19 | // An email type. Use Intent.putExtra(DATA, string) where string is the email address. 20 | public static final String EMAIL = "EMAIL_TYPE"; 21 | 22 | // Use Intent.putExtra(DATA, string) where string is the phone number to call. 23 | public static final String PHONE = "PHONE_TYPE"; 24 | 25 | // An SMS type. Use Intent.putExtra(DATA, string) where string is the number to SMS. 26 | public static final String SMS = "SMS_TYPE"; 27 | 28 | public static final String CONTACT = "CONTACT_TYPE"; 29 | 30 | public static final String LOCATION = "LOCATION_TYPE"; 31 | } 32 | 33 | // When using Type.CONTACT, these arrays provide the keys for adding or retrieving multiple 34 | // phone numbers and addresses. 35 | public static final String[] PHONE_KEYS = { 36 | ContactsContract.Intents.Insert.PHONE, 37 | ContactsContract.Intents.Insert.SECONDARY_PHONE, 38 | ContactsContract.Intents.Insert.TERTIARY_PHONE 39 | }; 40 | 41 | public static final String[] PHONE_TYPE_KEYS = { 42 | ContactsContract.Intents.Insert.PHONE_TYPE, 43 | ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE, 44 | ContactsContract.Intents.Insert.TERTIARY_PHONE_TYPE 45 | }; 46 | 47 | public static final String[] EMAIL_KEYS = { 48 | ContactsContract.Intents.Insert.EMAIL, 49 | ContactsContract.Intents.Insert.SECONDARY_EMAIL, 50 | ContactsContract.Intents.Insert.TERTIARY_EMAIL 51 | }; 52 | 53 | public static final String[] EMAIL_TYPE_KEYS = { 54 | ContactsContract.Intents.Insert.EMAIL_TYPE, 55 | ContactsContract.Intents.Insert.SECONDARY_EMAIL_TYPE, 56 | ContactsContract.Intents.Insert.TERTIARY_EMAIL_TYPE 57 | }; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /QRGenearator/src/main/java/androidmads/library/qrgenearator/QRGEncoder.java: -------------------------------------------------------------------------------- 1 | package androidmads.library.qrgenearator; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.Bundle; 5 | import android.provider.ContactsContract; 6 | import android.telephony.PhoneNumberUtils; 7 | 8 | import com.google.zxing.BarcodeFormat; 9 | import com.google.zxing.EncodeHintType; 10 | import com.google.zxing.MultiFormatWriter; 11 | import com.google.zxing.common.BitMatrix; 12 | 13 | import java.util.Collection; 14 | import java.util.EnumMap; 15 | import java.util.HashSet; 16 | import java.util.Map; 17 | 18 | @SuppressWarnings("ALL") 19 | public class QRGEncoder { 20 | 21 | private int WHITE = 0xFFFFFFFF; 22 | private int BLACK = 0xFF000000; 23 | private int dimension = Integer.MIN_VALUE; 24 | private String contents = null; 25 | private String displayContents = null; 26 | private String title = null; 27 | private BarcodeFormat format = null; 28 | private boolean encoded = false; 29 | 30 | public void setColorWhite(int color) { 31 | this.WHITE = color; 32 | } 33 | 34 | public void setColorBlack(int color) { 35 | this.BLACK = color; 36 | } 37 | 38 | public int getColorWhite() { 39 | return this.WHITE; 40 | } 41 | 42 | public int getColorBlack() { 43 | return this.BLACK; 44 | } 45 | 46 | public QRGEncoder(String data, String type) { 47 | encoded = encodeContents(data, null, QRGContents.Type.TEXT); 48 | } 49 | 50 | public QRGEncoder(String data, String type, int dimension) { 51 | this.dimension = dimension; 52 | encoded = encodeContents(data, null, QRGContents.Type.TEXT); 53 | } 54 | 55 | public QRGEncoder(String data, Bundle bundle, String type, int dimension) { 56 | this.dimension = dimension; 57 | encoded = encodeContents(data, bundle, type); 58 | } 59 | 60 | public String getTitle() { 61 | return title; 62 | } 63 | 64 | private boolean encodeContents(String data, Bundle bundle, String type) { 65 | // Default to QR_CODE if no format given. 66 | format = BarcodeFormat.QR_CODE; 67 | if (format == BarcodeFormat.QR_CODE) { 68 | this.format = BarcodeFormat.QR_CODE; 69 | encodeQRCodeContents(data, bundle, type); 70 | } else if (data != null && data.length() > 0) { 71 | contents = data; 72 | displayContents = data; 73 | title = "Text"; 74 | } 75 | return contents != null && contents.length() > 0; 76 | } 77 | 78 | private void encodeQRCodeContents(String data, Bundle bundle, String type) { 79 | switch (type) { 80 | case QRGContents.Type.TEXT: 81 | if (data != null && data.length() > 0) { 82 | contents = data.replace("\\n", "\n"); 83 | displayContents = data; 84 | title = "Text"; 85 | } 86 | break; 87 | case QRGContents.Type.EMAIL: 88 | data = trim(data); 89 | if (data != null) { 90 | contents = "mailto:" + data; 91 | displayContents = data; 92 | title = "E-Mail"; 93 | } 94 | break; 95 | case QRGContents.Type.PHONE: 96 | data = trim(data); 97 | if (data != null) { 98 | contents = "tel:" + data; 99 | displayContents = PhoneNumberUtils.formatNumber(data); 100 | title = "Phone"; 101 | } 102 | break; 103 | case QRGContents.Type.SMS: 104 | data = trim(data); 105 | if (data != null) { 106 | contents = "sms:" + data; 107 | displayContents = PhoneNumberUtils.formatNumber(data); 108 | title = "SMS"; 109 | } 110 | break; 111 | case QRGContents.Type.CONTACT: 112 | if (bundle != null) { 113 | StringBuilder newContents = new StringBuilder(100); 114 | StringBuilder newDisplayContents = new StringBuilder(100); 115 | 116 | newContents.append("BEGIN:VCARD\n"); 117 | 118 | String name = trim(bundle.getString(ContactsContract.Intents.Insert.NAME)); 119 | if (name != null) { 120 | newContents.append("N:").append(escapeVCard(name)).append(';'); 121 | newDisplayContents.append(name); 122 | newContents.append("\n"); 123 | } 124 | 125 | String address = trim(bundle.getString(ContactsContract.Intents.Insert.POSTAL)); 126 | if (address != null) { 127 | //the append ; is removed because it is unnecessary because we are breaking into new row 128 | newContents.append("ADR:").append(escapeVCard(address));//.append(';') 129 | newContents.append("\n"); 130 | newDisplayContents.append('\n').append(address); 131 | } 132 | 133 | Collection uniquePhones = new HashSet<>(QRGContents.PHONE_KEYS.length); 134 | for (int x = 0; x < QRGContents.PHONE_KEYS.length; x++) { 135 | String phone = trim(bundle.getString(QRGContents.PHONE_KEYS[x])); 136 | if (phone != null) { 137 | uniquePhones.add(phone); 138 | } 139 | } 140 | for (String phone : uniquePhones) { 141 | newContents.append("TEL:").append(escapeVCard(phone));//.append(';') 142 | newContents.append("\n"); 143 | //noinspection deprecation 144 | newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone)); 145 | } 146 | 147 | Collection uniqueEmails = new HashSet<>(QRGContents.EMAIL_KEYS.length); 148 | for (int x = 0; x < QRGContents.EMAIL_KEYS.length; x++) { 149 | String email = trim(bundle.getString(QRGContents.EMAIL_KEYS[x])); 150 | if (email != null) { 151 | uniqueEmails.add(email); 152 | } 153 | } 154 | for (String email : uniqueEmails) { 155 | newContents.append("EMAIL:").append(escapeVCard(email));//.append(';') 156 | newContents.append("\n"); 157 | newDisplayContents.append('\n').append(email); 158 | } 159 | 160 | String organization = trim(bundle.getString(ContactsContract.Intents.Insert.COMPANY)); 161 | if (organization != null) { 162 | newContents.append("ORG:").append(organization);//.append(';') 163 | newContents.append("\n"); 164 | newDisplayContents.append('\n').append(organization); 165 | } 166 | 167 | String url = trim(bundle.getString(ContactsContract.Intents.Insert.DATA)); 168 | if (url != null) { 169 | // in this field only the website name and the domain are necessary (example : somewebsite.com) 170 | newContents.append("URL:").append(escapeVCard(url));//.append(';'); 171 | newContents.append("\n"); 172 | newDisplayContents.append('\n').append(url); 173 | } 174 | 175 | String note = trim(bundle.getString(ContactsContract.Intents.Insert.NOTES)); 176 | if (note != null) { 177 | newContents.append("NOTE:").append(escapeVCard(note));//.append(';') 178 | newContents.append("\n"); 179 | newDisplayContents.append('\n').append(note); 180 | } 181 | 182 | // Make sure we've encoded at least one field. 183 | if (newDisplayContents.length() > 0) { 184 | //this end vcard needs to be at the end in order for the default phone reader to recognize it as a contact 185 | newContents.append("END:VCARD"); 186 | newContents.append(';'); 187 | contents = newContents.toString(); 188 | displayContents = newDisplayContents.toString(); 189 | title = "Contact"; 190 | } else { 191 | contents = null; 192 | displayContents = null; 193 | } 194 | 195 | } 196 | break; 197 | case QRGContents.Type.LOCATION: 198 | if (bundle != null) { 199 | // These must use Bundle.getFloat(), not getDouble(), it's part of the API. 200 | float latitude = bundle.getFloat("LAT", Float.MAX_VALUE); 201 | float longitude = bundle.getFloat("LONG", Float.MAX_VALUE); 202 | if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) { 203 | contents = "geo:" + latitude + ',' + longitude; 204 | displayContents = latitude + "," + longitude; 205 | title = "Location"; 206 | } 207 | } 208 | break; 209 | } 210 | } 211 | 212 | public Bitmap getBitmap() { 213 | if (!encoded) return null; 214 | try { 215 | Map hints = null; 216 | String encoding = guessAppropriateEncoding(contents); 217 | if (encoding != null) { 218 | hints = new EnumMap<>(EncodeHintType.class); 219 | hints.put(EncodeHintType.CHARACTER_SET, encoding); 220 | } 221 | MultiFormatWriter writer = new MultiFormatWriter(); 222 | BitMatrix result = writer.encode(contents, format, dimension, dimension, hints); 223 | int width = result.getWidth(); 224 | int height = result.getHeight(); 225 | int[] pixels = new int[width * height]; 226 | // All are 0, or black, by default 227 | for (int y = 0; y < height; y++) { 228 | int offset = y * width; 229 | for (int x = 0; x < width; x++) { 230 | pixels[offset + x] = result.get(x, y) ? getColorWhite() : getColorBlack(); 231 | } 232 | } 233 | 234 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 235 | bitmap.setPixels(pixels, 0, width, 0, 0, width, height); 236 | return bitmap; 237 | } catch (Exception ex) { 238 | return null; 239 | } 240 | } 241 | 242 | public Bitmap getBitmap(int margin) { 243 | if (!encoded) return null; 244 | try { 245 | Map hints = null; 246 | hints = new EnumMap<>(EncodeHintType.class); 247 | String encoding = guessAppropriateEncoding(contents); 248 | if (encoding != null) { 249 | hints.put(EncodeHintType.CHARACTER_SET, encoding); 250 | } 251 | 252 | // Setting the margin width 253 | hints.put(EncodeHintType.MARGIN, margin); 254 | 255 | MultiFormatWriter writer = new MultiFormatWriter(); 256 | BitMatrix result = writer.encode(contents, format, dimension, dimension, hints); 257 | int width = result.getWidth(); 258 | int height = result.getHeight(); 259 | int[] pixels = new int[width * height]; 260 | for (int y = 0; y < height; y++) { 261 | int offset = y * width; 262 | for (int x = 0; x < width; x++) { 263 | pixels[offset + x] = result.get(x, y) ? getColorBlack() : getColorWhite(); 264 | } 265 | } 266 | 267 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 268 | bitmap.setPixels(pixels, 0, width, 0, 0, width, height); 269 | return bitmap; 270 | } catch (Exception ex) { 271 | return null; 272 | } 273 | } 274 | 275 | private String guessAppropriateEncoding(CharSequence contents) { 276 | // Very crude at the moment 277 | for (int i = 0; i < contents.length(); i++) { 278 | if (contents.charAt(i) > 0xFF) { 279 | return "UTF-8"; 280 | } 281 | } 282 | return "UTF-8"; // Default encoding 283 | } 284 | 285 | private String trim(String s) { 286 | if (s == null) { 287 | return null; 288 | } 289 | String result = s.trim(); 290 | return result.length() == 0 ? null : result; 291 | } 292 | 293 | private String escapeVCard(String input) { 294 | if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) { 295 | return input; 296 | } 297 | int length = input.length(); 298 | StringBuilder result = new StringBuilder(length); 299 | for (int i = 0; i < length; i++) { 300 | char c = input.charAt(i); 301 | if (c == ':' || c == ';') { 302 | result.append('\\'); 303 | } 304 | result.append(c); 305 | } 306 | return result.toString(); 307 | } 308 | 309 | } 310 | -------------------------------------------------------------------------------- /QRGenearator/src/main/java/androidmads/library/qrgenearator/QRGSaver.java: -------------------------------------------------------------------------------- 1 | package androidmads.library.qrgenearator; 2 | 3 | import android.graphics.Bitmap; 4 | import android.util.Log; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | 10 | @SuppressWarnings("ALL") 11 | public class QRGSaver { 12 | 13 | public boolean save(String saveLocation, String imageName, Bitmap bitmap, int imageFormat) { 14 | 15 | boolean success = false; 16 | String imageDetail = saveLocation + imageName + imgFormat(imageFormat); 17 | FileOutputStream outStream; 18 | File file = new File(saveLocation); 19 | if (!file.exists()) { 20 | file.mkdir(); 21 | } else { 22 | Log.d("QRGSaver", "Folder Exists"); 23 | } 24 | try { 25 | outStream = new FileOutputStream(imageDetail); 26 | bitmap.compress((Bitmap.CompressFormat) compressFormat(imageFormat), 100, outStream); 27 | outStream.flush(); 28 | outStream.close(); 29 | success = true; 30 | } catch (IOException e) { 31 | Log.d("QRGSaver", e.toString()); 32 | } 33 | 34 | return success; 35 | } 36 | 37 | public boolean save(String saveLocation, String imageName, Bitmap bitmap) { 38 | return save(saveLocation, imageName, bitmap, QRGContents.ImageType.IMAGE_PNG); 39 | } 40 | 41 | private String imgFormat(int imageFormat) { 42 | return imageFormat == QRGContents.ImageType.IMAGE_PNG ? ".png" : ".jpg"; 43 | } 44 | 45 | private Comparable>> compressFormat(int imageFormat) { 46 | return imageFormat == QRGContents.ImageType.IMAGE_PNG ? Bitmap.CompressFormat.PNG : 47 | (imageFormat == QRGContents.ImageType.IMAGE_WEBP ? Bitmap.CompressFormat.WEBP : Bitmap.CompressFormat.JPEG); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /QRGenearator/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Library 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QRGenerator 2 | QR Generator Library and Saves the QR Code as Image 3 | 4 | ### Featured In: 5 | [![](https://jitpack.io/v/androidmads/QRGenerator.svg?style=for-the-badge)](https://jitpack.io/#androidmads/QRGenerator) 6 | 7 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-QR%20Generator-green.svg?style=for-the-badge)](https://android-arsenal.com/details/1/3890) 8 | 9 | [![CSharpCorner](https://img.shields.io/badge/C%23-Corner-blue.svg?style=for-the-badge)](https://www.c-sharpcorner.com/article/how-to-generate-qr-code-in-android/) 10 | 11 | [![StackOverflow](https://img.shields.io/badge/stack%20overflow-FE7A16?logo=stack-overflow&logoColor=white&style=for-the-badge)](https://rb.gy/vol1bm) 12 | 13 | [![Androidmads](https://img.shields.io/badge/Androidmads-Blog-09BBB2?style=for-the-badge)](https://www.androidmads.info/2018/07/how-to-generate-qr-code-in-android.html) 14 | 15 | ### How to Import the Library: 16 | Add it in your root build.gradle at the end of repositories: 17 | 18 | App-level build.gradle: 19 | ``` groovy 20 | allprojects { 21 | repositories { 22 | ... 23 | maven { url 'https://jitpack.io' } 24 | } 25 | } 26 | ``` 27 | Module-level build.gradle: 28 | ```groovy 29 | dependencies { 30 | implementation 'com.github.androidmads:QRGenerator:1.0.5' 31 | } 32 | ``` 33 | settings.gradle: 34 | ``` 35 | dependencyResolutionManagement { 36 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 37 | repositories { 38 | google() 39 | mavenCentral() 40 | maven(url = "https://jitpack.io") 41 | } 42 | } 43 | ``` 44 | Activity: 45 | ``` 46 | import androidmads.library.qrgenearator.QRGContents; 47 | import androidmads.library.qrgenearator.QRGEncoder; 48 | ``` 49 | 50 | ### Features: 51 | 1. QR code color can be changed dynamically 52 | 2. Android X support is included 53 | 3. Minimum support from version 14 is included 54 | 4. Margin of the QR code can be controlled 55 | 56 | ### Permission: 57 | Add This Permission for saving your generated code 58 | ```xml 59 | 60 | ``` 61 | ### How to use this Library: 62 | After importing this library, use the following lines to use this library. 63 | The following lines are used to generated the QR Code 64 | ```java 65 | // Initializing the QR Encoder with your value to be encoded, type you required and Dimension 66 | QRGEncoder qrgEncoder = new QRGEncoder(inputValue, null, QRGContents.Type.TEXT, smallerDimension); 67 | qrgEncoder.setColorBlack(Color.RED); 68 | qrgEncoder.setColorWhite(Color.BLUE); 69 | try { 70 | // Getting QR-Code as Bitmap 71 | bitmap = qrgEncoder.getBitmap(); 72 | // Setting Bitmap to ImageView 73 | qrImage.setImageBitmap(bitmap); 74 | } catch (WriterException e) { 75 | Log.v(TAG, e.toString()); 76 | } 77 | ``` 78 | The following lines are used to generated the QR Code without margin/default border 79 | ```java 80 | // Initializing the QR Encoder with your value to be encoded, type you required and Dimension 81 | QRGEncoder qrgEncoder = new QRGEncoder(inputValue, null, QRGContents.Type.TEXT, smallerDimension); 82 | qrgEncoder.setColorBlack(Color.RED); 83 | qrgEncoder.setColorWhite(Color.BLUE); 84 | try { 85 | // Getting QR-Code as Bitmap 86 | bitmap = qrgEncoder.getBitmap(0); 87 | // Setting Bitmap to ImageView 88 | qrImage.setImageBitmap(bitmap); 89 | } catch (WriterException e) { 90 | Log.v(TAG, e.toString()); 91 | } 92 | ``` 93 | The following lines are used to generated the Bar Code 94 | ```java 95 | BarcodeEncoder barcodeEncoder = new BarcodeEncoder(inputValue, BarcodeFormat.CODE_128, 800); 96 | bitmap = barcodeEncoder.getBitmap(2); // Margin of 2 pixels 97 | // Now you can use this bitmap as needed, e.g., display it in an ImageView 98 | qrImage.setImageBitmap(bitmap); 99 | ``` 100 | 101 | Save QR Code as Image 102 | ```java 103 | // Save with location, value, bitmap returned and type of Image(JPG/PNG). 104 | QRGSaver qrgSaver = new QRGSaver(); 105 | qrgSaver.save(savePath, edtValue.getText().toString().trim(), bitmap, QRGContents.ImageType.IMAGE_JPEG); 106 | ``` 107 | 108 | For more Details [Click Here](https://github.com/androidmads/QRGenerator/blob/master/app/src/main/java/androidmads/example/MainActivity.java) 109 | 110 | 111 | 112 | # License: 113 | ``` 114 | The MIT License (MIT) 115 | 116 | Copyright (c) 2016 AndroidMad / Mushtaq M A 117 | 118 | Permission is hereby granted, free of charge, to any person obtaining a copy 119 | of this software and associated documentation files (the "Software"), to deal 120 | in the Software without restriction, including without limitation the rights 121 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 122 | copies of the Software, and to permit persons to whom the Software is 123 | furnished to do so, subject to the following conditions: 124 | 125 | The above copyright notice and this permission notice shall be included in all 126 | copies or substantial portions of the Software. 127 | 128 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 129 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 130 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 131 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 132 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 133 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 134 | SOFTWARE. 135 | ``` 136 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 34 5 | 6 | defaultConfig { 7 | applicationId "androidmads.example" 8 | minSdkVersion 19 9 | targetSdkVersion 33 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | namespace 'androidmads.example' 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(include: ['*.jar'], dir: 'libs') 24 | implementation 'androidx.appcompat:appcompat:1.5.1' 25 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 26 | testImplementation 'junit:junit:4.13.2' 27 | implementation project(':QRGenearator') 28 | //implementation 'com.github.androidmads:QRGenerator:1.0.3' 29 | } 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in F:\Dev_Tools\Android_Studio\sdk\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/androidmads/example/GenDataActivity.java: -------------------------------------------------------------------------------- 1 | package androidmads.example; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.EditText; 8 | 9 | import androidx.appcompat.app.AppCompatActivity; 10 | 11 | public class GenDataActivity extends AppCompatActivity { 12 | 13 | EditText editTextName, editTextAddress, editTextPhone, editTextAddressMail, editTextNotes, editTextOrganization, editTextURL; 14 | Button btnGenerate; 15 | 16 | private static final String TAG = "MainActivity"; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_gen_data); 22 | 23 | editTextName = findViewById(R.id.editTextName); 24 | editTextAddress = findViewById(R.id.editTextAddress); 25 | editTextPhone = findViewById(R.id.editTextPhone); 26 | editTextAddressMail = findViewById(R.id.editTextAddressMail); 27 | btnGenerate = findViewById(R.id.btnGenerate); 28 | editTextNotes = findViewById(R.id.editTextNotes); 29 | editTextOrganization = findViewById(R.id.editTextOrganization); 30 | editTextURL = findViewById(R.id.editTextURL); 31 | 32 | btnGenerate.setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View view) { 35 | 36 | //keys in bundle correspond to the fields in the ContactsContract.class 37 | Intent intent = new Intent(getApplicationContext(), GenQRActivity.class); 38 | Bundle bundle = new Bundle(); 39 | bundle.putString("name", editTextName.getText().toString()); 40 | bundle.putString("postal", editTextAddress.getText().toString()); 41 | bundle.putString("phone", editTextPhone.getText().toString()); 42 | bundle.putString("email", editTextAddressMail.getText().toString()); 43 | bundle.putString("notes", editTextNotes.getText().toString()); 44 | bundle.putString("company", editTextOrganization.getText().toString()); 45 | bundle.putString("data", editTextURL.getText().toString()); 46 | intent.putExtras(bundle); 47 | startActivity(intent); 48 | } 49 | }); 50 | 51 | } 52 | } -------------------------------------------------------------------------------- /app/src/main/java/androidmads/example/GenQRActivity.java: -------------------------------------------------------------------------------- 1 | package androidmads.example; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.widget.ImageView; 7 | import android.widget.Toast; 8 | 9 | import androidx.appcompat.app.AppCompatActivity; 10 | 11 | import androidmads.library.qrgenearator.QRGContents; 12 | import androidmads.library.qrgenearator.QRGEncoder; 13 | 14 | public class GenQRActivity extends AppCompatActivity { 15 | 16 | ImageView imageQR; 17 | Bitmap bitmap; 18 | private static final String TAG = "QRActivity"; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_gen_q_r); 24 | 25 | imageQR = findViewById(R.id.imageQR); 26 | 27 | final Bundle bundle = getIntent().getExtras(); 28 | // String name = bundle.getString("name"); 29 | // String address = bundle.getString("postal"); 30 | // String phone = bundle.getString("phone"); 31 | // String email = bundle.getString("email"); 32 | // String notes = bundle.getString("notes"); 33 | // String organization = bundle.getString("company"); 34 | // String url = bundle.getString("data"); 35 | // Toast.makeText(this, name + address + phone, Toast.LENGTH_SHORT).show(); 36 | 37 | 38 | //setting the data as null and bundle of data from the previous activity because of the type of the QR 39 | QRGEncoder qrgEncoder = new QRGEncoder(null, bundle, QRGContents.Type.CONTACT, 500); 40 | try { 41 | // Getting QR-Code as Bitmap 42 | bitmap = qrgEncoder.getBitmap(); 43 | // Setting Bitmap to ImageView 44 | imageQR.setImageBitmap(bitmap); 45 | } catch (Exception e) { 46 | Log.v(TAG, e.toString()); 47 | } 48 | 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/androidmads/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package androidmads.example; 2 | 3 | import androidx.annotation.RequiresApi; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | import androidx.core.app.ActivityCompat; 6 | import androidx.core.content.ContextCompat; 7 | 8 | import android.Manifest; 9 | import android.content.Intent; 10 | import android.content.pm.PackageManager; 11 | import android.graphics.Bitmap; 12 | import android.graphics.Color; 13 | import android.graphics.Point; 14 | import android.os.Build; 15 | import android.os.Bundle; 16 | import android.os.Environment; 17 | import android.view.Display; 18 | import android.view.View; 19 | import android.view.WindowManager; 20 | import android.widget.EditText; 21 | import android.widget.ImageView; 22 | import android.widget.Toast; 23 | 24 | import java.util.Objects; 25 | 26 | import androidmads.library.qrgenearator.BarcodeEncoder; 27 | import androidmads.library.qrgenearator.BarcodeFormat; 28 | import androidmads.library.qrgenearator.QRGContents; 29 | import androidmads.library.qrgenearator.QRGEncoder; 30 | import androidmads.library.qrgenearator.QRGSaver; 31 | 32 | public class MainActivity extends AppCompatActivity { 33 | 34 | private EditText edtValue; 35 | private ImageView qrImage; 36 | private String inputValue; 37 | private String savePath = Environment.getExternalStorageDirectory().getPath() + "/QRCode/"; 38 | private Bitmap bitmap; 39 | private QRGEncoder qrgEncoder; 40 | private AppCompatActivity activity; 41 | private EditText mColorPreviewWhite, mColorPreviewBlack; 42 | 43 | 44 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | setContentView(R.layout.activity_main); 49 | 50 | qrImage = findViewById(R.id.qr_image); 51 | edtValue = findViewById(R.id.edt_value); 52 | mColorPreviewWhite = findViewById(R.id.preview_selected_firstcolor); 53 | mColorPreviewBlack = findViewById(R.id.preview_selected_secondcolor); 54 | 55 | activity = this; 56 | 57 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { 58 | savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath() + "/QRCode/"; 59 | } 60 | 61 | findViewById(R.id.generate_barcode).setOnClickListener(view -> { 62 | inputValue = edtValue.getText().toString().trim(); 63 | if (inputValue.length() > 0) { 64 | try { 65 | 66 | BarcodeEncoder barcodeEncoder = new BarcodeEncoder(inputValue, 67 | BarcodeFormat.CODE_128, 800); 68 | bitmap = barcodeEncoder.getBitmap(2); // Margin of 2 pixels 69 | 70 | // Now you can use this bitmap as needed, e.g., display it in an ImageView 71 | 72 | qrImage.setImageBitmap(bitmap); 73 | } catch (Exception e) { 74 | e.printStackTrace(); 75 | } 76 | } else { 77 | edtValue.setError(getResources().getString(R.string.value_required)); 78 | } 79 | }); 80 | 81 | 82 | findViewById(R.id.generate_qrcode).setOnClickListener(view -> { 83 | inputValue = edtValue.getText().toString().trim(); 84 | if (inputValue.length() > 0) { 85 | WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE); 86 | Display display = manager.getDefaultDisplay(); 87 | Point point = new Point(); 88 | display.getSize(point); 89 | int width = point.x; 90 | int height = point.y; 91 | int smallerDimension = Math.min(width, height); 92 | smallerDimension = smallerDimension * 3 / 4; 93 | 94 | qrgEncoder = new QRGEncoder(inputValue, null, QRGContents.Type.TEXT, smallerDimension); 95 | qrgEncoder.setColorBlack(Color.parseColor(mColorPreviewBlack.getText().toString())); 96 | qrgEncoder.setColorWhite(Color.parseColor(mColorPreviewWhite.getText().toString())); 97 | try { 98 | bitmap = qrgEncoder.getBitmap(); 99 | qrImage.setImageBitmap(bitmap); 100 | } catch (Exception e) { 101 | e.printStackTrace(); 102 | } 103 | } else { 104 | edtValue.setError(getResources().getString(R.string.value_required)); 105 | } 106 | }); 107 | 108 | findViewById(R.id.save_barcode).setOnClickListener(v -> { 109 | if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 110 | try { 111 | boolean save = new QRGSaver().save(savePath, edtValue.getText().toString().trim(), bitmap, QRGContents.ImageType.IMAGE_JPEG); 112 | String result = save ? "Image Saved" : "Image Not Saved"; 113 | Toast.makeText(activity, result, Toast.LENGTH_LONG).show(); 114 | edtValue.setText(null); 115 | } catch (Exception e) { 116 | e.printStackTrace(); 117 | } 118 | } else { 119 | ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0); 120 | } 121 | }); 122 | 123 | } 124 | 125 | public void goto_CQBarcode(View view) { 126 | startActivity(new Intent(getApplicationContext(), GenDataActivity.class)); 127 | } 128 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_gen_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 25 | 26 | 33 | 34 | 35 | 36 | 44 | 45 | 52 | 53 | 60 | 61 | 62 | 63 | 71 | 72 | 80 | 81 | 88 | 89 | 90 | 91 | 99 | 100 | 107 | 108 | 109 | 110 |