Callback Listener in Unity - How to call script file method from UnityPlayerActivity in Android

14,992

Solution 1

Another option will be to implement an interface callback using AndroidJavaProxy. Instead of using UnitySendMessage, you can simply have an Interface callback in your java code and then implement this interface in C# using AndroidJavaProxy and pass it to the Java method in order to receive messages back.

Create your Java interface:

package com.example.android;
public interface PluginCallback {
    public void onSuccess(String videoPath);
    public void onError(String errorMessage);
}

Call the passed listener/callback to return messages

public void myPluginMethod(PluginCallback callback) {
    // Do something
    callback.onSuccess("onSuccess");
    // Do something horrible
    callback.onError("onError");
}

Implement the interface in C#

class AndroidPluginCallback : AndroidJavaProxy
    {
        public AndroidPluginCallback() : base("com.example.android.PluginCallback") { }

        public void onSuccess(string videoPath) {
            Debug.Log("ENTER callback onSuccess: " + videoPath);
        }
        public void onError(string errorMessage)
        {
            Debug.Log("ENTER callback onError: " + errorMessage);
        }
    }

Pass the C# interface to the Java method

AndroidJavaObject pluginClass = new     AndroidJavaObject("com.example.android.MyPlugin");
pluginClass.Call("myPluginMethod", new AndroidPluginCallback());

Solution 2

I believe you are only allowed to call UnitySendMessage() from the main thread - at least in one scenario above you are calling it from the Android UI worker thread.

As a quick sanity test, try calling it before you right at the top of your shareText() function.

Share:
14,992

Related videos on Youtube

user1986760
Author by

user1986760

Updated on September 14, 2022

Comments

  • user1986760
    user1986760 over 1 year

    I have an android library project and imported the library project in the Unity project. Now, I want to implement a callback in Unity project, which will execute according to the response given by the android library project. I mean to say, Call Script File method from UnityPlayerActivity (Android Project).

    Currently I am using below line of code but nothing happens:

    UnityPlayer.UnitySendMessage("Main Camera","showMessage",errorMessage);
    

    Main Camera is my Game Object. showMessage is message name in Script File. Message is message which will be displayed in Unity through Android Activity.

    Please check my below code Unity Script File and Android Activity.

    Unity Script File:

    using UnityEngine;
    using System.Collections;
    
    public class scriptfile : MonoBehaviour {
    
        // Use this for initialization
        void Start () {
    
    
            AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); 
            AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); 
            jo.Call("shareText","236","236");
        }
    
        void showMessage(string message){
            print ("hello");
            Debug.Log ("hello");
        } 
    }
    

    Android File UnityPlayerActivity:

    /**
     * Created by CH-E01073 on 28-09-2015.
     */
    public class MainAct extends UnityPlayerActivity implements RegistrationListener,BOffersListener {
        Context context;
        SharedPreferences prefs ;
        String AppIds="";
        String PublisherIDs="";
         public void shareText(String AppId,String PublisherID) {
           context=MainAct.this;
            prefs = PreferenceManager
                   .getDefaultSharedPreferences(context);
           Log.e("AppID", AppId);
           Log.e("PublisherID",PublisherID);
    
            AppIds=AppId;
            PublisherIDs=PublisherID;
    
             runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
                     UnityPlayer.UnitySendMessage("Main Camera","showMessage","Start UI Thread");
                     if (prefs.getString(FreeBConstants.ID, null) == null
                             || prefs.getString(FreeBConstants.ID, null).equals("")
                             || !Build.VERSION.RELEASE.equals(prefs.getString(
                             FreeBConstants.VERSION, null))
                             || !FreeBCommonUtility.getDeviceId(context).equals(
                             (prefs.getString(FreeBConstants.DEVICE_ID, null)))) {
                    BSDKLogger.enableLogging(true);
                    SDKRegistration.initialize(MainAct.this, getApplicationContext(), AppIds,PublisherIDs);
                     }else{
    
                    Offers Offers = new Offers(MainAct.this);
                     Offers.setOnFreeBOffersListener(MainAct.this);
                     Offers.setTitle(
                             "Pick Any Offer to unlock your premium features",
                             "#FFFFFF", "#FF6D00");
                     }
             }
             });
    
    
    
        }
    
        @Override
        public void onOffersLoaded(String code,String freeBOffers) {
            CommonUtility.showToast(getApplicationContext(), code);
            UnityPlayer.UnitySendMessage("Main Camera","showMessage",freeBOffers);
        }
    
        @Override
        public void onShowOffers() {
    
             UnityPlayer.UnitySendMessage("Main Camera","showMessage","Show Offers");
        }
    
        @Override
        public void noOfferInstalled(String s, String s2) {
        }
    
        @Override
        public void onLeaveApplication(String s, String s2) {
        }
    
        @Override
        public void onDialogDismiss(String s) {
        }
    
        @Override
        public void onOffersFailed(String code, String errorMessage) {
    
            FreeBCommonUtility.showToast(getApplicationContext(), errorMessage);
            UnityPlayer.UnitySendMessage("Main Camera","showMessage",errorMessage);
        }
    
        @Override
        public void onOffersInstallSuccess(String code, String errorMessage) {
             FreeBCommonUtility.showToast(getApplicationContext(), errorMessage);
        }
    
        @Override
        public void onOffersInstallFailure(String code, String errorMessage) {
             FreeBCommonUtility.showToast(getApplicationContext(), errorMessage);
        }
    
    
        @Override
        public void onRegistrationFailed(String code, String errorMessage) {
            FreeBCommonUtility.showToast(getApplicationContext(), errorMessage);
            UnityPlayer.UnitySendMessage("Main Camera","showMessage",errorMessage);
        }
    
        @Override
        public void onRegistrationSuccess(String code, String errorMessage) {
          // FreeBCommonUtility.showToast(getApplicationContext(), errorMessage);
            Log.e("SUCCESS", errorMessage);
            // TODO Auto-generated method stub
            UnityPlayer.UnitySendMessage("Main Camera","showMessage",errorMessage);
    
            Offers Offers = new Offers(MainAct.this);
            Offers.setOnFreeBOffersListener(MainAct.this);
           Offers.setTitle(
                 "Pick Any Offer to unlock your premium features",
                  "#FFFFFF", "#FF6D00");
        }
    }
    

    Can anyone help me to get rid of this issue?

    • Vivek
      Vivek over 8 years
      Make sure your script attached with Main Camera (Gameobject which is called). see ref answers.unity3d.com/questions/366452/…
    • user1986760
      user1986760 over 8 years
      yes vivek, its already attached correctly.
    • Ori Frish
      Ori Frish over 8 years
      I personally don't like the Unity messaging system, why not using an interface for callback?
    • user1986760
      user1986760 over 8 years
      is there no way to implement interfaces for communicating between android to unity. Exactly, interface is nice idea if we want to communicate within the unity or within the android modules. Here we want to create bridge between Android Activity to Unity Script File.
  • Guney Ozsan
    Guney Ozsan over 2 years
    My class needs to be AppCompatActivity. And I'm getting an error AndroidJavaException: java.lang.IllegalStateException: Method addObserver must be called on the main thread. I tried things like runOnUiThread(new Runnable() { @Override public void run() { callback.onSuccess("Some message"); }, but could not make it work. Any ideas?