慣性聚合 関心のあるブログ、ニュース、テクノロジーを効率的に追跡
原文を読む 慣性聚合で開く

おすすめ購読元

博客园 - 司徒正美
V
V2EX
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
Apple Machine Learning Research
Apple Machine Learning Research
IT之家
IT之家
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
月光博客
月光博客
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python)
Google I/O 2026から発表されたスリッパーアナウンスは、私たちがアプリを考える方法を変えるものです
Vrushali · 2026-05-24 · via DEV Community

これはGoogle I/O Writing Challenge


への提出です。Google I/O 2026では、みんなが「Compose First」「Gemini統合」と「Android 17の適応レイアウト推進」について話していました。公平なことですが、それらは大きなものです。しかし、私が考えられないでいた発表がありました。ほとんどヘッドラインにも載らなかった発表ですが、それがAppFunctions APIです。

私は10年間アンドロイドアプリを開発してきました。APIが来たり去ったりしました。これが違うと感じるのは、今日何をするかではなく、アプリがこれからどうなっていくかを示しているからです。


AppFunctionsの実際の意味

根本的には、AppFunctionsはあなたのアプリがAIアシスタントに独立した、名前付きのアクションを直接公開できるようにします。考えられるのは

  • "Create expense report"
  • "Book appointment"
  • "Send daily update"

ユーザーがアプリを起動したり、画面にナビゲートしたり、フローをタップしたりする代わりに、Geminiのようなエージェントは、アプリが前景に来ることなく、ユーザーを代表してこれらのアクションを直接呼び出すことができます.

AppFunctionを登録する方法の大まかなイメージはこちらです.

@AppFunction
suspend fun createExpenseReport(
    context: AppFunctionContext,
    params: CreateExpenseParams
): ExpenseResult {
    // your business logic here
    return ExpenseResult(id = repo.create(params))
}

フルスクリーンモードを開始します. フルスクリーンモードを終了します.

関数を定義します。パラメータを定義します。AIがいつ、どのようにそれを呼び出すかを判断します.


AppFunctionsの統合方法:ステップバイステップの例

具体的に説明しましょう。ゼロからGemini呼び出し可能な形までの完全な統合方法です.

ステップ1 — 依存関係を追加

// build.gradle.kts (module)
dependencies {
    implementation("androidx.appfunctions:appfunctions:1.0.0-alpha01")
    ksp("androidx.appfunctions:appfunctions-compiler:1.0.0-alpha01")
}

フルスクリーンモードを開始 フルスクリーンモードを終了

ステップ 2 — 入力/出力の型を定義する

AppFunctionsは型付きKotlinデータクラスを使用します。それらをシリアライズ可能に保ちなさい — AIエージェントは自然言語からそれらを構築する必要があります.

@Serializable
data class CreateExpenseParams(
    val title: String,
    val amount: Double,
    val category: String? = null  // nullable — agent may not always provide this
)

@Serializable
data class ExpenseResult(
    val id: String,
    val success: Boolean,
    val message: String
)

フルスクリーンモードを開始 フルスクリーンモードを終了

ステップ 3 — 関数を注釈する

使用@AppFunction はサスペンド関数上で実行されます。アノテーションプロセッサはコンパイル時に登録スキーマを生成します—ボイラープレートXMLは不要です。

class ExpenseAppFunctions(
    private val repo: ExpenseRepository
) {

    @AppFunction
    suspend fun createExpenseReport(
        context: AppFunctionContext,
        params: CreateExpenseParams
    ): ExpenseResult {
        val id = repo.create(params)
        return ExpenseResult(
            id = id,
            success = true,
            message = "Expense created: ${params.title}"
        )
    }
}

フルスクリーンモードに入る フルスクリーンモードから退出する

ステップ4 — アジェントセーフにする(全員がスキップするステップ)

アジェントはネットワーク障害時に再試行できる。 idempotencyがないと、1つのユーザーボイスコマンドが重複レコードを作成する可能性があります。

@AppFunction
suspend fun createExpenseReport(
    context: AppFunctionContext,
    params: CreateExpenseParams
): ExpenseResult {

    // Idempotency: return existing record if already created
    val existing = repo.findByTitle(params.title)
    if (existing != null) {
        return ExpenseResult(
            id = existing.id,
            success = true,
            message = "Already exists"
        )
    }
    return ExpenseResult(id = repo.create(params), success = true, message = "Created")
}

フルスクリーンモードを開始 フルスクリーンモードを終了

注意: AppFunctionContext.callerPackageNameを使用して、エージェントごとにidempotencyキーをスコープ化する場合、より細かい制御が必要な場合は

ステップ5 — AndroidManifestに登録

これがないと、Geminiは実行時にあなたの関数を発見できません

<!-- AndroidManifest.xml -->
<service
    android:name=".ExpenseAppFunctions"
    android:exported="true"
    android:permission="android.permission.BIND_APP_FUNCTION_SERVICE">

    <intent-filter>
        <action android:name="androidx.appfunctions.AppFunctionService"/>
    </intent-filter>

</service>

フルスクリーンモードを開始 フルスクリーンモードを終了

ステップ6 — ジェミニがそれを使う方法

記録されたら、ユーザーが 「£45のタクシーを経費に追加」 と言えば、これが背景でトリガーされます — UIなし、ナビゲーションなし、タップなし:

// Gemini constructs and executes this on-device
val result = appFunctionManager.executeAppFunction(
    targetPackage = "com.yourapp",
    functionId = "createExpenseReport",
    params = CreateExpenseParams(
        title = "Taxi",
        amount = 45.0,
        category = "Transport"
    )
)
// result.message → "Expense created: Taxi"

フルスクリーンモードに入る フルスクリーンモードから退出する

それは完全なループです。依存からエージェントコール可能なアクションへの6つのステップ——そして実際の作業の大部分はステップ3と4で、ステップ1や


ではありません。 なぜこれは聞こえるより大きいのか

この精神的な変化が必要であることを率直に言います.

過去10年間、Androidアプリは受動的なツールでした は、ユーザーがそれらを開き、それらとやり取りし、閉じます。アプリは待ちます。ユーザーが戻ってきます。それがモデルです.

AppFunctions はそのモデルを完全に破ります.

注意: あなたのアプリはもはや UI だけではありません。外部の知性によって呼び出される機能のセットです — ユーザーを代表して、複数のアプリ間で動作し、明示的なナビゲーションを必要としません。

それはインクリメンタルなアップデートではありません。それは別のパラダイムです.

これが永遠に私たちが持ってきたUXの仮定にとって意味することを考えてみてください.

  • ユーザーを案内するために設計されたオンボーディングフロー?エージェントがそれらをバイパスする場合、それほど関連性はありません.
  • ナビゲーションアーキテクチャ?まだ重要ですが、それが唯一の入り口ではありません.
  • 状態管理?今や、UIライフサイクルの外からトリガーされたアクションを考慮する必要があります

誰も話していない部分:これが開発者に求めるもの

ここで、私は多くのカバレッジがボールを落としていると考えます

皆がAppFunctionsをアプリに「追加」する機能として捉えています。注釈をいくつか追加し、いくつかのアクションを公開すれば完了です。しかし、この捉え方はアーキテクチャ的な意味合いを見逃しています。

あなたのアプリケーションロジックはエージェントに安全である必要があります

これは意味します

  • 一貫性がより重要ですネットワークの問題が発生した場合、エージェントはcreateExpenseReportを二回呼び出すかもしれません。それを処理しましたか
  • エラーメッセージは機械が読める必要がありますあなたの関数が失敗した場合、エージェントは復旧またはレポートするための構造化された情報が必要です——トーストではありません
  • 権限と認証は明示的に設定される必要があります. ユーザーを代表して行動するエージェントもスコープを尊重する必要があります。周囲のユーザー認証を単に想定することはできません.

これは「機能を追加する」よりも「サービスレイヤーを再考する」に近いです.


私の率直な見解:興奮しますが、準備はできていません

正直に言わせてもらいますが — 広義のAndroid開発者コミュニティはこの移行にまだ準備できていません.

Composableへの移行はまだ中です。多くのチームがまだスパゲッティからMVVMを解きほぐしています。そして今、私たちはアプリをエージェント互換APIとして考えるよう求められていますか?

注意:「GoogleがAppFunctionsを発表した」と「大多数の生産アプリが設計良好なAppFunctionsを公開している」という間のギャップは、年単位で測られるでしょう。それでいいのです——ただし、アーキテクチャについて考えることを始めるなら。.

このカーブをリードする開発者は、今すぐビジネスロジックを第一級APIとして扱う人々です——クリーンな使用例、明確な入出力契約、適切なエラーハンドリング。まだエージェントが呼んでいるわけではなく、良いアーキテクチャが利益を還元するからです.


明日私がチームに伝えるべきこと

もし明日、I/O 2026から一つの要点を引き出してスタンドアップに入って行ったら、それがこれだ:

エージェント対応のためにあなたのユースケースを監査するのを始めてください。

次のスプリントにAppFunctionsをリリースするためではなく、次のように問いかけます:AIがキーボードに人間がいない場合にこのアクションを呼び出す必要があったら、私たちのコードは耐えうるか?エラー状態は意味があるか?認証モデルは機能するか?

その質問だけで、AppFunctionsに関わらず解決すべき多くの構造的負債が浮かび上がります。


プライバシーについて一言 — 誰かが言わなければならないことです

AppFunctionsに興奮しています。しかし、このプライバシー表面を開くことについて指摘しなければ、あなたに不誠実になることになります。

エージェントがユーザーが明示的に何かをタップしないであなたのアプリを呼び出せる場合、同意モデルが曖昧になります。考えに値するいくつかのことは以下の通りです:

  • エージェントは静かに動作します。ユーザーは一度「タクシー費用を追加」と言いました—彼らは自分のデバイスからどのデータが残ったかやどのシステムが触られたかを確認しませんでした。あなたの関数はそれが言う通りに正確に動作する必要があります。
  • 機密データには明示的なスコープが必要です。 アプリ機能が金融、健康、またはメッセージに触れる場合、出力を公開APIレスポンスとして扱ってください。必要な最小限のデータのみを返し、それ以上は何も返さないようにしてください.
  • 呼び出し元のパッケージ名を検証してください. AppFunctionContext は呼び出し元のエージェントのパッケージを提供します。機密操作の場合、信頼できる呼び出し元のみをホワイトリストに追加してください——すべてのエージェントが同等の信頼を得るとは想定しないでください.
  • すべての呼び出しを記録してください。 ユーザーは自分のエージェントが自分の代わりに何をしたかを確認できるべきです。最初から監査証跡を構築してください。

良いニュースは:AndroidのBIND_APP_FUNCTION_SERVICE権限により、デフォルトではGeminiのようなシステムに認められたエージェントのみがあなたの機能を呼び出すことができます。プラットフォームのガイドラインは十分です。しかし、エージェントエコシステムが成長するにつれて、攻撃対象も広がります。

注意: すべてを@AppFunctionは公開APIエンドポイントのように、入力を検証し、出力の範囲を設定し、呼び出しを記録します。注釈はシンプルですが、それが持つ責任はありません。

実際に公開しているもの

これが開発者を驚かせることです:あなたが公開しているのはソースコードではなく、あなたは実際に公開しているのはアプリケーションの機能表面であり、それには独自のリスクがあります。

アプリの機能が外部に示すもの:

  • createExpenseReportdeleteUserAccountといった関数名は発見可能な公開スキーマとして機能します — 適切なツールを持つ誰でも、あなたのアプリが登録している内容を列挙できます
  • パラメータの型はあなたの内部データモデルを明らかにします。CreateExpenseParamsの形状も、単に名前だけではなく見えます
  • あなたのビジネスロジックの境界 — もしarchiveAllRecords は AppFunctionとして存在し、UIを提供する前にその機能を宣伝していた

考慮すべき実際の攻撃シナリオ:

  • プローブアプリが登録された関数を列挙してデータモデルを逆-engineerする
  • 管理者レベルの関数が内部認証チェックなしで信頼できないエージェントによって呼び出される——マニフェスト権限だけでは不十分
  • リリース前に競合他社はあなたの関数名を読み取り、何が来るかを正確に知る

どうすればいいか:

  • 明示的にエージェント呼び出し可能として設計されていない関数を登録しない — あなたのリポジトリにあるすべてが@AppFunction
  • 認証チェックを追加関数内に すべての機能、宣言された権限とは独立して
  • 敏感な操作では汎用的な名前を使用し、関数名自体が意図を漏らさないように
  • リリースする前に @AppFunction 注釈を監査する。公開されるREST APIを監査するのと同じ方法で

Google I/O 2026には多くの興奮する発表がありました。Compose Firstは遅れても歓迎されます。AI開発ツールは本当に役立ちます。Android Automotiveは探求する価値のある実際のキャリアパスです.

しかし、AppFunctionsは「Androidアプリ」という意味を変えるものです。それは見過ごされがちなものです。そして5年後、I/O 2026をシフトが始まった瞬間として振り返ると思います。

今日からエージェントがあなたの関数を呼び始めた場合、あなたの現在のサービスレイヤーで idempotency(一貫性)をどのように処理しますか?アーキテクチャの「悪夢」シナリオをコメント欄に投稿してください——それを聞けて嬉しいです.


関連セッション: 開発者キーノート — Google I/O 2026