这两天为解决unity3d与android项目整合中出现的无法监听真机back实体键的问题找了很多资料,网上也有很多人遇到了这个问题,但是似乎都没找到有效的解决方法。
UnityPlayerNativeActivity,传入参数加载对应的三维图,按返回键或home键分别返回上一个activity和返回桌面。默认情况下按home键会返回桌面,但是按back键则无法监听到,没有任何反应。
===========UnityPlayer相关==============================
UnityPlayer里有三个类,分别是UnityPlayerProxyActivity、UnityPlayerActivity、UnityPlayerNativeActivity。
UnityPlayerProxyActivity用来判断手机的系统版本,从而确定启动UnityPlayerActivity还是UnityPlayerNativeActivity。所以UnityPlayerProxyActivity这个类自己就直接去掉不用了。
UnityPlayerNativeActivity这个类的加载速率据说会比较快,系统版本要求2.3以上,之前也一直用这个类整合使用。但是这两天在使用这个类时一直没法解决实体按键事件的问题,具体可以看下这段介绍:
UnityPlayerNativeActivity
同样我们可以创建UnityPlayerNativeActivity的子类,这与创建UnityPlayerActivity的子类具有相同的效果,但是会有较小的输入延迟。但是,需要明白的是,NativeActivity是在Gingerbread中引入的(即android 2.3),老的android版本没有这个特性,因为在NativeActivity中,触摸事件都是在native代码中处理的,java视图正常情况下是无法获取这些事件的,不过在unity3d中,有允许将事件传到DalvikVM的转发机制,要应用这个转发机制,必须修改manifest文件如下:
view source print ?
01.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
02.
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.company.product"
>
03.
<
application
android:icon
=
"@drawable/app_icon"
android:label
=
"@string/app_name"
>
04.
<
activity
android:name
=
".OverrideExampleNative"
05.
android:label
=
"@string/app_name"
06.
android:configChanges
=
"fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
>
07.
<
meta-data
android:name
=
"android.app.lib_name"
android:value
=
"unity"
/>
08.
<
meta-data
android:name
=
"unityplayer.ForwardNativeEventsToDalvik"
android:value
=
"true"
/>
09.
<
intent-filter
>
10.
<
action
android:name
=
"android.intent.action.MAIN"
/>
11.
<
category
android:name
=
"android.intent.category.LAUNCHER"
/>
12.
</
intent-filter
>
13.
</
activity
>
14.
</
application
>
15.
</
manifest
>
UnityPlayerNativeActivity后,除home键外,其他按键都没法监听到。
======================在Unity中捕捉Android的常用按钮返回事件=============
另有一种办法是可以在jni脚本文件里监听到实体按键,可以在脚本文件里对按键事件进行处理。不过针对返回键只有一个方法可以调用,即Application.Quit();但是这个方法会退出整个application,按下返回键后,三维图页面退出了,同时其他页面也闪退了,无法返回到上一个activity的页面。
view source print ?
01.
#pragma strict
02.
function Start () {
03.
}
04.
function Update () {
05.
if
(Input.GetKey(KeyCode.Escape)){
06.
Application.Quit();
07.
}
08.
}
09.
function OnGUI () {
10.
}
于是改用UnityPlayerActivity这个类进行尝试,通过测试终于发现可以直接在这个类里监听到按键,但是却无法识别按键。
view source print ?
01.
// Pass any keys not handled by (unfocused) views straight to UnityPlayer
02.
public
boolean
onKeyMultiple(
int
keyCode,
int
count, KeyEvent event)
03.
{
04.
return
mUnityPlayer.onKeyMultiple(keyCode, count, event);
05.
}
06.
public
boolean
onKeyDown(
int
keyCode, KeyEvent event)
07.
{
08.
return
mUnityPlayer.onKeyDown(keyCode, event);
09.
}
10.
public
boolean
onKeyUp(
int
keyCode, KeyEvent event)
11.
{
12.
return
mUnityPlayer.onKeyUp(keyCode, event);
13.
}
onBackPressed()方法也仍然无效。网上很多一样的问题,却没有有效的答案。
================继承UnityPlayerActivity获取按键事件==================================
找不到确切的解决办法,决定改变思路再尝试下。原先的UnityPlayerActivity保持不变,参数传入的接收和处理仍然在这个类里进行,自己再创建一个类来继承UnityPlayerActivity。测试后发现终于可以识别到按键了,同时正常加载UnityPlayerActivity这个视图。
view source print ?
01.
public
class
ExtendActivity
extends
UnityPlayerActivity
02.
{
03.
04.
@Override
05.
protected
void
onCreate(Bundle savedInstanceState)
06.
{
07.
super
.onCreate(savedInstanceState);
08.
}
09.
10.
@Override
11.
public
boolean
onKeyDown(
int
keyCode, KeyEvent event)
12.
{
13.
if
(keyCode == KeyEvent.KEYCODE_BACK)
14.
{
15.
finish();
16.
Log.e(
"key"
,
"key"
);
17.
}
18.
// TODO Auto-generated method stub
19.
return
super
.onKeyDown(keyCode, event);
20.
}
21.
}
ExtendActivity就等于加载了UnityPlayerActivity,但是按下back键后又出现了原先的问题,三维图退出了,紧接着其他activity也退出了,就跟jni脚本文件里执行Application.Quit()方法的效果一样。(这个还没整明白具体原因)。
=======================通过mUnityPlayer.quit()退出并返回上一个activity==================
于是接着继续测试修改。为UnityPlayerActivity注册了广播接收者,在按下ExtendActivity的back键时发送广播通知UnityPlayerActivity执行finish()方法。修改后发现问题一样,还是无法返回到上一个activity。
正整得头大的时候,又看了遍UnityPlayerActivity类,发现了mUnityPlayer.quit()方法。于是尝试把finish()方法换成mUnityPlayer.quit(),通过退出unityplayer来结束UnityPlayerActivity,没想最后终于成功了。喜大普奔啊。
java代码如下:
ExtendActivity类
view source print ?
01.
public
class
ExtendActivity
extends
UnityPlayerActivity
02.
{
03.
04.
@Override
05.
protected
void
onCreate(Bundle savedInstanceState)
06.
{
07.
super
.onCreate(savedInstanceState);
08.
}
09.
10.
@Override
11.
public
boolean
onKeyDown(
int
keyCode, KeyEvent event)
12.
{
13.
if
(keyCode == KeyEvent.KEYCODE_BACK)
14.
{
15.
sendBroadcast(
new
Intent(
"finish"
));
16.
// finish();
17.
Log.e(
"key"
,
"key"
);
18.
}
19.
// TODO Auto-generated method stub
20.
return
super
.onKeyDown(keyCode, event);
21.
}
22.
}
UnityPlayerActivity类里添加的方法:
view source print ?
1.
//注册广播接受者
2.
private
void
registBroadcast()
3.
{
4.
BroadcastReceiver receiver =
new
FinishUnityBroadcast();
5.
IntentFilter filter =
new
IntentFilter();
6.
filter.addAction(
"finish"
);
7.
registerReceiver(receiver, filter );
8.
}
view source print ?
01.
//关闭三维图的广播
02.
class
FinishUnityBroadcast
extends
BroadcastReceiver
03.
{
04.
@Override
05.
public
void
onReceive(Context context, Intent intent)
06.
{
07.
mUnityPlayer.quit();
08.
}
09.
}