1
0

More than 3 years have passed since last update.

Androidによる加速度センサの値を用いた制御とUDP通信のアプリケーション

Posted at

前回との変更点

前回まではLEDを模した画像の表示で加速度センサの制御をしていましたが、今回はラジオボタンとスピナーを用いて加速度センサの制御を行えるように変更しました。

アプリケーションのGUI

このアプリケーションでは、三軸(X,Y,Z)の加速度センサの値をUDP通信で送る。端末内で加速度センサを用いた制御をラジオボタンとスピナーを用いて行えるようにしました。なお、ラジオボタンで制御項目を設定しているので、軸を一つずつしか制御できません。

アプリケーションのGUI

ASUSTab K013の場合

ソースコード

ソケット通信を行うので、Androidmanifest.xmlに下記を追加する。

Androidmanifest.xml
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

次に、画像と音声ファイルを扱うため、app内のresのdrawableとrawを作成し、その中に画像データと音声データを入れる。
その後、スピナーを用いるのでres内にあるvalues内にSpinner.xmlを作成する。

app
 └res
   ├drawable
   │ ├en.jpg
   │ ├en_gleen.jpg
   │ └en_red.jpg
   ├raw
   │ ├xjikum.mp3
   │ ├xjikup.mp3
   │ ├yjikum.mp3
   │ ├yjikup.mp3
   │ ├zjikum.mp3
   │ └zjikup.mp3
   └values
     └Spinner.xml

Spinner.xmlのソースコードは下記のようにする

Spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="items">
        <item>以上</item>
        <item>以下</item>
    </string-array>
</resources>
activity_main.xml
<Spinner
        android:id="@+id/spinner2"
        android:layout_width="67dp"
        android:layout_height="32dp"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="180dp"
        android:entries="@array/items"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/y_if" />

    <Spinner
        android:id="@+id/spinner3"
        android:layout_width="67dp"
        android:layout_height="32dp"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="128dp"
        android:entries="@array/items"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/z_if" />

    <EditText
        android:id="@+id/IP_Address"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="52dp"
        android:layout_marginEnd="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="127.0.0.1"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/Port"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="48dp"
        android:layout_marginEnd="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="8080"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/IP_Address" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="280dp"
        android:text="X:"
        android:textSize="24sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="24dp"
        android:text="Y:"
        android:textSize="24sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="24dp"
        android:text="Z:"
        android:textSize="24sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView2" />

    <TextView
        android:id="@+id/X_Data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="280dp"
        android:text="TextView"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/textView"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/Y_Data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="TextView"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/textView2"
        app:layout_constraintTop_toBottomOf="@+id/X_Data" />

    <TextView
        android:id="@+id/Z_Data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="TextView"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/textView3"
        app:layout_constraintTop_toBottomOf="@+id/Y_Data" />

    <TextView
        android:id="@+id/textView7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="230dp"
        android:text="加速度センサの値"
        android:textSize="24sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/Ran"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="87dp"
        android:layout_marginLeft="87dp"
        android:layout_marginBottom="70dp"
        android:text="通信開始"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginBottom="8dp"
        android:text="IPアドレス"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/IP_Address"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginBottom="8dp"
        android:text="ポート番号"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/Port"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/End"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="87dp"
        android:layout_marginRight="87dp"
        android:layout_marginBottom="70dp"
        android:text="通信解除"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="300dp"
        android:layout_marginEnd="124dp"
        android:text="Delay"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/Delay"
        android:layout_width="159dp"
        android:layout_height="49dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="40dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="100"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView6" />

    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="67dp"
        android:layout_height="32dp"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="248dp"
        android:entries="@array/items"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/x_if" />

    <EditText
        android:id="@+id/y_if"
        android:layout_width="66dp"
        android:layout_height="49dp"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="183dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="500"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/RBGroup" />

    <EditText
        android:id="@+id/x_if"
        android:layout_width="66dp"
        android:layout_height="49dp"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="243dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="500"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/RBGroup" />

    <EditText
        android:id="@+id/z_if"
        android:layout_width="66dp"
        android:layout_height="49dp"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="123dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="500"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/RBGroup" />


    <RadioGroup
        android:id="@+id/RBGroup"
        android:layout_width="125dp"
        android:layout_height="180dp"
        android:layout_marginStart="40dp"
        android:layout_marginBottom="113dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent">


        <RadioButton
            android:id="@+id/x_button"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:text="Xの値が"
            android:textSize="24sp" />

        <RadioButton
            android:id="@+id/y_button"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:text="Yの値が"
            android:textSize="24sp" />

        <RadioButton
            android:id="@+id/z_button"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:text="Zの値が"
            android:textSize="24sp" />
    </RadioGroup>
MainActivity.java
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private SensorManager sensorManager;
    private TextView X_Data_TextView,Y_Data_TextView,Z_Data_TextView;
    private float data_X,data_Y,data_Z;
    private int data_x,data_y,data_z;
    private String Data;
    private Timer timer1,timer2;
    private mTimerTask1 timerTask1;
    private mTimerTask2 timerTask2;
    private Handler handler = new Handler();
    private long Delay;
    private Spinner spinner1,spinner2,spinner3;
    private int spn1,spn2,spn3;
    private int X,Y,Z;
    private String x,y,z;
    SoundPool soundPool;
    int mp3_xp,mp3_xm,mp3_yp,mp3_ym,mp3_zp,mp3_zm;
    private int xp,yp,zp,xm,ym,zm;
    private RadioGroup rg ;
    private RadioButton RBid;

    @Override
    protected void onCreate(Bundle savedInstanceState)  {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //加速度センサーの設定
        sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

        //加速度を表示するテキストの設定
        X_Data_TextView = findViewById(R.id.X_Data);
        Y_Data_TextView = findViewById(R.id.Y_Data);
        Z_Data_TextView = findViewById(R.id.Z_Data);

        //効果音付けるのに必要なやつ
        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_xp = soundPool.load(this, R.raw.xjikup, 1);
        mp3_xm = soundPool.load(this,R.raw.xjikum,1 );
        mp3_yp = soundPool.load(this, R.raw.yjikup, 1);
        mp3_ym = soundPool.load(this,R.raw.yjikum,1 );
        mp3_zp = soundPool.load(this, R.raw.zjikup, 1);
        mp3_zm = soundPool.load(this,R.raw.zjikum,1 );

        //スピナーの設定
        spinner1=findViewById(R.id.spinner1);
        spinner2=findViewById(R.id.spinner2);
        spinner3=findViewById(R.id.spinner3);

        //ラジオボタングループの設定と値取得
        rg =findViewById(R.id.RBGroup);
        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                RBid = findViewById(checkedId);
            }
        });

        //接続の開始と解除ボタンの設定
        Button ran = findViewById(R.id.Ran);
        Button end = findViewById(R.id.End);

        //接続開始ボタンを押したときの処理
        ran.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(null != timer1){
                    timer1.cancel();
                    timer1 = null;
                }

                xp=yp=zp=xm=ym=zm=0;

                //ディレイの設定
                String delay = ((EditText)findViewById(R.id.Delay)).getText().toString();
                Delay = Long.parseLong(delay);

                //UDP通信開始
                timer1 = new Timer();
                timerTask1 = new mTimerTask1();
                timer1.schedule(timerTask1,0, Delay);

                //加速度センサを用いた制御
                timer2 = new Timer();
                timerTask2 = new mTimerTask2();
                timer2.schedule(timerTask2,0,Delay);
            }
        });

        end.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if(null != timer1){
                    timer1.cancel();
                    timer1 = null;
                }

                //IPアドレスとポート番号の設定
                final String address = ((EditText) findViewById(R.id.IP_Address)).getText().toString();
                String port = ((EditText) findViewById(R.id.Port)).getText().toString();
                int Port = Integer.parseInt(port);

                //「exit」を送信する為の設定
                String exit = "exit";
                byte buf[] = new byte[exit.length()];
                try {
                    buf = exit.getBytes("SHIFT_JIS");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                //UDP通信の開始
                InetSocketAddress inetSocketAddress = new InetSocketAddress(address, Port);
                final DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length, inetSocketAddress);
                AsyncTask<DatagramPacket, Void, Void> task = new AsyncTask<DatagramPacket, Void, Void>() {
                    @Override
                    protected Void doInBackground(DatagramPacket... datagramPackets) {
                        DatagramSocket datagramSocket = null;
                        try {
                            datagramSocket = new DatagramSocket();
                            datagramSocket.send(datagramPackets[0]);
                            datagramSocket.close();
                        } catch (SocketException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        return null;
                    }

                };
                task.execute(datagramPacket);

            }
        });

    }



    @Override
    protected void onResume(){
        super.onResume();
        //Event Listener登録
        Sensor accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener((SensorEventListener) this,accel,SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause(){
        super.onPause();
        //Event Listener登録解除
        sensorManager.unregisterListener((SensorEventListener) this);
    }

    //加速度センサの値を表示するのとUDP通信で送信するための設定
    @Override
    public void onSensorChanged(SensorEvent event){
        if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){

            data_X= (500+event.values[0]*25);
            data_Y= (500+event.values[1]*25);
            data_Z= (500+event.values[2]*25);

            data_x = (int)data_X;
            data_y = (int)data_Y;
            data_z = (int)data_Z;
            Data = data_x + " " +
                    data_y + " " +
                    data_z;
            X_Data_TextView.setText(String.valueOf(data_x));
            Y_Data_TextView.setText(String.valueOf(data_y));
            Z_Data_TextView.setText(String.valueOf(data_z));
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy){

    }

    //加速度センサの値を用いての制御
    private class mTimerTask2 extends TimerTask{
        @Override
        public void run() {
            handler.post(new Runnable() {
                @Override
                public void run() {

                    spn1=spinner1.getSelectedItemPosition();
                    spn2=spinner2.getSelectedItemPosition();
                    spn3=spinner3.getSelectedItemPosition();

                    x=((EditText)findViewById(R.id.x_if)).getText().toString();
                    y=((EditText)findViewById(R.id.y_if)).getText().toString();
                    z=((EditText)findViewById(R.id.z_if)).getText().toString();
                    X=Integer.parseInt(x);
                    Y=Integer.parseInt(y);
                    Z=Integer.parseInt(z);

                    if(RBid==(findViewById(R.id.x_button))&&spn1==0&&data_x>=X){
                        xp += 1;
                        if (xp == 1) {
                            yp=zp=xm=ym=zm=0;
                            soundPool.play(mp3_xp, 2, 2, 0, 0, 1f);
                        }
                    }
                    else if(RBid==(findViewById(R.id.x_button))&&spn1==1&&data_x<=X){
                        xm += 1;
                        if (xm == 1) {
                            xp=yp=zp=ym=zm=0;
                            soundPool.play(mp3_xm, 2, 2, 0, 0, 1f);
                        }
                    }
                    else if(RBid==(findViewById(R.id.y_button))&&spn2==0&&data_y>=Y){
                        yp += 1;
                        if (yp == 1) {
                            xp=zp=xm=ym=zm=0;
                            soundPool.play(mp3_yp, 2, 2, 0, 0, 1f);
                        }
                    }
                    else if(RBid==(findViewById(R.id.y_button))&&spn2==1&&data_y<=Y){
                        ym += 1;
                        if (ym == 1) {
                            xp=yp=zp=xm=zm=0;
                            soundPool.play(mp3_ym, 2, 2, 0, 0, 1f);
                        }
                    }
                    else if(RBid==(findViewById(R.id.z_button))&&spn3==0&&data_z>=Z){
                        zp += 1;
                        if (zp == 1) {
                            xp=yp=xm=ym=zm=0;
                            soundPool.play(mp3_zp, 2, 2, 0, 0, 1f);
                        }
                    }
                    else if(RBid==(findViewById(R.id.z_button))&&spn3==1&&data_z<=Z){
                        zm += 1;
                        if (zm == 1) {
                            xp=yp=zp=xm=ym=0;
                            soundPool.play(mp3_zm, 2, 2, 0, 0, 1f);
                        }
                    }
                    else{
                        xp=xm=yp=ym=zp=zm=0;
                    }
                }
            });
        }

    }

    //UDP通信
    private class mTimerTask1 extends TimerTask{
        @Override
        public void run(){

            handler.post(new Runnable() {
                @Override
                public void run() {
                    final String address = ((EditText) findViewById(R.id.IP_Address)).getText().toString();
                    String port = ((EditText) findViewById(R.id.Port)).getText().toString();
                    int Port = Integer.parseInt(port);
                    byte buf[] = new byte[Data.length()];

                    try {
                        buf = Data.getBytes("SHIFT_JIS");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }

                    InetSocketAddress inetSocketAddress = new InetSocketAddress(address, Port);
                    final DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length, inetSocketAddress);


                    AsyncTask<DatagramPacket, Void, Void> task = new AsyncTask<DatagramPacket, Void, Void>() {
                        @Override
                        protected Void doInBackground(DatagramPacket... datagramPackets) {
                            DatagramSocket datagramSocket = null;

                            try {
                                datagramSocket = new DatagramSocket();
                                datagramSocket.send(datagramPackets[0]);
                                datagramSocket.close();
                            } catch (SocketException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                            return null;
                        }

                    };
                    task.execute(datagramPacket);
                }
            });

        }
    }
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0