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
7 changes: 4 additions & 3 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: 1.8
distribution: adopt
java-version: 11
- name: Debug build
run: ./gradlew assembleDebug --stacktrace
- name: Unit test
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
name: Publish

on:
push:
tags:
- "*-RELEASE"
release:
types: [ released ]

jobs:
publish:
Expand All @@ -12,10 +11,11 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: 1.8
distribution: adopt
java-version: 11
- name: Release build and source jar generation
run: ./gradlew assembleRelease androidSourcesJar -x :app:assembleRelease
- name: Publish to MavenCentral
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Log.d("LOGIN_COUNT", "Count: ${settings.loginCount}")
You can include _Krate_ in your project from the `mavenCentral()` repository, like so:

```groovy
implementation 'hu.autsoft:krate:1.1.0'
implementation 'hu.autsoft:krate:1.2.0'
```

# Optionals vs defaults
Expand Down Expand Up @@ -152,7 +152,7 @@ class CustomMoshiKrate(context: Context) : SimpleKrate(context) {
If you only want to use Moshi adapters that you generate via Moshi's [codegen facilities](https://github.com/square/moshi#codegen), you can use the following Krate artifact in your project to make use of these adapters:

```groovy
implementation 'hu.autsoft:krate-moshi-codegen:1.1.0'
implementation 'hu.autsoft:krate-moshi-codegen:1.2.0'
```

This will give you a default `Moshi` instance created by a call to `Moshi.Builder().build()`. This instance will find and use any of the adapters generated by Moshi's codegen automatically.
Expand All @@ -162,7 +162,7 @@ This will give you a default `Moshi` instance created by a call to `Moshi.Builde
If you rely on [reflection](https://github.com/square/moshi#reflection) for your Moshi serialization, and therefore need a `KotlinJsonAdapterFactory` included in your `Moshi` instance, use the following Krate Moshi dependency:

```groovy
implementation 'hu.autsoft:krate-moshi-reflect:1.1.0'
implementation 'hu.autsoft:krate-moshi-reflect:1.2.0'
```

The default `Moshi` instance from this dependency will include the aforementioned factory, and be able to serialize any Kotlin class. Note that this approach relies on the `kotlin-reflect` library, which is a large dependency.
Expand All @@ -174,7 +174,7 @@ You may choose to use Moshi's codegen for some classes in your project, and seri
The `krate-kotlinx` artifact provides a `kotlinxPref` delegate which can store any arbitrary type, as long as Kotlinx.serializazion can serialize and deserialize it. This addon, like the base library, is available from `mavenCentral()`:

```groovy
implementation 'hu.autsoft:krate-kotlinx:1.1.0'
implementation 'hu.autsoft:krate-kotlinx:1.2.0'
```

Its usage is the same as with any of the base library's delegates:
Expand Down Expand Up @@ -206,7 +206,7 @@ class CustomKotlinxKrate(context: Context) : SimpleKrate(context) {
The `krate-gson` artifact provides a `gsonPref` delegate which can store any arbitrary type, as long as Gson can serialize and deserialize it. This addon, like the base library, is available from `mavenCentral()`:

```groovy
implementation 'hu.autsoft:krate-gson:1.1.0'
implementation 'hu.autsoft:krate-gson:1.2.0'
```

Its basic usage is the same as with any of the base library's delegates:
Expand Down
13 changes: 7 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion compile_sdk
Expand All @@ -17,16 +16,18 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
viewBinding true
}
}

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

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

implementation project(path: ':krate')
Expand Down
6 changes: 4 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
package="hu.autsoft.krateexample">

<application
android:allowBackup="true"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
33 changes: 19 additions & 14 deletions app/src/main/java/hu/autsoft/krateexample/ExampleActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package hu.autsoft.krateexample

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import hu.autsoft.krateexample.databinding.ActivityExampleBinding
import hu.autsoft.krateexample.krates.ExampleCustomKrate
import hu.autsoft.krateexample.krates.ExampleSettings
import hu.autsoft.krateexample.krates.ExampleSimpleKrate
import kotlinx.android.synthetic.main.activity_example.*

class ExampleActivity : AppCompatActivity() {

Expand All @@ -17,9 +17,13 @@ class ExampleActivity : AppCompatActivity() {

lateinit var exampleSettings: ExampleSettings

private lateinit var binding: ActivityExampleBinding

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

binding = ActivityExampleBinding.inflate(layoutInflater)
setContentView(binding.root)

when (intent.getStringExtra(KEY_KRATE_TYPE)) {
TYPE_SIMPLE -> {
Expand All @@ -37,23 +41,24 @@ class ExampleActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()

booleanPreference.isChecked = exampleSettings.exampleBoolean
floatPreferenceInput.setText(exampleSettings.exampleFloat.toString())
intPreferenceInput.setText(exampleSettings.exampleInt.toString())
longPreferenceInput.setText(exampleSettings.exampleLong.toString())
stringPreferenceInput.setText(exampleSettings.exampleString)
stringSetPreferenceInput.setText(exampleSettings.exampleStringSet.joinToString(separator = ", "))
binding.booleanPreference.isChecked = exampleSettings.exampleBoolean
binding.floatPreferenceInput.setText(exampleSettings.exampleFloat.toString())
binding.intPreferenceInput.setText(exampleSettings.exampleInt.toString())
binding.longPreferenceInput.setText(exampleSettings.exampleLong.toString())
binding.stringPreferenceInput.setText(exampleSettings.exampleString)
binding.stringSetPreferenceInput.setText(exampleSettings.exampleStringSet.joinToString(separator = ", "))
}

override fun onPause() {
super.onPause()

exampleSettings.exampleBoolean = booleanPreference.isChecked
exampleSettings.exampleFloat = floatPreferenceInput.text.toString().toFloat()
exampleSettings.exampleInt = intPreferenceInput.text.toString().toInt()
exampleSettings.exampleLong = longPreferenceInput.text.toString().toLong()
exampleSettings.exampleString = stringPreferenceInput.text.toString()
exampleSettings.exampleStringSet = stringSetPreferenceInput.text.toString().split(",").map(String::trim).toSet()
exampleSettings.exampleBoolean = binding.booleanPreference.isChecked
exampleSettings.exampleFloat = binding.floatPreferenceInput.text.toString().toFloat()
exampleSettings.exampleInt = binding.intPreferenceInput.text.toString().toInt()
exampleSettings.exampleLong = binding.longPreferenceInput.text.toString().toLong()
exampleSettings.exampleString = binding.stringPreferenceInput.text.toString()
exampleSettings.exampleStringSet =
binding.stringSetPreferenceInput.text.toString().split(",").map(String::trim).toSet()
}

}
16 changes: 10 additions & 6 deletions app/src/main/java/hu/autsoft/krateexample/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ package hu.autsoft.krateexample
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import hu.autsoft.krateexample.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

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

btnSimpleKrate.setOnClickListener {
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

binding.btnSimpleKrate.setOnClickListener {
val intent = Intent(this, ExampleActivity::class.java)
.putExtra(ExampleActivity.KEY_KRATE_TYPE, ExampleActivity.TYPE_SIMPLE)
.putExtra(ExampleActivity.KEY_KRATE_TYPE, ExampleActivity.TYPE_SIMPLE)
startActivity(intent)
}
btnCustomKrate.setOnClickListener {
binding.btnCustomKrate.setOnClickListener {
val intent = Intent(this, ExampleActivity::class.java)
.putExtra(ExampleActivity.KEY_KRATE_TYPE, ExampleActivity.TYPE_CUSTOM)
.putExtra(ExampleActivity.KEY_KRATE_TYPE, ExampleActivity.TYPE_CUSTOM)
startActivity(intent)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ class EncryptedKrate(applicationContext: Context) : Krate {
// 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()
.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
applicationContext,
sharedPrefsFile,
masterKeyAlias,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}

Expand Down
12 changes: 6 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
buildscript {
ext.kotlin_version = '1.5.20'
ext.krate_version = '1.1.0'
ext.kotlin_version = '1.5.31'
ext.krate_version = '1.2.0'

ext.moshi_version = '1.12.0'
ext.junit_version = '4.13.2'
ext.robolectric_version = '4.5.1'
ext.robolectric_version = '4.6.1'

ext.min_sdk = 15
ext.compile_sdk = 29
ext.target_sdk = 29
ext.compile_sdk = 31
ext.target_sdk = 31

repositories {
google()
Expand All @@ -17,7 +17,7 @@ buildscript {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.2'
classpath 'com.android.tools.build:gradle:7.0.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "io.github.gradle-nexus:publish-plugin:1.1.0"
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 1 addition & 6 deletions krate-gson/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

buildFeatures {
buildConfig false
}
Expand All @@ -32,8 +28,7 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {

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

testImplementation "junit:junit:$junit_version"
testImplementation "org.robolectric:robolectric:$robolectric_version"
Expand Down
29 changes: 21 additions & 8 deletions krate-gson/src/main/kotlin/hu/autsoft/krate/gson/Functions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,46 @@ 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.gson.default.GsonDelegateWithDefaultFactory
import hu.autsoft.krate.gson.optional.GsonDelegateFactory
import java.lang.reflect.Type
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadWriteProperty

/**
* Creates an optional preference of type T with the given [key] in this [Krate] instance.
* This instance will be serialized using Gson.
*/
public inline fun <reified T : Any> Krate.gsonPref(key: String): ReadWriteProperty<Krate, T?> {
public inline fun <reified T : Any> Krate.gsonPref(
key: String,
): PropertyDelegateProvider<Krate, ReadWriteProperty<Krate, T?>> {
return gsonPrefImpl(key, object : TypeToken<T>() {}.type)
}

@PublishedApi
internal fun <T : Any> Krate.gsonPrefImpl(key: String, type: Type): ReadWriteProperty<Krate, T?> {
return GsonDelegate(key, type)
internal fun <T : Any> Krate.gsonPrefImpl(
key: String,
type: Type,
): PropertyDelegateProvider<Krate, ReadWriteProperty<Krate, T?>> {
return GsonDelegateFactory(key, type)
}

/**
* Creates a non-optional preference of type T with the given [key] and [defaultValue] in this [Krate] instance.
* This instance will be serialized using Gson.
*/
public inline fun <reified T : Any> Krate.gsonPref(key: String, defaultValue: T): ReadWriteProperty<Krate, T> {
public inline fun <reified T : Any> Krate.gsonPref(
key: String,
defaultValue: T,
): PropertyDelegateProvider<Krate, ReadWriteProperty<Krate, T>> {
return gsonPrefImpl(key, defaultValue, object : TypeToken<T>() {}.type)
}

@PublishedApi
internal fun <T : Any> Krate.gsonPrefImpl(key: String, defaultValue: T, type: Type): ReadWriteProperty<Krate, T> {
return GsonDelegateWithDefault(key, defaultValue, type)
internal fun <T : Any> Krate.gsonPrefImpl(
key: String,
defaultValue: T,
type: Type,
): PropertyDelegateProvider<Krate, ReadWriteProperty<Krate, T>> {
return GsonDelegateWithDefaultFactory(key, defaultValue, type)
}
Loading