Commit cb1b5ddd authored by Drahomír Karchňák's avatar Drahomír Karchňák

#557 Initial implementation of ios qr code scanner

parent f008cb55
package cz.nic.tablexia.util.ui;
import java.util.HashSet;
import java.util.Set;
/**
* Created by drahomir on 10/5/16.
*/
public abstract class QRCodeScanner {
public interface QRCodeListener {
void onCodeScanned(String data);
}
private Set<QRCodeListener> listeners;
private boolean scanningEnabled = false;
public void enableScanning() {
scanningEnabled = true;
}
public void disableScanning() {
scanningEnabled = false;
}
public boolean isScanningEnabled() {
return scanningEnabled;
}
public void addQRCodeListener(QRCodeListener listener) {
if(listeners == null) listeners = new HashSet<QRCodeListener>();
listeners.add(listener);
}
public void removeQRCodeListener(QRCodeListener listener) {
if(listeners != null) {
listeners.remove(listener);
}
}
public void onCodeScanned(String data) {
if(listeners != null) {
for(QRCodeListener listener : listeners) {
listener.onCodeScanned(data);
}
}
}
/* ABSTRACT METHODS */
public abstract boolean isCameraAccessible();
public abstract void startCameraPreview();
public abstract void stopCameraPreview();
}
package cz.nic.tablexia;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.iosrobovm.IOSApplication;
import org.robovm.apple.avfoundation.AVCaptureConnection;
import org.robovm.apple.avfoundation.AVCaptureDevice;
import org.robovm.apple.avfoundation.AVCaptureDeviceInput;
import org.robovm.apple.avfoundation.AVCaptureDevicePosition;
import org.robovm.apple.avfoundation.AVCaptureMetadataOutput;
import org.robovm.apple.avfoundation.AVCaptureMetadataOutputObjectsDelegateAdapter;
import org.robovm.apple.avfoundation.AVCaptureOutput;
import org.robovm.apple.avfoundation.AVCaptureSession;
import org.robovm.apple.avfoundation.AVCaptureVideoPreviewLayer;
import org.robovm.apple.avfoundation.AVMediaType;
import org.robovm.apple.avfoundation.AVMetadataObject;
import org.robovm.apple.avfoundation.AVMetadataObjectType;
import org.robovm.apple.coregraphics.CGAffineTransform;
import org.robovm.apple.dispatch.DispatchQueue;
import org.robovm.apple.foundation.NSArray;
import org.robovm.apple.foundation.NSErrorException;
import org.robovm.apple.uikit.UIView;
import java.util.Arrays;
import cz.nic.tablexia.util.ui.QRCodeScanner;
/**
* Created by drahomir on 10/5/16.
*/
public class IOSQRCodeScanner extends QRCodeScanner {
private class CaptureMetadataOutputDelegate extends AVCaptureMetadataOutputObjectsDelegateAdapter{
private IOSQRCodeScanner qrCodeScanner;
public CaptureMetadataOutputDelegate() {
this.qrCodeScanner = IOSQRCodeScanner.this;
}
@Override
public void didOutputMetadataObjects(AVCaptureOutput captureOutput, NSArray<AVMetadataObject> metadataObjects, AVCaptureConnection connection) {
if(!isScanningEnabled()) return;
if(metadataObjects != null && metadataObjects.size() > 0) {
AVMetadataObject data = metadataObjects.get(0);
if(data.getType() == AVMetadataObjectType.QRCode) {
//Found QR Code TODO - change data.toString()
qrCodeScanner.onCodeScanned(data.toString());
}
}
}
}
private AVCaptureDevice cameraDevice;
private AVCaptureSession captureSession;
private AVCaptureDeviceInput captureDeviceInput;
private AVCaptureMetadataOutput captureMetadataOutput;
private CaptureMetadataOutputDelegate captureDelegate;
private DispatchQueue dispatchQueue;
private boolean cameraPreviewRunning = false;
private void initializeCameraDevice() {
if(cameraDevice != null) return;
NSArray<AVCaptureDevice> captureDevices = AVCaptureDevice.getDevicesForMediaType(AVMediaType.Video);
for(AVCaptureDevice captureDevice : captureDevices) {
if(captureDevice.getPosition() == AVCaptureDevicePosition.Back) {
//We found back camera!
cameraDevice = captureDevice;
return;
}
}
}
@Override
public boolean isCameraAccessible() {
initializeCameraDevice();
return cameraDevice != null;
}
@Override
public void startCameraPreview() {
if(cameraPreviewRunning) return;
cameraPreviewRunning = true;
captureSession = new AVCaptureSession();
initializeCameraDevice();
//INPUT DEVICE//
try {
captureDeviceInput = new AVCaptureDeviceInput(cameraDevice);
if(captureSession.canAddInput(captureDeviceInput)) captureSession.addInput(captureDeviceInput);
} catch (NSErrorException e) {
e.printStackTrace();
}
captureMetadataOutput = new AVCaptureMetadataOutput();
dispatchQueue = DispatchQueue.getMainQueue();
captureDelegate = new CaptureMetadataOutputDelegate();
captureMetadataOutput.setMetadataObjectsDelegate(captureDelegate, dispatchQueue);
if(captureSession.canAddOutput(captureMetadataOutput)) captureSession.addOutput(captureMetadataOutput);
captureMetadataOutput.setMetadataObjectTypes(Arrays.asList(AVMetadataObjectType.QRCode));
//Prevents java objects to get GCed unless captureSession ObjC object gets deallocated!
cameraDevice.addStrongRef(captureDeviceInput);
captureDeviceInput.addStrongRef(captureDelegate);
captureMetadataOutput.addStrongRef(captureDelegate);
captureDelegate.addStrongRef(captureSession);
IOSApplication iosApplication = (IOSApplication) Gdx.app;
UIView cameraPreviewView = new UIView();
cameraPreviewView.setTransform(CGAffineTransform.Identity().rotate(-Math.PI / 2.0));
cameraPreviewView.setBounds(iosApplication.getUIViewController().getView().getBounds());
cameraPreviewView.setCenter(iosApplication.getUIViewController().getView().getCenter());
AVCaptureVideoPreviewLayer videoPreviewLayer = new AVCaptureVideoPreviewLayer(captureSession);
videoPreviewLayer.setFrame(cameraPreviewView.getBounds());
cameraPreviewView.getLayer().addSublayer(videoPreviewLayer);
iosApplication.getUIViewController().getView().addSubview(cameraPreviewView);
if(!captureSession.isRunning()) captureSession.startRunning();
}
@Override
public void stopCameraPreview() {
if(!cameraPreviewRunning) return;
cameraPreviewRunning = false;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment