Unity3D与Android项目交互中无法监听back键返回的解决办法

 这两天为解决unity3d与android项目整合中出现的无法监听真机back实体键的问题找了很多资料,网上也有很多人遇到了这个问题,但是似乎都没找到有效的解决方法。

 原文地址:http://www.it165.net/pro/html/201308/6925.html

   实现的效果是从A_Activity跳转到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文件如下:


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>

   即使按照上述的xml配置后,进入三维图的UnityPlayerNativeActivity后,除home键外,其他按键都没法监听到。

 ======================在Unity中捕捉Android的常用按钮返回事件=============

   另有一种办法是可以在jni脚本文件里监听到实体按键,可以在脚本文件里对按键事件进行处理。不过针对返回键只有一个方法可以调用,即Application.Quit();但是这个方法会退出整个application,按下返回键后,三维图页面退出了,同时其他页面也闪退了,无法返回到上一个activity的页面。


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这个类进行尝试,通过测试终于发现可以直接在这个类里监听到按键,但是却无法识别按键。

 

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. }

   只要有按键被按下,这三个方法都能执行,包括音量键等。但是只能监听到按键事件,却无法识别是否按下的是返回键,还是菜单键。加上KeyCode.Escape或者KeyCode.Back都无效,用onBackPressed()方法也仍然无效。网上很多一样的问题,却没有有效的答案。


================继承UnityPlayerActivity获取按键事件==================================

    找不到确切的解决办法,决定改变思路再尝试下。原先的UnityPlayerActivity保持不变,参数传入的接收和处理仍然在这个类里进行,自己再创建一个类来继承UnityPlayerActivity。测试后发现终于可以识别到按键了,同时正常加载UnityPlayerActivity这个视图。

 

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类


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类里添加的方法:

 

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. }
01. //关闭三维图的广播
02. class FinishUnityBroadcast extends BroadcastReceiver
03. {
04. @Override
05. public void onReceive(Context context, Intent intent)
06. {
07. mUnityPlayer.quit();
08. }
09. }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值