Skip to content

Commit

Permalink
Support lifecycle service
Browse files Browse the repository at this point in the history
  • Loading branch information
zhxnlai committed Jan 18, 2019
1 parent c1d05d8 commit 70a30d2
Show file tree
Hide file tree
Showing 11 changed files with 328 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ While we are working on Bintray support, Scarlet is available via [JitPack][jitp
<dependency>
<groupId>com.github.tinder.scarlet</groupId>
<artifactId>scarlet</artifactId>
<version>0.2.2-alpha4</version>
<version>0.2.3-alpha1</version>
</dependency>
```

Expand All @@ -98,7 +98,7 @@ repositories {
maven { url "https://jitpack.io" }
}
implementation 'com.github.tinder.scarlet:scarlet:$0.2.2-alpha4'
implementation 'com.github.tinder.scarlet:scarlet:$0.2.3-alpha1'
```

### Plug-in Roadmap
Expand Down
1 change: 1 addition & 0 deletions demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ dependencies {
implementation rootProject.ext.multiDex
implementation rootProject.ext.constraintLayout
implementation rootProject.ext.liveDateReactiveSterams
implementation rootProject.ext.lifecycleExtensions
implementation rootProject.ext.rxBinding
implementation rootProject.ext.rxJava
implementation rootProject.ext.rxAndroid
Expand Down
12 changes: 9 additions & 3 deletions demo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<uses-permission android:name="android.permission.STORAGE"/>

<application
android:name="com.tinder.app.root.ScarletDemoApplication"
android:name=".app.root.ScarletDemoApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand All @@ -20,14 +20,20 @@
android:theme="@style/AppTheme">

<activity
android:name="com.tinder.app.root.view.DemoActivity"
android:name=".app.root.view.DemoActivity"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

<service
android:name=".service.ChatRoomSocketIoService"
android:enabled="true"
android:exported="false">
</service>
</application>

</manifest>
</manifest>
8 changes: 5 additions & 3 deletions demo/src/main/java/com/tinder/app/root/view/DemoActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@
package com.tinder.app.root.view

import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.viewpager.widget.ViewPager
import com.google.android.material.tabs.TabLayout
import com.tinder.R
import com.tinder.app.socketio.chatroom.view.ChatRoomFragment
import com.tinder.app.socketio.chatroomservice.view.ChatRoomServiceFragment
import com.tinder.app.sse.stockprice.view.StockPriceFragment
import com.tinder.app.websocket.echo.view.EchoBotFragment
import com.tinder.app.websocket.gdax.view.GdaxFragment
import com.tinder.app.sse.stockprice.view.StockPriceFragment

class DemoActivity : AppCompatActivity() {

Expand Down Expand Up @@ -57,7 +58,8 @@ class DemoActivity : AppCompatActivity() {
"WS - Echo Bot" to { EchoBotFragment() },
"WS - GDAX" to { GdaxFragment() },
"SSE - Stock Price" to { StockPriceFragment() },
"SocketIo - Chat Room" to { ChatRoomFragment() }
"SocketIo - Chat Room" to { ChatRoomFragment() },
"SocketIo - Chat Room Service" to { ChatRoomServiceFragment() }
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* © 2019 Match Group, LLC.
*/

package com.tinder.app.socketio.chatroomservice.view

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.Messenger
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.tinder.R
import com.tinder.service.ChatRoomSocketIoService
import timber.log.Timber

class ChatRoomServiceFragment : Fragment() {

private var messenger: Messenger? = null
private var isBound = false

private val serviceConnection = object : ServiceConnection {

override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
messenger = Messenger(service)
isBound = true

Timber.d("chat onServiceConnected")
}

override fun onServiceDisconnected(name: ComponentName?) {
messenger = null
isBound = false

Timber.d("chat onServiceDisconnected")
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_chatroom_service, container, false) as View
return view
}

override fun onStart() {
super.onStart()
bindService()
}

override fun onDestroy() {
super.onDestroy()
unbindService()
}

private fun bindService() {
val intent = Intent(activity, ChatRoomSocketIoService::class.java)
activity?.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}

private fun unbindService() {
activity?.unbindService(serviceConnection)
isBound = false
}
}
160 changes: 160 additions & 0 deletions demo/src/main/java/com/tinder/service/ChatRoomSocketIoService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* © 2018 Match Group, LLC.
*/

package com.tinder.service

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Intent
import android.os.Handler
import android.os.IBinder
import android.os.Messenger
import androidx.lifecycle.LifecycleService
import com.tinder.R
import com.tinder.app.socketio.chatroom.api.AddUserTopic
import com.tinder.app.socketio.chatroom.api.ChatRoomService
import com.tinder.app.socketio.chatroom.api.NewMessageTopic
import com.tinder.app.socketio.chatroom.api.TypingStartedTopic
import com.tinder.app.socketio.chatroom.api.TypingStoppedTopic
import com.tinder.app.socketio.chatroom.api.UserJoinedTopic
import com.tinder.app.socketio.chatroom.api.UserLeftTopic
import com.tinder.scarlet.Scarlet
import com.tinder.scarlet.lifecycle.android.AndroidLifecycle
import com.tinder.scarlet.messageadapter.moshi.MoshiMessageAdapter
import com.tinder.scarlet.socketio.SocketIoEvent
import com.tinder.scarlet.socketio.client.SocketIoClient
import com.tinder.scarlet.socketio.client.SocketIoEventName
import com.tinder.scarlet.streamadapter.rxjava2.RxJava2StreamAdapterFactory
import io.reactivex.Flowable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber

class ChatRoomSocketIoService : LifecycleService() {

var incomingMessageCount = 0
private val messenger = Messenger(IncomingHandler())

override fun onCreate() {
super.onCreate()

val config = Scarlet.Configuration(
lifecycle = AndroidLifecycle.ofLifecycleServiceForeground(application, this),
messageAdapterFactories = listOf(MoshiMessageAdapter.Factory()),
streamAdapterFactories = listOf(RxJava2StreamAdapterFactory())
)
val serverUrl = "https://socket-io-chat.now.sh/"

val scarlet = Scarlet(
SocketIoClient({ serverUrl }),
config
)

val chatRoomService = scarlet.create<ChatRoomService>()
val addUserTopic = scarlet
.child(SocketIoEventName("add user"), config)
.create<AddUserTopic>()
val newMessageTopic = scarlet
.child(SocketIoEventName("new message"), config)
.create<NewMessageTopic>()
val typingStartedTopic = scarlet
.child(SocketIoEventName("typing"), config)
.create<TypingStartedTopic>()
val typingStoppedTopic = scarlet
.child(SocketIoEventName("stop typing"), config)
.create<TypingStoppedTopic>()
val userJoinedTopic = scarlet
.child(SocketIoEventName("user joined"), config)
.create<UserJoinedTopic>()
val userLeftTopic = scarlet
.child(SocketIoEventName("user left"), config)
.create<UserLeftTopic>()

val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager

val notificationChannel =
NotificationChannel(channelId, "Default", NotificationManager.IMPORTANCE_HIGH)
notificationManager.createNotificationChannel(notificationChannel)

Timber.d("chatroom scarlet created")

chatRoomService.observeStateTransition()
.subscribe {
Timber.d("chatroom service: $it")

val notification = createNotification {
setContentText("State Transition ${it.toState}")
}
notificationManager.notify(notificationIdCurrentState, notification)
}

val username = "scarlet service"

addUserTopic.observeSocketIoEvent()
.filter { it is SocketIoEvent.OnConnectionOpened }
.observeOn(Schedulers.io())
.subscribe({
addUserTopic.sendAddUser(username)

Timber.d("chatroom added user: $it")
val notification = createNotification {
setContentText("Joined chatroom")
}
notificationManager.notify(notificationIdCurrentState, notification)
}, { e ->
Timber.e(e)
})

Flowable.fromPublisher(AndroidLifecycle.ofLifecycleServiceForeground(application, this))
.subscribe({
Timber.d("chatroom lifecycle: $it")

val notification = createNotification {
setContentText("Lifecycle State: $it")
}
notificationManager.notify(notificationIdCurrentState, notification)
})

Flowable.merge(
newMessageTopic.observeNewMessage().map { "${it.username}: ${it.message}" },
typingStartedTopic.observeTypingStarted().map { "${it.username} started typing" },
typingStoppedTopic.observeTypingStopped().map { "${it.username} stopped typing" }
).subscribe {
Timber.d("chatroom new message: $it")

val notification = createNotification {
setContentText("$it")
}

val notificationId = notificationIdIncomingMessage + incomingMessageCount
incomingMessageCount += 1
notificationManager.notify(notificationId, notification)
}
}

override fun onBind(intent: Intent?): IBinder? {
super.onBind(intent)
Timber.d("chatroom onbind")
return messenger.binder
}

private fun createNotification(builder: Notification.Builder.() -> Unit): Notification {
return Notification.Builder(applicationContext, channelId)
.setSmallIcon(R.drawable.ic_action_info)
.setWhen(System.currentTimeMillis())
.setContentTitle("Chat Room")
.setAutoCancel(true)
.setOngoing(true)
.apply(builder)
.build()
}

private inner class IncomingHandler : Handler()

companion object {
const val notificationIdCurrentState = 10000
const val notificationIdIncomingMessage = 10001
const val channelId = "default"
}
}
23 changes: 23 additions & 0 deletions demo/src/main/res/layout/fragment_chatroom_service.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ © 2019 Match Group, LLC.
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/stockName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/space_l"
android:layout_marginEnd="@dimen/space_xs"
android:layout_marginStart="@dimen/space_xxl"
android:layout_gravity="center"
android:autoLink="web"
android:linksClickable="true"
android:lines="10"
android:text="Interact with this demo at\n https://socket-io-chat.now.sh/\nIncoming Messages will show up as notifications" />

</LinearLayout>
4 changes: 2 additions & 2 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
*/

ext {
minSdkVersion = 21
minSdkVersion = 28
minSdkVersionAndroidLifecycle = 19
targetSdkVersion = 28
compileSdkVersion = 28
buildToolsVersion = '28.0.3'

appCompat = 'androidx.appcompat:appcompat:1.0.0'
lifecycleExtensions = 'androidx.lifecycle:lifecycle-extensions:2.0.0-rc01'
lifecycleExtensions = 'androidx.lifecycle:lifecycle-extensions:2.0.0'
material = 'com.google.android.material:material:1.0.0'
multiDex = 'androidx.multidex:multidex:2.0.0'
constraintLayout = 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

android.enableJetifier=true
android.useAndroidX=true
version=0.2.2-alpha4
version=0.2.3-alpha1
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,18 @@ object AndroidLifecycle {
)
.combineWith(ConnectivityOnLifecycle(application))
}

@JvmStatic
@JvmOverloads
fun ofLifecycleServiceForeground(
application: Application,
lifecycleOwner: LifecycleOwner,
throttleTimeoutMillis: Long = ACTIVITY_THROTTLE_TIMEOUT_MILLIS
): Lifecycle {
return LifecycleOwnerStartedLifecycle(
lifecycleOwner,
LifecycleRegistry(throttleTimeoutMillis)
)
.combineWith(ConnectivityOnLifecycle(application))
}
}
Loading

0 comments on commit 70a30d2

Please sign in to comment.