Showing posts with label Android. Show all posts
Showing posts with label Android. Show all posts

Wednesday, December 28, 2011

The java way of highlighting an HTML content with JSoup and Regex (works for android too)

When I wanted to do this the first time, I tried to search on Stack Overflow and other Q&A forums but in vain. There are very few places where this topic has been discussed and none really concluded it. So here's some solution I formulated with parts of it flicked from various places.

What I wanted to do was: fetch html from a web page into my java application; get a search string from the application user; build a regex out of search string and highlight html content that matched the regex. This is quite easy to do this with a javascript but my use case required this to be done in the java code.

Basically I required this piece of code around the text that should be highlighted.


<span style="background-color:yellow"> Text that matched regex </span> 


Building the regex from search string

Suppose my search string was 'hello world' then my regex would be (hello)|(world*).

Here's the function that will do it.

private static String buildRegexFromQuery(String queryString) {
        String regex = "";
        String queryToConvert = queryString;

        /* Clean up query */

        queryToConvert = queryToConvert.replaceAll("[\\p{Punct}]*", " ");
        queryToConvert = queryToConvert.replaceAll("[\\s]*", " ");

        String[] regexArray = queryString.split(" ");

        regex = "(";
        for(int i = 0; i < regexArray.length - 1; i++) {
            String item = regexArray[i];
            regex += "(\\b)" + item + "(\\b)|";
        }

        regex += "(\\b)" + regexArray[regexArray.length - 1] + "[a-zA-Z0-9]*?(\\b))";
        return regex;
    }

Searching and replacing proper html content

I cannot just do a simple String.replaceAll() because that would mess the whole thing when matched text is inside the tags. So I was pretty sure I required a html parser. Then I met the beautiful. JSoup.

JSoup made things quite easy to me. I just had to traverse the HTML DOM tree, retrieve text and make changes. With the NodeTraversor and NodeVisitor class it is a piece of cake to traverse the html content.

     public String getHighlightedHtml() {
    
     Document doc = Jsoup.parse(htmlContent);
    
     final List<TextNode> nodesToChange = new ArrayList<TextNode>();
    
     NodeTraversor nd  = new NodeTraversor(new NodeVisitor() {
    
      @Override
      public void tail(Node node, int depth) {
       if (node instanceof TextNode) {
        TextNode textNode = (TextNode) node;
        String text = textNode.getWholeText();
         
        mat = pat.matcher(text);
        
        if(mat.find()) {
         nodesToChange.add(textNode);
        }
       }
      }
    
      @Override
      public void head(Node node, int depth) {        
      }
     });
    
     nd.traverse(doc.body());
    
     for (TextNode textNode : nodesToChange) {
      Node newNode = buildElementForText(textNode);
      textNode.replaceWith(newNode);
     }
     return doc.toString();
    }

Wrapping it all...

Here's my final class to wrap things up -

public class Highlighter {
    
   private String regex;
     private String htmlContent;
     Pattern pat;
     Matcher mat;
    
    
     public Highlighter(String searchString, String htmlString) {
      regex = buildRegexFromQuery(searchString);
      htmlContent = htmlString;
      pat = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
     }
    
     public String getHighlightedHtml() {
    
      Document doc = Jsoup.parse(htmlContent);
    
      final List<TextNode> nodesToChange = new ArrayList<TextNode>();
    
      NodeTraversor nd  = new NodeTraversor(new NodeVisitor() {
    
       @Override
       public void tail(Node node, int depth) {
        if (node instanceof TextNode) {
         TextNode textNode = (TextNode) node;
         String text = textNode.getWholeText();
         
         mat = pat.matcher(text);
         
         if(mat.find()) {
          nodesToChange.add(textNode);
         }
        }
       }
    
       @Override
       public void head(Node node, int depth) {        
       }
      });
    
      nd.traverse(doc.body());
    
      for (TextNode textNode : nodesToChange) {
       Node newNode = buildElementForText(textNode);
       textNode.replaceWith(newNode);
      }
      return doc.toString();
     }
    
     private static String buildRegexFromQuery(String queryString) {
      String regex = "";
      String queryToConvert = queryString;
      
      /* Clean up query */
      
      queryToConvert = queryToConvert.replaceAll("[\\p{Punct}]*", " ");
      queryToConvert = queryToConvert.replaceAll("[\\s]*", " ");
      
      String[] regexArray = queryString.split(" ");
      
      regex = "(";
      for(int i = 0; i < regexArray.length - 1; i++) {
       String item = regexArray[i];
       regex += "(\\b)" + item + "(\\b)|";
      }
    
      regex += "(\\b)" + regexArray[regexArray.length - 1] + "[a-zA-Z0-9]*?(\\b))";
      return regex;
     }
    
     private Node buildElementForText(TextNode textNode) {
      String text = textNode.getWholeText().trim();
      
      ArrayList<MatchedWord> matchedWordSet = new ArrayList<MatchedWord>();
      
      mat = pat.matcher(text);
      
      while(mat.find()) {
       matchedWordSet.add(new MatchedWord(mat.start(), mat.end()));
      }
      
      StringBuffer newText = new StringBuffer(text);
    
      for(int i = matchedWordSet.size() - 1; i >= 0; i-- ) {
       String wordToReplace = newText.substring(matchedWordSet.get(i).start, matchedWordSet.get(i).end);
       wordToReplace = "<b>" + wordToReplace+ "</b>";
       newText = newText.replace(matchedWordSet.get(i).start, matchedWordSet.get(i).end, wordToReplace);  
      }
      return new DataNode(newText.toString(), textNode.baseUri());
     }
     
     class MatchedWord {
      public int start;
      public int end;
      
      public MatchedWord(int start, int end) {
       this.start = start;
       this.end = end;
      }
     }
    }


Don't forget to add the JSoup library to your build path. Download JSoup from here

Tuesday, July 12, 2011

Get the new Android Market

Google has just announced the release of its new version of Android Market which is the version 3.0.26. Google said the new Android market will be rolled out with the new devices that are going to come. If you are an android owner and still waiting for the new version to hit your phone, then you’re probably missing all the fun. You can right away download this Android market from here and install it like any other application. The new android market has lot more applications and a whole new look. Here’s the video released by the Google -
New Android Market for Phones

&lt;&lt;Download link&gt;&gt;

Monday, February 14, 2011

LG Added Optimus 3D,Optimus 2X and Optimus Black to their Optimus Family

LG has unveiled three of their new optimus models, Optimus 3D, Optimus 2X, Optimus Black to compliment their Optimus series mobile phones. All of them are running on Android Operating System. Announcement was made at Barcelona.

Read the rest here

Friday, February 11, 2011

Nokia and Microsoft join hands to ride over Apple and Google

Here comes the sensational news in the industry!! Two giants decided to take on Apple and Google together.

Microsoft's journey into the Mobile OS segment was way back, on 19th April 2000. As of now Windows OS share is a mere ~2% of the overall market. This is the impact they have made in the smart phone industry so far.

Where as Nokia, the global leader in the mobile phone segment was troubled by the introduction of Android OS from Google. The competitors are using Android OS for their smart phones extensively. With the inbuilt Symbian OS Nokia looked to be in the tribal age. Gradually the Smart phones kicked them off the ground. The tie up says it all.

Wednesday, February 9, 2011

OliveSmart V-S300 first Android 2.3 Gingerbread smartphone for India


Just a week after the release of Android 2.3 GingerBread, Olive Telecom has announced release of its new smartphone OliveSmart V-S300 running on Android 2.3. OliveSmart V-S300 is being launched in association with Aircel and expected to cost around Rs. 20,000.

OliveSmart V-S300 runs android 2.3 and provides features like the HSPA+ connectivity, Bluetooth 2.1, Wifi, Proximity & Accelerometer sensors, GSM Quadband, Fluence Noise Cancellation with dual microphone and a 3.5mm headset jack, GPS, digital compass with Google Maps and MapMyIndia.

OliveSmart V-S300 has a hardware, pretty decent with 1Ghz Qualcomm SnapDragon processor along with Adreno 205 GPU for the graphics. The smartphone comes with a 4.1 inch WVGA display with a resolution of 480 x 800 and a capacitive touch interface with multi-touch support. OliveSmart V-S300 embodies an auto-focus 5mp camera with flash and supports 720p quality video recording. OliveSmart V-S300 has an in-built memory of 2GB with 512 MB ROM and extendable up to 32GB. And not to miss out, OliveSmart comes with HDMI Port Type D with DLNA capabilities for remote playback of HD content and Live TV.

OliveSmart V-S300 is a feature rich phone for the price it is available for. And looking at the features, it looks like a very decent phone and could be counted on. Let us just wait and see for more reviews on this phone once it is available.

OliveSmart V-S300 is expected to be available by the end of March.
More information on the phone is available on their OliveWebsite here

Thursday, January 27, 2011

Samsung Releases four new Android Smart Phones

Ever since Google released its mobile OS Android, Samsung has been very fond of Android. After the huge success of Samsung's Galaxy S and Nexus S, it has now announced four new phones to add to the list of android samsung phones. All the phones offer capacitive touch screen with 3G, WiFi, Bluetooth and GPS.

Samsung Ace - GT S5830


Samsung Galaxy Ace offers -

  • 800Mhz Qualcomm Turbo Processor
  • 3.5 inch HVGA touchscreen
  • Android 2.2 Froyo with TouchWiz 3.0 UI Layer
  • 5mp Camera
  • Stereo FM Radio
Samsung Fit GT S5670


Samsung Galaxy Fit is expected to be a mid-range smartphone and offers - 
  • 600 Mhz Processor
  • 3.31 inch QVGA display
  • Android 2.2 Froyo
  • 5mp Camera
Samsung Gio GT S5600


Samsung Galaxy Gio offers - 
  • 800 Mhz Processor
  • 3.2 inch HVGA Display
  • Android 2.2 Froyo
  • 3mp Camera
Samsung Galaxy Mini GT S5570


Samsung Galaxy mini offers -
  • 600 Mhz Processor
  • 3.14 inch QVGA display
  • Andriod 2.2 Froyo
  • 3mp Camera
These phones will be available in Russia and eventually arrive to European countries and also India and China.  The phone is expected to be in mid-range budget. I assume it to be between Rs. 11000 and Rs.16000.

Monday, January 24, 2011

India's first dual sim android phone - Motorola Glam XT800

Motorola XT800
Motorola has released its new Android Smart phone supporting dual-SIM capability in India. Named Motorola Glam XT800, the handset comes with Android 2.2 Froyo, a 3.7 inch touch screen, 5 mega pixel camera and GSM+CDMA connection. 

Motorola XT800 works on a processor of 550Mhz and a 256MB RAM on board. External memory can be extended up to 32GB using the microSDHC Card. Motorola XT800 comes with a 3.7 inch touch screen with FWVGA kind of display and a resolution of 480x854, aspect ratio being 16:9. Motorola XT800 also includes a camera of 5mp and capable of 720p HD video recording. Not to miss out, Motorola XT800 also provides an HDMI port for plugging it into an HD TV.

Motorola XT800 has the GPS module, supports Bluetooth 2.1 and also offers Wi-Fi 802.11 b/g. 

Even though Mororola XT800 seems to be a feature rich power packed phone, the processor speed of 550Mhz would make it hardly any good. Motorola has released an upgraded version called Motrola XT800+  in China which has a faster processor. This very fact makes me uncomfortable with this phone and would definitely not recommend it until I get one for hands-on review. 

Tuesday, September 28, 2010

Sony Ericssion Live View - Android Widget in Physical Form

Sony Ericssion unveiled their innovation named LiveView. Using LiveView you can get to know what is happening on your phone without opening your phone. LiveView is an accessary that will work on Bluetooth. To make it work you should have a mobile operating with Android 2.X OS and should be installed with LiveView android application. This application can be downloaded from Android Market.

Using LiveView you will get to know the incoming call alerts, missed call lists. You can even mute the ring using this. It will alert you when you have received a new text message which you can read right away from the LiveView. LiveView can display you Twitter and Facebook updates. You can very well use it as a wrist

Know More...