1 page.title=WikiNotes: Linkify your Text! 2 @jd:body 3 4 <img style="margin-left: 1.5em; margin-bottom:1.5em; float: right;" 5 src="images/WikiNotes.png" alt="Linkify example" border="0"> 6 7 <p>This article introduces <a 8 href="http://android-developers.blogspot.com/2008/03/announcing-apps-for-android 9 .html">WikiNotes for Android</a>, part of the <a 10 href="http://code.google.com/p/apps-for-android/">Apps for Android</a> 11 project. It covers the use of Linkify to turn ordinary text views 12 into richer, link-oriented content that causes Android intents to fire 13 when a link is selected.</p> 14 15 <p><strong>Linkify</strong>: The {@link android.text.util.Linkify} class in the 16 framework is perfect for creating a wiki note pad. It lets you specify a <a 17 title="regular expression" 18 href="http://en.wikipedia.org/wiki/Regular_expression">regular expression 19 »</a> 20 to match, and a scheme to prepend. The scheme is a string that, when 21 the matched text is added, forms a Content URI to allow the correct 22 data to be looked up.</p> 23 24 <p>For example, in our case we want to look for a regular expression match for a 25 WikiWord (that is, a word with <a title="word with camel case" 26 href="http://en.wikipedia.org/wiki/CamelCase">camel case »</a> and no 27 spaces). Linkify can then turn this into a Content URI — something like 28 <code>content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord</code>, 29 which can then be used to locate the correct wiki page from a 30 {@link android.content.ContentProvider}.</p> 31 32 <p>As a bonus, the Linkify class also defines several default matches, 33 in particular it is able to turn web URLs, email addresses and 34 telephone numbers into active links which fire Android intents 35 automatically.</p> 36 37 <p>Linkify can be passed any TextView in your application, and will 38 take care of creating the links and enabling their "clickability" for 39 you.</p> 40 41 <p><strong>Default Linkify</strong>: Using the set of default active 42 link options is very straightforward. Simply pass it a handle to a 43 TextView with content in it, and the <code>Linkify.ALL</code> flag:</p> 44 45 <pre>TextView noteView = (TextView) findViewById(R.id.noteview); 46 noteView.setText(someContent); 47 Linkify.addLinks(noteView, Linkify.ALL);</pre> 48 49 <p>and that's it. The <code>Linkify.ALL</code> flag applies all of the predefined 50 link actions, and the TextView will be immediately updated with a set 51 of active links which, if you select them, fire default intents for the 52 actions (e.g. a web URL will start the browser with that URL, a 53 telephone number will bring up the phone dialer with that number ready 54 to call, etc.).</p> 55 56 <p><strong>Custom Linkify</strong>: So what about our WikiWord? There is no 57 pre-defined action for that, so it needs to be defined and associated with a 58 scheme.</p> 59 60 <p>The first task is to define a regular expression that matches the kind of 61 WikiWords we want to find. The regex in this case is:</p> 62 63 <pre>\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\b</pre> 64 65 <p>Obvious, no? Well actually this is equivalent to the following 66 description: "Starting with a word boundary (the \b) find at least one 67 upper case letter, followed by at least one lower case letter or a 68 numeric digit, followed by another upper case letter, and then any mix 69 of upper case, lower case or numeric until the next word boundary (the 70 final \b)". Regular expressions are not very pretty, but they are an 71 extremely concise and accurate way of specifying a search pattern.</p> 72 73 <p>We also need to tell Linkify what to do with a match to the 74 WikiWord. Linkify will automatically append whatever is matched to a 75 scheme that is supplied to it, so for the sake of argument let's assume 76 we have a {@link android.content.ContentProvider} that matches the 77 following content URI:</p> 78 79 <pre>content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord</pre> 80 81 <p>The WikiWord part will be appended by Linkify when it finds a match, so we 82 just need the part before that as our scheme.</p> 83 84 <p>Now that we have these two things, we use Linkify to connect them up:</p> 85 86 <pre>Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b"); 87 String wikiViewURL = "content://com.google.android.wikinotes.db.wikinotes/wikinotes/"; 88 Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);</pre> 89 90 <p>Note that the \b's had to be escaped with double backslashes for the Java 91 Pattern.compile line.</p> 92 93 <p>Linkify can be used multiple times on the same view to add more 94 links, so using this after the Default Linkify call means that the 95 existing active links will be maintained and the new WikiWords will be 96 added. You could define more Linkify actions and keep applying them to 97 the same TextView if you wanted to.</p> 98 99 <p>Now, if we have a WikiWord in the TextView, let's say 100 <code>MyToDoList</code>, Linkify will turn it into an active link with the 101 content URI:</p> 102 103 <pre>content://com.google.android.wikinotes.db.wikinotes/wikinotes/MyToDoList</pre> 104 105 <p>and if you click on it, Android will fire the default intent for that content 106 URI.</p> 107 108 <p>For this to all work, you will need a ContentProvider that 109 understands that Content URI, and you will need a default activity 110 capable of doing something with the resulting data. I plan to cover 111 these in future blog entries (and soon). In fact, the whole Wiki Note 112 Pad application is currently undergoing some clean up and review, and 113 will then hopefully be released as a sample application.</p> 114