| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 | package com.fastest.pass.autofillimport android.app.assist.AssistStructureimport android.service.autofill.AutofillServiceimport android.service.autofill.Datasetimport android.service.autofill.FillCallbackimport android.service.autofill.FillContextimport android.service.autofill.FillRequestimport android.service.autofill.FillResponseimport android.view.autofill.AutofillIdimport android.view.autofill.AutofillValueimport android.widget.RemoteViewsimport com.fastest.pass.home.domain.model.AddPasswordimport com.fastest.pass.sharedpref.CredentialManagerclass FastestPassAutofillService : AutofillService() {    override fun onFillRequest(        request: FillRequest,        cancellationSignal: android.os.CancellationSignal,        callback: FillCallback    ) {        // Extract structure        val context: List<FillContext> = request.fillContexts        val structure: AssistStructure = context.last().structure        val packageName = getRequestingPackageName(structure)        if (packageName == null) {            callback.onFailure("Unable to determine requesting package")            return        }        // Fetch credentials matching the package name or domain       /* val data = getCredentials().filter {            it.url.contains(packageName)        }*/        val data = getCredentials()        if (data.isEmpty()) {            callback.onFailure("No matching credentials found")            return        }        val fillResponseBuilder = FillResponse.Builder()        for (i in 0 until structure.windowNodeCount) {            val windowNode = structure.getWindowNodeAt(i)            val viewNode = windowNode.rootViewNode         parseViewNode(viewNode, data, fillResponseBuilder)        }    callback.onSuccess(fillResponseBuilder.build())    }    override fun onSaveRequest(        request: android.service.autofill.SaveRequest,        callback: android.service.autofill.SaveCallback    ) {      /*  val credentialManager = CredentialManager(applicationContext)        // Extracting the FillContexts from the SaveRequest        val fillContexts = request.fillContexts        // For each field in the SaveRequest, extract the autofill values (email and password)        val credentials = mutableListOf<AddPassword>()        for (context in fillContexts) {            val structure = context.structure            // Loop through the views in the structure and extract the autofill values            for (i in 0 until structure.windowNodeCount) {                val windowNode = structure.getWindowNodeAt(i)                val rootNode = windowNode.rootViewNode                // Extract the values from the autofill fields                val title = extractAutofillValue(rootNode, "personFirstName") ?: ""                val url = extractAutofillValue(rootNode, "personLastName") ?: ""                val username = extractAutofillValue(rootNode, "username") ?: ""                val password = extractAutofillValue(rootNode, "password") ?: ""                val notes = extractAutofillValue(rootNode, "addressStreet") ?: ""                // Create a new Credential object and add it to the list                val credential = AddPassword(title, url, username, password, notes)                credentials.add(credential)            }        }        // Save the credentials in SharedPreferences        credentialManager.saveCredentials(credentials)*/        callback.onSuccess()    }    private fun extractAutofillValue(node: AssistStructure.ViewNode, hint: String): String? {        val autofillHints = node.autofillHints        // Check if the hint matches the autofill field (e.g., "emailAddress" or "password")        if (autofillHints != null && autofillHints.contains(hint)) {            val value = node.autofillValue            return if (value != null && value.isText) value.textValue.toString() else null        }        // Recursively check child nodes if no value is found        for (i in 0 until node.childCount) {            val childNode = node.getChildAt(i)            val result = extractAutofillValue(childNode, hint)            if (result != null) return result        }        return null    }    private fun getCredentials(): List<AddPassword> {        val credentialManager = CredentialManager(applicationContext)        return credentialManager.getCredentials()    }    private fun parseViewNode(        node: AssistStructure.ViewNode,        credentials: List<AddPassword>,        fillResponseBuilder: FillResponse.Builder    )  {        val autofillHints = node.autofillHints        if (autofillHints != null) {            // Collect Autofill IDs for username and password fields            val emailAddress: AutofillId? =                if ("emailAddress" in autofillHints) node.autofillId else null            val username: AutofillId? =                if ("username" in autofillHints) node.autofillId else null            val passwordId: AutofillId? = if ("password" in autofillHints) node.autofillId else null            if (username != null || emailAddress != null || passwordId != null) {                credentials.forEach { credential ->                    val presentation =                        RemoteViews(packageName, android.R.layout.simple_list_item_1).apply {                            setTextViewText(                                android.R.id.text1,                                "${credential.username} @ ${credential.url}"                            )                        }                    val datasetBuilder = Dataset.Builder()                    emailAddress?.let {                        datasetBuilder.setValue(                            it,                            AutofillValue.forText(credential.username),                            presentation                        )                    }                    passwordId?.let {                        datasetBuilder.setValue(                            it,                            AutofillValue.forText(credential.password),                            presentation                        )                    }                    username?.let {                        datasetBuilder.setValue(                            it,                            AutofillValue.forText(credential.username),                            presentation                        )                    }                    fillResponseBuilder.addDataset(datasetBuilder.build())                }            }        }        // Recursively parse child nodes        for (i in 0 until node.childCount) {           parseViewNode(node.getChildAt(i), credentials, fillResponseBuilder)        }    }    private fun getRequestingPackageName(structure: AssistStructure): String? {        return structure.activityComponent?.packageName    }}
 |