Skip to content

Instantly share code, notes, and snippets.

@salamanders
Last active August 1, 2018 23:17
Show Gist options
  • Save salamanders/0e20fe1122000220c76b118d16c83f56 to your computer and use it in GitHub Desktop.
Save salamanders/0e20fe1122000220c76b118d16c83f56 to your computer and use it in GitHub Desktop.
Hello World Timer Camera using CameraKit
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.camerakit.CameraKitView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cameraView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:camera_facing="back"
app:camera_imageJpegQuality="99"
/>
</android.support.constraint.ConstraintLayout>
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
defaultConfig {
applicationId "info.benjaminhill.snailfps"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
repositories {
maven { url 'https://dl.bintray.com/camerakit/camerakit-android-snapshots' }
}
// Make sure snapshots won't get cached.
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0-beta01'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
// implementation 'com.wonderkiln:camerakit:0.13.1'
// implementation 'com.android.support:exifinterface:27.1.1'
implementation group: 'com.camerakit', name: 'camerakit', version: '1.0.0-Snapshot', changing: true
}
package info.benjaminhill.snailfps
import android.content.pm.PackageManager
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.widget.Toast
/**
* Work out the dangerous permissions listed in the AndroidManifest.xml (dynamically)
* before diving into the app: `runAfterAllPermissionsGranted { yourCode }`
*/
abstract class EZPermissionActivity : AppCompatActivity() {
private lateinit var permissionCallback: () -> Unit
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Don't ignore exceptions in coroutines https://github.com/Kotlin/kotlinx.coroutines/issues/148#issuecomment-338101986
val baseUEH = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler { thread, error ->
// this may double log the error on older versions of android
Log.w(TAG, "FATAL EXCEPTION: ${thread.name} $error")
Log.w(TAG, error)
baseUEH.uncaughtException(thread, error)
throw error
}
}
/** Protect your code with this block */
protected fun runAfterAllPermissionsGranted(f: () -> Unit) = if (missingPermissions.isEmpty()) {
Log.i(TAG, "We already have all the permissions (${requiredPermissions.joinToString()}) we needed, running directly")
f()
} else {
// This is a prototype so we skip the right way to do permissions (with reasons given first, fallback plan, etc)
Log.i(TAG, "Requesting permissions, be back soon.")
logPermissions()
permissionCallback = f
ActivityCompat.requestPermissions(this, missingPermissions.toTypedArray(), SIMPLE_PERMISSION_ID)
}
override fun onRequestPermissionsResult(requestCode: Int, grantPermissions: Array<out String>, grantResults: IntArray) =
if (requestCode == SIMPLE_PERMISSION_ID) {
Log.i(TAG, "Permission grant result: ${grantPermissions.joinToString()}=${grantResults.joinToString()}")
logPermissions()
if (missingPermissions.isEmpty()) {
Log.i(TAG, "User granted all permissions that we requested.")
permissionCallback()
} else {
Log.w(TAG, "User declined required permissions: ${missingPermissions.joinToString()}")
Toast.makeText(this, "Please restart the app after allowing access to: ${missingPermissions.joinToString()}", Toast.LENGTH_LONG).show()
}
} else {
super.onRequestPermissionsResult(requestCode, grantPermissions, grantResults)
}
private fun logPermissions() = requiredPermissions.forEach {
Log.i(TAG, "Permission: $it; missing: ${it in missingPermissions}")
}
private val requiredPermissions
get() = packageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS).requestedPermissions
.toSet()
private val missingPermissions
get() = requiredPermissions
.filter { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED }
.toSet()
companion object {
private const val SIMPLE_PERMISSION_ID = 42
private const val TAG = "ezpermissions"
}
}
package info.benjaminhill.snailfps
import android.media.MediaScannerConnection
import android.os.Bundle
import android.os.Environment
import android.util.Log
import com.camerakit.CameraKitView
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.schedule
class MainActivity : EZPermissionActivity() {
private lateinit var ckView: CameraKitView
private val sdf = SimpleDateFormat("yyyyMMddhhmmss", Locale.US)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "onCreate: Starting Snail FPS")
ckView = cameraView
}
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume")
ckView.onResume()
runAfterAllPermissionsGranted {
Timer().schedule(3000) {
ckView.captureImage { _, imageBytes ->
Log.i(TAG, "onImage 1 ${imageBytes.size}")
val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)!!
path.mkdirs()
val timestamp = sdf.format(Date())!!
File(path, "snail_$timestamp.jpg").let { imageFile ->
Log.w(TAG, "Writing image to file: $imageFile ${imageFile.isFile}")
imageFile.createNewFile()
imageFile.writeBytes(imageBytes)
MediaScannerConnection.scanFile(applicationContext, arrayOf(imageFile.path), arrayOf("image/jpeg")) { str, u ->
Log.i(TAG, "scanFile $str $u")
}
}
Log.i(TAG, "onImage 1 FINISHED")
}
Log.d(TAG, "captureImage 1")
}
}
}
override fun onPause() {
ckView.onPause()
super.onPause()
}
override fun onRequestPermissionsResult(requestCode: Int, grantPermissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, grantPermissions, grantResults)
ckView.onRequestPermissionsResult(requestCode, grantPermissions, grantResults)
}
companion object {
const val TAG = "tsnailfps"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment