Skip to content

Crashing on Android whenever calling setInputState or fireState. #319

@JerryBels

Description

@JerryBels

Description

I'm just trying to get a POC working, and using your base example I'm unable to have any change in my runtime without crashing. And when it doesn't crash, it doesn't apply the wanted changes anyway, and stops the animation.

Provide a Repro

import Rive, { RiveRef } from 'rive-react-native';
import { StyleSheet, Text, View, Pressable } from 'react-native';
import React, { useState, useRef } from 'react';

export default function RiveDemo() {
  const [artboardName, setArtboardName] = useState('Avatar 2');
  const [isPlaying, setIsPlaying] = useState(false);
  const [isHappyState, setIsHappyState] = useState(false);
  const [isSadState, setIsSadState] = useState(false);
  const riveRef = useRef<RiveRef>(null);

  // riveRef.current?.getBooleanState('isSad').then(console.log);
  // riveRef.current?.getBooleanState('nope').then(console.log);

  const toggleArtboard = () => {
    setArtboardName(prev => (prev === 'Avatar 1' ? 'Avatar 2' : 'Avatar 1'));
    // Reset might be needed depending on desired behavior when artboard changes
    riveRef.current?.reset();
    setIsPlaying(false); // Stop playback when artboard changes
    // Reset mood states when artboard changes
    setIsHappyState(false);
    setIsSadState(false);
    riveRef.current?.setInputState('avatar', 'isHappy', false);
    riveRef.current?.setInputState('avatar', 'isSad', false);
  };

  const togglePlayPause = () => {
    if (isPlaying) {
      riveRef.current?.pause();
    } else {
      // Play the state machine defined in the Rive component
      riveRef.current?.play(undefined, undefined, undefined, true);
    }
    setIsPlaying(!isPlaying);
  };

  const toggleHappy = () => {
    const newState = !isHappyState;
    riveRef.current?.setInputState('avatar', 'isHappy', newState);
    setIsHappyState(newState);
    // Optionally ensure moods are mutually exclusive
    if (newState && isSadState) {
      riveRef.current?.setInputState('avatar', 'isSad', false);
      setIsSadState(false);
    }
  };

  const toggleSad = () => {
    const newState = !isSadState;
    riveRef.current?.setInputState('avatar', 'isSad', newState);
    setIsSadState(newState);
    // Optionally ensure moods are mutually exclusive
    if (newState && isHappyState) {
       riveRef.current?.setInputState('avatar', 'isHappy', false);
       setIsHappyState(false);
    }
  };

  return (
    <View style={styles.container}>
      <Rive
        ref={riveRef}
        url="https://public.rive.app/community/runtime-files/2195-4346-avatar-pack-use-case.riv"
        artboardName={artboardName} // Use state for artboardName
        stateMachineName="avatar"
        style={{ width: 300 }}
        onStateChanged={(stateMachineName, stateName) => {
          console.log('stateMachineName', stateMachineName);
          console.log('stateName', stateName);
        }}
        animationName='happy'
        onRiveEventReceived={(event) => {
          console.log('event', event);
        }}
        children={<Text>Hello</Text>}
        key={`${artboardName}-${isHappyState}-${isSadState}`}
        
      />
      <View style={styles.controlsContainer}>
        <Pressable onPress={toggleArtboard} style={styles.button}>
          <Text style={styles.buttonText}>Artboard: {artboardName}</Text>
        </Pressable>
        <Pressable onPress={togglePlayPause} style={styles.button}>
          <Text style={styles.buttonText}>{isPlaying ? 'Pause' : 'Play'}</Text>
        </Pressable>
        <Pressable onPress={toggleHappy} style={styles.button}>
          <Text style={styles.buttonText}>Toggle Happy ({isHappyState ? 'On' : 'Off'})</Text>
        </Pressable>
        <Pressable onPress={toggleSad} style={styles.button}>
          <Text style={styles.buttonText}>Toggle Sad ({isSadState ? 'On' : 'Off'})</Text>
        </Pressable>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1, // Use flex: 1 instead of height: '100%'
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center', // Center content vertically
  },
  controlsContainer: {
    marginTop: 20,
    alignItems: 'center',
  },
  button: {
    backgroundColor: '#007AFF',
    paddingVertical: 10,
    paddingHorizontal: 20,
    borderRadius: 5,
    marginBottom: 10,
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
  },
});

Source .riv/.rev file

Yours: https://public.rive.app/community/runtime-files/2195-4346-avatar-pack-use-case.riv

Expected behavior

Well, for the triggers to work :)

Device & Versions (please complete the following information)

  • Device: Android emulator and Pixel 8a
  • OS: Android 35
  • NPM Version: 10.9.2

Additional context

This is just a POC, I wanted to start like that and then at some point swap parts on the chosen avatar from a list of parts displayed below. The POC is crashing, but should you find a solution, I guess replacing the body parts would be done through setInputState, like setInputState('avatar', 'mouth', '10')?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions