27 | * The stream will immediately end with an {@link IllegalBonjourTypeException}
28 | * if the input type does not obey Bonjour type specifications.
29 | * If you intend to use this method with arbitrary types that can be provided by user input,
30 | * it is highly encouraged to verify this input
31 | * using {@link #isBonjourType(String)} before calling this method!
32 | *
33 | * @param type Type of service to discover
34 | * @return An {@link Observable} of {@link BonjourEvent}s for the specific type
35 | */
36 | fun newDiscovery(type: String): Observable
90 | * The stream will immediately end with an {@link IllegalBonjourTypeException}
91 | * if the input type does not obey Bonjour type specifications.
92 | * If you intend to use this method with arbitrary types that can be provided by user input,
93 | * it is highly encouraged to verify this input
94 | * using {@link #isBonjourType(String)} before calling this method!
95 | *
96 | * When the returned {@link Completable} is unsubscribed from, the broadcast ends,
97 | * and this is the only instance (aside from error events) where it terminates.
98 | * It never emits the onCompleted() event because of that,
99 | * so avoid chaining something after this Completable using andThen().
100 | *
101 | * @param config Configuration of the service to advertise
102 | * @return A {@link Completable} holding the state of the broadcast, valid until unsubscription
103 | */
104 | fun newBroadcast(config: BonjourBroadcastConfig): Completable =
105 | if (config.type.isBonjourType()) {
106 | // New Broadcast request for the Driver
107 | val broadcast = driver.createBroadcast()
108 | val connection = platform.createConnection()
109 |
110 | Completable.defer {
111 | Completable.create { emitter ->
112 | // Initialization
113 | broadcast.initialize()
114 | connection.initialize()
115 |
116 | // Destruction
117 | val disposable = platform.runOnTeardown {
118 | broadcast.teardown()
119 | connection.teardown()
120 | }
121 | emitter.setDisposable(disposable)
122 |
123 | // Lifetime
124 | val callback = object : BroadcastCallback {
125 | override fun broadcastFailed(cause: Exception?) {
126 | emitter.onError(BroadcastFailedException(driver.name, cause))
127 | }
128 | }
129 |
130 | try {
131 | val address = config.address ?: platform.getWifiAddress()
132 | broadcast.start(address, config, callback)
133 | } catch (ex: Exception) {
134 | callback.broadcastFailed(ex)
135 | }
136 | }
137 | }
138 |
139 | } else {
140 | // Not a Bonjour type
141 | Completable.error(IllegalBonjourTypeException(config.type))
142 | }
143 |
144 | /**
145 | * Configuration and Creation of RxBonjour instances.
146 | * Supply a Platform & a Driver to the Builder (provided by separate artifacts)
147 | * before creating the RxBonjour instance itself.
148 | */
149 | class Builder {
150 | private var platform: Platform? = null
151 | private var driver: Driver? = null
152 |
153 | fun platform(platform: Platform) = also { this.platform = platform }
154 | fun driver(driver: Driver) = also { this.driver = driver }
155 |
156 | fun create(): RxBonjour {
157 | require(platform != null, { "You need to provide a platform() to RxBonjour's builder" })
158 | require(driver != null, { "You need to provide a driver() to RxBonjour's builder" })
159 | return RxBonjour(platform!!, driver!!)
160 | }
161 | }
162 | }
163 |
164 | /* Extension Functions */
165 |
166 | fun String.isBonjourType() = this.matches(TYPE_PATTERN)
167 |
--------------------------------------------------------------------------------
/rxbonjour/src/main/kotlin/de/mannodermaus/rxbonjour/Schedulers.kt:
--------------------------------------------------------------------------------
1 | package de.mannodermaus.rxbonjour
2 |
3 | import io.reactivex.CompletableTransformer
4 | import io.reactivex.ObservableTransformer
5 | import io.reactivex.schedulers.Schedulers
6 |
7 | class BonjourSchedulers private constructor() {
8 | companion object {
9 | @JvmStatic
10 | fun completableAsync(): CompletableTransformer =
11 | CompletableTransformer {
12 | it.subscribeOn(Schedulers.computation())
13 | .observeOn(Schedulers.computation())
14 | }
15 |
16 | @JvmStatic
17 | fun