After opening embedded Unity fragment, resolution changes in parent Android app

Viewed 139

I have a Unity activity embedded as a fragment inside of my Android app. Everything works fine, except that after the fragment runs, the resolution of the app is funny. And it stays that way even after restarting. I have to make a change to the AndroidManifest and then reinstall in order to get the resolution right again.

Here is a piece of the manifest from the Android app.

<application
    android:name=".App"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:extractNativeLibs="true"
    android:theme="@style/AppTheme"
    android:usesCleartextTraffic="true">
    <activity android:name=".FragmentActivity"
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:windowSoftInputMode="adjustNothing">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

Here is the entire AndroidManifest from unityLibrary that I imported into the app.

<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools">
  <application>
    <activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector" android:screenOrientation="fullSensor" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="false">
     <!--<intent-filter>-->
        <!--<action android:name="android.intent.action.MAIN" />-->
        <!--<category android:name="android.intent.category.DEFAULT" />-->
      <!--</intent-filter>-->
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
      <meta-data android:name="android.notch_support" android:value="true" />
    </activity>
    <meta-data android:name="unity.splash-mode" android:value="0" />
    <meta-data android:name="unity.splash-enable" android:value="True" />
    <meta-data android:name="notch.config" android:value="portrait|landscape" />
    <meta-data android:name="unity.build-id" android:value="f6e555a5-44fc-47be-9a81-b3809caa8f74" />
  </application>
  <uses-feature android:glEsVersion="0x00030000" />
  <uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>

Here's the activity that holds the fragment.

class FragmentActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_fragment)

    }
}

Here's the fragment itself.

class UnityFragment : Fragment() {
    protected var mUnityPlayer: UnityPlayer? = null
    var frameLayoutForUnity: FrameLayout? = null

    fun UnityFragment() {}

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        mUnityPlayer = UnityPlayer(activity)
        val view = inflater.inflate(R.layout.fragment_unity, container, false)
        frameLayoutForUnity =
                view.findViewById<View>(R.id.frameLayoutForUnity) as FrameLayout
        frameLayoutForUnity!!.addView(
                mUnityPlayer!!.view,
                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT
        )
        mUnityPlayer!!.requestFocus()
        mUnityPlayer!!.windowFocusChanged(true)
        return view
    }

    override fun onDestroy() {
        mUnityPlayer!!.quit()
        super.onDestroy()
    }

    override fun onPause() {
        super.onPause()
        mUnityPlayer!!.pause()
    }

    override fun onResume() {
        super.onResume()
        mUnityPlayer!!.resume()
    }
}

And here's R.layout.fragment_unity.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/frameLayoutForUnity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".UnityFragment"/>

The layout for FragmentActivity is just a single fragment inside of a constraintlayout.

I hope someone can point me in the right direction because I really don't understand how screen resolution works or what controls it. But based on the appearance of layouts in the rest of the app, it feels like that's what it's related to.

1 Answers

I found a solution, but it's not super enlightening. What I mean is that I found a way to make the symptom stop.

For reasons I can't explain, if I set hardwareAccelerated to true inside of my app Manifest WHILE ALSO turning notchsupport to false inside the unityLibrary Manifest then my custom views stop drawing their canvases weird.

I know this seems like rain dancing or using a dowsing rod, but it works and I can revisit later to make an implementation that I understand.

Some notes: My gut feeling is that I'm letting the unity manifest talk over my app manifest and somehow turn off hardwareAccelerated, since that would explain the canvases being drawn differently. But suppressing hardwareAccelerated turning off inside the unity manifest and also forcing it as enabled in the app manifest are not enough by themselves to stop the symptom. The only thing that stops the symptom is doing all of that and also turning off notch_support. Maybe somewhere notch_support interacts with hardwareAccelerated. But I think it's more likely that there's a third factor causing all this and this random confluence of settings affects that factor happenstantially.

Edit: It's been a long time since I asked this question. But I see that it's gotten some interest recently from someone likely experiencing the same problem. I never figured out what the problem was. It sort of just happened intermittently and eventually stopped. But for the benefit of posterity I would like to say that visually detecting a change in resolution in any situation and for any cause points to a failure to accommodate different screens and is probably why the question got downvoted.

So if you're experiencing this problem too, the first place you should probably look is whether you're using px instead of dp in your custom drawn canvases. A lot of the canvas draw methods default to px and you have to normalize to dp yourself.

Also use percentages to size things out inside of ConstraintLayouts.

Related