Skip to content
Andika Wasisto edited this page Jun 27, 2020 · 10 revisions

Adding dependency

To use CamRNG in your app, add the dependency in your app-level build.gradle.

Requesting camera permission and creating a CamRng instance

It is recommended to create a CamRng instance only when it is needed then free the resources immediately once you are finished with it to prevent the device from overheating. But if you're creating a random number generator server or you need your activity or fragment to generate numbers multiple times, you can create a CamRng instance on the onStart method.

The following example shows how to create a NoiseBasedCamRng with the maximum number of pixels

class MyActivity : AppCompatActivity() {

    companion object {
        private const val REQUEST_CAMERA_PERMISSION = 1
    }

    override fun onStart() {
        super.onStart()

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            onPermissionGranted()
        } else {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults.size == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                onPermissionGranted()
            } else {
                Toast.makeText(this, "Camera permission denied", Toast.LENGTH_LONG).show()
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

    private fun onPermissionGranted() {
        try {
            val camRng = NoiseBasedCamRng.newInstance(context = this)

            // ...

        } catch (e: CameraInitializationFailedException) {
            Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
        }
    }

See Instance Creation & Configuration

Using a CamRng instance

CamRNG uses RxJava 2 to output the generated data. The following example shows how to use a CamRng instance to show a random number between 1-6 when a user clicks a button.

Create a CompositeDisposable on your activity or fragment

class MyActivity : AppCompatActivity() {

    private val compositeDisposable = CompositeDisposable()

Generate a random number between 1-6

diceRollButton.setOnClickListener {
    compositeDisposable.add(
        camRng.getInt(bound = 6)
            .map {
                it + 1
            }
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { diceRollOutcome ->
                diceRollOutcomeTextView.text = diceRollOutcome.toString()
            }
        )
}

See Usage Cookbook

Freeing resources

You have to free the resources once you are done generating numbers to avoid memory leak and overheating. The following example shows how to free the resources if you created a NoiseBasedCamRng instance on the onStart method.

class MyActivity : AppCompatActivity() {

    override fun onStop() {
        super.onStop()
        NoiseBasedCamRng.reset()
    }

    override fun onDestroy() {
        super.onDestroy()
        compositeDisposable.dispose()
    }

Full Activity Example

class MyActivity : AppCompatActivity() {

    companion object {
        private const val REQUEST_CAMERA_PERMISSION = 1
    }

    private val compositeDisposable = CompositeDisposable()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.my_activity)
    }

    override fun onStart() {
        super.onStart()

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            onPermissionGranted()
        } else {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults.size == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                onPermissionGranted()
            } else {
                Toast.makeText(this, "Camera permission denied", Toast.LENGTH_LONG).show()
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

    private fun onPermissionGranted() {
        try {
            val camRng = NoiseBasedCamRng.newInstance(context = this)

            diceRollButton.setOnClickListener {
                compositeDisposable.add(
                    camRng.getInt(bound = 6)
                        .map {
                            it + 1
                        }
                        .subscribeOn(Schedulers.newThread())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe { diceRollOutcome ->
                            diceRollOutcomeTextView.text = diceRollOutcome.toString()
                        }
                )
            }
        } catch (e: CameraInitializationFailedException) {
            Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
        }
    }

    override fun onStop() {
        super.onStop()
        NoiseBasedCamRng.reset()
    }

    override fun onDestroy() {
        super.onDestroy()
        compositeDisposable.dispose()
    }
}