diff --git a/hello-jniCallback/app/src/main/cpp/hello-jnicallback.c b/hello-jniCallback/app/src/main/cpp/hello-jnicallback.c
index 86738e720..e644a6e8b 100644
--- a/hello-jniCallback/app/src/main/cpp/hello-jnicallback.c
+++ b/hello-jniCallback/app/src/main/cpp/hello-jnicallback.c
@@ -278,11 +278,11 @@ Java_com_example_hellojnicallback_MainActivity_startTicks(JNIEnv *env,
* we need to hold and make sure our native thread has finished before return
* for a clean shutdown. The caller is from onPause
*/
-JNIEXPORT void JNICALL Java_com_example_hellojnicallback_MainActivity_StopTicks(
- JNIEnv *env, jobject instance) {
- pthread_mutex_lock(&g_ctx.lock);
- g_ctx.done = 1;
- pthread_mutex_unlock(&g_ctx.lock);
+JNIEXPORT void JNICALL
+Java_com_example_hellojnicallback_MainActivity_stopTicks(JNIEnv *env, jobject instance) {
+ pthread_mutex_lock(&g_ctx.lock);
+ g_ctx.done = 1;
+ pthread_mutex_unlock(&g_ctx.lock);
// waiting for ticking thread to flip the done flag
struct timespec sleepTime;
diff --git a/hello-jniCallback/app/src/main/java/com/example/hellojnicallback/MainActivity.java b/hello-jniCallback/app/src/main/java/com/example/hellojnicallback/MainActivity.java
index cff89cb39..2c8b39fcc 100644
--- a/hello-jniCallback/app/src/main/java/com/example/hellojnicallback/MainActivity.java
+++ b/hello-jniCallback/app/src/main/java/com/example/hellojnicallback/MainActivity.java
@@ -17,33 +17,86 @@
import androidx.annotation.Keep;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory;
+
import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
- int hour = 0;
- int minute = 0;
- int second = 0;
+ MainViewModel model;
TextView tickView;
+ TextView helloJniMsg;
+ Button pauseBtn;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- tickView = (TextView) findViewById(R.id.tickView);
+ tickView = findViewById(R.id.tickView);
+ helloJniMsg = findViewById(R.id.hellojniMsg);
+ pauseBtn = findViewById(R.id.pauseBtn);
+
+ // Fetch the ViewModel, or have one instantiated
+ model = new ViewModelProvider(this,
+ AndroidViewModelFactory.getInstance(this.getApplication())
+ ).get(MainViewModel.class);
+
+ // if the timer has yet to be started, toggle it's state to trigger it's first run
+ // otherwise, and only if it was previously running, start the jni thread for tick callbacks
+ if(!model.started) {
+ model.started = true;
+ toggleTimerState();
+ } else {
+ if(model.running) {
+ startTicks();
+ }
+ }
+
+ setText();
}
+
+ /*
+ * onDestroy gets called for configuration changes.
+ * We make sure that the jni context cleans up so we don't lose track of threads.
+ */
@Override
- public void onResume() {
- super.onResume();
- hour = minute = second = 0;
- ((TextView)findViewById(R.id.hellojniMsg)).setText(stringFromJNI());
- startTicks();
+ protected void onDestroy(){
+ super.onDestroy();
+ if(model.running) {
+ stopTicks();
+ }
}
- @Override
- public void onPause () {
- super.onPause();
- StopTicks();
+ private void toggleTimerState() {
+ model.running = !model.running;
+ setText();
+ if(model.running){
+ model.resetTimer();
+ startTicks();
+ } else {
+ stopTicks();
+ }
+ }
+
+ private void setText() {
+ helloJniMsg.setText(stringFromJNI());
+ tickView.setText(model.time());
+
+ if(model.running) {
+ pauseBtn.setText(R.string.pause);
+ } else {
+ pauseBtn.setText(R.string.resume);
+ }
+
+
+ }
+
+ public void onPauseBtn(View v){
+ toggleTimerState();
}
/*
@@ -51,22 +104,11 @@ public void onPause () {
*/
@Keep
private void updateTimer() {
- ++second;
- if(second >= 60) {
- ++minute;
- second -= 60;
- if(minute >= 60) {
- ++hour;
- minute -= 60;
- }
- }
+ model.updateTimer();
runOnUiThread(new Runnable() {
@Override
public void run() {
- String ticks = "" + MainActivity.this.hour + ":" +
- MainActivity.this.minute + ":" +
- MainActivity.this.second;
- MainActivity.this.tickView.setText(ticks);
+ MainActivity.this.tickView.setText(model.time());
}
});
}
@@ -75,5 +117,5 @@ public void run() {
}
public native String stringFromJNI();
public native void startTicks();
- public native void StopTicks();
+ public native void stopTicks();
}
diff --git a/hello-jniCallback/app/src/main/java/com/example/hellojnicallback/MainViewModel.java b/hello-jniCallback/app/src/main/java/com/example/hellojnicallback/MainViewModel.java
new file mode 100644
index 000000000..839b098e7
--- /dev/null
+++ b/hello-jniCallback/app/src/main/java/com/example/hellojnicallback/MainViewModel.java
@@ -0,0 +1,31 @@
+package com.example.hellojnicallback;
+
+import androidx.lifecycle.ViewModel;
+
+public class MainViewModel extends ViewModel {
+ private int hour = 0;
+ private int minute = 0;
+ private int second = 0;
+ public boolean started = false;
+ public boolean running = false;
+
+ public void updateTimer() {
+ ++second;
+ if(second >= 60) {
+ ++minute;
+ second -= 60;
+ if(minute >= 60) {
+ ++hour;
+ minute -= 60;
+ }
+ }
+ }
+
+ public void resetTimer() {
+ hour = minute = second = 0;
+ }
+
+ public String time() {
+ return hour + ":" + minute + ":" + second;
+ }
+}
diff --git a/hello-jniCallback/app/src/main/res/layout/activity_main.xml b/hello-jniCallback/app/src/main/res/layout/activity_main.xml
index 4f5f3e2c0..774a5f9f3 100644
--- a/hello-jniCallback/app/src/main/res/layout/activity_main.xml
+++ b/hello-jniCallback/app/src/main/res/layout/activity_main.xml
@@ -43,5 +43,16 @@
app:layout_constraintBottom_toBottomOf="@+id/activity_hello_jnicallback"
tools:layout_constraintBottom_creator="0" />
+
+
diff --git a/hello-jniCallback/app/src/main/res/values/strings.xml b/hello-jniCallback/app/src/main/res/values/strings.xml
index 10914504b..9db97dc2f 100644
--- a/hello-jniCallback/app/src/main/res/values/strings.xml
+++ b/hello-jniCallback/app/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
Hello-jniCallback
+ PAUSE
+ RESUME