2013-11-07 2 views
4

Я создаю приложение для Android, используя Unity, и оно идет очень хорошо. Тем не менее, у меня есть странная проблема, связанная с тайм-аутом экрана, и экран блокировки не отображается.Unity3D Android Lockscreen не отображается, когда экран отключается. (Wakelock?)

Что должно произойти

  • Пользователь перестает играть
  • раз отсеивать и выключает
  • Позже, игрок возвращается и превращает свой телефон обратно на
  • Lockscreen показывает, пользователь может ввести их пароль или разблокировать их телефон
  • Приложение восстанавливает фокус и продолжает

Что происходит

  • Пользователь перестает играть
  • раз отсеивать и выключает
  • Позже, игрок возвращается и превращает свой телефон обратно на
  • Lockscreen делает НЕ шоу ! Приложение находится прямо в центре внимания, минуя LockScreen все вместе
  • Пользователи злиться, что их безопасность находится под угрозой :(

Примечания

  • Это происходит независимо от того, или нет Я использую Android-плагины
  • Я использую Unity 4.2.0f4 (Хотя изменения в более поздних версиях ничего не знают об этой проблеме)
  • Это происходит даже на пустой Android проекта
  • Я проверил это на 5 различных устройств, все они имеют ту же проблему

Я подозреваю, что это вызвано wakelock, что Unity не сдавайся когда экран отключается. Это заставляет приложение удерживать фокус, и lockscreen никогда не получает «load». Это довольно серьезная проблема.

Кто-нибудь знает, как это исправить?

Примечание: я уже задал вопрос this question on Unity Answers чуть более недели назад и еще не получил ответов. Я подумал, может быть, мне повезло.

+1

Ive подтвердил, что моя связь 10 имеет то же точное поведение, что и – MichaelTaylor3D

ответ

2

Сначала я хотел бы сказать спасибо MichaelTaylor3D's Answer указал мне в правильное направление.

Были несколько вопросов, с тем, как он решил проблему, что я думаю, что я исправил:

Первый вопрос с KeyguardManager подход к блокировки экрана. Это было обесценено в API версии 8 и не будет работать с API 9+. Новое решение использует API-интерфейс Device Admin, который кажется очень навязчивым для игры.

Я просмотрел определение UnityPlayer в eclipse и нашел функцию setWakeLock (boolean), однако она является частной.

Я сделал пользовательский андроид деятельности. В нем я получаю доступ к защищенной функции UnityPlayer setWakeLock(boolean) и вызывает ее в функции .

Я признаю, что это не идеальный вариант, но он, похоже, работает без побочных эффектов. Я отправил отчет об ошибке в 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# < -> Java Interop.

Опять же, я знаю, что это своего рода хакерское решение, но оно работает на нескольких устройствах независимо от уровня API без побочных эффектов. Надеюсь, это скоро будет исправлено Unity и больше не потребует уродливого исправления.

+0

У вас есть ссылка на ошибку единства, о которой вы сообщали? – gollumullog

0

У меня нет никакого опыта с Unity, но попробуйте использовать этот http://developer.android.com/reference/android/os/PowerManager.WakeLock.html

Чтобы увидеть, если единство вынуждает wakelock как-то с isHeld(); и попытайтесь переопределить его в своей деятельности.

EDIT: Я использую wakelock при загрузке, и это делает экран черным, но не блокирует устройство, так что это, вероятно, так, поэтому попробуйте его освободить, это может дать какой-то вид конфликта, но это всегда стоит попробовать.

0

Это непроверенное, но вы можете попробовать это,

В основном вы хотите, чтобы попытаться получить доступ к Android SDK напрямую, Unity есть некоторые классы, которые позволяют это сделать.

Попробуйте написать внешний класс Java и поместить его в папку «Плагины/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> 

Затем создайте # скрипт Unity C, вызывающий внешний класс Java: 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 вызов LockScreen на событиях паузы приложения: referenced here

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

Вам необходимо убедиться, что для следующего флага установлено значение false

Application.runInBackground = false; 

Я бы подумал, иначе событие паузы не будет запущено, когда устройство выключится. (Это по умолчанию отключено)

Даже если это работа вокруг, я до сих пор считаю, что это ошибка Unity, который должен быть reported to them.

+0

Благодарим за предложение. Я сделаю это после работы. Я согласен, что это ошибка единства, и я отправлю отчет. – Khalos

+0

Спасибо! Этот ответ был очень полезен при решении моей проблемы. Поэтому я награждаю вас щедростью. Однако я сделал это по-другому, поэтому я отправлю еще один ответ с моим окончательным решением. Если его можно принять и я. – Khalos