Writing a whois client for Android

    Logo

    In my last article, I said that there are quite a few libraries for parsing html, this time I decided to show how you can extract information from text using regular expressions, where it is impossible to “catch” tags and use the libraries mentioned. Initially, it all started with a small application, but gradually I came up with something new and as a result, it seems to me, it turned out pretty interesting.

    Under the cut, I will talk about the development process, show examples of work and development options.

    To begin with, I decided to study what is on the market, so I looked into the market and downloaded several applications using the “whois” keyword, I immediately realized that my application will be unique in that it will work with IDN domains, that is Cyrillic domain names.

    Development


    The first distinguishing feature of my application is its support for Cyrillic domains, and the second is that I will output "recognized" data. I will clearly know in which line, what data is located, and not like downloaded applications, where they trivially take and parse a block with data output and output it to WebView, so that it is clear why I need regular expressions, I will show a piece of the document with the information that interests me:

    whois block

    The screenshot shows that the tags are practically absent and no xpath here will help to break this text, so it's time to start creating a project and for work:

    new project

    This time I decided to choose the minimum version for which I downloaded the SDK, a little later I read on the hub that 2.1 and 2.2 are the most popular versions now, I’ll say right away that I’m developing for 2.1 (testing on the emulator), and I will use it on 2.2.

    This time I paid more attention to the interface, for this reason I can’t upload the full xml interface files, because they turned out pretty impressive.

    The main elements are:
          android:layout_width="fill_parent"
       android:id="@+id/site"
       android:maxLines="1"
       android:text="">
      

      
          android:layout_width="wrap_content"
       android:layout_height="wrap_content">
      


    * This source code was highlighted with Source Code Highlighter.

    In EditText we will indicate the site, here I specified android: maxLines = "1" so that it is impossible to enter several lines. Button is used to start parsing, it later turned out that in order to set simple styles for a button, you need a few more gestures than in many PC applications, so I will use a separate file for android settings: background = "@ layout / custom_button" . The ListView is also not as simple as it might seem at first glance, for it I developed a separate row, which consists of two columns.

    Interface files:
    main.xml - main file
    custom_button.xml - button styles
    color.xml - colors
    row.xml - line ListView

    As a result, we will get a left screenshot (though you have to set the strings of constants yourself or go to the end of the article and download the project):

    Interface

    I combined all the screenshots in two so that the post doesn’t get too long, so I’ll say right away that it’s the result of ProgressDialog after clicking the "Get whois data" button. As I wrote above, only one line is available, so when you try to press the transfer button on a new line, we will end the input, which will immediately hide the keyboard:
    EditText edittext = (EditText)findViewById(R.id.site);
    edittext.setImeOptions(EditorInfo.IME_ACTION_DONE);

    But since the user may not hide the keyboard and press the button “Get whois data”, we will hide it programmatically:
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);

    I also wanted to try calling the messages on the screen:

    Messages

    At our left:
    Toast.makeText(MainActivity.this, "Информация отсутствует...", Toast.LENGTH_LONG).show();

    And on the right is displayed:
    AlertDialog.Builder alertbox = new AlertDialog.Builder(MainActivity.this);
    alertbox.setMessage("Невозможно подключиться к серверу");
    alertbox.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface arg0, int arg1) {
        //обработка нажатия кнопки Ок
      }
    });
    alertbox.show();

    * This source code was highlighted with Source Code Highlighter.

    The second message is more critical, so you need to make sure that the user reads it, for this we use AlertDialog.

    We will use a third-party library to translate the domain . Using which you can get from "site.rf" the character set "xn - 80aswg.xn - p1ai".
    import gnu.inet.encoding.IDNA;
    IDNA.toASCII("сайт.рф");

    Many will say, why not use java.net.idn, but the documentation says that it is only in 9 api, and we have 7, my test also showed that import does not work in 7-8 api, but in 9 really everything is OK and the following code works fine without any libraries.

    Now we pass directly to parsing, as already mentioned, I will use regular expressions:
        HashMap map;
        Pattern p = Pattern.compile("created:\\s+(\\d{4}\\.\\d{2}\\.\\d{2})\n", Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(str);
        if (matcher.find()) {
          map = new HashMap();
          map.put("param", "создан:");
          map.put("value", matcher.group(1));
          list.add(map);
        }

    * This source code was highlighted with Source Code Highlighter.

    "Created: \\ s + (\\ d {4} \\. \\ d {2} \\. \\ d {2}) \ n" - date in the format yyyy.dd.MM or yyyy.MM.dd
    "Person: \\ s + (. +) \ N" - any character set between the space and the carriage return to a new line
    "phone: \\ s + (\\ + [\\ s \\ d] +) \ n" - + (plus) and spaces with numbers between spaces and a carriage return to a new line
    “mail: \\ s + (. +) \ n” - any character set between a space and a carriage return to a new line
    “registrar: \\ s + (. +) \ n "- any character set between a space and a carriage return to a new line
    " org: \\ s + (. +) \ n "- any character set between a space and a carriage return to a new line

    In fact, there are only two options: use the library and get only a block of code where the data you are looking for is contained and in addition use innertext, which in the future will give you quite tangible flexibility, as many registrars add their tags - these are links to mailto, a link to the site as in the example, etc. Or run through the regular expressions the whole response from the server (I tried to choose a registrar whose page is not overloaded too much).

    After we get the result, you can load it into a ListView:
    ListView list = (ListView) findViewById(R.id.whoisList);
    SimpleAdapter myAdapter = new SimpleAdapter(MainActivity.this, mylist, R.layout.row,
          new String[] { "param", "value"},
          new int[] {R.id.whoisParam, R.id.whoisData});
    list.setAdapter(myAdapter);

    * This source code was highlighted with Source Code Highlighter.

    The result of work for the two sites will be as follows:

    Sites

    And the last thing I wanted to do was add a menu and another Activity:
      Menu myMenu = null;

      @Override
      public boolean onCreateOptionsMenu(Menu menu) 
      {
        //call the parent to attach any system level menus
        super.onCreateOptionsMenu(menu);
        
        this.myMenu = menu;
        
        int base = Menu.FIRST; // value is 1
        MenuItem item = menu.add(base, base, base, "Помощь");
        item.setIcon(R.drawable.help);
        
        //it must return true to show the menu
        //if it is false menu won't show
        return true;
      }
      
      @Override
      public boolean onOptionsItemSelected(MenuItem item)   {
        if (item.getItemId() == 1)    {
          Intent intent = new Intent(MainActivity.this, Help.class);
          startActivity(intent);
        }
        //should return true if the menu item
        //is handled
        return true;
      }

    * This source code was highlighted with Source Code Highlighter.

    Here I create a menu and do the processing of pressing the menu button, after which I will see the following picture (on the left is the form after the menu is called, and on the right after the button is clicked). To close, just call finish () in the second Activity.

    Menu

    The only thing I almost forgot is the manifest file, where you definitely need to mention the use of the Internet and the existence of a new Activity. The finished project is as follows:

    Project

    Download link: project ( mirror )

    Total


    It seems to me that a rather interesting application has turned out, this time there are a lot of development options. This application can become a rather interesting seo tool in the future, you can add sites for other domain zones, obtain PageRank, TIC, save the results in the database. In general, it seems to me that the idea can be infinitely developed, although I agree with those who decide to write a web service, and the Android application will be used as a client to receive data from one single site, which of course will save traffic and most likely will work faster.

    Also popular now: