2015-11-06 24 views
13

Tôi đang xây dựng một ứng dụng Android bao gồm trải nghiệm tương tác 3D Unity.Android UnityPlayerActivity Action Bar

Tôi đã nhập dự án Unity vào Android Studio nhưng khi khởi chạy hoạt động là toàn màn hình và không hiển thị thanh tác vụ Android.

Làm thế nào tôi có thể làm điều này?

Integration bước

  • Tạo dự án Unity mới.
  • Xuất "Dự án Android của Google" từ Unity.
  • Nhập dự án vào Android Studio.

Solutions Đã cố gắng

  • Thay đổi chủ đề trong biểu hiện.
  • Đặt chủ đề trong lớp Java UnityPlayerActivity.
  • Ghi đè Tệp kê khai Android thống nhất bằng cách đặt tệp kê khai có chủ đề được cập nhật trong thư mục Unity/Assets/Plugins/Android.
  • Thay đổi UnityPlayerHoạt động để mở rộng AppCompatActivity. Điều này sẽ hiển thị thanh hành động nhưng có một khoảng trắng giữa nó và thanh trạng thái.
  • Đặt "Screen.fullScreen = false;" trong Unity SceneManager. Thao tác này sẽ xóa chế độ nhập vai để thanh trạng thái Android hiển thị.
  • Tắt "Thanh trạng thái bị ẩn" trong cài đặt trình phát. Xuất hiện để không có hiệu lực.
  • Bao bọc UnityPlayer trong FrameLayout. Điều này cho phép tôi thay đổi kích thước Unity thành dạng xem.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.company.unity.test" 
    android:installLocation="preferExternal" 
    android:versionCode="1" 
    android:versionName="1.0"> 

    <supports-screens 
     android:anyDensity="true" 
     android:largeScreens="true" 
     android:normalScreens="true" 
     android:smallScreens="true" 
     android:xlargeScreens="true" /> 

    <application 
     android:banner="@drawable/app_banner" 
     android:debuggable="false" 
     android:icon="@drawable/app_icon" 
     android:isGame="true" 
     android:label="@string/app_name" 
     android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> 
     <activity 
      android:name="com.company.unity.test.UnityPlayerActivity" 
      android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" 
      android:label="@string/app_name" 
      android:launchMode="singleTask" 
      android:screenOrientation="fullSensor"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
       <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> 
      </intent-filter> 
      <meta-data 
       android:name="unityplayer.UnityActivity" 
       android:value="true" /> 
     </activity> 
    </application> 

    <uses-sdk 
     android:minSdkVersion="9" 
     android:targetSdkVersion="23" /> 

    <uses-feature android:glEsVersion="0x00020000" /> 
    <uses-feature 
     android:name="android.hardware.sensor.accelerometer" 
     android:required="false" /> 
    <uses-feature 
     android:name="android.hardware.touchscreen" 
     android:required="false" /> 
    <uses-feature 
     android:name="android.hardware.touchscreen.multitouch" 
     android:required="false" /> 
    <uses-feature 
     android:name="android.hardware.touchscreen.multitouch.distinct" 
     android:required="false" /> 
</manifest> 

UnityPlayerActivity.java

package com.company.unity.test; 

import android.app.Activity; 
import android.content.res.Configuration; 
import android.graphics.PixelFormat; 
import android.os.Bundle; 
import android.view.KeyEvent; 
import android.view.MotionEvent; 
import android.view.Window; 

import com.unity3d.player.UnityPlayer; 

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

    // Setup activity layout 
    @Override protected void onCreate (Bundle savedInstanceState) 
    { 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     super.onCreate(savedInstanceState); 

     getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy 

     mUnityPlayer = new UnityPlayer(this); 
     setContentView(mUnityPlayer); 
     mUnityPlayer.requestFocus(); 
    } 

    // Quit Unity 
    @Override protected void onDestroy() 
    { 
     mUnityPlayer.quit(); 
     super.onDestroy(); 
    } 

    // Pause Unity 
    @Override protected void onPause() 
    { 
     super.onPause(); 
     mUnityPlayer.pause(); 
    } 

    // Resume Unity 
    @Override protected void onResume() 
    { 
     super.onResume(); 
     mUnityPlayer.resume(); 
    } 

    // This ensures the layout will be correct. 
    @Override public void onConfigurationChanged(Configuration newConfig) 
    { 
     super.onConfigurationChanged(newConfig); 
     mUnityPlayer.configurationChanged(newConfig); 
    } 

    // Notify Unity of the focus change. 
    @Override public void onWindowFocusChanged(boolean hasFocus) 
    { 
     super.onWindowFocusChanged(hasFocus); 
     mUnityPlayer.windowFocusChanged(hasFocus); 
    } 

    // For some reason the multiple keyevent type is not supported by the ndk. 
    // Force event injection by overriding dispatchKeyEvent(). 
    @Override public boolean dispatchKeyEvent(KeyEvent event) 
    { 
     if (event.getAction() == KeyEvent.ACTION_MULTIPLE) 
      return mUnityPlayer.injectEvent(event); 
     return super.dispatchKeyEvent(event); 
    } 

    // Pass any events not handled by (unfocused) views straight to UnityPlayer 
    @Override public boolean onKeyUp(int keyCode, KeyEvent event)  { return mUnityPlayer.injectEvent(event); } 
    @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); } 
    @Override public boolean onTouchEvent(MotionEvent event)   { return mUnityPlayer.injectEvent(event); } 
    /*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } 
} 
+0

Tôi đã viết bạn đã thay đổi chủ đề trong tệp kê khai nhưng trong ví dụ: có @android: style/Theme.NoTitleBar.Fullscreen. Đây có phải là chủ đề bạn đã thay đổi không? Nếu không thì nó là gì? – Lingviston

+0

@Lingviston Mã tôi đăng hiển thị tích hợp ban đầu. Tôi đã thử thay đổi chủ đề thành 'android: theme =" @ android: style/Theme.Material.Light.DarkActionBar "' trên cả thẻ ứng dụng và hoạt động nhưng không thể hiển thị thanh hành động. – Morepork

+0

@Morepork bạn đã tìm thấy giải pháp chưa? – Piotr

Trả lời

4

Tôi nghĩ rằng tôi đã tìm thấy giải pháp.
Change lót:

mUnityPlayer = new UnityPlayer(this); 

nên nó tạo ra UnityPlayer lớp con của riêng mình, trong đó sẽ ghi đè setFullscreen phương pháp (chút hacky):

public class UnityPlayerWrapper extends UnityPlayer { 
    public UnityPlayerWrapper(ContextWrapper contextWrapper) { 
     super(contextWrapper); 
    } 

    @Override 
    protected void setFullscreen(boolean b) { 
     super.setFullscreen(false); 
    } 
} 

Bên cạnh đó, hãy loại bỏ dòng đó: requestWindowFeature(Window.FEATURE_NO_TITLE);

+0

Tôi đã thử điều này trong dự án của mình nhưng tôi không thấy thanh hành động. Thử nghiệm trên Samsung Galaxy S6 chạy Android 5.1 .1. – Morepork

+0

bạn cũng vô hiệu hóa dòng đó - requestWindowFeature (Window.FEATURE_NO_TITLE);? – Piotr

+1

Làm việc sau khi tắt tính năng không có tiêu đề. Cảm ơn @Piotr. – Morepork

6

cho Unity phiên bản 5.5 cách tốt nhất để tránh chế độ nhập vai trong Android là truyền trong constructor không phải là Activity nhưng để cast ApplicationContext vào Context Context.

mUnityPlayer = new UnityPlayer((ContextWrapper) getApplicationContext()); 

đó làm việc vì trong UnityPlayer.class obfuscated (trong đoàn kết-classes.jar) có một tấm séc sơ thẩm.

private void h() { 
    if(this.h instanceof Activity) { 
     ((Activity)this.h).getWindow().setFlags(1024, 1024); 
    } 
} 

Vì vậy, nếu đó không phải là Hoạt động, UnityPlayer.class không đặt cờ.

+0

nó hiển thị thanh công cụ ngay bây giờ sau khi thay đổi thành ContextWrapper.Nhưng vấn đề là bây giờ máy ảnh xem không hiển thị.Bạn có thể vui lòng đưa ra một số gợi ý ? –

+0

Bạn có thể sử dụng các hàm mở rộng kotlin để ghi đè phương pháp này không? –

+0

Vô tình không phải là sở hữu e để ghi đè phương thức đó, vì là riêng tư. Bạn có thể làm với một giải pháp bẩn: sử dụng sự phản chiếu. –

0

Piotr câu trả lời đang làm việc cho phiên bản cũ và Lorenzo DM của câu trả lời cũng hợp lệ nhưng

mUnityPlayer = new UnityPlayer((ContextWrapper) getApplicationContext());

không làm việc trong một số thiết bị. Vì vậy, cuối cùng tôi đã sửa đổi UnityPlayerActivity ở đây là giải pháp mới



public class UnityPlayerActivity extends AppCompatActivity 
{ 
    protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code 
    ActionBar actionBar; 
    private Toolbar toolbar; 
    private FrameLayout unityContainer; 

    // Setup activity layout 
    @Override protected void onCreate (Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     mUnityPlayer = new UnityPlayer(this); 
     setContentView(R.layout.activity_unity_player); 
     mappingWidgets(); 
     init(); 

    } 

    void mappingWidgets(){ 
     toolbar = (Toolbar) findViewById(R.id.toolbar); 
     unityContainer = (FrameLayout) findViewById(R.id.unity_container); 
     FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); 
     unityContainer.addView(mUnityPlayer.getView(), 0, layoutParams); 
     mUnityPlayer.requestFocus(); 

    } 
    void init(){ 
     setSupportActionBar(toolbar); 
     actionBar = getSupportActionBar(); 
     if (actionBar != null) 
      actionBar.setDisplayHomeAsUpEnabled(true); 
     toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       finish(); 
       onDestroy(); 
      } 
     }); 
     setTitle(getString(R.string.app_name)); 


    } 


    @Override protected void onNewIntent(Intent intent) 
    { 
     setIntent(intent); 
    } 

    // Quit Unity 
    @Override protected void onDestroy() 
    { 
     mUnityPlayer.quit(); 
     super.onDestroy(); 
    } 

    // Pause Unity 
    @Override protected void onPause() 
    { 
     super.onPause(); 
     mUnityPlayer.pause(); 
    } 

    // Resume Unity 
    @Override protected void onResume() 
    { 
     super.onResume(); 
     mUnityPlayer.resume(); 
    } 

    // Low Memory Unity 
    @Override public void onLowMemory() 
    { 
     super.onLowMemory(); 
     mUnityPlayer.lowMemory(); 
    } 

    // Trim Memory Unity 
    @Override public void onTrimMemory(int level) 
    { 
     super.onTrimMemory(level); 
     if (level == TRIM_MEMORY_RUNNING_CRITICAL) 
     { 
      mUnityPlayer.lowMemory(); 
     } 
    } 

    // This ensures the layout will be correct. 
    @Override public void onConfigurationChanged(Configuration newConfig) 
    { 
     super.onConfigurationChanged(newConfig); 
     mUnityPlayer.configurationChanged(newConfig); 
    } 

    // Notify Unity of the focus change. 
    @Override public void onWindowFocusChanged(boolean hasFocus) 
    { 
     super.onWindowFocusChanged(hasFocus); 
     mUnityPlayer.windowFocusChanged(hasFocus); 
    } 

    // For some reason the multiple keyevent type is not supported by the ndk. 
    // Force event injection by overriding dispatchKeyEvent(). 
    @Override public boolean dispatchKeyEvent(KeyEvent event) 
    { 
     if (event.getAction() == KeyEvent.ACTION_MULTIPLE) 
      return mUnityPlayer.injectEvent(event); 
     return super.dispatchKeyEvent(event); 
    } 

    // Pass any events not handled by (unfocused) views straight to UnityPlayer 
    //@Override public boolean onKeyUp(int keyCode, KeyEvent event)  { return mUnityPlayer.injectEvent(event); } 
    // Pass any events not handled by (unfocused) views straight to UnityPlayer 
    @Override public boolean onKeyUp(int keyCode, KeyEvent event)  { 
     if(keyCode == KeyEvent.KEYCODE_BACK) { 
      finish(); 
      onDestroy(); 
      return true; 
     } 
     return mUnityPlayer.injectEvent(event); } 
    @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); } 
    @Override public boolean onTouchEvent(MotionEvent event)   { return mUnityPlayer.injectEvent(event); } 
    /*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } 
} 
Các vấn đề liên quan