I’ve searched online for similar questions, and while I’ve found several similar questions, none had reliable answers, which is why I’m posting here.
When the Unity3D project is compiled for Android, it basically just gives the scene as an Activity that you can start/end/etc. I want to change this Activity into a Fragment in order to display it as a tab inside a navigation drawer, and as a sub-view inside another fragment/activity.
So basically I had a MainActivity
with an Open button, and a UnityPlayerNativeActivity
which is the actual Unity3D project.
I searched how to change a general activity to a fragment, and changed the UnityPlayerNativeActivity
to match. For example, in the newly-titled UnityPlayerNativeFragment
below (with comments reflecting what exactly was changed from before):
import com.unity3d.player.UnityPlayer;
// Other imports available in full code linked to below
public class UnityPlayerNativeFragment extends Fragment
{
// Changes in this class:
// 1- 'this' references changed to "getActivity()"
// 2- onCreate -> onCreateView
// 3- protected -> public in function names
// 4- @Override added before function calls
// 5- newInstance and onAttach added
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
private static final String ARG_SECTION_NUMBER = "section_number";
public static UnityPlayerNativeFragment newInstance(int sectionNumber) {
UnityPlayerNativeFragment fragment = new UnityPlayerNativeFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((HomeActivity) activity).onSectionAttached(
getArguments().getInt(ARG_SECTION_NUMBER));
}
// 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.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
//below line removed because it was causing errors
//getActivity().requestWindowFeature(Window.FEATURE_NO_TITLE);
getActivity().getWindow().takeSurface(null);
getActivity().setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
getActivity().getWindow().setFormat(PixelFormat.RGB_565);
mUnityPlayer = new UnityPlayer(getActivity());
if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
getActivity().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();
return playerView;
}
@Override
public void onDestroy ()
{
mUnityPlayer.quit();
super.onDestroy();
}
// onPause()/onResume() must be sent to UnityPlayer to enable pause and resource recreation on resume.
@Override
public void onPause()
{
super.onPause();
mUnityPlayer.pause();
}
@Override
public void onResume()
{
super.onResume();
mUnityPlayer.resume();
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
}
The AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.SamerBekhazi.Test" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@style/AppTheme" android:icon="@drawable/app_icon" android:label="@string/app_name">
<activity android:launchMode="singleTask" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:screenOrientation="portrait" android:name=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
</activity>
</application>
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
<uses-feature android:glEsVersion="0x00020000" />
</manifest>
I only included those 2 files here because I figure the problem is from one or the other. The full code is downloadable here. Extract/Import into Android Studio - you may need to press Sync Project with Gradle Files
once for it to work.
The rest of the project is based on the Navigation Drawer Activity
project that Android Studio auto-creates for you when creating a new project. I basically just call a newInstance
of the above UnityPlayerNativeFragment
when its corresponding icon is pressed in the NavigationDrawer
.
What results when I press the tab for the scene: A black screen, with the Action Bar showing still, but nothing else. The top-right “Settings” button is still press-able, as is the Navigation Drawer button, but when one presses another tab on the Navigation Drawer, the entire app freezes and you have to force exit. I think the latter issue is because you can’t close a UnityPlayer
that hasn’t opened properly, so the main issue is in actually making the UnityPlayer
open up properly inside the Fragment. The rest of the app (the other tabs) work fine. I tried several variations (everything I could think of) in the above code and AndroidManifest.xml
file, but nothing worked.
Logcat doesn’t show any errors, it just says:
11-11 21:22:19.681 29280-29280/com.Bekhazi.Bouncy_Ball W/linker﹕ libmain.so has text relocations. This is wasting memory and is a security risk. Please fix.
11-11 21:22:19.681 29280-29280/com.Bekhazi.Bouncy_Ball D/dalvikvm﹕ Added shared lib /data/app-lib/com.Bekhazi.Bouncy_Ball-2/libmain.so 0x42d64cd8
11-11 21:22:19.691 29280-29280/com.Bekhazi.Bouncy_Ball W/linker﹕ libmono.so has text relocations. This is wasting memory and is a security risk. Please fix.
11-11 21:22:19.691 29280-29280/com.Bekhazi.Bouncy_Ball W/linker﹕ libunity.so has text relocations. This is wasting memory and is a security risk. Please fix.
What exactly is wrong here? The target build is for Android 5.0 and I’m using Android Studio 0.8.14.
Worth noting: I was able to successfully load the scene onto my Nexus 5 when it was an Activity.