Update sample IME code to support showing autofill inline suggestion
Test: manual
Bug: 146587788
Change-Id: I0e5fa3d811b8951fe471f76ce14a5bdbddd81581
diff --git a/samples/AutofillKeyboard/Android.bp b/samples/AutofillKeyboard/Android.bp
index 5c6a561..273dbd2 100644
--- a/samples/AutofillKeyboard/Android.bp
+++ b/samples/AutofillKeyboard/Android.bp
@@ -6,5 +6,6 @@
sdk_version: "current",
static_libs: [
"androidx.annotation_annotation",
+ "android-support-annotations",
],
}
diff --git a/samples/AutofillKeyboard/res/layout/keyboard_10_9_9.xml b/samples/AutofillKeyboard/res/layout/keyboard_10_9_9.xml
index 3f64b89..846de35 100644
--- a/samples/AutofillKeyboard/res/layout/keyboard_10_9_9.xml
+++ b/samples/AutofillKeyboard/res/layout/keyboard_10_9_9.xml
@@ -22,7 +22,10 @@
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/KeyboardArea">
- <View style="@style/KeyboardRow.Header"/>
+ <LinearLayout
+ android:id="@+id/suggestion_view"
+ style="@style/KeyboardRow.Header">
+ </LinearLayout>
<LinearLayout style="@style/KeyboardRow">
<TextView
diff --git a/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/AutofillImeService.java b/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/AutofillImeService.java
index cb4bb77..4f102fa 100644
--- a/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/AutofillImeService.java
+++ b/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/AutofillImeService.java
@@ -17,15 +17,33 @@
package com.example.android.autofillkeyboard;
import android.inputmethodservice.InputMethodService;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.support.annotation.GuardedBy;
+import android.util.Log;
+import android.util.Size;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.inline.InlinePresentationSpec;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InlineSuggestion;
+import android.view.inputmethod.InlineSuggestionsRequest;
+import android.view.inputmethod.InlineSuggestionsResponse;
+import android.widget.LinearLayout;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
/** The {@link InputMethodService} implementation for Autofill keyboard. */
public class AutofillImeService extends InputMethodService {
private InputView mInputView;
private Decoder mDecoder;
+ private LinearLayout mSuggestionStrip;
@Override
public View onCreateInputView() {
@@ -45,6 +63,7 @@
mInputView.removeAllViews();
Keyboard keyboard = Keyboard.qwerty(this);
mInputView.addView(keyboard.inflateKeyboardView(LayoutInflater.from(this), mInputView));
+ mSuggestionStrip = mInputView.findViewById(R.id.suggestion_view);
}
@Override
@@ -56,7 +75,108 @@
outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_CONTENT;
}
+ /***************** Inline Suggestions Demo Code *****************/
+
+ private static final String TAG = "AutofillImeService";
+
+ private Handler mMainHandler = new Handler();
+
+ @GuardedBy("this")
+ private List<View> mSuggestionViews = new ArrayList<>();
+ @GuardedBy("this")
+ private List<Size> mSuggestionViewSizes = new ArrayList<>();
+ @GuardedBy("this")
+ private boolean mSuggestionViewVisible = false;
+
+ @Override
+ public InlineSuggestionsRequest onCreateInlineSuggestionsRequest() {
+ Log.d(TAG, "onCreateInlineSuggestionsRequest() called");
+ final ArrayList<InlinePresentationSpec> presentationSpecs = new ArrayList<>();
+ presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
+ new Size(400, 100)).build());
+ presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
+ new Size(400, 100)).build());
+
+ return new InlineSuggestionsRequest.Builder(presentationSpecs)
+ .setMaxSuggestionCount(2)
+ .build();
+ }
+
+ @Override
+ public boolean onInlineSuggestionsResponse(InlineSuggestionsResponse response) {
+ Log.d(TAG, "onInlineSuggestionsResponse() called");
+ AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
+ onInlineSuggestionsResponseInternal(response);
+ });
+ return true;
+ }
+
+ private synchronized void updateInlineSuggestionVisibility(boolean visible, boolean force) {
+ Log.d(TAG, "updateInlineSuggestionVisibility() called, visible=" + visible + ", force="
+ + force);
+ mMainHandler.post(() -> {
+ Log.d(TAG, "updateInlineSuggestionVisibility() running");
+ if (visible == mSuggestionViewVisible && !force) {
+ return;
+ } else if (visible) {
+ mSuggestionStrip.removeAllViews();
+ final int size = mSuggestionViews.size();
+ for (int i = 0; i < size; i++) {
+ ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+ mSuggestionViewSizes.get(i).getWidth(),
+ mSuggestionViewSizes.get(i).getHeight());
+ mSuggestionStrip.addView(mSuggestionViews.get(i), layoutParams);
+ }
+ mSuggestionViewVisible = true;
+ } else {
+ mSuggestionStrip.removeAllViews();
+ mSuggestionViewVisible = false;
+ }
+ });
+ }
+
+ private synchronized void updateSuggestionViews(View[] suggestionViews, Size[] sizes) {
+ Log.d(TAG, "updateSuggestionViews() called");
+ mSuggestionViews = Arrays.asList(suggestionViews);
+ mSuggestionViewSizes = Arrays.asList(sizes);
+ updateInlineSuggestionVisibility(true, true);
+ }
+
+ private void onInlineSuggestionsResponseInternal(InlineSuggestionsResponse response) {
+ Log.d(TAG, "onInlineSuggestionsResponseInternal() called. Suggestion="
+ + response.getInlineSuggestions().size());
+
+ final List<InlineSuggestion> inlineSuggestions = response.getInlineSuggestions();
+ final int totalSuggestionsCount = inlineSuggestions.size();
+ final AtomicInteger suggestionsCount = new AtomicInteger(totalSuggestionsCount);
+ final View[] suggestionViews = new View[totalSuggestionsCount];
+ final Size[] sizes = new Size[totalSuggestionsCount];
+
+ for (int i=0; i<totalSuggestionsCount; i++) {
+ final int index = i;
+ InlineSuggestion inlineSuggestion = inlineSuggestions.get(index);
+ Size size = inlineSuggestion.getInfo().getPresentationSpec().getMaxSize();
+ inlineSuggestion.inflate(this, size,
+ AsyncTask.THREAD_POOL_EXECUTOR,
+ suggestionView -> {
+ Log.d(TAG, "new inline suggestion view ready");
+ suggestionViews[index] = suggestionView;
+ sizes[index] = size;
+ suggestionView.setOnTouchListener((v, event) -> {
+ Toast.makeText(AutofillImeService.this, "hello",
+ Toast.LENGTH_LONG).show();
+ return false;
+ });
+ if (suggestionsCount.decrementAndGet() == 0) {
+ updateSuggestionViews(suggestionViews, sizes);
+ }
+ });
+ }
+ }
+
void handle(String data) {
+ Log.d(TAG, "handle() called: [" + data + "]");
mDecoder.decode(data);
+ updateInlineSuggestionVisibility(mDecoder.isEmpty(), false);
}
}
diff --git a/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/Decoder.java b/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/Decoder.java
index ffdda85..9239602 100644
--- a/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/Decoder.java
+++ b/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/Decoder.java
@@ -41,4 +41,12 @@
mInputConnection.commitText(data, 1);
}
}
+
+ boolean isEmpty() {
+ if (mInputConnection.getTextBeforeCursor(1, 0).length() == 0
+ && mInputConnection.getTextAfterCursor(1, 0).length() == 0) {
+ return true;
+ }
+ return false;
+ }
}