Kapt: Gradle integration tests for the new kapt

(cherry picked from commit 467d0fd)
This commit is contained in:
Yan Zhulanow
2016-08-12 19:03:38 +03:00
committed by Yan Zhulanow
parent 9960e7f7cd
commit 46367d720c
94 changed files with 1810 additions and 8 deletions
@@ -26,7 +26,6 @@
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -45,7 +45,7 @@ class ExampleAnnotationProcessor : AbstractProcessor() {
val simpleName = element.simpleName.toString()
val generatedJavaClassName = generatedFilePrefix.capitalize() + simpleName.capitalize() + generatedFileSuffix
filer.createSourceFile(generatedJavaClassName).openWriter().use { with(it) {
filer.createSourceFile(packageName + '.' + generatedJavaClassName).openWriter().use { with(it) {
appendln("package $packageName;")
appendln("public final class $generatedJavaClassName {}")
}}
@@ -72,8 +72,14 @@ abstract class BaseGradleIT {
val androidHome: File? = null,
val androidGradlePluginVersion: String? = null)
open inner class Project(val projectName: String, val wrapperVersion: String, val minLogLevel: LogLevel = LogLevel.DEBUG) {
open val resourcesRoot = File(resourcesRootFile, "testProject/$projectName")
open inner class Project(
val projectName: String,
val wrapperVersion: String,
directoryPrefix: String? = null,
val minLogLevel: LogLevel = LogLevel.DEBUG
) {
val resourceDirName = if (directoryPrefix != null) "$directoryPrefix/$projectName" else projectName
open val resourcesRoot = File(resourcesRootFile, "testProject/$resourceDirName")
val projectDir = File(workingDir.canonicalFile, projectName)
open fun setupWorkingDir() {
@@ -10,7 +10,7 @@ import kotlin.test.assertEquals
abstract class BaseIncrementalGradleIT : BaseGradleIT() {
inner class JpsTestProject(val buildLogFinder: BuildLogFinder, val resourcesBase: File, val relPath: String, wrapperVersion: String = "2.10", minLogLevel: LogLevel = LogLevel.DEBUG) : Project(File(relPath).name, wrapperVersion, minLogLevel) {
inner class JpsTestProject(val buildLogFinder: BuildLogFinder, val resourcesBase: File, val relPath: String, wrapperVersion: String = "2.10", minLogLevel: LogLevel = LogLevel.DEBUG) : Project(File(relPath).name, wrapperVersion, null, minLogLevel) {
override val resourcesRoot = File(resourcesBase, relPath)
val mapWorkingToOriginalFile = hashMapOf<File, File>()
@@ -0,0 +1,142 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle
import org.junit.Test
import java.io.File
import java.io.FileFilter
class Kapt2IT: BaseGradleIT() {
companion object {
private const val GRADLE_VERSION = "2.10"
private const val ANDROID_GRADLE_PLUGIN_VERSION = "1.5.+"
}
private fun androidBuildOptions() =
BuildOptions(withDaemon = true,
androidHome = File("../../../dependencies/android-sdk-for-tests"),
androidGradlePluginVersion = ANDROID_GRADLE_PLUGIN_VERSION)
override fun defaultBuildOptions(): BuildOptions =
super.defaultBuildOptions().copy(withDaemon = true)
private fun CompiledProject.assertKaptSuccessful() {
assertContains("Kapt: Annotation processing complete, 0 errors, 0 warnings")
}
@Test
fun testSimple() {
val project = Project("simple", GRADLE_VERSION, directoryPrefix = "kapt2")
project.build("build") {
assertSuccessful()
assertKaptSuccessful()
assertContains(":compileKotlin")
assertContains(":compileJava")
assertFileExists("build/generated/source/kapt2/main/example/TestClassGenerated.java")
assertFileExists("build/classes/main/example/TestClass.class")
assertFileExists("build/classes/main/example/TestClassGenerated.class")
assertFileExists("build/classes/main/example/SourceAnnotatedTestClassGenerated.class")
assertFileExists("build/classes/main/example/BinaryAnnotatedTestClassGenerated.class")
assertFileExists("build/classes/main/example/RuntimeAnnotatedTestClassGenerated.class")
assertContains("example.JavaTest PASSED")
}
project.build("build") {
assertSuccessful()
assertContains(":compileKotlin UP-TO-DATE")
assertContains(":compileJava UP-TO-DATE")
}
}
@Test
fun testInheritedAnnotations() {
Project("inheritedAnnotations", GRADLE_VERSION, directoryPrefix = "kapt2").build("build") {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("build/generated/source/kapt2/main/example/TestClassGenerated.java")
assertFileExists("build/generated/source/kapt2/main/example/AncestorClassGenerated.java")
assertFileExists("build/classes/main/example/TestClassGenerated.class")
assertFileExists("build/classes/main/example/AncestorClassGenerated.class")
}
}
@Test
fun testButterKnife() {
val project = Project("android-butterknife", GRADLE_VERSION, directoryPrefix = "kapt2")
val options = androidBuildOptions()
project.build("assembleRelease", options = options) {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("app/build/generated/source/kapt2/release/org/example/kotlin/butterknife/SimpleActivity\$\$ViewBinder.java")
assertFileExists("app/build/intermediates/classes/release/org/example/kotlin/butterknife/SimpleActivity\$\$ViewBinder.class")
assertFileExists("app/build/intermediates/classes/release/org/example/kotlin/butterknife/SimpleAdapter\$ViewHolder.class")
}
project.build("assembleRelease", options = options) {
assertSuccessful()
assertContains(":compileReleaseKotlin UP-TO-DATE")
assertContains(":compileReleaseJavaWithJavac UP-TO-DATE")
}
}
@Test
fun testDagger() {
val project = Project("android-dagger", GRADLE_VERSION, directoryPrefix = "kapt2")
val options = androidBuildOptions()
project.build("assembleRelease", options = options) {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("app/build/generated/source/kapt2/release/com/example/dagger/kotlin/DaggerApplicationComponent.java")
assertFileExists("app/build/generated/source/kapt2/release/com/example/dagger/kotlin/ui/HomeActivity_MembersInjector.java")
assertFileExists("app/build/intermediates/classes/release/com/example/dagger/kotlin/DaggerApplicationComponent.class")
assertFileExists("app/build/intermediates/classes/release/com/example/dagger/kotlin/AndroidModule.class")
}
}
@Test
fun testDbFlow() {
val project = Project("android-dbflow", GRADLE_VERSION, directoryPrefix = "kapt2")
val options = androidBuildOptions()
project.build("assembleRelease", options = options) {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("app/build/generated/source/kapt2/release/com/raizlabs/android/dbflow/config/GeneratedDatabaseHolder.java")
assertFileExists("app/build/generated/source/kapt2/release/com/raizlabs/android/dbflow/config/AppDatabaseapp_Database.java")
assertFileExists("app/build/generated/source/kapt2/release/mobi/porquenao/poc/kotlin/core/Item_Table.java")
assertFileExists("app/build/generated/source/kapt2/release/mobi/porquenao/poc/kotlin/core/Item_Adapter.java")
}
}
@Test
fun testRealm() {
val project = Project("android-realm", GRADLE_VERSION, directoryPrefix = "kapt2")
val options = androidBuildOptions()
project.build("assembleRelease", options = options) {
assertSuccessful()
assertKaptSuccessful()
assertFileExists("build/generated/source/kapt2/release/io/realm/CatRealmProxy.java")
assertFileExists("build/generated/source/kapt2/release/io/realm/CatRealmProxyInterface.java")
assertFileExists("build/generated/source/kapt2/release/io/realm/DefaultRealmModule.java")
assertFileExists("build/generated/source/kapt2/release/io/realm/DefaultRealmModuleMediator.java")
}
}
}
@@ -24,7 +24,7 @@ class KaptIT: BaseGradleIT() {
assertContains(":compileKotlin")
assertContains(":compileJava")
assertFileExists("build/tmp/kapt/main/wrappers/annotations.main.txt")
assertFileExists("build/generated/source/kapt/main/TestClassGenerated.java")
assertFileExists("build/generated/source/kapt/main/example/TestClassGenerated.java")
assertFileExists("build/classes/main/example/TestClass.class")
assertFileExists("build/classes/main/example/TestClassGenerated.class")
assertNoSuchFile("build/classes/main/example/SourceAnnotatedTestClassGenerated.class")
@@ -162,8 +162,8 @@ class KaptIT: BaseGradleIT() {
fun testInheritedAnnotations() {
Project("kaptInheritedAnnotations", GRADLE_VERSION).build("build") {
assertSuccessful()
assertFileExists("build/generated/source/kapt/main/TestClassGenerated.java")
assertFileExists("build/generated/source/kapt/main/AncestorClassGenerated.java")
assertFileExists("build/generated/source/kapt/main/example/TestClassGenerated.java")
assertFileExists("build/generated/source/kapt/main/example/AncestorClassGenerated.java")
assertFileExists("build/classes/main/example/TestClassGenerated.class")
assertFileExists("build/classes/main/example/AncestorClassGenerated.class")
}
@@ -0,0 +1,37 @@
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "org.example.kotlin.butterknife"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.jakewharton:butterknife:8.0.1'
kapt 'com.jakewharton:butterknife-compiler:8.0.1'
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
}
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/yan/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.example.kotlin.butterknife">
<application
android:label="@string/app_name"
android:name=".SimpleApp">
<activity
android:label="@string/app_name"
android:name=".SimpleActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,84 @@
package org.example.kotlin.butterknife
import android.app.Activity
import android.os.Bundle
import android.view.View
import android.view.animation.AlphaAnimation
import android.widget.Button
import android.widget.ListView
import android.widget.TextView
import android.widget.Toast
import android.widget.Toast.LENGTH_SHORT
import butterknife.*
class SimpleActivity : Activity() {
@BindView(R.id.title)
lateinit var title: TextView
@BindView(R.id.subtitle)
lateinit var subtitle: TextView
@BindView(R.id.hello)
lateinit var hello: Button
@BindView(R.id.list_of_things)
lateinit var listOfThings: ListView
@BindView(R.id.footer)
lateinit var footer: TextView
@BindViews(R.id.title, R.id.subtitle, R.id.hello)
lateinit var headerViews: MutableList<View>
@JvmField
@BindColor(R.color.blue)
var titleTextColor: Int = 0
private lateinit var adapter: SimpleAdapter
@OnClick(R.id.hello)
fun sayHello() {
Toast.makeText(this, "Hello, views!", LENGTH_SHORT).show()
ButterKnife.apply(headerViews.toList(), ALPHA_FADE)
}
@OnLongClick(R.id.hello)
fun sayGetOffMe(): Boolean {
Toast.makeText(this, "Let go of me!", LENGTH_SHORT).show()
return true
}
@OnItemClick(R.id.list_of_things)
fun onItemClick(position: Int) {
Toast.makeText(this, "You clicked: " + adapter.getItem(position), LENGTH_SHORT).show()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.simple_activity)
ButterKnife.bind(this)
title.text = "Butter Knife"
subtitle.text = "Field and method binding for Android views."
footer.text = "by Jake Wharton"
hello.text = "Say Hello"
title.setTextColor(titleTextColor)
adapter = SimpleAdapter(this)
listOfThings.adapter = adapter
}
companion object {
private val ALPHA_FADE = ButterKnife.Action<View> { view, index ->
with (AlphaAnimation(0f, 1f)) {
fillBefore = true
duration = 500
startOffset = (index * 100).toLong()
view.startAnimation(this)
}
}
}
}
@@ -0,0 +1,57 @@
package org.example.kotlin.butterknife
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import butterknife.ButterKnife
import butterknife.BindView
class SimpleAdapter(context: Context) : BaseAdapter() {
private val inflater = LayoutInflater.from(context)
override fun getCount() = CONTENTS.size
override fun getItem(position: Int) = CONTENTS[position]
override fun getItemId(position: Int) = position.toLong()
override fun getView(position: Int, v: View?, parent: ViewGroup): View {
var view = v
val holder: ViewHolder
if (view != null) {
holder = view.tag as ViewHolder
} else {
view = inflater.inflate(R.layout.simple_list_item, parent, false)
holder = ViewHolder(view)
view!!.tag = holder
}
val word = getItem(position)
holder.word.text = "Word: $word"
holder.length.text = "Length: ${word.length}"
holder.position.text = "Position: $position"
return view
}
class ViewHolder(view: View) {
@BindView(R.id.word)
lateinit var word: TextView
@BindView(R.id.length)
lateinit var length: TextView
@BindView(R.id.position)
lateinit var position: TextView
init {
ButterKnife.bind(this, view)
}
}
companion object {
private val CONTENTS = "The quick brown fox jumps over the lazy dog".split(" ")
}
}
@@ -0,0 +1,11 @@
package org.example.kotlin.butterknife
import android.app.Application
import butterknife.ButterKnife
class SimpleApp : Application() {
override fun onCreate() {
super.onCreate()
ButterKnife.setDebug(BuildConfig.DEBUG)
}
}
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="50sp"
/>
<TextView
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
/>
<Button
android:id="@+id/hello"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="10dp"
/>
<ListView
android:id="@+id/list_of_things"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="10dp"
/>
<TextView
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="17sp"
android:textStyle="italic"
/>
</LinearLayout>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/word"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/length"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/position"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="blue">#3366ee</color>
</resources>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Butter Knife</string>
</resources>
@@ -0,0 +1,24 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
}
}
allprojects {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
}
@@ -0,0 +1,37 @@
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.example.dagger.kotlin"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.3.0'
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
compile 'com.google.dagger:dagger:2.2'
kapt 'com.google.dagger:dagger-compiler:2.2'
provided 'org.glassfish:javax.annotation:10.0-b28'
}
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/yan/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.dagger.kotlin">
<application
android:allowBackup="true"
android:label="app_name"
android:name=".DemoApplication">
<activity
android:label="app_name"
android:name=".ui.HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.kotlin
import android.content.Context
import android.content.Context.LOCATION_SERVICE
import android.location.LocationManager
import dagger.Module
import dagger.Provides
import javax.inject.Singleton
/**
* A module for Android-specific dependencies which require a [Context] or
* [android.app.Application] to create.
*/
@Module class AndroidModule(private val application: BaseApplication) {
/**
* Allow the application context to be injected but require that it be annotated with
* [@Annotation][ForApplication] to explicitly differentiate it from an activity context.
*/
@Provides @Singleton @ForApplication
fun provideApplicationContext(): Context {
return application
}
@Provides @Singleton
fun provideLocationManager(): LocationManager {
return application.getSystemService(LOCATION_SERVICE) as LocationManager
}
}
@@ -0,0 +1,13 @@
package com.example.dagger.kotlin
import com.example.dagger.kotlin.ui.HomeActivity
import dagger.Component
import javax.inject.Singleton
@Singleton
@Component(modules = arrayOf(AndroidModule::class))
interface ApplicationComponent {
fun inject(application: BaseApplication)
fun inject(homeActivity: HomeActivity)
fun inject(demoActivity: DemoActivity)
}
@@ -0,0 +1,11 @@
package com.example.dagger.kotlin
import android.app.Application
abstract class BaseApplication : Application() {
protected fun initDaggerComponent(): ApplicationComponent {
return DaggerApplicationComponent.builder().androidModule(AndroidModule(this)).build()
}
}
@@ -0,0 +1,12 @@
package com.example.dagger.kotlin
import android.app.Activity
import android.os.Bundle
abstract class DemoActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Perform injection so that when this call returns all dependencies will be available for use.
(application as DemoApplication).component.inject(this)
}
}
@@ -0,0 +1,13 @@
package com.example.dagger.kotlin
class DemoApplication : BaseApplication() {
lateinit var component: ApplicationComponent
override fun onCreate() {
super.onCreate()
val component = initDaggerComponent()
component.inject(this) // As of now, LocationManager should be injected into this.
this.component = component
}
}
@@ -0,0 +1,6 @@
package com.example.dagger.kotlin
import javax.inject.Qualifier
@Qualifier
annotation class ForApplication
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.kotlin.ui
import android.location.LocationManager
import android.os.Bundle
import com.example.dagger.kotlin.DemoActivity
import com.example.dagger.kotlin.DemoApplication
import com.example.dagger.kotlin.R
import kotlinx.android.synthetic.main.activity_main.locationInfo
import javax.inject.Inject
class HomeActivity : DemoActivity() {
@Inject
lateinit var locationManager: LocationManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
(application as DemoApplication).component.inject(this)
// TODO do something with the injected dependencies here!
locationInfo.text = "Injected LocationManager:\n$locationManager"
}
}
@@ -0,0 +1,10 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".ui.HomeActivity">
<TextView android:id="@+id/locationInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp" />
</RelativeLayout>
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">kotlin</string>
</resources>
@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
@@ -0,0 +1,24 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
}
}
allprojects {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
}
@@ -0,0 +1,39 @@
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName '1.0'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
def dbflow_version = "3.1.1"
dependencies {
// Android Support Libraries
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:cardview-v7:23.3.0'
compile 'com.android.support:recyclerview-v7:23.3.0'
// DBFlow
kapt "com.github.Raizlabs.DBFlow:dbflow-processor:${dbflow_version}"
compile "com.github.Raizlabs.DBFlow:dbflow-core:${dbflow_version}"
compile "com.github.Raizlabs.DBFlow:dbflow:${dbflow_version}"
compile "com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:${dbflow_version}"
// Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
}
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="mobi.porquenao.poc.kotlin"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".DatabaseApplication"
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,18 @@
package mobi.porquenao.poc.kotlin
import android.app.Application
import com.raizlabs.android.dbflow.config.FlowConfig
import com.raizlabs.android.dbflow.config.FlowManager
class DatabaseApplication : Application() {
override fun onCreate() {
super.onCreate()
FlowManager.init(FlowConfig.Builder(this).build())
}
override fun onTerminate() {
super.onTerminate()
FlowManager.destroy()
}
}
@@ -0,0 +1,9 @@
package mobi.porquenao.poc.kotlin.core
import com.raizlabs.android.dbflow.annotation.Database
@Database(name = AppDatabase.NAME, version = AppDatabase.VERSION, generatedClassSeparator = "_")
object AppDatabase {
const val NAME: String = "app"
const val VERSION: Int = 1
}
@@ -0,0 +1,20 @@
package mobi.porquenao.poc.kotlin.core
import com.raizlabs.android.dbflow.converter.TypeConverter
import java.util.*
import com.raizlabs.android.dbflow.annotation.TypeConverter as TypeConverterAnnotation
@TypeConverterAnnotation
class CalendarConverter : TypeConverter<Long, Calendar>() {
override fun getDBValue(model: Calendar): Long? {
return model.timeInMillis
}
override fun getModelValue(data: Long?): Calendar {
val calendar = Calendar.getInstance()
calendar.timeInMillis = data!!
return calendar
}
}
@@ -0,0 +1,19 @@
package mobi.porquenao.poc.kotlin.core
import com.raizlabs.android.dbflow.annotation.Column
import com.raizlabs.android.dbflow.annotation.PrimaryKey
import com.raizlabs.android.dbflow.annotation.Table
import com.raizlabs.android.dbflow.structure.BaseModel
import java.util.*
@Table(name = "items", database = AppDatabase::class)
class Item : BaseModel() {
@PrimaryKey(autoincrement = true)
@Column(name = "id")
var id: Long = 0
@Column(name = "updated_at", typeConverter = CalendarConverter::class)
var updatedAt: Calendar = Calendar.getInstance()
}
@@ -0,0 +1,15 @@
package mobi.porquenao.poc.kotlin.core
import com.raizlabs.android.dbflow.sql.language.Select
object ItemRepository {
fun getAll(): MutableList<Item> {
return Select()
.from(Item::class.java)
.where()
.orderBy(Item_Table.updated_at, false)
.queryList()
}
}
@@ -0,0 +1,38 @@
package mobi.porquenao.poc.kotlin.ui
import android.app.ActivityManager
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import mobi.porquenao.poc.kotlin.R
abstract class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
prepareTaskDescription()
}
override fun setContentView(layoutResID: Int) {
super.setContentView(layoutResID)
setSupportActionBar(toolbar)
}
private fun prepareTaskDescription() {
if (Build.VERSION.SDK_INT >= 21) {
if (sTaskDescription == null) {
val label = getString(R.string.app_name)
val icon = BitmapFactory.decodeResource(resources, R.drawable.ic_task)
val colorPrimary = resources.getColor(R.color.app_primary_500)
sTaskDescription = ActivityManager.TaskDescription(label, icon, colorPrimary)
}
setTaskDescription(sTaskDescription)
}
}
companion object {
private var sTaskDescription: ActivityManager.TaskDescription? = null
}
}
@@ -0,0 +1,36 @@
package mobi.porquenao.poc.kotlin.ui
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.view.Menu
import android.view.MenuItem
import kotlinx.android.synthetic.main.activity_main.*
import mobi.porquenao.poc.kotlin.R
class MainActivity : BaseActivity() {
lateinit var listAdapter: MainAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
with (list) {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(this@MainActivity)
listAdapter = MainAdapter()
adapter = listAdapter
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
listAdapter.add()
list.smoothScrollToPosition(0)
return true
}
}
@@ -0,0 +1,67 @@
package mobi.porquenao.poc.kotlin.ui
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.main_item.view.*
import mobi.porquenao.poc.kotlin.R
import mobi.porquenao.poc.kotlin.core.Item
import mobi.porquenao.poc.kotlin.core.ItemRepository
import java.util.*
class MainAdapter : RecyclerView.Adapter<MainAdapter.ViewHolder>() {
private val mItems: MutableList<Item>
private val mOnClickListener: View.OnClickListener
init {
mItems = ItemRepository.getAll()
mOnClickListener = View.OnClickListener { v ->
val item = v.tag as Item
item.updatedAt = Calendar.getInstance()
item.save()
notifyDataSetChanged()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return ViewHolder(layoutInflater.inflate(R.layout.main_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = mItems[position]
val date = item.updatedAt.timeInMillis
val color = "#" + date.toString().substring(7)
holder.card.setCardBackgroundColor(Color.parseColor(color))
holder.title.text = color
holder.date.text = DateFormat.format("hh:mm:ss", Date(date))
with (holder.container) {
tag = item
setOnClickListener(mOnClickListener)
}
}
override fun getItemCount(): Int {
return mItems.size
}
fun add() {
val item = Item()
mItems.add(0, item)
item.save()
notifyItemInserted(0)
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val card = view.card
val container = view.container
val title = view.title
val date = view.date
}
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:attr/selectableItemBackground" android:state_pressed="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/AppToolbar"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:scrollbars="vertical"/>
</LinearLayout>
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
android:id="@+id/card"
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="100dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
app:cardBackgroundColor="@color/app_primary_500"
app:cardCornerRadius="2dp"
tools:ignore="RtlHardcoded,RtlSymmetry">
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical"
android:padding="16dip"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="30sp"
tools:text="#2196F3"/>
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="18sp"
android:text="01:23:45"
tools:ignore="HardcodedText" />
</LinearLayout>
</android.support.v7.widget.CardView>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_event"
android:icon="@drawable/abc_ic_menu_copy_mtrl_am_alpha"
android:title="@string/menu_add"
app:showAsAction="always"/>
</menu>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="app_primary_500">#2196F3</color>
<color name="app_primary_700">#0087e9</color>
<color name="app_accent_200">#FF3D00</color>
</resources>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">POC Kotlin</string>
<string name="menu_add">Add</string>
</resources>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">@color/app_accent_200</item>
<item name="colorPrimary">@color/app_primary_500</item>
<item name="colorPrimaryDark">@color/app_primary_700</item>
</style>
<style name="AppToolbar" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">?attr/colorPrimary</item>
<item name="android:minHeight">?attr/actionBarSize</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
<item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
</style>
</resources>
@@ -0,0 +1,25 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
}
}
allprojects {
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
maven { url "https://jitpack.io" }
}
}
@@ -0,0 +1,63 @@
buildscript {
ext.realm_version = '1.1.1'
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
classpath("io.realm:realm-gradle-plugin:$realm_version") {
exclude group: 'com.android.tools.build', module: 'gradle'
}
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
}
}
apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'realm-android'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId 'io.realm.examples.kotlin'
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
}
}
dexOptions {
incremental false
}
}
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
maven {
url 'http://oss.jfrog.org/artifactory/oss-snapshot-local'
}
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
compile "org.jetbrains.kotlin:kotlin-reflect:0.1-SNAPSHOT"
compile 'org.jetbrains.anko:anko-common:0.9'
}
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/22.6.2/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
@@ -0,0 +1,20 @@
<manifest package="io.realm.examples.kotlin"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".KotlinExampleActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,219 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.realm.examples.kotlin
import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.widget.LinearLayout
import android.widget.TextView
import io.realm.Realm
import io.realm.Sort
import io.realm.RealmConfiguration
import io.realm.examples.kotlin.model.Cat
import io.realm.examples.kotlin.model.Dog
import io.realm.examples.kotlin.model.Person
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import kotlin.properties.Delegates
class KotlinExampleActivity : Activity() {
companion object {
val TAG: String = KotlinExampleActivity::class.qualifiedName as String
}
private var rootLayout: LinearLayout by Delegates.notNull()
private var realm: Realm by Delegates.notNull()
private var realmConfig: RealmConfiguration by Delegates.notNull()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_realm_basic_example)
rootLayout = findViewById(R.id.container) as LinearLayout
rootLayout.removeAllViews()
// These operations are small enough that
// we can generally safely run them on the UI thread.
// Create configuration and reset Realm.
realmConfig = RealmConfiguration.Builder(this).build()
Realm.deleteRealm(realmConfig)
// Open the realm for the UI thread.
realm = Realm.getInstance(realmConfig)
basicCRUD(realm)
basicQuery(realm)
basicLinkQuery(realm)
// Delete all persons
// Using executeTransaction with a lambda reduces code size and makes it impossible
// to forget to commit the transaction.
realm.executeTransaction {
realm.delete(Person::class.java)
}
// More complex operations can be executed on another thread, for example using
// Anko's async extension method.
doAsync() {
var info: String
info = complexReadWrite()
info += complexQuery()
uiThread {
showStatus(info)
}
}
}
override fun onDestroy() {
super.onDestroy()
realm.close() // Remember to close Realm when done.
}
private fun showStatus(txt: String) {
Log.i(TAG, txt)
val tv = TextView(this)
tv.text = txt
rootLayout.addView(tv)
}
private fun basicCRUD(realm: Realm) {
showStatus("Perform basic Create/Read/Update/Delete (CRUD) operations...")
// All writes must be wrapped in a transaction to facilitate safe multi threading
realm.executeTransaction {
// Add a person
var person = realm.createObject(Person::class.java)
person.id = 1
person.name = "Young Person"
person.age = 14
}
// Find the first person (no query conditions) and read a field
var person = realm.where(Person::class.java).findFirst()
showStatus(person.name + ": " + person.age)
// Update person in a transaction
realm.executeTransaction {
person.name = "Senior Person"
person.age = 99
showStatus(person.name + " got older: " + person.age)
}
}
private fun basicQuery(realm: Realm) {
showStatus("\nPerforming basic Query operation...")
showStatus("Number of persons: ${realm.where(Person::class.java).count()}")
val results = realm.where(Person::class.java).equalTo("age", 99).findAll()
showStatus("Size of result set: " + results.size)
}
private fun basicLinkQuery(realm: Realm) {
showStatus("\nPerforming basic Link Query operation...")
showStatus("Number of persons: ${realm.where(Person::class.java).count()}")
val results = realm.where(Person::class.java).equalTo("cats.name", "Tiger").findAll()
showStatus("Size of result set: ${results.size}")
}
private fun complexReadWrite(): String {
var status = "\nPerforming complex Read/Write operation..."
// Open the default realm. All threads must use it's own reference to the realm.
// Those can not be transferred across threads.
val realm = Realm.getInstance(realmConfig)
// Add ten persons in one transaction
realm.executeTransaction {
val fido = realm.createObject(Dog::class.java)
fido.name = "fido"
for (i in 0..9) {
val person = realm.createObject(Person::class.java)
person.id = i.toLong()
person.name = "Person no. $i"
person.age = i
person.dog = fido
// The field tempReference is annotated with @Ignore.
// This means setTempReference sets the Person tempReference
// field directly. The tempReference is NOT saved as part of
// the RealmObject:
person.tempReference = 42
for (j in 0..i - 1) {
val cat = realm.createObject(Cat::class.java)
cat.name = "Cat_$j"
person.cats.add(cat)
}
}
}
// Implicit read transactions allow you to access your objects
status += "\nNumber of persons: ${realm.where(Person::class.java).count()}"
// Iterate over all objects
for (person in realm.where(Person::class.java).findAll()) {
val dogName: String = person?.dog?.name ?: "None"
status += "\n${person.name}: ${person.age} : $dogName : ${person.cats.size}"
// The field tempReference is annotated with @Ignore
// Though we initially set its value to 42, it has
// not been saved as part of the Person RealmObject:
check(person.tempReference == 0)
}
// Sorting
val sortedPersons = realm.where(Person::class.java).findAllSorted("age", Sort.DESCENDING);
check(realm.where(Person::class.java).findAll().last().name == sortedPersons.first().name)
status += "\nSorting ${sortedPersons.last().name} == ${realm.where(Person::class.java).findAll().first().name}"
realm.close()
return status
}
private fun complexQuery(): String {
var status = "\n\nPerforming complex Query operation..."
// Realm implements the Closable interface, therefore we can make use of Kotlin's built-in
// extension method 'use' (pun intended).
Realm.getInstance(realmConfig).use {
// 'it' is the implicit lambda parameter of type Realm
status += "\nNumber of persons: ${it.where(Person::class.java).count()}"
// Find all persons where age between 7 and 9 and name begins with "Person".
val results = it
.where(Person::class.java)
.between("age", 7, 9) // Notice implicit "and" operation
.beginsWith("name", "Person")
.findAll()
status += "\nSize of result set: ${results.size}"
}
return status
}
}
@@ -0,0 +1,23 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.realm.examples.kotlin.model
import io.realm.RealmObject
open class Cat : RealmObject() {
open var name: String? = null
}
@@ -0,0 +1,23 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.realm.examples.kotlin.model
import io.realm.RealmObject
open class Dog : RealmObject() {
open var name: String? = null
}
@@ -0,0 +1,51 @@
/*
* Copyright 2015 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.realm.examples.kotlin.model
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey
// Your model has to extend RealmObject. Furthermore, the class and all of the
// properties must be annotated with open (Kotlin classes and methods are final
// by default).
open class Person(
// You can put properties in the constructor as long as all of them are initialized with
// default values. This ensures that an empty constructor is generated.
// All properties are by default persisted.
// Properties can be annotated with PrimaryKey or Index.
// If you use non-nullable types, properties must be initialized with non-null values.
@PrimaryKey open var name: String = "",
open var age: Int = 0,
// Other objects in a one-to-one relation must also subclass RealmObject
open var dog: Dog? = null,
// One-to-many relations is simply a RealmList of the objects which also subclass RealmObject
open var cats: RealmList<Cat> = RealmList(),
// You can instruct Realm to ignore a field and not persist it.
@Ignore open var tempReference: Int = 0,
open var id: Long = 0
) : RealmObject() {
// The Kotlin compiler generates standard getters and setters.
// Realm will overload them and code inside them is ignored.
// So if you prefer you can also just have empty abstract methods.
}
@@ -0,0 +1,30 @@
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:keep="@layout/activity_realm_basic_example">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:gravity="center_horizontal"
android:text="@string/status_output"
android:textStyle="bold"
android:textSize="18sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="10sp"
android:orientation="vertical"
tools:context=".RealmIntroExample"/>
</LinearLayout>
</ScrollView>
@@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
@@ -0,0 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Kotlin example</string>
<string name="status_output">Status Output…</string>
</resources>
@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
@@ -0,0 +1,36 @@
buildscript {
repositories {
mavenCentral()
maven {
url 'file://' + pathToKotlinPlugin
}
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
}
}
apply plugin: "java"
apply plugin: "kotlin"
apply plugin: "kotlin-kapt"
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
compile "org.jetbrains.kotlin:annotation-processor-example:0.1-SNAPSHOT"
kapt "org.jetbrains.kotlin:annotation-processor-example:0.1-SNAPSHOT"
}
task show << {
buildscript.configurations.classpath.each { println it }
}
kapt {
generateStubs = true
}
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example
@example.ExampleAnnotation
open class TestClass
class AncestorClass : TestClass()
@@ -0,0 +1,33 @@
buildscript {
repositories {
mavenCentral()
maven {
url 'file://' + pathToKotlinPlugin
}
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
}
}
apply plugin: "java"
apply plugin: "kotlin"
apply plugin: "kotlin-kapt"
repositories {
maven {
url 'file://' + pathToKotlinPlugin
}
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"
compile "org.jetbrains.kotlin:annotation-processor-example:0.1-SNAPSHOT"
kapt "org.jetbrains.kotlin:annotation-processor-example:0.1-SNAPSHOT"
testCompile 'junit:junit:4.12'
}
task show << {
buildscript.configurations.classpath.each { println it }
}
@@ -0,0 +1,5 @@
package foo
internal class InternalDummy {
internal val x = "InternalDummy.x"
}
@@ -0,0 +1,7 @@
package foo
internal class InternalDummyUser {
internal fun use(dummy: InternalDummy) {
if (dummy.x != "InternalDummy.x") throw AssertionError("dummy.x = ${dummy.x}")
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javaPackage;
public class JavaClass {
public void test() {
System.out.println(example.TestClassGenerated.class.getName());
System.out.println(example.SourceAnnotatedTestClassGenerated.class.getName());
System.out.println(example.BinaryAnnotatedTestClassGenerated.class.getName());
System.out.println(example.RuntimeAnnotatedTestClassGenerated.class.getName());
}
}
@@ -0,0 +1,15 @@
package example
@example.ExampleAnnotation
@example.ExampleSourceAnnotation
@example.ExampleBinaryAnnotation
@example.ExampleRuntimeAnnotation
public class TestClass {
@example.ExampleAnnotation
public val testVal: String = "text"
@example.ExampleAnnotation
public fun testFunction(): TestClassGenerated = TestClassGenerated()
}
@@ -0,0 +1,12 @@
package example;
import org.junit.Assert;
import org.junit.Test;
public class JavaTest {
@Test
public void test() {
TestClass testClass = new TestClass();
Assert.assertEquals("text", testClass.getTestVal());
}
}
@@ -0,0 +1,12 @@
package foo
import org.junit.Test
class InternalDummyTest {
@Test
fun testDummy() {
val dummy = InternalDummy()
val dummyUser = InternalDummyUser()
dummyUser.use(dummy)
}
}