错误管理UnityPlayer生命周期中的一个原生的Andr​​oid应用 [英] Errors managing the UnityPlayer lifecycle in a native android application

查看:3047
本文介绍了错误管理UnityPlayer生命周期中的一个原生的Andr​​oid应用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个Android应用程序,需要在activiy加载UnityPlayer例如,使用code从下面的论坛帖子作为指导:

I am working on an android app that needs to load a UnityPlayer instance in an activiy, using code from the following forum post as a guide:

<一个href="http://forum.unity3d.com/threads/98315-Using-Unity-Android-In-a-Sub-View">http://forum.unity3d.com/threads/98315-Using-Unity-Android-In-a-Sub-View

最初的应用程序正常显示UnityPlayer称为UnityActivity.java的活动中。

Initially the application is correctly displaying the UnityPlayer inside an activity called "UnityActivity.java".

这个问题开始,当用户返回到MainActivity(通过pressing硬件后退按钮或点击动作条后退按钮),然后尝试重新打开UnityActivity - 在这种情况下,一个黑色的屏幕示出,而不是UnityPlayer。在论坛的用户建议转发的onPause和onResume生命周期事件的UnityPlayer,如在code波纹管。如果这样做,但是,下面的错误出现和应用程序崩溃。

The problem starts when the user navigates back to the MainActivity (by either pressing the hardware back button or clicking on the ActionBar back button) and then tries to re-open the UnityActivity - in which case a black screen is shown instead of the UnityPlayer. A user in the forums suggested forwarding the onPause and onResume lifecycle events to the UnityPlayer, as shown in the code bellow. When doing that, however, the following errors show up and the app crashes.

这是导航到UnityActivity当第一次登录:

This is logged when navigating to the UnityActivity for the first time:

W /的libc(21095):在pthread_create sched_setscheduler调用失败:操作不允许

时,单击后退按钮时,记录此错误:

This error is logged when clicking the back button:

W /编舞(20963):已经有一个悬而未决垂直同步事件。应该只有一次。

导航到UnityActivity时,第二次将记录此错误:

This error is logged when navigating to the UnityActivity for the second time:

A /的libc(21095):为00000000(code = 1),螺纹致命的信号11(SIGSEGV)21176(螺纹5073)

......此时我被踢出了应用程序。

...at which point I get kicked out of the application.

这是主要的活动 MainActivity.java 的摘录:

This is an excerpt of the main activity MainActivity.java :

public void startUnityActivity(View view) {
        Intent intent = new Intent(this, UnityActivity.class);
    startActivity(intent);
}

这是统一的活动 UnityActivity.java 的摘录:

This is an excerpt of the Unity activity UnityActivity.java :

public class UnityActivity extends ActionBarActivity {
    UnityPlayer m_UnityPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

         setContentView(R.layout.activity_unity);

        m_UnityPlayer = new UnityPlayer(this);
        int glesMode = m_UnityPlayer.getSettings().getInt("gles_mode", 1);
        m_UnityPlayer.init(glesMode, false);

        FrameLayout layout = (FrameLayout) findViewById(R.id.unityView);
        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        layout.addView(m_UnityPlayer, 0, lp);
        m_UnityPlayer.windowFocusChanged(true);
        m_UnityPlayer.resume();
    }
    @Override
    public void onWindowFocusChanged(boolean hasFocus)
    {
        super.onWindowFocusChanged(hasFocus);
        m_UnityPlayer.windowFocusChanged(hasFocus);
    }
    @Override
    public void onPause() {
         super.onPause();  
         m_UnityPlayer.pause();
    }
    @Override
    public void onResume() {
        super.onResume(); 
        m_UnityPlayer.resume();
    }

这是该活动如何在清单中描述的 ../ AndroidManifest.xml中

This is how the activities are described in the manifest ../AndroidManifest.xml:

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.package.example.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>
    <activity 
        android:name="com.package.example.UnityActivity" 
        android:label="@string/title_activity_unity" 
        android:screenOrientation="portrait" 
        android:launchMode="singleTask" 
        android:parentActivityName="com.package.example.MainActivity"
        android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale">
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
      <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />
    </activity>
</application>

这是怎么UnityActivity布局定义 ../ RES /布局/ activity_unity.xml

This is how the layout of the UnityActivity is defined ../res/layout/activity_unity.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.package.example.UnityActivity"
tools:ignore="MergeRootFrame" >
    <FrameLayout
    android:id="@+id/unityView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    </FrameLayout>
</FrameLayout>

我会很感激任何提示和解决方案,为我指明了正确的方向。

I'd be thankful for any tips and solutions pointing me in the right direction.

推荐答案

好了,先易后难

W/libc(21095): pthread_create sched_setscheduler call failed: Operation not permitted

还有就是你可以做些什么。您还可以得到这个当您直接从统一为Android编译,所以它的发动机内的一个问题。

There is nothing you can do about it. You even get this when you compile directly from Unity for Android, so it's a problem inside the engine.

您链接的指南是pretty的过时。您不再需要从不同位置的文件复制到创建一个简单的Andr​​oid项目。

The guide you linked is pretty outdated. You no longer need to copy files from various locations to create a simple Android project.

  1. 通过设置创建一个Android项目构建设置 - &GT; Android的 - &GT;谷歌Android项目
  2. 您现在有一个完整的包准备导入Eclipse或Android工作室
  3. 在编译和部署

在您新的Andr​​oid项目类 UnityPlayerNativeActivity 向您介绍如何设置 UnityPlayer ,你需要什么样的事件前锋。下面是使用统一4.3.4版本

Using UnityPlayer in a subactivity

The class UnityPlayerNativeActivity in your new Android project shows you how to setup the UnityPlayer and what events you need to forward. Here is the version used by Unity 4.3.4

package de.leosori.NativeAndroid;

import com.unity3d.player.*;
import android.app.NativeActivity;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class UnityPlayerNativeActivity extends NativeActivity
{
    protected UnityPlayer mUnityPlayer;     // don't change the name of this variable; referenced from native code

    // UnityPlayer.init() should be called before attaching the view to a layout - it will load the native code.
    // UnityPlayer.quit() should be the last thing called - it will unload the native code.
    protected void onCreate (Bundle savedInstanceState)
    {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);

        getWindow().takeSurface(null);
        setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
        getWindow().setFormat(PixelFormat.RGB_565);

        mUnityPlayer = new UnityPlayer(this);
        if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
            getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
                                   WindowManager.LayoutParams.FLAG_FULLSCREEN);

        int glesMode = mUnityPlayer.getSettings().getInt("gles_mode", 1);
        boolean trueColor8888 = false;
        mUnityPlayer.init(glesMode, trueColor8888);

        View playerView = mUnityPlayer.getView();
        setContentView(playerView);
        playerView.requestFocus();
    }
    protected void onDestroy ()
    {
        mUnityPlayer.quit();
        super.onDestroy();
    }

    // onPause()/onResume() must be sent to UnityPlayer to enable pause and resource recreation on resume.
    protected void onPause()
    {
        super.onPause();
        mUnityPlayer.pause();
    }
    protected void onResume()
    {
        super.onResume();
        mUnityPlayer.resume();
    }
    public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        mUnityPlayer.configurationChanged(newConfig);
    }
    public void onWindowFocusChanged(boolean hasFocus)
    {
        super.onWindowFocusChanged(hasFocus);
        mUnityPlayer.windowFocusChanged(hasFocus);
    }
    public boolean dispatchKeyEvent(KeyEvent event)
    {
        if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
            return mUnityPlayer.onKeyMultiple(event.getKeyCode(), event.getRepeatCount(), event);
        return super.dispatchKeyEvent(event);
    }
}

尽管 UnityPlayerNativeActivity 延伸 NativeActivity的,你仍然可以从 ActionBarActivity 不代替任何问题,据我可以告诉。至少它在我的实验工作。

Although UnityPlayerNativeActivity extends NativeActivity you can still extend from ActionBarActivity instead without any problems as far as I can tell. At least it worked during my experiments.

你错过了最重要的部分是在的onDestroy调用 mUnityPlayer.quit()()。力图打造的新实例 UnityPlayer ,而旧的仍然在运行会导致死机,挂活动和无尽的痛苦。

The most important part you are missing is the call to mUnityPlayer.quit() during onDestroy(). Trying to create a new instance of UnityPlayer while the old one is still running will lead to crashes, hanging activities and endless suffering.

固定,你可能会惊讶,现在你的整个应用程序时,你从你的 UnityActivity 返回干脆关闭。 mUnityPlayer.quit()将杀死它里面运行的进程。没有一个方法调用 mUnityPlayer.quit(),连的onDestroy()方法完成后执行。

Fixing that you may be surprised that now your whole App simply closes when you return from your UnityActivity. mUnityPlayer.quit() will kill the process it is running inside. Not a single method will execute after calling mUnityPlayer.quit(), not even the onDestroy() method will finish.

制胜之道是开始你的 UnityActivity 通过添加参数<一个新的进程href="http://developer.android.com/guide/topics/manifest/activity-element.html#proc"><$c$c>android:process=":UnityKillsMe您activty在你的的Andr​​oidManifest.xml

The path to victory is to start your UnityActivity as a new process by adding the parameter android:process=":UnityKillsMe to your activty inside your AndroidManifest.xml.

在你的情况是这样的

<activity 
    android:name="com.package.example.UnityActivity" 
    android:label="@string/title_activity_unity" 
    android:screenOrientation="portrait" 
    android:launchMode="singleTask" 
    android:process=":UnityKillsMe"
    android:parentActivityName="com.package.example.MainActivity"
    android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale">
    <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
</activity>

我不知道有关参数 unityplayer.ForwardNativeEventsToDalvik ...在一开始创建的项目将其设置为官(过时)文档提到

I'm not sure about the parameter unityplayer.ForwardNativeEventsToDalvik... The project created in the beginning sets it to false and the official (outdated) documentation mentions

由于触摸/移动事件在当地code处理,Java的意见通常不会看到这些事件。然而,有,在统一的转发机制,允许将事件传播到DalvikVM

Since touch/motion events are processed in native code, Java views would normally not see those events. There is, however, a forwarding mechanism in Unity which allows events to be propagated to the DalvikVM.

在我的小例子项目中,我看不出有差别

In my small example project I could not see a difference

您需要找到一个工作流程,以开发具有统一的Andr​​oid项目,反之亦然整合。使用Unity再次导出将与你在你的Andr​​oid项目所做的更改发生冲突,所以你需要导出到一个单独的文件夹,并链接到统一的部分从您的Andr​​oid项目。

You need to find a workflow to integrate your development with Unity with the Android project or vice versa. Exporting again with Unity would conflict with the changes you made in your Android project, so you would need to export into a separate folder and link to the Unity part from your Android project.

根据上述文档您可以整合你的Andr​​oid编译的类和<$ C C>的Andr​​oidManifest.xml $以插件形式进入统一。

According to the aforementioned documentation you may be able to integrate your compiled Android classes and AndroidManifest.xml as plugins into Unity.

将所得的.class文件(S)应该是玉米pressed成.jar文件和放置在资产 - >插件 - >机器人夹。由于清单使然启动它这活动也需要创建一个新的Andr​​oidManifest.xml。 AndroidManifest.xml文件应该也放置在资产 - >插件 - >机器人夹

The resulting .class file(s) should be compressed into a .jar file and placed in the Assets->Plugins->Android folder. Since the manifest dictates which activity to launch it is also necessary to create a new AndroidManifest.xml. The AndroidManifest.xml file should also be placed in the Assets->Plugins->Android folder.

祝你好运!

这篇关于错误管理UnityPlayer生命周期中的一个原生的Andr​​oid应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆