引言

通常一款游戏开发到后期,一般都会涉及到第三方SDK的接入与集成

对于不熟悉SDK接入的同学来说,接SDK每次都是云里雾里,
而熟悉SDK接入的同学又觉得不断地重复做接入SDK工作这样没有成就感,太尼玛无聊了(Android渠道一弄就十几个,直接吐血)。

概述

其实通常情况下接入SDK都是很简单的一个过程,这边记录一下自己学习接入ShareSDK的过程。

  1. 创建Android工程,编写代码,导出Android项目为Jar包供Unity调用
  2. Unity端工程调用jar的接口,实现unity调用java函数
  3. 打包测试调用结果

实践

一、创建Android工程(Android Studio)

注意包名要和unity的包名一致




Unity 安卓端和UI交互 unity和安卓sdk的交互_接sdk


Unity 安卓端和UI交互 unity和安卓sdk的交互_Android_02


二、导入Classes.jar包到Android工程中

Unity和Android做交互,他们两个之间不认识肯定,没法直接通信,因此需要一个中间的搭桥牵线的人,Classes.jar就起到了这个作用。
Classes.jar是由Unity提供给我们的,我们需要找到它并且引入到我们的Android项目中。Claess.jar的路径一般如下
如果用MONO:Unity5.6.6EditorDataPlaybackEnginesandroidplayerVariationsmonoReleaseClasses
如果用il2cpp:Unity5.6.6EditorDataPlaybackEnginesandroidplayerVariationsil2cppReleaseClasses

我们找到它直接拖到我们的Android工程的libs目录下。


Unity 安卓端和UI交互 unity和安卓sdk的交互_android_03


关键一步:右键-Add as Library,导入成功就可以开始编写代码了

三、编写Android端的代码

  我们在Android端编写一些代码,提供一些接口来供Unity一会的调用。


Unity 安卓端和UI交互 unity和安卓sdk的交互_Android_04


打开我们的MainActivity.java,然后添加代码。需要注意的是,让我们的MainActivity继承Jar包中的UnityPlayerActivity类,这样,Unity才能调的到

还需要把 setContentView(R.layout.activity_main); 这段代码注释掉,要不然会显示Android的默认布局文件,上面就一个 Hello World。


package com.Aver3.Snake;

import com.unity3d.player.UnityPlayerActivity;
import com.unity3d.player.UnityPlayer;
import android.os.Bundle;

public class MainActivity extends UnityPlayerActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_main); 注释掉 不显示View
    }

    //供U3D调用的方法
    public int Add(int x,int y){
        return x + y;
    }

//    Android调用Unity的方法
    public void JavaCallUnityFunc(){
        String str="Android Call Unity.";
        String UnityClass="Canvas";
        String UnityMethod="ForJavaCallFunc";
        //参数1:unity脚本挂载的gameobject   参数2:方法名   参数3:要传递的参数
        UnityPlayer.UnitySendMessage(UnityClass, UnityMethod, str);
    }
}


四、导出Android项目为Jar包

  1. 修改build.gradle模块文件


Unity 安卓端和UI交互 unity和安卓sdk的交互_Android_05


//apply plugin: 'com.android.application'
apply plugin: 'com.android.library' //说明是Library模块

android {
    compileSdkVersion 28
    defaultConfig {
//      applicationId "com.Aver3.Snake"
        minSdkVersion 17
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
    buildTypes {
        release {
            //混淆
            minifyEnabled false
            //加载默认混淆配置文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    lintOptions {
        abortOnError false
    }

    dexOptions {
        javaMaxHeapSize "4g"
    }
}

//删除build.gradle里的依赖     
//这里要删的话,导出前删,否者会XML配置会报错
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation files('libs/classes.jar')
}

task makeJar(type: Copy) {
    delete 'build/libs/mysdk.jar'                           //删除旧的Jar包
    from('build/intermediates/intermediate-jars/release')   //从该地址复制
    into('build/libs/')                                     //复制到该地址
    include('classes.jar')                                  //包含文件
    rename ('classes.jar', 'mysdk.jar')                     //重命名
}

makeJar.dependsOn(build)


2. 删除单元测试

删除androidTest和Test


Unity 安卓端和UI交互 unity和安卓sdk的交互_jar_06


3. 删除布局文件

删除activity_main.xml


Unity 安卓端和UI交互 unity和安卓sdk的交互_Android_07


4. 忘记有没有改AndroidManifest.xml文件了,也附上


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.Aver3.Snake"
    android:installLocation="auto">

    <application
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
                  android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


5. 同步gradle


Unity 安卓端和UI交互 unity和安卓sdk的交互_android_08


6. 运行makeJar 任务


Unity 安卓端和UI交互 unity和安卓sdk的交互_接sdk_09


可以直接输入makeJar搜索,找到后双击运行这个任务,第一次运行需要下载一些依赖,可能需要一会儿,运行结束,jar就打好了。


Unity 安卓端和UI交互 unity和安卓sdk的交互_android_10


Unity 安卓端和UI交互 unity和安卓sdk的交互_android_11


五、导入 Unity

  1. 将生成的jar和AndroidManifest.xml导入unity 工程的 Asset/Plugins/Android/ 目录下。没有的话就手动创建目录。


Unity 安卓端和UI交互 unity和安卓sdk的交互_android_12


2. 修改AndroidManifest.xml文件


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.Aver3.Snake">

    <application
        android:theme="@style/UnityThemeSelector"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name">
        android:theme="@style/UnityThemeSelector">
        <activity android:name="com.Aver3.Snake.MainActivity"
                  android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
    </application>
</manifest>


六、unity和Jar交互

  1. unity调用jar
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
  string message = "this is my title";
  string body = "this is my content";
  jo.Call("ShareText", message, body);


unity 中调用 android 层的接口基本都是通过 AndroidJavaClass 、AndroidJavaObject 的方式。

2. jar调用unity


//参数1:unity脚本挂载的gameobject   参数2:方法名   参数3:要传递的参数
UnityPlayer.UnitySendMessage("headImage","AndroidSaveHeadImageOver","headImage.png");


例子:


using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    public Button btn1;
    public Button btn2;
    public Text logText;
    private void Start()
    {
        btn1.onClick.AddListener(TestCallJavaFunc);
        btn2.onClick.AddListener(TestFromJavaCallUnityFunc);

        logText.text = "Start";
    }

    private const string JAVA_CLASS_Name = "com.unity3d.player.UnityPlayer";
    private void CallJavaFunc(string javaFuncName, params object[] args)
    {
        try
        {
            //获取到AndroidJavaClass,至于这里为什么调用这个类,我也不是很清楚
            //获取unity的Java类,只能调用静态方法,获取静态属性
            using(AndroidJavaClass jc = new AndroidJavaClass(JAVA_CLASS_Name))
            {
                //获取到Activity
                using(AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))
                {
                    //调用Java方法
                    jo.Call(javaFuncName, args);
                }
            }
        }
        catch(System.Exception ex)
        {
            Debug.Log("callSdk error:" + ex.Message);
        }
    }

    void TestCallJavaFunc()
    {
        try
        {
            AndroidJavaClass javaVM = new AndroidJavaClass(JAVA_CLASS_Name);
            AndroidJavaObject currentActivity = javaVM.GetStatic<AndroidJavaObject>("currentActivity");
            int result = currentActivity.Call<int>("Add", 1999, 1);
            logText.text = "Call Java Func :Add ,rusult:" + result.ToString();
        }
        catch(System.Exception ex)
        {
            Debug.LogError("Call Sdk Error:" + ex.Message);
            logText.text = ex.Message;
            throw;
        }
    }

    public void ForJavaCallFunc(string str)
    {
        logText.text = str;
    }

    public void TestFromJavaCallUnityFunc()
    {
        CallJavaFunc("JavaCallUnityFunc");
    }
}


七、打包测试

打包也是很多坑

sdk版本不匹配啊 Unity编译时找不到AndroidSDK的问题 | Unable to list target platforms

AndroidManifest.xml的包名和unity包名不匹配会闪退啊,各种坑,一脚一个深。

整了好久,终于可以互相调用了

理解了基本原理,下面接一个简单的分享链接的shareSDK测试一下是否能用。


Unity 安卓端和UI交互 unity和安卓sdk的交互_Android_13


Unity 安卓端和UI交互 unity和安卓sdk的交互_Android_14


AS导出具体流程: Android Studio 如何导出 Jar 给 Unity 使用

Classes.jar 介绍: Extending the UnityPlayerActivity Java Code