initial impl

This commit is contained in:
Adam Velebil 2023-10-19 16:35:45 +02:00
parent 4ffda92872
commit 604ac19294
No known key found for this signature in database
GPG Key ID: C9B1E4A3CBBD2E10
6 changed files with 84 additions and 17 deletions

View File

@ -78,6 +78,16 @@
android:exported="true" android:exported="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/NdefActivityTheme"> android:theme="@style/NdefActivityTheme">
</activity>
<activity-alias
android:name=".AliasNdefActivity"
android:exported="true"
android:enabled="true"
android:launchMode="singleTop"
android:theme="@style/NdefActivityTheme"
android:targetActivity=".NdefActivity">
<intent-filter <intent-filter
android:autoVerify="true" android:autoVerify="true"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">
@ -89,7 +99,7 @@
</intent-filter> </intent-filter>
</activity> </activity-alias>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->

View File

@ -97,16 +97,59 @@ class MainActivity : FlutterFragmentActivity() {
* *
* @param enable if true, alias activity will be enabled * @param enable if true, alias activity will be enabled
*/ */
private fun enableAliasMainActivityComponent(enable: Boolean) { private fun enableActivityAlias(aliasName: String, enabledState: Int) {
val componentName = ComponentName(packageName, "com.yubico.authenticator.AliasMainActivity") val componentName = ComponentName(packageName, "com.yubico.authenticator.$aliasName")
applicationContext.packageManager.setComponentEnabledSetting( applicationContext.packageManager.setComponentEnabledSetting(
componentName, componentName,
if (enable) enabledState,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
else
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
PackageManager.DONT_KILL_APP PackageManager.DONT_KILL_APP
) )
logger.trace("Activity alias '$aliasName' is enabled: $enabledState")
}
/**
* Sets state of AliasMainActivity to enabled. This will enable USB discovery.
*/
private fun enableAppUsbDiscovery() {
enableActivityAlias(
"AliasMainActivity",
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
)
}
/**
* Sets state of AliasMainActivity to default. This will deactivate the USB discovery.
*
* The default for AliasMainActivity is disabled.
*/
private fun disableAppUsbDiscovery() {
enableActivityAlias(
"AliasMainActivity",
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
)
}
/**
* Sets state of AliasNdefActivity to defaut. This will activate NFC intent filters.
*
* The default for AliasNdefActivity is enabled.
*/
private fun enableAppNfcDiscovery() {
enableActivityAlias(
"AliasNdefActivity",
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
)
}
/**
* Sets state of AliasNdefActivity to disabled. This will deactivate NFC intent filters.
*/
private fun disableAppNfcDiscovery() {
// enable NFC discovery based on user preferences
enableActivityAlias(
"AliasNdefActivity",
PackageManager.COMPONENT_ENABLED_STATE_DISABLED
)
} }
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {
@ -180,16 +223,24 @@ class MainActivity : FlutterFragmentActivity() {
stopUsbDiscovery() stopUsbDiscovery()
stopNfcDiscovery() stopNfcDiscovery()
if (!appPreferences.openAppOnUsb) { if (!appPreferences.openAppOnUsb) {
enableAliasMainActivityComponent(false) disableAppUsbDiscovery()
} }
if (appPreferences.openAppOnNfcTap || appPreferences.copyOtpOnNfcTap) {
enableAppNfcDiscovery()
} else {
disableAppNfcDiscovery()
}
super.onPause() super.onPause()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
enableAliasMainActivityComponent(true) enableAppUsbDiscovery()
// Handle opening through otpauth:// link // Handle opening through otpauth:// link
val intentData = intent.data val intentData = intent.data

View File

@ -17,13 +17,15 @@
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
enum NfcTapAction { enum NfcTapAction {
noAction,
launch, launch,
copy, copy,
both; launchAndCopy;
String getDescription(AppLocalizations l10n) => switch (this) { String getDescription(AppLocalizations l10n) => switch (this) {
NfcTapAction.noAction => l10n.l_do_nothing,
NfcTapAction.launch => l10n.l_launch_ya, NfcTapAction.launch => l10n.l_launch_ya,
NfcTapAction.copy => l10n.l_copy_otp_clipboard, NfcTapAction.copy => l10n.l_copy_otp_clipboard,
NfcTapAction.both => l10n.l_launch_and_copy_otp NfcTapAction.launchAndCopy => l10n.l_launch_and_copy_otp
}; };
} }

View File

@ -142,12 +142,13 @@ class NfcTapActionNotifier extends StateNotifier<NfcTapAction> {
final copyOtp = prefs.getBool(_prefNfcCopyOtp) ?? false; final copyOtp = prefs.getBool(_prefNfcCopyOtp) ?? false;
final NfcTapAction action; final NfcTapAction action;
if (launchApp && copyOtp) { if (launchApp && copyOtp) {
action = NfcTapAction.both; action = NfcTapAction.launchAndCopy;
} else if (copyOtp) { } else if (copyOtp) {
action = NfcTapAction.copy; action = NfcTapAction.copy;
} else { } else if (launchApp) {
// This is the default value if both are false.
action = NfcTapAction.launch; action = NfcTapAction.launch;
} else {
action = NfcTapAction.noAction;
} }
return NfcTapActionNotifier._(prefs, action); return NfcTapActionNotifier._(prefs, action);
} }
@ -155,8 +156,10 @@ class NfcTapActionNotifier extends StateNotifier<NfcTapAction> {
Future<void> setTapAction(NfcTapAction value) async { Future<void> setTapAction(NfcTapAction value) async {
if (state != value) { if (state != value) {
state = value; state = value;
await _prefs.setBool(_prefNfcOpenApp, value != NfcTapAction.copy); await _prefs.setBool(_prefNfcOpenApp,
await _prefs.setBool(_prefNfcCopyOtp, value != NfcTapAction.launch); value == NfcTapAction.launch || value == NfcTapAction.launchAndCopy);
await _prefs.setBool(_prefNfcCopyOtp,
value == NfcTapAction.copy || value == NfcTapAction.launchAndCopy);
} }
} }
} }

View File

@ -579,6 +579,7 @@
"@_android_settings": {}, "@_android_settings": {},
"s_nfc_options": "NFC options", "s_nfc_options": "NFC options",
"l_on_yk_nfc_tap": "On YubiKey NFC tap", "l_on_yk_nfc_tap": "On YubiKey NFC tap",
"l_do_nothing": "Do nothing",
"l_launch_ya": "Launch Yubico Authenticator", "l_launch_ya": "Launch Yubico Authenticator",
"l_copy_otp_clipboard": "Copy OTP to clipboard", "l_copy_otp_clipboard": "Copy OTP to clipboard",
"l_launch_and_copy_otp": "Launch app and copy OTP", "l_launch_and_copy_otp": "Launch app and copy OTP",

View File

@ -66,7 +66,7 @@ extension _WidgetTesterHelper on WidgetTester {
Future<void> selectBothOption() async { Future<void> selectBothOption() async {
await openNfcTapOptionSelection(); await openNfcTapOptionSelection();
await tap(find.byKey(android_keys.nfcTapOption(NfcTapAction.both))); await tap(find.byKey(android_keys.nfcTapOption(NfcTapAction.launchAndCopy)));
await pumpAndSettle(); await pumpAndSettle();
} }