taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

commit 2e88af80e385e8bda32a685b126f88c7d32d9c67
parent fc5195c17b2ed5ada68fb1159db7ea568d960d61
Author: Bohdan Potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Sun, 27 Apr 2025 21:48:18 +0200

support taler-pos intent

Diffstat:
Mmerchant-terminal/src/main/AndroidManifest.xml | 7+++++++
Mmerchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/merchant-terminal/src/main/AndroidManifest.xml b/merchant-terminal/src/main/AndroidManifest.xml @@ -48,6 +48,13 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> + + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + <data android:scheme="taler-pos" /> + </intent-filter> </activity> <service diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt @@ -20,6 +20,7 @@ import android.content.Intent import android.content.Intent.ACTION_MAIN import android.content.Intent.CATEGORY_HOME import android.content.Intent.FLAG_ACTIVITY_NEW_TASK +import android.net.Uri import android.os.Bundle import android.os.Handler import android.view.MenuItem @@ -34,6 +35,7 @@ import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupWithNavController import com.google.android.material.navigation.NavigationView.OnNavigationItemSelectedListener import net.taler.lib.android.TalerNfcService +import net.taler.merchantpos.config.Config import net.taler.merchantpos.databinding.ActivityMainBinding class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener { @@ -72,6 +74,8 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener { setSupportActionBar(ui.main.toolbar) val appBarConfiguration = AppBarConfiguration(nav.graph, ui.drawerLayout) ui.main.toolbar.setupWithNavController(nav, appBarConfiguration) + + handleSetupIntent(intent) } override fun onStart() { @@ -103,6 +107,11 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener { return true } + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + handleSetupIntent(intent) + } + @Deprecated("Deprecated in Java") override fun onBackPressed() { val currentDestination = nav.currentDestination?.id @@ -126,4 +135,52 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener { } else super.onBackPressed() } + /** + * Handle the setup intent from the URL scheme. E.g. scanned the QR code from the camera + * + * This is the URL format: + * taler-pos://backend.demo.taler.net/#/username=<username>&password=<password> + */ + private fun handleSetupIntent(intent: Intent) { + if (intent.action != Intent.ACTION_VIEW) return + val data = intent.data ?: return + if (data.scheme != "taler-pos") return + + val host = data.host ?: return + + val params = data.fragment + ?.removePrefix("/") + ?.split('&') + ?.associate { part -> + part.split('=', limit = 2).let { it[0] to Uri.decode(it.getOrElse(1) { "" }) } + } ?: return + + val instance = params["username"] ?: return + val token = params["password"] ?: return + + // Build a regular Merchant-API URL: https://<host>/instances/<instance> + val merchantUrl = Uri.Builder() + .scheme("https") + .encodedAuthority(host) + .appendPath("instances") + .appendPath(instance) + .build() + .toString() + + // Re-use the existing “new config” class + val newConfig = Config.New( + merchantUrl = merchantUrl, + accessToken = token, + savePassword = true + ) + + // Kick off the exact same pipeline the Settings screen would start + model.configManager.fetchConfig(newConfig, /*save =*/ true) + + // Take the user to the fetcher fragment so they see the spinner / error handling + if (nav.currentDestination?.id != R.id.configFetcher) { + nav.navigate(R.id.action_global_configFetcher) + } + } + }