Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity3D Android Lockscreen not shown when screen times out. (Wakelock?)

I am building an android app using Unity and it is coming along very well. However, I'm having an odd issue relating to the screen timing out and the lockscreen not showing.

What Should Happen

  • User stops playing
  • Screen Times out and turns off
  • Later, player returns and turns their phone back on
  • Lockscreen shows, user can enter their password, or otherwise unlock their phone
  • App regains focus and continues

What IS happening

  • User stops playing
  • Screen Times out and turns off
  • Later, player returns and turns their phone back on
  • Lockscreen does NOT show! The app is right in focus, bypassing the lockscreen all together
  • Users get mad that their security is compromised :(

Notes

  • This happens regardless of whether or not I'm using Android Plugins
  • I'm using Unity 4.2.0f4 (Though the changelogs for the more recent versions have nothing about this issue)
  • It even happens on a blank Android project
  • I've tested this on 5 different devices, all have the same problem

I suspect that this is caused by a wakelock that Unity does not give up when the screen times out. This causes the app to hold focus and the lockscreen never gets to 'load'. This is a pretty serious problem.

Does anyone know of any way to fix this?

Note: I've already asked this question on Unity Answers a little over a week ago and haven't gotten any responses yet. I thought maybe I'd have better luck here.

like image 379
Khalos Avatar asked Nov 02 '22 11:11

Khalos


1 Answers

First I'd like to say thanks to MichaelTaylor3D's Answer for pointing me in the right direction.

There were a few issues with the way he solved the problem that I think I have corrected:

The first issue is with the KeyguardManager approach to locking the screen. This was depreciated in API version 8 and won't work on API 9+. The new solution uses the Device Admin API which seems very intrusive for a game.

I looked through the UnityPlayer definition in eclipse and found a function called setWakeLock(boolean), however it is private.

I made a custom android Activity. In it, I access a protected UnityPlayer function setWakeLock(boolean) and calls it in the onPause function.

I admit this is less than ideal, but it does seem to work with no side effects. I've submitted a bug report to Unity, so hopefully this work around will not be required for long.

public class UnityPlayerWithLockscreen extends UnityPlayerNativeActivity {


    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
         super.onCreate(savedInstanceState);
    }

    //Provides access to the private UnityPlayer.setWakeLock(boolean) method.
    public void setWakeLock(boolean useWakelock) {
        Method setWakeLockMethod;

        //Use Reflection to get the setWakeLock(boolean) method from the UnityPlayer class
        setWakeLockMethod = mUnityPlayer.getClass().getDeclaredMethod("setWakeLock");

        //Set the method to me accessible
        setWakeLockMethod.setAccessible(true);

        //Invoke the method with our argument
        setWakeLockMethod.invoke(mUnityPlayer, useWakelock);
    }


    @Override
    protected void onPause()
    {
        super.onPause();

        //Force unity to release the wakelock
        setWakeLock(false);     
    }
}

Then you need to set this activity as the main activity in the AndroidManifest file:

<?xml version="1.0" encoding="utf-8"?>
<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".UnityPlayerWithLockscreen"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

This solution also doesn't require any C# scripts or C# <-> Java interop.

Again, I know this is sort of a hacky solution, but it seems to work on several devices regardless of API level with no side effects. Hopefully this gets fixed by Unity soon and will no longer require an ugly fix.

like image 54
Khalos Avatar answered Nov 15 '22 05:11

Khalos