2012-09-11 26 views
5

私はUnity3dエンジンでアンドロイド用のアプリケーションを開発しています。このアプリケーションは、ネットワークソケット経由でPC上の自分のサーバーに接続する必要があります。 Android用のUnity3dプラグインのサンプルがいくつか見つかりました。それらに基づいて、私はUnity3dとAndroid用のJavaについていくつかのコードをC#で書いています。私は、ネットワーク操作がAndroidアプリケーションのUIスレッドで実行されてはならないことを知りました。だから私はネットワーク要求にAsynTaskを使わなければなりません。また、私はC#スクリプトから非静的メソッドを呼び出そうとしましたが、データを返しません。静的呼び出しのみがJavaアプリケーションからのデータを返します。したがって、私のAsyncTaskクラスは静的です。しかし、ネットワーク経由でデータを取得するためにAsyncTaskジョブで静的関数を呼び出すと、アプリケーションがクラッシュします。私は間違いを受けます。私の問題を解決するのを助けてくれますか?私はこの問題を解決する2つの方法を参照してください: 1)Unity3dの非静的メソッド呼び出しでデータを取得するために私のC#コードを変更します。 Javaコードですべてのメソッドを非静的に変更します。 2)静的メソッドと静的AsyncTaskで動作するようにJavaコードを変更します。Unity3d Androidプラグイン静的AsyncTaskの問題

私のC#スクリプトAndroidClientPlugin.cs:

using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 
using System; 

public class AndroidClientPlugin : MonoBehaviour { 
    private float TEST; 

    private AndroidJavaClass cls_UnityPlayer; 
    private AndroidJavaObject obj_Activity; 
    private AndroidJavaClass cls_CompassActivity; 
    // Use this for initialization 
    void Start() { 

     AndroidJNI.AttachCurrentThread(); 
     cls_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); 
     obj_Activity = cls_UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); 
     cls_CompassActivity = new AndroidJavaClass("com.lab.Android.AndroidClientPlugin"); 

     cls_CompassActivity.SetStatic<String>("ServerAddressValue", "192.168.1.5"); 
     cls_CompassActivity.SetStatic<String>("ServerPortValue", "8881"); 

    } 
    void OnGUI() { 
     GUI.Label(new Rect(Screen.width/2 -200, Screen.height/2, 400,100), "x = " + TEST.ToString()); 
    } 
    void Update() 
    { 
     if(cls_CompassActivity.CallStatic<bool>("GetData")) 
     { 
      TEST = cls_CompassActivity.CallStatic<float>("getPosX"); 
     } 
    } 
} 

私のJavaスクリプトAndroidClientPlugin.java:

package com.lab.Android; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.TimeUnit; 
import java.util.concurrent.TimeoutException; 

import com.unity3d.player.UnityPlayer; 
import com.unity3d.player.UnityPlayerActivity; 

import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Looper; 
import android.os.StrictMode; 
import android.util.Log; 
import android.content.Context; 
import android.content.Intent; 
import android.app.Activity; 

public class AndroidClientPlugin extends UnityPlayerActivity { 

    //Server address parameters 
    public static String ServerAddressValue; 
    public static String ServerPortValue; 
    //Tracker parameters 
    public static String vServerName; 
    public static String vSensorNumber; 

    private static SensorData vTaskResult; 

    public static cTask BackgroundTask; 

    @Override 
    protected void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 

     //set thread strict mode off 
     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
     StrictMode.setThreadPolicy(policy); 

     vTaskResult = new SensorData(); 
     ServerAddressValue = "192.168.1.5"; 
     ServerPortValue = "8881"; 
     vServerName = "Tracker0"; 
     vSensorNumber = "0";  
     BackgroundTask = new cTask();   
    } 

    @Override 
    protected void onResume() 
    { 
     super.onResume(); 
    } 

    @Override 
    protected void onStop() 
    { 
     super.onStop(); 
    } 

    public static boolean GetData() 
    {  
     cTaskResult taskResult = new cTaskResult(); 
     taskResult = BackgroundTask.DoAsyncTask(ServerAddressValue, ServerPortValue, vServerName, vSensorNumber); 
     vTaskResult = taskResult.ResultData; 
     return taskResult.DataIsReady; 
    } 


    public static class cTaskResult 
    { 
     public boolean DataIsReady; 
     public SensorData ResultData; 
     public cTaskResult() 
     { 
      DataIsReady = false; 
      ResultData = new SensorData(); 
     } 
    } 

    public static class cTask 
    {  
     public cTask() 
     {    
     } 
     public cTaskResult DoAsyncTask(String serverAddress, String serverPort, String trackerName, String trackerSensorNumber) 
     { 
      cTaskResult Result = new cTaskResult();  
      GetDataTask Task; 
      Task = new GetDataTask();  
      Task.execute(serverAddress, serverPort, trackerName, trackerSensorNumber, Result);   
      try { 
       Result = Task.get(1, TimeUnit.SECONDS); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (ExecutionException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (TimeoutException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      return Result;   
     } 

     public static class GetDataTask extends AsyncTask<Object, Void, cTaskResult> 
     { 
      @Override 
      protected void onPreExecute() { 
       super.onPreExecute(); 
      } 

      @Override 
      protected cTaskResult doInBackground(Object... params) { 
       cTaskResult TMPData = new cTaskResult(); 
       //doing network requests 
       //TMPData.DataIsReady = NetClient.getInstance().GetData((String)params[0], (String)params[1], (String)params[2], Integer.valueOf((String)params[3]), TMPData.ResultData); 
       //TMPData is a result of network operations 
       TMPData.DataIsReady = true; 
       TMPData.ResultData = new SensorData(); 

       return TMPData; 
      } 

      @Override 
      protected void onPostExecute(cTaskResult result) { 
       super.onPostExecute(result); 
      } 
      } 
    } 

    public static float getPosX() 
    { 
     return vTaskResult.posX; 
    } 
} 

デバッグメッセージ:あなたがアンドロイドを呼んすべての

09-11 12:56:05.514: E/CMarlinMediator(137): Error : MarlinMediator Failed to get TrustedTime 
09-11 12:56:05.594: E/CMarlinMediator(137): Error : MarlinMediator Failed to get TrustedTime 
09-11 12:56:12.184: E/Adreno200-EGL(7590): <qeglDrvAPI_eglGetConfigAttrib:484>: EGL_BAD_ATTRIBUTE 
09-11 12:56:12.184: E/Adreno200-EGL(7590): <qeglDrvAPI_eglGetConfigAttrib:484>: EGL_BAD_ATTRIBUTE 
09-11 12:56:12.184: E/Adreno200-EGL(7590): <qeglDrvAPI_eglGetConfigAttrib:484>: EGL_BAD_ATTRIBUTE 
09-11 12:56:14.304: E/AndroidRuntime(7590): FATAL EXCEPTION: GLThread 741 
09-11 12:56:14.304: E/AndroidRuntime(7590): java.lang.ExceptionInInitializerError 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at com.lab.Android.AndroidClientPlugin$cTask.DoAsyncTask(AndroidClientPlugin.java:128) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at com.lab.Android.AndroidClientPlugin.GetData(AndroidClientPlugin.java:79) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at com.unity3d.player.UnityPlayer.nativeRender(Native Method) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at com.unity3d.player.UnityPlayer.onDrawFrame(Unknown Source) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1462) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216) 
09-11 12:56:14.304: E/AndroidRuntime(7590): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at android.os.Handler.<init>(Handler.java:121) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:607) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:607) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  at android.os.AsyncTask.<clinit>(AsyncTask.java:190) 
09-11 12:56:14.304: E/AndroidRuntime(7590):  ... 6 more 
09-11 12:56:15.194: E/CMarlinMediator(137): Error : MarlinMediator Failed to get TrustedTime 
09-11 12:56:15.234: E/CMarlinMediator(137): Error : MarlinMediator Failed to get TrustedTime 

答えて

1

まず、更新機能のコード?以来、それはすべてのフレームと呼ばれます。

おそらく、ネイティブコードが実行されていることを示すフラグを入れて、それを2回呼び出さないでください。

問題については、私が知る限り、AsyncTaskの作成とタスクの実行をUIスレッド内で呼び出す必要があります。 問題は以下のとおりです。

  1. あなたはユニティでUpdateメソッド内の静的メソッドAndroidClientPlugin.GetDataを呼び出します。私が知る限り、アンドロイドのUIスレッドと同じスレッドではありません。だからUnityのスレッド内でそれを呼びました:
  2. あなたはUnity3dのスレッド内でAsyncTaskを作成して実行しているのでエラーになります。
  3. 私の解決策がある

(あなたはそれを試すことができます):

public static void GetData() 
{  
    //this will be called on UIThread of Android 
    com.unity3d.player.UnityPlayer.currentActivity.runOnUiThread(new Runnable(){ 
     public void run(){ 
      cTaskResult taskResult = new cTaskResult(); 
      taskResult = BackgroundTask.DoAsyncTask(ServerAddressValue, ServerPortValue, vServerName, vSensorNumber); 
      vTaskResult = taskResult.ResultData; 
       com.unity3d.player.UnityPlayer.currentActivity.SendMessage("YourGameObjectName", "YourMethodName", taskResult.DataIsReady); 
      //return taskResult.DataIsReady;  
     } 
    }); 

} 
関連する問題