benjamindean / flutter_vibration

Handle vibration on iOS and Android in Flutter apps
217 stars 67 forks source link

Vibration works only once but never more than that #101

Closed airwavetechio-gh closed 2 months ago

airwavetechio-gh commented 2 months ago

Hi there,

I have a screen that is a chat window, and every time the sender adds a message, it should vibrate.

I've tried to add some handling of the vibration but nothing seems to get the vibration to work after the initial addQuestion has been invoked.

Here's where I'm at in terms of code at the moment:


bool _isVibrateOn = true;

void addQuestion(String question) async {
    if (_isVibrateOn) {
      logger.d('Should be vibin');
      _triggerVibration();
    }
    setState(() {
      questions.last['text'] = question;
      questions.last['isLoading'] = false;
    });
    scrollToBottom();
  }

  Future<void> _triggerVibration() async {
    if (await Vibration.hasVibrator() ?? false) {
      if (await Vibration.hasCustomVibrationsSupport() ?? false) {
        Vibration.cancel(); // Stop any existing vibration
        await Vibration.vibrate(duration: 100); // Start new vibration
      } else {
        Vibration.cancel();
        await Vibration.vibrate();
        await Future.delayed(Duration(milliseconds: 100));
        Vibration.cancel();
      }
    }
  }

Any thoughts on how I can get the vibration to go off on demand? Thanks!

benjamindean commented 2 months ago

Hey! What happens with _isVibrateOn? Does it by any chance sets to false somewhere? Also, try awaiting for all the futures:

bool _isVibrateOn = true;

void addQuestion(String question) async {
  if (_isVibrateOn) {
    logger.d('Should be vibin');

    await _triggerVibration();
  }

  setState(() {
    questions.last['text'] = question;
    questions.last['isLoading'] = false;
  });

  scrollToBottom();
}

Future<void> _triggerVibration() async {
  if (await Vibration.hasVibrator() ?? false) {
    if (await Vibration.hasCustomVibrationsSupport() ?? false) {
      await Vibration.cancel(); // Stop any existing vibration
      await Vibration.vibrate(duration: 100); // Start new vibration
    } else {
      await Vibration.cancel();
      await Vibration.vibrate();
    }
  }
}
airwavetechio-gh commented 2 months ago

Hi, thanks for responding. I updated my function as suggested, using await, and still have the same issue.

I also removed the bool _isVibrateOn for now so that there isn't anything triggering that, just in case. I see the statements in my logger right before and after when the vibration should occur.

For more information about my setup, testing on real device, Iphone 15 Pro Max, IOS 17.4.1, vibration: ^1.8.4

airwavetechio-gh commented 2 months ago

Upon further testing, this has something to do with the way I'm leveraging the camera while triggering the vibration. Multiple vibrations work until after I use the camera. We can probably close this for now since I will have to figure out the best way to work around this.

airwavetechio-gh commented 2 months ago

For those who want to know, the only way I was able to get this to work was to refresh my camera's init flow. Essentially refresh my camera preview widget.

It added a little snag in my UX though as the screen goes blank for a second or less after the camera gets used once but that refresh resets whatever lock the camera puts on the vibrator, or at least, that's what I think.