2012-09-11 17 views
5

मैं यूनिटी 3 डी इंजन पर एंड्रॉइड के लिए एक एप्लीकेशन विकसित कर रहा हूं। यह एप्लिकेशन नेटवर्क सॉकेट के माध्यम से पीसी पर मेरे सर्वर से कनेक्ट होना चाहिए। मुझे एंड्रॉइड के लिए कुछ Unity3d प्लगइन उदाहरण मिले। उनके आधार पर मैंने यूनिटी 3 डी और एंड्रॉइड के लिए जावा पर सी # पर कुछ कोड लिखा है। मुझे पता चला कि एंड्रॉइड एप्लिकेशन में यूआई-थ्रेड में नेटवर्क ऑपरेशंस नहीं चलना चाहिए। तो मुझे नेटवर्क अनुरोधों के लिए AsynTask का उपयोग करना होगा। इसके अलावा मैंने सी # स्क्रिप्ट से गैर स्थैतिक तरीकों को कॉल करने का प्रयास किया है लेकिन वे कोई डेटा नहीं लौटाते हैं। केवल स्थिर कॉल जावा एप्लिकेशन से डेटा लौटाते हैं। तो मेरा AsyncTask वर्ग स्थिर है। लेकिन जब मैं नेटवर्क के माध्यम से डेटा प्राप्त करने के लिए AsyncTask नौकरी के साथ स्थैतिक फ़ंक्शन को कॉल करता हूं तो मेरा एप्लिकेशन क्रैश हो जाता है। मुझे त्रुटियां मिलती हैं I क्या आप मेरी समस्याओं को ठीक करने में मेरी मदद कर सकते हैं? मुझे इस समस्या को ठीक करने के दो तरीके दिखाई देते हैं: 1) गैर-स्टेटिक विधि कॉल के माध्यम से डेटा प्राप्त करने के लिए यूनिटी 3 डी के लिए अपना सी # कोड बदलें। जावा कोड में गैर-स्टेटिक में सभी विधियों को बदलें। 2) स्थिर जावा विधियों और स्थिर AsyncTask के साथ काम करने के लिए मेरे जावा कोड बदलें।यूनिटी 3 डी एंड्रॉइड प्लगइन स्थिर AsyncTask समस्या

मेरे ग # स्क्रिप्ट 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"); 
     } 
    } 
} 

मेरे जावा स्क्रिप्ट 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

सबसे पहले, तुम क्यों एंड्रॉयड फोन अद्यतन समारोह में कोड? चूंकि इसे हर फ्रेम कहा जाएगा।

शायद आपको कुछ झंडा डालना चाहिए जो इंगित करता है कि देशी कोड चल रहा है, और इसे दो बार नहीं कहा जाता है।

और आपकी समस्या के बारे में, जहां तक ​​मुझे पता है, AsyncTask निर्माण और कार्य चलाना यूआई-थ्रेड के भीतर बुलाया जाना चाहिए। समस्याएं हैं:

  1. आप एकता में Update विधि के भीतर स्थिर विधि AndroidClientPlugin.GetData कहते हैं। जहां तक ​​मुझे पता है, यह एंड्रॉइड के यूआई-थ्रेड के साथ एक ही धागा नहीं है। तो आपने इसे यूनिटी के अपने धागे के भीतर बुलाया, और:
  2. आप Unity3d के थ्रेड के भीतर AsyncTask बनाते और चलाते हैं, इसलिए यह त्रुटि होगी।

मेरे समाधान है (यदि आप इसे कोशिश कर सकते हैं):

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;  
     } 
    }); 

} 
संबंधित मुद्दे