Android Open Source - AIRShare Q R Code Encoder






From Project

Back to project page AIRShare.

License

The source code is released under:

Apache License

If you think the Android project AIRShare listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2008 ZXing authors/*  w w w .  ja  v  a2  s . com*/
 *
 * 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.client.android.encode;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.telephony.PhoneNumberUtils;
import android.util.Log;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.android.Contents;
import com.google.zxing.client.android.Intents;
import com.google.zxing.client.android.R;
import com.google.zxing.client.result.AddressBookParsedResult;
import com.google.zxing.client.result.ParsedResult;
import com.google.zxing.client.result.ResultParser;
import com.google.zxing.common.BitMatrix;

/**
 * This class does the work of decoding the user's request and extracting all
 * the data to be encoded in a barcode.
 * 
 * @author dswitkin@google.com (Daniel Switkin)
 */
public final class QRCodeEncoder {

    private static final String TAG = QRCodeEncoder.class.getSimpleName();

    private static final int WHITE = 0xFFFFFFFF;
    private static final int BLACK = 0xFF000000;

    private final Context activity;
    private String contents;
    private String displayContents;
    private String title;
    private BarcodeFormat format;
    private final int dimension;
    private final boolean useVCard;

    public QRCodeEncoder(Context activity, Intent intent, int dimension, boolean useVCard) throws WriterException {
        this.activity = activity;
        this.dimension = dimension;
        this.useVCard = useVCard;
        String action = intent.getAction();
        if (action.equals(Intents.Encode.ACTION)) {
            encodeContentsFromZXingIntent(intent);
        } else if (action.equals(Intent.ACTION_SEND)) {
            encodeContentsFromShareIntent(intent);
        }
    }

    String getContents() {
        return contents;
    }

    String getDisplayContents() {
        return displayContents;
    }

    String getTitle() {
        return title;
    }

    boolean isUseVCard() {
        return useVCard;
    }

    // It would be nice if the string encoding lived in the core ZXing library,
    // but we use platform specific code like PhoneNumberUtils, so it can't.
    private boolean encodeContentsFromZXingIntent(Intent intent) {
        // Default to QR_CODE if no format given.
        String formatString = intent.getStringExtra(Intents.Encode.FORMAT);
        format = null;
        if (formatString != null) {
            try {
                format = BarcodeFormat.valueOf(formatString);
            } catch (IllegalArgumentException iae) {
                // Ignore it then
            }
        }
        if (format == null || format == BarcodeFormat.QR_CODE) {
            String type = intent.getStringExtra(Intents.Encode.TYPE);
            if (type == null || type.isEmpty()) {
                return false;
            }
            this.format = BarcodeFormat.QR_CODE;
            encodeQRCodeContents(intent, type);
        } else {
            String data = intent.getStringExtra(Intents.Encode.DATA);
            if (data != null && !data.isEmpty()) {
                contents = data;
                displayContents = data;
                title = activity.getString(R.string.contents_text);
            }
        }
        return contents != null && !contents.isEmpty();
    }

    // Handles send intents from multitude of Android applications
    private void encodeContentsFromShareIntent(Intent intent) throws WriterException {
        // Check if this is a plain text encoding, or contact
        if (intent.hasExtra(Intent.EXTRA_STREAM)) {
            encodeFromStreamExtra(intent);
        } else {
            encodeFromTextExtras(intent);
        }
    }

    private void encodeFromTextExtras(Intent intent) throws WriterException {
        // Notice: Google Maps shares both URL and details in one text, bummer!
        String theContents = ContactEncoder.trim(intent.getStringExtra(Intent.EXTRA_TEXT));
        if (theContents == null) {
            theContents = ContactEncoder.trim(intent.getStringExtra("android.intent.extra.HTML_TEXT"));
            // Intent.EXTRA_HTML_TEXT
            if (theContents == null) {
                theContents = ContactEncoder.trim(intent.getStringExtra(Intent.EXTRA_SUBJECT));
                if (theContents == null) {
                    String[] emails = intent.getStringArrayExtra(Intent.EXTRA_EMAIL);
                    if (emails != null) {
                        theContents = ContactEncoder.trim(emails[0]);
                    } else {
                        theContents = "?";
                    }
                }
            }
        }

        // Trim text to avoid URL breaking.
        if (theContents == null || theContents.isEmpty()) {
            throw new WriterException("Empty EXTRA_TEXT");
        }
        contents = theContents;
        // We only do QR code.
        format = BarcodeFormat.QR_CODE;
        if (intent.hasExtra(Intent.EXTRA_SUBJECT)) {
            displayContents = intent.getStringExtra(Intent.EXTRA_SUBJECT);
        } else if (intent.hasExtra(Intent.EXTRA_TITLE)) {
            displayContents = intent.getStringExtra(Intent.EXTRA_TITLE);
        } else {
            displayContents = contents;
        }
        title = activity.getString(R.string.contents_text);
    }

    // Handles send intents from the Contacts app, retrieving a contact as a
    // VCARD.
    private void encodeFromStreamExtra(Intent intent) throws WriterException {
        format = BarcodeFormat.QR_CODE;
        Bundle bundle = intent.getExtras();
        if (bundle == null) {
            throw new WriterException("No extras");
        }
        Uri uri = bundle.getParcelable(Intent.EXTRA_STREAM);
        if (uri == null) {
            throw new WriterException("No EXTRA_STREAM");
        }
        byte[] vcard;
        String vcardString;
        try {
            InputStream stream = activity.getContentResolver().openInputStream(uri);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[2048];
            int bytesRead;
            while ((bytesRead = stream.read(buffer)) > 0) {
                baos.write(buffer, 0, bytesRead);
            }
            vcard = baos.toByteArray();
            vcardString = new String(vcard, 0, vcard.length, "UTF-8");
        } catch (IOException ioe) {
            throw new WriterException(ioe);
        }
        Log.d(TAG, "Encoding share intent content:");
        Log.d(TAG, vcardString);
        Result result = new Result(vcardString, vcard, null, BarcodeFormat.QR_CODE);
        ParsedResult parsedResult = ResultParser.parseResult(result);
        if (!(parsedResult instanceof AddressBookParsedResult)) {
            throw new WriterException("Result was not an address");
        }
        encodeQRCodeContents((AddressBookParsedResult) parsedResult);
        if (contents == null || contents.isEmpty()) {
            throw new WriterException("No content to encode");
        }
    }

    private void encodeQRCodeContents(Intent intent, String type) {
        if (type.equals(Contents.Type.TEXT)) {
            String data = intent.getStringExtra(Intents.Encode.DATA);
            if (data != null && !data.isEmpty()) {
                contents = data;
                displayContents = data;
                title = activity.getString(R.string.contents_text);
            }
        } else if (type.equals(Contents.Type.EMAIL)) {
            String data = ContactEncoder.trim(intent.getStringExtra(Intents.Encode.DATA));
            if (data != null) {
                contents = "mailto:" + data;
                displayContents = data;
                title = activity.getString(R.string.contents_email);
            }
        } else if (type.equals(Contents.Type.PHONE)) {
            String data = ContactEncoder.trim(intent.getStringExtra(Intents.Encode.DATA));
            if (data != null) {
                contents = "tel:" + data;
                displayContents = PhoneNumberUtils.formatNumber(data);
                title = activity.getString(R.string.contents_phone);
            }
        } else if (type.equals(Contents.Type.SMS)) {
            String data = ContactEncoder.trim(intent.getStringExtra(Intents.Encode.DATA));
            if (data != null) {
                contents = "sms:" + data;
                displayContents = PhoneNumberUtils.formatNumber(data);
                title = activity.getString(R.string.contents_sms);
            }
        } else if (type.equals(Contents.Type.CONTACT)) {

            Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
            if (bundle != null) {

                String name = bundle.getString(ContactsContract.Intents.Insert.NAME);
                String organization = bundle.getString(ContactsContract.Intents.Insert.COMPANY);
                String address = bundle.getString(ContactsContract.Intents.Insert.POSTAL);
                Collection<String> phones = new ArrayList<String>(Contents.PHONE_KEYS.length);
                for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
                    phones.add(bundle.getString(Contents.PHONE_KEYS[x]));
                }
                Collection<String> emails = new ArrayList<String>(Contents.EMAIL_KEYS.length);
                for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
                    emails.add(bundle.getString(Contents.EMAIL_KEYS[x]));
                }
                String url = bundle.getString(Contents.URL_KEY);
                Iterable<String> urls = url == null ? null : Collections.singletonList(url);
                String note = bundle.getString(Contents.NOTE_KEY);

                ContactEncoder mecardEncoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder();
                String[] encoded = mecardEncoder.encode(Collections.singleton(name),
                        organization,
                        Collections.singleton(address),
                        phones,
                        emails,
                        urls,
                        note);
                // Make sure we've encoded at least one field.
                if (!encoded[1].isEmpty()) {
                    contents = encoded[0];
                    displayContents = encoded[1];
                    title = activity.getString(R.string.contents_contact);
                }

            }

        } else if (type.equals(Contents.Type.LOCATION)) {
            Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
            if (bundle != null) {
                // These must use Bundle.getFloat(), not getDouble(), it's part
                // of the API.
                float latitude = bundle.getFloat("LAT", Float.MAX_VALUE);
                float longitude = bundle.getFloat("LONG", Float.MAX_VALUE);
                if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) {
                    contents = "geo:" + latitude + ',' + longitude;
                    displayContents = latitude + "," + longitude;
                    title = activity.getString(R.string.contents_location);
                }
            }
        }
    }

    private void encodeQRCodeContents(AddressBookParsedResult contact) {
        ContactEncoder encoder = useVCard ? new VCardContactEncoder() : new MECARDContactEncoder();
        String[] encoded = encoder.encode(toIterable(contact.getNames()),
                contact.getOrg(),
                toIterable(contact.getAddresses()),
                toIterable(contact.getPhoneNumbers()),
                toIterable(contact.getEmails()),
                toIterable(contact.getURLs()),
                null);
        // Make sure we've encoded at least one field.
        if (!encoded[1].isEmpty()) {
            contents = encoded[0];
            displayContents = encoded[1];
            title = activity.getString(R.string.contents_contact);
        }
    }

    private static Iterable<String> toIterable(String[] values) {
        return values == null ? null : Arrays.asList(values);
    }

    public Bitmap encodeAsBitmap() throws WriterException {
        String contentsToEncode = contents;
        if (contentsToEncode == null) {
            return null;
        }
        Map<EncodeHintType, Object> hints = null;
        String encoding = guessAppropriateEncoding(contentsToEncode);
        if (encoding != null) {
            hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
            hints.put(EncodeHintType.CHARACTER_SET, encoding);
        }
        BitMatrix result;
        try {
            result = new MultiFormatWriter().encode(contentsToEncode, format, dimension, dimension, hints);
        } catch (IllegalArgumentException iae) {
            // Unsupported format
            return null;
        }
        int width = result.getWidth();
        int height = result.getHeight();
        int[] pixels = new int[width * height];
        for (int y = 0; y < height; y++) {
            int offset = y * width;
            for (int x = 0; x < width; x++) {
                pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
            }
        }

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    private static String guessAppropriateEncoding(CharSequence contents) {
        // Very crude at the moment
        for (int i = 0; i < contents.length(); i++) {
            if (contents.charAt(i) > 0xFF) {
                return "UTF-8";
            }
        }
        return null;
    }

}




Java Source Code List

com.ggt.airshare.AIRShareApplication.java
com.ggt.airshare.LauncherActivity.java
com.ggt.airshare.MotherActivity.java
com.ggt.airshare.ShairingActivity.java
com.ggt.airshare.httpserver.NanoHTTPD.java
com.ggt.airshare.httpserver.ShAIReHttpServerListener.java
com.ggt.airshare.httpserver.ShAIReHttpServer.java
com.ggt.airshare.httpserver.ShaireServiceListener.java
com.ggt.airshare.httpserver.ShaireService.java
com.ggt.airshare.urlshortener.UrlShortenerException.java
com.ggt.airshare.urlshortener.UrlShortenerListener.java
com.ggt.airshare.urlshortener.UrlShortener.java
com.ggt.airshare.utils.ContactsUtils.java
com.ggt.airshare.utils.FileUtils.java
com.ggt.airshare.utils.HTMLUtils.java
com.ggt.airshare.utils.NetworkUtils.java
com.ggt.airshare.utils.ShAIReConstants.java
com.google.zxing.client.android.Contents.java
com.google.zxing.client.android.FinishListener.java
com.google.zxing.client.android.Intents.java
com.google.zxing.client.android.encode.ContactEncoder.java
com.google.zxing.client.android.encode.EncodeActivity.java
com.google.zxing.client.android.encode.Formatter.java
com.google.zxing.client.android.encode.MECARDContactEncoder.java
com.google.zxing.client.android.encode.QRCodeEncoder.java
com.google.zxing.client.android.encode.VCardContactEncoder.java
com.ianhanniballake.localstorage.LocalStorageProvider.java
com.ipaulpro.afilechooser.FileChooserActivity.java
com.ipaulpro.afilechooser.FileListAdapter.java
com.ipaulpro.afilechooser.FileListFragment.java
com.ipaulpro.afilechooser.FileLoader.java
com.ipaulpro.afilechooser.utils.FileUtils.java
de.psdev.licensesdialog.LicenseResolver.java
de.psdev.licensesdialog.LicensesDialogFragment.java
de.psdev.licensesdialog.LicensesDialog.java
de.psdev.licensesdialog.NoticesHtmlBuilder.java
de.psdev.licensesdialog.NoticesXmlParser.java
de.psdev.licensesdialog.SingleLicenseDialogFragment.java
de.psdev.licensesdialog.SingleLicenseDialog.java
de.psdev.licensesdialog.licenses.ApacheSoftwareLicense20.java
de.psdev.licensesdialog.licenses.BSD3ClauseLicense.java
de.psdev.licensesdialog.licenses.ISCLicense.java
de.psdev.licensesdialog.licenses.License.java
de.psdev.licensesdialog.licenses.MITLicense.java
de.psdev.licensesdialog.licenses.NanoHttpdLicense.java
de.psdev.licensesdialog.licenses.ViewerJSLicense.java
de.psdev.licensesdialog.licenses.XstreamLicense.java
de.psdev.licensesdialog.model.Notice.java
de.psdev.licensesdialog.model.Notices.java