Unity3D Android集成Java源代码

由于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原生功能。

创建一个最简单的Android Service类

新建一个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();
    }
}

注册Android服务的package

打开\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#代码启动Android Service

由于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;
  }

猜你喜欢

转载自blog.csdn.net/qq_31042143/article/details/125241436