下面列出了android.util.MutableInt#android.app.assist.AssistStructure 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void parseAutofillFields(AssistStructure.ViewNode viewNode,
HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint,
Map<String, FilledAutofillField> filledAutofillFieldsByTypeName,
Dataset.Builder builder, MutableBoolean setValueAtLeastOnce) {
String[] rawHints = viewNode.getAutofillHints();
if (rawHints == null || rawHints.length == 0) {
logv("No af hints at ViewNode - %s", viewNode.getIdEntry());
return;
}
String fieldTypeName = AutofillHints.getFieldTypeNameFromAutofillHints(
fieldTypesByAutofillHint, Arrays.asList(rawHints));
if (fieldTypeName == null) {
return;
}
FilledAutofillField field = filledAutofillFieldsByTypeName.get(fieldTypeName);
if (field == null) {
return;
}
bindValueToNode(viewNode, field, builder, setValueAtLeastOnce);
}
private void parseNode(AssistStructure.ViewNode root, List<String> allHints,
MutableInt autofillSaveType, List<AutofillId> autofillIds,
List<AutofillId> focusedAutofillIds) {
String[] hints = root.getAutofillHints();
if (hints != null) {
for (String hint : hints) {
FieldTypeWithHeuristics fieldTypeWithHints = mFieldTypesByAutofillHint.get(hint);
if (fieldTypeWithHints != null && fieldTypeWithHints.fieldType != null) {
allHints.add(hint);
autofillSaveType.value |= fieldTypeWithHints.fieldType.getSaveInfo();
autofillIds.add(root.getAutofillId());
}
}
}
if (root.isFocused()) {
focusedAutofillIds.add(root.getAutofillId());
}
}
private void parseAutofillFields(AssistStructure.ViewNode viewNode,
HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint,
Map<String, FilledAutofillField> filledAutofillFieldsByTypeName,
Dataset.Builder builder, MutableBoolean setValueAtLeastOnce) {
String[] rawHints = viewNode.getAutofillHints();
if (rawHints == null || rawHints.length == 0) {
logv("No af hints at ViewNode - %s", viewNode.getIdEntry());
return;
}
String fieldTypeName = AutofillHints.getFieldTypeNameFromAutofillHints(
fieldTypesByAutofillHint, Arrays.asList(rawHints));
if (fieldTypeName == null) {
return;
}
FilledAutofillField field = filledAutofillFieldsByTypeName.get(fieldTypeName);
if (field == null) {
return;
}
bindValueToNode(viewNode, field, builder, setValueAtLeastOnce);
}
private void parseNode(AssistStructure.ViewNode root, List<String> allHints,
MutableInt autofillSaveType, List<AutofillId> autofillIds,
List<AutofillId> focusedAutofillIds) {
String[] hints = root.getAutofillHints();
if (hints != null) {
for (String hint : hints) {
FieldTypeWithHeuristics fieldTypeWithHints = mFieldTypesByAutofillHint.get(hint);
if (fieldTypeWithHints != null && fieldTypeWithHints.fieldType != null) {
allHints.add(hint);
autofillSaveType.value |= fieldTypeWithHints.fieldType.getSaveInfo();
autofillIds.add(root.getAutofillId());
}
}
}
if (root.isFocused()) {
focusedAutofillIds.add(root.getAutofillId());
}
}
private void parseAutofillFields(AssistStructure.ViewNode viewNode,
DatasetWithFilledAutofillFields datasetWithFilledAutofillFields, int partition) {
String[] hints = viewNode.getAutofillHints();
if (hints == null || hints.length == 0) {
return;
}
AutofillValue autofillValue = viewNode.getAutofillValue();
String textValue = null;
Long dateValue = null;
Boolean toggleValue = null;
CharSequence[] autofillOptions = null;
Integer listIndex = null;
if (autofillValue != null) {
if (autofillValue.isText()) {
// Using toString of AutofillValue.getTextValue in order to save it to
// SharedPreferences.
textValue = autofillValue.getTextValue().toString();
} else if (autofillValue.isDate()) {
dateValue = autofillValue.getDateValue();
} else if (autofillValue.isList()) {
autofillOptions = viewNode.getAutofillOptions();
listIndex = autofillValue.getListValue();
} else if (autofillValue.isToggle()) {
toggleValue = autofillValue.getToggleValue();
}
}
appendViewMetadata(datasetWithFilledAutofillFields,
hints, partition, textValue, dateValue, toggleValue,
autofillOptions, listIndex);
}
private void parseWebDomain(AssistStructure.ViewNode viewNode, StringBuilder validWebDomain) {
String webDomain = viewNode.getWebDomain();
if (webDomain != null) {
logd("child web domain: %s", webDomain);
if (validWebDomain.length() > 0) {
if (!webDomain.equals(validWebDomain.toString())) {
throw new SecurityException("Found multiple web domains: valid= "
+ validWebDomain + ", child=" + webDomain);
}
} else {
validWebDomain.append(webDomain);
}
}
}
private void onSuccess() {
Intent intent = getIntent();
boolean forResponse = intent.getBooleanExtra(EXTRA_FOR_RESPONSE, true);
AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
ClientParser clientParser = new ClientParser(structure);
mReplyIntent = new Intent();
mLocalAutofillDataSource.getFieldTypeByAutofillHints(
new DataCallback<HashMap<String, FieldTypeWithHeuristics>>() {
@Override
public void onLoaded(HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
ClientViewMetadataBuilder builder = new ClientViewMetadataBuilder(clientParser,
fieldTypesByAutofillHint);
mClientViewMetadata = builder.buildClientViewMetadata();
mDatasetAdapter = new DatasetAdapter(clientParser);
mResponseAdapter = new ResponseAdapter(AuthActivity.this,
mClientViewMetadata, mPackageName, mDatasetAdapter);
if (forResponse) {
fetchAllDatasetsAndSetIntent(fieldTypesByAutofillHint);
} else {
String datasetName = intent.getStringExtra(EXTRA_DATASET_NAME);
fetchDatasetAndSetIntent(fieldTypesByAutofillHint, datasetName);
}
}
@Override
public void onDataNotAvailable(String msg, Object... params) {
}
});
}
/**
* Traverses through the {@link AssistStructure} and does something at each {@link ViewNode}.
*
* @param processor contains action to be performed on each {@link ViewNode}.
*/
public void parse(NodeProcessor processor) {
for (AssistStructure structure : mStructures) {
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
AssistStructure.ViewNode viewNode = structure.getWindowNodeAt(i).getRootViewNode();
traverseRoot(viewNode, processor);
}
}
}
private void traverseRoot(AssistStructure.ViewNode viewNode, NodeProcessor processor) {
processor.processNode(viewNode);
int childrenSize = viewNode.getChildCount();
if (childrenSize > 0) {
for (int i = 0; i < childrenSize; i++) {
traverseRoot(viewNode.getChildAt(i), processor);
}
}
}
@NonNull
private ArrayMap<String, AutofillId> getAutofillableFields(@NonNull AssistStructure structure) {
ArrayMap<String, AutofillId> fields = new ArrayMap<>();
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
ViewNode node = structure.getWindowNodeAt(i).getRootViewNode();
addAutofillableFields(fields, node);
}
return fields;
}
/**
* Parses the {@link AssistStructure} representing the activity being autofilled, and returns a
* map of autofillable fields (represented by their autofill ids) mapped by the hint associate
* with them.
*
* <p>An autofillable field is a {@link ViewNode} whose {@link #getHint(ViewNode)} metho
*/
@NonNull
private Map<String, AutofillId> getAutofillableFields(@NonNull AssistStructure structure) {
Map<String, AutofillId> fields = new ArrayMap<>();
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
ViewNode node = structure.getWindowNodeAt(i).getRootViewNode();
addAutofillableFields(fields, node);
}
return fields;
}
/**
* Parses the {@link AssistStructure} representing the activity being autofilled, and returns a
* map of autofillable fields (represented by their autofill ids) mapped by the hint associate
* with them.
*
* <p>An autofillable field is a {@link ViewNode} whose {@link #getHint(ViewNode)} metho
*/
@NonNull
private ArrayMap<String, AutofillId> getAutofillableFields(@NonNull AssistStructure structure) {
ArrayMap<String, AutofillId> fields = new ArrayMap<>();
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
ViewNode node = structure.getWindowNodeAt(i).getRootViewNode();
addAutofillableFields(fields, node);
}
return fields;
}
@Override
public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
List<FillContext> fillContexts = request.getFillContexts();
List<AssistStructure> structures =
fillContexts.stream().map(FillContext::getStructure).collect(toList());
AssistStructure latestStructure = fillContexts.get(fillContexts.size() - 1).getStructure();
ClientParser parser = new ClientParser(structures);
mLocalAutofillDataSource.getFieldTypeByAutofillHints(
new DataCallback<HashMap<String, FieldTypeWithHeuristics>>() {
@Override
public void onLoaded(
HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
mAutofillDataBuilder = new ClientAutofillDataBuilder(
fieldTypesByAutofillHint, getPackageName(), parser);
ClientViewMetadataBuilder clientViewMetadataBuilder =
new ClientViewMetadataBuilder(parser, fieldTypesByAutofillHint);
mClientViewMetadata = clientViewMetadataBuilder.buildClientViewMetadata();
String packageName = latestStructure.getActivityComponent().getPackageName();
if (!mPackageVerificationRepository.putPackageSignatures(packageName)) {
callback.onFailure(getString(R.string.invalid_package_signature));
return;
}
if (logVerboseEnabled()) {
logv("onSaveRequest(): clientState=%s",
bundleToString(request.getClientState()));
}
dumpStructure(latestStructure);
checkWebDomainAndBuildAutofillData(packageName, callback);
}
@Override
public void onDataNotAvailable(String msg, Object... params) {
loge("Should not happen - could not find field types.");
}
});
}
public static void dumpStructure(AssistStructure structure) {
if (logVerboseEnabled()) {
int nodeCount = structure.getWindowNodeCount();
logv("dumpStructure(): component=%s numberNodes=%d",
structure.getActivityComponent(), nodeCount);
for (int i = 0; i < nodeCount; i++) {
logv("node #%d", i);
WindowNode node = structure.getWindowNodeAt(i);
dumpNode(new StringBuilder(), " ", node.getRootViewNode(), 0);
}
}
}
/**
* Gets a node if it matches the filter criteria for the given id.
*/
public static ViewNode findNodeByFilter(@NonNull AssistStructure structure, @NonNull Object id,
@NonNull NodeFilter filter) {
logv("Parsing request for activity %s", structure.getActivityComponent());
final int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
final WindowNode windowNode = structure.getWindowNodeAt(i);
final ViewNode rootNode = windowNode.getRootViewNode();
final ViewNode node = findNodeByFilter(rootNode, id, filter);
if (node != null) {
return node;
}
}
return null;
}
private void onFieldSelected(FilledAutofillField field, FieldType fieldType) {
DatasetWithFilledAutofillFields datasetWithFilledAutofillFields = new DatasetWithFilledAutofillFields();
String newDatasetId = UUID.randomUUID().toString();
FilledAutofillField copyOfField = new FilledAutofillField(newDatasetId,
field.getFieldTypeName(), field.getTextValue(), field.getDateValue(),
field.getToggleValue());
String datasetName = "dataset-manual";
AutofillDataset autofillDataset = new AutofillDataset(newDatasetId, datasetName, mPackageName);
datasetWithFilledAutofillFields.filledAutofillFields = ImmutableList.of(copyOfField);
datasetWithFilledAutofillFields.autofillDataset = autofillDataset;
Intent intent = getIntent();
AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
ClientParser clientParser = new ClientParser(structure);
mReplyIntent = new Intent();
mLocalAutofillDataSource.getFieldTypeByAutofillHints(
new DataCallback<HashMap<String, FieldTypeWithHeuristics>>() {
@Override
public void onLoaded(HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
ClientViewMetadataBuilder builder = new ClientViewMetadataBuilder(clientParser,
fieldTypesByAutofillHint);
mClientViewMetadata = builder.buildClientViewMetadata();
mDatasetAdapter = new DatasetAdapter(clientParser);
mResponseAdapter = new ResponseAdapter(ManualActivity.this,
mClientViewMetadata, mPackageName, mDatasetAdapter);
FillResponse fillResponse = mResponseAdapter.buildResponseForFocusedNode(
datasetName, field, fieldType);
setResponseIntent(fillResponse);
finish();
}
@Override
public void onDataNotAvailable(String msg, Object... params) {
}
});
}
public static void dumpStructure(AssistStructure structure) {
int nodeCount = structure.getWindowNodeCount();
Log.v(TAG, "dumpStructure(): component=" + structure.getActivityComponent()
+ " numberNodes=" + nodeCount);
for (int i = 0; i < nodeCount; i++) {
Log.v(TAG, "node #" + i);
WindowNode node = structure.getWindowNodeAt(i);
dumpNode(" ", node.getRootViewNode());
}
}
@Override
public void handleAssist(final Bundle data, final AssistStructure structure,
final AssistContent content, final int index, final int count) {
// We want to pre-warm the AssistStructure before handing it off to the main
// thread. We also want to do this on a separate thread, so that if the app
// is for some reason slow (due to slow filling in of async children in the
// structure), we don't block other incoming IPCs (such as the screenshot) to
// us (since we are a oneway interface, they get serialized). (Okay?)
Thread retriever = new Thread("AssistStructure retriever") {
@Override
public void run() {
Throwable failure = null;
if (structure != null) {
try {
structure.ensureData();
} catch (Throwable e) {
Log.w(TAG, "Failure retrieving AssistStructure", e);
failure = e;
}
}
mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOOII(MSG_HANDLE_ASSIST,
data, failure == null ? structure : null, failure, content,
index, count));
}
};
retriever.start();
}
void doOnHandleAssist(Bundle data, AssistStructure structure, Throwable failure,
AssistContent content) {
if (failure != null) {
onAssistStructureFailure(failure);
}
onHandleAssist(data, structure, content);
}
void doOnHandleAssistSecondary(Bundle data, AssistStructure structure, Throwable failure,
AssistContent content, int index, int count) {
if (failure != null) {
onAssistStructureFailure(failure);
}
onHandleAssistSecondary(data, structure, content, index, count);
}
private void parseAutofillFields(AssistStructure.ViewNode viewNode,
DatasetWithFilledAutofillFields datasetWithFilledAutofillFields, int partition) {
String[] hints = viewNode.getAutofillHints();
if (hints == null || hints.length == 0) {
return;
}
AutofillValue autofillValue = viewNode.getAutofillValue();
String textValue = null;
Long dateValue = null;
Boolean toggleValue = null;
CharSequence[] autofillOptions = null;
Integer listIndex = null;
if (autofillValue != null) {
if (autofillValue.isText()) {
// Using toString of AutofillValue.getTextValue in order to save it to
// SharedPreferences.
textValue = autofillValue.getTextValue().toString();
} else if (autofillValue.isDate()) {
dateValue = autofillValue.getDateValue();
} else if (autofillValue.isList()) {
autofillOptions = viewNode.getAutofillOptions();
listIndex = autofillValue.getListValue();
} else if (autofillValue.isToggle()) {
toggleValue = autofillValue.getToggleValue();
}
}
appendViewMetadata(datasetWithFilledAutofillFields,
hints, partition, textValue, dateValue, toggleValue,
autofillOptions, listIndex);
}
private void parseWebDomain(AssistStructure.ViewNode viewNode, StringBuilder validWebDomain) {
String webDomain = viewNode.getWebDomain();
if (webDomain != null) {
logd("child web domain: %s", webDomain);
if (validWebDomain.length() > 0) {
if (!webDomain.equals(validWebDomain.toString())) {
throw new SecurityException("Found multiple web domains: valid= "
+ validWebDomain + ", child=" + webDomain);
}
} else {
validWebDomain.append(webDomain);
}
}
}
private void onSuccess() {
Intent intent = getIntent();
boolean forResponse = intent.getBooleanExtra(EXTRA_FOR_RESPONSE, true);
AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
ClientParser clientParser = new ClientParser(structure);
mReplyIntent = new Intent();
mLocalAutofillDataSource.getFieldTypeByAutofillHints(
new DataCallback<HashMap<String, FieldTypeWithHeuristics>>() {
@Override
public void onLoaded(HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
ClientViewMetadataBuilder builder = new ClientViewMetadataBuilder(clientParser,
fieldTypesByAutofillHint);
mClientViewMetadata = builder.buildClientViewMetadata();
mDatasetAdapter = new DatasetAdapter(clientParser);
mResponseAdapter = new ResponseAdapter(AuthActivity.this,
mClientViewMetadata, mPackageName, mDatasetAdapter);
if (forResponse) {
fetchAllDatasetsAndSetIntent(fieldTypesByAutofillHint);
} else {
String datasetName = intent.getStringExtra(EXTRA_DATASET_NAME);
fetchDatasetAndSetIntent(fieldTypesByAutofillHint, datasetName);
}
}
@Override
public void onDataNotAvailable(String msg, Object... params) {
}
});
}
/**
* Traverses through the {@link AssistStructure} and does something at each {@link ViewNode}.
*
* @param processor contains action to be performed on each {@link ViewNode}.
*/
public void parse(NodeProcessor processor) {
for (AssistStructure structure : mStructures) {
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
AssistStructure.ViewNode viewNode = structure.getWindowNodeAt(i).getRootViewNode();
traverseRoot(viewNode, processor);
}
}
}
private void traverseRoot(AssistStructure.ViewNode viewNode, NodeProcessor processor) {
processor.processNode(viewNode);
int childrenSize = viewNode.getChildCount();
if (childrenSize > 0) {
for (int i = 0; i < childrenSize; i++) {
traverseRoot(viewNode.getChildAt(i), processor);
}
}
}
@NonNull
private ArrayMap<String, AutofillId> getAutofillableFields(@NonNull AssistStructure structure) {
ArrayMap<String, AutofillId> fields = new ArrayMap<>();
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
ViewNode node = structure.getWindowNodeAt(i).getRootViewNode();
addAutofillableFields(fields, node);
}
return fields;
}
/**
* Parses the {@link AssistStructure} representing the activity being autofilled, and returns a
* map of autofillable fields (represented by their autofill ids) mapped by the hint associate
* with them.
*
* <p>An autofillable field is a {@link ViewNode} whose {@link #getHint(ViewNode)} metho
*/
@NonNull
private Map<String, AutofillId> getAutofillableFields(@NonNull AssistStructure structure) {
Map<String, AutofillId> fields = new ArrayMap<>();
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
ViewNode node = structure.getWindowNodeAt(i).getRootViewNode();
addAutofillableFields(fields, node);
}
return fields;
}
/**
* Parses the {@link AssistStructure} representing the activity being autofilled, and returns a
* map of autofillable fields (represented by their autofill ids) mapped by the hint associate
* with them.
*
* <p>An autofillable field is a {@link ViewNode} whose {@link #getHint(ViewNode)} metho
*/
@NonNull
private ArrayMap<String, AutofillId> getAutofillableFields(@NonNull AssistStructure structure) {
ArrayMap<String, AutofillId> fields = new ArrayMap<>();
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
ViewNode node = structure.getWindowNodeAt(i).getRootViewNode();
addAutofillableFields(fields, node);
}
return fields;
}
@Override
public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
List<FillContext> fillContexts = request.getFillContexts();
List<AssistStructure> structures =
fillContexts.stream().map(FillContext::getStructure).collect(toList());
AssistStructure latestStructure = fillContexts.get(fillContexts.size() - 1).getStructure();
ClientParser parser = new ClientParser(structures);
mLocalAutofillDataSource.getFieldTypeByAutofillHints(
new DataCallback<HashMap<String, FieldTypeWithHeuristics>>() {
@Override
public void onLoaded(
HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
mAutofillDataBuilder = new ClientAutofillDataBuilder(
fieldTypesByAutofillHint, getPackageName(), parser);
ClientViewMetadataBuilder clientViewMetadataBuilder =
new ClientViewMetadataBuilder(parser, fieldTypesByAutofillHint);
mClientViewMetadata = clientViewMetadataBuilder.buildClientViewMetadata();
String packageName = latestStructure.getActivityComponent().getPackageName();
if (!mPackageVerificationRepository.putPackageSignatures(packageName)) {
callback.onFailure(getString(R.string.invalid_package_signature));
return;
}
if (logVerboseEnabled()) {
logv("onSaveRequest(): clientState=%s",
bundleToString(request.getClientState()));
}
dumpStructure(latestStructure);
checkWebDomainAndBuildAutofillData(packageName, callback);
}
@Override
public void onDataNotAvailable(String msg, Object... params) {
loge("Should not happen - could not find field types.");
}
});
}
public static void dumpStructure(AssistStructure structure) {
if (logVerboseEnabled()) {
int nodeCount = structure.getWindowNodeCount();
logv("dumpStructure(): component=%s numberNodes=%d",
structure.getActivityComponent(), nodeCount);
for (int i = 0; i < nodeCount; i++) {
logv("node #%d", i);
WindowNode node = structure.getWindowNodeAt(i);
dumpNode(new StringBuilder(), " ", node.getRootViewNode(), 0);
}
}
}