Pages

getteammates.com

Friday, 6 February 2015

Accessing android java classes from Unity 3D; launching an android alert dialog from Unity 3D



Introduction


Let me share a sample code in C# which communicates with android java classes.

What I will do is open an AlertDialog from unity c# scripts.

In the process I will show you how to access android classes, derive from an android java class, override its methods, also how to execute task in android main thread.

You can use the technique used in the document to access anything that is accessible in android.

If you want to say create a custom dialog you can create a jar library which has the required code and access the classes in the jar by using the same technique.

The jar library and the resources of course should be kept in the Assets/Plugins/Android folder.

Accessing the activity class

In unity AndroidJavaClass represents the java.lang.Class and AndroidJavaObject the java.lang.Object. We will use both of these classes to get the instance of Activity class.

  // Obtain activity
  AndroidJavaClass unityPlayer = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
  AndroidJavaObject activity = unityPlayer.GetStatic<  AndroidJavaObject >  ("currentActivity");

Running code on UI thread

We will use the method runOnUiThread of the activity to run on UI thread. Here we will use AndroidJavaRunnable class which represents java.lang.Runnable.

    // Here we are using lambda expression you can also pass a function as argument to the AndroidJavaRunnable class
    activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>  {
        // put your code there
    }

Deriving from a Java interface

AndroidJavaProxy will be used to derive from a java interface. To derive from a java interface first derive from AndroidJavaProxy and then call the java interface from the constructor as show below,
private class PositiveButtonListner : AndroidJavaProxy {

  public PositiveButtonListner()
   : base("android.content.DialogInterface$OnClickListener") {
  }

  public void onClick(AndroidJavaObject obj, int value ) {
     // do your stuff here, it will be overridden from DialogInterface.OnClickListener
  }
 }

Complete source code



using UnityEngine;
using System.Collections;

public class AndroidDialog : MonoBehaviour {

 const int ButtonWidth = 256;
 const int ButtonHeight = 64;

 private string mMessage = "See My Android Dialog";

 private bool mYesPressed = false;
 private bool mNoPressed = false;

 // Use this for initialization
 void Start () {
 }
 
 // Update is called once per frame
 void Update () {
 }

 void OnGUI() {

  if (GUI.Button(new Rect((Screen.width-ButtonWidth)/2, (Screen.height-ButtonHeight)/2,
                           ButtonWidth, ButtonHeight),
                 "ShowDialog")) {
   showDialog();
  }

  if (mYesPressed) {
   GUI.Label(new Rect((Screen.width-ButtonWidth)/2, (Screen.height-ButtonHeight)/2 + 2 * ButtonHeight,
                      ButtonWidth, ButtonHeight), "You Pressed Yes");
  }

  if (mNoPressed) {
   GUI.Label(new Rect((Screen.width-ButtonWidth)/2, (Screen.height-ButtonHeight)/2 + 2 * ButtonHeight,
                      ButtonWidth, ButtonHeight), "You Pressed No");
  }
 }

 // Lets put our android specific code under the macro UNITY_ANDROID
#if UNITY_ANDROID
 // Lets create some listners.
 // These listners will be passed to android 

 // Create the postive action listner class
 // It has to be derived from the AndroidJavaProxy class
 // Make the methods as same as that of DialogInterface.OnClickListener
 private class PositiveButtonListner : AndroidJavaProxy {
  private AndroidDialog mDialog;

  public PositiveButtonListner(AndroidDialog d)
   : base("android.content.DialogInterface$OnClickListener") {
   mDialog = d;
  }

  public void onClick(AndroidJavaObject obj, int value ) {
   mDialog.mYesPressed = true;
   mDialog.mNoPressed = false;
  }
 }

 // Create the postive action listner class
 // It has to be derived from the AndroidJavaProxy class
 // Make the methods as same as that of DialogInterface.OnClickListener
 private class NegativeButtonListner : AndroidJavaProxy {
  private AndroidDialog mDialog;

  public NegativeButtonListner(AndroidDialog d)
  : base("android.content.DialogInterface$OnClickListener") {
   mDialog = d;
  }
  
  public void onClick(AndroidJavaObject obj, int value ) {
   mDialog.mYesPressed = false;
   mDialog.mNoPressed = true;
  }
 }


#endif

 private void showDialog() {

#if UNITY_ANDROID
  // Obtain activity
  AndroidJavaClass unityPlayer = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
  AndroidJavaObject activity = unityPlayer.GetStatic< AndroidJavaObject>  ("currentActivity");

  // Lets execute the code in the UI thread
  activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>  {

   // Create an AlertDialog.Builder object
   AndroidJavaObject alertDialogBuilder = new AndroidJavaObject("android/app/AlertDialog$Builder", activity);

   // Call setMessage on the builder
   alertDialogBuilder.Call< AndroidJavaObject> ("setMessage", mMessage);

   // Call setCancelable on the builder
   alertDialogBuilder.Call< AndroidJavaObject> ("setCancelable", true);

   // Call setPositiveButton and set the message along with the listner
   // Listner is a proxy class
   alertDialogBuilder.Call< AndroidJavaObject> ("setPositiveButton", "Yes", new PositiveButtonListner(this));

   // Call setPositiveButton and set the message along with the listner
   // Listner is a proxy class
   alertDialogBuilder.Call< AndroidJavaObject> ("setNegativeButton", "No", new NegativeButtonListner(this));

   // Finally get the dialog instance and show it
   AndroidJavaObject dialog = alertDialogBuilder.Call< AndroidJavaObject> ("create");
   dialog.Call("show");
  }));
#endif

 }
}


No comments:

Post a Comment