1

When i try to use the setOnClickListener to make Pepper say something or do an animation the aplication crashes. However if i try the same code the method onRobotFocusedGained it works fine.

I tried multiple ways, one of them was to create a method to make Pepper do an animation and then call the method inside the setOnClickListener like this:

private void doAnimation(QiContext qiContext){
// Create an animation object.
Animation myAnimation = AnimationBuilder.with(qiContext)
        .withResources(R.raw.sniffing_b001)
        .build();

// Build the action.
Animate animate = AnimateBuilder.with(qiContext)
        .withAnimation(myAnimation)
        .build();

animate.run();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Register the RobotLifecycleCallbacks to this Activity.
    QiSDK.register(this, this);
    ImageButton button1= findViewById(R.id.button1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            doAnimation();
        }
    });

1 Answers1

0

The piece of code you shared cannot compile because doAnimation requires a QiContext you did not provide in the callback.

Instead, you could disable the button by default and wait for the onRobotFocusGained callback which provides the QiContext to setOnClickListener and enable the button.

Then something else is wrong: building and playing an animation is a long action, and you must not wait for it to end in the main loop.

For convenience I recommend you put the Qi SDK code in onRobotFocusGained which is in a different ("worker") thread than the main loop, and then only start the animation asynchronously in the OnClickListener's callback (which is triggered in the main loop):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Register the RobotLifecycleCallbacks to this Activity.
    QiSDK.register(this, this);
    ImageButton button1 = findViewById(R.id.button1);
    button1.setEnabled(false);
}

@Override
protected void onRobotFocusGained(QiContext qiContext) {
    // Create an animation object.
    Animation myAnimation = AnimationBuilder.with(qiContext)
        .withResources(R.raw.sniffing_b001)
        .build();

    // Build the action.
    final Animate animate = AnimateBuilder.with(qiContext)
        .withAnimation(myAnimation)
        .build();

    // On click, run it.
    ImageButton button1 = findViewById(R.id.button1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            animate.async().run();
        }
    });
    button1.setEnabled(true);
}

@Override
protected void onRobotFocusLost(QiContext qiContext) {
    ImageButton button1 = findViewById(R.id.button1);
    button1.setOnClickListener(null);
    button1.setEnabled(false);
}

I did not try the code, let me know how it works.

Finally, do not forget that errors in asynchronous operations are not climbing up the stack of the main loop, and end up in the logs if you do not handle them.

Victor Paléologue
  • 2,025
  • 1
  • 17
  • 27