Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Build and test

on: [push, pull_request]

jobs:
test:
name: Build and test
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Debug build
run: ./gradlew assembleDebug --stacktrace
- name: Unit test
run: ./gradlew testDebugUnitTest --stacktrace
34 changes: 34 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Publish

on:
push:
tags:
- "*-RELEASE"

jobs:
publish:
name: Release build and publish
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Create secrets file
env:
GPG_KEY_CONTENTS: ${{ secrets.GPG_KEY_CONTENTS }}
SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }}
run: sudo bash -c "echo '$GPG_KEY_CONTENTS' | base64 -d > '$SIGNING_SECRET_KEY_RING_FILE'"
- name: Release build and source jar generation
run: ./gradlew :krate:assembleRelease :krate-gson:assembleRelease :krate-moshi-stub:assembleRelease :krate-moshi-core:assembleRelease :krate-moshi-reflect:assembleRelease :krate-moshi-codegen:assembleRelease :krate:androidSourcesJar :krate-gson:androidSourcesJar :krate-moshi-stub:androidSourcesJar :krate-moshi-core:androidSourcesJar :krate-moshi-reflect:androidSourcesJar :krate-moshi-codegen:androidSourcesJar
- name: Publish to MavenCentral
run: ./gradlew publishReleasePublicationToSonatypeRepository closeAndReleaseRepository
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }}
SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }}
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,25 @@ class MainActivity : AppCompatActivity(), Krate {
}
```

### Third party implementations

You can create the `SharedPreferences` instance to implement Krate's interface by using third party `SharedPreferences` implementations as well. For example, [EncryptedSharedPreferences](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences) or [Harmony](https://github.com/pablobaxter/Harmony) are such implementations.

Here's how you'd use EncryptedSharedPreferences with Krate ([see this source file for the full code](hu/autsoft/krateexample/krates/ExampleThirdPartyKrates.kt)):

```kotlin
class EncryptedKrate(applicationContext: Context) : Krate {
override val sharedPreferences: SharedPreferences

init {
/* ... */
sharedPreferences = EncryptedSharedPreferences.create(applicationContext, ...)
}

val myStringValue: String by stringPref("my_string_value", "")
}
```

# Validation

You can add validation rules to your Krate properties by providing an additional lambda parameter, `isValid`:
Expand Down
12 changes: 8 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ android {
compileSdkVersion compile_sdk
defaultConfig {
applicationId "hu.autsoft.krateexample"
minSdkVersion min_sdk
minSdkVersion 21
targetSdkVersion target_sdk
versionCode 1
versionName "1.0"
Expand All @@ -21,9 +21,13 @@ android {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'

// Third-party SharedPreferences implementations
implementation "androidx.security:security-crypto:1.1.0-alpha02"
implementation 'com.frybits.harmony:harmony:1.1.2'

implementation project(path: ':krate')
implementation project(path: ':krate-gson')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package hu.autsoft.krateexample.krates

import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import com.frybits.harmony.getHarmonySharedPreferences
import hu.autsoft.krate.Krate
import hu.autsoft.krate.stringPref

/**
* Encrypted Krate based on the AndroidX EncryptedSharedPreferences class.
*/
class EncryptedKrate(applicationContext: Context) : Krate {
override val sharedPreferences: SharedPreferences

init {
// Check the official docs on how to create EncryptedPreferences instances
// https://developer.android.com/topic/security/data
// https://developer.android.com/reference/kotlin/androidx/security/crypto/EncryptedSharedPreferences
val masterKeyAlias = MasterKey.Builder(applicationContext)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val sharedPrefsFile = "my_sensitive_data.txt"

sharedPreferences = EncryptedSharedPreferences.create(
applicationContext,
sharedPrefsFile,
masterKeyAlias,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}

val myStringValue: String by stringPref("my_string_value", "")
}

/**
* Harmony is a multi-process SharedPreferences implementation.
* See its GitHub page for details https://github.com/pablobaxter/Harmony
*/
class HarmonyKrate(context: Context) : Krate {
override val sharedPreferences: SharedPreferences = context.getHarmonySharedPreferences("PREF_NAME")

val myStringValue: String by stringPref("my_string_value", "")
}
7 changes: 4 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
buildscript {
ext.kotlin_version = '1.3.61'
ext.kotlin_version = '1.4.10'
ext.krate_version = '0.4.0'

ext.moshi_version = '1.9.2'
ext.moshi_version = '1.9.3'
ext.junit_version = '4.13'

ext.min_sdk = 15
ext.compile_sdk = 29
Expand All @@ -15,7 +16,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.21.0"
}
Expand Down
3 changes: 1 addition & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#Sun Feb 09 16:52:49 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
12 changes: 11 additions & 1 deletion krate-gson/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@ android {
}
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += [
'-progressive',
'-Xexplicit-api=strict',
'-Xopt-in=kotlin.RequiresOptIn',
]
}
}

dependencies {
implementation project(':krate')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
api 'com.google.code.gson:gson:2.8.5'

testImplementation 'junit:junit:4.12'
testImplementation "junit:junit:$junit_version"
testImplementation 'org.robolectric:robolectric:4.3.1'
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@file:Suppress("RedundantVisibilityModifier", "unused")
@file:Suppress("unused")

package hu.autsoft.krate.gson

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal inline val Krate.internalGson: Gson
*
* Set to null to use the default instance.
*/
var Krate.gson: Gson?
public var Krate.gson: Gson?
set(value) {
if (value != null) {
gsonInstances[this] = value
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
@file:Suppress("RedundantVisibilityModifier", "unused")
@file:[Suppress("unused") OptIn(InternalKrateApi::class)]

package hu.autsoft.krate.gson

import com.google.gson.reflect.TypeToken
import hu.autsoft.krate.Krate
import hu.autsoft.krate.gson.default.GsonDelegateWithDefault
import hu.autsoft.krate.gson.optional.GsonDelegate
import hu.autsoft.krate.internal.InternalKrateApi
import hu.autsoft.krate.validated.ValidatedPreferenceDelegate
import java.lang.reflect.Type
import kotlin.properties.ReadWriteProperty
Expand Down
2 changes: 1 addition & 1 deletion krate-gson/src/test/java/hu/autsoft/krate/Util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package hu.autsoft.krate
import android.content.Context
import androidx.test.platform.app.InstrumentationRegistry

val targetContext: Context
internal val targetContext: Context
get() = InstrumentationRegistry.getInstrumentation().targetContext
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.content.Context
import hu.autsoft.krate.SimpleKrate


class GsonTestKrate(context: Context) : SimpleKrate(context) {
internal class GsonTestKrate(context: Context) : SimpleKrate(context) {

init {
sharedPreferences.edit().clear().commit()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package hu.autsoft.krate.gson

data class TestModel(val x: Int, val y: Double, val z: String)
internal data class TestModel(val x: Int, val y: Double, val z: String)
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class CustomGsonInstanceTest {
internal class CustomGsonInstanceTest {

private lateinit var krate: Krate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class GsonDelegateTest {
internal class GsonDelegateTest {

private lateinit var krate: GsonTestKrate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class GsonDelegateWithDefaultTest {
internal class GsonDelegateWithDefaultTest {

private lateinit var krate: GsonTestKrate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class ValidatedGsonDelegateTest {
internal class ValidatedGsonDelegateTest {

private lateinit var krate: GsonTestKrate

Expand Down
11 changes: 10 additions & 1 deletion krate-moshi-codegen/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ android {
}
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += [
'-progressive',
'-Xexplicit-api=strict',
]
}
}

dependencies {
implementation project(':krate')
api project(':krate-moshi-core')
Expand All @@ -25,7 +34,7 @@ dependencies {
api "com.squareup.moshi:moshi:$moshi_version"
kaptTest "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"

testImplementation 'junit:junit:4.12'
testImplementation "junit:junit:$junit_version"
testImplementation 'org.robolectric:robolectric:4.3.1'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.content.Context
import hu.autsoft.krate.SimpleKrate


class MoshiTestKrate(context: Context) : SimpleKrate(context) {
internal class MoshiTestKrate(context: Context) : SimpleKrate(context) {

init {
sharedPreferences.edit().clear().commit()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package hu.autsoft.krate.moshi
import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class TestModel(val x: Int, val y: Double, val z: String)
internal data class TestModel(val x: Int, val y: Double, val z: String)
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class CustomMoshiInstanceTest {
internal class CustomMoshiInstanceTest {

private lateinit var krate: Krate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class MoshiDelegateTest {
internal class MoshiDelegateTest {

private lateinit var krate: MoshiTestKrate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class MoshiDelegateWithDefaultTest {
internal class MoshiDelegateWithDefaultTest {

private lateinit var krate: MoshiTestKrate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class ValidatedGsonDelegateTest {
internal class ValidatedGsonDelegateTest {

private lateinit var krate: MoshiTestKrate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package hu.autsoft.krate.moshi.util
import android.content.Context
import androidx.test.platform.app.InstrumentationRegistry

val targetContext: Context
internal val targetContext: Context
get() = InstrumentationRegistry.getInstrumentation().targetContext
10 changes: 10 additions & 0 deletions krate-moshi-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ android {
}
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += [
'-progressive',
'-Xexplicit-api=strict',
'-Xopt-in=kotlin.RequiresOptIn',
]
}
}

dependencies {
implementation project(':krate')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
Expand Down
Loading