随着智能硬件的逐步发展,Unity上的通用蓝牙需求越来越多。近期我也完成了一个Unity上的通用蓝牙插件。
但本次仅介绍在这个项目中的用到的Unity和Android通信与交互部分,U3D的蓝牙有需求可以私聊讨论:P。
好了现在咱们逐步讲解U3D是如何调用Android原生Java代码的:
1、第一步建立一个Android工程(有点废话)
在例子工程中为了便于演示,我只建立了两个Activity:MainActivity(下面简称mAct)和NextActivity(下面简称nAct)。
mAct原始代码:
package com.clover.unityplugforblog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button_jump = (Button) findViewById(R.id.button_jump);
button_jump.setOnClickListener(MainActivity.this);
}
@Override
public void onClick(View v){
jump_view();
}
void jump_view()
{
Intent inent = new Intent(MainActivity.this, NextActivity.class);
startActivity(inent);
}
}
例子工程mAct就是显示一个按键然后实现Activity的跳转。nAct就不贴了,仅仅是显示一个空界面。好了,现在开始改造这个工程,
让其输出一个U3D可用的.jar库文件。
2、 在Android工程中添加U3D提供的class.jar
我是在Mac上用的Unity版本是5.4.3,因此class.jar文件位置是:
/Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes
请根据您的本机系统对这个地址进行修改。我们使用class.jar的目的是有些Unity调用class需要继承UnityPlayerActivity,所以先对其添加。
将class.jar拷贝到工程的如下目录:
再将其以library形式添加到工程
接下来修改mAct让其继承UnityPlayerActivity,再注释掉其与原生activity生命周期有关的回调函数。
package com.clover.unityplugforblog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity{//AppCompatActivity implements View.OnClickListener{
// @Override
// protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
//
// Button button_jump = (Button) findViewById(R.id.button_jump);
// button_jump.setOnClickListener(MainActivity.this);
// }
//
// @Override
// public void onClick(View v){
// jump_view();
// }
public void jump_view()
{
Intent inent = new Intent(MainActivity.this, NextActivity.class);
startActivity(inent);
}
}
这样mAct基本就改造完成了,这个class也就是是后面unity调用的入口class.
3 修改NextActivity
nAct是unity将要调用的activity,我们也要向其添加一些代码:
package com.clover.unityplugforblog;
import android.app.Activity;
import android.content.Intent;
//import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class NextActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
}
public static void Call(Activity activity)
{
// Creating an intent with the current activity and the activity we wish to start
Intent myIntent = new Intent(activity, NextActivity.class);
activity.startActivity(myIntent);
}
}
上面的Call静态方法是最新加入的,其参数是u3d传入的。代码内容很好理解,就是从u3d当前activity打开这个activity。
4 修改build.gradle文件
app的build.gradle决定了是否将本工程编译成一个库文件,所以现在我们对其进行修改。修改结果如下:
//apply plugin: 'com.android.application'
apply plugin: 'com.android.library'
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
//add
sourceSets {
main {
//Path to your source code
java {
srcDir 'src/main/java'
}
}
}
defaultConfig {
//applicationId "com.clover.unityplugforblog" //delete
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//add
lintOptions {
abortOnError false
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
testCompile 'junit:junit:4.12'
compile files('libs/classes.jar')
}
//add
//task to delete the old jar
task deleteOldJar(type: Delete) {
delete 'release/AndroidPlugin.jar'
}
//add
//task to export contents as jar
task exportJar(type: Copy) {
from('build/intermediates/bundles/release/')
into('release/')
include('classes.jar')
///Rename the jar
rename('classes.jar', 'AndroidPlugin.jar')
}
//add
exportJar.dependsOn(deleteOldJar, build)
首先我们将apply plugin: 'com.android.application'修改为apply plugin: 'com.android.library',保证输出的是一个库文件。
其次注销掉applicationId "com.clover.unityplugforblog" ,保证制定的输出形式不与其冲突。
然后//add 标注之下的脚本都是新添加的,用于指定编译内容和添加了一个编译命令。这样在右侧的Gradle栏的app::other::中就能找到一个exportJar命令,双击它
等待一会,幸运的话就能看到.jar的输出
将这个jar和如下的.xml文件一并拷入Unity工程的Plugins/Android文件夹下
application android:label="@string/app_name">
activity android:name=".MainActivity">
intent-filter>
action android:name="android.intent.action.MAIN" />
category android:name="android.intent.category.LAUNCHER" />
/intent-filter>
/activity>
/application>
上面xml文件定义了unity的主Activity文件和之后可以跳转的Android原生Activity。
5 Unity C#代码
我的u3d场景中只有一个Canvas的button,这个button的click回调执行内容如下:
public void callButton(){
AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unity.GetStatic
AndroidJavaClass jc = new AndroidJavaClass("com.clover.unityplugforblog.NextActivity");
// Calling a Call method to which the current activity is passed
jc.CallStatic("Call", currentActivity);
//currentActivity.Call ("jump_view");
AndroidJavaObject context = currentActivity.Call
}
这段代码主要完成的就是让u3d调用java代码并传递参数。调用的就是nAct中的Call函数并将自己的Java对象传递进去,完成Android界面的跳转。
完成以上工作并从Unity导出Android工程或.apk文件就能实现Unity调用Android Java代码并打开Android原生界面的功能。Android工程和Unity工程的路径如下:
https://github.com/celesius/UnityAndroidPlugin_Android.git
https://github.com/celesius/UnityAndroidPlugin_Unity.git