1.构建表单界面
为 TextInputEditText
添加 android:importantForAutofill="yes"
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
"match_parent"
android:layout_height="wrap_content">
"@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username"
android:importantForAutofill="yes"/>
"match_parent"
android:layout_height="wrap_content">
"@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password"
android:importantForAutofill="yes"
android:selectAllOnFocus="false"
android:singleLine="true"/>
"@+id/login"
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Login"/>
复制代码
2.处理表单
使用SharedPreferences将用户信息储存
package com.iwakeup.learnandroid.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import com.google.android.material.button.MaterialButton;
import com.iwakeup.learnandroid.R;
import com.iwakeup.learnandroid.impl.BaseFragment;
import androidx.fragment.app.Fragment;
public class AutoFilFragment extends Fragment implements BaseFragment {
EditText username,password;
MaterialButton login;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_autofill,container,false);
initView(view);
return view;
}
@Override
public void initView(View view) {
username=view.findViewById(R.id.username);
password=view.findViewById(R.id.password);
login=view.findViewById(R.id.login);
login.setOnClickListener(loginC);
}
View.OnClickListener loginC =new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences sp=getActivity().getSharedPreferences("user",Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sp.edit();
editor.putString("username",username.getText().toString());
editor.putString("password",password.getText().toString());
editor.apply();
}
};
}
复制代码
3.构建AutoFillService
重写 onFillRequest()
和 onSaveRequest
public class MyAutoFillService extends AutofillService {
List viewNodeList;
@Override
public void onFillRequest(FillRequest fillRequest, CancellationSignal cancellationSignal, FillCallback fillCallback) {
List context = fillRequest.getFillContexts();
AssistStructure structure = context.get(context.size() - 1).getStructure();
viewNodeList = new ArrayList<>();
traverseStructure(structure,viewNodeList);
SharedPreferences sharedPreferences=getSharedPreferences("user",MODE_PRIVATE);
String spusername=sharedPreferences.getString("username",null);
String sppassword=sharedPreferences.getString("password",null);
//加载自动填充的布局,可更换为自定义View
RemoteViews usernamePresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
usernamePresentation.setTextViewText(android.R.id.text1, spusername);
RemoteViews passwordPresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
passwordPresentation.setTextViewText(android.R.id.text1, sppassword);
ParsedStructure parsedStructure=new ParsedStructure();
parsedStructure.setUsernameId(viewNodeList.get(0).getAutofillId());
parsedStructure.setPasswordId(viewNodeList.get(1).getAutofillId());
//构建填充的数据
FillResponse fillResponse = new FillResponse.Builder()
.addDataset(new Dataset.Builder()
.setValue(ParsedStructure.usernameId,
AutofillValue.forText(spusername), usernamePresentation)
.setValue(ParsedStructure.passwordId,
AutofillValue.forText(sppassword), passwordPresentation)
.build())
.build();
fillCallback.onSuccess(fillResponse);
}
@Override
public void onSaveRequest(SaveRequest saveRequest, SaveCallback saveCallback) {
// Get the structure from the request
List context = saveRequest.getFillContexts();
AssistStructure structure = context.get(context.size() - 1).getStructure();
// Traverse the structure looking for data to save
traverseStructure(structure, viewNodeList);
// Persist the data, if there are no errors, call onSuccess()
saveCallback.onSuccess();
}
public void traverseStructure(AssistStructure structure, List viewNodeList) {
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
AssistStructure.WindowNode windowNode = structure.getWindowNodeAt(i);
AssistStructure.ViewNode viewNode = windowNode.getRootViewNode();
traverseNode(viewNode,viewNodeList);
}
}
public void traverseNode(AssistStructure.ViewNode viewNode, List viewNodeList) {
if(viewNode.getAutofillHints() != null && viewNode.getAutofillHints().length > 0) {
// If the client app provides autofill hints, you can obtain them using:
// viewNode.getAutofillHints();
return;
} else {
// Or use your own heuristics to describe the contents of a view
// using methods such as getText() or getHint().
//遍历EditText布局
if (viewNode.getClassName().contains("EditText")) {
String viewId = viewNode.getIdEntry();
if (viewId != null && (viewId.contains("username") || viewId.contains("username") || viewId.contains("password"))) {
//添加到list
viewNodeList.add(viewNode);
return;
}
}
}
for(int i = 0; i < viewNode.getChildCount(); i++) {
AssistStructure.ViewNode childNode = viewNode.getChildAt(i);
traverseNode(childNode, viewNodeList);
}
}
static class ParsedStructure {
static AutofillId usernameId;
static AutofillId passwordId;
public AutofillId getPasswordId() {
return passwordId;
}
public void setPasswordId(AutofillId passwordId) {
ParsedStructure.passwordId = passwordId;
}
public AutofillId getUsernameId() {
return usernameId;
}
public void setUsernameId(AutofillId usernameId) {
this.usernameId = usernameId;
}
}
复制代码
4.清单声明和权限
".MyAutofillService"
android:label="My Autofill Service"
android:permission="android.permission.BIND_AUTOFILL_SERVICE">
"android.service.autofill.AutofillService" />
"android.autofill"
android:resource="@xml/service_configuration" />
复制代码
"http://schemas.android.com/apk/res/android"
android:settingsActivity="com.example.android.SettingsActivity" />复制代码
5.在设备上启用该服务
最后手机中设置一下:设置 > 系统 > 语言和输入 > 高级 > 输入帮助 > 自动填充服务>复制代码