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 çalıştığını nasıl doğrulayacağınız açıklanmaktadır.

Sürüm uyumluluğu

Bu uygulama, projenizin compileSdk değerinin API düzeyi 37 veya sonraki sürümlere ayarlanmasını gerektirir. Projenizde Android Gradle eklentisi 9.1.0 veya sonraki bir sürüm kullanılmalıdır.

Uygulamanızın, AppFunctions'ın desteklenip desteklenmediğini doğrulaması gerekmez. Bu işlem, AppFunctions Jetpack kitaplığında otomatik olarak gerçekleştirilir. AppFunctionManager, özellik destekleniyorsa bir örnek, desteklenmiyorsa null değerini 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-beta01")
  // 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-beta01")
}

AppFunctions mantığını uygulama

Android uygulamanız için bir AppFunction uygulamak istiyorsanız belirli AppFunctions mantığını uygulayan bir sınıf oluşturun. Bu işlem, parametreler ve yanıtlar için serileştirilebilir veri sınıfları oluşturmayı ve ardından işlev yönteminde temel mantığı sağlamayı içerir.

Aşağıdaki kodda, TODO uygulamasında görev oluşturmaya yönelik örnek bir uygulama gösterilmektedir. Bu uygulamada, özel parametrelerin ve yanıt türlerinin tanımlanması ile bir depo kullanan ana işlev mantığı yer alır.

@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.
     */
    @AppFunctionDeclaration(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 şunları yapmalıdır:
    • AppFunction'ı askıya alma işlevi olarak tanımlayın.
    • İşlem, iş parçacığını engelleyebileceğinde uygun bir eş yordam dağıtıcısına geçin.
  • isDescribedByKDoc, true olarak ayarlandığında işlev açıklaması veya serileştirilebilir açıklama, temsilcinin uygulamanın AppFunction'ını nasıl kullanacağını anlamasına yardımcı olmak için AppFunctionMetadata kapsamında kodlanır. 1.0.0-beta01 sürümünden itibaren isDescribedByKDoc için varsayılan değer yoktur. Bu nedenle, değeri açıkça ayarlayın.

Manifest'inizde AppFunction hizmetini bildirme

KSP tarafından oluşturulan hizmet beyanını ve app_metadata özelliğini modül manifest'inize (ör. src/main/AndroidManifest.xml) kaydedin. KSP derleyicisi, soyut giriş noktası sınıfınızı genişleten somut hizmet sınıfını (TaskAppFunctionService) 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 açma/kapatma

AppFunctions'ı geçitlerken 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ılar tarafından kullanılamıyorsa geçitler faydalı olabilir. AppFunctions'ı dinamik olarak etkinleştirip devre dışı bırakarak akıllı sistem, kullanıcınızın her an hangi özellikleri kullanabileceğini tam olarak bilir.

Belirli bir hesap durumu gerektiren AppFunctions'ı güvenli bir şekilde kontrol etmek için iki adımlı bir işlem uygulayın:

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

Özellik bayrağınız doğrulanmadan önce işleve erişilmesini önlemek için @AppFunctionDeclaration ek açıklamanızın isEnabled parametresini false olarak ayarlayın.

@AppFunctionDeclaration(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 @AppFunctionServiceEntryPoint sınıfı için işlev kimliği sabitlerini içeren karşılık gelen bir sınıf oluşturur (Ids son ekini kullanarak). Bir işlevin etkin durumunu çalışma zamanında değiştirmek için bu oluşturulan kimlik sabitlerini AppFunctionManager'teki 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 gereken noktalar

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

Hassas bilgilerin açığa çıkmasını önleyen 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ü gezinmesi yerine sohbet yoluyla ifade etmesi daha kolay olan görevleri kullanılabilir hale getirin.
  • Erişimi daraltın: Temsilciye yalnızca kullanıcının belirli isteğini yerine getirmek için gereken verilere ve işlemlere erişim izni veren AppFunction'lar oluşturun.
  • Hassas olmayan bilgiler: Yalnızca son derece kişisel veya gizli olmayan verileri ya da kullanıcının işlem bağlamında paylaşılmasına açıkça izin verdiği verileri paylaşın.
  • Zarar verici işlemler için net onay: Zarar verici işlemler (ör. veri silme) gerçekleştiren işlevlerde son derece dikkatli olun. Asistan bu işlemleri çağırabilir ancak uygulamanızın kendi onay adımını içermesi ve niyetlerle ilgili net, anlaşılır bir dil kullanması gerekir. Kullanıcının kendisinden ne istendiğinin gerçekten farkında olduğundan emin olmak için birden fazla onay adımı eklemek de yararlıdır.

AppFunction entegrasyonunu doğrulama

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

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

Ayrıca, açık tanımlayıcısını ("$enclosingClassName#$methodName") kullanarak bir AppFunction'ı 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 deneyimlemek ve herhangi bir isteme gerek kalmadan uçtan uca iş akışlarını doğrulamak için cihazınıza AppFunctions test aracısı Android uygulamasını yükleyip çalıştırın.

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

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.
Use the AppFunction descriptions to choose functions and parameters.

Daha eski API sürümlerinden geçiş yapma

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 sundu. 1.0.0-alpha12 sürümünde eski sağlayıcılar kaldırıldı. 1.0.0-alpha13 sürümünde @AppFunction ek açıklaması @AppFunctionDeclaration olarak, 1.0.0-beta01 sürümünde ise uygulama meta veri XML dosyanızdaki appfn:description özelliği appfn:instructions olarak yeniden adlandırıldı.

Uygulamanız AppFunctions'ın önceki bir sürümünü (ör. 1.0.0-alpha09 veya 1.0.0-alpha10) kullanıyorsa Android Studio'da Gemini gibi bir yapay zeka IDE'sinde AppFunctions temsilci becerisini kullanarak taşıma işleminizi otomatikleştirebilirsiniz. Bu beceri, derleme bağımlılıklarınızı birleştirmek, gerekli @AppFunctionServiceEntryPoint hizmet sarmalayıcısını oluşturmak, bağlam parametrelerini ayırmak, manifest beyanlarınızı güncellemek ve 1.0.0-beta01 yeniden adlandırmalarını uygulamak için bir temsilciye rehberlik eden özel taşıma kuralları içerir.