इस गाइड में बताया गया है कि AppFunctions API को अपने Android ऐप्लिकेशन में कैसे इंटिग्रेट करें, किसी फ़ंक्शन के लिए लॉजिक कैसे लागू करें, और यह कैसे पुष्टि करें कि इंटिग्रेशन सही तरीके से काम कर रहा है.
वर्शन के साथ काम करने वाली सुविधाएं
इस सुविधा को लागू करने के लिए, यह ज़रूरी है कि आपका प्रोजेक्ट compileSdk एपीआई लेवल 36 या उसके बाद के वर्शन पर सेट हो.
आपके ऐप्लिकेशन को यह पुष्टि करने की ज़रूरत नहीं है कि AppFunctions काम करती हैं या नहीं. यह काम, AppFunctions Jetpack लाइब्रेरी में अपने-आप होता है.
अगर सुविधा काम करती है, तो AppFunctionManager एक इंस्टेंस दिखाता है. अगर सुविधा काम नहीं करती है, तो शून्य दिखाता है.
डिपेंडेंसी
अपने मॉड्यूल की 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 लॉजिक लागू करना
अपने Android ऐप्लिकेशन के लिए 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 को लागू करने की सुविधा, Android यूज़र इंटरफ़ेस (यूआई) थ्रेड में काम करती है.
इसलिए, ज़्यादा समय तक चलने वाली कार्रवाई को ये काम करने चाहिए:
- AppFunction को सस्पेंड फ़ंक्शन के तौर पर एलान करें.
- जब ऑपरेशन थ्रेड को ब्लॉक कर सकता हो, तब किसी सही कोरूटीन डिस्पैचर पर स्विच करें.
- जब
isDescribedByKDocकोtrueपर सेट किया जाता है, तो फ़ंक्शन के ब्यौरे या सीरियलाइज़ किए जा सकने वाले ब्यौरे कोAppFunctionMetadataके हिस्से के तौर पर कोड में बदला जाता है. इससे एजेंट को यह समझने में मदद मिलती है कि ऐप्लिकेशन के AppFunction का इस्तेमाल कैसे किया जाए.
मेनिफ़ेस्ट में AppFunction सेवा का एलान करना
KSP से जनरेट किए गए सेवा के एलान और app_metadata प्रॉपर्टी को अपने मॉड्यूल मेनिफ़ेस्ट में रजिस्टर करें. उदाहरण के लिए, src/main/AndroidManifest.xml में.
KSP कंपाइलर, आपकी ऐब्स्ट्रैक्ट एंट्री पॉइंट क्लास को बढ़ाने वाली कॉन्क्रीट सर्विस क्लास (TaskAppFunctionService) जनरेट करता है. साथ ही, आपकी 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 की उपलब्धता को टॉगल करें
AppFunctions को गेट करते समय, फ़ंक्शन को साफ़ तौर पर चालू या बंद करने के लिए, AppFunctionManager API का इस्तेमाल करें. गेटिंग की सुविधा तब काम आ सकती है, जब आपके ऐप्लिकेशन की कुछ सुविधाएं सभी उपयोगकर्ताओं के लिए उपलब्ध न हों. AppFunctions को डाइनैमिक तरीके से चालू या बंद करने पर, इंटेलिजेंस सिस्टम को यह पता चलता है कि आपके उपयोगकर्ता के लिए कौनसी सुविधाएं उपलब्ध हैं.
ऐसी AppFunctions को सुरक्षित तरीके से गेट करने के लिए जिनमें खाते की खास स्थिति की ज़रूरत होती है, यह दो चरणों वाली प्रोसेस अपनाएं:
पहला चरण. फ़ंक्शन को डिफ़ॉल्ट रूप से बंद करें
अगर आपको यह फ़ंक्शन, फ़ीचर फ़्लैग की पुष्टि होने से पहले ऐक्सेस होने से रोकना है, तो अपने @AppFunction एनोटेशन के isEnabled पैरामीटर को false पर सेट करें.
@AppFunction(isEnabled = false, isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = TODO()
दूसरा चरण. डाइनैमिक तौर पर रनटाइम पर फ़ंक्शन चालू करना
हर AppFunction क्लास के लिए, कंपाइलर एक मिलती-जुलती क्लास जनरेट करता है. इसमें फ़ंक्शन आईडी कॉन्स्टेंट होते हैं. ये कॉन्स्टेंट, Ids सफ़िक्स का इस्तेमाल करते हैं. इन जनरेट किए गए आईडी कॉन्स्टेंट का इस्तेमाल, AppFunctionManagerCompat से setAppFunctionEnabled तरीके के साथ किया जा सकता है. इससे रनटाइम के दौरान, किसी फ़ंक्शन की चालू स्थिति को बदला जा सकता है.
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 के तौर पर उपलब्ध कराना है, यह चुनते समय ध्यान रखें कि सिस्टम एजेंट, उपयोगकर्ता की क्वेरी को सर्वर पर प्रोसेस कर सकते हैं. ऐसा वे एलएलएम की बेहतर सुविधाओं का फ़ायदा पाने के लिए करते हैं.
लोगों को बेहतरीन अनुभव देने के लिए, हम इन दिशा-निर्देशों का पालन करने का सुझाव देते हैं. इससे संवेदनशील जानकारी को भी सुरक्षित रखा जा सकेगा:
- नैचुरल लैंग्वेज से फ़ायदा पाने वाली सुविधाएं: ऐसे टास्क उपलब्ध कराएं जिन्हें उपयोगकर्ता, मैन्युअल यूज़र इंटरफ़ेस (यूआई) नेविगेशन के बजाय बातचीत में आसानी से पूरा कर सकें.
- सीमित ऐक्सेस: ऐसी AppFunctions बनाएं जो एजेंट को सिर्फ़ उस डेटा और उन कार्रवाइयों का ऐक्सेस दें जिनकी ज़रूरत उपयोगकर्ता के अनुरोध को पूरा करने के लिए होती है.
- संवेदनशील जानकारी नहीं: सिर्फ़ ऐसा डेटा शेयर करें जो बहुत निजी या गोपनीय न हो. इसके अलावा, ऐसा डेटा शेयर करें जिसे शेयर करने की अनुमति उपयोगकर्ता ने साफ़ तौर पर दी हो.
- डेटा मिटाने जैसी कार्रवाइयों के लिए, साफ़ तौर पर पुष्टि करना: डेटा मिटाने जैसी कार्रवाइयां करने वाले फ़ंक्शन का इस्तेमाल करते समय, बहुत ज़्यादा सावधानी बरतें. हालांकि, एजेंट इन्हें लागू कर सकता है, लेकिन आपके ऐप्लिकेशन में पुष्टि करने का अपना चरण शामिल होना चाहिए. साथ ही, इसमें साफ़ तौर पर बताया जाना चाहिए कि ऐसा क्यों किया जा रहा है. पुष्टि करने के लिए एक से ज़्यादा चरण जोड़ने से भी मदद मिलती है. इससे यह पक्का किया जा सकता है कि उपयोगकर्ता को पता है कि उससे क्या करने के लिए कहा जा रहा है.
AppFunction इंटिग्रेशन की पुष्टि करना
यह पुष्टि करने के लिए कि आपने AppFunctions को सही तरीके से इंटिग्रेट किया है, adb
shell cmd app_function का इस्तेमाल किया जा सकता है.
आपके ऐप्लिकेशन में उपलब्ध AppFunctions की जानकारी देखने के लिए, 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 टेस्टिंग एजेंट Android ऐप्लिकेशन इंस्टॉल करें और उसे चलाएं.
अगर आपको चैट पर आधारित असिस्टेंट, जैसे कि Android Studio में 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.
एपीआई के पुराने वर्शन से माइग्रेट करना
AppFunctions के वर्शन 1.0.0-alpha10 में, कंपाइल-टाइम @AppFunctionServiceEntryPoint आर्किटेक्चर पेश किया गया है. यह आर्किटेक्चर, लाइब्रेरी की डिपेंडेंसी को एक साथ जोड़ता है और लेगसी कॉन्फ़िगरेशन प्रोवाइडर (AppFunctionConfiguration.Provider) को बदलता है.
अगर आपका ऐप्लिकेशन फ़िलहाल AppFunctions के पुराने वर्शन (जैसे कि 1.0.0-alpha09) का इस्तेमाल करता है, तो माइग्रेशन की प्रोसेस को अपने-आप पूरा होने के लिए सेट किया जा सकता है. इसके लिए, Android Studio में Gemini जैसे एआई आईडीई में AppFunctions एजेंट की स्किल का इस्तेमाल करें. इस स्किल में माइग्रेशन के खास नियम शामिल हैं. ये नियम, एजेंट को आपकी बिल्ड डिपेंडेंसी को एक साथ रखने, ज़रूरी @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.