EventsFlow
This commit is contained in:
parent
464ef4e697
commit
20d5350a60
7 changed files with 92 additions and 8 deletions
|
@ -22,7 +22,7 @@ android {
|
|||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example.recyclersample"
|
||||
applicationId "io.heckel.ntfy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 1
|
||||
|
@ -45,7 +45,6 @@ android {
|
|||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -54,6 +53,7 @@ dependencies {
|
|||
implementation "androidx.core:core-ktx:$rootProject.coreKtxVersion"
|
||||
implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
|
||||
implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"
|
||||
implementation 'com.google.code.gson:gson:2.8.8'
|
||||
|
||||
// RecyclerView
|
||||
implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerViewVersion"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.heckel.ntfy">
|
||||
package="io.heckel.ntfy">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import android.widget.Button
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.heckel.ntfy.R
|
||||
import io.heckel.ntfy.R
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
const val TOPIC_URL = "url"
|
||||
|
|
64
app/src/main/java/io/heckel/ntfy/data/NtfyApi.kt
Normal file
64
app/src/main/java/io/heckel/ntfy/data/NtfyApi.kt
Normal file
|
@ -0,0 +1,64 @@
|
|||
package io.heckel.ntfy.data
|
||||
|
||||
import android.content.Context
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import java.io.IOException
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
class NtfyApi(context: Context) {
|
||||
private val gson = GsonBuilder().create()
|
||||
|
||||
private suspend fun getStreamConnection(url: String): HttpURLConnection =
|
||||
withContext(Dispatchers.IO) {
|
||||
return@withContext (URL(url).openConnection() as HttpURLConnection).also {
|
||||
it.setRequestProperty("Accept", "text/event-stream")
|
||||
it.doInput = true
|
||||
}
|
||||
}
|
||||
|
||||
data class Event(val name: String = "", val data: JsonObject = JsonObject())
|
||||
|
||||
fun getEventsFlow(): Flow<Event> = flow {
|
||||
coroutineScope {
|
||||
val conn = getStreamConnection("https://ntfy.sh/_phil")
|
||||
val input = conn.inputStream.bufferedReader()
|
||||
try {
|
||||
conn.connect()
|
||||
var event = Event()
|
||||
while (isActive) {
|
||||
val line = input.readLine()
|
||||
println("PHIL: " + line)
|
||||
when {
|
||||
line.startsWith("event:") -> {
|
||||
event = event.copy(name = line.substring(6).trim())
|
||||
}
|
||||
line.startsWith("data:") -> {
|
||||
val data = line.substring(5).trim()
|
||||
try {
|
||||
event = event.copy(data = gson.fromJson(data, JsonObject::class.java))
|
||||
} catch (e: JsonSyntaxException) {
|
||||
// Nothing
|
||||
}
|
||||
}
|
||||
line.isEmpty() -> {
|
||||
emit(event)
|
||||
event = Event()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
println("PHIL: " + e.message)
|
||||
this.cancel(CancellationException("Network Problem", e))
|
||||
} finally {
|
||||
conn.disconnect()
|
||||
input.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ import android.widget.Button
|
|||
import android.widget.TextView
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.heckel.ntfy.R
|
||||
import io.heckel.ntfy.R
|
||||
import io.heckel.ntfy.list.TOPIC_ID
|
||||
|
||||
class TopicDetailActivity : AppCompatActivity() {
|
||||
|
|
|
@ -19,12 +19,11 @@ package io.heckel.ntfy.list
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.heckel.ntfy.R
|
||||
import io.heckel.ntfy.R
|
||||
import io.heckel.ntfy.data.Topic
|
||||
|
||||
class TopicsAdapter(private val onClick: (Topic) -> Unit) :
|
||||
|
|
|
@ -22,16 +22,24 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.heckel.ntfy.R
|
||||
import io.heckel.ntfy.R
|
||||
import io.heckel.ntfy.add.AddTopicActivity
|
||||
import io.heckel.ntfy.add.TOPIC_URL
|
||||
import io.heckel.ntfy.data.NtfyApi
|
||||
import io.heckel.ntfy.data.Topic
|
||||
import io.heckel.ntfy.detail.TopicDetailActivity
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
const val TOPIC_ID = "topic id"
|
||||
|
||||
class TopicsListActivity : AppCompatActivity() {
|
||||
private val api = NtfyApi(this)
|
||||
private val newTopicActivityRequestCode = 1
|
||||
private val topicsListViewModel by viewModels<TopicsListViewModel> {
|
||||
TopicsListViewModelFactory(this)
|
||||
|
@ -55,6 +63,19 @@ class TopicsListActivity : AppCompatActivity() {
|
|||
fab.setOnClickListener {
|
||||
fabOnClick()
|
||||
}
|
||||
|
||||
val self = this
|
||||
api.getEventsFlow().asLiveData(Dispatchers.IO).observe(this, Observer { event ->
|
||||
// Get the Activity's lifecycleScope and launch
|
||||
this.lifecycleScope.launch(Dispatchers.Main) {
|
||||
// run the code again in IO context
|
||||
withContext(Dispatchers.IO) {
|
||||
println(event.data)
|
||||
//Toast.makeText(self, event.data, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/* Opens TopicDetailActivity when RecyclerView item is clicked. */
|
||||
|
|
Loading…
Reference in a new issue