API مربوط به AppFunctions را به برنامه خود اضافه کنید.

این راهنما توضیح می‌دهد که چگونه API مربوط به AppFunctions را در برنامه اندروید خود ادغام کنید، منطق یک تابع را پیاده‌سازی کنید و تأیید کنید که ادغام به درستی کار می‌کند.

سازگاری نسخه

این پیاده‌سازی مستلزم آن است که compileSdk پروژه شما روی سطح API 36 یا بالاتر تنظیم شده باشد.

برنامه شما لازم نیست تأیید کند که آیا AppFunctions پشتیبانی می‌شود یا خیر؛ این کار به طور خودکار در کتابخانه AppFunctions Jetpack انجام می‌شود. AppFunctionManager در صورت پشتیبانی از ویژگی، یک نمونه را برمی‌گرداند و در غیر این صورت مقدار null را برمی‌گرداند.

وابستگی‌ها

وابستگی‌های کتابخانه‌ای مورد نیاز را به فایل build.gradle.kts (یا build.gradle) ماژول خود اضافه کنید و افزونه KSP را در ماژول برنامه سطح بالای خود مطابق شکل پیکربندی کنید:

dependencies {
  implementation("androidx.appfunctions:appfunctions:1.0.0-alpha10")
  // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP)
  // See Add the KSP plugin to your project
  ksp("androidx.appfunctions:appfunctions-compiler:1.0.0-alpha10")
}

پیاده‌سازی منطق AppFunctions

برای پیاده‌سازی یک AppFunction برای برنامه اندروید خود، کلاسی ایجاد کنید که منطق خاص AppFunctions را پیاده‌سازی کند. این شامل ایجاد کلاس‌های داده قابل سریال‌سازی برای پارامترها و پاسخ‌ها و سپس ارائه منطق اصلی در داخل متد تابع است.

کد زیر نمونه‌ای از پیاده‌سازی ایجاد یک وظیفه در برنامه TODO را نشان می‌دهد که شامل تعریف پارامترهای سفارشی و انواع پاسخ و منطق تابع اصلی با استفاده از یک مخزن است.

@RequiresApi(36)
@AndroidEntryPoint
@AppFunctionServiceEntryPoint(
    serviceName = "TaskAppFunctionService",
    appFunctionXmlFileName = "task_app_function_service",
)
abstract class BaseTaskAppFunctionService : AppFunctionService() {
    @Inject internal lateinit var taskRepository: TaskRepository

    /**
     * Creates a task based on [createTaskParams].
     *
     * @param createTaskParams The parameter to describe how to create the task.
     */
    @AppFunction(isDescribedByKDoc = true)
    suspend fun createTask(
        createTaskParams: CreateTaskParams,
    ): Task = withContext(Dispatchers.IO) {
        // Developers can use predefined exceptions to let the agent know
        // why it failed.
        if (createTaskParams.title == null && createTaskParams.content == null) {
            throw AppFunctionInvalidArgumentException("Title or content should be non-null")
        }

        val id = taskRepository.createTask(
            createTaskParams.title,
            createTaskParams.content
        )

        return@withContext taskRepository
            .getTask(id)
            ?.toTask()
            ?: throw AppFunctionElementNotFoundException("Task not found for ID = $id")
    }

    // Maps internal TaskEntity
    private fun TaskEntity.toTask() = Task(id = id, title = title, content = description)
}

نکات کلیدی در مورد کد

  • به طور پیش‌فرض، پیاده‌سازی AppFunction در نخ رابط کاربری اندروید اجرا می‌شود. بنابراین، یک عملیات طولانی‌مدت باید موارد زیر را انجام دهد:
    • تابع AppFunction را به عنوان یک تابع suspend تعریف کنید.
    • وقتی عملیات می‌تواند نخ را مسدود کند، به یک توزیع‌کننده کوروتین مناسب تغییر دهید.
  • وقتی isDescribedByKDoc روی true تنظیم شده باشد، توضیحات تابع یا توضیحات قابل سریال‌سازی به عنوان بخشی از AppFunctionMetadata کدگذاری می‌شود تا به عامل کمک کند نحوه استفاده از AppFunction برنامه را درک کند.

سرویس AppFunction را در مانیفست خود تعریف کنید.

تعریف سرویس تولید شده توسط KSP و ویژگی app_metadata را در داخل مانیفست ماژول خود، مثلاً در src/main/AndroidManifest.xml ، ثبت کنید. کامپایلر KSP کلاس سرویس عینی ( TaskAppFunctionService ) را که کلاس نقطه ورود انتزاعی شما را بسط می‌دهد، به همراه طرحواره XML مربوطه در دایرکتوری assets/ شما تولید می‌کند.

<service
    android:name="com.example.snippets.ai.TaskAppFunctionService"
    android:permission="android.permission.BIND_APP_FUNCTION_SERVICE"
    android:exported="true"
    tools:targetApi="36">
    <property
        android:name="android.app.appfunctions.schema"
        android:value="app_functions_schema.xsd" />
    <property
        android:name="android.app.appfunctions.v2"
        android:value="task_app_function_service.xml" />
    <intent-filter>
        <action android:name="android.app.appfunctions.AppFunctionService" />
    </intent-filter>
</service>
<property
    android:name="android.app.appfunctions.app_metadata"
    android:resource="@xml/app_metadata" />

اختیاری: فعال/غیرفعال کردن قابلیت دسترسی AppFunction در زمان اجرا

از API AppFunctionManager برای فعال یا غیرفعال کردن صریح توابع هنگام تنظیم AppFunctions خود استفاده کنید. تنظیم می‌تواند زمانی مفید باشد که ویژگی‌های خاصی از برنامه شما برای همه کاربران در دسترس نباشد. با فعال یا غیرفعال کردن پویای AppFunctions، سیستم اطلاعاتی دقیقاً می‌داند کدام ویژگی‌ها در هر زمان معین برای کاربر شما در دسترس هستند.

برای مسدود کردن ایمن AppFunctionهایی که به وضعیت حساب خاصی نیاز دارند، یک فرآیند دو مرحله‌ای را دنبال کنید:

مرحله ۱. غیرفعال کردن پیش‌فرض این عملکرد

برای جلوگیری از دسترسی به تابع قبل از تأیید feature flag، پارامتر isEnabled از حاشیه‌نویسی @AppFunction را روی false تنظیم کنید.

@AppFunction(isEnabled = false, isDescribedByKDoc = true)
suspend fun createTask(
    createTaskParams: CreateTaskParams,
): Task = TODO()

مرحله ۲. فعال کردن پویای تابع در زمان اجرا

برای هر کلاس AppFunction ، کامپایلر یک کلاس متناظر حاوی ثابت‌های شناسه تابع (با استفاده از پسوند Ids ) تولید می‌کند. می‌توانید از این ثابت‌های شناسه تولید شده در کنار متد setAppFunctionEnabled از AppFunctionManagerCompat برای تغییر وضعیت فعال بودن یک تابع در زمان اجرا استفاده کنید.

suspend fun onFeatureEnabled(context: Context) {
    try {
        AppFunctionManager.getInstance(context)
            ?.setAppFunctionEnabled(
                BaseTaskAppFunctionServiceIds.CREATE_TASK_ID,
                AppFunctionManager.APP_FUNCTION_STATE_ENABLED,
            )
    } catch (e: Exception) {
        // Handle exception: AppFunctions indexation may not be fully completed
        // upon initial app startup.
    }
}

suspend fun onFeatureDisabled(context: Context) {
    try {
        AppFunctionManager.getInstance(context)
            ?.setAppFunctionEnabled(
                BaseTaskAppFunctionServiceIds.CREATE_TASK_ID,
                AppFunctionManager.APP_FUNCTION_STATE_DISABLED,
            )
    } catch (e: Exception) {
        // Handle exception
    }
}

ملاحظات مربوط به انواع قابلیت‌هایی که باید در دسترس قرار گیرند

امنیت همیشه از اهمیت بالایی برخوردار است. وقتی انتخاب می‌کنید که کدام قابلیت‌های برنامه‌تان را به عنوان AppFunctions در دسترس قرار دهید، مهم است به یاد داشته باشید که عوامل سیستم ممکن است درخواست‌های کاربر را روی سرور پردازش کنند تا از قابلیت‌های پیشرفته LLM استفاده کنند.

برای ارائه یک تجربه کاربری عالی که از افشای اطلاعات حساس نیز جلوگیری می‌کند، توصیه می‌کنیم این دستورالعمل‌ها را دنبال کنید:

  • قابلیت‌هایی که از زبان طبیعی بهره می‌برند : وظایفی را در دسترس قرار دهید که بیان آنها در مکالمه برای کاربر آسان‌تر از پیمایش دستی رابط کاربری باشد.
  • دسترسی محدود : AppFunctionهایی ایجاد کنید که فقط به عامل (agent) دسترسی به داده‌ها و اقداماتی را می‌دهند که برای انجام درخواست خاص کاربر لازم است.
  • اطلاعات غیرحساس : فقط داده‌هایی را به اشتراک بگذارید که خیلی شخصی یا محرمانه نباشند، یا داده‌هایی که کاربر صراحتاً در چارچوب عمل به اشتراک‌گذاری آنها رضایت داده باشد.
  • تأیید بدون ابهام برای هرگونه اقدام مخرب : در مورد توابعی که اقدامات مخرب انجام می‌دهند (مانند حذف داده‌ها) بسیار محتاط باشید. اگرچه ممکن است عامل آنها را فراخوانی کند، برنامه شما باید مرحله تأیید خود را داشته باشد و از زبانی واضح و بدون ابهام در مورد اهداف استفاده کند. همچنین اضافه کردن بیش از یک مرحله تأیید مفید است تا مطمئن شوید که کاربر از آنچه از او خواسته می‌شود آگاه است.

تأیید ادغام AppFunction

برای تأیید اینکه آیا AppFunctions را به درستی ادغام کرده‌اید، می‌توانید از adb shell cmd app_function استفاده کنید.

برای مشاهده جزئیات AppFunctionهایی که برنامه شما ارائه می‌دهد، adb shell cmd app_function list-app-functions | grep --after-context 10 $myPackageName استفاده کنید.

همچنین می‌توانید یک AppFunction را مستقیماً از خط فرمان با استفاده از شناسه صریح آن ( "$enclosingClassName#$methodName" ) اجرا کنید:

adb shell "cmd app_function execute-app-function \
  --package com.example.android.appfunctions \
  --function 'com.example.android.appfunctions.BaseTaskAppFunctionService#createTask' \
  --parameters '{\"createTaskParams\": {\"title\": \"Buy milk\", \"content\": \"From grocery store\"}}'"

برای تجربه Android MCP در عمل و تأیید گردش‌های کاری سرتاسری بدون نیاز به هیچ گونه اعلانی، برنامه اندروید AppFunctions testing agent را روی دستگاه خود نصب و اجرا کنید.

اگر در حال تأیید ادغام خود با استفاده از دستیارهای مبتنی بر چت مانند Gemini در اندروید استودیو هستید، از مهارت توسعه AppFunctions استفاده کنید یا یک اعلان مانند موارد زیر ارائه دهید:

Execute `adb shell cmd app_function` to learn how the tool works, then act as a
chat agent aiming to invoke AppFunctions to fulfil user prompts for this app.
Rely on the AppFunction description as instructions.

مهاجرت از نسخه‌های API پایین‌تر

در نسخه 1.0.0-alpha10، AppFunctions یک معماری زمان کامپایل @AppFunctionServiceEntryPoint معرفی کرد که وابستگی‌های کتابخانه را تجمیع کرده و جایگزین ارائه‌دهندگان پیکربندی قدیمی ( AppFunctionConfiguration.Provider ) می‌شود.

اگر برنامه شما در حال حاضر از نسخه قبلی AppFunctions (مانند 1.0.0-alpha09) استفاده می‌کند، می‌توانید مهاجرت خود را با استفاده از مهارت AppFunctions agent در یک IDE هوش مصنوعی مانند Gemini در اندروید استودیو خودکار کنید. این مهارت شامل قوانین مهاجرت اختصاصی است که یک agent را برای ادغام وابستگی‌های ساخت شما، ایجاد پوشش سرویس مورد نیاز @AppFunctionServiceEntryPoint ، جداسازی پارامترهای زمینه و به‌روزرسانی اعلان‌های مانیفست شما راهنمایی می‌کند.

برای شروع مهاجرت خودکار با عامل هوش مصنوعی خود، از اعلانی مانند موارد زیر استفاده کنید:

Use the AppFunctions migration skill to upgrade my app's AppFunctions implementation from 1.0.0-alpha09 to the 1.0.0-alpha10 @AppFunctionServiceEntryPoint architecture.