rcs34.android

Tuesday, October 6, 2015

GlyphView: Stale view: javax.swing.text.BadLocationException: Length must be positive


In this article I will show you, how you can get rid of the "GlyphView: Stale view: javax.swing.text.BadLocationException: Length must be positive" exception in JAVA Swing's JTextPane

If you are trying to develop your own cool text editor based on the JTextPane component, you probably have seen the message, which actually tells you, that you are trying to work with some incorrect offset/length combination.

The cause of the situation may be on your side and you should be sure for example, that you do modify the JTextPane's content only from the Dispatch thread (SwingUtilities.invokeLater is your friend).

If you are "pretty sure", that you do everything in the right way and your program keeps to fail with the BadLocationException, you can try the following workaround:

You will need your own implementations of the JTextPane, EditorKit and StyledDocument. You can put them all to one single class.
public class SCADTextPane extends JTextPane {

  private class Document extends DefaultStyledDocument {

    @Override
    public void getText(int _offset, int _length, Segment _txt) {
      if(_length<0){
        System.out.println("Getting rid of negative length "+_length);
       }
      try {
        super.getText(_offset, Math.max(_length, 0), _txt);
      } catch (Exception _e) {
        Logger.logError(new Exception("Offset/length/text: " + _offset + "/" + _length));
        Logger.logError(_e);
      }
    }
  }

  private class Kit extends StyledEditorKit {

    @Override
    public Document createDefaultDocument() {
      return new Document();
    }
  }

  @Override
  public EditorKit createDefaultEditorKit() {
    return new Kit();
  }
}


You can easily see, what makes the magic. You just grab the _length parameter of the getText() method and make sure that it's value is positive. You can of course do the similar with the _offset parameter.

Hope this will help you.



Thursday, January 22, 2015

Cooley–Tukey FFT algorithm


In this article I will show you, how you can compute the Cooley–Tukey FFT algorithm using the pure JAVA language.

If you are trying to work with some kind of signal analysis, you have probably learned that the FFT is the most widely used technique to extract the frequency spectrum from a signal.

You have of course many options to get some working FFT library. But some of them are licensed, and some of them are not easy to use nor well documented. If you want only to do some simple experiments with the FFT, you can freely use the code which I share On code.google.com. Once you add the FFTCooleyTukey class to your project, you can use it as follows:

    ...
    int SAMPLE_SIZE=1024;
    double[][] sample = new double[2][SAMPLE_SIZE];
    double[][]fftValues = new double[2][SAMPLE_SIZE];
    double[][]ifftValues = new double[2][SAMPLE_SIZE];
    //Read values and zero the imaginary part
    for(int i=0;i<SAMPLE_SIZE;i++){
      sample[0][i]=source[i];
      sample[1][i]=0;
    }
    System.out.println("\nOrig: "+Arrays.toString(sample[0]));
    try {
      fft.fft(sample, fftValues);
      System.out.println("FFT amplitudes: "+Arrays.toString(fftValues[0]));
      //Ask for aprticular frequency components
      System.out.println("200Hz component: "+fftValues[0][(int)Math.round(fft.getIndexOf(200))]);
      System.out.println("500Hz component: "+fftValues[0][(int)Math.round(fft.getIndexOf(500))]);
      fft.ifft(fftValues,ifftValues);
      System.out.println("IFFT amplitudes: "+Arrays.toString(ifftValues[0]));
    } catch (Exception ex) {
      Logger.getLogger(TunerPitchAnalyzer.class.getName()).log(Level.SEVERE, null, ex);
    }
    ...



Usage examples:
You can for example simply find the fftValues[0] for an index which holds the highest value and directly take the signal's base frequency like this:
    nFreq = fft.getFreq(maxIndex);

Or you can build a simple equalizer. Just multiply correspondent values in the fftValues[0] with a gain coefficient. The signal restored with the ifft() will then reflect the changes in the frequency spectrum.

Fill free to download the source on href="https://code.google.com/p/fft-processor/source/browse/trunk/FFTCooleyTukey.java

Hope this will help you.



Friday, September 27, 2013

OpenGL - load 3D objects from .obj files


In this article I will show you, how to load  complex 3D objects into your JAVA program and how to render them. The example uses JAVA/JOGL, so it is not directly Android-related.

If you try to create some 3D program based on the OpenGL platform, you probably have learned, that it is nearly impossible to create the 3D objects in a vertex-by-vertex way. Maybe there are geeks who are able to define, say 10 kilos of triangles by hand, but I'm not so assiduous to break my fingers on a keyboard.

Fortunately there are much more convenient ways of creating 3D objects. The most convenient of all is probably to download them from Internet ;-) But before we start to use them in the program we have to load them there.
3D objects loaded into the JAVA program

The way I'm about to teach you is that simple:
  • Download 3D object from Internet
  • Import it to the Blender program (http://www.blender.org/)
  • Export it to the .obj format
  • Load it to your program and use it there
Of course you can create the 3D object with Blender (or another 3D editor) by yourself.

The last part of the list can be done surprisingly easily cause the .obj format (http://en.wikipedia.org/wiki/Wavefront_.obj_file) is quite simple and straightforward. I have written the simple loader for you and you are welcome to download it here. Don't worry about the size of the archive - it is so big because it holds four example models for you, so you can just load the projects into Netbeans and run. There are two projects in the archive
  • JOGLObj - the loader itself with the "main" class JOGLObject
  • JOGL - just the example program which shows how to use the JOGLObject

Note you will need java JDK7, and the JOGL library installed and imported to the project (http://jogamp.org/wiki/index.php/Downloading_and_installing_JOGL)


Hope this will help you to create something nice.

Thursday, January 24, 2013

Copy files between Android and PC


In this article I will show you, how you can copy files between PC and an Android device.

If you use some Android device, especially if you are a Linux user, you have probably learned, that it is not any easy, to put some files  from PC on the Android, or copy some files from the Android on your PC.

In this mini 'promotional' article I will introduce you an application, which allows you to copy files between any PC and Android. The application is named AndroidRC (or AndroidRCServer, which is actually an alias). You can install the application from Google Play.

Once it is installed on your Android device, the only thing you have to do is to connect to the server with your web browser. The server will refuse your connection as you have to approve the access for your PC's IP address. So enable the IP on your Android and reload the page in the browser. Now you can work with files on your Android. you can do much more in fact. See the video below.




Hope this will help you.

Monday, January 21, 2013

Android - print all contacts properties


In this article I will show you, how you can print out all the contacts from an Android device.

If you are trying to work with contacts on Android, you have probably learned, that the contacts structure is not any simple there. As a matter of fact it is not any difficult, anyway it may be challenging to figure out, how to work with all the database stuff properly, especially on older versions (<11) of the Android's API.

In short: Contacts are stored in three tables - Contacts, RawContacts and Data. Every Contacts row can be linked in several RawContacts rows and every RawContacts row can be linked in several Data rows. The links are made with ID's. Easy - isn't it?

I encourage you to read the http://developer.android.com/guide/topics/providers/contacts-provider.html document.

Following snippet shows how to print contacts information on the standard output:
 /**
   * Method wich reads user ID's from Contacts table and calls printRaw for all
   * of them
   */
  private void contacts() {
    // ID is only thing, that we are interested in
    String[] projection = new String[] { ContactsContract.Contacts._ID };
    // Get all user IDs
    Cursor cursor = getContentResolver().query(
        ContactsContract.Contacts.CONTENT_URI, projection, null, null, null);
    if (cursor.moveToFirst()) {
      while (!cursor.isAfterLast()) {
        System.out.println("######################");
        printRaw(cursor.getString(cursor
            .getColumnIndex(ContactsContract.Contacts._ID)));
        cursor.moveToNext();
      }
    }
  }
  
  /**
   * For given user ID finds all rows in RawContacts. Then calls printData for
   * all of them
   * 
   * @param _id
   */
  private void printRaw(String _id) {
    //What we are interested in
    String[] projection = new String[] { ContactsContract.RawContacts._ID,
        ContactsContract.RawContacts.ACCOUNT_TYPE,
        ContactsContract.RawContacts.ACCOUNT_NAME };
    Cursor cursor = getContentResolver().query(
        ContactsContract.RawContacts.CONTENT_URI, projection,
        ContactsContract.RawContacts.CONTACT_ID + " = ?", new String[] { _id },
        null);
    if (cursor.moveToFirst()) {
      while (!cursor.isAfterLast()) {
        System.out.println("======="
            + cursor.getString(cursor
                .getColumnIndex(ContactsContract.RawContacts.ACCOUNT_NAME))
            + "@"
            + cursor.getString(cursor
                .getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE))
            + "=========");
        printData(cursor.getString(cursor
            .getColumnIndex(ContactsContract.RawContacts._ID)));
        cursor.moveToNext();
      }
    }
  }
  /**
   * This one prints all available data for the given RawContact
   * @param _id
   */
  private void printData(String _id) {
    String[] projection = new String[] { ContactsContract.Data.MIMETYPE,
        ContactsContract.Data.DATA1, ContactsContract.Data.DATA2,
        ContactsContract.Data.DATA5, ContactsContract.Data.DATA14,
        ContactsContract.Data.DATA15 };
    Cursor cursor = getContentResolver().query(
        ContactsContract.Data.CONTENT_URI, projection,
        ContactsContract.Data.RAW_CONTACT_ID + " = ?", new String[] { _id },
        null);
    if (cursor.moveToFirst()) {
      while (!cursor.isAfterLast()) {
        String mime = cursor.getString(cursor
            .getColumnIndex(ContactsContract.Data.MIMETYPE));
        if (mime.equals(StructuredName.CONTENT_ITEM_TYPE)) {
          System.out.println("Name: "
              + cursor.getString(cursor
                  .getColumnIndex(StructuredName.DISPLAY_NAME)));
        } else if (mime.equals(Phone.CONTENT_ITEM_TYPE)) {
          System.out.println("Phone: "
              + cursor.getString(cursor.getColumnIndex(Phone.NUMBER)));
        } else if (mime.equals(Email.CONTENT_ITEM_TYPE)) {
          System.out.println("E-mail: "
              + cursor.getString(cursor.getColumnIndex(Email.ADDRESS)));
        } else if (mime.equals(Photo.CONTENT_ITEM_TYPE)) {
          byte[] photo = cursor.getBlob(cursor.getColumnIndex(Photo.PHOTO));
          if (photo != null) {
            System.out.println("Photo: " + photo.length);
          }
        } else if (mime.equals(Organization.CONTENT_ITEM_TYPE)) {
          System.out.println("Organization: "
              + cursor.getString(cursor.getColumnIndex(Organization.COMPANY)));
        } else if (mime.equals(Im.CONTENT_ITEM_TYPE)) {
          System.out.println("Instant messaging: "
              + cursor.getString(cursor.getColumnIndex(Im.PROTOCOL)));
        } else if (mime.equals(Nickname.CONTENT_ITEM_TYPE)) {
          System.out.println("Nick: "
              + cursor.getString(cursor.getColumnIndex(Nickname.NAME)));
        } else if (mime.equals(Note.CONTENT_ITEM_TYPE)) {
          System.out.println("Note: "
              + cursor.getString(cursor.getColumnIndex(Note.NOTE)));
        } else if (mime.equals(StructuredPostal.CONTENT_ITEM_TYPE)) {
          System.out.println("Postal: "
              + cursor.getString(cursor
                  .getColumnIndex(StructuredPostal.FORMATTED_ADDRESS)));
        } else if (mime.equals(GroupMembership.CONTENT_ITEM_TYPE)) {
          System.out.println("Group: "
              + cursor.getString(cursor
                  .getColumnIndex(GroupMembership.GROUP_ROW_ID)));
        } else if (mime.equals(Website.CONTENT_ITEM_TYPE)) {
          System.out.println("Web: "
              + cursor.getString(cursor.getColumnIndex(Website.URL)));
        } else if (mime.equals(Event.CONTENT_ITEM_TYPE)) {
          System.out.println("Event: "
              + cursor.getString(cursor.getColumnIndex(Event.START_DATE))
              + ": " + cursor.getString(cursor.getColumnIndex(Event.TYPE)));
        } else if (mime.equals(Relation.CONTENT_ITEM_TYPE)) {
          System.out.println("Relation: "
              + cursor.getString(cursor.getColumnIndex(Relation.NAME)));
        } else if (mime.equals(SipAddress.CONTENT_ITEM_TYPE)) {
          System.out
              .println("SIP: "
                  + cursor.getString(cursor
                      .getColumnIndex(SipAddress.SIP_ADDRESS)));
        }
        cursor.moveToNext();
      }
    }
  }
Note, that just showed approach follows the contacts structure stupidly and therefore is pretty slow, due to plenty of subsequent database calls. Some more efficient way should be used in a real application - for example list records from the Data table which contains ID's of RawContact same as of the Contact directly in a one shot.

Hope this will help you.

Wednesday, December 19, 2012

Disable text selection in HTML

This is not Android-related, but I do not plan to create a new blog for it:-)
Here is the way how to text selection can be disabled in html. It is usable in case of javascript GUI building.
<body onmousedown="return false">

Tuesday, September 18, 2012

Memory leak when setting Drawable from an AsyncTask

In this article I share my experience with memory leak problem which have relieved me of several hours of my precious time. Maybe I will not tell anything new to you, but maybe I save  someone's minute.

If you are working with ImageView on Android, you probably know, that it is recommended way to update (fill) the ImageView with a Drawable from an AsyncTask, especially in cases that the image for the Drawable have to be downloaded from the Internet first. In the examples below m.photo.getFullSizeImg() represents the method, which downloads the image from Internet and put it into the Drawable object.
During my work I have faced problem with the OutOfMemoryException when I try to start my image -showing-activity several times.

My original, bad one, memory-leak-causing code looked like this:
public class Populator extends AsyncTask<Void, Drawable, Drawable> {
    
    @Override
    protected Drawable doInBackground(Void... params) {
      Drawable preview = null;
      preview = m.photo.getFullSizeImg();
      return preview;
    }
    
    @Override
    protected void onPostExecute(Drawable _preview) {
      imageView.setImageDrawable(_preview);
    }
  }
The problem with this cute code is that variable preview holds the reference to the image Drawable even after onPostExecute() is finished and therefore the garbage collector can't remove the AsyncTask from the memory. So to solve the problem, we have to assign null to the preview variable. that's all and two possible ways of doing it I show bellow.

Well working code using onProgressUpdate() instead of onPostExecute():
public class Populator extends AsyncTask<Void, Drawable, Drawable> {
    
    @Override
    protected Drawable doInBackground(Void... params) {
      Drawable preview = null;
      preview = m.photo.getFullSizeImg();
      publishProgress(preview);
      preview=null;
      return null;
    }
    
    @Override
    protected void onProgressUpdate(Drawable... _preview) {
      imageView.setImageDrawable(_preview[0]);
    }
  }

Another well working code using class variable and onPostExecute():
  public class Populator extends AsyncTask<Void, Void, Void> {
    private Drawable preview = null;
    
    @Override
    protected Void doInBackground(Void... params) {
      preview = m.photo.getFullSizeImg();
      return null;
    }
    
    @Override
    protected void onPostExecute(Void params) {
      imageView.setImageDrawable(preview);
      preview = null;
    }
  }


Hope this will help you.