Unity3d Android -Ecperen не показан при выходе на экран. (Wakelock?)

StackOverflow https://stackoverflow.com/questions/19846822

Вопрос

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

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

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

Что случилось

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

Заметки

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

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

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

Примечание: я уже спрашивал Этот вопрос о ответах Unity Чуть более недели назад и еще не получили никаких ответов. Я подумал, может быть, мне повезло здесь.

Это было полезно?

Решение

Сначала я хотел бы сказать спасибо Michaeltaylor3d ответ для указания мне в правильном направлении.

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

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

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

Я сделал пользовательскую активность Android. В нем я получаю доступ к защищенной функции 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# <-> Java Interop.

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

Другие советы

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

Чтобы увидеть, как -то заставляет единство Wakelock с iSheld (); и постарайтесь переопределить это в своей деятельности

РЕДАКТИРОВАТЬ: Я использую Wakelock при загрузке, и это делает экран черным, но не блокируйте устройство, так что это, вероятно, так, поэтому попробуйте его выпустить, это может дать какой -то конфликт, но всегда стоит попробовать.

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

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

Попробуйте написать внешний класс Java и поместите его в папку Plugins/Android.

Метод класса Java может быть чем -то вроде этого: ссылка на этот вопросубедитесь, что это Скомпилируется в файл .jar

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, так что 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: ссылка здесь

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 вызовете экрана блокировки на событии паузы приложения: ссылка здесь

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

Вы должны убедиться, что следующий флаг установлен на ложный

Application.runInBackground = false;

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

Даже если это обход, я все еще думаю, что это ошибка единства, которая должна быть сообщил им.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top