赞
踩
由于Java是Android的官方语言,大量原生调用和库都是基于Java语言的。而Unity3D的开发语言是C#,导致很多原生功能需要借用Jar库。
使用U3D的很多程序员对Java以及Android Studio之类的开发工具并不熟悉,一个很简单的功能也可能要耗费掉许多精力,需要大量学习以帮助熟悉Java和他的开发框架。
自从Unity3D 2018以后,这种烦恼减少了。Unity3D 2018可以直接使用Java(.java)和Kotlin(.kt)源码文件了。只要把.java或者.kt的源代码文件直接放置在Plugins目录下,Android Gradle编译系统会自动编译Jar,无需用户自己做设置。
下图为Gradle编译器自动生成的类似于Android Studio开发功能目录结构
以下提供一个最简单的Android Service框架,可以在自己的Unity3D Android工程中方便使用,扩展Android原生功能。
新建一个MainService.java文件,放置于Plugins目录下。Java类的文件命名方式和C#类类似,文件名和类名要一致。
package com.VRFab.VRXPlayer; // 调用服务的package包名前缀,此处包名全程是com.VRFab.VRXPlayer.MainService import android.app.Service; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.ComponentName; import android.app.ActivityOptions; import android.graphics.PixelFormat; import android.os.IBinder; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.provider.Settings; import android.graphics.Rect; import com.unity3d.player.UnityPlayer; import android.widget.Toast; import android.os.Build; public class MainService extends Service { // 从Service继承后台服务类(另一个类型是Activity实体窗口类) //Log用的TAG private static final String TAG = "MainService"; protected UnityPlayer mUnityPlayer; // 静态成员 public static String message = ""; public static Activity activity = null; // 静态函数 public static void StartService(Activity act) { activity = act; act.startService(new Intent(act, MainService.class)); } public static void Launch(String pkgName) { message = "Launch"; Intent LaunchIntent = new Intent(); LaunchIntent.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); ComponentName componentName = new ComponentName(pkgName, "com.unity3d.player.UnityPlayerActivity"); LaunchIntent.setComponent(componentName); LaunchIntent.setAction("android.intent.action.MAIN"); ActivityOptions ao = ActivityOptions.makeBasic(); Rect rect = new Rect(0, 0, 200, 100); ActivityOptions bounds = ao.setLaunchBounds(rect); activity.startActivity(LaunchIntent, bounds.toBundle()); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "MainService Created"); message = "MainService Created"; mUnityPlayer = new UnityPlayer(this.getApplicationContext()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } // Quit Unity @Override public void onDestroy () { super.onDestroy(); } }
打开\Assets\Plugins\Android\AndroidManifest.xml文件,添加服务注册代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">
<application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:isGame="true">
<!--activity注册-->
<activity>
<!--...-->
</activity>
<!--service注册-->
<service android:name="com.VRFab.VRXPlayer.MainService" android:enabled="true" android:exported="true">
<!--android:name和Service的package全名一致-->
</service>
</application>
</manifest>
由于C#不能直接使用Java的类型,Unity3D C#通过AndroidJavaClass和AndroidJavaObject对Java类进行包装,AndroidJavaClass是对Java类类型的引用,AndroidJavaObject是对Java类实例的引用。
通常通过AndroidJavaClass调用静态函数*(CallStatic和CallStatic<>,注意,没有返回值的函数不要用CallStatic<>调用,会报没有匹配函数错误)和静态成员(GetStatic<>/SetStatic<>)*
通过AndroidJavaObject调用成员函数*(Call和Call<>,注意,没有返回值的函数不要用Call<>调用,会报没有匹配函数错误)和属性(Get<>/Set<>)*
实际上AndroidJavaClass和AndroidJavaObject都有Call和CallStatic函数,也都有GetStatic/SetStatic和Get/Set函数,规则上有一定混乱的,最好还是按照字面意思分别用作静态函数调用和成员函数调用
AndroidJavaClass clsMainService = new AndroidJavaClass("com.VRFab.VRXBle.MainService"); // 创建MainService类型引用
AndroidJavaClass clsActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); // 创建UnityPlayer类型引用
AndroidJavaObject objActivity = clsActivity.GetStatic<AndroidJavaObject>("currentActivity"); // UnityPlayer类型调用静态成员获得UnityPlayerActivity实例引用,这是Unity3D生成App的主Activity,也是唯一Activity
clsMainService.CallStatic("StartService", objActivity); // 通过MainService类型调用Java静态成员,启动com.VRFab.VRXBle.MainService后台服务,具体启动代码见java代码
之后,我们可以在MainService中添加Java函数和代码,通过Call和CallStatic调用,帮助Unity3D C#实现Android原生功能。
比如我们可以调用MainService.Launch函数帮我们启动apk,通过java代码可以设置更多启动参数
clsMainService.CallStatic("Launch", "com.VRFab.GameApp"); // Launch代码见MainService.java
如果通过C#直接调用启动apk包,则只能通过AndroidJavaClass和AndroidJavaObject调用Java库,实现的代码比较复杂和别扭
public static XmlRequestResult OpenPackage(string pkgName) { XmlRequestResult r = new XmlRequestResult(); using (AndroidJavaClass jcPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (AndroidJavaObject joActivity = jcPlayer.GetStatic<AndroidJavaObject>("currentActivity")) { try { AndroidJavaObject Intent = new AndroidJavaObject("android.content.Intent"); AndroidJavaObject ComponentName = new AndroidJavaObject("android.content.ComponentName", pkgName, "com.unity3d.player.UnityPlayerActivity"); Intent.Call<AndroidJavaObject>("setComponent", ComponentName); Intent.Call<AndroidJavaObject>("setAction", "android.intent.action.MAIN"); joActivity.Call("startActivity", Intent); r.Code = XmlRequestResult.ExceptionCode.noerror; r.Message = "OK"; } catch (System.Exception ex) { r.Code = XmlRequestResult.ExceptionCode.unknown_exception; r.Message = "调用程序包失败: " + ex.Message; } } } return r; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。