x


Compass java plugin for Unity Android

Hello,

I'm trying to create a java plugin to get compass info from Android. I started with this example:

http://docwiki.unity3d.com/uploads/Main/AndroidJavaPluginProject.zip

Then, I tried to include the necessary code from:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/Compass.html

The problem I found is that it is necessary to create a SensorListener and I'm not sure if this will work as a Unity plugin.

Anyone has tried to do this?

This is my piece of code:

private final SensorListener mSensorListener = new SensorListener()
{
    public void onSensorChanged(int sensor, float[] values)
    {
        if (sensor == SensorManager.SENSOR_MAGNETIC_FIELD)
        {
            float xmag = values[0];
            float ymag = values[1];
            float zmag = values[2];
        }
    }

    public void onAccuracyChanged(int sensor, int accuracy)
    {
        int i=0;
    }
};

The alternative is to code the plugin with native code (NDK), but sensor data is only available with Android SDK 2.3 (Almost every android phone runs 2.2 nowadays)

Thanks in advance,

Joel

more ▼

asked Jan 20 '11 at 03:23 PM

jsr2k1 gravatar image

jsr2k1
218 7 9 19

(comments are locked)
10|3000 characters needed characters left

4 answers: sort newest

I think you should be able to do it. However you will have to pull the data from the sensor each cycle, instead of having the data pushed to you from the java EventBus.

The following is just pseudo-code so don't hold me to it but it should be something like:

public class SensorClass {

private Activity mActivity;

float xmag;
float ymag;
float zmag;

private final SensorListener mSensorListener = new SensorListener() {

    public void onSensorChanged(int sensor, float[] values) {
        if (sensor == SensorManager.SENSOR_MAGNETIC_FIELD) {
            xmag = values[0];
            ymag = values[1];
            zmag = values[2];
        }
    }

    public void onAccuracyChanged(int sensor, int accuracy) {
        int i=0;
    }
};

public SensorClass(Activity currentActivity) {
    mActivity = currentActivity;

    mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);

    mSensorManager.registerListener(mSensorListener, mSensor,
            SensorManager.SENSOR_DELAY_GAME);

}

public float getX() {
    return xmag;
}

public float getY() {
    return ymag;
}

public float getZ() {
    return zmag;
}

}

This way you have a standalone java class that is aggregating the sensor updates for you then you just need to instantiate and call the getters from your .cs code

public class CallJavaCode : MonoBehaviour {

private IntPtr  JavaClass;
private float   xValue;
private float   yValue;
private float   zValue;


void Start ()
{

    JavaVM.AttachCurrentThread();

    IntPtr cls_Activity = JNI.FindClass("com/unity3d/player/UnityPlayer");
    int fid_Activity    = JNI.GetStaticFieldID(cls_Activity, "currentActivity", "Landroid/app/Activity;");
    IntPtr obj_Activity = JNI.GetStaticObjectField(cls_Activity, fid_Activity);
    Debug.Log("obj_Activity = " + obj_Activity);

    IntPtr cls_JavaClass    = JNI.FindClass("org/example/SensorClass");
    int mid_JavaClass       = JNI.GetMethodID(cls_JavaClass, "<init>", "(Landroid/app/Activity;)V");
    IntPtr obj_JavaClass    = JNI.NewObject(cls_JavaClass, mid_JavaClass, obj_Activity);

    JavaClass   = JNI.NewGlobalRef(obj_JavaClass);

    // this is where the JNI magic happens
    xValue  = JNI.CallFloatMethod(JavaClass, JNI.GetMethodID(cls_JavaClass, "getX", "()F"))
    yValue  = JNI.CallFloatMethod(JavaClass, JNI.GetMethodID(cls_JavaClass, "getY", "()F"))
    zValue  = JNI.CallFloatMethod(JavaClass, JNI.GetMethodID(cls_JavaClass, "getZ", "()F"))

    }
    }

Then on each update cycle you can call the

xValue  = JNI.CallFloatMethod(JavaClass, JNI.GetMethodID(cls_JavaClass, "getX", "()F"))

methods to get the current X,Y,Z values respectively. Again this is just pseudocode so it probably won't compile :) But you get the idea.

more ▼

answered Jan 20 '11 at 09:06 PM

pfranza gravatar image

pfranza
96 1 1 8

PERFECT! It works! Thank you very much!

Jan 24 '11 at 12:13 PM jsr2k1

I'm totally new to Java, but not C#. The above almost makes sense to me, but I can't get it to work. All the JNI stuff and JavaVM seems to have been changed (removed) and I had to update the Java code to get it to compile. It ran on my Galaxy tab then crashed, though I didn't mean to run it, but I couldn't find a build command for Java.

Where is the C++ code that reads the java? Would this be easier now with AndroidJNI and AndroidJavaObject helpers in Unity?

I'm trying to access the gyro on my galaxy tab, but Unity says it's not available (and of course, it actually is available), but I have spent the last 8 hours trying to get something working and I am now at a loss, any help in getting the java code into Unity would be really appreciated (preferably without needing Unity Pro, but I sense that is a necessity).

Aug 17 '11 at 06:55 AM Talimar

Hey Blitzwing - I'm still trying to get this working. Have a thread in the forum with my code so far. Hoping someone from UT will chime in and answer my questions: http://forum.unity3d.com/threads/100751-Android-Plugin-JNI-Question

Aug 17 '11 at 06:21 PM Joshua Falkner
(comments are locked)
10|3000 characters needed characters left

There is a plugin by Prefrontal Cortex in the asset store, which provides access to each and every android sensor. If you don't want to write your own, you could give it a try.

Demo scene (type into your mobiles' browser to install): goo.gl/oLkOQ

Forum thread: http://forum.unity3d.com/threads/101279-GyroDroid-2.0-Access-each-and-every-sensor-on-Android-devices-RELASED

more ▼

answered Sep 06 '11 at 04:18 PM

felix. gravatar image

felix.
1.9k 18 23 47

(comments are locked)
10|3000 characters needed characters left

philo, try this:

public SensorClass(Activity currentActivity)
{
    mActivity = currentActivity;
    mSensorManager = (SensorManager) mActivity.getSystemService(mActivity.SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    mSensorManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_GAME);
}
more ▼

answered Apr 12 '11 at 10:22 AM

jsr2k1 gravatar image

jsr2k1
218 7 9 19

I'm having the same issue as Philo. I'm able to compile the .class and .jar file, but when I run it my device it crashes. Did you have to recompile the .cpp and recreate the http://libjavabridge.so?

Jun 05 '11 at 03:57 PM Joshua Falkner

Actually I just figured out the crashing issue - I wasn't signing the jar. Looking in the build_plugins.sh showed me all the steps I was missing.

Jun 05 '11 at 04:29 PM Joshua Falkner
(comments are locked)
10|3000 characters needed characters left

I understand (in theory) how this code works, but i can't get the SensorManager to work.

I managed to build the JavaPluginSample project in Eclipse but the game crashes instantly when i include this part of the code:

mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);

Maybe you can push me in the right direction.

philo

more ▼

answered Apr 11 '11 at 07:05 AM

philo gravatar image

philo
1 2

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x2463
x392
x295
x25

asked: Jan 20 '11 at 03:23 PM

Seen: 8334 times

Last Updated: Sep 06 '11 at 04:18 PM