本案例使用的AndroidStudio版本为
171.4408382
Unity版本为
5.2.4f1
本案例可以达到的效果为,Unity和安卓交互,互传消息,并且只适合Unity项目中仅有一种sdk的情况下使用,当项目中有多个SDK需要合并的时候,请查看本人的另一篇文章
https://blog.csdn.net/weixin_43271060/article/details/90370009
项目开始
一、创建安卓项目,并进行编译
1、点击如上图所示Start a new Android Studio project 创建Android项目,因为我们要制作的是Unity中可以使用的插件,所以,我们最终需要导出Unity可以使用的.jar格式的文件
2、选择安卓版本
3、添加一个类到Mobile中,我们选择一个空的Axtivity类就可以了
4、点击Finish
5、等待AndroidStudio进行编译
6、编译完成后会报如下图所示错误
7、点击左边build.gradle
8、解决此报错,将版本26改为27,
修改完后的build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "app.cientx.com.unitywithandroid"
minSdkVersion 14
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
改完后点击右上角SyncNow,AndroidStudio会自动进行编译,等待编译完成
9、一般来说,我们都不管第一个Module,需要重新创建一个新的Module,点击菜单中File->New->NewModule
10、选择第二个AndroidLibrary
11、编辑ModuleName和PackageName
其中 Module name 有意义即可
Package name需要和Unity项目中的包名保持一致
点击Finish后等待编译完成
然后就报了这样的错,这种错应该是sdk版本中没有Android2.3的版本,需要我再在sdk中加入2.3的版本
12、解决SDK版本中没有2.3的版本的问题
点击Apply后AndroidStudio会自动下载
发现还有报同样的错误,然后我们将新建Module的build.gradle中的minSdkVersion改为14,最后点击右上角的SyncNow后等待重新编译,编译完成后便没有错误了
13、在我们新建的Module的包名的位置上右键新建一个空的Activity
在弹出的弹框中点击Finish
二、编写Java代码
1、因为我们最终是在Unity中使用的,所以需要我们引入Unity内置的classes.jar包,包的路径位置Unity的安装目录下
Unity\Editor\Data\PlaybackEngines\androidplayer\Variations\mono\Release\Classes\classes.jar
2、选中classes.jar包,选择复制,然后在此目录下选择Paste或者Ctrl+V
点击ok
3、选中我们新建的Module
右键Open Module Settings
选择如下
4、选择我们要引入的jar包,并点击ok,我们就可以将classes.jar包引入到AndroidStudio中,供我们调用了
5、设置我们新建的MainActivity,因为不需要JAVA中的视图,所以需要注释掉设置视图的代码
package com.android.anplugin;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
}
}
6、让MainActivity继承自UnityPlayerActivity
package com.android.anplugin;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
}
}
7、Android Studio格式化代码快捷键 Ctrl+Alt+L
8、在类中添加Unity要调用的函数
package com.android.anplugin;
import android.os.Bundle;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
}
public static void TestStatic() {
UnityPlayer.UnitySendMessage("NetLogic","Test1Call","调用了StaticTest1");
}
public void TestNoStatic(String res) {
UnityPlayer.UnitySendMessage("NetLogic","Test12Call","调用了Test2:"+res);
}
public int TestReturn(int[] res) {
int num1 = res[0];
int num2 = res[1];
return num1 * num2;
}
}
9、编写AndroidManifest.xml文件
原有的.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.anplugin">
<application>
<activity android:name=".MainActivity"></activity>
</application>
</manifest>
将我们第一个Module app 中的AndroidManifest.xml中Activity签名的内容复制到新建的Module中
app Module
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.cientx.com.unitywithandroid">
<application
android:allowBackup="true"
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">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
复制后的.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.anplugin">
<application>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
我们在AndroidManifest.xml中添加一些权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.anplugin">
<!--访问网络连接,可能产生GPRS流量-->
<uses-permission android:name="android.permission.INTERNET"/>
<application>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
三、添加Android签名
正式发布安卓应用是需要获取安卓应用签名的
1、获取Android应用的签名文件
2、创建签名文件
点击Create new
Key store path : 签名文件路径
Password : 签名密码
Confirm : 确认密码
Alias : 别名
Validity ( years ) : 有限期 (年)
First and Last Name : 全名
Organizational Unit : 组织单位
Organization : 组织
City or Locality : 城市或地方
State or Province : 州或省
Country Code(XX) : 国家代码
填完后点击ok
点击Next
APK Destination Folder : apk目标文件夹
Build Type : 构建类型
release是发布版本用的签名文件
debug是debug用的签名文件
BuildType选择release
Signature Versions 签名版本选择V1(Jar Signature)
点击Finish
等待编译完成
3、配置gradle,让app自动签名
点击ok等待编译完成
此时我们新建的Module的build.gradle中便会出现如下所示签名文件的配置信息
signingConfigs {
config {
keyAlias 'release.keystore'
keyPassword '1234567'
storeFile file('E:/Andriod/Keystore/release.keystore')
storePassword '1234567'
}
}
四、编译jar包
编译jar包的方式有两种,(如果编译不通过,请看下面的“编译jar遇到的坑”)
方式一、
点击右上角的Gradle中的assembleRelease
双击之后便开始编译jar包了
,编译完成后,我们可以在下图路径中查找我们需要的jar包
选中路径,右键Show in Explorer 打开目录
将目录中的classes.jar包复制到当前目录下的libs目录中,并替换libs目录中的classes.jar包
因为不需要视图,所以直接将修改后的libs目录复制到Unity项目中的Assests/Plugins/Android目录下,没有的话就创建
注意路径名称不要拼写错误,否则便无法读取到jar包中的内容
然后将下图目录中的AndroidManifest.xml文件复制到同样的Unity目录下
注意:此方式有弊端,如果在我们之后有其他程序员也用这种方式在项目添加SDK的话,classes.jar文件就会因为命名一样而产生冲突,下面我看方式二
方式二、
在我们的第二个Module中的build.gradle的内容中添加如下信息
//修改classes.jar包的名字并指定生成的位置
task makeJar(type:Copy){
//删除已经存在的
delete 'build/libs/plugin_sdk.jar'
//设置要复制的文件目录
from('build/intermediates/bundles/release/')
//发布完后存放的目录
into('build/libs')
//导入classes.jar文件
include('classes.jar')
//重命名
rename('classes.jar','plugin_sdk.jar')
}
makeJar.dependsOn(build)
添加完后
apply plugin: 'com.android.library'
android {
signingConfigs {
config {
keyAlias 'release.keystore'
keyPassword '1234567'
storeFile file('E:/Andriod/Keystore/release.keystore')
storePassword '1234567'
}
}
compileSdkVersion 26
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation files('libs/classes.jar')
}
//修改classes.jar包的名字并指定生成的位置
task makeJar(type:Copy){
//删除已经存在的
delete 'build/libs/plugin_sdk.jar'
//设置要复制的文件目录
from('build/intermediates/bundles/release/')
//发布完后存放的目录
into('build/libs')
//导入classes.jar文件
include('classes.jar')
//重命名
rename('classes.jar','plugin_sdk.jar')
}
makeJar.dependsOn(build)
然后点击右上角的SyncNow进行重新编译
等到编译完后,打开右上角Gradle
选择如下图所示other中的制作jar包的选项makeJar
双击后便开始进行编译了
编译完成后,我们便可以在下图目录中找到我们制作的jar包了
注意:
上述两种方式有一个共同的弊端
就是无法将嵌入的第三方的sdk文件打包到一起,所以,如果我们引用了第三方的jar文件,就需要将第三方的jar文件一起复制到Unity/Assets/Plugins/Android/目录下
编译jar包遇到的坑:
当我们进行编译的时候,有时会遇到如下情况
解决方案是在gradle.properties中添加如下内容
android.enableAapt2=false
然后再点击右上角的SyncNow
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.enableAapt2=false
等待编译完成
编译已经通过,我们就将生成的jar包放到Unity项目的Plugins/Android中
五、在Unity中调用
我们创建一个新的Unity项目,然后再场景中添加空的对象,名称为AndroidStudio中我们编写的对象的名称Netlogic
,创建NetLogic脚本,并挂载到NetLogic对象身上
NetLogic脚本
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class NetLogic : MonoBehaviour
{
private AndroidJavaObject androidObject = null;
public Text log;
void Start()
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
androidObject = jc.GetStatic<AndroidJavaObject>("currentActivity");
}
public void OnClickTestStatic()
{
if (androidObject==null)
{
Debug.Log("androidObject==null");
return;
}
androidObject.CallStatic("TestStatic");
}
public void OnClickTestNoStatic()
{
if (androidObject == null)
{
Debug.Log("androidObject==null");
return;
}
androidObject.Call("TestNoStatic", "这是非静态的函数");
}
public void OnClickTestHaveReturn()
{
if (androidObject == null)
{
Debug.Log("androidObject==null");
return;
}
int res = androidObject.Call<int>("TestReturn", new int[] { 100, 60 });
log.text = "当前点击了有返回值的函数,回调结果为:" + res;
}
void Test1Call(string res)
{
log.text = "当前点击了静态的函数,回调结果为:" + res;
}
void Test12Call(string res)
{
log.text = "当前点击了非静态的函数,回调结果为:" + res;
}
}
准备发布前,要先设置Unity中的安卓签名
选择我们创建的签名文件
输入密码
最后打包发布,在真机上测试
真机为小米6