public static IntPtr GetMethodID(IntPtr javaClass, string methodName)
        {
            bool   isStatic = false;
            string empty    = string.Empty;

            return(AndroidJNIHelper.GetMethodID(javaClass, methodName, empty, isStatic));
        }
        public static IntPtr GetMethodID <ReturnType>(IntPtr jclass, string methodName, object[] args, bool isStatic)
        {
            string signature = _AndroidJNIHelper.GetSignature <ReturnType>(args);
            IntPtr methodID  = AndroidJNIHelper.GetMethodID(jclass, methodName, signature, isStatic);

            if (methodID == IntPtr.Zero)
            {
                Debug.Warning("JNI: Unable to find method id for '" + methodName + "'" + ((!isStatic) ? string.Empty : " (static)"));
                //AndroidJNI.ExceptionClear();
            }
            return(methodID);
        }
        protected void _Call(string methodName, params object[] args)
        {
            if (args == null)
            {
                args = new object[1];
            }
            string signature = AndroidJNIHelper.GetSignature(args);

            Debug.Warning("Call<void>" + methodName + signature + args);
            IntPtr cachedMethodID = AndroidJNIHelper.GetMethodID(this.m_jclass, methodName, args, false);

            jvalue[] args2 = AndroidJNIHelper.CreateJNIArgArray(args);
            AndroidJNI.CallVoidMethod(this.m_jobject, cachedMethodID, args2);
        }
        protected ReturnType _Call <ReturnType>(string methodName, params object[] args)
        {
            if (args == null)
            {
                args = new object[1];
            }
            string signature = AndroidJNIHelper.GetSignature <ReturnType>(args);

            Debug.Warning("Call<" + typeof(ReturnType).ToString() + ">" + methodName + signature + args);
            IntPtr cachedMethodID = AndroidJNIHelper.GetMethodID <ReturnType> (this.m_jclass, methodName, args, false);

            jvalue[] args2 = AndroidJNIHelper.CreateJNIArgArray(args);
            if (typeof(ReturnType).IsPrimitive)
            {
                if (typeof(ReturnType) == typeof(int))
                {
                    object rt = AndroidJNI.CallIntMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
                if (typeof(ReturnType) == typeof(bool))
                {
                    object rt = AndroidJNI.CallBooleanMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
                if (typeof(ReturnType) == typeof(byte))
                {
                    object rt = AndroidJNI.CallByteMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
                if (typeof(ReturnType) == typeof(short))
                {
                    object rt = AndroidJNI.CallShortMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
                if (typeof(ReturnType) == typeof(long))
                {
                    object rt = AndroidJNI.CallLongMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
                if (typeof(ReturnType) == typeof(float))
                {
                    object rt = AndroidJNI.CallFloatMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
                if (typeof(ReturnType) == typeof(double))
                {
                    object rt = AndroidJNI.CallDoubleMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
                if (typeof(ReturnType) == typeof(char))
                {
                    object rt = AndroidJNI.CallCharMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
            }
            else
            {
                if (typeof(ReturnType) == typeof(string))
                {
                    object rt = AndroidJNI.CallStringMethod(this.m_jobject, cachedMethodID, args2);
                    return((ReturnType)rt);
                }
                if (typeof(ReturnType) == typeof(AndroidJavaObject))
                {
                    IntPtr jobject = AndroidJNI.CallObjectMethod(this.m_jobject, cachedMethodID, args2);
                    object rt      = new AndroidJavaObject(jobject);
                    return((ReturnType)rt);
                }
//                 if (typeof(Array).IsAssignableFrom(typeof(ReturnType)))
//                 {
//                     IntPtr array = AndroidJNI.CallObjectMethod(this.m_jobject, cachedMethodID, args2);
//                     return (ReturnType)AndroidJNIHelper.ConvertFromJNIArray<ReturnType>(array);
//                 }
                Debug.Warning("JNI: Unknown return type '" + typeof(ReturnType) + "'");
            }
            return(default(ReturnType));
        }
        public static IntPtr GetMethodID(IntPtr javaClass, string methodName, string signature)
        {
            bool isStatic = false;

            return(AndroidJNIHelper.GetMethodID(javaClass, methodName, signature, isStatic));
        }
        public static string GetSignature(object obj)
        {
            if (obj == null)
            {
                return("Ljava/lang/Object;");
            }
            Type type = (!(obj is Type)) ? obj.GetType() : ((Type)obj);

            if (type.IsPrimitive)
            {
                if (type.Equals(typeof(int)))
                {
                    return("I");
                }
                if (type.Equals(typeof(bool)))
                {
                    return("Z");
                }
                if (type.Equals(typeof(byte)))
                {
                    return("B");
                }
                if (type.Equals(typeof(short)))
                {
                    return("S");
                }
                if (type.Equals(typeof(long)))
                {
                    return("J");
                }
                if (type.Equals(typeof(float)))
                {
                    return("F");
                }
                if (type.Equals(typeof(double)))
                {
                    return("D");
                }
                if (type.Equals(typeof(char)))
                {
                    return("C");
                }
            }
            else
            {
                if (type.Equals(typeof(string)))
                {
                    return("Ljava/lang/String;");
                }
//                 if (type.Equals(typeof(AndroidJavaRunnable)))
//                 {
//                     return "Ljava/lang/Runnable;";
//                 }
                if (type.Equals(typeof(AndroidJavaObject)))
                {
                    if (obj == type)
                    {
                        return("Ljava/lang/Object;");
                    }
                    AndroidJavaObject androidJavaObject = (AndroidJavaObject)obj;
                    AndroidJavaObject androidJavaObject2;

                    object[] args           = new object[0];
                    IntPtr   cachedMethodID = AndroidJNIHelper.GetMethodID <AndroidJavaObject>(androidJavaObject.GetRawClass(), "getClass", args, false);
                    jvalue[] args2          = AndroidJNIHelper.CreateJNIArgArray(args);
                    IntPtr   pobj           = AndroidJNI.CallObjectMethod(androidJavaObject.GetRawObject(), cachedMethodID, args2);
                    androidJavaObject2 = new AndroidJavaObject(pobj);


                    string retStr;
                    IntPtr cachedMethodID2 = AndroidJNIHelper.GetMethodID <AndroidJavaObject>(androidJavaObject.GetRawClass(), "getName", args, false);

                    retStr = AndroidJNI.CallStringMethod(androidJavaObject2.GetRawObject(), cachedMethodID2, args2);
                    return("L" + retStr + ";");
                }
                else
                {
                    if (typeof(Array).IsAssignableFrom(type))
                    {
                        if (type.GetArrayRank() != 1)
                        {
                            Debug.Warning("JNI: System.Array in n dimensions is not allowed");
                            return(string.Empty);
                        }
                        StringBuilder stringBuilder = new StringBuilder();
                        stringBuilder.Append('[');
                        stringBuilder.Append(_AndroidJNIHelper.GetSignature(type.GetElementType()));
                        return(stringBuilder.ToString());
                    }
                    else
                    {
                        Debug.Warning(string.Concat(new object[]
                        {
                            "JNI: Unknown signature for type '",
                            type,
                            "' (obj = ",
                            obj,
                            ") ",
                            (type != obj) ? "instance" : "equal"
                        }));
                    }
                }
            }
            return(string.Empty);
        }