Pessoal, a ideia é usar o onTouchListener comparando o MotionEvent mesmo. No entanto, isso não é o suficiente. Na realidade, o código é um pouco mais complicado que isso.
Temos três MotionEvents principais: down, up e move, o grande problema é que o down é disparado apenas uma vez quando o dedo toca o button pela primeira vez. Por isso que fazer um if só fará seu código ser disparado uma única vez.
Então, uma ideia seria fazer um while, porém não teríamos como controlar a condição de parada desse laço, fazendo nossa app ficar num comportamento parecido com loop infinito. Então, um jeito que funciona seria fazer um controlador como filho de uma AsyncTask e aproveitar o cancel dessa classe para conseguirmos matar esse “loop infinito”.
Como essa AsyncTask só faz sentido para esse botão, deixei-a como uma classe interna, obtendo o seguinte código:
public class MainActivity extends AppCompatActivity {
private boolean clicando = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
Button botao = (Button) findViewById(R.id.botao);
botao.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, final MotionEvent motionEvent) {
ControleDoLed controle = new ControleDoLed();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
clicando = true;
controle.execute();
break;
case MotionEvent.ACTION_UP:
clicando = false;
controle.cancel(true);
break;
}
return false;
}
});
}
private class ControleDoLed extends AsyncTask{
@Override
protected Object doInBackground(Object[] objects) {
while (clicando) {
Log.i("CONTROLE", "led aceso");
}
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
Log.i("CONTROLE", "led apagado");
}
}
}