@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
44import android.app.Activity
55import android.content.Context
66import android.content.ContextWrapper
7- import android.content.Intent
87import android.graphics.Color
98import android.os.Build
109import android.os.Handler
@@ -17,55 +16,39 @@ import android.widget.FrameLayout
1716import androidx.lifecycle.DefaultLifecycleObserver
1817import androidx.lifecycle.LifecycleOwner
1918import com.unity3d.player.IUnityPlayerLifecycleEvents
20- import io.flutter.plugin.common.BinaryMessenger
21- import io.flutter.plugin.common.MethodCall
22- import io.flutter.plugin.common.MethodChannel
23- import io.flutter.plugin.common.MethodChannel.MethodCallHandler
2419import io.flutter.plugin.platform.PlatformView
2520
2621
2722@SuppressLint(" NewApi" )
2823class FlutterUnityWidgetController (
2924 private val id : Int ,
3025 private val context : Context ? ,
31- binaryMessenger : BinaryMessenger ,
3226 lifecycleProvider : LifecycleProvider
33- ) : PlatformView,
27+ ): PlatformView,
3428 DefaultLifecycleObserver ,
3529 FlutterUnityWidgetOptionsSink ,
36- MethodCallHandler ,
37- UnityEventListener ,
3830 IUnityPlayerLifecycleEvents {
3931
4032 // #region Members
4133 private val LOG_TAG = " FlutterUnityController"
4234 private var lifecycleProvider: LifecycleProvider = lifecycleProvider
4335 private var options: FlutterUnityWidgetOptions = FlutterUnityWidgetOptions ()
4436
45- private val methodChannel: MethodChannel
46-
47- private var methodChannelResult: MethodChannel .Result ? = null
4837 private var view: FrameLayout
4938 private var disposed: Boolean = false
5039 private var attached: Boolean = false
5140 private var loadedCallbackPending: Boolean = false
41+ var viewId: String = " unity-id-$id "
5242
5343 init {
54- UnityPlayerUtils .controllers.add( this )
44+ UnityPlayerUtils .controllers[viewId] = this
5545
5646 var tempContext = UnityPlayerUtils .activity as Context
5747 if (context != null ) tempContext = context
5848 // set layout view
5949 view = FrameLayout (tempContext)
6050 view.setBackgroundColor(Color .WHITE )
6151
62- // setup method channel
63- methodChannel = MethodChannel (binaryMessenger, " plugin.xraph.com/unity_view_$id " )
64- methodChannel.setMethodCallHandler(this )
65-
66- // Set unity listener
67- UnityPlayerUtils .addUnityEventListener(this )
68-
6952 if (UnityPlayerUtils .unityPlayer == null ) {
7053 createPlayer()
7154 refocusUnity()
@@ -90,7 +73,6 @@ class FlutterUnityWidgetController(
9073
9174 override fun dispose () {
9275 Log .d(LOG_TAG , " this controller disposed" )
93- UnityPlayerUtils .removeUnityEventListener(this )
9476 if (disposed) {
9577 return
9678 }
@@ -104,77 +86,6 @@ class FlutterUnityWidgetController(
10486 disposed = true
10587 }
10688
107- override fun onMethodCall (methodCall : MethodCall , result : MethodChannel .Result ) {
108- when (methodCall.method) {
109- " unity#waitForUnity" -> {
110- if (UnityPlayerUtils .unityPlayer != null ) {
111- result.success(null )
112- return
113- }
114- result.success(null )
115- methodChannelResult = result
116- }
117- " unity#createPlayer" -> {
118- invalidateFrameIfNeeded()
119- this .createPlayer()
120- refocusUnity()
121- result.success(null )
122- }
123- " unity#isReady" -> {
124- result.success(UnityPlayerUtils .unityPlayer != null )
125- }
126- " unity#isLoaded" -> {
127- result.success(UnityPlayerUtils .unityLoaded)
128- }
129- " unity#isPaused" -> {
130- result.success(UnityPlayerUtils .unityPaused)
131- }
132- " unity#postMessage" -> {
133- invalidateFrameIfNeeded()
134- val gameObject: String = methodCall.argument<String >(" gameObject" ).toString()
135- val methodName: String = methodCall.argument<String >(" methodName" ).toString()
136- val message: String = methodCall.argument<String >(" message" ).toString()
137- UnityPlayerUtils .postMessage(gameObject, methodName, message)
138- result.success(true )
139- }
140- " unity#pausePlayer" -> {
141- invalidateFrameIfNeeded()
142- UnityPlayerUtils .pause()
143- result.success(true )
144- }
145- " unity#openInNativeProcess" -> {
146- openNativeUnity()
147- result.success(true )
148- }
149- " unity#resumePlayer" -> {
150- invalidateFrameIfNeeded()
151- UnityPlayerUtils .resume()
152- result.success(true )
153- }
154- " unity#unloadPlayer" -> {
155- invalidateFrameIfNeeded()
156- UnityPlayerUtils .unload()
157- result.success(true )
158- }
159- " unity#dispose" -> {
160- // destroyUnityViewIfNecessary()
161- // if ()
162- // dispose()
163- result.success(null )
164- }
165- " unity#silentQuitPlayer" -> {
166- UnityPlayerUtils .quitPlayer()
167- result.success(true )
168- }
169- " unity#quitPlayer" -> {
170- if (UnityPlayerUtils .unityPlayer != null ) {
171- UnityPlayerUtils .unityPlayer!! .destroy()
172- }
173- result.success(true )
174- }
175- else -> result.notImplemented()
176- }
177- }
17889 // #endregion
17990
18091 // #region Options Override
@@ -196,33 +107,27 @@ class FlutterUnityWidgetController(
196107 // #endregion
197108
198109 // #region Unity Events
199- override fun onMessage (message : String ) {
200- Handler (Looper .getMainLooper()).post {
201- methodChannel.invokeMethod(" events#onUnityMessage" , message)
202- }
203- }
204-
205- override fun onSceneLoaded (name : String , buildIndex : Int , isLoaded : Boolean , isValid : Boolean ) {
206- Handler (Looper .getMainLooper()).post {
207- val payload: MutableMap <String , Any > = HashMap ()
208- payload[" name" ] = name
209- payload[" buildIndex" ] = buildIndex
210- payload[" isLoaded" ] = isLoaded
211- payload[" isValid" ] = isValid
212- methodChannel.invokeMethod(" events#onUnitySceneLoaded" , payload)
213- }
214- }
215110
216111 override fun onUnityPlayerUnloaded () {
217- Log .d(LOG_TAG , " onUnityPlayerUnloaded" )
112+ Log .d(FlutterUnityWidgetPlugin . LOG_TAG , " onUnityPlayerUnloaded" )
218113 UnityPlayerUtils .unityLoaded = false
219114 Handler (Looper .getMainLooper()).post {
220- methodChannel.invokeMethod(" events#onUnityUnloaded" , true )
115+ DataStreamEventNotifier .notifier.onNext(
116+ DataStreamEvent (
117+ DataStreamEventTypes .OnUnityPlayerUnloaded .name,
118+ true ,
119+ )
120+ )
221121 }
222122 }
223123
224124 override fun onUnityPlayerQuitted () {
225- if (disposed) return
125+ DataStreamEventNotifier .notifier.onNext(
126+ DataStreamEvent (
127+ DataStreamEventTypes .OnUnityPlayerQuited .name,
128+ true ,
129+ )
130+ )
226131 }
227132
228133 // #endregion
@@ -265,44 +170,35 @@ class FlutterUnityWidgetController(
265170 this .lifecycleProvider.getLifecycle().addObserver(this )
266171 }
267172
268- private fun openNativeUnity () {
269- val activity = getActivity(null )
270- if (activity != null ) {
271- val intent = Intent (getActivity(null )!! .applicationContext, OverrideUnityActivity ::class .java)
272- intent.flags = Intent .FLAG_ACTIVITY_REORDER_TO_FRONT
273- intent.putExtra(" fullscreen" , options.fullscreenEnabled)
274- intent.putExtra(" flutterActivity" , activity.javaClass)
275- activity.startActivityForResult(intent, 1 )
276- }
277- }
278-
279173 private fun destroyUnityViewIfNecessary () {
280174 if (options.unloadOnDispose) {
281175 UnityPlayerUtils .unload()
282176 }
283177 }
284178
285- private fun createPlayer () {
179+ fun createPlayer () {
286180 try {
287181 if (UnityPlayerUtils .activity != null ) {
288182 UnityPlayerUtils .createUnityPlayer( this , object : OnCreateUnityViewCallback {
289183 override fun onReady () {
290184 // attach unity to controller
291185 attachToView()
292186
293- if (methodChannelResult != null ) {
294- methodChannelResult!! .success(true )
295- methodChannelResult = null
296- }
187+ DataStreamEventNotifier .notifier.onNext(
188+ DataStreamEvent (
189+ DataStreamEventTypes .OnUnityViewCreated .name,
190+ viewId,
191+ )
192+ )
297193 }
298194 })
299195 }
300196 } catch (e: Exception ) {
301- if (methodChannelResult != null ) {
302- methodChannelResult!! .error(" FLUTTER_UNITY_WIDGET" , e.message, e)
303- methodChannelResult!! .success(false )
304- methodChannelResult = null
305- }
197+ // if (methodChannelResult != null) {
198+ // methodChannelResult!!.error("FLUTTER_UNITY_WIDGET", e.message, e)
199+ // methodChannelResult!!.success(false)
200+ // methodChannelResult = null
201+ // }
306202 }
307203 }
308204
@@ -324,9 +220,13 @@ class FlutterUnityWidgetController(
324220 }
325221
326222 private fun detachView () {
327- UnityPlayerUtils .controllers.remove(this )
328- methodChannel.setMethodCallHandler(null )
329- UnityPlayerUtils .removePlayer(this )
223+ try {
224+ if (! UnityPlayerUtils .controllers.containsValue(this )) return
225+ UnityPlayerUtils .controllers.remove(viewId)
226+ UnityPlayerUtils .removePlayer(this )
227+ } catch (e: Exception ) {
228+ Log .e(LOG_TAG , e.message, e)
229+ }
330230 }
331231
332232
@@ -349,7 +249,7 @@ class FlutterUnityWidgetController(
349249 }
350250
351251 // DO NOT CHANGE THIS FUNCTION
352- private fun refocusUnity () {
252+ fun refocusUnity () {
353253 UnityPlayerUtils .resume()
354254 UnityPlayerUtils .pause()
355255 UnityPlayerUtils .resume()
@@ -359,15 +259,20 @@ class FlutterUnityWidgetController(
359259 if (UnityPlayerUtils .unityPlayer!! .parent != view) {
360260 this .attachToView()
361261 Handler (Looper .getMainLooper()).post {
362- methodChannel.invokeMethod(" events#onViewReattached" , null )
262+ DataStreamEventNotifier .notifier.onNext(
263+ DataStreamEvent (
264+ DataStreamEventTypes .OnViewReattached .name,
265+ viewId,
266+ )
267+ )
363268 }
364269 }
365270 view.requestLayout()
366271 }
367272
368273 // / Reference solution to Google Maps implementation
369274 // / https://github.com/flutter/plugins/blob/b0bfab678f83bebd49e9f9d0a83fe9b40774e853/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java#L154
370- private fun invalidateFrameIfNeeded () {
275+ fun invalidateFrameIfNeeded () {
371276 if (UnityPlayerUtils .unityPlayer == null || loadedCallbackPending) {
372277 return
373278 }
0 commit comments