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:launchMode="singleTop"
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
android:autoVerify="true"
tools:ignore="UnusedAttribute">
@ -89,7 +99,7 @@
</intent-filter>
</activity>
</activity-alias>
<!-- Don't delete the meta-data below.
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
*/
private fun enableAliasMainActivityComponent(enable: Boolean) {
val componentName = ComponentName(packageName, "com.yubico.authenticator.AliasMainActivity")
private fun enableActivityAlias(aliasName: String, enabledState: Int) {
val componentName = ComponentName(packageName, "com.yubico.authenticator.$aliasName")
applicationContext.packageManager.setComponentEnabledSetting(
componentName,
if (enable)
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
else
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
enabledState,
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) {
@ -180,16 +223,24 @@ class MainActivity : FlutterFragmentActivity() {
stopUsbDiscovery()
stopNfcDiscovery()
if (!appPreferences.openAppOnUsb) {
enableAliasMainActivityComponent(false)
disableAppUsbDiscovery()
}
if (appPreferences.openAppOnNfcTap || appPreferences.copyOtpOnNfcTap) {
enableAppNfcDiscovery()
} else {
disableAppNfcDiscovery()
}
super.onPause()
}
override fun onResume() {
super.onResume()
enableAliasMainActivityComponent(true)
enableAppUsbDiscovery()
// Handle opening through otpauth:// link
val intentData = intent.data

View File

@ -17,13 +17,15 @@
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
enum NfcTapAction {
noAction,
launch,
copy,
both;
launchAndCopy;
String getDescription(AppLocalizations l10n) => switch (this) {
NfcTapAction.noAction => l10n.l_do_nothing,
NfcTapAction.launch => l10n.l_launch_ya,
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 NfcTapAction action;
if (launchApp && copyOtp) {
action = NfcTapAction.both;
action = NfcTapAction.launchAndCopy;
} else if (copyOtp) {
action = NfcTapAction.copy;
} else {
// This is the default value if both are false.
} else if (launchApp) {
action = NfcTapAction.launch;
} else {
action = NfcTapAction.noAction;
}
return NfcTapActionNotifier._(prefs, action);
}
@ -155,8 +156,10 @@ class NfcTapActionNotifier extends StateNotifier<NfcTapAction> {
Future<void> setTapAction(NfcTapAction value) async {
if (state != value) {
state = value;
await _prefs.setBool(_prefNfcOpenApp, value != NfcTapAction.copy);
await _prefs.setBool(_prefNfcCopyOtp, value != NfcTapAction.launch);
await _prefs.setBool(_prefNfcOpenApp,
value == NfcTapAction.launch || value == NfcTapAction.launchAndCopy);
await _prefs.setBool(_prefNfcCopyOtp,
value == NfcTapAction.copy || value == NfcTapAction.launchAndCopy);
}
}
}

View File

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

View File

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