From a29c986a637649b70466077c88cdd753f155d5ed Mon Sep 17 00:00:00 2001 From: MRSa Date: Sat, 15 Apr 2023 14:40:49 +0900 Subject: [PATCH] =?utf8?q?=E3=82=B0=E3=83=A9=E3=83=95=E3=82=A3=E3=83=83?= =?utf8?q?=E3=82=AF=E3=83=A2=E3=83=BC=E3=83=89=E3=81=AE=E6=96=87=E5=AD=97?= =?utf8?q?=E8=A1=A8=E7=A4=BA=E3=82=92=E8=A6=8B=E7=9B=B4=E3=81=97=E3=80=82?= =?utf8?q?=20MainActivity=E3=81=AEkotlin=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .idea/kotlinc.xml | 6 + build.gradle | 4 + wear/build.gradle | 9 +- wear/src/main/AndroidManifest.xml | 7 +- .../joggingtimer/stopwatch/MainActivity.java | 823 --------------------- .../gokigen/joggingtimer/stopwatch/MainActivity.kt | 700 ++++++++++++++++++ .../stopwatch/graphview/LapTimeGraphView.java | 4 +- wear/src/main/res/values-ja/strings.xml | 2 + wear/src/main/res/values/strings.xml | 2 + 9 files changed, 729 insertions(+), 828 deletions(-) create mode 100644 .idea/kotlinc.xml delete mode 100644 wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/MainActivity.java create mode 100644 wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/MainActivity.kt diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..69e8615 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 2736a7e..4f29ddc 100644 --- a/build.gradle +++ b/build.gradle @@ -2,12 +2,16 @@ buildscript { + ext { + kotlin_version = '1.8.20' + } repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:8.0.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/wear/build.gradle b/wear/build.gradle index a3b9962..8501882 100644 --- a/wear/build.gradle +++ b/wear/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'org.jetbrains.kotlin.android' android { compileSdkVersion 33 @@ -16,12 +17,17 @@ android { } } namespace 'net.osdn.gokigen.joggingtimer' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.google.android.support:wearable:2.9.0' - //implementation 'com.google.android.gms:play-services-wearable:18.0.0' + implementation 'androidx.preference:preference-ktx:1.2.0' implementation 'androidx.recyclerview:recyclerview:1.3.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' @@ -29,5 +35,6 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.wear:wear:1.2.0' + implementation 'androidx.core:core-ktx:1.10.0' compileOnly 'com.google.android.wearable:wearable:2.9.0' } diff --git a/wear/src/main/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml index 848e0e2..e83b7fd 100644 --- a/wear/src/main/AndroidManifest.xml +++ b/wear/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - + @@ -23,6 +24,7 @@ @@ -62,7 +64,8 @@ android:label="@string/result_detail"> + android:name="androidx.wear.activity.ConfirmationActivity" + android:label="@string/confirmation"> diff --git a/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/MainActivity.java b/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/MainActivity.java deleted file mode 100644 index b4d4bfe..0000000 --- a/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/MainActivity.java +++ /dev/null @@ -1,823 +0,0 @@ -package net.osdn.gokigen.joggingtimer.stopwatch; - -import static net.osdn.gokigen.joggingtimer.utilities.SelectReferenceViewModeDialog.PREF_KEY_DISPLAY_LAPGRAPHIC; -import static net.osdn.gokigen.joggingtimer.utilities.SelectReferenceViewModeDialog.PREF_KEY_REFERENCE_TIME_SELECTION; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.Color; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.constraintlayout.widget.ConstraintSet; -import androidx.core.widget.NestedScrollView; -import androidx.fragment.app.FragmentManager; -import androidx.wear.ambient.AmbientModeSupport; -import androidx.wear.widget.BoxInsetLayout; - -import net.osdn.gokigen.joggingtimer.R; -import net.osdn.gokigen.joggingtimer.recordlist.ListActivity; -import net.osdn.gokigen.joggingtimer.stopwatch.graphview.LapTimeGraphView; -import net.osdn.gokigen.joggingtimer.utilities.SelectReferenceViewModeDialog; -import net.osdn.gokigen.joggingtimer.utilities.SetReferenceDialog; -import net.osdn.gokigen.joggingtimer.utilities.TimeStringConvert; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -/** - * - * - */ -public class MainActivity extends AppCompatActivity implements IClickCallback, MyTimerTrigger.ITimeoutReceiver, MyTimerCounter.ICounterStatusNotify, AmbientModeSupport.AmbientCallbackProvider, SelectReferenceViewModeDialog.SelectReferenceCallback -{ - private final String TAG = toString(); - private final IWearableActivityControl controller = new WearableActivityController(); - private final MyTimerCounter counter = new MyTimerCounter(); - private boolean isCounterLapTime = true; - private boolean isLaptimeView = true; - private boolean pendingStart = false; - private int currentLapCount = 0; - private int currentReferenceId = 0; - private ITimerStopTrigger stopTrigger = null; - - /** - * - */ - @Override - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - Log.v(TAG, "onCreate()"); - - setContentView(R.layout.activity_main); - - controller.setup(this, this, counter); - - // Enables Always-on - //getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - //setAmbientEnabled(); - try - { - AmbientModeSupport.AmbientController ambientController = AmbientModeSupport.attach(this); - ambientController.setAutoResumeEnabled(true); - //boolean isAmbient = ambientController.isAmbient(); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - /** - * - */ - @Override - protected void onResume() - { - super.onResume(); - - // インテントを取得する - Intent intent = getIntent(); - String action = intent.getAction(); - Log.v(TAG, "onResume() : " + action); - - boolean isStartTimer = false; - if (action != null) - { - if (action.equals("com.google.android.wearable.action.STOPWATCH")) - { - isStartTimer = true; - } - else if (action.equals("vnd.google.fitness.TRACK")) - { - String activity = intent.getStringExtra("actionStatus"); - if ((activity != null)&&(activity.equals("ActiveActionStatus"))) - { - isStartTimer = true; - } - } - } - isLaptimeView = controller.getDisplayMode(); - currentReferenceId = controller.getReferenceTimerSelection(); - //Log.v(TAG, "isLaptimeView " + isLaptimeView); - - controller.setupReferenceData(); - - if (isStartTimer) - { - // start a timer! - //startTimer(); - pendingStart = true; - } - } - - /** - * - */ - @Override - protected void onPause() - { - super.onPause(); - Log.v(TAG, "onPause()"); - } - - /** - * - * - */ - @Override - public void onStart() - { - super.onStart(); - Log.v(TAG, "onStart()"); - - // データベースのセットアップ - counter.setCallback(this); - controller.setupDatabase(this, false); - } - - /** - * - * - */ - @Override - public void onStop() - { - super.onStop(); - Log.v(TAG, "onStop()"); - if (stopTrigger != null) - { - stopTrigger.forceStop(); - } - controller.exitApplication(this); - } - -/* - @Override - public void onEnterAmbient(Bundle ambientDetails) - { - super.onEnterAmbient(ambientDetails); - Log.v(TAG, "onEnterAmbient()"); - } - - @Override - public void onExitAmbient() - { - super.onExitAmbient(); - Log.v(TAG, "onExitAmbient()"); - //updateTimerLabel(); - } - - @Override - public void onUpdateAmbient() - { - super.onUpdateAmbient(); - Log.v(TAG, "onUpdateAmbient()"); - } -*/ - - /** - * - */ - private void updateTimerLabel() - { - ITimerCounter timerCounter = counter; - int bgColor; - NestedScrollView insetLayout = findViewById(R.id.top_layout); - ConstraintLayout layout = findViewById(R.id.main_layout); - - ImageButton btn1 = findViewById(R.id.btn1); - ImageButton btn2 = findViewById(R.id.btn2); - ImageButton btn3 = findViewById(R.id.btn3); - - updateMainSubCounter(); - - if (timerCounter.isStarted()) - { - bgColor = Color.BLACK; - insetLayout.setBackgroundColor(bgColor); - insetLayout.invalidate(); - - layout.setBackgroundColor(bgColor); - layout.invalidate(); - - btn1.setImageResource(R.drawable.ic_flag_black_24dp); - btn1.setBackgroundColor(bgColor); - - // チャタリング防止(ラップタイムとして、3秒以内は記録しないようボタンを消しておく) - long currentElapsedTime = timerCounter.getCurrentElapsedTime(); - btn1.setVisibility((currentElapsedTime > 3000) ? View.VISIBLE : View.INVISIBLE); - btn1.invalidate(); - - btn2.setImageResource(R.drawable.ic_stop_black_24dp); - btn2.setBackgroundColor(bgColor); - btn2.setVisibility(View.VISIBLE); - btn2.invalidate(); - - btn3.setImageResource(R.drawable.ic_block_black_24dp); - btn3.setBackgroundColor(bgColor); - btn3.setVisibility(View.INVISIBLE); - btn3.invalidate(); - } - else if (timerCounter.isReset()) - { - bgColor = Color.BLACK; - insetLayout.setBackgroundColor(bgColor); - insetLayout.invalidate(); - - layout.setBackgroundColor(bgColor); - layout.invalidate(); - - btn1.setImageResource(R.drawable.ic_play_arrow_black_24dp); - btn1.setBackgroundColor(bgColor); - btn1.setVisibility(View.VISIBLE); - btn1.invalidate(); - - btn2.setImageResource(R.drawable.ic_format_list_bulleted_black_24dp); - btn2.setBackgroundColor(bgColor); - btn2.setVisibility(View.VISIBLE); - btn2.invalidate(); - - btn3.setImageResource(R.drawable.ic_refresh_black_24dp); - btn3.setBackgroundColor(bgColor); - btn3.setVisibility(View.INVISIBLE); - btn3.invalidate(); - } - else - { - bgColor = Color.BLACK; - insetLayout.setBackgroundColor(bgColor); - insetLayout.invalidate(); - - layout.setBackgroundColor(bgColor); - layout.invalidate(); - - btn1.setImageResource(R.drawable.ic_play_arrow_black_24dp); - btn1.setVisibility(View.VISIBLE); - btn1.setBackgroundColor(bgColor); - btn1.invalidate(); - - btn2.setImageResource(R.drawable.ic_format_list_bulleted_black_24dp); - btn2.setVisibility(View.VISIBLE); - btn2.setBackgroundColor(bgColor); - btn2.invalidate(); - - btn3.setImageResource(R.drawable.ic_refresh_black_24dp); - btn3.setVisibility(View.VISIBLE); - btn3.setBackgroundColor(bgColor); - btn3.invalidate(); - } - updateElapsedTimes(); - } - - @Override - public void clickedCounter() - { - // 表示順番を変える - isCounterLapTime = !isCounterLapTime; - } - - /** - * - */ - @Override - public void clickedBtn1() - { - startTimer(); - } - - /** - * - * - */ - private void startTimer() - { - try - { - ITimerCounter timerCounter = counter; - LapTimeGraphView graphView = findViewById(R.id.graph_area); - if (timerCounter.isStarted()) - { - Log.v(TAG, "startTimer() LAP TIME"); - long currentElapsedTime = timerCounter.getCurrentElapsedTime(); - if (currentElapsedTime > 3000) // チャタリング防止(ラップタイムとして、3秒以内は記録しないようにする) - { - currentLapCount++; - long lapTime = timerCounter.timeStamp(); - long refLapTime = timerCounter.getReferenceLapTime(currentLapCount); - long diffTime = (refLapTime == 0) ? 0 : (currentElapsedTime - refLapTime); - controller.vibrate(50); - controller.getDataEntry().appendTimeData(lapTime); - controller.addTimeStamp(currentLapCount, currentElapsedTime, diffTime); - //Log.v(TAG, " [[[ " + currentLapCount + " lap: " + currentElapsedTime + " diff:" + diffTime + " (" + refLapTime + ") ]]]"); - - if (graphView != null) - { - graphView.notifyLapTime(); - } - } - } - else - { - Log.v(TAG, "startTimer() START"); - controller.clearTimeStamp(); - timerCounter.start(); - MyTimerTrigger trigger = new MyTimerTrigger(this, 100, timerCounter); - trigger.startTimer(); - currentLapCount = 0; - stopTrigger = trigger; - controller.timerStarted(true); - controller.vibrate(120); - - Date date = new Date(); - SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US); - String title = sdf1.format(date); - long startTime = timerCounter.getStartTime(); - controller.getDataEntry().createIndex(title, startTime); - - if (graphView != null) - { - graphView.notifyStarted(startTime); - } - } - updateTimerLabel(); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - /** - * - * - */ - private boolean stopTimer() - { - boolean ret = false; - try - { - ITimerCounter timerCounter = counter; - if (timerCounter.isStarted()) - { - timerCounter.stop(); - controller.timerStarted(false); - controller.vibrate(120); - controller.getDataEntry().finishTimeData(timerCounter.getStartTime(), timerCounter.getStopTime()); - - int lapCount = currentLapCount + 1; - long currentElapsedTime = timerCounter.getLastElapsedTime() - timerCounter.getElapsedTime(currentLapCount); - long refLapTime = timerCounter.getReferenceLapTime(lapCount); - long diffTime = (refLapTime == 0) ? 0 : (currentElapsedTime - refLapTime); - controller.addTimeStamp(lapCount, currentElapsedTime, diffTime); - ret = true; - - LapTimeGraphView graphView = findViewById(R.id.graph_area); - if (graphView != null) - { - graphView.notifyStopped(); - } - } - updateTimerLabel(); - } - catch (Exception e) - { - e.printStackTrace(); - } - return (ret); - } - - /** - * - */ - @Override - public void clickedBtn2() - { - if (!((ITimerCounter) counter).isStarted()) - { - // 停止中は、記録一覧を呼び出す - launchListActivity(); - - // ぶるぶる - controller.vibrate(35); - } - updateTimerLabel(); - } - - /** - * - */ - @Override - public void clickedBtn3() - { - ITimerCounter timerCounter = counter; - if (!timerCounter.isStarted()) - { - timerCounter.reset(); - controller.vibrate(50); - controller.clearTimeStamp(); - currentLapCount = 0; - LapTimeGraphView graphView = findViewById(R.id.graph_area); - if (graphView != null) - { - graphView.notifyReset(); - } - } - updateTimerLabel(); - } - - @Override - public void clickedArea() - { - Log.v(TAG, "clickedArea()"); - - } - - @Override - public boolean pushedBtn1() - { - return (false); - } - - @Override - public boolean pushedBtn2() - { - return (stopTimer()); - } - - @Override - public boolean pushedBtn3() - { - return (false); - } - - @Override - public boolean pushedArea() - { - try - { - // 基準値の設定ダイアログを表示する - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - final boolean viewMode = preferences.getBoolean(PREF_KEY_DISPLAY_LAPGRAPHIC, false); - final int selectionId = preferences.getInt(PREF_KEY_REFERENCE_TIME_SELECTION, 0); - final SelectReferenceViewModeDialog.SelectReferenceCallback callback = this; - - this.runOnUiThread(() -> { - try - { - // 基準値&表示モード設定ダイアログを表示する - SelectReferenceViewModeDialog dialog = SelectReferenceViewModeDialog.newInstance(viewMode, selectionId, callback); - FragmentManager manager = getSupportFragmentManager(); - dialog.show(manager, "dialog"); - } - catch (Exception e) - { - e.printStackTrace(); - } - }); - } - catch (Exception e) - { - e.printStackTrace(); - } - return (true); - } - - /** - * - * - */ - @Override - public void timeout() - { - try - { - runOnUiThread(this::updateTimerLabel); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - /** - * - * - */ - private void updateMainSubCounter() - { - TextView main = findViewById(R.id.main_counter); - TextView sub = findViewById(R.id.sub_counter1); - - ITimerCounter timerCounter = counter; - long time1 = timerCounter.getPastTime(); - CharSequence str1 = TimeStringConvert.getTimeString(time1); - CharSequence str2 = ""; - if (timerCounter.isStarted()) - { - long time2 = timerCounter.getCurrentElapsedTime(); - int lapCount = timerCounter.getElapsedCount(); - if ((time2 >= 100) && (lapCount > 1)) - { - str2 = "[" + lapCount + "] " + TimeStringConvert.getTimeString(time2); - } - } - - if ((str2.length() > 0)&&(isCounterLapTime)) - { - // ラップタイムの方を大きく表示する - main.setText(str2); - sub.setText(str1); - } - else - { - main.setText(str1); - sub.setText(str2); - } - main.invalidate(); - sub.invalidate(); - } - - /** - * - * - */ - private void updateElapsedTimes() - { - if (isLaptimeView) - { - updateElapsedTimesGraph(); - } - else - { - updateElapsedTimesText(); - } - } - - /** - * - * - */ - private void updateElapsedTimesGraph() - { - //Log.v(TAG, "updateElapsedTimesGraph()"); - LapTimeGraphView view = findViewById(R.id.graph_area); - view.invalidate(); - } - - /** - * - * - */ - private void updateElapsedTimesText() - { - // Log.v(TAG, "updateElapsedTimesText()"); - } - - /** - * Launch ListActivity - * - */ - private void launchListActivity() - { - Log.v(TAG, "launchListActivity()"); - try - { - Intent intent = new Intent(this, ListActivity.class); - startActivity(intent); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - /** - * - * - */ - @Override - protected void onUserLeaveHint() - { - Log.v(TAG, "onUserLeaveHint() " ); - // ハードキー(ホームボタン)が押されたとき、これがひろえるが... - } - - /** - * - * - */ - @Override - public boolean dispatchKeyEvent(KeyEvent event) - { - Log.v(TAG, "dispatchKeyEvent() : " + event.getAction() + " (" + event.getKeyCode() + ")"); - - return (super.dispatchKeyEvent(event)); - } - - @Override - public void onPointerCaptureChanged(boolean hasCapture) { - super.onPointerCaptureChanged(hasCapture); - } - - /** - * - * - */ - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) - { - Log.v(TAG, "onKeyDown() : " + event.getAction() + " (" + event.getKeyCode() + ")" + keyCode); - if (event.getRepeatCount() == 0) - { - if (keyCode == KeyEvent.KEYCODE_STEM_1) - { - startTimer(); - return (true); - } - else if (keyCode == KeyEvent.KEYCODE_STEM_2) - { - startTimer(); - return (true); - } - else if (keyCode == KeyEvent.KEYCODE_STEM_3) - { - startTimer(); - return (true); - } - } - return (super.onKeyDown(keyCode, event)); - } - - /** - * - * - */ - @Override - public void counterStatusChanged(final boolean forceStartTimer) - { - if (forceStartTimer) - { - try - { - LapTimeGraphView graphView = findViewById(R.id.graph_area); - MyTimerTrigger trigger = new MyTimerTrigger(this, 100, counter); - trigger.startTimer(); - stopTrigger = trigger; - if (graphView != null) - { - graphView.notifyLapTime(); - } - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - runOnUiThread(() -> { - // 自動スタート時の処理。。 - if (pendingStart) - { - startTimer(); - pendingStart = false; - } - - // ラップタイム表示状態の更新 - reloadLapTimeList(forceStartTimer); - - // 表示ビューの切り替え - changeGraphicView(isLaptimeView); - - // 表示のボタン状態を変更 - updateTimerLabel(); - }); - } - - /** - * - * - */ - private void reloadLapTimeList(final boolean forceStartTimer) - { - if (!forceStartTimer) - { - return; - } - - // Adapter と TimerCounterの整合性を確認 - try - { - List lapTimeList; - lapTimeList = ((ITimerCounter) counter).getLapTimeList(); - int lapCount = lapTimeList.size(); - int listCount = controller.getLapTimeCount(); - if (lapCount != listCount) - { - Log.v(TAG, "LAP COUNT IS MISMATCH!!! lap:" + lapCount + " vs list:" + listCount); - int index = 0; - controller.clearTimeStamp(); - long prevTime = lapTimeList.get(0); - for (long lapTime : lapTimeList) - { - index++; - if (prevTime != lapTime) - { - long refLapTime = counter.getReferenceLapTime(index - 1); - long curLapTime = lapTime - prevTime; - long calcRefLapTime = (refLapTime == 0) ? 0 : (curLapTime - refLapTime); - controller.addTimeStamp((index - 1), curLapTime, calcRefLapTime); - } - prevTime = lapTime; - } - currentLapCount = lapCount - 1; - } - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - /** - * - * - */ - private void changeGraphicView(boolean isGraphics) - { - try - { - LapTimeGraphView graphView = findViewById(R.id.graph_area); - ListView listView = findViewById(R.id.laptime_list_area); - if (isGraphics) - { - graphView.setITimerCounter(counter); - graphView.setVisibility(View.VISIBLE); - listView.setVisibility(View.INVISIBLE); - } - else - { - graphView.setVisibility(View.INVISIBLE); - listView.setVisibility(View.VISIBLE); - } - //controller.vibrate(30); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - @Override - public AmbientModeSupport.AmbientCallback getAmbientCallback() - { - return (new AmbientModeSupport.AmbientCallback() { - public void onEnterAmbient(Bundle ambientDetails) - { - Log.v(TAG, "onEnterAmbient()"); - } - public void onExitAmbient(Bundle ambientDetails) - { - Log.v(TAG, "onExitAmbient()"); - //updateTimerLabel(); - } - }); - } - - @Override - public void selectedReferenceViewMode(int referenceId, int viewMode) - { - isLaptimeView = (viewMode != 0); - currentReferenceId = referenceId; - - controller.setDisplayMode(isLaptimeView); - controller.setReferenceTimerSelection(currentReferenceId); - controller.setupReferenceData(); - - Log.v(TAG, "pushedArea() : " + isLaptimeView + " REF: " + currentReferenceId); - - runOnUiThread(() -> { - // ラップタイム表示状態の更新 - reloadLapTimeList(true); - - // 表示ビューの切り替え - changeGraphicView(isLaptimeView); - - // 表示のボタン状態を変更 - updateTimerLabel(); - }); - } -} diff --git a/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/MainActivity.kt b/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/MainActivity.kt new file mode 100644 index 0000000..de9c74e --- /dev/null +++ b/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/MainActivity.kt @@ -0,0 +1,700 @@ +package net.osdn.gokigen.joggingtimer.stopwatch + +import android.content.Intent +import android.graphics.Color +import android.os.Bundle +import android.util.Log +import android.view.KeyEvent +import android.view.View +import android.widget.ImageButton +import android.widget.ListView +import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.widget.NestedScrollView +import androidx.wear.ambient.AmbientModeSupport +import net.osdn.gokigen.joggingtimer.R +import net.osdn.gokigen.joggingtimer.recordlist.ListActivity +import net.osdn.gokigen.joggingtimer.stopwatch.MyTimerCounter.ICounterStatusNotify +import net.osdn.gokigen.joggingtimer.stopwatch.MyTimerTrigger.ITimeoutReceiver +import net.osdn.gokigen.joggingtimer.stopwatch.graphview.LapTimeGraphView +import net.osdn.gokigen.joggingtimer.utilities.SelectReferenceViewModeDialog +import net.osdn.gokigen.joggingtimer.utilities.SelectReferenceViewModeDialog.SelectReferenceCallback +import net.osdn.gokigen.joggingtimer.utilities.TimeStringConvert +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +/** + * + * + */ +class MainActivity : AppCompatActivity(), IClickCallback, ITimeoutReceiver, ICounterStatusNotify, AmbientModeSupport.AmbientCallbackProvider, SelectReferenceCallback +{ + private val controller: IWearableActivityControl = WearableActivityController() + private val counter = MyTimerCounter() + private var isCounterLapTime = true + private var isLaptimeView = true + private var pendingStart = false + private var currentLapCount = 0 + private var currentReferenceId = 0 + private var stopTrigger: ITimerStopTrigger? = null + + /** + * + */ + override fun onCreate(savedInstanceState: Bundle?) + { + super.onCreate(savedInstanceState) + Log.v(TAG, "onCreate()") + setContentView(R.layout.activity_main) + controller.setup(this, this, counter) + try + { + val ambientController = AmbientModeSupport.attach(this) + ambientController.setAutoResumeEnabled(true) + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + /** + * + */ + override fun onResume() + { + super.onResume() + + // インテントを取得する + val intent = intent + val action = intent.action + Log.v(TAG, "onResume() : $action") + var isStartTimer = false + if (action != null) + { + if (action == "com.google.android.wearable.action.STOPWATCH") + { + isStartTimer = true + } + else if (action == "vnd.google.fitness.TRACK") + { + if (intent.getStringExtra("actionStatus") == "ActiveActionStatus") + { + isStartTimer = true + } + } + } + isLaptimeView = controller.displayMode + currentReferenceId = controller.referenceTimerSelection + controller.setupReferenceData() + if (isStartTimer) + { + pendingStart = true + } + } + + /** + * + */ + override fun onPause() + { + super.onPause() + Log.v(TAG, "onPause()") + } + + /** + * + * + */ + public override fun onStart() + { + super.onStart() + Log.v(TAG, "onStart()") + + // データベースのセットアップ + counter.setCallback(this) + controller.setupDatabase(this, false) + } + + /** + * + * + */ + public override fun onStop() + { + super.onStop() + Log.v(TAG, "onStop()") + stopTrigger?.forceStop() + controller.exitApplication(this) + } + + /** + * + */ + private fun updateTimerLabel() + { + val timerCounter: ITimerCounter = counter + val bgColor: Int + val insetLayout = findViewById(R.id.top_layout) + val layout = findViewById(R.id.main_layout) + val btn1 = findViewById(R.id.btn1) + val btn2 = findViewById(R.id.btn2) + val btn3 = findViewById(R.id.btn3) + updateMainSubCounter() + if (timerCounter.isStarted) + { + bgColor = Color.BLACK + insetLayout.setBackgroundColor(bgColor) + insetLayout.invalidate() + layout.setBackgroundColor(bgColor) + layout.invalidate() + btn1.setImageResource(R.drawable.ic_flag_black_24dp) + btn1.setBackgroundColor(bgColor) + + // チャタリング防止(ラップタイムとして、3秒以内は記録しないようボタンを消しておく) + val currentElapsedTime = timerCounter.currentElapsedTime + btn1.visibility = if (currentElapsedTime > 3000) View.VISIBLE else View.INVISIBLE + btn1.invalidate() + btn2.setImageResource(R.drawable.ic_stop_black_24dp) + btn2.setBackgroundColor(bgColor) + btn2.visibility = View.VISIBLE + btn2.invalidate() + btn3.setImageResource(R.drawable.ic_block_black_24dp) + btn3.setBackgroundColor(bgColor) + btn3.visibility = View.INVISIBLE + btn3.invalidate() + } + else if (timerCounter.isReset) + { + bgColor = Color.BLACK + insetLayout.setBackgroundColor(bgColor) + insetLayout.invalidate() + layout.setBackgroundColor(bgColor) + layout.invalidate() + btn1.setImageResource(R.drawable.ic_play_arrow_black_24dp) + btn1.setBackgroundColor(bgColor) + btn1.visibility = View.VISIBLE + btn1.invalidate() + btn2.setImageResource(R.drawable.ic_format_list_bulleted_black_24dp) + btn2.setBackgroundColor(bgColor) + btn2.visibility = View.VISIBLE + btn2.invalidate() + btn3.setImageResource(R.drawable.ic_refresh_black_24dp) + btn3.setBackgroundColor(bgColor) + btn3.visibility = View.INVISIBLE + btn3.invalidate() + } + else + { + bgColor = Color.BLACK + insetLayout.setBackgroundColor(bgColor) + insetLayout.invalidate() + layout.setBackgroundColor(bgColor) + layout.invalidate() + btn1.setImageResource(R.drawable.ic_play_arrow_black_24dp) + btn1.visibility = View.VISIBLE + btn1.setBackgroundColor(bgColor) + btn1.invalidate() + btn2.setImageResource(R.drawable.ic_format_list_bulleted_black_24dp) + btn2.visibility = View.VISIBLE + btn2.setBackgroundColor(bgColor) + btn2.invalidate() + btn3.setImageResource(R.drawable.ic_refresh_black_24dp) + btn3.visibility = View.VISIBLE + btn3.setBackgroundColor(bgColor) + btn3.invalidate() + } + updateElapsedTimes() + } + + override fun clickedCounter() + { + // 表示順番を変える + isCounterLapTime = !isCounterLapTime + } + + /** + * + */ + override fun clickedBtn1() + { + startTimer() + } + + /** + * + * + */ + private fun startTimer() + { + try + { + val timerCounter: ITimerCounter = counter + val graphView = findViewById(R.id.graph_area) + if (timerCounter.isStarted) + { + Log.v(TAG, "startTimer() LAP TIME") + val currentElapsedTime = timerCounter.currentElapsedTime + if (currentElapsedTime > 3000) // チャタリング防止(ラップタイムとして、3秒以内は記録しないようにする) + { + currentLapCount++ + val lapTime = timerCounter.timeStamp() + val refLapTime = timerCounter.getReferenceLapTime(currentLapCount) + val diffTime = if (refLapTime == 0L) 0 else currentElapsedTime - refLapTime + controller.vibrate(50) + controller.dataEntry.appendTimeData(lapTime) + controller.addTimeStamp(currentLapCount.toLong(), currentElapsedTime, diffTime) + graphView?.notifyLapTime() + } + } else { + Log.v(TAG, "startTimer() START") + controller.clearTimeStamp() + timerCounter.start() + val trigger = MyTimerTrigger(this, 100, timerCounter) + trigger.startTimer() + currentLapCount = 0 + stopTrigger = trigger + controller.timerStarted(true) + controller.vibrate(120) + val date = Date() + val sdf1 = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US) + val title = sdf1.format(date) + val startTime = timerCounter.startTime + controller.dataEntry.createIndex(title, startTime) + graphView?.notifyStarted(startTime) + } + updateTimerLabel() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + /** + * + * + */ + private fun stopTimer(): Boolean + { + var ret = false + try + { + val timerCounter: ITimerCounter = counter + if (timerCounter.isStarted) + { + timerCounter.stop() + controller.timerStarted(false) + controller.vibrate(120) + controller.dataEntry.finishTimeData(timerCounter.startTime, timerCounter.stopTime) + val lapCount = currentLapCount + 1 + val currentElapsedTime = timerCounter.lastElapsedTime - timerCounter.getElapsedTime(currentLapCount) + val refLapTime = timerCounter.getReferenceLapTime(lapCount) + val diffTime = if (refLapTime == 0L) 0 else currentElapsedTime - refLapTime + controller.addTimeStamp(lapCount.toLong(), currentElapsedTime, diffTime) + ret = true + val graphView = findViewById(R.id.graph_area) + graphView?.notifyStopped() + } + updateTimerLabel() + } + catch (e: Exception) + { + e.printStackTrace() + } + return ret + } + + /** + * + */ + override fun clickedBtn2() + { + if (!(counter as ITimerCounter).isStarted) + { + // 停止中は、記録一覧を呼び出す + launchListActivity() + + // ぶるぶる + controller.vibrate(35) + } + updateTimerLabel() + } + + /** + * + */ + override fun clickedBtn3() + { + val timerCounter: ITimerCounter = counter + if (!timerCounter.isStarted) + { + timerCounter.reset() + controller.vibrate(50) + controller.clearTimeStamp() + currentLapCount = 0 + val graphView = findViewById(R.id.graph_area) + graphView?.notifyReset() + } + updateTimerLabel() + } + + override fun clickedArea() + { + Log.v(TAG, "clickedArea()") + } + + override fun pushedBtn1(): Boolean + { + return false + } + + override fun pushedBtn2(): Boolean + { + return stopTimer() + } + + override fun pushedBtn3(): Boolean + { + return false + } + + override fun pushedArea(): Boolean + { + try + { + // 基準値の設定ダイアログを表示する + val preferences = androidx.preference.PreferenceManager.getDefaultSharedPreferences( + applicationContext + ) + val viewMode = preferences.getBoolean( + SelectReferenceViewModeDialog.PREF_KEY_DISPLAY_LAPGRAPHIC, + false + ) + val selectionId = preferences.getInt( + SelectReferenceViewModeDialog.PREF_KEY_REFERENCE_TIME_SELECTION, + 0 + ) + val callback: SelectReferenceCallback = this + runOnUiThread { + try { + // 基準値&表示モード設定ダイアログを表示する + val dialog = + SelectReferenceViewModeDialog.newInstance(viewMode, selectionId, callback) + val manager = supportFragmentManager + dialog.show(manager, "dialog") + } catch (e: Exception) { + e.printStackTrace() + } + } + } catch (e: Exception) { + e.printStackTrace() + } + return true + } + + /** + * + * + */ + override fun timeout() + { + try + { + runOnUiThread { updateTimerLabel() } + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + /** + * + * + */ + private fun updateMainSubCounter() + { + val main = findViewById(R.id.main_counter) + val sub = findViewById(R.id.sub_counter1) + val timerCounter: ITimerCounter = counter + val time1 = timerCounter.pastTime + val str1 = TimeStringConvert.getTimeString(time1) + var str2: CharSequence = "" + if (timerCounter.isStarted) + { + val time2 = timerCounter.currentElapsedTime + val lapCount = timerCounter.elapsedCount + if (time2 >= 100 &&(lapCount > 1)) + { + str2 = "[" + lapCount + "] " + TimeStringConvert.getTimeString(time2) + } + } + if (str2.isNotEmpty() && this.isCounterLapTime) + { + // ラップタイムの方を大きく表示する + main.text = str2 + sub.text = str1 + } + else + { + main.text = str1 + sub.text = str2 + } + main.invalidate() + sub.invalidate() + } + + /** + * + * + */ + private fun updateElapsedTimes() + { + if (isLaptimeView) + { + updateElapsedTimesGraph() + } + else + { + updateElapsedTimesText() + } + } + + /** + * + * + */ + private fun updateElapsedTimesGraph() + { + val view = findViewById(R.id.graph_area) + view.invalidate() + } + + /** + * + * + */ + private fun updateElapsedTimesText() + { + // Log.v(TAG, "updateElapsedTimesText()"); + } + + /** + * Launch ListActivity + * + */ + private fun launchListActivity() + { + Log.v(TAG, "launchListActivity()") + try + { + val intent = Intent(this, ListActivity::class.java) + startActivity(intent) + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + /** + * + * + */ + override fun onUserLeaveHint() + { + Log.v(TAG, "onUserLeaveHint() ") + // ハードキー(ホームボタン)が押されたとき、これがひろえるが... + } + + /** + * + * + */ + override fun dispatchKeyEvent(event: KeyEvent): Boolean + { + Log.v(TAG, "dispatchKeyEvent() : " + event.action + " (" + event.keyCode + ")") + return super.dispatchKeyEvent(event) + } + + /** + * + * + */ + override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean + { + Log.v(TAG, "onKeyDown() : " + event.action + " (" + event.keyCode + ")" + keyCode) + if (event.repeatCount == 0) + { + when (keyCode) { + KeyEvent.KEYCODE_STEM_1 -> { + startTimer() + return true + } + KeyEvent.KEYCODE_STEM_2 -> { + startTimer() + return true + } + KeyEvent.KEYCODE_STEM_3 -> { + startTimer() + return true + } + } + } + return super.onKeyDown(keyCode, event) + } + + /** + * + * + */ + override fun counterStatusChanged(forceStartTimer: Boolean) + { + if (forceStartTimer) + { + try + { + val graphView = findViewById(R.id.graph_area) + val trigger = MyTimerTrigger(this, 100, counter) + trigger.startTimer() + stopTrigger = trigger + graphView?.notifyLapTime() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + runOnUiThread { + // 自動スタート時の処理。。 + if (pendingStart) { + startTimer() + pendingStart = false + } + + // ラップタイム表示状態の更新 + reloadLapTimeList(forceStartTimer) + + // 表示ビューの切り替え + changeGraphicView(isLaptimeView) + + // 表示のボタン状態を変更 + updateTimerLabel() + } + } + + /** + * + * + */ + private fun reloadLapTimeList(forceStartTimer: Boolean) + { + if (!forceStartTimer) + { + return + } + + // Adapter と TimerCounterの整合性を確認 + try + { + val lapTimeList: List = (counter as ITimerCounter).lapTimeList + val lapCount = lapTimeList.size + val listCount = controller.lapTimeCount + if (lapCount != listCount) + { + Log.v(TAG, "LAP COUNT IS MISMATCH!!! lap:$lapCount vs list:$listCount") + var index = 0 + controller.clearTimeStamp() + var prevTime = lapTimeList[0] + for (lapTime in lapTimeList) + { + index++ + if (prevTime != lapTime) + { + val refLapTime = counter.getReferenceLapTime(index - 1) + val curLapTime = lapTime - prevTime + val calcRefLapTime = if (refLapTime == 0L) 0 else curLapTime - refLapTime + controller.addTimeStamp((index - 1).toLong(), curLapTime, calcRefLapTime) + } + prevTime = lapTime + } + currentLapCount = lapCount - 1 + } + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + /** + * + * + */ + private fun changeGraphicView(isGraphics: Boolean) + { + try + { + val graphView = findViewById(R.id.graph_area) + val listView = findViewById(R.id.laptime_list_area) + if (isGraphics) + { + graphView.setITimerCounter(counter) + graphView.visibility = View.VISIBLE + listView.visibility = View.INVISIBLE + } + else + { + graphView.visibility = View.INVISIBLE + listView.visibility = View.VISIBLE + } + //controller.vibrate(30); + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + override fun getAmbientCallback(): AmbientModeSupport.AmbientCallback + { + return object : AmbientModeSupport.AmbientCallback() { + override fun onEnterAmbient(ambientDetails: Bundle) { + Log.v(TAG, "onEnterAmbient()") + } + } + } + + override fun selectedReferenceViewMode(referenceId: Int, viewMode: Int) + { + isLaptimeView = viewMode != 0 + currentReferenceId = referenceId + controller.displayMode = isLaptimeView + controller.referenceTimerSelection = currentReferenceId + controller.setupReferenceData() + Log.v(TAG, "pushedArea() : $isLaptimeView REF: $currentReferenceId") + runOnUiThread { + // ラップタイム表示状態の更新 + reloadLapTimeList(true) + + // 表示ビューの切り替え + changeGraphicView(isLaptimeView) + + // 表示のボタン状態を変更 + updateTimerLabel() + } + } + + companion object + { + private val TAG = MainActivity::class.java.simpleName + //private const val REQUEST_CODE_PERMISSIONS = 10 + //private val REQUIRED_PERMISSIONS = arrayOf( + // Manifest.permission.VIBRATE, + // Manifest.permission.WAKE_LOCK, + //) + } +} diff --git a/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/graphview/LapTimeGraphView.java b/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/graphview/LapTimeGraphView.java index 997cc5f..43066a0 100644 --- a/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/graphview/LapTimeGraphView.java +++ b/wear/src/main/java/net/osdn/gokigen/joggingtimer/stopwatch/graphview/LapTimeGraphView.java @@ -280,7 +280,7 @@ public class LapTimeGraphView extends View Paint paint = new Paint(); paint.setColor(Color.WHITE); - paint.setStyle(Paint.Style.STROKE); + paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(0.0f); paint.setAntiAlias(true); //canvas.drawRect(rect, paint); @@ -343,7 +343,7 @@ public class LapTimeGraphView extends View try { float density = context.getResources().getDisplayMetrics().density; - paint.setTextSize(density * 20.0f + 0.5f); + paint.setTextSize(density * 16.0f + 0.5f); } catch (Exception e) { diff --git a/wear/src/main/res/values-ja/strings.xml b/wear/src/main/res/values-ja/strings.xml index 8e0aed8..1ebe2f9 100644 --- a/wear/src/main/res/values-ja/strings.xml +++ b/wear/src/main/res/values-ja/strings.xml @@ -3,6 +3,8 @@ JoggingTimer 記録一覧 ラップタイム詳細 + 確認 + Main ジョギングタイマ HH:MM diff --git a/wear/src/main/res/values/strings.xml b/wear/src/main/res/values/strings.xml index 9859265..be3d1eb 100644 --- a/wear/src/main/res/values/strings.xml +++ b/wear/src/main/res/values/strings.xml @@ -3,6 +3,8 @@ JoggingTimer Records Detail + Confirmation + Main Jogging Timer HH:MM -- 2.11.0