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.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);
}
}