سؤال

أقوم ببناء تطبيق Android باستخدام Unity ويأتي بشكل جيد للغاية. ومع ذلك ، فإنني أواجه مشكلة غريبة تتعلق بتوقيت الشاشة ولا تظهر شاشة القفل.

ما ينبغي أن يحدث

  • يتوقف المستخدم عن اللعب
  • أوقات الشاشة خارج وتطفئ
  • في وقت لاحق ، يعود اللاعب ويعيد هاتفه مرة أخرى
  • عروض LockScreen ، يمكن للمستخدم إدخال كلمة المرور الخاصة بهم ، أو إلغاء قفل هاتفهم بطريقة أخرى
  • يستعيد التطبيق التركيز ويستمر

ماذا يحدث

  • يتوقف المستخدم عن اللعب
  • أوقات الشاشة خارج وتطفئ
  • في وقت لاحق ، يعود اللاعب ويعيد هاتفه مرة أخرى
  • القفل لا ليس تبين! التطبيق صحيح في التركيز ، متجاوزًا شاشة القفل معًا
  • يشعر المستخدمون بالجنون لأن أمنهم يتعرض للخطر :(

ملحوظات

  • يحدث هذا بغض النظر عما إذا كنت أستخدم الإضافات Android أم لا
  • أنا أستخدم الوحدة 4.2.0f4 (على الرغم من أن changelogs للإصدارات الأحدث ليس لديها شيء حول هذه المشكلة)
  • يحدث حتى في مشروع Android فارغ
  • لقد اختبرت هذا على 5 أجهزة مختلفة ، وكلها لدي نفس المشكلة

أظن أن هذا ناتج عن wakelock أن الوحدة لا تستسلم عندما تخرج الشاشة. هذا يتسبب في تركيز التطبيق ولا يحصل شاشة القفل على "التحميل". هذه مشكلة خطيرة جدا.

لا أحد يعرف بأي طريقة لإصلاح هذا؟

ملاحظة: لقد طلبت بالفعل هذا السؤال حول إجابات الوحدة منذ ما يزيد قليلاً عن أسبوع ولم تحصل على أي ردود بعد. اعتقدت ربما سيكون لدي حظ أفضل هنا.

هل كانت مفيدة؟

المحلول

أولا أود أن أقول شكرا ل إجابة Michaeltaylor3d لتشير لي في الاتجاه الصحيح.

كانت هناك بعض المشكلات حول الطريقة التي حل بها المشكلة التي أعتقد أنني قمت بتصحيحها:

القضية الأولى هي مع KeyguardManager نهج إلى قفل الشاشة. تم انخفاض هذا في API الإصدار 8 ولن يعمل على API 9+. يستخدم الحل الجديد واجهة برمجة تطبيقات Admin Device التي تبدو متطفلة للغاية للعبة.

نظرت من خلال تعريف UnityPlayer في Eclipse ووجدت وظيفة تسمى Setwakelock (Boolean) ، ومع ذلك فهي خاصة.

لقد صنعت نشاط Android مخصص. في ذلك ، يمكنني الوصول إلى وظيفة unityplayer محمية setWakeLock(boolean) ويطلق عليه في onPause وظيفة.

أعترف أن هذا أقل من مثالي ، لكن يبدو أنه يعمل بدون آثار جانبية. لقد قمت بتقديم تقرير الأخطاء إلى الوحدة ، لذلك نأمل ألا يكون هذا العمل حولك مطلوبًا لفترة طويلة.

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 بدون آثار جانبية. نأمل أن يتم إصلاح هذا بواسطة الوحدة قريبًا ولن يتطلب حل قبيح.

نصائح أخرى

ليس لدي أي خبرة من الوحدة ولكن حاول استخدام هذا http://developer.android.com/reference/android/os/powermanager.wakelock.html

لمعرفة ما إذا كانت الوحدة تجبر Wakelock بطريقة ما مع Isheld () ؛ وحاول تجاوزه ضمن نشاطك

تحرير: أنا أستخدم Wakelock عند التنزيل وهذا يجعل الشاشة سوداء ولكن لا تقفل الجهاز ، لذلك ربما يكون هذا هو الحال ، لذا حاول إطلاقه ، فقد يعطي هذا نوعًا من الصراع ولكنه يستحق دائمًا المحاولة.

هذا لم يختبر ولكن يمكنك تجربة هذا ،

في الأساس ، تريد محاولة الوصول إلى Android SDK مباشرة ، تحتوي الوحدة على بعض الفصول التي تسمح لك بذلك.

حاول كتابة فئة Java الخارجية ووضعها في مجلد الإضافات/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 البياني بحيث تقوم الوحدة بتحميل هذا النشاط بدلاً من النشاط الرئيسي ووضعه في مجلد 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>

ثم قم بإنشاء برنامج نصي 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