Home | History | Annotate | Download | only in articles
      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 &raquo;</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 &raquo;</a> and no
     27 spaces). Linkify can then turn this into a Content URI &mdash; 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