use utf-8 in barcodes

This commit is contained in:
Daniel Gultsch 2018-03-19 21:05:20 +01:00
parent 0f97b44e9f
commit b682aeb252

View file

@ -35,174 +35,175 @@ import rocks.xmpp.addr.Jid;
public class BarcodeProvider extends ContentProvider implements ServiceConnection { public class BarcodeProvider extends ContentProvider implements ServiceConnection {
private static final String AUTHORITY = ".barcodes"; private static final String AUTHORITY = ".barcodes";
private final Object lock = new Object(); private final Object lock = new Object();
private XmppConnectionService mXmppConnectionService; private XmppConnectionService mXmppConnectionService;
private boolean mBindingInProcess = false; private boolean mBindingInProcess = false;
@Override public static Uri getUriForAccount(Context context, Account account) {
public boolean onCreate() { final String packageId = context.getPackageName();
File barcodeDirectory = new File(getContext().getCacheDir().getAbsolutePath() + "/barcodes/"); return Uri.parse("content://" + packageId + AUTHORITY + "/" + account.getJid().asBareJid() + ".png");
if (barcodeDirectory.exists() && barcodeDirectory.isDirectory()) { }
for (File file : barcodeDirectory.listFiles()) {
if (file.isFile() && !file.isHidden()) {
Log.d(Config.LOGTAG, "deleting old barcode file " + file.getAbsolutePath());
file.delete();
}
}
}
return true;
}
@Nullable public static Bitmap create2dBarcodeBitmap(String input, int size) {
@Override try {
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { final QRCodeWriter barcodeWriter = new QRCodeWriter();
return null; final Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
} hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
final BitMatrix result = barcodeWriter.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 Exception e) {
e.printStackTrace();
return null;
}
}
@Nullable @Override
@Override public boolean onCreate() {
public String getType(Uri uri) { File barcodeDirectory = new File(getContext().getCacheDir().getAbsolutePath() + "/barcodes/");
return "image/png"; if (barcodeDirectory.exists() && barcodeDirectory.isDirectory()) {
} for (File file : barcodeDirectory.listFiles()) {
if (file.isFile() && !file.isHidden()) {
Log.d(Config.LOGTAG, "deleting old barcode file " + file.getAbsolutePath());
file.delete();
}
}
}
return true;
}
@Nullable @Nullable
@Override @Override
public Uri insert(Uri uri, ContentValues values) { public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null; return null;
} }
@Override @Nullable
public int delete(Uri uri, String selection, String[] selectionArgs) { @Override
return 0; public String getType(Uri uri) {
} return "image/png";
}
@Override @Nullable
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { @Override
return 0; public Uri insert(Uri uri, ContentValues values) {
} return null;
}
@Override @Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { public int delete(Uri uri, String selection, String[] selectionArgs) {
return openFile(uri, mode, null); return 0;
} }
@Override @Override
public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) throws FileNotFoundException { public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
Log.d(Config.LOGTAG, "opening file with uri (normal): " + uri.toString()); return 0;
String path = uri.getPath(); }
if (path != null && path.endsWith(".png") && path.length() >= 5) {
String jid = path.substring(1).substring(0, path.length() - 4);
Log.d(Config.LOGTAG, "account:" + jid);
if (connectAndWait()) {
Log.d(Config.LOGTAG, "connected to background service");
try {
Account account = mXmppConnectionService.findAccountByJid(Jid.of(jid));
if (account != null) {
String shareableUri = account.getShareableUri();
String hash = CryptoHelper.getFingerprint(shareableUri);
File file = new File(getContext().getCacheDir().getAbsolutePath() + "/barcodes/" + hash);
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
Bitmap bitmap = create2dBarcodeBitmap(account.getShareableUri(), 1024);
OutputStream outputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
outputStream.flush();
}
return ParcelFileDescriptor.open(file,ParcelFileDescriptor.MODE_READ_ONLY);
}
} catch (Exception e) {
throw new FileNotFoundException();
}
}
}
throw new FileNotFoundException();
}
private boolean connectAndWait() { @Override
Intent intent = new Intent(getContext(), XmppConnectionService.class); public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
intent.setAction(this.getClass().getSimpleName()); return openFile(uri, mode, null);
Context context = getContext(); }
if (context != null) {
synchronized (this) {
if (mXmppConnectionService == null && !mBindingInProcess) {
Log.d(Config.LOGTAG,"calling to bind service");
context.startService(intent);
context.bindService(intent, this, Context.BIND_AUTO_CREATE);
this.mBindingInProcess = true;
}
}
try {
waitForService();
return true;
} catch (InterruptedException e) {
return false;
}
} else {
Log.d(Config.LOGTAG, "context was null");
return false;
}
}
@Override @Override
public void onServiceConnected(ComponentName name, IBinder service) { public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) throws FileNotFoundException {
synchronized (this) { Log.d(Config.LOGTAG, "opening file with uri (normal): " + uri.toString());
XmppConnectionService.XmppConnectionBinder binder = (XmppConnectionService.XmppConnectionBinder) service; String path = uri.getPath();
mXmppConnectionService = binder.getService(); if (path != null && path.endsWith(".png") && path.length() >= 5) {
mBindingInProcess = false; String jid = path.substring(1).substring(0, path.length() - 4);
synchronized (this.lock) { Log.d(Config.LOGTAG, "account:" + jid);
lock.notifyAll(); if (connectAndWait()) {
} Log.d(Config.LOGTAG, "connected to background service");
} try {
} Account account = mXmppConnectionService.findAccountByJid(Jid.of(jid));
if (account != null) {
String shareableUri = account.getShareableUri();
String hash = CryptoHelper.getFingerprint(shareableUri);
File file = new File(getContext().getCacheDir().getAbsolutePath() + "/barcodes/" + hash);
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
Bitmap bitmap = create2dBarcodeBitmap(account.getShareableUri(), 1024);
OutputStream outputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
outputStream.flush();
}
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
} catch (Exception e) {
throw new FileNotFoundException();
}
}
}
throw new FileNotFoundException();
}
@Override private boolean connectAndWait() {
public void onServiceDisconnected(ComponentName name) { Intent intent = new Intent(getContext(), XmppConnectionService.class);
synchronized (this) { intent.setAction(this.getClass().getSimpleName());
mXmppConnectionService = null; Context context = getContext();
} if (context != null) {
} synchronized (this) {
if (mXmppConnectionService == null && !mBindingInProcess) {
Log.d(Config.LOGTAG, "calling to bind service");
context.startService(intent);
context.bindService(intent, this, Context.BIND_AUTO_CREATE);
this.mBindingInProcess = true;
}
}
try {
waitForService();
return true;
} catch (InterruptedException e) {
return false;
}
} else {
Log.d(Config.LOGTAG, "context was null");
return false;
}
}
private void waitForService() throws InterruptedException { @Override
if (mXmppConnectionService == null) { public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (this.lock) { synchronized (this) {
lock.wait(); XmppConnectionService.XmppConnectionBinder binder = (XmppConnectionService.XmppConnectionBinder) service;
} mXmppConnectionService = binder.getService();
} else { mBindingInProcess = false;
Log.d(Config.LOGTAG,"not waiting for service because already initialized"); synchronized (this.lock) {
} lock.notifyAll();
} }
}
}
public static Uri getUriForAccount(Context context, Account account) { @Override
final String packageId = context.getPackageName(); public void onServiceDisconnected(ComponentName name) {
return Uri.parse("content://" + packageId + AUTHORITY + "/" + account.getJid().asBareJid() + ".png"); synchronized (this) {
} mXmppConnectionService = null;
}
}
public static Bitmap create2dBarcodeBitmap(String input, int size) { private void waitForService() throws InterruptedException {
try { if (mXmppConnectionService == null) {
final QRCodeWriter barcodeWriter = new QRCodeWriter(); synchronized (this.lock) {
final Hashtable<EncodeHintType, Object> hints = new Hashtable<>(); lock.wait();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); }
final BitMatrix result = barcodeWriter.encode(input, BarcodeFormat.QR_CODE, size, size, hints); } else {
final int width = result.getWidth(); Log.d(Config.LOGTAG, "not waiting for service because already initialized");
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 Exception e) {
e.printStackTrace();
return null;
}
}
} }