Reviving Fun: Modifying the Ultimate Lightning McQueen App for Android back to life!

Remember the excitement when your child first got their hands on the Ultimate Lightning McQueen toy? The joy of watching it zoom around with its expressive eyes and lifelike movements brought endless smiles. Unfortunately, that joy was cut short when Sphero discontinued the accompanying app for Android, leaving many kids, including my son, disappointed.

The Ultimate Lightning McQueen app was the key to unlocking the toy's full potential. It allowed you to control its movements, change its expressions, and even watch Cars-inspired animations. But when Sphero decided to pull the plug on updates and support, the app became unusable for many Android users. For months, my son kept asking to play with Lightning McQueen, unaware of the app's fate.

Faced with a dilemma, I delved into the online community of dedicated parents and enthusiasts who were unwilling to let this beloved toy go to waste. There, I discovered a glimmer of hope – modified versions of the app that could potentially bypass the update check and work seamlessly with the toy.

There are several versions floating around, each claiming to offer a solution. Some are older versions that may lack certain features introduced in later updates, while others are patched versions with modified code to bypass the update check. Finding the right one can be a bit of trial and error, but the effort is worth it when you see the delight on your child's face.

Here’s a brief guide on how to potentially revive your Ultimate Lightning McQueen experience:

  1. Research and Download: Look for modified versions of the Ultimate Lightning McQueen app online. These can often be found on enthusiast forums or tech communities. Make sure to download from trusted sources to avoid any security risks.

  2. Installation: Before installing any modified app, ensure that your device allows installation from unknown sources. You can usually find this option in your device’s settings under Security or Privacy.

  3. Testing Versions: Try different versions of the modified app. Some might work better than others depending on your device’s operating system and the toy’s firmware version. Don’t give up if the first one doesn’t work – there’s likely a version out there that will.

  4. Enjoyment: Once you find a version that works, let your child rediscover the joy of playing with Lightning McQueen. Control his movements, change his expressions, and explore all the features that made the toy so special in the first place.

  5. Community Support: Stay connected with other parents and enthusiasts who are navigating the same challenges. They often share tips, updates, and new versions of the app that could further enhance your experience.

While it’s unfortunate that Sphero discontinued support for the Ultimate Lightning McQueen app, the dedication of the community has kept the magic alive. By modifying the app, we can continue to create memories and bring smiles to our children’s faces. So, if you’re facing the same situation, don’t hesitate to explore the world of modified apps and let your kids enjoy their favorite toy once more. After all, Lightning McQueen isn’t just a toy – he’s a beloved friend on wheels, ready to race into new adventures with a little help from dedicated parents like us.

 

 

This is what In the could to block.

1- checking for Sphero toy MQ to connect

2- Checking for updates

3- Fail and show the update critical required if the object of API didn't fill the const // here i changed it to pass even if the link and API call is failing

Mcqueen\ExportedProject\Assets\Scripts\Assembly-CSharp\Cars\UI ==> 

using System;
using System.Collections;
using I2.Loc;
using ModulePresentationV2;
using UnityEngine;
using UnityEngine.UI;

namespace Cars.UI
{
    public class UpdateAnimationController : MonoBehaviour
    {
        [SerializeField]
        private Animator _animator;

        [SerializeField]
        private Animator _descriptionAnimator;

        [SerializeField]
        private string _animOnBoolName ="on";

        [SerializeField]
        private string _animStartTriggerName ="start";

        [SerializeField]
        private string _animRedTriggerName ="red";

        [SerializeField]
        private string _animYellowTriggerName ="yellow";

        [SerializeField]
        private string _animBlueTriggerName ="blue";

        [SerializeField]
        private AbstractMonitorBehaviour _redExitReporter;

        [SerializeField]
        private AbstractMonitorBehaviour _yellowExitReporter;

        [SerializeField]
        private AbstractMonitorBehaviour _blueExitReporter;

        [SerializeField]
        private AbstractMonitorBehaviour _infoOnExitReporter;

        [SerializeField]
        private Text _infoText;

        [SerializeField]
        private Text _updateTypeText;

        [SerializeField]
        private string _updateLocalizationKey;

        private bool _animatorOn;

        private string _currentState;

        private string _pendingInfoText;

        private string _pendingUpdateTypeText;

        private void Start()
        {
            _animatorOn = _animator.GetBool(_animOnBoolName);
            _descriptionAnimator.SetBool("on", true);
            _redExitReporter.Reported += HandleStateExit;
            _blueExitReporter.Reported += HandleStateExit;
            _yellowExitReporter.Reported += HandleStateExit;
            _infoOnExitReporter.Reported += HandleInfoOnExit;
        }

        private void OnDestroy()
        {
            if (_redExitReporter != null)
            {
                _redExitReporter.Reported -= HandleStateExit;
            }
            if (_blueExitReporter != null)
            {
                _blueExitReporter.Reported -= HandleStateExit;
            }
            if (_yellowExitReporter != null)
            {
                _yellowExitReporter.Reported -= HandleStateExit;
            }
            if (_infoOnExitReporter != null)
            {
                _infoOnExitReporter.Reported -= HandleInfoOnExit;
            }
        }

        private void _appUpdateController_UploadingUpdates(object sender, EventArgs e)
        {
            GoToYellow(_updateLocalizationKey);
        }

        private void HandleStateExit(object sender, EventArgs e)
        {
            StartCoroutine(SetText());
        }

        private void HandleInfoOnExit(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(_pendingInfoText))
            {
                _infoText.text = _pendingInfoText;
                _updateTypeText.text = _pendingUpdateTypeText;
                _descriptionAnimator.SetBool("on", true);
                _pendingInfoText = string.Empty;
                _pendingUpdateTypeText = null;
            }
        }

        public void HideInfoText()
        {
            _descriptionAnimator.SetBool("on", false);
            StartCoroutine(SetText());
        }

        public void GoToBlue(string locKey ="")
        {
            _pendingUpdateTypeText = string.Empty;
            SetPendingText(locKey);
            if (_currentState != _animBlueTriggerName)
            {
                _animator.SetBool("awake", true);
                SetTrigger(_animBlueTriggerName);
            }
        }

        public void GoToRed(string locKey ="")
        {
            _pendingUpdateTypeText = string.Empty;
            SetPendingText(locKey);
            if (_currentState != _animRedTriggerName)
            {
                _animator.SetBool("awake", true);
                SetTrigger(_animRedTriggerName);
            }
        }

        public void GoToYellow(string locKey ="")
        {
            SetPendingText(locKey);
            if (_currentState != _animYellowTriggerName)
            {
                _animator.SetBool("awake", true);
                SetTrigger(_animYellowTriggerName);
            }
        }

        public void GoToStart(string locKey ="")
        {
            _pendingUpdateTypeText = string.Empty;
            _pendingInfoText = string.Empty;
            HideInfoText();
            _animator.SetTrigger(_animStartTriggerName);
        }

        private void SetPendingText(string locKey)
        {
            _pendingInfoText = string.Empty;
            if (!string.IsNullOrEmpty(locKey))
            {
                _pendingInfoText = ScriptLocalization.Get(locKey);
            }
            if (_descriptionAnimator.GetBool("on"))
            {
                HideInfoText();
            }
            else
            {
                _descriptionAnimator.SetBool("on", true);
            }
        }

        private void SetTrigger(string triggerName)
        {
            if (!(_currentState == triggerName))
            {
                _animator.SetBool(_animOnBoolName, false);
                if (_currentState != null)
                {
                    _animator.ResetTrigger(_currentState);
                }
                _currentState = triggerName;
                _animator.SetTrigger(_currentState);
                StartCoroutine(Refresh());
            }
        }

        public void ShowDescription()
        {
            _descriptionAnimator.SetBool("on", true);
        }

        private void TurnOn()
        {
            if (!_animatorOn)
            {
                _infoText.text = _pendingInfoText;
                _updateTypeText.text = _pendingUpdateTypeText;
                _animator.SetBool(_animOnBoolName, true);
            }
        }

        private IEnumerator SetText()
        {
            yield return new WaitForSeconds(0.3f);
            _updateTypeText.text = _pendingUpdateTypeText;
            _infoText.text = _pendingInfoText;
            _descriptionAnimator.SetBool("on", true);
        }

        private IEnumerator Refresh()
        {
            yield return new WaitForSeconds(0.25f);
            _animator.SetBool(_animOnBoolName, true);
            yield return StartCoroutine(SetText());
        }
    }
}
 

4- if no update then check the firmware of mcqueen and compare, also fail in case of not higher or equal // also this one changed to pass even if the firmware is diff or lower

using System;
using System.Collections;
using Cars.Connection;
using Cars.ContentManagement;
using Cars.ContentManagement.Fetch;
using Cars.ToyAdapter;
using Cars.ToyData;
using Cars.ToyUpdate;
using Cars.ToyUpdate.Strategies;
using Cars.Utils;
using I2.Loc;
using Sphero;
using UnityEngine;
using UnityEngine.UI;

namespace Cars.UI.ConnectionUI
{
    public class ConnectionButtonStateUpdater : MonoBehaviour
    {
        [SerializeField]
        private ToyConnectionEvent _connectionEvent;

        [SerializeField]
        private ConnectionButtonAnimatorController _animatorController;

        [SerializeField]
        private UpdateManager _updateManager;

        [SerializeField]
        private ContentFetchAndDownload _fetchAndDownload;

        [SerializeField]
        private Slider _fillSlider;

        [SerializeField]
        private string _lookingForToysLocKey;

        [SerializeField]
        private string _connectingLocKey;

        [SerializeField]
        private string _downloadingLocKey;

        [SerializeField]
        private string _criticalErrorFetchLocKey;

        [SerializeField]
        private string _criticalErrorDownloadLocKey;

        [SerializeField]
        private string _makingCriticalRepairsLocKey;

        [SerializeField]
        private string _updatingFirmwareLocKey;

        [SerializeField]
        private string _updatingAnimationsLocKey;

        [SerializeField]
        private string _updatingAudioLocKey;

        [SerializeField]
        private string _settingUpForAudioUpdate;

        [SerializeField]
        private string _checkingForUpdatesLocKey;

        [SerializeField]
        private string _bluetoothDisabledLocKey;

        [SerializeField]
        private string _disconnectedLocKey;

        [SerializeField]
        private string _networkErrorLocKey;

        [SerializeField]
        private ToyDataVersionProviderBehaviourContainer _toyData;

        [SerializeField]
        private ContentBundleDownloadBehaviour _downloadBehaviour;

        [SerializeField]
        private ContentBundleFetchManager _fetchManager;

        [SerializeField]
        private Text _slowInternetText;

        [SerializeField]
        private Text _percentageText;

        private ILMQToyAdapter _toyAdapter;

        private IToyBoxAdapter _toyBoxAdapter;

        private bool _initialConnectionMade;

        private bool _updatesComplete;

        private uint _failedFetchCount;

        private uint _fetchSuccessCount;

        private uint _failedDownloadCount;

        private uint _downloadSuccessCount;

        public event EventHandler ConnectPressed;

        public event EventHandler StartPressed;

        private void Awake()
        {
            _toyAdapter = SingletonBehaviour.Instance;
            Subscribe();
        }

        private void Start()
        {
            if (_connectionEvent.ToyConnected)
            {
                _animatorController.GoToState(ConnectionButtonState.Yellow);
            }
            else
            {
                _animatorController.GoToState(ConnectionButtonState.Press);
            }
        }

        private void Subscribe()
        {
            _updateManager.LookingForToys += _updateManager_LookingForToys;
            _updateManager.ToyDisconnected += _updateManager_ConnectionLost;
            _updateManager.ConnectingToToy += _updateManager_ConnectingToToy;
            _updateManager.CheckingForUpdates += _updateManager_CheckingForUpdates;
            _updateManager.UpdatesComplete += _updateManager_UpdatesComplete;
            _updateManager.ProgressUpdated += _updateManager_ProgressUpdated;
            _updateManager.BluetoothStatusChanged += _updateManager_BluetoothStatusChanged;
            _updateManager.CriticalUpdatesRequired += _updateManager_CriticalUpdatesRequired;
            _updateManager.ActiveUpdateStateChanged += _updateManager_ActiveUpdateStateChanged;
            _fetchAndDownload.FetchStarted += _fetchAndDownload_FetchStarted;
            _fetchAndDownload.DownloadStarted += _fetchAndDownload_DownloadStarted;
            _fetchAndDownload.DownloadProgressUpdated += _fetchAndDownload_DownloadProgressUpdated;
            _fetchAndDownload.Completed += _fetchAndDownload_Completed;
            _downloadBehaviour.DownloadFailed += _downloadBehaviour_DownloadFailed;
            _downloadBehaviour.DownloadComplete += _downloadBehaviour_DownloadComplete;
            _downloadBehaviour.AssetDownloaded += _downloadBehaviour_AssetDownloaded;
            _fetchManager.ContentBundleFetchFailed += _fetchManager_ContentBundleFetchFailed;
            _fetchManager.ContentFetchComplete += _fetchManager_ContentFetchComplete;
        }

        private void Unsubscribe()
        {
            if (_updateManager != null)
            {
                _updateManager.LookingForToys -= _updateManager_LookingForToys;
                _updateManager.ToyDisconnected -= _updateManager_ConnectionLost;
                _updateManager.ConnectingToToy -= _updateManager_ConnectingToToy;
                _updateManager.CheckingForUpdates -= _updateManager_CheckingForUpdates;
                _updateManager.UpdatesComplete -= _updateManager_UpdatesComplete;
                _updateManager.ProgressUpdated -= _updateManager_ProgressUpdated;
                _updateManager.BluetoothStatusChanged -= _updateManager_BluetoothStatusChanged;
                _updateManager.CriticalUpdatesRequired -= _updateManager_CriticalUpdatesRequired;
                _updateManager.ActiveUpdateStateChanged -= _updateManager_ActiveUpdateStateChanged;
            }
            if (_fetchAndDownload != null)
            {
                _fetchAndDownload.FetchStarted -= _fetchAndDownload_FetchStarted;
                _fetchAndDownload.DownloadStarted -= _fetchAndDownload_DownloadStarted;
                _fetchAndDownload.DownloadProgressUpdated -= _fetchAndDownload_DownloadProgressUpdated;
            }
            if (_downloadBehaviour != null)
            {
                _downloadBehaviour.DownloadFailed -= _downloadBehaviour_DownloadFailed;
                _downloadBehaviour.DownloadComplete -= _downloadBehaviour_DownloadComplete;
                _downloadBehaviour.AssetDownloaded -= _downloadBehaviour_AssetDownloaded;
            }
            if (_fetchManager != null)
            {
                _fetchManager.ContentBundleFetchFailed -= _fetchManager_ContentBundleFetchFailed;
                _fetchManager.ContentFetchComplete -= _fetchManager_ContentFetchComplete;
            }
        }

        private void _buttonReporter_Reported(object sender, EventArgs e)
        {
            if (!_updatesComplete)
            {
                this.ConnectPressed.Raise(this, EventArgs.Empty);
                return;
            }
            this.StartPressed.Raise(this, EventArgs.Empty);
            _animatorController.Reset();
        }

        private void _updateManager_ActiveUpdateStateChanged(object sender, UpdateStateEventArgs e)
        {
            switch (e.UpdateType)
            {
            case UpdateState.MainAppCorrupt:
                SetButtonToState(ConnectionButtonState.Yellow);
                SetButtonDescription(_makingCriticalRepairsLocKey);
                break;
            case UpdateState.AudioNoric:
                SetButtonToState(ConnectionButtonState.Yellow);
                SetButtonDescription(_settingUpForAudioUpdate);
                break;
            case UpdateState.ProcessAudioFiles:
                SetButtonToState(ConnectionButtonState.Yellow);
                SetButtonDescription(_settingUpForAudioUpdate);
                break;
            case UpdateState.AudioImage:
                SetButtonToState(ConnectionButtonState.Yellow);
                SetButtonDescription(_updatingAudioLocKey);
                break;
            case UpdateState.Nordic:
                SetButtonToState(ConnectionButtonState.Yellow);
                _animatorController.SetDescription(ScriptLocalization.Get(_updatingFirmwareLocKey) + " A");
                break;
            case UpdateState.ST:
                SetButtonToState(ConnectionButtonState.Yellow);
                _animatorController.SetDescription(ScriptLocalization.Get(_updatingFirmwareLocKey) + " B");
                break;
            case UpdateState.Animation:
                SetButtonToState(ConnectionButtonState.Yellow);
                SetButtonDescription(_updatingAnimationsLocKey);
                break;
            case UpdateState.SetUpdateAudioCRC:
            case UpdateState.RequestingLastAudioBlock:
            case UpdateState.SetAudioCRC:
            case UpdateState.WaitingForInterrupt:
            case UpdateState.AwaitingToyConnection:
                break;
            }
        }

        private void SetButtonToState(ConnectionButtonState state)
        {
            _animatorController.GoToState(state);
        }

        private void SetButtonDescription(string locKey)
        {
            _animatorController.SetDescription(ScriptLocalization.Get(locKey));
        }

        private void _updateManager_CheckingForUpdates(object sender, EventArgs e)
        {
            _percentageText.text = string.Empty;
            SetButtonToState(ConnectionButtonState.Yellow);
            if (_toyAdapter.State == ToyState.MainAppCorrupt)
            {
                SetButtonDescription(_criticalErrorFetchLocKey);
            }
            else
            {
                SetButtonDescription(_checkingForUpdatesLocKey);
            }
        }

        private void _fetchManager_ContentFetchComplete(object sender, ContentBundleListEventArgs e)
        {
            _failedFetchCount = 0u;
            _fetchSuccessCount = 0u;
            StopAllCoroutines();
            StartCoroutine(FadeText(0f));
        }

        private void _fetchManager_ContentBundleFetchFailed(object sender, EventArgs e)
        {
            _failedFetchCount++;
            _fetchSuccessCount = 0u;
            if (_failedFetchCount == 3)
            {
                StopAllCoroutines();
                StartCoroutine(FadeText(1f));
            }
        }

        private void _fetchAndDownload_Completed(object sender, EventArgs e)
        {
            _fillSlider.value = 1f;
        }

        private void _fetchAndDownload_FetchStarted(object sender, EventArgs e)
        {
            SetButtonToState(ConnectionButtonState.Yellow);
            if (_toyData.MainAppCorrupt || VersionUtils.IsSemverZero(_toyData.StVersion))
            {
                SetButtonDescription(_criticalErrorFetchLocKey);
            }
            else
            {
                SetButtonDescription(_checkingForUpdatesLocKey);
            }
        }

        private void _fetchAndDownload_DownloadStarted(object sender, EventArgs e)
        {
            if (_updateManager.State == UpdateManager.UpdateManagerState.Connecting || _updateManager.State == UpdateManager.UpdateManagerState.CheckingForUpdates)
            {
                _animatorController.GoToState(ConnectionButtonState.Yellow);
                if (_toyData.MainAppCorrupt || VersionUtils.IsSemverZero(_toyData.StVersion))
                {
                    SetButtonDescription(_criticalErrorDownloadLocKey);
                }
                else
                {
                    SetButtonDescription(_downloadingLocKey);
                }
            }
        }

        private void _fetchAndDownload_DownloadProgressUpdated(object sender, FloatEventArgs e)
        {
            _fillSlider.value = e.Value;
            int num = (int)(e.Value * 100f);
            if (num > 0)
            {
                _percentageText.text = num + "%";
            }
        }

        private void _updateManager_ConnectionLost(object sender, EventArgs e)
        {
            SetButtonToState(ConnectionButtonState.Red);
            SetButtonDescription(_disconnectedLocKey);
        }

        private void _updateManager_CriticalUpdatesRequired(object sender, EventArgs e)
        {
            _fillSlider.value = 1f;
            _updatesComplete = true;
            _percentageText.text = string.Empty;
            if (_connectionEvent.ToyConnected)
            {
                SetButtonToState(ConnectionButtonState.Blue);
                _animatorController.TurnOffDescription();
            }
        }

        private void _updateManager_BluetoothStatusChanged(object sender, BooleanEventArgs e)
        {
            if (!e.Value)
            {
                SetButtonToState(ConnectionButtonState.Red);
                SetButtonDescription(_bluetoothDisabledLocKey);
            }
            else
            {
                SetButtonToState(ConnectionButtonState.Yellow);
            }
        }

        private void _updateManager_LookingForToys(object sender, EventArgs e)
        {
            SetButtonToState(ConnectionButtonState.Yellow);
            SetButtonDescription(_lookingForToysLocKey);
        }

        private void _updateManager_ConnectingToToy(object sender, EventArgs e)
        {
            SetButtonToState(ConnectionButtonState.Yellow);
            SetButtonDescription(_connectingLocKey);
        }

        private void _updateManager_ProgressUpdated(object sender, FloatEventArgs e)
        {
            if (e.Value <= 0f)
            {
                _fillSlider.value = 1f;
                _percentageText.text = string.Empty;
                return;
            }
            _fillSlider.value = e.Value;
            int num = (int)(e.Value * 100f);
            if (num > 0)
            {
                _percentageText.text = num + "%";
            }
        }

        private void _updateManager_UpdatesComplete(object sender, EventArgs e)
        {
            _fillSlider.value = 1f;
            _updatesComplete = true;
            _percentageText.text = string.Empty;
            if (_connectionEvent.ToyConnected)
            {
                SetButtonToState(ConnectionButtonState.Blue);
                _animatorController.TurnOffDescription();
            }
        }

        private void OnDestroy()
        {
            Unsubscribe();
        }

        private void _downloadBehaviour_DownloadFailed(object sender, EventArgs e)
        {
            _failedDownloadCount++;
            _downloadSuccessCount = 0u;
            if (_failedDownloadCount == 5)
            {
                StopAllCoroutines();
                StartCoroutine(FadeText(1f));
            }
        }

        private void _downloadBehaviour_AssetDownloaded(object sender, AssetEventArgs e)
        {
            _downloadSuccessCount++;
            if (_downloadSuccessCount == 5 && _failedDownloadCount >= 5)
            {
                _failedDownloadCount = 0u;
                _downloadSuccessCount = 0u;
                StopAllCoroutines();
                StartCoroutine(FadeText(0f));
            }
        }

        private void _downloadBehaviour_DownloadComplete(object sender, EventArgs e)
        {
            _failedDownloadCount = 0u;
            _downloadSuccessCount = 0u;
            StopAllCoroutines();
            StartCoroutine(FadeText(0f));
            _percentageText.text = string.Empty;
        }

        private IEnumerator FadeText(float alpha)
        {
            Color newColor = _slowInternetText.color;
            float step = ((!(alpha > _slowInternetText.color.a)) ? (-0.2f) : 0.2f);
            while (Mathf.Abs(newColor.a - alpha) > Mathf.Abs(step))
            {
                newColor.a += step;
                _slowInternetText.color = newColor;
                yield return null;
            }
            newColor.a = alpha;
            _slowInternetText.color = newColor;
        }
    }
}
 

5- Start

 

** one of the issues that I faced, controling Mcqueen if the firmware is different, it can play with the lights, on and off, but you cannot control it or modify the speech for it.

Regards 

Hope this solution helps your kids to enjoy the toy

Download links below

v1.0.0 ==> https://tbit.to/wklgjg25s7xk/theoldest-mcqueen-1.0.0.apk.html


v1.1.0 ==> https://tbit.to/uu7vu13yccy5/1.1.0mcqueen.apk.html


v1.2.0 ==> https://tbit.to/vwar9e6ix1if/mcqueen1.2.0Preferred.apk.html


v1.2.1 ==> https://tbit.to/80pmlrh4ntz1/121McQueen.apk.html


v1.2.3 ==> https://tbit.to/2op2osy34fv6/mcqueen1.2.3.apk.html


All versions in one zip file ==> https://tbit.to/2sr95sf43847/mcqueen-android-mod-no-updates.zip.html

 

OneDrive links:

Password to download ddkits123

1.1.0mcqueen.apk

mcqueen1.2.0Preferred.apk

121McQueen.apk

mcqueen1.2.3.apk

mcqueen-android-mod-no-updates.zip

 

 

Please leave a comment and confirm which version works with your Mcqueen to help other kids

 

 

By: Mutasem Elayyoub