Sunday, July 3, 2011
Email from a link and Android Intents - bring it home
Yesterday, we *almost* got off easy by using linkify to launch a feedback email. But...we would like to fill in the subject automatically, with something like "feedback".
So, what to we have so far?
TextView feedback = (TextView) findViewById(R.id.feedback);
String text = "Feedback: mcd@kanjisoft.com";
feedback.setText(text);
Linkify.addLinks(feedback, Linkify.ALL);
We also have some sample code on how to create and intent with the subject set:
/* Create the Intent */
final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
/* Fill it with Data */
emailIntent.setType("plain/text");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"to@email.com"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Feedback");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Text");
Intent i = new Intent(Intent.ACTION_SEND_TO)
But, how to get that intent to be launched by the linkify?
Let's briefly review Linkify:
http://developer.android.com/resources/articles/wikinotes-linkify.html
WikiNotes: Linkify your Text!
This article introduces WikiNotes for Android, part of the Apps for Android project. It covers the use of Linkify to turn ordinary text views into richer, link-oriented content that causes Android intents to fire when a link is selected.
// in other words, it highlights a part of the text as a link.
Linkify: The Linkify class in the framework is perfect for creating a wiki note pad. It lets you specify a regular expression » to match, and a scheme to prepend.
// So, for example, the scheme would be http:// or content:// or whatever, and
// then the highlights the part which will come after it.
The scheme is a string that, when the matched text is added, forms a Content URI to allow the correct data to be looked up.
// that's what I just said, which applies specifically to wiki.
For example, in our case we want to look for a regular expression match for a WikiWord (that is, a word with camel case » and no spaces). Linkify can then turn this into a Content URI — something like content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord, which can then be used to locate the correct wiki page from a ContentProvider.
// ok, kin
As a bonus, the Linkify class also defines several default matches, in particular it is able to turn web URLs, email addresses and telephone numbers into active links which fire Android intents automatically.
// That's what I'm doing right now for email.
Linkify can be passed any TextView in your application, and will take care of creating the links and enabling their "clickability" for you.
// Ok.
Default Linkify: Using the set of default active link options is very straightforward. Simply pass it a handle to a TextView with content in it, and the Linkify.ALL flag:
TextView noteView = (TextView) findViewById(R.id.noteview);
noteView.setText(someContent);
Linkify.addLinks(noteView, Linkify.ALL);
// That's also what I'm doing.
and that's it. The Linkify.ALL flag applies all of the predefined link actions, and the TextView will be immediately updated with a set of active links which, if you select them, fire default intents for the actions (e.g. a web URL will start the browser with that URL, a telephone number will bring up the phone dialer with that number ready to call, etc.).
// ok; but how do you do it specifically for email?
// This site has some good info:
http://www.ianr.unl.edu/internet/mailto.html
Simple MailTo
a href="mailto:astark1@unl.edu"
// Ok, let's this variation with "mailto" as the prefix:
TextView feedback = (TextView) findViewById(R.id.feedback);
String text = "Feedback: mcd@kanjisoft.com";
feedback.setText(text);
// pattern we want to match and turn into a clickable link
Pattern pattern = Pattern.compile("mcd@kanjisoft.com");
// prefix our pattern with mailto:
Linkify.addLinks(feedback, pattern, "mailto:");
That's it. Now, can we add the subject as a parameter? From the same page:
a href="mailto:astark1@unl.edu?subject=Comments from MailTo Syntax Page"
So, change the pattern:
TextView feedback = (TextView) findViewById(R.id.feedback);
String text = "Feedback: mcd@kanjisoft.com?subject=Feedback";
feedback.setText(text);
// pattern we want to match and turn into a clickable link
Pattern pattern = Pattern.compile("mcd@kanjisoft.com?subject=Feedback");
Linkify.addLinks(feedback, pattern, "mailto:");
And see what happens:
Fail..it split it into two lines and nothing happened.
Well, based on this:
http://www.indelible.org/ink/android-linkify/
// Detect US postal ZIP codes and link to a lookup service
Pattern pattern = Pattern.compile("\\d{5}([\\-]\\d{4})?");
String scheme = "http://zipinfo.com/cgi-local/zipsrch.exe?zip=";
Linkify.addLinks(text, pattern, scheme);
It looks like all I really need is in the scheme. I still need to have text, but the pattern doesn't have to be anything.
How about this:
TextView feedback = (TextView) findViewById(R.id.feedback);
String text = "Feedback: ";
feedback.setText(text);
// pattern we want to match and turn into a clickable link
Pattern pattern = Pattern.compile("xxx");
Linkify.addLinks(feedback,
pattern,
"mailto:mcd@kanjisoft.com?subject=Feedback");
No; it's losing the whole mailto part.
Ok. I give up. Back to the docs.
Where were we?
And that's it. The Linkify.ALL flag applies all of the predefined link actions, and the TextView will be immediately updated with a set of active links which, if you select them, fire default intents for the actions (e.g. a web URL will start the browser with that URL, a telephone number will bring up the phone dialer with that number ready to call, etc.).
// ok.
Custom Linkify: So what about our WikiWord? There is no pre-defined action for that, so it needs to be defined and associated with a scheme.
The first task is to define a regular expression that matches the kind of WikiWords we want to find. The regex in this case is:
\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\b
Obvious, no? Well actually this is equivalent to the following description: "Starting with a word boundary (the \b) find at least one upper case letter, followed by at least one lower case letter or a numeric digit, followed by another upper case letter, and then any mix of upper case, lower case or numeric until the next word boundary (the final \b)". Regular expressions are not very pretty, but they are an extremely concise and accurate way of specifying a search pattern.
// ok. We all know about regex patterns, but it never hurts to have a review.
We also need to tell Linkify what to do with a match to the WikiWord. Linkify will automatically append whatever is matched to a scheme that is supplied to it, so for the sake of argument let's assume we have a ContentProvider that matches the following content URI:
content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord
// ok...
The WikiWord part will be appended by Linkify when it finds a match, so we just need the part before that as our scheme.
Now that we have these two things, we use Linkify to connect them up:
Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b");
String wikiViewURL = "content://com.google.android.wikinotes.db.wikinotes/wikinotes/";
Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);
// ok. So, the scheme comes fist, then then anything that matches the regex.
// But we knew that. What if we did something like match "subject=Feedback"
// and put the rest as the url?
Ok, progress. It still splits it up into two lines, but actually that's because of the length, perhaps. Also, the mailto: and all doesn't really even need to be seen. How do I get rid of that? Unlike the http url, I don't even want the link to necessarily be seen.
//Let's keep reading.
Note that the \b's had to be escaped with double backslashes for the Java Pattern.compile line.
// sure.
Linkify can be used multiple times on the same view to add more links, so using this after the Default Linkify call means that the existing active links will be maintained and the new WikiWords will be added. You could define more Linkify actions and keep applying them to the same TextView if you wanted to.
// Does it mean after a view is updated, with new Wiki Words? And what is meant by
// the default linkify, again?
Now, if we have a WikiWord in the TextView, let's say MyToDoList, Linkify will turn it into an active link with the content URI:
content://com.google.android.wikinotes.db.wikinotes/wikinotes/MyToDoList
and if you click on it, Android will fire the default intent for that content URI.
// Ok.
For this to all work, you will need a ContentProvider that understands that Content URI, and you will need a default activity capable of doing something with the resulting data. I plan to cover these in future blog entries (and soon). In fact, the whole Wiki Note Pad application is currently undergoing some clean up and review, and will then hopefully be released as a sample application.
ok. Still, my problem is unresolved. I need something that say:
"Send Feedback" and does mailto:mcd@kanjisoft.com?subject=feedback.
Wait a second. All I need to do is have the "Send feedback" be the pattern,
and the url be mailto:mcd@kanjisoft.com?subject=feedback. Let's try it.
TextView feedback = (TextView) findViewById(R.id.feedback);
String text = "Send feedback";
feedback.setText(text);
// pattern we want to match and turn into a clickable link
Pattern pattern = Pattern.compile("Send feedback");
Linkify.addLinks(feedback, pattern,"mailto:mcd@kanjisoft.com?subject=Feedback");
Almost; everything works, but the subject is "feedbackSend Feedback". So, it's appending the highlighted text. So, the problem is, that the pattern.compile does two things. It highlights the text, and appends it. This isn't really ideal, because in this case, I want the two to be different.
So, I haven't really resolved the problem. But, in the interest of time, I'll compromise, and have it say Send feedback, where only the feedback will be highlited.
The final result (image at top):
TextView feedback = (TextView) findViewById(R.id.feedback);
//String text = "Feedback: mcd@kanjisoft.com?subject=Feedback";
String text = "Send feedback";
feedback.setText(text);
// pattern we want to match and turn into a clickable link
Pattern pattern = Pattern.compile("feedback");
// prefix our pattern with http://
Linkify.addLinks(feedback, pattern, "mailto:mcd@kanjisoft.com?subject=");
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment