QR Code sharing with multiple QR Codes

This commit is contained in:
Dominik Schürmann 2013-10-05 23:32:47 +02:00
parent 05cc2023da
commit 2942d94a29
5 changed files with 225 additions and 11 deletions

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/share_qr_code_dialog_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="@string/share_qr_code_dialog_start"
android:textAppearance="@android:style/TextAppearance.Medium" />
<ImageView
android:id="@+id/share_qr_code_dialog_image"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@ -81,6 +81,8 @@
<string name="btn_setPassPhrase">Set Passphrase</string> <string name="btn_setPassPhrase">Set Passphrase</string>
<string name="btn_search">Search</string> <string name="btn_search">Search</string>
<string name="btn_export_to_server">Export To Server</string> <string name="btn_export_to_server">Export To Server</string>
<string name="btn_next">Next</string>
<string name="btn_back">Back</string>
<!-- menu_lowerCase: capitalized words, no punctuation --> <!-- menu_lowerCase: capitalized words, no punctuation -->
<string name="menu_about">About</string> <string name="menu_about">About</string>
@ -376,4 +378,8 @@
<string name="api_select_pub_keys_dublicates_text">More than one public key exist for these user ids:</string> <string name="api_select_pub_keys_dublicates_text">More than one public key exist for these user ids:</string>
<string name="api_select_pub_keys_text">Please review the list of recipients!</string> <string name="api_select_pub_keys_text">Please review the list of recipients!</string>
<!-- Share -->
<string name="share_qr_code_dialog_start">Go through all QR Codes using \'Next\', and scan them one by one.</string>
<string name="share_qr_code_dialog_progress">QR Code %1$d of %2$d</string>
</resources> </resources>

View File

@ -20,16 +20,15 @@ package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList; import java.util.ArrayList;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import com.actionbarsherlock.app.SherlockFragmentActivity; import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentIntegratorSupportV4;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import com.actionbarsherlock.app.SherlockFragmentActivity;
public class ShareActivity extends SherlockFragmentActivity { public class ShareActivity extends SherlockFragmentActivity {
// Actions for internal use only: // Actions for internal use only:
public static final String ACTION_SHARE_KEYRING = Constants.INTENT_PREFIX + "SHARE_KEYRING"; public static final String ACTION_SHARE_KEYRING = Constants.INTENT_PREFIX + "SHARE_KEYRING";
@ -59,9 +58,6 @@ public class ShareActivity extends SherlockFragmentActivity {
ArrayList<String> keyringArmored = ProviderHelper.getPublicKeyRingsAsArmoredString(this, ArrayList<String> keyringArmored = ProviderHelper.getPublicKeyRingsAsArmoredString(this,
new long[] { masterKeyId }); new long[] { masterKeyId });
// close this activity
finish();
if (ACTION_SHARE_KEYRING.equals(action)) { if (ACTION_SHARE_KEYRING.equals(action)) {
// let user choose application // let user choose application
Intent sendIntent = new Intent(Intent.ACTION_SEND); Intent sendIntent = new Intent(Intent.ACTION_SEND);
@ -71,8 +67,13 @@ public class ShareActivity extends SherlockFragmentActivity {
getResources().getText(R.string.shareKeyringWith))); getResources().getText(R.string.shareKeyringWith)));
} else if (ACTION_SHARE_KEYRING_WITH_QR_CODE.equals(action)) { } else if (ACTION_SHARE_KEYRING_WITH_QR_CODE.equals(action)) {
// use barcode scanner integration library // use barcode scanner integration library
// new IntentIntegrator(this).shareText(keyringArmored.get(0)); // TODO: old new IntentIntegrator(this).shareText(keyringArmored.get(0));
// new IntentIntegratorSupportV4(this).shareText(activity, text); ShareQrCodeDialogFragment dialog = ShareQrCodeDialogFragment.newInstance(keyringArmored
} .get(0));
dialog.show(getSupportFragmentManager(), "qrCodeShareDialog");
}
// close this activity
// finish();
} }
} }

View File

@ -0,0 +1,171 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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 org.sufficientlysecure.keychain.ui.dialog;
import java.util.ArrayList;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.QrCodeUtils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockDialogFragment;
public class ShareQrCodeDialogFragment extends SherlockDialogFragment {
private static final String ARG_CONTENT = "content";
private ImageView mImage;
private TextView mText;
private ArrayList<String> mContentList;
private int mCounter;
private static final int QR_CODE_SIZE = 1000;
/**
* Creates new instance of this dialog fragment
*
* @param content
* Content to be shared via QR Codes
* @return
*/
public static ShareQrCodeDialogFragment newInstance(String content) {
ShareQrCodeDialogFragment frag = new ShareQrCodeDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_CONTENT, content);
frag.setArguments(args);
return frag;
}
/**
* Creates dialog
*/
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity activity = getActivity();
String content = getArguments().getString(ARG_CONTENT);
mContentList = splitString(content, 1000);
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setTitle(R.string.menu_shareQrCode);
LayoutInflater inflater = activity.getLayoutInflater();
View view = inflater.inflate(R.layout.share_qr_code_dialog, null);
alert.setView(view);
mImage = (ImageView) view.findViewById(R.id.share_qr_code_dialog_image);
mText = (TextView) view.findViewById(R.id.share_qr_code_dialog_text);
// start with first
mCounter = 0;
mImage.setImageBitmap(QrCodeUtils.getQRCodeBitmap(mContentList.get(mCounter), QR_CODE_SIZE));
// OnClickListener are set in onResume to prevent automatic dismissing of Dialogs
// http://stackoverflow.com/questions/2620444/how-to-prevent-a-dialog-from-closing-when-a-button-is-clicked
alert.setPositiveButton(R.string.btn_next, null);
alert.setNegativeButton(android.R.string.cancel, null);
return alert.create();
}
@Override
public void onResume() {
super.onResume();
AlertDialog alertDialog = (AlertDialog) getDialog();
final Button backButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
final Button nextButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCounter > 0) {
mCounter--;
updateQrCode();
updateDialog(backButton, nextButton);
} else {
dismiss();
}
}
});
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCounter < mContentList.size() - 1) {
mCounter++;
updateQrCode();
updateDialog(backButton, nextButton);
} else {
dismiss();
}
}
});
}
private void updateQrCode() {
// Content: <counter>,<size>,<content>
mImage.setImageBitmap(QrCodeUtils.getQRCodeBitmap(mCounter + "," + mContentList.size()
+ "," + mContentList.get(mCounter), QR_CODE_SIZE));
}
private void updateDialog(Button backButton, Button nextButton) {
if (mCounter == 0) {
backButton.setText(android.R.string.cancel);
} else {
backButton.setText(R.string.btn_back);
}
if (mCounter == mContentList.size() - 1) {
nextButton.setText(android.R.string.ok);
} else {
nextButton.setText(R.string.btn_next);
}
mText.setText(getResources().getString(R.string.share_qr_code_dialog_progress,
mCounter + 1, mContentList.size()));
}
/**
* Split String by number of characters
*
* @param text
* @param size
* @return
*/
private ArrayList<String> splitString(String text, int size) {
ArrayList<String> strings = new ArrayList<String>();
int index = 0;
while (index < text.length()) {
strings.add(text.substring(index, Math.min(index + size, text.length())));
index += size;
}
return strings;
}
}

View File

@ -45,7 +45,7 @@ public class QrCodeUtils {
public static Bitmap getQRCodeBitmap(final String input, final int size) { public static Bitmap getQRCodeBitmap(final String input, final int size) {
try { try {
final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size,
size, hints); size, hints);