屏幕超时时未显示Unity3D Android锁屏。 (激活锁定?)

时间:2013-11-07 21:14:08

标签: android unity3d lockscreen wakelock

我正在使用Unity构建一个Android应用程序,它正在顺利进行。但是,我遇到了一个与屏幕超时和锁屏无关的奇怪问题。

应该发生什么

  • 用户停止播放
  • 屏幕超时并关闭
  • 稍后,玩家返回并重新开启手机
  • 锁屏显示,用户可以输入密码或以其他方式解锁手机
  • App重新获得关注并继续

发生了什么

  • 用户停止播放
  • 屏幕超时并关闭
  • 稍后,玩家返回并重新开启手机
  • 锁屏显示!该应用程序正确对焦,绕过锁屏一起
  • 用户对他们的安全性受到威胁感到愤怒:(

备注

  • 无论我是否使用Android插件
  • ,都会发生这种情况
  • 我正在使用Unity 4.2.0f4(虽然更新版本的更改日志对此问题没有任何意义)
  • 它甚至发生在一个空白的Android项目上
  • 我在5个不同的设备上测试了这个,都有同样的问题

我怀疑这是由于在屏幕超时时Unity不放弃的唤醒锁定引起的。这会导致应用程序保持焦点,锁屏永远不会“加载”。这是一个非常严重的问题。

有谁知道解决这个问题的方法?

注意:我已经在一周多前问过this question on Unity Answers并且还没有得到任何答复。我想也许我在这里有更好的运气。

3 个答案:

答案 0 :(得分:2)

首先,我要感谢MichaelTaylor3D's Answer指出我正确的方向。

他解决问题的方式存在一些问题,我认为我已经纠正过了:

第一个问题是使用KeyguardManager方法来锁定屏幕。这在API版本8中已经过折旧,不适用于API 9+。新解决方案使用Device Admin API,这似乎对游戏非常具有侵扰性。

我查看了eclipse中的UnityPlayer定义并找到了一个名为setWakeLock(boolean)的函数,但它是私有的。

我做了一个自定义的android Activity。在其中,我访问受保护的UnityPlayer函数setWakeLock(boolean)并在onPause函数中调用它。

我承认这不太理想,但似乎没有任何副作用。我已经向Unity提交了一份错误报告,所以希望这项工作不会长期存在。

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);     
    }
}

然后,您需要将此活动设置为AndroidManifest文件中的主要活动:

<?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>

此解决方案也不需要任何C#脚本或C#&lt; - &gt; Java互操作。

同样,我知道这是一种hacky解决方案,但它似乎适用于多种设备,无论API级别如何,都没有副作用。希望这很快就会被Unity修复,不再需要一个难看的修复。

答案 1 :(得分:0)

我没有Unity的任何经验,但尝试使用此http://developer.android.com/reference/android/os/PowerManager.WakeLock.html

用isHeld()来判断团结是否正在以某种方式强制唤醒锁;并尝试在您的活动中覆盖它

编辑:我在下载时使用唤醒锁,这使得屏幕变黑但没有锁定设备,所以可能就是这样,所以尝试释放它,这可能会产生某种冲突,但总是值得一试。

答案 2 :(得分:0)

这是未经测试的,但你可以试试这个,

基本上你想尝试直接访问Android SDK,Unity有一些允许你这样做的类。

尝试编写外部Java类并将其放在Plugins / Android文件夹中。

Java类方法可能是这样的:referenced from this question 确保其compiled into a .jar file

package com.yourcompany.yourgamename;

import com.unity3d.player.UnityPlayerActivity;

import android.content.Context;
import android.os.Bundle;
import android.util.Config;
import android.util.Log;
import android.app.Activity;   

public class MainActivity extends UnityPlayerActivity 
{    
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
         super.onCreate(savedInstanceState);
    }

    public static void lockScreen()
    {
        KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Activity.KEYGUARD_SERVICE); 
        KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);  
        lock.reenableKeyguard();  
    }
}

还要确保这是在Android Manifest文件中,以便Unity加载此活动而不是主活动,并将其放在\ Plugins \ Android文件夹中:

<?xml version="1.0" encoding="utf-8"?>

    

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".MainActivity"
              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>

然后创建一个调用外部Java类的Unity C#脚本:referenced here

public static void InvokeAndroidLockScreen()
{
    #if UNITY_ANDROID
    using (AndroidJavaClass cls_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    {
         using (AndroidJavaObject obj_Activity = cls_UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
         {
              obj_Activity .CallStatic("lockScreen");
         }
    }
    #else
    Debug.LogWarning("Cant invoke lockscreen on a non Android Device");
    #endif

}

然后最终在活动的monobehavior中调用应用程序暂停事件的锁屏:referenced here

void OnApplicationPause(bool pauseStatus)
{
     InvokeAndroidLockScreen();
}

您必须确保将以下标志设置为false

Application.runInBackground = false;

我会想,否则当设备关闭时,暂停事件不会被触发。 (默认情况下关闭)

即使这是一个解决方法,我仍然认为这是一个应该是reported to them.

的Unity Bug