stop watch

public class MainActivity extends AppCompatActivity {

    private long startTime;
    private long elapsedTime = 0l;

    private Handler handler = new Handler();
    private Runnable updateTimer;

    private Button startButton;
    private Button stopButton;
    private Button resetButton;
    private TextView timerLabel;

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

        startButton = (Button) findViewById(R.id.startButton);
        stopButton = (Button) findViewById(R.id.stopButton);
        resetButton = (Button) findViewById(R.id.resetButton);
        timerLabel = (TextView) findViewById(R.id.timerLabel);

        setButtonState(true,false,false);
    }

    public void setButtonState(boolean start, boolean stop, boolean reset){
        startButton.setEnabled(true);
        stopButton.setEnabled(false);
        resetButton.setEnabled(false);

    }

    public void startTimer(View view){
        // startTimeの取得
        startTime = SystemClock.elapsedRealtime(); // 起動してからの経過時間(ミリ秒)

        // 一定時間ごとに現在の経過時間を表示
        // handler -> Runnable(処理) -> UI
        updateTimer = new Runnable(){
            @Override
            public void run(){
                long t = SystemClock.elapsedRealtime() - startTime + elapsedTime;
                SimpleDateFormat sdf = new SimpleDateFormat("mm:ss.SSS", Locale.US);
                timerLabel.setText(sdf.format(t));
                handler.removeCallbacks(updateTimer);
                handler.postDelayed(updateTimer, 10);
            }
        };
        handler.postDelayed(updateTimer, 10);


        // ボタンの操作
        setButtonState(false, true, false);
    }

    public void stopTimer(View view){
        elapsedTime += SystemClock.elapsedRealtime() - startTime;
        handler.removeCallbacks(updateTimer);
        setButtonState(true,false, true);
    }

    public void resetTimer(View view){
        elapsedTime = 0;
        timerLabel.setText("00:00.000");
        setButtonState(true,false, false);
    }
}

runnable、SimpleDateFormat、removeCallbacks、handlerがよくわからんな。

SystemClock.elapsedRealtime();

SystemClock.elapsedRealtime();はdeveloperの公式ページに掲載されています。
https://developer.android.com/reference/android/os/SystemClock
elapsedRealtime() and elapsedRealtimeNanos() return the time since the system was booted, and include deep sleep. This clock is guaranteed to be monotonic, and continues to tick even when the CPU is in power saving modes, so is the recommend basis for general purpose interval timing.

public void startTimer(View view){
        // startTimeの取得
        startTime = SystemClock.elapsedRealtime(); // 起動してからの経過時間(ミリ秒)

        // 一定時間ごとに現在の経過時間を表示
        // handler -> Runnable(処理) -> UI
        updateTimer = new Runnable(){
            @Override
            public void run(){
                long t = SystemClock.elapsedRealtime() - startTime;
                SimpleDateFormat sdf = new SimpleDateFormat("mm:ss.SSS", Locale.US);
                timerLabel.setText(sdf.format(t));
                handler.removeCallbacks(updateTimer);
                handler.postDelayed(updateTimer, 10);
            }
        };
        handler.postDelayed(updateTimer, 10);


        // ボタンの操作
        setButtonState(false, true, false);
    }

setEabled(true)とsetEnabled(false)

setEnabledでtrueだとbuttonを押せる。

private Button startButton;
    private Button stopButton;
    private Button resetButton;

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

        startButton = (Button) findViewById(R.id.startButton);
        stopButton = (Button) findViewById(R.id.stopButton);
        resetButton = (Button) findViewById(R.id.resetButton);

        setButtonState(true,false,false);
    }

    public void setButtonState(boolean start, boolean stop, boolean reset){
        startButton.setEnabled(true);
        stopButton.setEnabled(false);
        resetButton.setEnabled(false);

    }

firstname, lastname, phone, emailをintentする

public void getScore(View view){


        // edittextを取得
        EditText fEditText = (EditText) findViewById(R.id.firstnEditText);
        EditText lEditText = (EditText) findViewById(R.id.lastnEditText);
        EditText pEditText = (EditText) findViewById(R.id.phoneEditText);
        EditText mEditText = (EditText) findViewById(R.id.mailEditText);
        // edittextの中身を取得
        String firstName = fEditText.getText().toString().trim();
        String lastName = lEditText.getText().toString().trim();
        String myPhone = pEditText.getText().toString().trim();
        String myMail = mEditText.getText().toString().trim();

        Pattern p = Pattern.compile("^[0-9\\-]+");
        Matcher m = p.matcher(myPhone);

        Pattern mp = Pattern.compile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$");
        Matcher mm = mp.matcher(myMail);

        // 中身を観て条件分岐
       if (firstName.equals("")){
             fEditText.setError("Please enter your first name!");
        } else if(lastName.equals("")){
           lEditText.setError("Please enter your last name!");
        } else if(myPhone.equals("") || m.find() == false){
           pEditText.setError("Please enter your phone number!");
        }else if(myMail.equals("") || mm.find() == false){
           mEditText.setError("Please enter your valid email");
        } else {
            Intent intent = new Intent(this, MyResult.class);
            intent.putExtra(EXTRA_MYFNAME, firstName);
           intent.putExtra(EXTRA_MYLNAME, lastName);
           intent.putExtra(EXTRA_MYPHONE, myPhone);
           intent.putExtra(EXTRA_MYMAIL, myMail);
            startActivity(intent);
        }
    }

入力すると

引き継がれる! EditTextは良さそうですね。

rfc5322 3.4.1. Addr-Spec Specification

メールアドレスの仕様
https://tools.ietf.org/html/rfc5322#page-17

以下抜粋
—-
An addr-spec is a specific Internet identifier that contains a
locally interpreted string followed by the at-sign character (“@”,
ASCII value 64) followed by an Internet domain. The locally
interpreted string is either a quoted-string or a dot-atom. If the
string can be represented as a dot-atom (that is, it contains no
characters other than atext characters or “.” surrounded by atext
characters), then the dot-atom form SHOULD be used and the quoted-
string form SHOULD NOT be used. Comments and folding white space
SHOULD NOT be used around the “@” in the addr-spec.

addr-spec = local-part “@” domain

local-part = dot-atom / quoted-string / obs-local-part

domain = dot-atom / domain-literal / obs-domain

domain-literal = [CFWS] “[” *([FWS] dtext) [FWS] “]” [CFWS]

dtext = %d33-90 / ; Printable US-ASCII
%d94-126 / ; characters not including
obs-dtext ; “[“, “]”, or “\”
——-
使えるのは、半角英数字か、「!#$%&’*+-/=?^_`{|}~」
で、正規表現で書くと、

^[\w!#%&'/=~`\*\+\?\{\}\^\$\-\|]+(\.[\w!#%&'/=~`\*\+\?\{\}\^\$\-\|]+)*@[\w!#%&'/=~`\*\+\?\{\}\^\$\-\|]+(\.[\w!#%&'/=~`\*\+\?\{\}\^\$\-\|]+)*$

実際に試してみる。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Playground {
    public static void main(String[ ] args) {
        
        String str = "hogehogehoge.jp";
        
        Pattern p = Pattern.compile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$");
        Matcher m = p.matcher(str);
        
        if(m.find() == true){
            System.out.println("OK");
        } else{
            System.out.println("NG");
        }
        
    }
}

NGとなる。

メールアドレスの判定をする。

public void getScore(View view){


        // edittextを取得
        EditText fEditText = (EditText) findViewById(R.id.firstnEditText);
        EditText lEditText = (EditText) findViewById(R.id.lastnEditText);
        EditText pEditText = (EditText) findViewById(R.id.phoneEditText);
        EditText mEditText = (EditText) findViewById(R.id.mailEditText);
        // edittextの中身を取得
        String firstName = fEditText.getText().toString().trim();
        String lastName = lEditText.getText().toString().trim();
        String myPhone = pEditText.getText().toString().trim();
        String myMail = mEditText.getText().toString().trim();

        Pattern p = Pattern.compile("^[0-9\\-]+");
        Matcher m = p.matcher(myPhone);

        Pattern mp = Pattern.compile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\\\.[a-zA-Z0-9-]+)*$");
        Matcher mm = mp.matcher(myMail);

        // 中身を観て条件分岐
       if (firstName.equals("")){
             fEditText.setError("Please enter your first name!");
        } else if(lastName.equals("")){
           lEditText.setError("Please enter your last name!");
        } else if(myPhone.equals("") || m.find() == false){
           pEditText.setError("Please enter your phone number!");
        }else if(myMail.equals("") || mm.find() == false){
           mEditText.setError("Please enter your valid email");
        } else {
            Intent intent = new Intent(this, MyResult.class);
            intent.putExtra(EXTRA_MYNAME, firstName);
            startActivity(intent);
        }
    }

EditTextがnullもしくは[0-9\\-]を判定する

MainActivity.javaで電話番号の判定
Pattern p = Pattern.compile(“^[0-9\\-]+”); として、EditTextが数字・ハイフンか正規表現を行う
javaのORは||なので、myPhone.equals(“”) || m.find() == false とする

public void getScore(View view){


        // edittextを取得
        EditText fEditText = (EditText) findViewById(R.id.firstnEditText);
        EditText lEditText = (EditText) findViewById(R.id.lastnEditText);
        EditText pEditText = (EditText) findViewById(R.id.phoneEditText);
        EditText mEditText = (EditText) findViewById(R.id.mailEditText);
        // edittextの中身を取得
        String firstName = fEditText.getText().toString().trim();
        String lastName = lEditText.getText().toString().trim();
        String myPhone = pEditText.getText().toString().trim();
        String myMail = mEditText.getText().toString().trim();

        Pattern p = Pattern.compile("^[0-9\\-]+");
        Matcher m = p.matcher(myPhone);

        // 中身を観て条件分岐
       if (firstName.equals("")){
             fEditText.setError("Please enter your first name!");
        } else if(lastName.equals("")){
           lEditText.setError("Please enter your last name!");
        } else if(myPhone.equals("") || m.find() == false){
           pEditText.setError("Please enter your phone number!");
        }else if(myMail.equals("")){
           mEditText.setError("Please enter your first name!");
        } else {
            Intent intent = new Intent(this, MyResult.class);
            intent.putExtra(EXTRA_MYNAME, firstName);
            startActivity(intent);
        }
    }

おお、Androidの開発の仕方が少しづつ掴めてきた。まずjavaで関数の挙動を確認して、studioで実機確認。php+vagrantとほぼ同じ。

続けてメールアドレスの判定も行いたい

郵便番号の正規表現

String str = "333-5555";
Pattern p = Pattern.compile("^[0-9]{3}-[0-9]{4}$");

ハイフンがない固定電話の電話番号なら、

Pattern p = Pattern.compile("^[0-9]{10}$");

携帯と固定電話の混入ならワイルドカード

Pattern p = Pattern.compile("^[0-9]*$");

ハイフンと数字なら、ハイフンをエスケープする

Pattern p = Pattern.compile("^[0-9\\-]+");

これをMainActivity.javaに入れてEditTextの判定したい。

java正規表現2

import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Playground {
    public static void main(String[ ] args) {
        
        String str = "123A5";
        
        Pattern p = Pattern.compile("^[0-9]*$");
        Matcher m = p.matcher(str);
        
        System.out.println(m.find());
    }
}

falseになります。
Pattern p = Pattern.compile(“^[0-9]”); とすればtrue
123の次にAが入っているので、Pattern p = Pattern.compile(“^[0-9a-zA-Z]*$”);とすれば、trueに変わります。

if else文で書きます。

public static void main(String[ ] args) {
        
        String str = "123A5";
        
        Pattern p = Pattern.compile("^[0-9a-zA-Z]*$");
        Matcher m = p.matcher(str);
        
        if(m.find() == true){
            System.out.println("OK");
        } else{
            System.out.println("NG");
        }
        
    }