Skip to content

Commit 072763b

Browse files
committed
add android version
1 parent 4f15d6f commit 072763b

File tree

15 files changed

+442
-116
lines changed

15 files changed

+442
-116
lines changed

README.md

+46-5
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,32 @@ using UnityEngine.UI;
3030
using UnityEngine;
3131

3232
public class NativeAPI {
33-
[DllImport("__Internal")]
34-
public static extern void sendMessageToMobileApp(string message);
33+
#if UNITY_IOS && !UNITY_EDITOR
34+
[DllImport("__Internal")]
35+
public static extern void sendMessageToMobileApp(string message);
36+
#endif
3537
}
3638

3739
public class ButtonBehavior : MonoBehaviour
3840
{
39-
public void ButtonPressed()
41+
public void ButtonPressed()
42+
{
43+
if (Application.platform == RuntimePlatform.Android)
4044
{
41-
NativeAPI.sendMessageToMobileApp("The button has been tapped!");
45+
using (AndroidJavaClass jc = new AndroidJavaClass("com.azesmwayreactnativeunity.ReactNativeUnityViewManager"))
46+
{
47+
jc.CallStatic("sendMessageToMobileApp", "The button has been tapped!");
48+
}
49+
}
50+
else if (Application.platform == RuntimePlatform.IPhonePlayer)
51+
{
52+
#if UNITY_IOS && !UNITY_EDITOR
53+
NativeAPI.sendMessageToMobileApp("The button has been tapped!");
54+
#endif
4255
}
56+
}
4357
}
58+
4459
```
4560

4661
### iOS
@@ -54,7 +69,33 @@ public class ButtonBehavior : MonoBehaviour
5469
7. In Build Phases move Embedded Frameworks before Compile Sources ( drag and drop )
5570

5671
### Android
57-
Under development...
72+
73+
1. Build Unity app to `[project_root]/unity/builds/android`
74+
2. Add the following lines to `android/settings.gradle`:
75+
```gradle
76+
include ':unityLibrary'
77+
project(':unityLibrary').projectDir=new File('..\\unity\\builds\\android\\unityLibrary')
78+
```
79+
3. Add into `android/build.gradle`
80+
```gradle
81+
allprojects {
82+
repositories {
83+
// this
84+
flatDir {
85+
dirs "${project(':unityLibrary').projectDir}/libs"
86+
}
87+
// ...
88+
```
89+
4. Add into `android/gradle.properties`
90+
```gradle
91+
unityStreamingAssets=.unity3d
92+
```
93+
5. Add strings to ``android/app/src/main/res/values/strings.xml``
94+
95+
```javascript
96+
<string name="game_view_content_description">Game view</string>
97+
```
98+
6. Remove `<intent-filter>...</intent-filter>` from ``<project_name>/unity/builds/android/unityLibrary/src/main/AndroidManifest.xml`` at unityLibrary to leave only integrated version.
5899
59100
### Usage
60101

android/build.gradle

+5-3
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ def safeExtGet(prop, fallback) {
1919
}
2020

2121
android {
22-
compileSdkVersion safeExtGet('ReactNativeUnity_compileSdkVersion', 29)
22+
compileSdkVersion safeExtGet('ReactNativeUnity_compileSdkVersion', 31)
2323
defaultConfig {
24-
minSdkVersion safeExtGet('ReactNativeUnity_minSdkVersion', 16)
25-
targetSdkVersion safeExtGet('ReactNativeUnity_targetSdkVersion', 29)
24+
minSdkVersion safeExtGet('ReactNativeUnity_minSdkVersion', 21)
25+
targetSdkVersion safeExtGet('ReactNativeUnity_targetSdkVersion', 31)
2626
versionCode 1
2727
versionName "1.0"
2828

@@ -56,4 +56,6 @@ repositories {
5656
dependencies {
5757
//noinspection GradleDynamicVersion
5858
implementation "com.facebook.react:react-native:+" // From node_modules
59+
implementation project(':unityLibrary')
60+
implementation files("${project(':unityLibrary').projectDir}/libs/unity-classes.jar")
5961
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package com.azesmwayreactnativeunity;
2+
3+
import android.annotation.SuppressLint;
4+
import android.app.Activity;
5+
import android.graphics.PixelFormat;
6+
import android.os.Build;
7+
import android.view.ViewGroup;
8+
import android.view.WindowManager;
9+
10+
import com.unity3d.player.UnityPlayer;
11+
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
12+
13+
import java.util.concurrent.CopyOnWriteArraySet;
14+
15+
public class ReactNativeUnity {
16+
private static UnityPlayer unityPlayer;
17+
private static boolean _isUnityReady;
18+
private static boolean _isUnityPaused;
19+
20+
public static UnityPlayer getPlayer() {
21+
if (!_isUnityReady) {
22+
return null;
23+
}
24+
return unityPlayer;
25+
}
26+
27+
public static boolean isUnityReady() {
28+
return _isUnityReady;
29+
}
30+
31+
public static boolean isUnityPaused() {
32+
return _isUnityPaused;
33+
}
34+
35+
public static void createPlayer(final Activity activity, final CreateCallback callback) {
36+
if (unityPlayer != null) {
37+
callback.onReady();
38+
return;
39+
}
40+
activity.runOnUiThread(new Runnable() {
41+
@Override
42+
public void run() {
43+
activity.getWindow().setFormat(PixelFormat.RGBA_8888);
44+
int flag = activity.getWindow().getAttributes().flags;
45+
boolean fullScreen = false;
46+
if ((flag & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN) {
47+
fullScreen = true;
48+
}
49+
50+
unityPlayer = new UnityPlayer(activity);
51+
52+
try {
53+
// wait a moument. fix unity cannot start when startup.
54+
Thread.sleep(1000);
55+
} catch (Exception e) {
56+
}
57+
58+
// start unity
59+
addUnityViewToBackground();
60+
unityPlayer.windowFocusChanged(true);
61+
unityPlayer.requestFocus();
62+
unityPlayer.resume();
63+
64+
// restore window layout
65+
if (!fullScreen) {
66+
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
67+
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
68+
}
69+
_isUnityReady = true;
70+
callback.onReady();
71+
}
72+
});
73+
}
74+
75+
public static void pause() {
76+
if (unityPlayer != null) {
77+
unityPlayer.pause();
78+
_isUnityPaused = true;
79+
}
80+
}
81+
82+
public static void resume() {
83+
if (unityPlayer != null) {
84+
unityPlayer.resume();
85+
_isUnityPaused = false;
86+
}
87+
}
88+
89+
public static void unload() {
90+
if (unityPlayer != null) {
91+
unityPlayer.unload();
92+
_isUnityPaused = false;
93+
}
94+
}
95+
96+
public static void addUnityViewToBackground() {
97+
if (unityPlayer == null) {
98+
return;
99+
}
100+
if (unityPlayer.getParent() != null) {
101+
((ViewGroup) unityPlayer.getParent()).removeView(unityPlayer);
102+
}
103+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
104+
unityPlayer.setZ(-1f);
105+
}
106+
final Activity activity = ((Activity) unityPlayer.getContext());
107+
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(1, 1);
108+
activity.addContentView(unityPlayer, layoutParams);
109+
}
110+
111+
public static void addUnityViewToGroup(ViewGroup group) {
112+
if (unityPlayer == null) {
113+
return;
114+
}
115+
if (unityPlayer.getParent() != null) {
116+
((ViewGroup) unityPlayer.getParent()).removeView(unityPlayer);
117+
}
118+
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT);
119+
group.addView(unityPlayer, 0, layoutParams);
120+
unityPlayer.windowFocusChanged(true);
121+
unityPlayer.requestFocus();
122+
unityPlayer.resume();
123+
}
124+
125+
public interface CreateCallback {
126+
void onReady();
127+
}
128+
}

android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnityPackage.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ public List<NativeModule> createNativeModules(ReactApplicationContext reactConte
1717

1818
@Override
1919
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
20-
return Arrays.<ViewManager>asList(new ReactNativeUnityViewManager());
20+
return Arrays.<ViewManager>asList(new ReactNativeUnityViewManager(reactContext));
2121
}
2222
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.azesmwayreactnativeunity;
2+
3+
import android.annotation.SuppressLint;
4+
import android.app.Activity;
5+
import android.content.Context;
6+
import android.content.res.Configuration;
7+
import android.os.Build;
8+
import android.os.Bundle;
9+
import android.util.Log;
10+
import android.view.LayoutInflater;
11+
import android.view.MotionEvent;
12+
import android.view.View;
13+
import android.view.ViewGroup;
14+
import android.widget.FrameLayout;
15+
import androidx.annotation.NonNull;
16+
17+
import com.facebook.react.bridge.Arguments;
18+
import com.facebook.react.bridge.ReactContext;
19+
import com.facebook.react.bridge.WritableMap;
20+
import com.facebook.react.uimanager.ThemedReactContext;
21+
import com.facebook.react.uimanager.events.RCTEventEmitter;
22+
import com.facebook.react.views.view.ReactViewGroup;
23+
import com.unity3d.player.UnityPlayer;
24+
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
25+
import java.util.Objects;
26+
27+
@SuppressLint("ViewConstructor")
28+
public class ReactNativeUnityView extends FrameLayout {
29+
private UnityPlayer view;
30+
31+
public ReactNativeUnityView(Context context) {
32+
super(context);
33+
}
34+
35+
public void setUnityPlayer(UnityPlayer player) {
36+
this.view = player;
37+
ReactNativeUnity.addUnityViewToGroup(this);
38+
}
39+
40+
@Override
41+
public void onWindowFocusChanged(boolean hasWindowFocus) {
42+
super.onWindowFocusChanged(hasWindowFocus);
43+
if (view != null) {
44+
view.windowFocusChanged(hasWindowFocus);
45+
}
46+
}
47+
48+
@Override
49+
protected void onConfigurationChanged(Configuration newConfig) {
50+
super.onConfigurationChanged(newConfig);
51+
if (view != null) {
52+
view.configurationChanged(newConfig);
53+
}
54+
}
55+
56+
@Override
57+
protected void onDetachedFromWindow() {
58+
ReactNativeUnity.addUnityViewToBackground();
59+
super.onDetachedFromWindow();
60+
}
61+
}

0 commit comments

Comments
 (0)