diff --git a/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherImplTest.kt b/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherImplTest.kt index 13acfdc..429fcf0 100644 --- a/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherImplTest.kt +++ b/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherImplTest.kt @@ -29,16 +29,20 @@ class ActivityLauncherImplTest { val extras = Bundle().apply { putString("test_key", "test_value") } - val request = LaunchRequest(componentName, extras) + val intent = Intent().apply { + component = componentName + putExtras(extras) + } + val request = LaunchRequest(intent) activityLauncher.launchActivity(request) argumentCaptor().apply { verify(context).startActivity(capture()) - val intent = firstValue - assertEquals(componentName, intent.component) - assertEquals("test_value", intent.getStringExtra("test_key")) - assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK, intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK) + val capturedIntent = firstValue + assertEquals(componentName, capturedIntent.component) + assertEquals("test_value", capturedIntent.getStringExtra("test_key")) + assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK, capturedIntent.flags and Intent.FLAG_ACTIVITY_NEW_TASK) } } } diff --git a/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ProxyImplTest.kt b/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ProxyImplTest.kt index b77f6c2..accc580 100644 --- a/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ProxyImplTest.kt +++ b/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ProxyImplTest.kt @@ -88,14 +88,14 @@ class ProxyImplTest { fun testCreateLauncherIconDelegation() { val componentName = ComponentName("com.test", "Activity") val icon: IconCompat = mock() - whenever(intentSigner.signRequest(any())).thenReturn("signature") + whenever(intentSigner.signRequest(any())).thenReturn("signature") // Mock the context and capture it to verify startActivity val mockContext: Context = mock() whenever(mockContext.packageManager).thenReturn(packageManager) val proxyWithMockContext = ShortcutCreatorProxyImpl(mockContext, intentSigner) - val request = ShortcutRequest("Test", componentName, icon) + val request = ShortcutRequest("Test", Intent().setComponent(componentName), icon) proxyWithMockContext.createLauncherIcon(request, null) verify(intentSigner).signRequest(eq(request)) diff --git a/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorImplTest.kt b/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorImplTest.kt index f41b1a4..d187998 100644 --- a/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorImplTest.kt +++ b/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorImplTest.kt @@ -89,7 +89,7 @@ class ShortcutCreatorImplTest { android.graphics.Bitmap.createBitmap(1, 1, android.graphics.Bitmap.Config.ARGB_8888), ) val signature = "test_signature" - whenever(intentSigner.signRequest(any())).thenReturn(signature) + whenever(intentSigner.signRequest(any())).thenReturn(signature) val shortcutManager = mock() val mockContext = object : android.content.ContextWrapper(context) { @@ -105,7 +105,7 @@ class ShortcutCreatorImplTest { } val shortcutCreatorWithMock = ShortcutCreatorImpl(mockContext, intentSigner) - val request = ShortcutRequest("Test App", componentName, icon) + val request = ShortcutRequest("Test App", Intent().setComponent(componentName), icon) shortcutCreatorWithMock.createLauncherIcon(request) diff --git a/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ViewIntentParserImplTest.kt b/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ViewIntentParserImplTest.kt index 91734b3..d3254bc 100644 --- a/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ViewIntentParserImplTest.kt +++ b/app/src/androidTest/java/de/szalkowski/activitylauncher/data/launcher/ViewIntentParserImplTest.kt @@ -31,8 +31,8 @@ class ViewIntentParserImplTest { val request = parser.parseLaunchRequest(intent) - assertEquals("com.example", request?.component?.packageName) - assertEquals("com.example.MainActivity", request?.component?.className) + assertEquals("com.example", request?.intent?.component?.packageName) + assertEquals("com.example.MainActivity", request?.intent?.component?.className) } @Test @@ -45,8 +45,8 @@ class ViewIntentParserImplTest { } val request = parser.parseLaunchRequest(intent) - assertEquals("com.test", request?.component?.packageName) - assertEquals("com.test.Activity", request?.component?.className) + assertEquals("com.test", request?.intent?.component?.packageName) + assertEquals("com.test.Activity", request?.intent?.component?.className) } @Test @@ -72,7 +72,7 @@ class ViewIntentParserImplTest { val request = parser.parseShortcutRequest(intent) assertEquals("Test Name", request?.name) - assertEquals("com.test", request?.component?.packageName) - assertEquals("com.test.Activity", request?.component?.className) + assertEquals("com.test", request?.intent?.component?.packageName) + assertEquals("com.test.Activity", request?.intent?.component?.className) } } diff --git a/app/src/androidTest/java/de/szalkowski/activitylauncher/entrypoint/MainActivityIntentTest.kt b/app/src/androidTest/java/de/szalkowski/activitylauncher/entrypoint/MainActivityIntentTest.kt index 26faba2..9e93317 100644 --- a/app/src/androidTest/java/de/szalkowski/activitylauncher/entrypoint/MainActivityIntentTest.kt +++ b/app/src/androidTest/java/de/szalkowski/activitylauncher/entrypoint/MainActivityIntentTest.kt @@ -95,7 +95,6 @@ class MainActivityIntentTest { whenever(viewIntentParser.parseLaunchRequest(any())).thenAnswer { invocation: org.mockito.invocation.InvocationOnMock -> realParser.parseLaunchRequest(invocation.getArgument(0)) } whenever(viewIntentParser.parseShortcutRequest(any())).thenAnswer { invocation: org.mockito.invocation.InvocationOnMock -> realParser.parseShortcutRequest(invocation.getArgument(0)) } whenever(viewIntentParser.componentNameFromIntent(any())).thenAnswer { invocation: org.mockito.invocation.InvocationOnMock -> realParser.componentNameFromIntent(invocation.getArgument(0)) } - whenever(viewIntentParser.packageFromIntent(any())).thenAnswer { invocation: org.mockito.invocation.InvocationOnMock -> realParser.packageFromIntent(invocation.getArgument(0)) } whenever(viewIntentParser.parseShortcutIntent(any())).thenAnswer { invocation: org.mockito.invocation.InvocationOnMock -> realParser.parseShortcutIntent(invocation.getArgument(0)) } whenever(settingsRepository.disclaimerAccepted).thenReturn(true) whenever(supportReminder.shouldDisplayReminder()).thenReturn(false) diff --git a/app/src/androidTest/java/de/szalkowski/activitylauncher/entrypoint/ShortcutFlowTest.kt b/app/src/androidTest/java/de/szalkowski/activitylauncher/entrypoint/ShortcutFlowTest.kt index 35e59c4..833afb8 100644 --- a/app/src/androidTest/java/de/szalkowski/activitylauncher/entrypoint/ShortcutFlowTest.kt +++ b/app/src/androidTest/java/de/szalkowski/activitylauncher/entrypoint/ShortcutFlowTest.kt @@ -119,9 +119,8 @@ class ShortcutFlowTest { ShortcutRequest( name = appName, - component = launchIntent.component!!, + intent = launchIntent, icon = mock(), - extras = launchIntent.extras, launcherPlugin = launchPlugin, ) } @@ -135,9 +134,12 @@ class ShortcutFlowTest { null } ?: return@thenAnswer null + val launchPluginStr = intent.getStringExtra(ShortcutCreator.INTENT_EXTRA_LAUNCH_PLUGIN) + val launchPlugin = launchPluginStr?.let { ComponentName.unflattenFromString(it) } + LaunchRequest( - component = launchIntent.component!!, - extras = launchIntent.extras, + intent = launchIntent, + launcherPlugin = launchPlugin, ) } } @@ -164,9 +166,9 @@ class ShortcutFlowTest { ActivityScenario.launch(intent).use { val captor = argumentCaptor() verify(activityLauncher).launchActivity(captor.capture()) - assertEquals("com.test", captor.firstValue.component.packageName) - assertEquals("com.test.Activity", captor.firstValue.component.className) - assertEquals("value", captor.firstValue.extras?.getString("key")) + assertEquals("com.test", captor.firstValue.intent.component?.packageName) + assertEquals("com.test.Activity", captor.firstValue.intent.component?.className) + assertEquals("value", captor.firstValue.intent.extras?.getString("key")) } } @@ -215,7 +217,7 @@ class ShortcutFlowTest { val captor = argumentCaptor() verify(shortcutCreator).createLauncherIcon(captor.capture()) assertEquals("Test App", captor.firstValue.name) - assertEquals(componentName, captor.firstValue.component) + assertEquals(componentName, captor.firstValue.intent.component) } } @@ -232,7 +234,7 @@ class ShortcutFlowTest { ActivityScenario.launch(intent).use { val captor = argumentCaptor() verify(activityLauncher).launchActivity(captor.capture()) - assertEquals(componentName, captor.firstValue.component) + assertEquals(componentName, captor.firstValue.intent.component) } } @@ -254,7 +256,9 @@ class ShortcutFlowTest { ActivityScenario.launch(intent).use { verify(activityLauncher, never()).launchActivity(any()) - verify(activityLauncherProxy).launchActivity(any(), eq(ComponentName.unflattenFromString(launchPlugin))) + val captor = argumentCaptor() + verify(activityLauncherProxy).launchActivity(captor.capture()) + assertEquals(ComponentName.unflattenFromString(launchPlugin), captor.firstValue.launcherPlugin) } } } diff --git a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherImpl.kt b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherImpl.kt index e254d06..b7592b7 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherImpl.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherImpl.kt @@ -5,7 +5,6 @@ import android.content.Intent import android.widget.Toast import dagger.hilt.android.qualifiers.ApplicationContext import de.szalkowski.activitylauncher.R -import de.szalkowski.activitylauncher.core.util.getActivityIntent import de.szalkowski.activitylauncher.domain.launcher.ActivityLauncher import de.szalkowski.activitylauncher.domain.model.LaunchRequest import javax.inject.Inject @@ -13,7 +12,7 @@ import javax.inject.Inject class ActivityLauncherImpl @Inject constructor(@ApplicationContext private val context: Context) : ActivityLauncher { override fun launchActivity(request: LaunchRequest) { - val intent = getActivityIntent(request.component, request.extras) + val intent = request.intent intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) try { diff --git a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherProxyImpl.kt b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherProxyImpl.kt index 5c1de81..cdcb087 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherProxyImpl.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ActivityLauncherProxyImpl.kt @@ -5,7 +5,6 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import dagger.hilt.android.qualifiers.ApplicationContext -import de.szalkowski.activitylauncher.core.util.getActivityIntent import de.szalkowski.activitylauncher.core.util.toIconCompat import de.szalkowski.activitylauncher.domain.launcher.ActivityLauncherProxy import de.szalkowski.activitylauncher.domain.launcher.ShortcutCreator @@ -18,14 +17,13 @@ class ActivityLauncherProxyImpl @Inject constructor( ) : ActivityLauncherProxy { private val pm: PackageManager = context.packageManager - override fun launchActivity(request: LaunchRequest, plugin: ComponentName?) { + override fun launchActivity(request: LaunchRequest) { val intent = Intent(ActivityLauncherProxy.INTENT_LAUNCH_ACTIVITY) - if (plugin != null) { - intent.component = plugin + if (request.launcherPlugin != null) { + intent.component = request.launcherPlugin } - val launchIntent = getActivityIntent(request.component, request.extras) - intent.putExtra(ShortcutCreator.INTENT_EXTRA_INTENT, launchIntent.toUri(Intent.URI_INTENT_SCHEME)) + intent.putExtra(ShortcutCreator.INTENT_EXTRA_INTENT, request.intent.toUri(Intent.URI_INTENT_SCHEME)) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(intent) diff --git a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/IntentSignerImpl.kt b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/IntentSignerImpl.kt index 0c833fb..3615441 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/IntentSignerImpl.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/IntentSignerImpl.kt @@ -1,11 +1,13 @@ package de.szalkowski.activitylauncher.data.launcher +import android.content.ComponentName import android.content.Context +import android.content.Intent import android.util.Base64 import androidx.core.content.edit import dagger.hilt.android.qualifiers.ApplicationContext -import de.szalkowski.activitylauncher.core.util.getActivityIntent import de.szalkowski.activitylauncher.domain.launcher.IntentSigner +import de.szalkowski.activitylauncher.domain.model.LaunchRequest import de.szalkowski.activitylauncher.domain.model.ShortcutRequest import java.security.SecureRandom import javax.crypto.Mac @@ -29,10 +31,12 @@ class IntentSignerImpl @Inject constructor(@ApplicationContext context: Context) } } - override fun signRequest(request: ShortcutRequest): String { - val launchIntent = getActivityIntent(request.component, request.extras) - val uri = launchIntent.toUri(0) - val launcherPlugin = request.launcherPlugin?.flattenToString() + override fun signRequest(request: ShortcutRequest): String = signIntent(request.intent, request.launcherPlugin) + override fun signRequest(request: LaunchRequest): String = signIntent(request.intent, request.launcherPlugin) + + private fun signIntent(intent: Intent, launcherPlugin: ComponentName?): String { + val uri = intent.toUri(0) + val launcherPlugin = launcherPlugin?.flattenToString() val message = if (launcherPlugin == null) { uri } else { @@ -41,7 +45,7 @@ class IntentSignerImpl @Inject constructor(@ApplicationContext context: Context) return hmac256(key, message) } - override fun validateRequestSignature(request: ShortcutRequest, signature: String): Boolean { + override fun validateRequestSignature(request: LaunchRequest, signature: String): Boolean { val compSignature = signRequest(request) return signature == compSignature } diff --git a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorImpl.kt b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorImpl.kt index 1cb14a2..1de34d9 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorImpl.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorImpl.kt @@ -6,7 +6,6 @@ import android.content.Intent import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat import dagger.hilt.android.qualifiers.ApplicationContext -import de.szalkowski.activitylauncher.core.util.getActivityIntent import de.szalkowski.activitylauncher.domain.launcher.IntentSigner import de.szalkowski.activitylauncher.domain.launcher.ShortcutCreator import de.szalkowski.activitylauncher.domain.model.ShortcutRequest @@ -28,10 +27,9 @@ class ShortcutCreatorImpl @Inject constructor( ShortcutActivity::class.java, ) - val launchIntent = getActivityIntent(request.component, request.extras) intent.putExtra( ShortcutCreator.INTENT_EXTRA_INTENT, - launchIntent.toUri(Intent.URI_INTENT_SCHEME), + request.intent.toUri(Intent.URI_INTENT_SCHEME), ) val signature = intentSigner.signRequest(request) diff --git a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorProxyImpl.kt b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorProxyImpl.kt index 9921ea0..e689a2e 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorProxyImpl.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ShortcutCreatorProxyImpl.kt @@ -5,7 +5,6 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import dagger.hilt.android.qualifiers.ApplicationContext -import de.szalkowski.activitylauncher.core.util.getActivityIntent import de.szalkowski.activitylauncher.core.util.toIconCompat import de.szalkowski.activitylauncher.domain.launcher.IntentSigner import de.szalkowski.activitylauncher.domain.launcher.ShortcutCreator @@ -28,8 +27,7 @@ class ShortcutCreatorProxyImpl @Inject constructor( } intent.putExtra(ShortcutCreator.INTENT_EXTRA_NAME, request.name) - val launchIntent = getActivityIntent(request.component, request.extras) - intent.putExtra(ShortcutCreator.INTENT_EXTRA_INTENT, launchIntent.toUri(Intent.URI_INTENT_SCHEME)) + intent.putExtra(ShortcutCreator.INTENT_EXTRA_INTENT, request.intent.toUri(Intent.URI_INTENT_SCHEME)) intent.putExtra(ShortcutCreator.INTENT_EXTRA_ICON, request.icon.toBundle()) val signature = intentSigner.signRequest(request) diff --git a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ViewIntentParserImpl.kt b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ViewIntentParserImpl.kt index 0dadaf8..fb535a6 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ViewIntentParserImpl.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/data/launcher/ViewIntentParserImpl.kt @@ -13,32 +13,24 @@ import javax.inject.Inject class ViewIntentParserImpl @Inject constructor( private val getActivityIconUseCase: GetActivityIconUseCase, ) : ViewIntentParser { - override fun packageFromIntent(intent: Intent): String? { - if (intent.action != Intent.ACTION_VIEW) { - return null - } - - return runCatching { - val url = intent.dataString.orEmpty() - if (url.startsWith("https://activitylauncher.net/activity/")) { - val rawComponent = url.removePrefix("https://activitylauncher.net/activity/") - ComponentName.unflattenFromString(rawComponent)?.packageName - } else { - null - } - }.getOrNull() - } - override fun parseLaunchRequest(intent: Intent): LaunchRequest? { val launchIntentStr = intent.getStringExtra(ShortcutCreator.INTENT_EXTRA_INTENT) ?: intent.getStringExtra(ShortcutCreator.LEGACY_INTENT_EXTRA_INTENT) val launchIntent = launchIntentStr?.let { parseShortcutIntent(it) } - val component = launchIntent?.component - ?: componentNameFromIntent(intent) - ?: return null + val launcherPluginStr = intent.getStringExtra(ShortcutCreator.INTENT_EXTRA_LAUNCH_PLUGIN) + val launcherPlugin = launcherPluginStr?.let { ComponentName.unflattenFromString(it) } - return LaunchRequest(component, launchIntent?.extras) + if (launchIntent != null) { + return LaunchRequest(launchIntent, launcherPlugin) + } + + val component = componentNameFromIntent(intent) ?: return null + val newLaunchIntent = Intent().apply { + this.component = component + } + + return LaunchRequest(newLaunchIntent, launcherPlugin) } override fun parseShortcutRequest(intent: Intent): ShortcutRequest? { @@ -55,7 +47,7 @@ class ViewIntentParserImpl @Inject constructor( val launcherPluginStr = intent.getStringExtra(ShortcutCreator.INTENT_EXTRA_LAUNCH_PLUGIN) val launcherPlugin = launcherPluginStr?.let { ComponentName.unflattenFromString(it) } - return ShortcutRequest(appName, component, icon, launchIntent.extras, launcherPlugin) + return ShortcutRequest(appName, launchIntent, icon, launcherPlugin) } override fun componentNameFromIntent(intent: Intent): ComponentName? { diff --git a/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/ActivityLauncherProxy.kt b/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/ActivityLauncherProxy.kt index b549c85..f665ad5 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/ActivityLauncherProxy.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/ActivityLauncherProxy.kt @@ -1,11 +1,10 @@ package de.szalkowski.activitylauncher.domain.launcher -import android.content.ComponentName import de.szalkowski.activitylauncher.domain.model.LaunchRequest import de.szalkowski.activitylauncher.domain.model.PluginInfo interface ActivityLauncherProxy { - fun launchActivity(request: LaunchRequest, plugin: ComponentName? = null) + fun launchActivity(request: LaunchRequest) fun hasMultipleHandlers(): Boolean fun getPlugins(): List diff --git a/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/IntentSigner.kt b/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/IntentSigner.kt index 4f6ea06..9754def 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/IntentSigner.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/IntentSigner.kt @@ -1,8 +1,10 @@ package de.szalkowski.activitylauncher.domain.launcher +import de.szalkowski.activitylauncher.domain.model.LaunchRequest import de.szalkowski.activitylauncher.domain.model.ShortcutRequest interface IntentSigner { fun signRequest(request: ShortcutRequest): String - fun validateRequestSignature(request: ShortcutRequest, signature: String): Boolean + fun signRequest(request: LaunchRequest): String + fun validateRequestSignature(request: LaunchRequest, signature: String): Boolean } diff --git a/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/ViewIntentParser.kt b/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/ViewIntentParser.kt index aa9febf..447633e 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/ViewIntentParser.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/domain/launcher/ViewIntentParser.kt @@ -6,7 +6,6 @@ import de.szalkowski.activitylauncher.domain.model.LaunchRequest import de.szalkowski.activitylauncher.domain.model.ShortcutRequest interface ViewIntentParser { - fun packageFromIntent(intent: Intent): String? fun componentNameFromIntent(intent: Intent): ComponentName? fun parseShortcutIntent(uri: String): Intent? fun parseLaunchRequest(intent: Intent): LaunchRequest? diff --git a/app/src/main/java/de/szalkowski/activitylauncher/domain/model/LaunchRequest.kt b/app/src/main/java/de/szalkowski/activitylauncher/domain/model/LaunchRequest.kt index 8d26ca1..001ec2d 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/domain/model/LaunchRequest.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/domain/model/LaunchRequest.kt @@ -1,9 +1,9 @@ package de.szalkowski.activitylauncher.domain.model import android.content.ComponentName -import android.os.Bundle +import android.content.Intent data class LaunchRequest( - val component: ComponentName, - val extras: Bundle? = null, + val intent: Intent, + val launcherPlugin: ComponentName? = null, ) diff --git a/app/src/main/java/de/szalkowski/activitylauncher/domain/model/ShortcutRequest.kt b/app/src/main/java/de/szalkowski/activitylauncher/domain/model/ShortcutRequest.kt index b6f0a32..4dcc49f 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/domain/model/ShortcutRequest.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/domain/model/ShortcutRequest.kt @@ -1,13 +1,12 @@ package de.szalkowski.activitylauncher.domain.model import android.content.ComponentName -import android.os.Bundle +import android.content.Intent import androidx.core.graphics.drawable.IconCompat data class ShortcutRequest( val name: String, - val component: ComponentName, + val intent: Intent, val icon: IconCompat, - val extras: Bundle? = null, val launcherPlugin: ComponentName? = null, ) diff --git a/app/src/main/java/de/szalkowski/activitylauncher/domain/usecase/launcher/CreateShortcutUseCase.kt b/app/src/main/java/de/szalkowski/activitylauncher/domain/usecase/launcher/CreateShortcutUseCase.kt index 2196481..313d4fc 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/domain/usecase/launcher/CreateShortcutUseCase.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/domain/usecase/launcher/CreateShortcutUseCase.kt @@ -13,7 +13,7 @@ class CreateShortcutUseCase @Inject constructor( private val shortcutCreatorProxy: ShortcutCreatorProxy, ) { operator fun invoke(request: ShortcutRequest, shortcutPlugin: ComponentName? = null) { - Log.i("CreateShortcutUseCase", "Creating shortcut: ${request.component.flattenToShortString()}") + Log.i("CreateShortcutUseCase", "Creating shortcut: ${request.intent.component?.flattenToShortString()}") if (shortcutPlugin != null || shortcutCreatorProxy.hasMultipleHandlers()) { shortcutCreatorProxy.createLauncherIcon(request, shortcutPlugin) } else { diff --git a/app/src/main/java/de/szalkowski/activitylauncher/domain/usecase/launcher/LaunchActivityUseCase.kt b/app/src/main/java/de/szalkowski/activitylauncher/domain/usecase/launcher/LaunchActivityUseCase.kt index fe1fb7f..8f097b8 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/domain/usecase/launcher/LaunchActivityUseCase.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/domain/usecase/launcher/LaunchActivityUseCase.kt @@ -1,6 +1,5 @@ package de.szalkowski.activitylauncher.domain.usecase.launcher -import android.content.ComponentName import android.util.Log import de.szalkowski.activitylauncher.domain.launcher.ActivityLauncher import de.szalkowski.activitylauncher.domain.launcher.ActivityLauncherProxy @@ -14,14 +13,15 @@ class LaunchActivityUseCase @Inject constructor( private val activityLauncherProxy: ActivityLauncherProxy, private val recentsRepository: RecentsRepository, ) { - operator fun invoke(request: LaunchRequest, launchPlugin: ComponentName? = null) { - Log.i("LaunchActivityUseCase", "Launching activity: ${request.component.flattenToShortString()}") - if (launchPlugin != null || activityLauncherProxy.hasMultipleHandlers()) { - activityLauncherProxy.launchActivity(request, launchPlugin) + operator fun invoke(request: LaunchRequest) { + val component = request.intent.component ?: return + Log.i("LaunchActivityUseCase", "Launching activity: ${component.flattenToShortString()}") + if (request.launcherPlugin != null || activityLauncherProxy.hasMultipleHandlers()) { + activityLauncherProxy.launchActivity(request) } else { activityLauncher.launchActivity(request) } - recentsRepository.addActivity(request.component) + recentsRepository.addActivity(component) } fun hasMultipleHandlers(): Boolean = activityLauncherProxy.hasMultipleHandlers() diff --git a/app/src/main/java/de/szalkowski/activitylauncher/entrypoint/MainActivity.kt b/app/src/main/java/de/szalkowski/activitylauncher/entrypoint/MainActivity.kt index 4fccbb8..0d6c886 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/entrypoint/MainActivity.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/entrypoint/MainActivity.kt @@ -200,7 +200,7 @@ class MainActivity : AppCompatActivity(), ActionBarSearch { val launchRequest = viewIntentParser.parseLaunchRequest(intent) val componentNameFromExtra = intent.getParcelableExtra(EXTRA_ACTIVITY_COMPONENT_NAME) - val componentName = launchRequest?.component ?: componentNameFromExtra + val componentName = launchRequest?.intent?.component ?: componentNameFromExtra if (componentName != null) { val bundle = Bundle().apply { diff --git a/app/src/main/java/de/szalkowski/activitylauncher/entrypoint/ShortcutActivity.kt b/app/src/main/java/de/szalkowski/activitylauncher/entrypoint/ShortcutActivity.kt index 9c77bc3..0f91a5a 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/entrypoint/ShortcutActivity.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/entrypoint/ShortcutActivity.kt @@ -13,7 +13,6 @@ import de.szalkowski.activitylauncher.domain.launcher.IntentSigner import de.szalkowski.activitylauncher.domain.launcher.ShortcutCreator import de.szalkowski.activitylauncher.domain.launcher.ShortcutCreatorProxy import de.szalkowski.activitylauncher.domain.launcher.ViewIntentParser -import de.szalkowski.activitylauncher.domain.model.LaunchRequest import de.szalkowski.activitylauncher.domain.usecase.launcher.LaunchActivityUseCase import javax.inject.Inject @@ -98,16 +97,16 @@ class ShortcutActivity : AppCompatActivity() { } private fun handleLaunchShortcut() { - val request = viewIntentParser.parseShortcutRequest(intent) ?: return + val request = viewIntentParser.parseLaunchRequest(intent) ?: return val signature = intent.getStringExtra(ShortcutCreator.INTENT_EXTRA_SIGNATURE).orEmpty() if (!intentSigner.validateRequestSignature(request, signature)) { Log.e("ShortcutActivity", "Invalid signature for shortcut") - redirectToMain(request.component) + request.intent.component?.let { redirectToMain(it) } return } - launchActivityUseCase.invoke(LaunchRequest(request.component, request.extras), request.launcherPlugin) + launchActivityUseCase.invoke(request) } private fun handleLaunchActivity() { diff --git a/app/src/main/java/de/szalkowski/activitylauncher/presentation/activities/ActivityDetailsViewModel.kt b/app/src/main/java/de/szalkowski/activitylauncher/presentation/activities/ActivityDetailsViewModel.kt index 2d4f3fd..921b688 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/presentation/activities/ActivityDetailsViewModel.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/presentation/activities/ActivityDetailsViewModel.kt @@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import de.szalkowski.activitylauncher.R +import de.szalkowski.activitylauncher.core.util.getActivityIntent import de.szalkowski.activitylauncher.domain.favorites.FavoritesRepository import de.szalkowski.activitylauncher.domain.launcher.IconLoader import de.szalkowski.activitylauncher.domain.model.LaunchRequest @@ -170,9 +171,8 @@ class ActivityDetailsViewModel @Inject constructor( val icon = _editedIcon.value ?: getActivityIconUseCase(info.iconResourceName, info.componentName) val request = ShortcutRequest( name = info.name, - component = info.componentName, + intent = getActivityIntent(info.componentName, Bundle()), icon = icon, - extras = Bundle(), launcherPlugin = _selectedLaunchPlugin.value?.componentName, ) createShortcutUseCase(request, _selectedShortcutPlugin.value?.componentName) @@ -189,10 +189,10 @@ class ActivityDetailsViewModel @Inject constructor( fun launchActivity() { val info = getEditedActivityInfo() val request = LaunchRequest( - component = info.componentName, - extras = Bundle(), + intent = getActivityIntent(info.componentName, Bundle()), + launcherPlugin = _selectedLaunchPlugin.value?.componentName, ) - launchActivityUseCase(request, _selectedLaunchPlugin.value?.componentName) + launchActivityUseCase(request) } fun shareActivity() { diff --git a/app/src/main/java/de/szalkowski/activitylauncher/presentation/common/BaseActivityListFragment.kt b/app/src/main/java/de/szalkowski/activitylauncher/presentation/common/BaseActivityListFragment.kt index 7f6e1f4..8e73345 100644 --- a/app/src/main/java/de/szalkowski/activitylauncher/presentation/common/BaseActivityListFragment.kt +++ b/app/src/main/java/de/szalkowski/activitylauncher/presentation/common/BaseActivityListFragment.kt @@ -12,6 +12,7 @@ import androidx.navigation.NavDirections import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView +import de.szalkowski.activitylauncher.core.util.getActivityIntent import de.szalkowski.activitylauncher.domain.launcher.IconLoader import de.szalkowski.activitylauncher.domain.model.LaunchRequest import de.szalkowski.activitylauncher.domain.packages.PackageRepository @@ -49,7 +50,7 @@ abstract class BaseActivityListFragment : Fragment() { icon.loadDrawable(requireContext()) ?: requireContext().packageManager.defaultActivityIcon } adapter.onItemClick = { info -> - launchActivityUseCase(LaunchRequest(info.componentName)) + launchActivityUseCase(LaunchRequest(getActivityIntent(info.componentName, null))) } adapter.onItemLongClick = { info -> runCatching { diff --git a/app/src/test/java/de/szalkowski/activitylauncher/data/launcher/IntentSignerImplTest.kt b/app/src/test/java/de/szalkowski/activitylauncher/data/launcher/IntentSignerImplTest.kt index c9867f5..7cdcb41 100644 --- a/app/src/test/java/de/szalkowski/activitylauncher/data/launcher/IntentSignerImplTest.kt +++ b/app/src/test/java/de/szalkowski/activitylauncher/data/launcher/IntentSignerImplTest.kt @@ -4,7 +4,7 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.SharedPreferences -import de.szalkowski.activitylauncher.core.util.getActivityIntent +import de.szalkowski.activitylauncher.domain.model.LaunchRequest import de.szalkowski.activitylauncher.domain.model.ShortcutRequest import org.junit.Assert.* import org.junit.Before @@ -47,69 +47,51 @@ class IntentSignerImplTest { @Test fun testSignAndValidateRequest() = withMockedBase64 { - val componentName = mock() val icon = mock() - val request = ShortcutRequest("Test", componentName, icon) val intent = mock() + val shortcutRequest = ShortcutRequest("Test", intent, icon) + val launchRequest = LaunchRequest(intent) - val intentUtilClass = Class.forName("de.szalkowski.activitylauncher.core.util.ActivityIntentKt") - mockStatic(intentUtilClass).use { mockedIntentUtil -> - mockedIntentUtil.`when` { - getActivityIntent(eq(componentName), anyOrNull()) - }.thenReturn(intent) - whenever(intent.toUri(anyInt())).thenReturn("intent:#Intent;action=com.test.ACTION;end") + whenever(intent.toUri(anyInt())).thenReturn("intent:#Intent;action=com.test.ACTION;end") - val signature = signer.signRequest(request) + val signature = signer.signRequest(shortcutRequest) - assertNotNull(signature) - assertTrue(signer.validateRequestSignature(request, signature)) - } + assertNotNull(signature) + assertTrue(signer.validateRequestSignature(launchRequest, signature)) } @Test fun testSignatureWithPlugin() = withMockedBase64 { - val componentName = mock() val icon = mock() val plugin = mock() whenever(plugin.flattenToString()).thenReturn("com.example/.Plugin") - val requestWithPlugin = ShortcutRequest("Test", componentName, icon, launcherPlugin = plugin) - val requestWithoutPlugin = ShortcutRequest("Test", componentName, icon) val intent = mock() + whenever(intent.toUri(anyInt())).thenReturn("intent:#Intent;action=com.test.ACTION;end") - val intentUtilClass = Class.forName("de.szalkowski.activitylauncher.core.util.ActivityIntentKt") - mockStatic(intentUtilClass).use { mockedIntentUtil -> - mockedIntentUtil.`when` { - getActivityIntent(eq(componentName), anyOrNull()) - }.thenReturn(intent) - whenever(intent.toUri(anyInt())).thenReturn("intent:#Intent;action=com.test.ACTION;end") + val shortcutRequestWithPlugin = ShortcutRequest("Test", intent, icon, launcherPlugin = plugin) + val shortcutRequestWithoutPlugin = ShortcutRequest("Test", intent, icon) + val launchRequestWithPlugin = LaunchRequest(intent, launcherPlugin = plugin) + val launchRequestWithoutPlugin = LaunchRequest(intent) - val signatureWithPlugin = signer.signRequest(requestWithPlugin) - val signatureWithoutPlugin = signer.signRequest(requestWithoutPlugin) + val signatureWithPlugin = signer.signRequest(shortcutRequestWithPlugin) + val signatureWithoutPlugin = signer.signRequest(shortcutRequestWithoutPlugin) - assertNotEquals(signatureWithPlugin, signatureWithoutPlugin) - assertTrue(signer.validateRequestSignature(requestWithPlugin, signatureWithPlugin)) - assertFalse(signer.validateRequestSignature(requestWithPlugin, signatureWithoutPlugin)) - assertFalse(signer.validateRequestSignature(requestWithoutPlugin, signatureWithPlugin)) - } + assertNotEquals(signatureWithPlugin, signatureWithoutPlugin) + assertTrue(signer.validateRequestSignature(launchRequestWithPlugin, signatureWithPlugin)) + assertFalse(signer.validateRequestSignature(launchRequestWithPlugin, signatureWithoutPlugin)) + assertFalse(signer.validateRequestSignature(launchRequestWithoutPlugin, signatureWithPlugin)) } @Test fun testKnownSignature() = withMockedBase64 { - val componentName = mock() val icon = mock() - val request = ShortcutRequest("Test", componentName, icon) val intent = mock() + val request = ShortcutRequest("Test", intent, icon) - val intentUtilClass = Class.forName("de.szalkowski.activitylauncher.core.util.ActivityIntentKt") - mockStatic(intentUtilClass).use { mockedIntentUtil -> - mockedIntentUtil.`when` { - getActivityIntent(eq(componentName), anyOrNull()) - }.thenReturn(intent) - whenever(intent.toUri(anyInt())).thenReturn("intent:#Intent;action=com.test.ACTION;end") + whenever(intent.toUri(anyInt())).thenReturn("intent:#Intent;action=com.test.ACTION;end") - val signature = signer.signRequest(request) - // Verified known signature for "intent:#Intent;action=com.test.ACTION;end" with key "test_key" - assertEquals("kPThuLUm6BnZkfNuIuRuVZfj8IXOinD+dURnRv1Ytd8=", signature) - } + val signature = signer.signRequest(request) + // Verified known signature for "intent:#Intent;action=com.test.ACTION;end" with key "test_key" + assertEquals("kPThuLUm6BnZkfNuIuRuVZfj8IXOinD+dURnRv1Ytd8=", signature) } } diff --git a/app/src/test/java/de/szalkowski/activitylauncher/domain/usecase/launcher/CreateShortcutUseCaseTest.kt b/app/src/test/java/de/szalkowski/activitylauncher/domain/usecase/launcher/CreateShortcutUseCaseTest.kt index aa7a4dd..610dcc9 100644 --- a/app/src/test/java/de/szalkowski/activitylauncher/domain/usecase/launcher/CreateShortcutUseCaseTest.kt +++ b/app/src/test/java/de/szalkowski/activitylauncher/domain/usecase/launcher/CreateShortcutUseCaseTest.kt @@ -11,9 +11,16 @@ import org.mockito.kotlin.* class CreateShortcutUseCaseTest { private val shortcutCreator: ShortcutCreator = mock() private val shortcutCreatorProxy: ShortcutCreatorProxy = mock() - private val componentName = ComponentName("com.test", "Activity") + private val componentName = mock { + on { packageName } doReturn "com.test" + on { className } doReturn "Activity" + on { flattenToShortString() } doReturn "com.test/Activity" + } private val icon = mock() - private val request = ShortcutRequest("Test", componentName, icon) + private val intent = mock { + on { component } doReturn componentName + } + private val request = ShortcutRequest("Test", intent, icon) private lateinit var useCase: CreateShortcutUseCase @Before diff --git a/app/src/test/java/de/szalkowski/activitylauncher/domain/usecase/launcher/LaunchActivityUseCaseTest.kt b/app/src/test/java/de/szalkowski/activitylauncher/domain/usecase/launcher/LaunchActivityUseCaseTest.kt index 846f91f..fc11c4c 100644 --- a/app/src/test/java/de/szalkowski/activitylauncher/domain/usecase/launcher/LaunchActivityUseCaseTest.kt +++ b/app/src/test/java/de/szalkowski/activitylauncher/domain/usecase/launcher/LaunchActivityUseCaseTest.kt @@ -1,6 +1,7 @@ package de.szalkowski.activitylauncher.domain.usecase.launcher import android.content.ComponentName +import android.content.Intent import de.szalkowski.activitylauncher.domain.launcher.ActivityLauncher import de.szalkowski.activitylauncher.domain.launcher.ActivityLauncherProxy import de.szalkowski.activitylauncher.domain.model.LaunchRequest @@ -16,7 +17,11 @@ class LaunchActivityUseCaseTest { private val activityLauncherProxy: ActivityLauncherProxy = mock() private val recentsRepository: RecentsRepository = mock() private lateinit var useCase: LaunchActivityUseCase - private val componentName = ComponentName("com.test", "Activity") + private val componentName = mock { + on { packageName } doReturn "com.test" + on { className } doReturn "Activity" + on { flattenToShortString() } doReturn "com.test/Activity" + } @Before fun setup() { @@ -25,7 +30,10 @@ class LaunchActivityUseCaseTest { @Test fun `should launch activity and add to recents`() { - val request = LaunchRequest(componentName) + val intent = mock { + on { component } doReturn componentName + } + val request = LaunchRequest(intent) useCase.invoke(request) verify(activityLauncher).launchActivity(eq(request)) @@ -35,10 +43,13 @@ class LaunchActivityUseCaseTest { @Test fun `should launch activity with plugin and add to recents`() { val plugin = ComponentName("com.plugin", "Plugin") - val request = LaunchRequest(componentName) - useCase.invoke(request, launchPlugin = plugin) + val intent = mock { + on { component } doReturn componentName + } + val request = LaunchRequest(intent, launcherPlugin = plugin) + useCase.invoke(request) - verify(activityLauncherProxy).launchActivity(eq(request), eq(plugin)) + verify(activityLauncherProxy).launchActivity(eq(request)) verify(recentsRepository).addActivity(componentName) } diff --git a/app/src/test/java/de/szalkowski/activitylauncher/presentation/activities/ActivityDetailsViewModelTest.kt b/app/src/test/java/de/szalkowski/activitylauncher/presentation/activities/ActivityDetailsViewModelTest.kt index 3a0bb7e..919013f 100644 --- a/app/src/test/java/de/szalkowski/activitylauncher/presentation/activities/ActivityDetailsViewModelTest.kt +++ b/app/src/test/java/de/szalkowski/activitylauncher/presentation/activities/ActivityDetailsViewModelTest.kt @@ -4,6 +4,7 @@ import android.content.ComponentName import androidx.core.graphics.drawable.IconCompat import androidx.lifecycle.SavedStateHandle import de.szalkowski.activitylauncher.R +import de.szalkowski.activitylauncher.core.util.getActivityIntent import de.szalkowski.activitylauncher.domain.favorites.FavoritesRepository import de.szalkowski.activitylauncher.domain.launcher.IconLoader import de.szalkowski.activitylauncher.domain.model.LaunchRequest @@ -104,20 +105,34 @@ class ActivityDetailsViewModelTest { @Test fun `should launch activity`() { - viewModel.launchActivity() - val captor = argumentCaptor() - verify(launchActivityUseCase).invoke(captor.capture(), isNull()) - assertEquals("com.test", captor.firstValue.component.packageName) - assertEquals("Activity", captor.firstValue.component.className) + val mockIntent = mock() + val utilClass = Class.forName("de.szalkowski.activitylauncher.core.util.ActivityIntentKt") + org.mockito.Mockito.mockStatic(utilClass).use { mockedUtil -> + mockedUtil.`when` { + getActivityIntent(eq(componentName), any()) + }.thenReturn(mockIntent) + + viewModel.launchActivity() + val captor = argumentCaptor() + verify(launchActivityUseCase).invoke(captor.capture()) + assertEquals(mockIntent, captor.firstValue.intent) + } } @Test fun `should create shortcut`() { - viewModel.createShortcut() - val captor = argumentCaptor() - verify(createShortcutUseCase).invoke(captor.capture(), isNull()) - assertEquals("com.test", captor.firstValue.component.packageName) - assertEquals("Activity", captor.firstValue.component.className) + val mockIntent = mock() + val utilClass = Class.forName("de.szalkowski.activitylauncher.core.util.ActivityIntentKt") + org.mockito.Mockito.mockStatic(utilClass).use { mockedUtil -> + mockedUtil.`when` { + getActivityIntent(eq(componentName), any()) + }.thenReturn(mockIntent) + + viewModel.createShortcut() + val captor = argumentCaptor() + verify(createShortcutUseCase).invoke(captor.capture(), isNull()) + assertEquals(mockIntent, captor.firstValue.intent) + } } @Test @@ -186,12 +201,20 @@ class ActivityDetailsViewModelTest { newViewModel.selectLaunchPlugin(pluginComp) - newViewModel.launchActivity() + val mockIntent = mock() + val utilClass = Class.forName("de.szalkowski.activitylauncher.core.util.ActivityIntentKt") + org.mockito.Mockito.mockStatic(utilClass).use { mockedUtil -> + mockedUtil.`when` { + getActivityIntent(eq(componentName), any()) + }.thenReturn(mockIntent) - val captor = argumentCaptor() - verify(launchActivityUseCase).invoke(captor.capture(), eq(pluginComp)) - assertEquals("com.test", captor.firstValue.component.packageName) - assertEquals("Activity", captor.firstValue.component.className) + newViewModel.launchActivity() + + val captor = argumentCaptor() + verify(launchActivityUseCase).invoke(captor.capture()) + assertEquals(mockIntent, captor.firstValue.intent) + assertEquals(pluginComp, captor.firstValue.launcherPlugin) + } } @Test @@ -208,12 +231,19 @@ class ActivityDetailsViewModelTest { newViewModel.selectShortcutPlugin(pluginComp) - newViewModel.createShortcut() + val mockIntent = mock() + val utilClass = Class.forName("de.szalkowski.activitylauncher.core.util.ActivityIntentKt") + org.mockito.Mockito.mockStatic(utilClass).use { mockedUtil -> + mockedUtil.`when` { + getActivityIntent(eq(componentName), any()) + }.thenReturn(mockIntent) - val captor = argumentCaptor() - verify(createShortcutUseCase).invoke(captor.capture(), eq(pluginComp)) - assertEquals("com.test", captor.firstValue.component.packageName) - assertEquals("Activity", captor.firstValue.component.className) + newViewModel.createShortcut() + + val captor = argumentCaptor() + verify(createShortcutUseCase).invoke(captor.capture(), eq(pluginComp)) + assertEquals(mockIntent, captor.firstValue.intent) + } } @Test @@ -230,13 +260,20 @@ class ActivityDetailsViewModelTest { newViewModel.selectLaunchPlugin(pluginComp) - newViewModel.createShortcut() + val mockIntent = mock() + val utilClass = Class.forName("de.szalkowski.activitylauncher.core.util.ActivityIntentKt") + org.mockito.Mockito.mockStatic(utilClass).use { mockedUtil -> + mockedUtil.`when` { + getActivityIntent(eq(componentName), any()) + }.thenReturn(mockIntent) - val captor = argumentCaptor() - verify(createShortcutUseCase).invoke(captor.capture(), isNull()) - assertEquals("com.test", captor.firstValue.component.packageName) - assertEquals("Activity", captor.firstValue.component.className) - assertEquals(pluginComp, captor.firstValue.launcherPlugin) + newViewModel.createShortcut() + + val captor = argumentCaptor() + verify(createShortcutUseCase).invoke(captor.capture(), isNull()) + assertEquals(mockIntent, captor.firstValue.intent) + assertEquals(pluginComp, captor.firstValue.launcherPlugin) + } } @Test