Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed iOS build - possible missing library (NiceVibrations) and temp fix #73

Open
IoIoToTM opened this issue Oct 18, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@IoIoToTM
Copy link
Contributor

When trying to build for iOS 18, I got a number of undefined symbols:
Screenshot 2024-10-18 at 15 08 46

After looking through it and online for some help, I found that in the file LofeltHaptics.cs it imports all the symbols that are undefined:

        // imports of iOS Framework bindings

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsDeviceMeetsMinimumRequirementsBinding();

        [DllImport("__Internal")]
        private static extern IntPtr lofeltHapticsInitBinding();

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsLoadBinding(IntPtr controller, [In] byte[] bytes, long size);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsPlayBinding(IntPtr controller);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsStopBinding(IntPtr controller);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsSeekBinding(IntPtr controller, float time);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsSetAmplitudeMultiplicationBinding(IntPtr controller, float factor);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsSetFrequencyShiftBinding(IntPtr controller, float shift);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsLoopBinding(IntPtr controller, bool enable);

        [DllImport("__Internal")]
        private static extern float lofeltHapticsGetClipDurationBinding(IntPtr controller);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsReleaseBinding(IntPtr controller);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsSystemHapticsTriggerBinding(int type);

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsSystemHapticsInitializeBinding();

        [DllImport("__Internal")]
        private static extern bool lofeltHapticsSystemHapticsReleaseBinding();

After looking online and following this, it turned out there are no iOS binaries in the project, only Android, macOS and Windows:
Screenshot 2024-10-18 at 15 11 42

Temporary fix:
Removed all references to iOS in the file, as I don't use that library for now. It built successfully afterwards:

// Copyright (c) Meta Platforms, Inc. and affiliates. 

using UnityEngine;
using System;

#if (UNITY_ANDROID && !UNITY_EDITOR)
using System.Text;
using System.Runtime.InteropServices;
#endif

namespace Lofelt.NiceVibrations
{
    /// <summary>
    /// C# wrapper for the Lofelt Studio Android SDK.
    /// </summary>
    ///
    /// You should not use this class directly, use HapticController instead, or the
    /// <c>MonoBehaviour</c> classes HapticReceiver and HapticSource.
    ///
    /// The Lofelt Studio Android SDK is included in Nice Vibrations as pre-compiled
    /// binary plugins.
    ///
    /// Each method here delegates to the Android SDK. The methods should only be
    /// called if DeviceMeetsMinimumPlatformRequirements() returns true, otherwise there will
    /// be runtime errors.
    ///
    /// All the methods do nothing when running in the Unity editor.
    ///
    /// Before calling any other method, Initialize() needs to be called.
    ///
    /// Errors are printed and swallowed, no exceptions are thrown on Android in this class.
    public static class LofeltHaptics
    {
#if (UNITY_ANDROID && !UNITY_EDITOR)
        static AndroidJavaObject lofeltHaptics;
        static AndroidJavaObject hapticPatterns;
        static long nativeController;

        // Cache the most commonly used JNI method IDs during initialization.
        // Calling a Java method via its method ID is faster and uses less allocations than
        // calling a method by string, like e.g. 'lofeltHaptics.Call("play")'.
        static IntPtr playMethodId = IntPtr.Zero;
        static IntPtr stopMethodId = IntPtr.Zero;
        static IntPtr seekMethodId = IntPtr.Zero;
        static IntPtr loopMethodId = IntPtr.Zero;
        static IntPtr setAmplitudeMultiplicationMethodId = IntPtr.Zero;
        static IntPtr playMaximumAmplitudePattern = IntPtr.Zero;

        [DllImport("lofelt_sdk")]
        private static extern bool lofeltHapticsLoadDirect(IntPtr controller, [In] byte[] bytes, long size);
#endif

        /// <summary>
        /// Initializes the Android library plugin.
        /// </summary>
        ///
        /// This needs to be called before calling any other method.
        public static void Initialize()
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            try
            {
                using (var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
                using (var context = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity"))
                {
                    lofeltHaptics = new AndroidJavaObject("com.lofelt.haptics.LofeltHaptics", context);
                    nativeController = lofeltHaptics.Call<long>("getControllerHandle");
                    hapticPatterns = new AndroidJavaObject("com.lofelt.haptics.HapticPatterns", context);

                    playMethodId = AndroidJNIHelper.GetMethodID(lofeltHaptics.GetRawClass(), "play", "()V", false);
                    stopMethodId = AndroidJNIHelper.GetMethodID(lofeltHaptics.GetRawClass(), "stop", "()V", false);
                    seekMethodId = AndroidJNIHelper.GetMethodID(lofeltHaptics.GetRawClass(), "seek", "(F)V", false);
                    loopMethodId = AndroidJNIHelper.GetMethodID(lofeltHaptics.GetRawClass(), "loop", "(Z)V", false);
                    setAmplitudeMultiplicationMethodId = AndroidJNIHelper.GetMethodID(lofeltHaptics.GetRawClass(), "setAmplitudeMultiplication", "(F)V", false);
                    playMaximumAmplitudePattern = AndroidJNIHelper.GetMethodID(hapticPatterns.GetRawClass(), "playMaximumAmplitudePattern", "([F)V", false);
                }
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
            }
#endif
        }

        /// <summary>
        /// Releases the resources used by the Android library plugin.
        /// </summary>
        public static void Release()
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            try
            {
                lofeltHaptics.Dispose();
                lofeltHaptics = null;

                hapticPatterns.Dispose();
                hapticPatterns = null;
            }
            catch (Exception ex)
            {
                Debug.LogWarning(ex);
            }
#endif
        }

        public static bool DeviceMeetsMinimumPlatformRequirements()
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            return JNIHelpers.Call<bool>(lofeltHaptics, "deviceMeetsMinimumRequirements");
#else
            return true;
#endif
        }

        public static void Load(byte[] data)
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            // For performance reasons, we do *not* call into the Java API with
            // `lofeltHaptics.Call("load", data)` here. Instead, we bypass the Java layer and
            // call into the native library directly, saving the costly conversion from
            // C#'s byte[] to Java's byte[].
            //
            // No exception handling needed here, lofeltHapticsLoadDirect() is a native method that
            // doesn't throw an exception and instead logs the error.
            lofeltHapticsLoadDirect((IntPtr)nativeController, data, data.Length);
#endif
        }

        public static float GetClipDuration()
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            return JNIHelpers.Call<float>(lofeltHaptics, "getClipDuration");
#else
            //No haptic clip was loaded with Lofelt SDK, so it returns 0.0f
            return 0.0f;
#endif
        }

        public static void Play()
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            JNIHelpers.Call(lofeltHaptics, playMethodId);
#endif
        }

        public static void PlayMaximumAmplitudePattern(float[] timings)
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            JNIHelpers.Call(hapticPatterns, playMaximumAmplitudePattern, timings);
#endif
        }

        public static void Stop()
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            JNIHelpers.Call(lofeltHaptics, stopMethodId);
#endif
        }

        public static void StopPattern()
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            try
            {
                hapticPatterns.Call("stopPattern");
            }
            catch (Exception ex)
            {
                Debug.LogWarning(ex);
            }
#endif
        }

        public static void Seek(float time)
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            JNIHelpers.Call(lofeltHaptics, seekMethodId, time);
#endif
        }

        public static void SetAmplitudeMultiplication(float factor)
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            JNIHelpers.Call(lofeltHaptics, setAmplitudeMultiplicationMethodId, factor);
#endif
        }

        public static void SetFrequencyShift(float shift)
        {
            // Removed for iOS
        }

        public static void Loop(bool enabled)
        {
#if (UNITY_ANDROID && !UNITY_EDITOR)
            JNIHelpers.Call(lofeltHaptics, loopMethodId, enabled);
#endif
        }

        public static void TriggerPresetHaptics(int type)
        {
            // Removed for iOS
        }
    }
}
@IoIoToTM IoIoToTM added the bug Something isn't working label Oct 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant