From 118330dfe1ce2885f5d966408cb532a7346e8d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Bj=C3=A4reholt?= Date: Sun, 27 Nov 2022 15:55:29 +0100 Subject: [PATCH 1/4] build: added test targets to Makefile --- Makefile | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Makefile b/Makefile index ae5f57b3..d9f2c75a 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,29 @@ build-apk-debug: $(APKDIR)/debug/mobile-debug.apk $(APKDIR)/androidTest/debug/mo mkdir -p dist cp -r $(APKDIR) dist +# Test targets +test: test-unit test-e2e + +test-unit: + ./gradlew test + +test-e2e: + # Run only screenshot test, for now + ./gradlew connectedAndroidTest \ + -Pandroid.testInstrumentationRunnerArguments.class=net.activitywatch.android.ScreenshotTest + +test-e2e-adb: + # Requires that: + # - you have adb installed + # - you have a device connected + # - you have the apk installed + # Run only screenshot test, for now + adb shell pm list instrumentation + adb shell am instrument -w \ + -e class net.activitywatch.android.ScreenshotTest + net.activitywatch.android.debug.test/androidx.test.runner.AndroidJUnitRunner + +# APK targets $(APKDIR)/release/mobile-release-unsigned.apk: TERM=xterm ./gradlew assembleRelease tree $(APKDIR) @@ -34,6 +57,7 @@ $(APKDIR)/androidTest/debug/mobile-debug-androidTest.apk: TERM=xterm ./gradlew assembleAndroidTest tree $(APKDIR) +# Signed release APK dist/aw-android.apk: $(APKDIR)/release/mobile-release-unsigned.apk @# TODO: Name the APK based on the version number or commit hash. mkdir -p dist From e11a222fbefdfb40723940a0c149efc494973fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Bj=C3=A4reholt?= Date: Sun, 27 Nov 2022 15:58:09 +0100 Subject: [PATCH 2/4] build: updated Android Studio files --- .gitignore | 1 + .idea/compiler.xml | 2 +- .idea/jarRepositories.xml | 5 +++++ .idea/misc.xml | 2 +- .idea/runConfigurations.xml | 12 ------------ 5 files changed, 8 insertions(+), 14 deletions(-) delete mode 100644 .idea/runConfigurations.xml diff --git a/.gitignore b/.gitignore index 159132cc..bb4a26d4 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ captures/ .idea/dictionaries .idea/libraries .idea/caches +.idea/deploymentTargetDropDown.xml # Keystore files # Uncomment the following lines if you do not want to check your keystore files in. diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 61a9130c..fb7f4a8a 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml index a5f05cd8..e34606cc 100644 --- a/.idea/jarRepositories.xml +++ b/.idea/jarRepositories.xml @@ -21,5 +21,10 @@ - + diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460d..00000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file From e1af740843e281ea99a441189f26ea7358dcc73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Bj=C3=A4reholt?= Date: Sun, 27 Nov 2022 15:59:18 +0100 Subject: [PATCH 3/4] fix: improved asset extraction --- .../activitywatch/android/AssetExtractor.kt | 33 +++++++++++++++-- .../activitywatch/android/RustInterface.kt | 35 ++++++++++++------- .../android/fragments/TestFragment.kt | 2 +- .../android/fragments/WebUIFragment.kt | 2 ++ 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/mobile/src/main/java/net/activitywatch/android/AssetExtractor.kt b/mobile/src/main/java/net/activitywatch/android/AssetExtractor.kt index 1a81d81e..3069684d 100644 --- a/mobile/src/main/java/net/activitywatch/android/AssetExtractor.kt +++ b/mobile/src/main/java/net/activitywatch/android/AssetExtractor.kt @@ -1,6 +1,7 @@ package net.activitywatch.android import android.content.Context +import android.content.pm.PackageManager import android.util.Log import java.io.File import java.io.FileOutputStream @@ -8,9 +9,31 @@ import java.io.FileOutputStream object AssetExtractor { private const val TAG = "AssetExtractor" - // TODO: Extract assets only if updated instead of using overwrite = true + // Returns the extracted versionCode, or 0 if it doesn't exist, + // used to check if we need to extract the assets again. + private fun getExtractedVersion(context: Context): Int { + val file = File(context.cacheDir, "last_extracted_version") + if(file.exists()) { + return file.readText().toInt() + } + return 0 + } + + // Sets extracted version to the current versionCode + private fun setExtractedVersion(context: Context) { + val version = BuildConfig.VERSION_CODE + val file = File(context.cacheDir, "last_extracted_version") + file.writeText(version.toString()) + } + + // Extracts all assets to the cacheDir + // Tries to detect updated using the versionCode, + // but will always extract if the file doesn't exist or if in debug mode. // From: https://stackoverflow.com/a/8475135/965332 - fun extractAssets(path: String, context: Context, overwrite: Boolean = true) { + fun extractAssets(path: String, context: Context, force_overwrite: Boolean = false) { + val extractedOlder = getExtractedVersion(context) != BuildConfig.VERSION_CODE + val overwrite = force_overwrite || extractedOlder || BuildConfig.DEBUG + val filenames = context.assets.list(path) //Log.w(TAG, "path: $path") //Log.w(TAG, "files: ${filenames!!.joinToString(", ")}") @@ -57,5 +80,9 @@ object AssetExtractor { } } } + + if(extractedOlder) { + setExtractedVersion(context) + } } -} \ No newline at end of file +} diff --git a/mobile/src/main/java/net/activitywatch/android/RustInterface.kt b/mobile/src/main/java/net/activitywatch/android/RustInterface.kt index e6a9f007..e615e16c 100644 --- a/mobile/src/main/java/net/activitywatch/android/RustInterface.kt +++ b/mobile/src/main/java/net/activitywatch/android/RustInterface.kt @@ -2,14 +2,18 @@ package net.activitywatch.android import android.content.Context import android.os.AsyncTask +import android.os.Handler +import android.os.Looper import android.system.Os import android.util.Log +import android.widget.Toast import net.activitywatch.android.models.Event import org.json.JSONArray import org.json.JSONException import org.json.JSONObject import org.threeten.bp.Instant import java.io.File +import java.util.concurrent.Executors private const val TAG = "RustInterface" @@ -51,22 +55,27 @@ class RustInterface constructor(context: Context? = null) { fun startServerTask(context: Context) { if(!serverStarted) { serverStarted = true - ServerTask(context).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) + val executor = Executors.newSingleThreadExecutor() + val handler = Handler(Looper.getMainLooper()) + executor.execute { + // will not block the UI thread + + // Extract web assets + AssetExtractor.extractAssets("webui", context) + + // Start server + Log.w(TAG, "Starting server...") + val assetDir = context.cacheDir.path + File.separator + "webui" + startServer(assetDir) + + handler.post { + // will run on UI thread after the task is done + } + } Log.w(TAG, "Server started") } } - // TODO: This probably shouldn't be an AsyncTask - private inner class ServerTask(val context: Context) : AsyncTask() { - override fun doInBackground(vararg inputs: String) { - AssetExtractor.extractAssets("webui", context) - - Log.w(TAG, "Starting server...") - val assetDir = context.cacheDir.path + File.separator + "webui" - startServer(assetDir) - } - } - fun createBucketHelper(bucket_id: String, type: String, hostname: String = "unknown", client: String = "aw-android") { if(bucket_id in getBucketsJSON().keys().asSequence()) { Log.i(TAG, "Bucket with ID '$bucket_id', already existed. Not creating.") @@ -114,4 +123,4 @@ class RustInterface constructor(context: Context? = null) { Log.w(TAG, getBucketsJSON().toString(2)) Log.w(TAG, getEventsJSON("test").toString(2)) } -} \ No newline at end of file +} diff --git a/mobile/src/main/java/net/activitywatch/android/fragments/TestFragment.kt b/mobile/src/main/java/net/activitywatch/android/fragments/TestFragment.kt index 1c90c4a3..6be961f8 100644 --- a/mobile/src/main/java/net/activitywatch/android/fragments/TestFragment.kt +++ b/mobile/src/main/java/net/activitywatch/android/fragments/TestFragment.kt @@ -44,7 +44,7 @@ class TestFragment : Fragment() { viewModel = ViewModelProviders.of(this).get(TestViewModel::class.java) // TODO: Use the ViewModel - val usw = UsageStatsWatcher(context!!) + val usw = UsageStatsWatcher(requireContext()) val button = view?.findViewById(R.id.button) as Button button.setOnClickListener { diff --git a/mobile/src/main/java/net/activitywatch/android/fragments/WebUIFragment.kt b/mobile/src/main/java/net/activitywatch/android/fragments/WebUIFragment.kt index eaa59381..bb98ff27 100644 --- a/mobile/src/main/java/net/activitywatch/android/fragments/WebUIFragment.kt +++ b/mobile/src/main/java/net/activitywatch/android/fragments/WebUIFragment.kt @@ -16,6 +16,7 @@ import android.content.Intent.ACTION_VIEW import android.util.Log import android.webkit.WebViewClient import net.activitywatch.android.R +import java.lang.Thread.sleep private const val TAG = "WebUI" @@ -60,6 +61,7 @@ class WebUIFragment : Fragment() { // Retry // TODO: Find way to not show the blinking Android error page Log.e(TAG, "WebView received error: $description") + sleep(100); arguments?.let { it.getString(ARG_URL)?.let { it1 -> myWebView.loadUrl(it1) } } From 96b19236ce3a225ef62d1fc7c123bbc53032de05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Bj=C3=A4reholt?= Date: Sun, 27 Nov 2022 16:10:38 +0100 Subject: [PATCH 4/4] build: disabled run of `test-e2e` on `test` target --- Makefile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d9f2c75a..cb4f5ec8 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ build-apk-debug: $(APKDIR)/debug/mobile-debug.apk $(APKDIR)/androidTest/debug/mo cp -r $(APKDIR) dist # Test targets -test: test-unit test-e2e +test: test-unit test-unit: ./gradlew test @@ -34,10 +34,8 @@ test-e2e: -Pandroid.testInstrumentationRunnerArguments.class=net.activitywatch.android.ScreenshotTest test-e2e-adb: - # Requires that: - # - you have adb installed - # - you have a device connected - # - you have the apk installed + # Requires that you have a device connected with the necessary APKs installed + # Alternative to using gradle, if you don't want to rebuild. # Run only screenshot test, for now adb shell pm list instrumentation adb shell am instrument -w \