Home » Android » Android – embedding Unity3d scene in activity – need to unregister receiver?

Android – embedding Unity3d scene in activity – need to unregister receiver?

Posted by: admin June 15, 2020 Leave a comment

Questions:

I’ve been a SO member for a while but never actually asked a question, so here goes..

My Aim

I’m trying to make an Android app with two activities. The first is a menu screen (using standard Android UI elements) with a button that opens the gameplay activity. The gameplay activity will have some standard Android UI elements and a FrameLayout containing a Unity 3D scene.

I’m using Unity 5 and Eclipse Luna.

What I’ve got working

I’ve made the menu screen with a simple button to start the second activity.
I’ve followed this tutorial and managed to get my Unity scene embedded in my second activity. All good so far…

The problem

The first time I start the gameplay activity it works fine (I can see the Unity scene embedded in my FrameLayout) but if I close the activity (to return to the menu activity) and then start the gameplay activity again I get this error…

Activity has leaked IntentReceiver [email protected] that was originally registered here.  Are you missing a call to unregisterReceiver()?

What I’ve tried

I’ve done a lot of searching online and it looks like I need to call something like this in onPause or onDestroy;

m_UnityPlayer.currentActivity.unregisterReceiver(receiver);

…but I don’t know what the receiver is so I can’t reference it in my unregisterReceiver call. I’ve tried creating a BroadcastReceiver, registering it and then unregistering it onPause but it makes no difference.

I found a post on the unity forum that asks the exact same question but, frustratingly, it is unanswered (a lot of questions on the Unity forum seem to be unanswered, that’s why I came here with this question).

I’ve also tried calling this method in onDestroy but it actually quits my whole app when I close the gameplay activity.

m_UnityPlayer.quit();

Code Sample

Here’s the code for my gameplay activity (I’ve removed the imports for clarity);

public class MyEmbeddedUnityActivity extends Activity {
    private UnityPlayer m_UnityPlayer;
    IntentFilter filter = new IntentFilter("");
    private BroadcastReceiver bRec = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //String action = intent.getAction();
            Log.d("", "onReceive intent: " + intent);
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_embedded_unity);

        if(m_UnityPlayer==null){
            m_UnityPlayer = new UnityPlayer(this);
            int glesMode = m_UnityPlayer.getSettings().getInt("gles_mode", 1);
            m_UnityPlayer.init(glesMode, false);

            m_UnityPlayer.currentActivity.registerReceiver(bRec, filter);

            FrameLayout layout = (FrameLayout) findViewById(R.id.my_frame);
            LayoutParams lp = new LayoutParams(200, 300);
            layout.addView(m_UnityPlayer, 0, lp);
        }

    }

    public void onWindowFocusChanged(boolean hasFocus){
        super.onWindowFocusChanged(hasFocus);
        m_UnityPlayer.windowFocusChanged(hasFocus);
    }

    @Override
    public void onDestroy (){
        //m_UnityPlayer.quit();
        m_UnityPlayer.currentActivity.unregisterReceiver(bRec);
        super.onDestroy();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig){
        super.onConfigurationChanged(newConfig);
        m_UnityPlayer.configurationChanged(newConfig);
    }

    @Override
    protected void onResume() {
        super.onResume();
        m_UnityPlayer.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        m_UnityPlayer.pause();
    }

}

And finally…

The steps I followed to embed the Unity scene were written in 2011. The whole process (of grabbing the files from the Unity project’s staging area and copying files around etc.) seems really hacky and undocumented.

Is there a better way of embedding Unity scenes in Android activities with Unity 5? Surely adding a Unity scene to an existing app is a fairly common thing to try to do?

Thanks, any help would be greatly appreciated!

How to&Answers:

So, I did some more searching and eventually found an answer, right here on SO!

As discussed in this answer, adding this line to the manifest fixes the problem;

android:process=":UnityKillsMe"

so the relevant part of the manifest looks like this;

...

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <activity
        android:name=".Studio"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:process=":UnityKillsMe"
        android:label="@string/title_activity_home" > 
    </activity>

...

This forces the gameplay activity to launch in a separate process. This means you can call m_UnityPlayer.quit() in the activity’s onDestroy method without the whole app closing.

Simple fix, but annoying that it seems to be completely undocumented.

Hope this helps someone!