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.