View identity: Generate and show QR code

This commit is contained in:
str4d
2014-11-18 11:14:33 +00:00
parent f5824991b0
commit fc8a511825
5 changed files with 135 additions and 20 deletions

View File

@@ -35,6 +35,7 @@ dependencies {
compile ('com.mcxiaoke.viewpagerindicator:library:2.4.1') {
exclude group: 'com.android.support', module: 'support-v4'
}
compile 'com.google.zxing:core:3.1.0'
compile 'com.google.zxing:android-integration:3.1.0'
}
@@ -45,6 +46,7 @@ dependencyVerification {
'com.android.support:appcompat-v7:45e999dda55fe81d9cc1c7342b7b70480ff3f307baa8da0df767f92fc5c52cd1',
'net.i2p.android.ext:floatingactionbutton:84cf5b67a66337bef59b46f57468c730387ca766b5a5f06ca852ba46cabbc0fb',
'com.mcxiaoke.viewpagerindicator:library:470bbd2bec1ede64ad21efd6f02676807d22f1b526c4ac6a5b41a428c6e47e67',
'com.google.zxing:core:f00b32f7a1b0edc914a8f74301e8dc34f189afc4698e9c8cc54e5d46772734a5',
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
]
}

View File

@@ -0,0 +1,5 @@
package i2p.bote.android;
public class Constants {
public static final String EMAILDEST_SCHEME = "bote";
}

View File

@@ -8,6 +8,7 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
@@ -20,7 +21,7 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;
import android.widget.TextView;
@@ -29,8 +30,10 @@ import com.google.zxing.integration.android.IntentIntegrator;
import java.io.IOException;
import java.security.GeneralSecurityException;
import i2p.bote.android.Constants;
import i2p.bote.android.R;
import i2p.bote.android.util.BoteHelper;
import i2p.bote.android.util.QrCodeUtils;
import i2p.bote.email.EmailIdentity;
import i2p.bote.fileencryption.PasswordException;
@@ -47,8 +50,7 @@ public class ViewIdentityFragment extends Fragment {
TextView mFingerprintField;
TextView mCryptoField;
TextView mKeyField;
Button mGenQRCode;
ImageView mKeyQrCode;
public static ViewIdentityFragment newInstance(String key) {
ViewIdentityFragment f = new ViewIdentityFragment();
@@ -82,7 +84,7 @@ public class ViewIdentityFragment extends Fragment {
mFingerprintField = (TextView) view.findViewById(R.id.fingerprint);
mCryptoField = (TextView) view.findViewById(R.id.crypto_impl);
mKeyField = (TextView) view.findViewById(R.id.key);
mGenQRCode = (Button) view.findViewById(R.id.generate_qr);
mKeyQrCode = (ImageView) view.findViewById(R.id.key_qr_code);
if (mKey != null) {
try {
@@ -142,13 +144,15 @@ public class ViewIdentityFragment extends Fragment {
mCryptoField.setText(mIdentity.getCryptoImpl().getName());
mKeyField.setText(mKey);
mGenQRCode.setOnClickListener(new View.OnClickListener() {
mKeyQrCode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
IntentIntegrator i = new IntentIntegrator(getActivity());
i.shareText("bote:" + mKey);
}
});
loadQrCode();
}
}
@@ -241,4 +245,34 @@ public class ViewIdentityFragment extends Fragment {
"i2p.bote", "contactDestination", mIdentity.getKey().getBytes()
);
}
/**
* Load QR Code asynchronously and with a fade in animation
*/
private void loadQrCode() {
AsyncTask<Void, Void, Bitmap> loadTask =
new AsyncTask<Void, Void, Bitmap>() {
protected Bitmap doInBackground(Void... unused) {
String qrCodeContent = Constants.EMAILDEST_SCHEME + ":" + mKey;
// render with minimal size
return QrCodeUtils.getQRCodeBitmap(qrCodeContent, 0);
}
protected void onPostExecute(Bitmap qrCode) {
// only change view, if fragment is attached to activity
if (ViewIdentityFragment.this.isAdded()) {
// scale the image up to our actual size. we do this in code rather
// than let the ImageView do this because we don't require filtering.
Bitmap scaled = Bitmap.createScaledBitmap(qrCode,
mKeyQrCode.getHeight(), mKeyQrCode.getHeight(),
false);
mKeyQrCode.setImageBitmap(scaled);
// simple fade-in animation
AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(200);
mKeyQrCode.startAnimation(anim);
}
}
};
loadTask.execute();
}
}

View File

@@ -0,0 +1,78 @@
/**
* Copyright (C) 2014 str4d
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2011 Andreas Schildbach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package i2p.bote.android.util;
import android.graphics.Bitmap;
import android.graphics.Color;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
import java.util.Hashtable;
/**
* Copied from OpenKeychain
* Originally copied from Bitcoin Wallet
*/
public class QrCodeUtils {
/**
* Generate Bitmap with QR Code based on input.
*
* @param input
* @param size
* @return QR Code as Bitmap
*/
public static Bitmap getQRCodeBitmap(final String input, final int size) {
try {
final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
final BitMatrix result = new QRCodeWriter().encode(input, BarcodeFormat.QR_CODE, size,
size, hints);
final int width = result.getWidth();
final int height = result.getHeight();
final int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
final int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
}
}
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
} catch (final WriterException e) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(QrCodeUtils.class);
if (log.shouldLog(Log.ERROR))
log.error("QrCodeUtils", e);
return null;
}
}
}

View File

@@ -68,9 +68,10 @@
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<RelativeLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/title_key_info"
@@ -83,16 +84,21 @@
android:id="@+id/crypto_impl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title_key_info"
android:layout_marginTop="8dp"
android:text="Crypto implementation"
android:textAppearance="@style/TextAppearance.AppCompat.Primary"/>
<ImageView
android:id="@+id/key_qr_code"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"/>
<TextView
android:id="@+id/key"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/crypto_impl"
android:layout_marginTop="8dp"
android:text="Key"
android:textAppearance="@style/TextAppearance.AppCompat.Secondary"/>
@@ -101,7 +107,6 @@
android:id="@+id/title_fingerprint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/key"
android:layout_marginTop="8dp"
android:text="Fingerprint"
android:textAppearance="@style/TextAppearance.AppCompat.Subject"
@@ -111,20 +116,11 @@
android:id="@+id/fingerprint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title_fingerprint"
android:layout_marginTop="8dp"
android:text="Fingerprint"
android:textAppearance="@style/TextAppearance.AppCompat.Primary"
android:visibility="gone"/>
<Button
android:id="@+id/generate_qr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/fingerprint"
android:layout_marginTop="8dp"
android:text="Generate QR code"/>
</RelativeLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>