More screenshots

    Works with the AI Agents you already use

    Claude CodeClaude CodeCursorCursorCodex CLICodex CLIMuseMuseDotsDots+22 more

    harmonyos app dev

    1

    Expert guidance for HarmonyOS NEXT development, ArkTS/ArkUI layouts, and Xiaoyi intelligent agent orchestration.

    $9.99

    Secure checkout via Stripe

    Money-back guarantee

    Converts to your local currency at checkout

    Security scanned
    harmonyos app dev

    harmonyos app dev

    Example session with this skill installed

    I'm porting my Android news app to HarmonyOS NEXT. Build the article list screen: fetch JSON from https://api.example.com/articles, show the articles in a scrollable list, and tapping one should open a detail page. Set up whatever project config this needs.

    • Read your context and instructions
    • Compiled the harmonyos app dev

    Using the

    harmonyos-app-dev skill. This touches three surfaces, so I'm applying its app-structure, UI and network references: Stage model, @kit.* imports, Navigation for page flow (not the deprecated global router), and @kit.NetworkKit for HTTP. Nothing from Android or OpenHarmony is carried over.

    What you get

    #FilePurpose
    1entry/src/main/module.json5declares ohos.permission.INTERNET (required even though it is auto-granted)
    2entry/src/main/ets/model/Article.etstyped article model + JSON parsing
    3entry/src/main/ets/service/ArticleService.etsone HTTP call, one HttpRequest, always destroyed
    4entry/src/main/ets/pages/Index.etsNavigation root with the list, and the Detail destination

    Target: API 12+ (compatibleSdkVersion ≥ 5.0.0(12)), verified unchanged up to SDK 26.0.0.

    1. entry/src/main/module.json5 — add the permission

    {
      "module": {
        // ...existing fields...
        "requestPermissions": [
          { "name": "ohos.permission.INTERNET" }
        ]
      }
    }
    

    Without this every request is rejected at runtime, and nothing in the IDE warns you first.

    2. entry/src/main/ets/model/Article.ets

    export interface ArticleDto {
      id: number;
      title: string;
      summary: string;
      body: string;
      publishedAt: string;
    }
    
    // ArkTS forbids untyped `any` from JSON.parse — parse into a known shape.
    export function parseArticles(json: string): ArticleDto[] {
      const raw = JSON.parse(json) as ArticleDto[];
      return raw.map((a): ArticleDto => ({
        id: a.id,
        title: a.title,
        summary: a.summary,
        body: a.body,
        publishedAt: a.publishedAt
      }));
    }
    

    3. entry/src/main/ets/service/ArticleService.ets

    import { http } from '@kit.NetworkKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    import { ArticleDto, parseArticles } from '../model/Article';
    
    const API_URL = 'https://api.example.com/articles';
    
    export async function fetchArticles(): Promise<ArticleDto[]> {
      // One HttpRequest per in-flight call; never reuse it.
      const req: http.HttpRequest = http.createHttp();
      try {
        const res = await req.request(API_URL, {
          method: http.RequestMethod.GET,
          header: { 'content-type': 'application/json' },
          expectDataType: http.HttpDataType.STRING,
          connectTimeout: 10_000,
          readTimeout: 10_000
        });
        if (res.responseCode !== 200) {
          throw new Error(`HTTP ${res.responseCode}`);
        }
        return parseArticles(String(res.result));
      } catch (e) {
        const err = e as BusinessError;
        console.error(`fetchArticles failed: ${err.code} ${err.message}`);
        throw err;
      } finally {
        req.destroy();
      }
    }
    

    4. entry/src/main/ets/pages/Index.ets

    import { fetchArticles } from '../service/ArticleService';
    import { ArticleDto } from '../model/Article';
    
    @Entry
    @Component
    struct Index {
      @State pathStack: NavPathStack = new NavPathStack();
      @State articles: ArticleDto[] = [];
      @State loading: boolean = true;
      @State error: string = '';
    
      aboutToAppear(): void {
        this.load();
      }
    
      async load(): Promise<void> {
        this.loading = true;
        this.error = '';
        try {
          this.articles = await fetchArticles();   // reassign, not push(): triggers re-render
        } catch (e) {
          this.error = 'Could not load articles. Pull down to retry.';
        } finally {
          this.loading = false;
        }
      }
    
      build() {
        Navigation(this.pathStack) {
          if (this.loading) {
            LoadingProgress().width(48).height(48)
          } else if (this.error !== '') {
            Column({ space: 12 }) {
              Text(this.error).fontSize(16)
              Button('Retry').onClick(() => { this.load() })
            }
          } else {
            List({ space: 8 }) {
              ForEach(this.articles, (item: ArticleDto) => {
                ListItem() {
                  Column({ space: 4 }) {
                    Text(item.title).fontSize(18).fontWeight(FontWeight.Medium).maxLines(2)
                    Text(item.summary).fontSize(14).fontColor('#666666').maxLines(2)
                  }
                  .alignItems(HorizontalAlign.Start)
                  .width('100%')
                  .padding(16)
                }
                .onClick(() => {
                  this.pathStack.pushPath({ name: 'Detail', param: item });
                })
              }, (item: ArticleDto) => item.id.toString())   // stable key: avoids re-creating every row
            }
            .width('100%')
            .height('100%')
            .divider({ strokeWidth: 1, color: '#EEEEEE' })
          }
        }
        .title('Articles')
        .mode(NavigationMode.Stack)
        .navDestination(this.destinations)
      }
    
      @Builder
      destinations(name: string, param: object) {
        if (name === 'Detail') {
          ArticleDetail({ article: param as ArticleDto })
        }
      }
    }
    
    @Component
    struct ArticleDetail {
      article: ArticleDto = { id: 0, title: '', summary: '', body: '', publishedAt: '' };
    
      build() {
        NavDestination() {
          Scroll() {
            Column({ space: 12 }) {
              Text(this.article.title).fontSize(24).fontWeight(FontWeight.Bold)
              Text(this.article.publishedAt).fontSize(12).fontColor('#999999')
              Text(this.article.body).fontSize(16).lineHeight(24)
            }
            .alignItems(HorizontalAlign.Start)
            .padding(16)
          }
        }
        .title(this.article.title)
      }
    }
    

    Android → HarmonyOS NEXT mapping (what changed in the port)

    Android habitHarmonyOS NEXT equivalent used hereWhy
    AndroidManifest.xml <uses-permission>module.json5 → requestPermissionsStage-model config; INTERNET is system_grant but still must be declared
    RecyclerView + adapterList + ForEach with a key generatordeclarative; the key function is what stops full re-renders
    Intent + second ActivityNavigation + NavPathStack.pushPath + NavDestinationone UIAbility, in-page stack; page state survives push/pop
    OkHttp / Retrofit@kit.NetworkKit http.createHttp()one request object per call, destroy() in finally
    onCreate fetchaboutToAppear()component lifecycle hook, runs before first build()

    Deliberately

    not used: the global router (phased out), @ohos.* imports (older form), and any-typed JSON (rejected by ArkTS strict mode).

    Run it

    hvigorw assembleHap
    hdc install entry/build/default/outputs/default/entry-default-signed.hap
    

    Or the green Run button in DevEco Studio with auto-signing enabled once under

    File > Project Structure > Signing Configs.

    Next steps

    1. Large feeds: switch ForEach to LazyForEach with an IDataSource so only visible rows are built.

    Pull-to-refresh: wrap the List in Refresh({ refreshing: $$this.refreshing }) and call load() in onRefreshing.
    3.

    Offline cache: persist the last response with @kit.ArkData preferences, read it in aboutToAppear() before the network call.
    4. Images: add Image(item.coverUrl) to the row; remote images need no extra permission beyond INTERNET.

    References: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/http-request (HTTP data request), https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navigation (Navigation), https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/module-configuration-file (module.json5).

    Connects securely to your tools. The creator never sees your data.

    About this skill

    HarmonyOS NEXT represents a complete departure from the Android/AOSP ecosystem. Developers moving to Huawei's standalone OS face a steep learning curve with ArkTS, the Stage model, and the unique Xiaoyi (小艺) agent infrastructure. Relying on outdated OpenHarmony snippets or generic TypeScript advice often leads to runtime failures and rejected builds.

    This skill provides a technical bridge to the official HarmonyOS NEXT (API 12-26) documentation. It handles the nuances of declarative UI construction, state management versioning, and system-level capability exposure. Whether you are migrating a legacy FA model app or building native intelligent agents for the Xiaoyi Open Platform, this tool ensures your code aligns with the latest SDK requirements.

    What it does

    • ArkUI construction generates declarative UI components using ArkTS decorators like @Entry, @Component, and @Builder.
    • State management implements data flow using both V1 (@State, @Link) and V2 (@ObservedV2, @Trace) patterns.
    • Xiaoyi agent development scaffolds intelligent agents using the A2A protocol, AgentKit, and HMAF frameworks.
    • Lifecycle orchestration manages UIAbility and ExtensionAbility transitions within the modern Stage model.
    • System kit integration provides boilerplate for @kit.AbilityKit, @kit.NetworkKit, and hardware-level APIs.

    How it works

    1. Analyze project scope by checking module.json5 for compatibleSdkVersion and deviceTypes.
    2. Retrieve official specs by searching the local reference bundle or fetching live API documentation from Huawei.
    3. Generate compliant code using current ArkTS conventions, kit-style imports, and Stage model structures.

    Frameworks & tools

    Developed for HarmonyOS NEXT (API 12 to 26), ArkTS, ArkUI, DevEco Studio, hvigor, ohpm, and the Xiaoyi Open Platform.

    Why this beats prompting it yourself

    Standard LLMs frequently hallucinate by mixing HarmonyOS code with OpenHarmony or Android snippets. This skill restricts logic to the official Huawei harmonyos-guides and service docs, ensuring API compatibility for NEXT-generation devices.

    Use cases

    • Migrating legacy FA model applications to the modern Stage model architecture.
    • Building complex list-detail layouts with Navigation and immersive light-sense materials.
    • Implementing cloud-side or device-side A2A agents for the Xiaoyi ecosystem.
    • Configuring multi-module HAP/HSP/HAR project structures and permissions.

    Known limitations

    This skill specifically excludes OpenHarmony and legacy Android-compatible HarmonyOS versions. Local documentation syncing requires a one-time 10-minute download via the provided Python scripts.

    How to use

    Skills on Agensi run inside your AI agent. Copy the prompt, paste it into your agent, and it connects to Agensi and installs this skill for you. If a payment is needed, your agent shows it to you first.

    Reviews

    No reviews yet

    Be one of the first to try it. Every listed skill passes our trust checks below.

    Security scanned

    Passed our 8-point scan before listing

    Fresh listing

    Recently published to Agensi

    Money-back guarantee

    Doesn't do what its page promises? You get your money back.

    Trust & safety

    Security scanned

    Verified clean 6 days ago

    • Passed all security checks, Safe to install

    Requires

    Huawei
    Python
    macOS
    Node.js

    Listed6 days ago

    What's inside

    Frequently Asked Questions