Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/DroidKaigi/conference-app-2018

The Official Conference App for DroidKaigi 2018 Tokyo
https://github.com/DroidKaigi/conference-app-2018

android android-app conference droidkaigi kotlin

Last synced: about 1 month ago
JSON representation

The Official Conference App for DroidKaigi 2018 Tokyo

Lists

README

        

# ![](app/src/main/res/mipmap-mdpi/ic_launcher.png) DroidKaigi 2018 official Android app
[![CircleCI](https://circleci.com/gh/DroidKaigi/conference-app-2018.svg?style=svg&circle-token=b8e6a12e76295c24c7be8f57807cf6ab4139288e)](https://circleci.com/gh/DroidKaigi/conference-app-2018)[![Waffle.io - Columns and their card count](https://badge.waffle.io/4004fb95e3835aef9cfea229c8443b4b62eacf957879565e813f405126decfae.svg?columns=all)](https://waffle.io/DroidKaigi/conference-app-2018)

[DroidKaigi 2018](https://droidkaigi.jp/2018/en/) is a conference tailored for developers on 8th and 9th February 2018.

[Try it on your device via DeployGate](https://dply.me/xt08ja#install)

# Features

* View conference schedule and details of each session
* Set notification for upcoming sessions on your preference
* Search sessions and speakers and topics
* Show Information Feed

# Contributing
We are always welcome your contribution!

## How to find the tasks
We use [waffle.io](https://waffle.io/DroidKaigi/conference-app-2018) to manage the tasks.
Please find the issues you'd like to contribute in it.
[welcome contribute](https://github.com/DroidKaigi/conference-app-2018/labels/welcome%20contribute) and [easy](https://github.com/DroidKaigi/conference-app-2018/labels/easy) are good for first contribution.

Of course, it would be great to send PullRequest which has no issue!

## How to contribute
If you find the tasks you want to contribute, please comment in the issue like [this](https://github.com/DroidKaigi/conference-app-2018/issues/73#issuecomment-357410022) to prevent to conflict contribution.
We'll reply as soon as possible, but it's unnecessary to wait our reaction. It's okay to start contribution and send PullRequest!

We've designated these issues as good candidates for easy contribution. You can always fork the repository and send a pull request (on a branch other than `master`).

# Development Environment

## Kotlin
This app is full Kotlin!

## RxJava2 & LiveData
Converting RxJava2's publisher to AAC LiveData with [LiveDataReactiveStreams](https://developer.android.com/reference/android/arch/lifecycle/LiveDataReactiveStreams.html).

> AllSessionsViewModel.kt

```kotlin
repository.sessions
.toResult(schedulerProvider)
.toLiveData()
```

> LiveDataReactiveStreamsExt.kt

```kotlin
fun Publisher.toLiveData() = LiveDataReactiveStreams.fromPublisher(this)
```

## Groupie

By using Groupie you can simplify the implementation around RecyclerView.

```kotlin
data class SpeakerItem(
val speaker: Speaker
) : BindableItem(speaker.id.hashCode().toLong()) {

override fun bind(viewBinding: ItemSpeakerBinding, position: Int) {
viewBinding.speaker = speaker
}

override fun getLayout(): Int = R.layout.item_speaker
}
```

# Architecture
This app uses an Android Architecture Components(AAC) based architecture using AAC(LiveData, ViewModel, Room), Kotlin, RxJava, DataBinding, dependency injection, Firebase.

## Fragment -> ViewModel

Use `LifecycleObserver` for telling lifecycle to ViewModel.

SessionsFragment.kt

```kotlin
class SessionsFragment : Fragment(), Injectable {

private lateinit var sessionsViewModel: SessionsViewModel

...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
lifecycle.addObserver(sessionsViewModel)
...
```

SessionsViewModel.kt

```kotlin
class SessionsViewModel @Inject constructor(
private val repository: SessionRepository,
private val schedulerProvider: SchedulerProvider
) : ViewModel(), LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreate() {
...
}
```

## ViewModel -> Repository

Use RxJava2(RxKotlin) and `ViewModel#onCleared()` for preventing leaking.

SessionsViewModel.kt

```kotlin
private val compositeDisposable: CompositeDisposable = CompositeDisposable()

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreate() {
repository
.refreshSessions()
.subscribeBy(onError = defaultErrorHandler())
.addTo(compositeDisposable)
}

override fun onCleared() {
super.onCleared()
compositeDisposable.clear()
}
```

## Repository -> API, Repository -> DB

Use Retrofit and save to the `Architecture Component Room`.

SessionDataRepository.kt

```kotlin
override fun refreshSessions(): Completable {
return api.getSessions()
.doOnSuccess { response ->
sessionDatabase.save(response)
}
.subscribeOn(schedulerProvider.computation())
.toCompletable()
}
```

## DB -> Repository

Use `Room` with RxJava2 Flowable Support.
And SessionDataRepository holds Flowable property.

SessionDao.kt

```kotlin
@Query("SELECT room_id, room_name FROM session GROUP BY room_id ORDER BY room_id")
abstract fun getAllRoom(): Flowable>
```

SessionDataRepository.kt

```kotlin
class SessionDataRepository @Inject constructor(
private val sessionDatabase: SessionDatabase,
...
) : SessionRepository {

override val rooms: Flowable> =
sessionDatabase.getAllRoom().toRooms()
```

## Repository -> ViewModel

We create LiveData from a ReactiveStreams publisher with [LiveDataReactiveStreams](https://developer.android.com/reference/android/arch/lifecycle/LiveDataReactiveStreams.html)

SessionsViewModel.kt

```kotlin
val rooms: LiveData>> by lazy {
repository.rooms
.toResult(schedulerProvider)
.toLiveData()
}
```

LiveDataReactiveStreamsExt.kt

```kotlin
fun Publisher.toLiveData() = LiveDataReactiveStreams.fromPublisher(this) as LiveData
```

And using `Result` class for error handling with Kotlin extension.

```kotlin
fun Flowable.toResult(schedulerProvider: SchedulerProvider): Flowable> =
compose { item ->
item
.map { Result.success(it) }
.onErrorReturn { e -> Result.failure(e.message ?: "unknown", e) }
.observeOn(schedulerProvider.ui())
.startWith(Result.inProgress())
}
```

```kotlin
sealed class Result(val inProgress: Boolean) {
class InProgress : Result(true)
data class Success(var data: T) : Result(false)
data class Failure(val errorMessage: String?, val e: Throwable) : Result(false)

```

## ViewModel -> Fragment

Fragment observe ViewModel's LiveData.
We can use the result with Kotlin `when` expression.
In `is Result.Success` block, you can access data with `result.data` by Kotlin Smart cast.

SessionsFragment.kt

```kotlin
sessionsViewModel.rooms.observe(this, { result ->
when (result) {
is Result.InProgress -> {
binding.progress.show()
}
is Result.Success -> {
binding.progress.hide()
sessionsViewPagerAdapter.setRooms(result.data)
}
is Result.Failure -> {
Timber.e(result.e)
binding.progress.hide()
}
}
})
```

## Release
The release process is automated by using [gradle-play-publisher](https://github.com/Triple-T/gradle-play-publisher).
When we add `git tag`, CI deploys the release apk to GooglePlay alpha.
To know more details, see [.circleci/config.yml](https://github.com/DroidKaigi/conference-app-2018/blob/master/.circleci/config.yml)

```shell
elif [[ "${CIRCLE_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Deploy to Google Play"
openssl aes-256-cbc -k $PUBLISHER_KEYS_JSON_DECRYPT_PASSWORD -d -in encrypted-publisher-keys.json -out app/publisher-keys.json
./gradlew publishApkRelease
fi
```

## iOS App with Kotlin/Native and Kotlin Multiplatform Projects
Some contributors are challenging to develop iOS app with [Kotlin/Native](https://kotlinlang.org/docs/reference/native-overview.html) and [Kotlin Multiplatform Projects](https://kotlinlang.org/docs/reference/multiplatform.html).
We are watching this project.
[DroidKaigi2018iOS](https://github.com/kikuchy/DroidKaigi2018iOS)

## DroidKaigi 2018 Flutter App
The unofficial conference app for DroidKaigi 2018 Tokyo
https://github.com/konifar/droidkaigi2018-flutter

## Thanks
Thank you for contributing!

* Contributors
* [GitHub : Contributors](https://github.com/DroidKaigi/conference-app-2018/graphs/contributors)
* Designer
* [okapi / Yuki Okamoto](https://www.instagram.com/okamoto.yuki/)
* [DroidKaigi 2018 Zeplin Scene](https://scene.zeplin.io/project/5a327a64f0b20176887c556c)

## Credit
This project uses some modern Android libraries and source codes.

* Android Architecture Components
* [Lifecycles](https://developer.android.com/topic/libraries/architecture/lifecycle.html)
* [LiveData](https://developer.android.com/topic/libraries/architecture/livedata.html)
* [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel.html)
* [Room](https://developer.android.com/topic/libraries/architecture/room.html)
* [ReactiveStreams](https://developer.android.com/reference/android/arch/lifecycle/LiveDataReactiveStreams.html)
* Android Support Libraries
* Support v4
* AppCompat v7
* Design
* VectorDrawable
* CardView
* ConstraintLayout
* RecyclerView
* AOSP Codes
* Firebase
* [Cloud Firestore](https://firebase.google.com/docs/firestore/)
* [Auth](https://firebase.google.com/docs/auth/)
* [KTX](https://github.com/android/android-ktx/), [Dagger2](https://google.github.io/dagger/), Dagger Android Support, [Glide4](https://bumptech.github.io/glide/) - Google
* [Kotlin](http://kotlinlang.org/) - JetBrains
* [Retrofit2](http://square.github.io/retrofit/), [Moshi](https://github.com/square/moshi/) - Square
* [RxJava2](https://github.com/ReactiveX/RxJava), [RxKotlin](https://github.com/ReactiveX/RxKotlin), RxAndroid - ReactiveX
* [OkHttp3](http://square.github.io/okhttp/)
* [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP), [Timber](https://github.com/JakeWharton/timber) - JakeWharton
* [Groupie](https://github.com/lisawray/groupie) - lisawray
* [Stetho](http://facebook.github.io/stetho/) - Facebook
* [Kotshi](https://github.com/ansman/kotshi) - ansman
* [DownloadableCalligraphy](https://github.com/takahirom/DownloadableCalligraphy) - takahirom
* [Kotpref](https://github.com/chibatching/Kotpref) - chibatching
* [RxBroadcast](https://github.com/cantrowitz/RxBroadcast) - cantrowitz
* [ProgressTimeLatch](https://github.com/chrisbanes/tivi/blob/96e7cae7560ffd358b8c58c47267ed1024df53f6/app/src/main/java/me/banes/chris/tivi/ui/ProgressTimeLatch.kt) - chrisbanes
* [Google I/O 2017](https://github.com/google/iosched)
* [DebouncingOnClickListener](https://github.com/JakeWharton/butterknife/blob/e78507711fe8a7c637ee61c44a7b09f1be8ff9f6/butterknife/src/main/java/butterknife/internal/DebouncingOnClickListener.java) - JakeWharton

## License

Copyright 2018 DroidKaigi

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.