Use custom dialog builder building url link clickable from service
This change is derived from I7611ebc1 (Honeycomb). Bug: 3246715 Change-Id: I6446bd785f1bd3d7b901e86661c91ca5a823f30emain
parent
eaa091da78
commit
34252baa86
|
@ -38,16 +38,13 @@ import android.os.IBinder;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.provider.Browser;
|
||||
import android.speech.SpeechRecognizer;
|
||||
import android.text.Layout;
|
||||
import android.text.Selection;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
|
@ -83,8 +80,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
|||
private static final String IME_OPTION_NO_MICROPHONE = "nm";
|
||||
private static final int RECOGNITIONVIEW_HEIGHT_THRESHOLD_RATIO = 6;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "VoiceIMEConnector";
|
||||
private static final String TAG = VoiceIMEConnector.class.getSimpleName();
|
||||
private static boolean DEBUG = LatinImeLogger.sDBG;
|
||||
|
||||
private boolean mAfterVoiceInput;
|
||||
|
@ -177,7 +173,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
|||
if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
|
||||
return;
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(mService);
|
||||
AlertDialog.Builder builder = new UrlLinkAlertDialogBuilder(mService);
|
||||
builder.setCancelable(true);
|
||||
builder.setIcon(R.drawable.ic_mic_dialog);
|
||||
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
|
@ -215,90 +211,80 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
|||
mService.getText(R.string.voice_warning_how_to_turn_off));
|
||||
}
|
||||
builder.setMessage(message);
|
||||
|
||||
builder.setTitle(R.string.voice_warning_title);
|
||||
mVoiceWarningDialog = builder.create();
|
||||
Window window = mVoiceWarningDialog.getWindow();
|
||||
WindowManager.LayoutParams lp = window.getAttributes();
|
||||
final Window window = mVoiceWarningDialog.getWindow();
|
||||
final WindowManager.LayoutParams lp = window.getAttributes();
|
||||
lp.token = token;
|
||||
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||
window.setAttributes(lp);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||
mVoiceInput.logKeyboardWarningDialogShown();
|
||||
mVoiceWarningDialog.show();
|
||||
// Make URL in the dialog message clickable
|
||||
TextView textView = (TextView) mVoiceWarningDialog.findViewById(android.R.id.message);
|
||||
if (textView != null) {
|
||||
final CustomLinkMovementMethod method = CustomLinkMovementMethod.getInstance();
|
||||
method.setVoiceWarningDialog(mVoiceWarningDialog);
|
||||
textView.setMovementMethod(method);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CustomLinkMovementMethod extends LinkMovementMethod {
|
||||
private static CustomLinkMovementMethod sLinkMovementMethodInstance =
|
||||
new CustomLinkMovementMethod();
|
||||
private static class UrlLinkAlertDialogBuilder extends AlertDialog.Builder {
|
||||
private AlertDialog mAlertDialog;
|
||||
|
||||
public void setVoiceWarningDialog(AlertDialog alertDialog) {
|
||||
mAlertDialog = alertDialog;
|
||||
public UrlLinkAlertDialogBuilder(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public static CustomLinkMovementMethod getInstance() {
|
||||
return sLinkMovementMethodInstance;
|
||||
}
|
||||
|
||||
// Almost the same as LinkMovementMethod.onTouchEvent(), but overrides it for
|
||||
// FLAG_ACTIVITY_NEW_TASK and mAlertDialog.cancel().
|
||||
@Override
|
||||
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
|
||||
int action = event.getAction();
|
||||
public AlertDialog.Builder setMessage(CharSequence message) {
|
||||
return super.setMessage(replaceURLSpan(message));
|
||||
}
|
||||
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
private Spanned replaceURLSpan(CharSequence message) {
|
||||
// Replace all spans with the custom span
|
||||
final SpannableStringBuilder ssb = new SpannableStringBuilder(message);
|
||||
for (URLSpan span : ssb.getSpans(0, ssb.length(), URLSpan.class)) {
|
||||
int spanStart = ssb.getSpanStart(span);
|
||||
int spanEnd = ssb.getSpanEnd(span);
|
||||
int spanFlags = ssb.getSpanFlags(span);
|
||||
ssb.removeSpan(span);
|
||||
ssb.setSpan(new ClickableSpan(span.getURL()), spanStart, spanEnd, spanFlags);
|
||||
}
|
||||
return ssb;
|
||||
}
|
||||
|
||||
x -= widget.getTotalPaddingLeft();
|
||||
y -= widget.getTotalPaddingTop();
|
||||
@Override
|
||||
public AlertDialog create() {
|
||||
final AlertDialog dialog = super.create();
|
||||
|
||||
x += widget.getScrollX();
|
||||
y += widget.getScrollY();
|
||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
@Override
|
||||
public void onShow(DialogInterface dialogInterface) {
|
||||
// Make URL in the dialog message click-able.
|
||||
TextView textView = (TextView) mAlertDialog.findViewById(android.R.id.message);
|
||||
if (textView != null) {
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
}
|
||||
});
|
||||
mAlertDialog = dialog;
|
||||
return dialog;
|
||||
}
|
||||
|
||||
Layout layout = widget.getLayout();
|
||||
int line = layout.getLineForVertical(y);
|
||||
int off = layout.getOffsetForHorizontal(line, x);
|
||||
class ClickableSpan extends URLSpan {
|
||||
public ClickableSpan(String url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
|
||||
|
||||
if (link.length != 0) {
|
||||
if (action == MotionEvent.ACTION_UP) {
|
||||
if (link[0] instanceof URLSpan) {
|
||||
URLSpan urlSpan = (URLSpan) link[0];
|
||||
Uri uri = Uri.parse(urlSpan.getURL());
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
Uri uri = Uri.parse(getURL());
|
||||
Context context = widget.getContext();
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
// Add this flag to start an activity from service
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
|
||||
if (mAlertDialog != null) {
|
||||
// Go back to the previous IME for now.
|
||||
// TODO: If we can find a way to bring the new activity to front
|
||||
// while keeping the warning dialog, we don't need to cancel here.
|
||||
// Dismiss the warning dialog and go back to the previous IME.
|
||||
// TODO: If we can find a way to bring the new activity to front while keeping
|
||||
// the warning dialog, we don't need to dismiss it here.
|
||||
mAlertDialog.cancel();
|
||||
}
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
link[0].onClick(widget);
|
||||
}
|
||||
} else if (action == MotionEvent.ACTION_DOWN) {
|
||||
Selection.setSelection(buffer, buffer.getSpanStart(link[0]),
|
||||
buffer.getSpanEnd(link[0]));
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
Selection.removeSelection(buffer);
|
||||
}
|
||||
}
|
||||
return super.onTouchEvent(widget, buffer, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue