11package com.mikhailgrigorev.quickpass
22
3+ import android.annotation.SuppressLint
34import android.app.assist.AssistStructure.ViewNode
5+ import android.content.Context
6+ import android.database.Cursor
7+ import android.database.SQLException
48import android.os.Build
59import android.os.CancellationSignal
610import android.service.autofill.*
7- import android.view.autofill.AutofillId
811import android.view.autofill.AutofillValue
912import android.widget.RemoteViews
13+ import android.widget.Toast
1014import androidx.annotation.RequiresApi
15+ import java.util.*
16+ import kotlin.collections.ArrayList
1117
1218@RequiresApi(Build .VERSION_CODES .O )
1319class MyAutofillService : AutofillService () {
1420
21+ private val _preferenceFile = " quickPassPreference"
22+ private val _keyUsername = " prefUserNameKey"
23+
24+ @SuppressLint(" Recycle" )
1525 override fun onFillRequest (
1626 request : FillRequest ,
1727 cancellationSignal : CancellationSignal , callback : FillCallback
@@ -20,34 +30,110 @@ class MyAutofillService : AutofillService() {
2030 request.fillContexts[request.fillContexts.size - 1 ].structure
2131 // Создаем пустой список
2232 val emailFields: MutableList <ViewNode ?> = ArrayList ()
33+ val passFields: MutableList <ViewNode ?> = ArrayList ()
2334 val appName = structure.activityComponent.packageName
2435
36+ // Checking prefs
37+ val sharedPref = getSharedPreferences(_preferenceFile , Context .MODE_PRIVATE )
38+ val username = sharedPref.getString(_keyUsername , " none" )
39+
40+ // Arrays
41+ val emails: ArrayList <String > = ArrayList ()
42+ val passwords: ArrayList <String > = ArrayList ()
43+ val names: ArrayList <String > = ArrayList ()
44+
45+ if ((username != null )&& (username != " none" )) {
46+
47+ val pdbHelper = PasswordsDataBaseHelper (this , username)
48+ val pDatabase = pdbHelper.writableDatabase
49+ try {
50+ val pCursor: Cursor = pDatabase.query(
51+ pdbHelper.TABLE_USERS , arrayOf(
52+ pdbHelper.KEY_NAME ,
53+ pdbHelper.KEY_PASS ,
54+ pdbHelper.KEY_LOGIN
55+ ),
56+ null , null ,
57+ null , null , null
58+ )
59+
60+ if (pCursor.moveToFirst()) {
61+ val nameIndex: Int = pCursor.getColumnIndex(pdbHelper.KEY_NAME )
62+ val passIndex: Int = pCursor.getColumnIndex(pdbHelper.KEY_PASS )
63+ val loginIndex: Int = pCursor.getColumnIndex(pdbHelper.KEY_LOGIN )
64+ do {
65+ val email = pCursor.getString(loginIndex).toString()
66+ val password = pCursor.getString(passIndex).toString()
67+ val name = pCursor.getString(nameIndex).toString()
68+ if (email != " " )
69+ emails.add(email)
70+ else
71+ emails.add(username)
72+ names.add(name)
73+ passwords.add(password)
74+ } while (pCursor.moveToNext())
75+ }
76+ } catch (e: SQLException ) {
77+ }
78+ }
79+
2580 // Заполняем список
2681 identifyEmailFields(structure.getWindowNodeAt(0 ).rootViewNode, emailFields)
27- if (emailFields.isEmpty()) return
28- val rvPrimaryEmail = RemoteViews (packageName, R .layout.email_suggestion)
29- val rvSecondaryEmail = RemoteViews (packageName, R .layout.email_suggestion)
30-
31- val primaryEmail = " QuickPass 1"
32- val secondaryEmail = " QuickPass 2"
33-
34- // Обновляет TextView
35- rvPrimaryEmail.setTextViewText(R .id.email_suggestion_item, primaryEmail)
36- rvSecondaryEmail.setTextViewText(R .id.email_suggestion_item, secondaryEmail)
37-
38- val emailField = emailFields[0 ]
39- val primaryEmailDataSet = Dataset .Builder (rvPrimaryEmail).setValue(
40- emailField?.autofillId!! ,
41- AutofillValue .forText(primaryEmail)
42- ).build()
43- val secondaryEmailDataSet = Dataset .Builder (rvSecondaryEmail).setValue(
44- emailField.autofillId!! ,
45- AutofillValue .forText(secondaryEmail)
46- ).build()
47- val response = FillResponse .Builder ().addDataset(primaryEmailDataSet)
48- .addDataset(secondaryEmailDataSet)
49- .build()
50- callback.onSuccess(response)
82+ identifyPassFields(structure.getWindowNodeAt(0 ).rootViewNode, passFields)
83+
84+ val dataSets: ArrayList <Dataset > = ArrayList ()
85+
86+ if (emailFields.isNotEmpty()){
87+
88+ var i = 0
89+
90+ for (mail in emails){
91+ if ((mail.contains(" @" )) or (names[i].toLowerCase(Locale .ROOT ).contains(appName.toLowerCase(
92+ Locale .ROOT
93+ )
94+ )) or (appName.toLowerCase(Locale .ROOT ).contains(names[i].toLowerCase(Locale .ROOT )))
95+ ) {
96+ val remoteView = RemoteViews (packageName, R .layout.autofill_suggestion)
97+ remoteView.setTextViewText(R .id.suggestion_item, mail)
98+ dataSets.add(
99+ Dataset .Builder (remoteView).setValue(
100+ emailFields[0 ]?.autofillId!! ,
101+ AutofillValue .forText(mail)
102+ ).build()
103+ )
104+ }
105+ i + = 1
106+ }
107+ }
108+ if (passFields.isNotEmpty()){
109+
110+ var i = 0
111+
112+ val remoteView = RemoteViews (packageName, R .layout.autofill_suggestion)
113+ remoteView.setTextViewText(R .id.suggestion_item, " Random" )
114+ for (name in names){
115+ if ((name.toLowerCase(Locale .ROOT ).contains(appName.toLowerCase(Locale .ROOT ))) or
116+ (appName.toLowerCase(Locale .ROOT ).contains(name.toLowerCase(Locale .ROOT )))){
117+ val remoteView = RemoteViews (packageName, R .layout.autofill_suggestion)
118+ remoteView.setTextViewText(R .id.suggestion_item, passwords[i])
119+ dataSets.add(Dataset .Builder (remoteView).setValue(
120+ passFields[0 ]?.autofillId!! ,
121+ AutofillValue .forText(passwords[i])
122+ ).build())
123+ }
124+ i + = 1
125+ }
126+ }
127+
128+ if (dataSets.size != 0 ){
129+ val response = FillResponse .Builder ()
130+ for (data in dataSets){
131+ response.addDataset(data)
132+ }
133+ val responseBuilder = response.build()
134+ callback.onSuccess(responseBuilder)
135+ }
136+
51137 }
52138
53139 private fun identifyEmailFields (
@@ -56,7 +142,10 @@ class MyAutofillService : AutofillService() {
56142 ) {
57143 if (node.className != null && node.className.contains(" EditText" )) {
58144 val viewId = node.idEntry
59- if (viewId != null && (viewId.contains(" email" ) || viewId.contains(" username" ))) {
145+ if (viewId != null && (viewId.contains(" email" ) ||
146+ viewId.contains(" username" ) ||
147+ viewId.contains(" name" ) ||
148+ viewId.contains(" mail" ))) {
60149 emailFields.add(node)
61150 return
62151 }
@@ -65,57 +154,31 @@ class MyAutofillService : AutofillService() {
65154 identifyEmailFields(node.getChildAt(i), emailFields)
66155 }
67156 }
68- /*
69- override fun onFillRequest(
70- request: FillRequest,
71- cancellationSignal: CancellationSignal,
72- callback: FillCallback
157+
158+ private fun identifyPassFields (
159+ node : ViewNode ,
160+ passFields : MutableList <ViewNode ?>
73161 ) {
74- // Get the structure from the request
75- val context: List<FillContext> = request.fillContexts
76- val structure: AssistStructure = context[context.size - 1].structure
77-
78- // Traverse the structure looking for nodes to fill out.
79- //val parsedStructure: ParsedStructure = parseStructure(structure)
80-
81- // Fetch user data that matches the fields.
82- //val (username: String, password: String) = fetchUserData(parsedStructure)
83-
84- val (username: String, password: String) = UserData("a", "b")
85-
86- // Build the presentation of the datasets
87- val usernamePresentation = RemoteViews(packageName, android.R.layout.simple_list_item_1)
88- usernamePresentation.setTextViewText(android.R.id.text1, "my_username")
89- val passwordPresentation = RemoteViews(packageName, R.layout.simple_list_item_1)
90- passwordPresentation.setTextViewText(android.R.id.text1, "Password for my_username")
91-
92- // Add a dataset to the response
93- val fillResponse: FillResponse = FillResponse.Builder()
94- .addDataset(Dataset.Builder()
95- .setValue(
96- //parsedStructure.usernameId,
97- AutofillValue.forText(username),
98- usernamePresentation
99- )
100- .setValue(
101- //parsedStructure.passwordId,
102- AutofillValue.forText(password),
103- passwordPresentation
104- )
105- .build())
106- .build()
107-
108- // If there are no errors, call onSuccess() and pass the response
109- callback.onSuccess(fillResponse)
110- }*/
162+ if (node.className != null && node.className.contains(" EditText" )) {
163+ val viewId = node.idEntry
164+ if (viewId != null && (viewId.contains(" password" ) ||
165+ viewId.contains(" pass" ) ||
166+ viewId.contains(" pin" ) ||
167+ viewId.contains(" code" ) ||
168+ viewId.contains(" secure" ))) {
169+ passFields.add(node)
170+ return
171+ }
172+ }
173+ for (i in 0 until node.childCount) {
174+ identifyPassFields(node.getChildAt(i), passFields)
175+ }
176+ }
111177
112178 override fun onSaveRequest (request : SaveRequest , callback : SaveCallback ) {
113-
114179 }
115180
116- data class ParsedStructure (var usernameId : AutofillId , var passwordId : AutofillId )
117-
118- data class UserData (var username : String , var password : String )
119-
181+ private fun toast (message : String )=
182+ Toast .makeText(this ,message, Toast .LENGTH_SHORT ).show()
120183
121184}
0 commit comments