Token导航 LogoToken导航

Agent Skill · 研究检索

implementing-android-code(实现安卓代码)

implementing-android-code 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

implementing-android-code 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 46,467。

总安装 776周安装 33GitHub Stars 8,685下载 272核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:implementing-android-code(实现安卓代码)
来源仓库:https://github.com/bitwarden/android
仓库路径:skills/implementing-android-code
安装命令:
npx skills add https://github.com/bitwarden/android --skill implementing-android-code
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/bitwarden/android --skill implementing-android-code

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

implementing-android-code 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中快速定位候选结果。适用于需要根据关键词、任务场景或来源线索进行信息搜集与整理的场景。通过关键词匹配和来源仓库筛选实现信息检索,支持结合具体任务目标使用。

安装命令为 npx skills add https://github.com/bitwarden/android --skill implementing-android-code。使用前需确认权限范围、维护状态,注意是否触发联网或文件读写操作。

来源仓库内路径:skills/implementing-android-code

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/bitwarden/android --skill implementing-android…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

implementing-android-code 怎么安装?

在终端执行 npx skills add https://github.com/bitwarden/android --skill implementing-android-code。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

implementing-android-code 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

implementing-android-code 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

implementing-android-code 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

implementing-android-code 用的人多吗?

公开数据是累计安装 776 次,近一周安装 33 次,下载 272 次,GitHub 8,685 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

implementing-android-code 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。
  • 来源仓库有 8,685 星,维护活跃度相对可查。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
implementing-android-code

实现安卓代码 · 本页

7768,685需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Implementing Android Code - Bitwarden Quick Reference

This skill provides tactical guidance for Bitwarden-specific patterns. For comprehensive architecture decisions and complete code style rules, consult docs/ARCHITECTURE.md and docs/STYLE_AND_BEST_PRACTICES.md.


Critical Patterns Reference

A. ViewModel Implementation (State-Action-Event Pattern)

All ViewModels follow the State-Action-Event (SAE) pattern via BaseViewModel<State, Event, Action>.

Key Requirements:

  • Annotate with @HiltViewModel
  • State class MUST be @Parcelize data class: Parcelable
  • Implement handleAction(action: A) - MUST be synchronous
  • Post internal actions from coroutines using sendAction()
  • Save/restore state via SavedStateHandle[KEY_STATE]
  • Private action handlers: private fun handle* naming convention

Template: See ViewModel template

Pattern Summary:

@HiltViewModel
class ExampleViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val repository: ExampleRepository,
) : BaseViewModel<ExampleState, ExampleEvent, ExampleAction>(
    initialState = savedStateHandle[KEY_STATE] ?: ExampleState(),
) {
    init {
        stateFlow.onEach { savedStateHandle[KEY_STATE] = it }.launchIn(viewModelScope)
    }

    override fun handleAction(action: ExampleAction) {
        // Synchronous dispatch only
        when (action) {
            is Action.Click -> handleClick()
            is Action.Internal.DataReceived -> handleDataReceived(action)
        }
    }

    private fun handleClick() {
        viewModelScope.launch {
            val result = repository.fetchData()
            sendAction(Action.Internal.DataReceived(result))  // Post internal action
        }
    }

    private fun handleDataReceived(action: Action.Internal.DataReceived) {
        mutableStateFlow.update { it.copy(data = action.result) }
    }
}

Reference:

  • ui/src/main/kotlin/com/bitwarden/ui/platform/base/BaseViewModel.kt (see handleAction method)
  • app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModel.kt (see class declaration)

Critical Gotchas:

  • ❌ NEVER update mutableStateFlow directly inside coroutines
  • ✅ ALWAYS post internal actions from coroutines, update state in handleAction()
  • ❌ NEVER forget @IgnoredOnParcel for sensitive data (causes security leak)
  • ✅ ALWAYS use @Parcelize on state classes for process death recovery
  • ✅ State restoration happens automatically if properly saved to SavedStateHandle

B. Navigation Implementation (Type-Safe)

All navigation uses type-safe routes with kotlinx.serialization.

Pattern Structure:

  1. @Serializable route data class with parameters
  2. ...Args helper class for extracting from SavedStateHandle
  3. NavGraphBuilder.{screen}Destination() extension for adding screen to graph
  4. NavController.navigateTo{Screen}() extension for navigation calls

Template: See Navigation template

Pattern Summary:

@Serializable
data class ExampleRoute(val userId: String, val isEditMode: Boolean = false)

data class ExampleArgs(val userId: String, val isEditMode: Boolean)

fun SavedStateHandle.toExampleArgs(): ExampleArgs {
    val route = this.toRoute<ExampleRoute>()
    return ExampleArgs(userId = route.userId, isEditMode = route.isEditMode)
}

fun NavController.navigateToExample(
    userId: String,
    isEditMode: Boolean = false,
    navOptions: NavOptions? = null,
) {
    this.navigate(route = ExampleRoute(userId, isEditMode), navOptions = navOptions)
}

fun NavGraphBuilder.exampleDestination(onNavigateBack: () -> Unit) {
    composableWithSlideTransitions<ExampleRoute> {
        ExampleScreen(onNavigateBack = onNavigateBack)
    }
}

Reference: app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/login/LoginNavigation.kt (see LoginRoute and extensions)

Key Benefits:

  • ✅ Type safety: Compile-time errors for missing parameters
  • ✅ No string literals in navigation code
  • ✅ Automatic serialization/deserialization
  • ✅ Clear contract for screen dependencies

C. Screen/Compose Implementation

All screens follow consistent Compose patterns.

Template: See Screen/Compose template

Key Patterns:

@Composable
fun ExampleScreen(
    onNavigateBack: () -> Unit,
    viewModel: ExampleViewModel = hiltViewModel(),
) {
    val state by viewModel.stateFlow.collectAsStateWithLifecycle()

    EventsEffect(viewModel = viewModel) { event ->
        when (event) {
            ExampleEvent.NavigateBack -> onNavigateBack()
        }
    }

    BitwardenScaffold(
        topBar = {
            BitwardenTopAppBar(
                title = stringResource(R.string.title),
                navigationIcon = rememberVectorPainter(BitwardenDrawable.ic_back),
                onNavigationIconClick = { viewModel.trySendAction(ExampleAction.BackClick) },
            )
        },
    ) {
        // UI content
    }
}

Reference: app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt (see LoginScreen composable)

Essential Requirements:

  • ✅ Use hiltViewModel() for dependency injection
  • ✅ Use collectAsStateWithLifecycle() for state (not collectAsState())
  • ✅ Use EventsEffect(viewModel) for one-shot events
  • ✅ Use Bitwarden* prefixed components from :ui module

State Hoisting Rules:

  • ViewModel state: Data that needs to survive process death or affects business logic
  • UI-only state: Temporary UI state (scroll position, text field focus) using remember or rememberSaveable

D. Data Layer Implementation

The data layer follows strict patterns for repositories, managers, and data sources.

Interface + Implementation Separation (ALWAYS)

Template: See Data Layer template

Pattern Summary:

// Interface (injected via Hilt)
interface ExampleRepository {
    suspend fun fetchData(id: String): ExampleResult
    val dataFlow: StateFlow<DataState<ExampleData>>
}

// Implementation (NOT directly injected)
class ExampleRepositoryImpl(
    private val exampleDiskSource: ExampleDiskSource,
    private val exampleService: ExampleService,
) : ExampleRepository {
    override suspend fun fetchData(id: String): ExampleResult {
        // NO exceptions thrown - return Result or sealed class
        return exampleService.getData(id).fold(
            onSuccess = { ExampleResult.Success(it.toModel()) },
            onFailure = { ExampleResult.Error(it.message) },
        )
    }
}

// Sealed result class (domain-specific)
sealed class ExampleResult {
    data class Success(val data: ExampleData) : ExampleResult()
    data class Error(val message: String?) : ExampleResult()
}

// Hilt Module
@Module
@InstallIn(SingletonComponent::class)
object ExampleRepositoryModule {
    @Provides
    @Singleton
    fun provideExampleRepository(
        exampleDiskSource: ExampleDiskSource,
        exampleService: ExampleService,
    ): ExampleRepository = ExampleRepositoryImpl(exampleDiskSource, exampleService)
}

Reference:

  • app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepository.kt
  • app/src/main/kotlin/com/x8bit/bitwarden/data/tools/generator/repository/di/GeneratorRepositoryModule.kt

Three-Layer Data Architecture:

  1. Data Sources - Raw data access (network, disk, SDK). Return Result<T>, never throw.
  2. Managers - Single responsibility business logic. Wrap OS/external services.
  3. Repositories - Aggregate sources/managers. Return domain-specific sealed classes.

Critical Rules:

  • ❌ NEVER throw exceptions in data layer
  • ✅ ALWAYS use interface + ...Impl pattern
  • ✅ ALWAYS inject interfaces, never implementations
  • ✅ Data sources return Result<T>, repositories return domain sealed classes
  • ✅ Use StateFlow for continuously observed data

E. UI Components

Use Existing Components First:

The :ui module provides reusable Bitwarden* prefixed components. Search before creating new ones.

Common Components:

  • BitwardenFilledButton - Primary action buttons
  • BitwardenOutlinedButton - Secondary action buttons
  • BitwardenTextField - Text input fields
  • BitwardenPasswordField - Password input with show/hide
  • BitwardenSwitch - Toggle switches
  • BitwardenTopAppBar - Toolbar/app bar
  • BitwardenScaffold - Screen container with scaffold
  • BitwardenBasicDialog - Simple dialogs
  • BitwardenLoadingDialog - Loading indicators

Component Discovery: Search ui/src/main/kotlin/com/bitwarden/ui/platform/components/ for existing Bitwarden* components. For build, test, and codebase discovery commands, use the build-test-verify skill.

When to Create New Reusable Components:

  • Component used in 3+ places
  • Component needs consistent theming across app
  • Component has semantic meaning (accessibility)
  • Component has complex state management

New Component Requirements:

  • Prefix with Bitwarden
  • Accept themed colors/styles from BitwardenTheme
  • Include preview composables for testing
  • Support accessibility (content descriptions, semantics)

String Resources:

New strings belong in the :ui module: ui/src/main/res/values/strings.xml

  • Use typographic apostrophes and quotes to avoid escape characters: you’ll not you\'ll, “word” not \"word\"
  • Reference strings via generated BitwardenString resource IDs
  • Do not add strings to other modules unless explicitly instructed

F. Security Patterns

Encrypted vs Unencrypted Storage:

Template: See Security templates

Pattern Summary:

class ExampleDiskSourceImpl(
    @EncryptedPreferences encryptedSharedPreferences: SharedPreferences,
    @UnencryptedPreferences sharedPreferences: SharedPreferences,
) : BaseEncryptedDiskSource(
    encryptedSharedPreferences = encryptedSharedPreferences,
    sharedPreferences = sharedPreferences,
),
    ExampleDiskSource {
    fun storeAuthToken(token: String) {
        putEncryptedString(KEY_TOKEN, token)  // Sensitive — uses base class method
    }

    fun storeThemePreference(isDark: Boolean) {
        putBoolean(KEY_THEME, isDark)  // Non-sensitive — uses base class method
    }
}

Android Keystore (Biometric Keys):

  • User-scoped encryption keys: BiometricsEncryptionManager
  • Keys stored in Android Keystore (hardware-backed when available)
  • Integrity validation on biometric state changes

Input Validation:

// Validation returns boolean, NEVER throws
interface RequestValidator {
    fun validate(request: Request): Boolean
}

// Sanitization removes dangerous content
fun String?.sanitizeTotpUri(issuer: String?, username: String?): String? {
    if (this.isNullOrBlank()) return null
    // Sanitize and return safe value
}

Security Checklist:

  • ✅ Use @EncryptedPreferences for credentials, keys, tokens
  • ✅ Use @UnencryptedPreferences for UI state, preferences
  • ✅ Use @IgnoredOnParcel for sensitive ViewModel state
  • ❌ NEVER log sensitive data (passwords, tokens, vault items)
  • ✅ Validate all user input before processing
  • ✅ Use Timber for non-sensitive logging only

G. Testing Patterns

ViewModel Testing:

Template: See Testing templates

Pattern Summary:

class ExampleViewModelTest : BaseViewModelTest() {
    private val mockRepository: ExampleRepository = mockk()

    @Test
    fun `ButtonClick should fetch data and update state`() = runTest {
        val expectedResult = ExampleResult.Success(data = "test")
        coEvery { mockRepository.fetchData(any()) } returns expectedResult

        val viewModel = createViewModel()
        viewModel.trySendAction(ExampleAction.ButtonClick)

        viewModel.stateFlow.test {
            assertEquals(EXPECTED_STATE.copy(data = "test"), awaitItem())
        }
    }

    private fun createViewModel(): ExampleViewModel = ExampleViewModel(
        savedStateHandle = SavedStateHandle(mapOf(KEY_STATE to EXPECTED_STATE)),
        repository = mockRepository,
    )
}

Reference: app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModelTest.kt

Key Testing Patterns:

  • ✅ Extend BaseViewModelTest for proper dispatcher management
  • ✅ Use runTest from kotlinx.coroutines.test
  • ✅ Use Turbine's .test {awaitItem()} for Flow assertions
  • ✅ Use MockK: coEvery for suspend functions, every for sync
  • ✅ Test both state changes and event emissions
  • ✅ Test both success and failure Result paths

Flow Testing with Turbine:

// Test state and events simultaneously
viewModel.stateEventFlow(backgroundScope) { stateFlow, eventFlow ->
    viewModel.trySendAction(ExampleAction.Submit)
    assertEquals(ExpectedState.Loading, stateFlow.awaitItem())
    assertEquals(ExampleEvent.ShowSuccess, eventFlow.awaitItem())
}

MockK Quick Reference:

coEvery { repository.fetchData(any()) } returns Result.success("data")  // Suspend
every { diskSource.getData() } returns "cached"  // Sync
coVerify { repository.fetchData("123") }  // Verify

H. Clock/Time Handling

All code needing current time must inject Clock for testability.

Key Requirements:

  • ✅ Inject Clock via Hilt in ViewModels
  • ✅ Pass Clock as parameter in extension functions
  • ✅ Use clock.instant() to get current time
  • ❌ Never call Instant.now() or DateTime.now() directly
  • ❌ Never use mockkStatic for datetime classes in tests

Pattern Summary:

// ViewModel with Clock
class MyViewModel @Inject constructor(
    private val clock: Clock,
) {
    val timestamp = clock.instant()
}

// Extension function with Clock parameter
fun State.getTimestamp(clock: Clock): Instant =
    existingTime ?: clock.instant()

// Test with fixed clock
val FIXED_CLOCK = Clock.fixed(
    Instant.parse("2023-10-27T12:00:00Z"),
    ZoneOffset.UTC,
)

Reference:

  • docs/STYLE_AND_BEST_PRACTICES.md (see Time and Clock Handling section)
  • core/src/main/kotlin/com/bitwarden/core/di/CoreModule.kt (see provideClock function)

Critical Gotchas:

  • ❌ Instant.now() creates hidden dependency, non-testable
  • ❌ mockkStatic(Instant::class) is fragile, can leak between tests
  • ✅ Clock.fixed(...) provides deterministic test behavior

Bitwarden-Specific Anti-Patterns

General anti-patterns are documented in CLAUDE.md. This section covers violations specific to Bitwarden's State-Action-Event, navigation, and data layer patterns:

❌ NEVER update ViewModel state directly in coroutines

  • Post internal actions, update state synchronously in handleAction()

❌ NEVER inject ...Impl classes

  • Only inject interfaces via Hilt

❌ NEVER create navigation without @Serializable routes

  • No string-based navigation, always type-safe

❌ NEVER use raw Result<T> in repositories

  • Use domain-specific sealed classes for better error handling

❌ NEVER make state classes without @Parcelize

  • All ViewModel state must survive process death

❌ NEVER skip SavedStateHandle persistence for ViewModels

  • Users lose form progress on process death

❌ NEVER forget @IgnoredOnParcel for passwords/tokens

  • Causes security vulnerability (sensitive data in parcel)

❌ NEVER use generic Exception catching

  • Catch specific exceptions only (RemoteException, IOException)

❌ NEVER call Instant.now() or DateTime.now() directly

  • Inject Clock via Hilt, use clock.instant() for testability

Quick Reference

For build, test, and codebase discovery commands, use the build-test-verify skill.

File Reference Format: When pointing to specific code, use: file_path:line_number

Example: ui/src/main/kotlin/com/bitwarden/ui/platform/base/BaseViewModel.kt (see handleAction method)

平台分布

Codex

35%
按下载量换算95

Claude

31.82%
按下载量换算87

Cursor

18.36%
按下载量换算50

Gemini CLI

8.63%
按下载量换算23

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills