Since the other day, I have been creating a metronome to create a music game on android. The rough composition of the metronome is ・ You can set the BPM yourself ・ Movement is fixed at 4 beats ・ The lamp that corresponds to the sound lights up one beat at a time. And so on.
I created an app GUI based on the above configuration.

mainactivity.xml
     <ImageView
        android:id="@+id/image1"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="67dp"
        android:layout_marginLeft="67dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="24dp"
        android:layout_marginRight="24dp"
        app:layout_constraintEnd_toStartOf="@+id/image2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/en" />
    <ImageView
        android:id="@+id/image2"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="24dp"
        android:layout_marginRight="24dp"
        app:layout_constraintEnd_toStartOf="@+id/image3"
        app:layout_constraintStart_toEndOf="@+id/image1"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/en" />
    <ImageView
        android:id="@+id/image3"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="24dp"
        android:layout_marginRight="24dp"
        app:layout_constraintEnd_toStartOf="@+id/image4"
        app:layout_constraintStart_toEndOf="@+id/image2"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/en" />
    <ImageView
        android:id="@+id/image4"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="67dp"
        android:layout_marginRight="67dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/image3"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/en" />
    <EditText
        android:id="@+id/BpM"
        android:layout_width="192dp"
        android:layout_height="50dp"
        android:layout_marginTop="95dp"
        android:layout_marginEnd="54dp"
        android:layout_marginRight="54dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="120"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="BPM:"
        android:textSize="26sp"
        app:layout_constraintEnd_toStartOf="@+id/BpM"
        app:layout_constraintTop_toTopOf="parent" />
    <Button
        android:id="@+id/strat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="67dp"
        android:layout_marginLeft="67dp"
        android:layout_marginBottom="102dp"
        android:text="Start"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
    <Button
        android:id="@+id/End"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="68dp"
        android:layout_marginRight="68dp"
        android:layout_marginBottom="102dp"
        android:text="END"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
The program created next is described below.
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.InputType;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
    ImageView Image1,Image2,Image3,Image4;
    int i,Delay;
    float X_Data,Y_Data,Z_Data;
    TextView text1;
    private Timer timer;
    private CountUpTimerTask timerTask;
    private Handler handler = new Handler();
    
    SoundPool soundPool;
    int mp3;
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        Image1 = findViewById(R.id.image1);
        Image2 = findViewById(R.id.image2);
        Image3 = findViewById(R.id.image3);
        Image4 = findViewById(R.id.image4);
        Button startButton = findViewById(R.id.strat);
        Button endButton = findViewById(R.id.End);
        EditText et = findViewById(R.id.BpM);
        Image1.setImageResource(R.drawable.en);
        Image2.setImageResource(R.drawable.en);
        Image3.setImageResource(R.drawable.en);
        Image4.setImageResource(R.drawable.en);
        //Allow only numbers to be entered in EditText
        et.setInputType(InputType.TYPE_CLASS_NUMBER);
        //Convert input value to int type
        String bpm = ((EditText)findViewById(R.id.BpM)).getText().toString();
        int BPM = Integer.parseInt((bpm));
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
        } else {
            AudioAttributes attr = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build();
            soundPool = new SoundPool.Builder()
                    .setAudioAttributes(attr)
                    .setMaxStreams(5)
                    .build();
        }
        mp3 = soundPool.load(this,R.raw.pop,1);
        //STARTButton
        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                i=0;
                String bpm = ((EditText)findViewById(R.id.BpM)).getText().toString();
                int BPM = Integer.parseInt((bpm));
                Delay = 60000/BPM;
                Image1.setImageResource(R.drawable.en);
                Image2.setImageResource(R.drawable.en);
                Image3.setImageResource(R.drawable.en);
                Image4.setImageResource(R.drawable.en);
               if(null != timer){
                   timer.cancel();
                   timer = null;
               }
               timer = new Timer();
               timerTask = new CountUpTimerTask();
               timer.schedule(timerTask,0,Delay);
            }
        });
        //ENDButton
        endButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(null != timer){
                    timer.cancel();
                    timer=null;
                }
                Image1.setImageResource(R.drawable.en);
                Image2.setImageResource(R.drawable.en);
                Image3.setImageResource(R.drawable.en);
                Image4.setImageResource(R.drawable.en);
            }
        });
    }
    class CountUpTimerTask extends TimerTask{
        @Override
        public void run(){
            handler.post(new Runnable() {
                @Override
                public void run() {
                    if (i == 0) {
                        Image1.setImageResource(R.drawable.eng);
                        Image4.setImageResource(R.drawable.en);
                        soundPool.play(mp3,2 , 2, 0, 0, 1f);
                        i++;
                    }
                    else if (i == 1) {
                        Image1.setImageResource(R.drawable.en);
                        Image2.setImageResource(R.drawable.eng);
                        soundPool.play(mp3,2 , 2, 0, 0, 1f);
                        i++;
                    }
                    else if (i == 2) {
                        Image2.setImageResource(R.drawable.en);
                        Image3.setImageResource(R.drawable.eng);
                        soundPool.play(mp3,2 , 2, 0, 0, 1f);
                        i++;
                    }
                    else {
                        Image3.setImageResource(R.drawable.en);
                        Image4.setImageResource(R.drawable.eng);
                        soundPool.play(mp3,2 , 2, 0, 0, 1f);
                        i = 0;
                    }
                }
            });
        }
    }
}
In this program, I don't know if it's due to android or the program, but there is a slight lag during operation. I would like to improve that. The next thing to add is that I want to make a sound every time I shake android in various directions, and I am currently trying to incorporate changes in the accelerometer into the metronome.
Recommended Posts