Last active
August 1, 2018 23:17
-
-
Save salamanders/0e20fe1122000220c76b118d16c83f56 to your computer and use it in GitHub Desktop.
Hello World Timer Camera using CameraKit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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