Android Oreo:如何将我的应用程序发布为自动填充服务提供商?

Bar*_*ica 3 passwords android autofill android-8.0-oreo

我是密码管理器应用程序的独立开发人员.我应该做什么,或者我应该实施什么(接口/ API /服务),使我的应用程序成为自动填充服务提供商(在Android Oreo API> = 26的设备中)?

我已经阅读了各种相关文档,但我无法理解如何做到这一点.我错过了什么吗?

目前我看到只有知名密码管理器才支持此功能:

提供自动填充服务的应用程序的图像

任何提示都是受欢迎的.

Cy *_*nol 9

像往常一样,Google自己的示例存储库为学习Autofill Framework的API 提供了一个良好的起点,并且涵盖了比我能够回答的更多的材料.以下是关键概念的概述.根据文档中的描述,我们希望创建一个自动填充服务,该服务将处理来自其他应用程序(客户端)的请求,以存储和检索自动填充字段数据.

首先,我们需要创建一个履行此合同的服务提供者类.我们可以扩展基AutofillService:

import android.service.autofill.AutofillService;
...
public class MyAutofillService extends AutofillService {
    ...
    @Override
    public void onFillRequest(FillRequest request, CancellationSignal cancellationSignal,
        FillCallback callback) { ... }

    @Override
    public void onSaveRequest(SaveRequest request, SaveCallback callback) { ... }
}
Run Code Online (Sandbox Code Playgroud)

服务onFillRequest()onSaveRequest()方法对我们的理解最重要.Android系统调用onFillRequest()以确定我们的服务是否可以为特定活动自动填充字段,并为方法a FillRequest提供包含我们的服务将检查可填充字段的上下文和视图信息.服务完成后,它会callback使用相应的自动填充数据调用提供的服务.

这里有一个显着的需要为一个提供自动填充建议的基本步骤简化概述FillRequest:

@Override
public void onFillRequest(FillRequest request, CancellationSignal signal, FillCallback callback) {
    List<FillContext> contexts = request.getFillContexts();
    AssistStructure structure = contexts.get(contexts.size() - 1);
    WindowNode windowNode = structure.getWindowNodeAt(0);
    ViewNode viewNode = windowNode.getRootViewNode(); // pretend this is an EditText

    String suggestionText = "This will appear in the autofill list for 'viewNode'.";
    RemoteViews suggestion = new RemoteViews(getPackageName(), R.layout.autofill_suggestion);
    suggestion.setTextViewText(R.id.autofill_suggestion, suggestionText);

    Dataset suggestionDataset = new Dataset.Builder(suggestion) 
        .setValue(viewNode.getAutoFillId(), AutofillValue.forText(suggestionText))
        .build();

    FillResponse response = new FillResponse.Builder() 
        .addDataset(suggestionDataset)
        .build();

    callback.onSuccess(response);
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到,Autofill API需要大量代码才能为View我们事先已经知道的提供单个静态自动填充建议- 该示例假定这viewNode是一个我们想要提供自动填充建议的文本输入字段.实际上,这个例子太简单了,但我想清楚地表明最小的实现.对于每一个WindowNode,我们需要通过根的视图树走ViewNode和它的每个孩子找到每一个我们的服务希望提供自动填充数据输入字段,然后创建一个RemoteViewsDataset一个包含每个字段的自动填充建议,我们将添加到FillResponse使用中FillResponse.Builder.addDataset().此示例未显示R.layout.autofill_suggestion TextView用于为a创建建议显示项的纯XML布局RemoteViews.

类似地,onSaveRequest()当用户想要将数据保存在活动的字段中以用于将来的完成请求并注入SaveRequest我们的服务用于查找要记住的自动填充数据时,Android会调用.

每种方法的具体实现将取决于我们的应用程序提供的自动填充数据的类型.自动填充服务必须认真检查每个字段的特征,并仔细选择一组适当的自动填充建议,以避免将用户的数据泄露给恶意客户端活动(请参阅注释).特别是对于密码管理器,我们需要特别注意正确地验证服务的用户,并在请求和保存自动填充数据时提供一组安全的建议.

我们现在可以注册服务<application>该项目的块AndroidManifest.xml中:

<service
    android:name=".MyAutofillService"
    android:label="Multi-Dataset Autofill Service"
    android:permission="android.permission.BIND_AUTOFILL_SERVICE">
    <meta-data
        android:name="android.autofill"
        android:resource="@xml/multidataset_service" />

    <intent-filter>
        <action android:name="android.service.autofill.AutofillService" />
    </intent-filter>
</service>
Run Code Online (Sandbox Code Playgroud)

如图所示,这会将我们的自动填充服务绑定为可用选项,该选项显示在问题中显示的自动填充服务列表中.该android:name属性必须与我们AutofillService类的名称匹配,我们的应用必须声明该BIND_AUTOFILL_SERVICE权限.将值更改android:label为服务的合适名称(例如,"使用Password Manager自动填充").或者,在字符串资源中设置它.另请注意,我们应该提供一个"设置"活动,用于配置我们在<meta?data>for中指定的服务android.autofill:

<autofill-service android:settingsActivity="foo.bar.SettingsActivity" />
Run Code Online (Sandbox Code Playgroud)

然后,用户可以通过其设备设置启用我们的自动填充服务.我们可以ACTION_REQUEST_SET_AUTOFILL_SERVICE在设置或首次启动期间广播意图,以帮助用户找到此屏幕.

  • 除了这里引用的内容之外,请记住它是*你的工作,而不是谷歌,[实施适当的安全](https://github.com/commonsguy/AutofillFollies/blob/master/WHITE_PAPER.md)(例如,不要将数据泄露给恶意活动). (3认同)
  • 引用@CommonsWare 的白皮书:**“自动填充将填充用户看不到的小部件......[或]......视图层次结构中根本不存在的小部件,而是由活动伪造的...... ."** - 这*应该*提醒任何构建自动填充服务的开发人员仔细考虑他们的服务如何选择何时提供用户数据。 (2认同)