Pregunta

Estoy construyendo una aplicación de Android usando Unity y está llegando muy bien. Sin embargo, tengo un problema extraño relacionado con el tiempo de pantalla de la pantalla y la pantalla de bloqueo no se muestra.

Qué debería pasar

  • El usuario deja de jugar
  • Los tiempos de pantalla se apagan y apagan
  • Más tarde, el jugador regresa y vuelve a encender su teléfono
  • Programas de pantalla de bloqueo, el usuario puede ingresar su contraseña o desbloquear su teléfono
  • La aplicación recupera el enfoque y continúa

Qué está pasando

  • El usuario deja de jugar
  • Los tiempos de pantalla se apagan y apagan
  • Más tarde, el jugador regresa y vuelve a encender su teléfono
  • Lockscreen sí NO ¡mostrar! La aplicación está bien en foco, sin pasar por la pantalla de bloqueo todos juntos
  • Los usuarios se enojaron porque su seguridad está comprometida :(

Notas

  • Esto sucede independientemente de si estoy usando o no complementos de Android
  • Estoy usando Unity 4.2.0f4 (aunque los Changelogs para las versiones más recientes no tienen nada sobre este problema)
  • Incluso sucede en un proyecto de Android en blanco
  • He probado esto en 5 dispositivos diferentes, todos tienen el mismo problema

Sospecho que esto es causado por un wakelock de que la unidad no se rinde cuando la pantalla sale tiempo. Esto hace que la aplicación mantenga el enfoque y la pantalla de bloqueo nunca llega a 'cargar'. Este es un problema bastante grave.

¿Alguien sabe de alguna forma de solucionar esto?

Nota: ya he preguntado Esta pregunta sobre las respuestas de Unity Hace poco más de una semana y aún no he recibido ninguna respuesta. Pensé que tal vez tendría mejor suerte aquí.

¿Fue útil?

Solución

Primero me gustaría agradecer a Respuesta de Michaeltaylor3D por señalarme en la dirección correcta.

Hubo algunos problemas con la forma en que resolvió el problema que creo que he corregido:

El primer problema es con el KeyguardManager enfoque para bloquear la pantalla. Esto se depreció en API versión 8 y no funcionará en API 9+. La nueva solución utiliza la API de administración del dispositivo que parece muy intrusiva para un juego.

Miré a través de la definición de UnityPlayer en Eclipse y encontré una función llamada setwakelock (boolean), sin embargo, es privado.

Hice una actividad de Android personalizada. En él, accedo a una función protegida de UnityPlayer setWakeLock(boolean) y lo llama en el onPause función.

Admito que esto es menos que ideal, pero parece funcionar sin efectos secundarios. He enviado un informe de errores a Unity, por lo que espero que este trabajo no sea necesario por mucho tiempo.

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

Luego debe establecer esta actividad como la actividad principal en el archivo 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>

Esta solución tampoco requiere ningún scripts C# o C# <-> Java Intop.

Nuevamente, sé que esta es una especie de solución hacky, pero parece funcionar en varios dispositivos, independientemente del nivel de API sin efectos secundarios. Esperemos que esto sea arreglado por Unity pronto y ya no requerirá una solución fea.

Otros consejos

No tengo ninguna experiencia de Unity, pero intente usar esto http://developer.android.com/reference/android/os/powermanager.wakelock.html

Para ver si la unidad está forzando el wakelock de alguna manera con isheld (); e intenta anularlo dentro de tu actividad

EDITAR: Estoy usando Wakelock al descargar y esto hace que la pantalla se vuelva negra pero no bloquee el dispositivo, por lo que este es probablemente el caso, así que intente liberarlo, esto podría dar algún tipo de conflicto, pero siempre vale la pena intentarlo.

Esto no se ha probado pero puedes probar esto,

Básicamente, desea intentar acceder al SDK de Android directamente, Unity tiene algunas clases que le permiten hacer esto.

Intente escribir una clase de Java externa y colóquela en la carpeta Plugins/Android.

El método de clase Java podría ser algo como esto: referenciado de esta preguntaAsegúrese de que sea compilado en un archivo .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();  
    }
}

También asegúrese de que esto esté en el archivo de manifiesto Android para que Unity cargue esta actividad en lugar de la principal y coloque en la carpeta 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>

Luego cree un script de Unity C# que invoque la clase Java externa: referenciado aquí

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

}

Luego, finalmente, en un monobehavior activo, invoca la pantalla de bloqueo en el evento de pausa de la aplicación: referenciado aquí

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

Tendría que asegurarse de que el siguiente indicador esté configurado en falso

Application.runInBackground = false;

Creo que o el evento de pausa no se activará cuando el dispositivo se apaga. (Esto está desactivada por defecto)

Incluso si esto es un trabajo, sigo pensando que este es un error de unidad que debería ser reportado a ellos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top