Add the ability to show qr codes of stored accounts
Signed-off-by: Tilo Spannagel <development@tilosp.de>
This commit is contained in:
parent
b8b9834f06
commit
5a165fd212
4 changed files with 86 additions and 0 deletions
|
@ -276,6 +276,46 @@ public class Entry {
|
|||
return jsonObj;
|
||||
}
|
||||
|
||||
public Uri toUri() {
|
||||
String type;
|
||||
switch (this.type) {
|
||||
case TOTP:
|
||||
type = "totp";
|
||||
break;
|
||||
case HOTP:
|
||||
type = "hotp";
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
Uri.Builder builder = new Uri.Builder()
|
||||
.scheme("otpauth")
|
||||
.authority(type)
|
||||
.appendPath(this.label)
|
||||
.appendQueryParameter("secret", new Base32().encodeAsString(this.secret));
|
||||
if (this.issuer != null) {
|
||||
builder.appendQueryParameter("issuer", this.issuer);
|
||||
}
|
||||
switch (this.type) {
|
||||
case HOTP:
|
||||
builder.appendQueryParameter("counter", Long.toString(this.counter));
|
||||
case TOTP:
|
||||
if (this.period != TokenCalculator.TOTP_DEFAULT_PERIOD)
|
||||
builder.appendQueryParameter("period", Integer.toString(this.period));
|
||||
break;
|
||||
}
|
||||
if (this.digits != TokenCalculator.TOTP_DEFAULT_DIGITS) {
|
||||
builder.appendQueryParameter("digits", Integer.toString(this.digits));
|
||||
}
|
||||
if (this.algorithm != TokenCalculator.DEFAULT_ALGORITHM) {
|
||||
builder.appendQueryParameter("algorithm", this.algorithm.name());
|
||||
}
|
||||
for (String tag : this.tags) {
|
||||
builder.appendQueryParameter("tags", tag);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public boolean isTimeBased() {
|
||||
return type == OTPType.TOTP || type == OTPType.STEAM;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ import android.content.ClipData;
|
|||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -46,9 +48,13 @@ import android.widget.Filter;
|
|||
import android.widget.Filterable;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.journeyapps.barcodescanner.BarcodeEncoder;
|
||||
|
||||
import org.shadowice.flocke.andotp.Activities.MainActivity;
|
||||
import org.shadowice.flocke.andotp.Database.Entry;
|
||||
import org.shadowice.flocke.andotp.Dialogs.TagsDialog;
|
||||
|
@ -681,6 +687,35 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
|||
.show();
|
||||
}
|
||||
|
||||
private void showQRCode(final int pos) {
|
||||
Uri uri = displayedEntries.get(pos).toUri();
|
||||
if (uri != null) {
|
||||
Bitmap bitmap;
|
||||
try {
|
||||
bitmap = new BarcodeEncoder().encodeBitmap(uri.toString(), BarcodeFormat.QR_CODE, 0, 0);
|
||||
} catch(Exception ignored) {
|
||||
Toast.makeText(context, R.string.toast_qr_failed_to_generate, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
BitmapDrawable drawable = new BitmapDrawable(context.getResources(), bitmap);
|
||||
drawable.setFilterBitmap(false);
|
||||
|
||||
ImageView image = new ImageView(context);
|
||||
image.setAdjustViewBounds(true);
|
||||
image.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||
image.setImageDrawable(drawable);
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.dialog_title_qr_code)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {})
|
||||
.setView(image)
|
||||
.create()
|
||||
.show();
|
||||
} else {
|
||||
Toast.makeText(context, R.string.toast_qr_unsuported, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void showPopupMenu(View view, final int pos) {
|
||||
View menuItemView = view.findViewById(R.id.menuButton);
|
||||
PopupMenu popup = new PopupMenu(view.getContext(), menuItemView);
|
||||
|
@ -707,6 +742,9 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
|||
} else if (id == R.id.menu_popup_remove) {
|
||||
removeItem(pos);
|
||||
return true;
|
||||
} else if (id == R.id.menu_popup_show_qr_code) {
|
||||
showQRCode(pos);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -20,4 +20,8 @@
|
|||
android:id="@+id/menu_popup_remove"
|
||||
android:title="@string/menu_popup_remove" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_popup_show_qr_code"
|
||||
android:title="@string/menu_popup_show_qr_code" />
|
||||
|
||||
</menu>
|
|
@ -57,6 +57,7 @@
|
|||
<string name="menu_popup_change_image">Change image</string>
|
||||
<string name="menu_popup_edit_tags">Edit tags</string>
|
||||
<string name="menu_popup_remove">Remove</string>
|
||||
<string name="menu_popup_show_qr_code">Show QR Code</string>
|
||||
|
||||
<!-- Toast messages -->
|
||||
<string name="toast_auth_failed">Authentication failed, please try again!</string>
|
||||
|
@ -71,6 +72,8 @@
|
|||
<string name="toast_qr_error">Could not find/confirm QR code</string>
|
||||
<string name="toast_qr_checksum_exception">Checksum verification failed while decoding QR code</string>
|
||||
<string name="toast_qr_format_error">Format error in QR code</string>
|
||||
<string name="toast_qr_unsuported">QR Code not supported</string>
|
||||
<string name="toast_qr_failed_to_generate">Failed to generate QR Code</string>
|
||||
|
||||
<!-- Dialogs -->
|
||||
<string name="dialog_title_auth">Authenticate</string>
|
||||
|
@ -80,6 +83,7 @@
|
|||
<string name="dialog_title_counter">Counter</string>
|
||||
<string name="dialog_title_used_tokens">Used tokens</string>
|
||||
<string name="dialog_title_keystore_error">KeyStore error</string>
|
||||
<string name="dialog_title_qr_code">QR Code</string>
|
||||
|
||||
<string name="dialog_title_enter_password">Enter password</string>
|
||||
|
||||
|
|
Loading…
Reference in a new issue