AppFunctions API'yi uygulamanıza ekleme

Bu kılavuzda, AppFunctions API'yi Android uygulamanıza nasıl entegre edeceğiniz, bir işlevin mantığını nasıl uygulayacağınız ve entegrasyonun doğru şekilde çalıştığını nasıl doğrulayacağınız açıklanmaktadır.

Sürüm uyumluluğu

Bu uygulama, projenizin compileSdk API düzeyi 36 veya sonraki sürümlere ayarlanmasını gerektirir.

Uygulamanızın, AppFunctions'ın desteklenip desteklenmediğini doğrulaması gerekmez. Bu işlem, AppFunctions Jetpack kitaplığı içinde otomatik olarak yapılır. AppFunctionManager, özellik destekleniyorsa bir örnek, desteklenmiyorsa null döndürür.

Bağımlılıklar

Gerekli kitaplık bağımlılıklarını modülünüzün build.gradle.kts (veya build.gradle) dosyasına ekleyin ve KSP eklentisini üst düzey uygulama modülünüzde gösterildiği gibi yapılandırın:

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 mantığını uygulama

Android uygulamanız için bir AppFunction uygulamak üzere belirli AppFunctions mantığını uygulayan bir sınıf oluşturun. Bu işlemde, parametreler ve yanıtlar için serileştirilebilir veri sınıfları oluşturulur ve ardından işlev yönteminde temel mantık sağlanır.

Aşağıdaki kodda, özel parametreleri ve yanıt türlerini tanımlama ve bir depo kullanarak ana işlev mantığını uygulama dahil olmak üzere TODO uygulamasında görev oluşturmaya yönelik örnek bir uygulama gösterilmektedir.

@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)
}

Kodla ilgili önemli noktalar

  • Varsayılan olarak, AppFunction uygulaması Android kullanıcı arayüzü iş parçacığında çalışır. Bu nedenle, uzun süreli bir işlem aşağıdakileri yapmalıdır:
    • AppFunction'ı askıya alma işlevi olarak bildirin.
    • İşlem, iş parçacığını engelleyebileceğinde uygun bir coroutine dağıtıcıya geçin.
  • isDescribedByKDoc, true olarak ayarlandığında, işlev açıklaması veya serileştirilebilir açıklama, AppFunctionMetadata'ın bir parçası olarak kodlanır. Bu sayede, temsilcinin uygulamanın AppFunction'ını nasıl kullanacağını anlamasına yardımcı olunur.

Manifest dosyanızda AppFunction hizmetini bildirin

KSP tarafından oluşturulan hizmet bildirimini ve app_metadata özelliğini modül manifestinizde (örneğin, src/main/AndroidManifest.xml içinde) kaydedin. KSP derleyicisi, TaskAppFunctionService soyut giriş noktası sınıfınızı genişleten somut hizmet sınıfını ve assets/ dizininizdeki ilgili XML şemasını oluşturur.

<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" />

İsteğe bağlı: Çalışma zamanında AppFunction kullanılabilirliğini değiştirme

AppFunction'larınızı sınırlarken işlevleri açıkça etkinleştirmek veya devre dışı bırakmak için AppFunctionManager API'sini kullanın. Uygulamanızın belirli özellikleri tüm kullanıcılara sunulmadığında sınırlama kullanışlı olabilir. AppFunction'ları dinamik olarak etkinleştirip devre dışı bırakarak, yapay zeka sistemi kullanıcınızın herhangi bir zamanda hangi özelliklere erişebileceğini tam olarak bilir.

Belirli bir hesap durumu gerektiren AppFunction'ları güvenli bir şekilde sınırlamak için iki adımlı bir süreç izleyin:

1. adım. İşlevi varsayılan olarak devre dışı bırakma

Özellik bayrağınız doğrulanmadan önce işlevin erişilebilir olmasını önlemek için @AppFunction ek açıklamanızın isEnabled parametresini false olarak ayarlayın.

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

2. Adım Çalışma zamanında işlevi dinamik olarak etkinleştirme

Derleyici, her AppFunction sınıfı için işlev kimliği sabitlerini (Ids sonekini kullanarak) içeren ilgili bir sınıf oluşturur. Bu oluşturulan kimlik sabitlerini, bir işlevin etkin durumunu çalışma zamanında değiştirmek için AppFunctionManagerCompat içindeki setAppFunctionEnabled yöntemiyle birlikte kullanabilirsiniz.

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
    }
}

Kullanıma sunulacak işlev türleriyle ilgili dikkat edilmesi gerekenler

Güvenlik her zaman en önemli önceliğimizdir. Uygulamanızın hangi özelliklerini AppFunction olarak kullanıma sunacağınızı seçerken sistem aracıların, gelişmiş LLM özelliklerinden yararlanmak için kullanıcı sorgularını sunucuda işleyebileceğini unutmayın.

Hassas bilgilerin açığa çıkmasını önlerken aynı zamanda mükemmel bir kullanıcı deneyimi sunmak için aşağıdaki yönergelere uymanızı öneririz:

  • Doğal dilden yararlanan işlevler: Kullanıcının manuel kullanıcı arayüzü gezinmesiyle ifade etmekte zorlanacağı görevleri, sohbette kolayca ifade edebileceği şekilde sunun.
  • Sınırlı erişim: Yalnızca kullanıcının belirli isteğini karşılamak için gereken verilere ve işlemlere erişim izni veren AppFunction'lar oluşturun.
  • Hassas olmayan bilgiler: Yalnızca çok kişisel veya gizli olmayan ya da kullanıcının işlem bağlamında paylaşmayı açıkça kabul ettiği verileri paylaşın.
  • Yıkıcı işlemler için net onay: Yıkıcı işlemler (ör. veri silme) gerçekleştiren işlevleri kullanırken çok dikkatli olun. Aracı bunları çağırabilir ancak uygulamanız kendi onay adımını içermeli ve amaçlarla ilgili net, anlaşılır bir dil kullanmalıdır. Kullanıcının ne yapması gerektiğinin farkında olduğundan emin olmak için birden fazla onay adımı eklemek de faydalı olur.

AppFunction entegrasyonunu doğrulama

AppFunctions'ı doğru şekilde entegre edip etmediğinizi doğrulamak için adb shell cmd app_function kullanabilirsiniz.

Uygulamanızın sağladığı AppFunctions'ın ayrıntılarını görmek için adb shell cmd app_function list-app-functions | grep --after-context 10 $myPackageName simgesini kullanın.

Ayrıca, AppFunction'ı açık tanımlayıcısını ("$enclosingClassName#$methodName") kullanarak doğrudan komut satırından da çalıştırabilirsiniz:

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'yi çalışırken görmek ve uçtan uca iş akışlarını herhangi bir isteme gerek kalmadan doğrulamak için cihazınıza AppFunctions testing agent Android uygulamasını yükleyip çalıştırın.

Entegrasyonunuzu Android Studio'daki Gemini gibi sohbet tabanlı asistanları kullanarak doğruluyorsanız AppFunctions geliştirme becerisini kullanın veya aşağıdaki gibi bir istem girin:

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.

Daha düşük API sürümlerinden taşıma

AppFunctions, 1.0.0-alpha10 sürümünde kitaplık bağımlılıklarını birleştiren ve eski yapılandırma sağlayıcıların (AppFunctionConfiguration.Provider) yerini alan bir derleme zamanı @AppFunctionServiceEntryPoint mimarisi sunar.

Uygulamanız şu anda AppFunctions'ın eski bir sürümünü (ör. 1.0.0-alpha09) kullanıyorsa Android Studio'daki Gemini gibi bir yapay zeka IDE'sinde AppFunctions agent skill'i kullanarak geçişinizi otomatikleştirebilirsiniz. Bu beceri, aracıyı derleme bağımlılıklarınızı birleştirmeye, gerekli @AppFunctionServiceEntryPoint hizmet sarmalayıcısını oluşturmaya, bağlam parametrelerini ayırmaya ve bildirim beyanlarınızı güncellemeye yönlendiren özel taşıma kuralları içerir.

Yapay zeka aracınızla otomatik taşıma başlatmak için aşağıdaki gibi bir istem kullanın:

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.