diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/androidTest/java/de/korrelator/overview/mispauth/ExampleInstrumentedTest.java b/app/src/androidTest/java/de/korrelator/overview/mispauth/ExampleInstrumentedTest.java new file mode 100644 index 0000000..b341e66 --- /dev/null +++ b/app/src/androidTest/java/de/korrelator/overview/mispauth/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package de.korrelator.overview.mispauth; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("de.korrelator.overview.mispauth", appContext.getPackageName()); + } +} diff --git a/app/src/main/java/de/korrelator/overview/mispauth/AppCompatPreferenceActivity.java b/app/src/main/java/de/korrelator/overview/mispauth/AppCompatPreferenceActivity.java new file mode 100644 index 0000000..538423a --- /dev/null +++ b/app/src/main/java/de/korrelator/overview/mispauth/AppCompatPreferenceActivity.java @@ -0,0 +1,109 @@ +package de.korrelator.overview.mispauth; + +import android.content.res.Configuration; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.support.annotation.LayoutRes; +import android.support.annotation.Nullable; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatDelegate; +import android.support.v7.widget.Toolbar; +import android.view.MenuInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls + * to be used with AppCompat. + */ +public abstract class AppCompatPreferenceActivity extends PreferenceActivity { + + private AppCompatDelegate mDelegate; + + @Override + protected void onCreate(Bundle savedInstanceState) { + getDelegate().installViewFactory(); + getDelegate().onCreate(savedInstanceState); + super.onCreate(savedInstanceState); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + getDelegate().onPostCreate(savedInstanceState); + } + + public ActionBar getSupportActionBar() { + return getDelegate().getSupportActionBar(); + } + + public void setSupportActionBar(@Nullable Toolbar toolbar) { + getDelegate().setSupportActionBar(toolbar); + } + + @Override + public MenuInflater getMenuInflater() { + return getDelegate().getMenuInflater(); + } + + @Override + public void setContentView(@LayoutRes int layoutResID) { + getDelegate().setContentView(layoutResID); + } + + @Override + public void setContentView(View view) { + getDelegate().setContentView(view); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().setContentView(view, params); + } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().addContentView(view, params); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getDelegate().onPostResume(); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + super.onTitleChanged(title, color); + getDelegate().setTitle(title); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getDelegate().onConfigurationChanged(newConfig); + } + + @Override + protected void onStop() { + super.onStop(); + getDelegate().onStop(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + getDelegate().onDestroy(); + } + + public void invalidateOptionsMenu() { + getDelegate().invalidateOptionsMenu(); + } + + private AppCompatDelegate getDelegate() { + if (mDelegate == null) { + mDelegate = AppCompatDelegate.create(this, null); + } + return mDelegate; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/korrelator/overview/mispauth/GenerateQrActivity.java b/app/src/main/java/de/korrelator/overview/mispauth/GenerateQrActivity.java new file mode 100644 index 0000000..8ca1b04 --- /dev/null +++ b/app/src/main/java/de/korrelator/overview/mispauth/GenerateQrActivity.java @@ -0,0 +1,45 @@ +package de.korrelator.overview.mispauth; + +import android.graphics.Bitmap; +import android.graphics.Point; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.Display; +import android.widget.ImageView; + +import net.glxn.qrgen.android.QRCode; + +import java.util.UUID; + +public class GenerateQrActivity extends AppCompatActivity { + + private Point displaySize; + private ImageView qrImageView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getSupportActionBar().setHomeButtonEnabled(true); + + setContentView(R.layout.activity_generate_qr); + qrImageView = findViewById(R.id.image_view_qr); + + + Display display = getWindowManager().getDefaultDisplay(); + displaySize = new Point(); + display.getSize(displaySize); + + DisplayQR("https://www.google.de \n OrgName \n " + UUID.randomUUID()); + } + + public void DisplayQR(String message){ + + Bitmap bitmap = QRCode.from(message) + .withSize(displaySize.x, displaySize.y) + .withColor(0xFF000000, 0x00000000) + .bitmap(); + + qrImageView.setImageBitmap(bitmap); + } +} diff --git a/app/src/main/java/de/korrelator/overview/mispauth/MainActivity.java b/app/src/main/java/de/korrelator/overview/mispauth/MainActivity.java new file mode 100644 index 0000000..65caecf --- /dev/null +++ b/app/src/main/java/de/korrelator/overview/mispauth/MainActivity.java @@ -0,0 +1,86 @@ +package de.korrelator.overview.mispauth; + +import android.app.Activity; +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +public class MainActivity extends AppCompatActivity { + + private static final int QR_REQUEST_CODE = 123; + private TextView qrResult; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + qrResult = findViewById(R.id.text_view_qr_result); + + Button scanButton = findViewById(R.id.button_scan); + scanButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startCameraIntent(); + } + }); + + Button generateButton = findViewById(R.id.button_generate); + generateButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startQrIntent(); + } + }); + } + + + private void startCameraIntent(){ + Intent intent = new Intent(this, ReadQrActivity.class); + startActivityForResult(intent, QR_REQUEST_CODE); + } + + + private void startQrIntent(){ + Intent intent = new Intent(this, GenerateQrActivity.class); + startActivity(intent); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + + if (requestCode == QR_REQUEST_CODE) { + if(resultCode == Activity.RESULT_OK){ + String result = data.getStringExtra("result"); + qrResult.setText(result); + } + + if (resultCode == Activity.RESULT_CANCELED) { + qrResult.setText("NO QR FOUND"); + } + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + + if (id == R.id.action_settings) { + startActivity(new Intent(this, SettingsActivity.class)); + return true; + } + + return super.onOptionsItemSelected(item); + } +} diff --git a/app/src/main/java/de/korrelator/overview/mispauth/ReadQrActivity.java b/app/src/main/java/de/korrelator/overview/mispauth/ReadQrActivity.java new file mode 100644 index 0000000..f298a5c --- /dev/null +++ b/app/src/main/java/de/korrelator/overview/mispauth/ReadQrActivity.java @@ -0,0 +1,346 @@ +package de.korrelator.overview.mispauth; + +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.ImageFormat; +import android.graphics.SurfaceTexture; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCaptureSession; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraDevice; +import android.hardware.camera2.CameraManager; +import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.params.StreamConfigurationMap; +import android.media.Image; +import android.media.ImageReader; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.ScriptIntrinsicYuvToRGB; +import android.renderscript.Type; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.util.Size; +import android.util.SparseArray; +import android.view.Surface; +import android.view.TextureView; + +import com.google.android.gms.vision.Frame; +import com.google.android.gms.vision.barcode.Barcode; +import com.google.android.gms.vision.barcode.BarcodeDetector; + +import java.util.Arrays; + +public class ReadQrActivity extends AppCompatActivity { + + // CAMERA + private static final int CAMERA_REQUEST_CODE = 1; + + private CameraManager cameraManager; + private int cameraFacing; + private String cameraId; + private Size previewSize; + + private CameraDevice cameraDevice; + private CameraDevice.StateCallback stateCallback; + private CameraCaptureSession cameraCaptureSession; + private CaptureRequest captureRequest; + private CaptureRequest.Builder captureRequestBuilder; + + private TextureView texturePreviewView; + private TextureView.SurfaceTextureListener surfaceTextureListener; + + private HandlerThread camBackgroundThread; + private Handler camBackgroundHandler; + + private ImageReader previewImageReader; + private ImageReader.OnImageAvailableListener previewImageListener; + + // BARCODE + private BarcodeDetector barcodeDetector; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_read_qr); + + Initialize(); + } + + private void Initialize(){ + + texturePreviewView = findViewById(R.id.texture_view); + + setUpBarcodeDetector(); + + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE); + + cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); + cameraFacing = CameraCharacteristics.LENS_FACING_BACK; + + surfaceTextureListener = new TextureView.SurfaceTextureListener() { + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { + setUpCamera(); + openCamera(); + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) { + + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + + } + }; + + stateCallback = new CameraDevice.StateCallback() { + @Override + public void onOpened(CameraDevice cameraDevice) { + ReadQrActivity.this.cameraDevice = cameraDevice; + createPreviewSession(); + } + + @Override + public void onDisconnected(CameraDevice cameraDevice) { + cameraDevice.close(); + ReadQrActivity.this.cameraDevice = null; + } + + @Override + public void onError(CameraDevice cameraDevice, int error) { + cameraDevice.close(); + ReadQrActivity.this.cameraDevice = null; + } + }; + + previewImageListener = new ImageReader.OnImageAvailableListener() { + @Override + public void onImageAvailable(ImageReader reader) { + + Image img = reader.acquireLatestImage(); + + if(img == null){ + return; + } + + Bitmap bitmapImage = YUV_420_888_toRGBIntrinsics(img); + + if(bitmapImage != null){ + Frame frame = new Frame.Builder().setBitmap(bitmapImage).build(); + SparseArray barcodes = barcodeDetector.detect(frame); + + if(barcodes.size() > 0){ + returnQrResult(barcodes.valueAt(0).displayValue); + } + } + + img.close(); + } + }; + } + + private void returnQrResult(String msg){ + Intent returnIntent = new Intent(); + returnIntent.putExtra("result", msg); + setResult(Activity.RESULT_OK, returnIntent); + finish(); + } + + private void setUpBarcodeDetector(){ + barcodeDetector = new BarcodeDetector.Builder(getApplicationContext()) + .setBarcodeFormats(Barcode.DATA_MATRIX | Barcode.QR_CODE) + .build(); + + Log.i("QR", "Setting up BarCodeDetector!"); + + if (!barcodeDetector.isOperational()) { + Log.e("QR", "BARCODE DETECTOR IS NOT OPERATIONAL !!!!"); + } + } + + + private void setUpCamera() { + try { + for (String cameraId : cameraManager.getCameraIdList()) { + + CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId); + + if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == cameraFacing) { + StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + previewSize = streamConfigurationMap.getOutputSizes(SurfaceTexture.class)[0]; + this.cameraId = cameraId; + + // TEST + previewImageReader = ImageReader.newInstance(400, 600, ImageFormat.YUV_420_888, 2); + previewImageReader.setOnImageAvailableListener(previewImageListener, camBackgroundHandler); + } + } + } catch (CameraAccessException e) { + e.printStackTrace(); + } + } + + private void openCamera() { + try { + if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { + cameraManager.openCamera(cameraId, stateCallback, camBackgroundHandler); + } + } catch (CameraAccessException e) { + e.printStackTrace(); + } + } + + private void createPreviewSession() { + try { + + SurfaceTexture surfaceTexture = texturePreviewView.getSurfaceTexture(); + surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); + + Surface previewSurface = new Surface(surfaceTexture); + + captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); + + // This is the real surface used for preview + captureRequestBuilder.addTarget(previewSurface); + + // preview Surface for postprocessing + captureRequestBuilder.addTarget(previewImageReader.getSurface()); + + cameraDevice.createCaptureSession(Arrays.asList(previewSurface, previewImageReader.getSurface()), new CameraCaptureSession.StateCallback() { + + @Override + public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { + if (cameraDevice == null) { + return; + } + + try { + captureRequest = captureRequestBuilder.build(); + + ReadQrActivity.this.cameraCaptureSession = cameraCaptureSession; + ReadQrActivity.this.cameraCaptureSession.setRepeatingRequest(captureRequest, null, camBackgroundHandler); + } catch (CameraAccessException e) { + e.printStackTrace(); + } + } + + @Override + public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { + + } + }, camBackgroundHandler); + } catch (CameraAccessException e) { + e.printStackTrace(); + } + } + + + private void camOpenBackgroundThread() { + camBackgroundThread = new HandlerThread("camera_background_thread"); + camBackgroundThread.start(); + camBackgroundHandler = new Handler(camBackgroundThread.getLooper()); + } + + private void closeCamera() { + if (cameraCaptureSession != null) { + cameraCaptureSession.close(); + cameraCaptureSession = null; + } + + if (cameraDevice != null) { + cameraDevice.close(); + cameraDevice = null; + } + } + + private void closeBackgroundThreads() { + if (camBackgroundHandler != null) { + camBackgroundThread.quitSafely(); + camBackgroundThread = null; + camBackgroundHandler = null; + } + } + + + @Override + protected void onResume() { + super.onResume(); + + camOpenBackgroundThread(); + + if (texturePreviewView.isAvailable()) { + setUpCamera(); + openCamera(); + } else { + texturePreviewView.setSurfaceTextureListener(surfaceTextureListener); + } + } + + @Override + protected void onStop() { + super.onStop(); + closeCamera(); + closeBackgroundThreads(); + } + + + private Bitmap YUV_420_888_toRGBIntrinsics(Image image) { + + if (image == null) return null; + + int W = image.getWidth(); + int H = image.getHeight(); + + Image.Plane Y = image.getPlanes()[0]; + Image.Plane U = image.getPlanes()[1]; + Image.Plane V = image.getPlanes()[2]; + + int Yb = Y.getBuffer().remaining(); + int Ub = U.getBuffer().remaining(); + int Vb = V.getBuffer().remaining(); + + byte[] data = new byte[Yb + Ub + Vb]; + + Y.getBuffer().get(data, 0, Yb); + V.getBuffer().get(data, Yb, Vb); + U.getBuffer().get(data, Yb + Vb, Ub); + + RenderScript rs = RenderScript.create(getApplicationContext()); + + ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs)); + + Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length); + Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT); + + Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(W).setY(H); + Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT); + + + final Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888); + + in.copyFromUnchecked(data); + + yuvToRgbIntrinsic.setInput(in); + yuvToRgbIntrinsic.forEach(out); + out.copyTo(bmpout); + image.close(); + return bmpout ; + } +} diff --git a/app/src/main/java/de/korrelator/overview/mispauth/SettingsActivity.java b/app/src/main/java/de/korrelator/overview/mispauth/SettingsActivity.java new file mode 100644 index 0000000..a46fec6 --- /dev/null +++ b/app/src/main/java/de/korrelator/overview/mispauth/SettingsActivity.java @@ -0,0 +1,28 @@ +package de.korrelator.overview.mispauth; + +import android.preference.Preference; +import android.preference.PreferenceFragment; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.ListView; + +public class SettingsActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getFragmentManager().beginTransaction().replace(android.R.id.content, new MainPreferenceFragment()).commit(); + } + + public static class MainPreferenceFragment extends PreferenceFragment { + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_main); + } + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_settings.png b/app/src/main/res/drawable-hdpi/ic_settings.png new file mode 100644 index 0000000..442ae11 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_settings.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_settings.png b/app/src/main/res/drawable-mdpi/ic_settings.png new file mode 100644 index 0000000..fd09e6e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_settings.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_settings.png b/app/src/main/res/drawable-xhdpi/ic_settings.png new file mode 100644 index 0000000..8e1af46 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_settings.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_settings.png b/app/src/main/res/drawable-xxhdpi/ic_settings.png new file mode 100644 index 0000000..dee13d7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_settings.png differ diff --git a/app/src/main/res/drawable/ic_info_black_24dp.xml b/app/src/main/res/drawable/ic_info_black_24dp.xml new file mode 100644 index 0000000..34b8202 --- /dev/null +++ b/app/src/main/res/drawable/ic_info_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/app/src/main/res/drawable/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..e3400cf --- /dev/null +++ b/app/src/main/res/drawable/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_sync_black_24dp.xml b/app/src/main/res/drawable/ic_sync_black_24dp.xml new file mode 100644 index 0000000..5a283aa --- /dev/null +++ b/app/src/main/res/drawable/ic_sync_black_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_generate_qr.xml b/app/src/main/res/layout/activity_generate_qr.xml new file mode 100644 index 0000000..edeb62e --- /dev/null +++ b/app/src/main/res/layout/activity_generate_qr.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_read_qr.xml b/app/src/main/res/layout/activity_read_qr.xml new file mode 100644 index 0000000..855d881 --- /dev/null +++ b/app/src/main/res/layout/activity_read_qr.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/preference_divider.xml b/app/src/main/res/layout/preference_divider.xml new file mode 100644 index 0000000..d444f7f --- /dev/null +++ b/app/src/main/res/layout/preference_divider.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml new file mode 100644 index 0000000..238168c --- /dev/null +++ b/app/src/main/res/menu/menu_main.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 3ab3e9c..4e76a5e 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,6 +1,6 @@ - #3F51B5 - #303F9F + #212121 + #000000 #FF4081 diff --git a/app/src/main/res/xml/pref_main.xml b/app/src/main/res/xml/pref_main.xml new file mode 100644 index 0000000..4646a05 --- /dev/null +++ b/app/src/main/res/xml/pref_main.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/test/java/de/korrelator/overview/mispauth/ExampleUnitTest.java b/app/src/test/java/de/korrelator/overview/mispauth/ExampleUnitTest.java new file mode 100644 index 0000000..35855b9 --- /dev/null +++ b/app/src/test/java/de/korrelator/overview/mispauth/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package de.korrelator.overview.mispauth; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..716245a --- /dev/null +++ b/readme.md @@ -0,0 +1,2 @@ +# MispAuth +Authentifizierung zweier Misp-Partner über QR-Codes \ No newline at end of file