Use custom dialog builder building url link clickable from service

This change is derived from I7611ebc1 (Honeycomb).

Bug: 3246715
Change-Id: I6446bd785f1bd3d7b901e86661c91ca5a823f30e
This commit is contained in:
Tadashi G. Takaoka 2011-02-01 14:03:12 +09:00
parent eaa091da78
commit 34252baa86

View file

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