Latest Entries

Tags

Links

Unix/Linux Stuff: pipe, shared memory & more fork

fork() allows a process/program to duplicate itself to create a brand new process. This process is basically a child of the calling process (parent). The child has its own process ID which gets returns to the parent upon creation while it returns 0 on its own process. Let's say we created:

int main(){
   printf("I am parent. My PID is: %d\n", getpid());
   int pid = fork();
   if(pid == 0){
      printf("I am child. My PID is %d\n", getpid());
      exit(0);
   } else {
      printf("My child's PID is: %d\n", pid);
   }
   return 0;
}

The code above may print something like this:

I am parent. My PID is: 29321
My child's PID is: 29322
I am child. My PID is 29322

But there is something to this that we must keep in mind. The termination process must be in sequence: child must die first, then parent - its calling process. If parent dies first, then child becomes a zombie. A zombie is a process that doesn't have a parent. When a child quits, it reports its termination to its parent. If no parent waits to collect the exit status of the child, it gets confused and becomes a ghost process that can be seen as a process but not killed. The child process remains in memory as a zombie. Eventually, as more zombies spawn, it takes up more resources which eventually leads to crashes, etc. In order to avoid this from happening, we must make the parent wait. Thankfully, there is a simple command called wait(). We use it like this:

int main(){
   printf("I am parent. My PID is: %d\n", getpid());
   int pid = fork();
   int wait;
   if(pid == 0){
      printf("I am child. My PID is %d\n", getpid());
      exit(0);
   } else {
      printf("My child's PID is: %d\n", pid);
   }
   wait(&status);
   return 0;
}

wait() stores the status information to status, it returns the process ID of the terminated child, and -1 on error as usual. Now, parent waits for child to end, the whole program ends in sequence.

Shared memory is a way for parent and child to share data or use the same portion of memory. It's very easy to use:

main()
{
   int* i, status, id;
   id=shmget((key_t)IPC_PRIVATE,4,0666|IPC_CREAT);
   i=(int *)shmat(id,0,0);
   *i=4;
   printf("Parent *i is %d\n",*i);
   if(!fork()){
      int* j;
      j=(int *)shmat(id,0,0);
      printf("Child *j is %d\n",*j);
      (*j)++;
      printf("Child *j is %d\n",*j);
      shmdt(j);
      exit(0);
   }
   //wait(&status);
   (*i)++;
   printf("Parent *i is %d\n",*i);
   shmdt(i);
}

There are three functions you must use for shared memory:

  • shmget() - allocates a shared memory segment. The first argument accepts a key_t value. IPC_PRIVATE is a special key value used to create a new memory segment. The IPC_PRIVATE name is a bit confusing considering that it is to be used to create new memory segment. This is apparently a bug for poor choice of name because IPC_NEW would clearly make more sense. The next argument is the number of bytes we want the shared memory to have. Since we are going to share an integer, we pass 4 to it - since an int is worth 4 bytes. Finally the last argument is the permission for new segment. On success, shmget() returns the ID to the shared memory, -1 on fail.
  • shmat() - this function is used to attach ourselves to the shared memory. We use the int pointer i we created to point to the address of shared memory. The first argument of shmat() is the ID of shared memory, the last two are used for more complex ones that accept shared memory address and flags. We pass 0 to those since we're not gonna use them. shmat() returns -1 on fail, or pointer to the shared memory on success.
  • shmdt() - finally, this function is used to detach ourselves to the shared memory. It only accepts an ID to the shared memory. Returns 0 on success, -1 otherwise.

Notice that I commented out wait(). Our expected output should be something like this:

Parent *i is 4
Child *j is 4
Child *j is 5
Parent *i is 6

But since we don't wait for the child the die, the output may be different than we expect. The parent may print the second printf() first before the child could and such like that. On the top of that, zombie processes will get created. That is why it is essential that we must keep the termination order of parent and child in proper sequence, or unexpected results may occur.

Another way for parent and child to share or pass data to one another is with the use of pipe(). Think of a pipe in a literal way - a tunnel that can be used for various things, such as a tunnel between a parent and child process!

int main() {
   int bytes_processed;
   int pipefd[2];
   char datapassed[] = "123";
   char buffer[BUFSIZ + 1] = "";
   int fork_result;
   if (pipe(pipefd) == 0) {
      if ((fork_result = fork()) == 0) {
         bytes_processed = read(pipefd[0], buffer, BUFSIZ);
         printf("Read %d bytes: %s\n", bytes_processed, buffer);
         exit(EXIT_SUCCESS);
      }
      else if (fork_result > 0) {
         bytes_processed = write(pipefd[1], datapassed, strlen(datapassed));
         printf("Wrote %d bytes\n", bytes_processed);
         exit(EXIT_SUCCESS);
      }
   }
   exit(EXIT_FAILURE);
}

The first thing we must have is an array that will hold two file descriptors: pipefd[2] - one for reading, and the other for writing. To create a pipe, simply call the pipe() function and pass that pipefd array. pipefd[0] contains file descriptor for reading, and pipefd[1] for writing. As you can see inside the child, we use the function we are familiar with: read() - read() is more or less the same as recv(), it accepts a file descriptor, buffer for reading, and the max size to read. Since the child is an exact copy of the parent, it should have the pipe that we created in the parent. We use the reading side of the pipe, pipefd[0]. The child will basically read whatever the parent writes to the writing side of the pipe. On the parent side, we have write(), which is again more or less the same as send().

Note that pipes can be used in many various things. Just as you use pipes in commands (eg. ls | wc), this is pretty much the coding side of it.

That's all, I hope you like it~

Unix/Linux Stuff: sockets, client/server, fork

New tutorial for everyone, especially for linux/unix fans. Creating and using sockets in unix is really fun and easy. It's easy if you take things for granted, but complex if you look at it in greater depth. What I mean by that is even though printf() is as easy as printing something, there are actually a lot of things going on with it. printf() is actually just wrapper for more low level lines of codes - machine language if you try to look at it in deeper level. But for now, let's look at printf() at unix/linux level. If you run the command strace printf, you will see a list of more commands or functions that the printf() calls in order to simply just print something. Most of these functions are unix/linux functions - some of them are probably you are familiar with, like open(), close(), write() and more. You can say that Unix/linux sockets are on the same level as those commands/functions.

Without further due, here are the source codes:

Let's start with the client.

Three important libraries we have to include:

  • sys/types.h - contains definitions of a number of data types used in system calls. These types are used in the next two include files.
  • sys/socket.h - includes a number of definitions of structures needed for sockets.
  • netinet/in.h - contains constants and structures needed for internet domain addresses.
struct sockaddr_in server = {AF_INET, MYPORT};

In the line above, we need to create a variable of struct sockaddr_in type that contains information about the server we are connecting to. AF_NET represents the address family (hence AF) for internet sockets (hence INET) for IPv4 protocol. If we are to connect to an IPv6 protocol, we would use AF_INET6. And finally, MYPORT is the port number.

server.sin_addr.s_addr = inet_addr("127.0.0.1");

sockaddr_in has a member sin.addr.s_addr which essentially will contain the address we are going to connect to.

   if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
      perror("socket call failed");
      exit(1);
   }

Next is we finally create a socket using the socket() function. The function has three arguments: domain, type and protocol. The domain argument basically selects the protocol family which will be used for communication, we'll use AF_INET. The type argument specifies the communication semantics. Since we want a two-way, connection-based byte streams, we'll pass the defined type SOCK_STREAM. Finally the protocol argument specifies a particular protocol to be used with the socket. Normally only a single protocol exists to support a particular socket type within a given protocol family, in which case protocol can be specified as 0. However, it is possible that many protocols may exist, this is where we'll specify it. socket() returns the file descriptor on success, -1 otherwise.

   if(connect(sockfd, (struct sockaddr *)&server, SIZE) == -1){
      perror("connect call failed");
      exit(1);
   }

connect() function as you might have guessed initiate a connection on a socket. The function has three arguments: socket file descriptor, sockaddr struct and its length. Since we're going to use the socket we just created, we pass its file descriptor. We will also pass the struct of the server (contains information about the server we are going to connect to), and finally the size of it (which is essentially sizeof(struct sockaddr_in)).

   for(rc='\n';;){
      if(rc == '\n')
         printf("Input a lowercase character\n");
      c = getchar();
      send(sockfd, &c, 1, 0);
      
      if(recv(sockfd, &rc, 1, 0) > 0)
         printf("%c", rc);
      else{
         printf("server has died\n");
         close(sockfd);
         exit(1);
      }
   }

We are then get into endless loop where we send a character to the server and receive back an upper-cased one. send() function has four arguments. First one is the socket file descriptor, next is the address to our character variable, the amount size to be sent is followed by it (1 since we are only sending one character), and finally an optional flag - we'll set it to 0 since we're not going to use it. recv() function has very similar way. Both recv() and send() will return -1 on fail, that is if server died, we lose connection, etc.

That's it for the client. Let's go with the server now.

The server has implementation of basic signal handling. Please ignore lines 19 to 21 for now, or you can research it your own. The server is more or less similar to the client because we need to create a socket for it as well. But minor change for the sockaddr_in struct: struct sockaddr_in server = {AF_INET, MYPORT, INADDR_ANY};. Pretty self-explanatory, INADDR_ANY - meaning it can be any address, we don't specify any since this is going to be the server, therefore, we accept any address.

   if(bind(sockfd, (struct sockaddr *)&server, SIZE) == -1){
      perror("bind call failed");
      exit(1);
   }
   if(listen(sockfd,5) == -1){
      perror("listen call failed");
      exit(1);
   }

Two new functions for the server: bind() and listen(). When a socket is created with socket(), it exists in a name space (address family) but has no address assigned to it. bind() assigns the address specified in sockaddr_in struct to the socket referred to by the file descriptor sockfd. The last parameter specifies the size, in bytes, of the address structure pointed to by sockaddr_in struct (eg. sizeof(sockaddr_in struct). Traditionally, this operation is called "assigning a name to a socket". listen() marks the socket to be used to accept incoming connection. Its last parameter defines the maximum length to which the queue of pending connections for the socket may grow - let's set it to 5. As usual, these two functions returns -1 on fail.

   while(1){
      if((newsockfd=accept(sockfd, NULL, NULL)) == -1){
         perror("accept call failed");
         continue;
      }
      
      if(fork() == 0){
         while(recv(newsockfd, &c, 1, 0) > 0){
            c = toupper(c);
            send(newsockfd, &c, 1, 0);
         }
         close(newsockfd);
         exit(0);
      }
      
      close(newsockfd);
   }

accept() function accepts a connection to the socket. It waits for incoming connections - the program basically "pause" on this function until someone connects to our server. On success, it returns a file descriptor to the accepted socket. We use fork() to create a child process of the program - an exact copy of the server, including its variables (such as newsockfd), objects, functions, etc. We need this so we can handle multiple connections, one child for each connections/clients. Everything inside if(fork() == 0) is run by the child! The fork() function returns 0 in the child process, and the fork() in parent process returns the process ID of the child. So if we do if(fork() == 0), then we know that inside that if statement, we are in child process. Then as usual we use the functions recv() for receiving something from the client and send() for sending something back to the client. Finally, we use close() to close the socket to the client as soon as we are done. We do the same for the parent (outside of if(fork() == 0)), we also close the connection of newsockfd because we'll need it for incoming new ones.

fork() is very essential if we want a server that accepts multiple connections/clients. Without it, our server would only accept one client. fork() can be confusing for those who are not familiar with threads or similar to that, but keep in mind that as soon as we call the fork() function, it creates an exact copy of the program (a child process to be more specific). Then it runs that program on that exact line where you called the fork() function.

Anyway, that's all for now. Hope you like it! =D

Android Development Part 4: Source Codes

Wow, it's been a while since my last post. I apologize for that, school has been really busy and took a lot of my free time. Now that exams are over, I can finally make use of my time for something more useful. Freedom for two weeks, yay.

First of all, as the title says, this post contains some useful Android source codes that can help you visualize how some of my tutorials are coded - I know I should've done this long time ago but oh well. The source codes are exports from Eclipse. Most of them need at least Android 4.0.3 (10) snapshot I believe, but to be in the safe side, make sure you have all 4.* and 2.* installed as your emulator/compiler. Also feel free to change the Android version in the manifest file. In order to import my source codes to your Eclipse, just go to File, then Import. In Import window, expand General and choose "Existing Projects into Workspace". Select archive file, click Next then Finish. Sometimes, Eclipse will complain about having errors, even though it doesn't. I don't know why Eclipse does this almost each time I import, maybe it's a bug on Eclipse's side. But if it does, try to clean the project by going to Project, then Clean. If not, try to delete the project and import again. It usually fixes it that way for some reason...

Below are the source codes, check them out:

As you noticed, these are directly from my class. Since my class encourages open source, the professor doesn't mind posting my source codes - or even sell them. In any case, enjoy. I'm sure a lot of people will learn more by looking at the source codes rather than reading long boring tutorials like mine.

Android Development Part 3: Content Provider

This tutorial assumes that you know how to make basic Activity and know how SQL works. On this tutorial, we are going to look at Content Providers. Content providers manage access to a structured set of data. They encapsulate the data, and provide mechanisms for defining data security. In other words, Content Provider is Android's way of storing data. Android can store data in many ways:

  • Files
  • SQLite database
  • On the web
  • Any other persistent storage location your application can access

Each content provider exposes a public URI (wrapped as a Uri object) that uniquely identifies its data set. All URIs for providers begin with the string "content://". Android defines CONTENT_URI constants for all the providers that come with the platform. If we store data on the web, it can be "http://" or "ftp://", depending on the protocol of course. For now, we will work with Android's internal db - SQLite.

To create a content provider, we must create a class that extends ContentProvider. On the top of that, we must override a few methods of the ContentProvider class.

public class etrter extends ContentProvider {

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}

}

After that, we must add a couple of member static variables:

	public static final String PROVIDER_NAME = "cs.elc.w12.provider.CoolProverbs";
	public static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/proverb");
	public static final String _ID = "_id";
	public static final String CONTENT = "proverb";
	public static final String ORIGIN = "proverb_origin";
	public static final String TIME = "time"; 
	   
	private static final int PROVERBS = 1;
	private static final int PROVERBS_ID = 2;
	private static final UriMatcher uriMatcher;
	static {
		uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		uriMatcher.addURI(PROVIDER_NAME, "proverb", PROVERBS);
		uriMatcher.addURI(PROVIDER_NAME, "proverb/#", PROVERBS_ID);
	}
	   
	private SQLiteDatabase proverbsDB;
	private static final String DATABASE_NAME = "Proverbs";
	private static final String DATABASE_TABLE = "proverbsList";
	private static final int DATABASE_VERSION = 1;
	private static final String DATABASE_CREATE = "CREATE TABLE " + DATABASE_TABLE + " (" + _ID + " INTEGER PRIMARY KEY, " +
	   										"proverb TEXT NOT NULL, proverb_origin TEXT NULL, time TEXT NULL);";
                                    
  • PROVIDER_NAME is the name of our provider. We also use this for the URI and many various things.
  • CONTENT_URI is the full URL to our content provider.
  • _ID, CONTENT, ORIGIN and TIME are column names of the table.
  • PROVERBS and PROVERBS_ID are unique integers for this content provider.
  • proverbsDB is a SQLiteDatabase variable type. This is what we mainly use to deal with the SQLite database.
  • DATABASE_NAME, DATABASE_TABLE, DATABASE_VERSION, DATABASE_CREATE are all database related stuff.

We also need to create a DatabaseHelper that will help us deal with SQLite. Create an inner class called DatabaseHelper which extends SQLiteOpenHelper class.

	private static class DatabaseHelper extends SQLiteOpenHelper {
		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL(DATABASE_CREATE);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
			onCreate(db);
		}
	}

First, we implement the DatabaseHelper constructor, we must also call the parent constructor and pass the context. We override two methods: onCreate() and onUpgrade(). I wouldn't tell much details about this, but let's assume that this helper class will create the database for us if it doesn't exist.

Now, let's implement the delete() method.

	public int delete(Uri arg0/* uri */, String arg1/* selection */, String[] arg2/* delectionArgs */) {
	      int count = 0;
	      switch(uriMatcher.match(arg0)) {
	         case PROVERBS:
	            count = proverbsDB.delete(DATABASE_TABLE, arg1, arg2);
	            break;
	         case PROVERBS_ID:
	            String id = arg0.getPathSegments().get(1);
	            count = proverbsDB.delete(DATABASE_TABLE, _ID + " = " + id +
	                  (!TextUtils.isEmpty(arg1) ? " AND (" + arg1 + ")" : ""), arg2);
	            break;
	         default:
	            throw new IllegalArgumentException("Unknown URI: " + arg0);
	      }
	      getContext().getContentResolver().notifyChange(arg0, null);
	      return count;
	}

The first argument of this method is the uri, second is the selection, third are the things to be deleted. We use switch to see if the first argument being pass is a PROVERBS (all data in table) or PROVERBS_ID (a specific data in the table, ID of a data). As you can see, we use proverbsDB's delete() method to delete data from SQLite. The getContext().getContentResolver().notifyChange() notifies the changes. We can catch this from the Activity side, but to keep things simple, let's leave this alone.

Now, let's implement onCreate()

	public boolean onCreate() {
	      Context context = getContext();
	      DatabaseHelper dbHelper = new DatabaseHelper(context);
	      proverbsDB = dbHelper.getWritableDatabase();
	      return (proverbsDB == null) ? false : true;
	}

getContext() returns whatever this is currently running in. We need to pass this context to the database helper that we created. Now, getWritableDatabase() grabs the database. It should create it if it doesn't exists. In either case, the onCreate() method will return true or false, depending on the status.

Now, let's implement getType()

	public String getType(Uri uri) {
		switch(uriMatcher.match(uri)) {
		case PROVERBS:
			return "vnd.android.cursor.dir/vnd.ecl.proverb";
		case PROVERBS_ID:
			return "vnd.android.cursor.item/vnd.ecl.proverb";
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}
	}

getType() method handles the MIME type of the data at the given URI. On this case, we return "vnd.android.cursor.dir/vnd.ecl.proverb" for PROVERBS for multiple items and we return "vnd.android.cursor.item/vnd.ecl.proverb" for PROVERBS_ID for a single item. As you can see, the one with "dir" are for multiple items and "item" for single item. See this to learn more about it.

Now, let's implement insert()

	public Uri insert(Uri uri, ContentValues values) {
		long rowID = proverbsDB.insert(DATABASE_TABLE, "", values);

		// if added successfully
		if (rowID > 0) {
			Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
			getContext().getContentResolver().notifyChange(_uri, null);
			return _uri;
		}
		throw new SQLException("Failed to insert row into " + uri);
	}

The same way we handle delete, we also use proverbsDB's method - on this case, insert(). We notify for changes and we return the uri of the inserted data. Throw an SQLException otherwise.

Now, let's implement query

	public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
			String arg4) {
		SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder();
		sqlBuilder.setTables(DATABASE_TABLE);
		if(uriMatcher.match(arg0) == PROVERBS_ID) {
			sqlBuilder.appendWhere(_ID + " = " + arg0.getPathSegments().get(1));
		}
		if(arg4 == null || arg4 == "") {
			arg4 = CONTENT;
		}
		Cursor cursor = sqlBuilder.query(proverbsDB, arg1, arg2, arg3, null, null, arg4);
		cursor.setNotificationUri(getContext().getContentResolver(), arg0);
		return cursor;
	}

The query() method returns a Cursor object. This cursor object is what we'll use to move around the returned result after querying something. We use SQLiteQueryBuilder to run a query. SQLiteQueryBuilder's query() method returns a Cursor object, which we then return.

Finally, let's implement update() method

	public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
		int count = 0;
		switch (uriMatcher.match(arg0)) {
		case PROVERBS:
			count = proverbsDB.update(DATABASE_TABLE, arg1, arg2, arg3);
			break;
		case PROVERBS_ID:
			String id = arg0.getPathSegments().get(1);
			count = proverbsDB.update(DATABASE_TABLE, arg1, _ID + " = " + id +
					(!TextUtils.isEmpty(arg2) ? " AND (" + arg1 + ")" : ""), arg3);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI: " + arg0);
		}
		getContext().getContentResolver().notifyChange(arg0, null);
		return count;
	}

Very similar way as insert() and delete() methods, the only difference is that we have an argument of what needed to be updated.

Now that we have completed the ContentProvider object, the Activity side should be pretty straight forward. To insert data, we must create ContentValues variable which will hold the data to be inserted.

    	ContentValues values = new ContentValues();
       
    	values.put(MyProverbsProvider._ID, "1");
    	values.put(MyProverbsProvider.CONTENT, "Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime");
    	values.put(MyProverbsProvider.ORIGIN, "Asian - Chinese");
       	values.put(MyProverbsProvider.TIME, "Unkown");

We then use the insert() method from getContentResolver() to insert it

getContentResolver().insert(MyProverbsProvider.CONTENT_URI, values);

getContentResolver() returns whatever content provider it is available in a package. On this case, it should return the ContentProvider that we have created.

To grab data, we do the following

        Cursor cursor = managedQuery(MyProverbsProvider.CONTENT_URI, null, null, null, "_id");
        if (cursor.moveToFirst()) {
        	do {
        		Toast.makeText(this,
                    "Content: " + cursor.getString(cursor.getColumnIndex(MyProverbsProvider.CONTENT)) + "\n" +
                    "Origin: " + cursor.getString(cursor.getColumnIndex(MyProverbsProvider.ORIGIN)) + "\n" +
                    "Time: " + cursor.getString(cursor.getColumnIndex(MyProverbsProvider.TIME)) + "\n" + 
                    "ID: " + cursor.getString(cursor.getColumnIndex(MyProverbsProvider._ID)) + "\n"
                    , Toast.LENGTH_LONG).show();
           } while (cursor.moveToNext());
        }

managedQuery() returns the cursor from query() of the content provider we created. We then use cursor's moveToFirst() and moveToNext() methods to traverse on each data in the table.

That's all for Content Provider, hope you enjoy! I'll post the source codes soon, so stay tune! For now, feel free to explore the web for more tutorials and information.

Android Development Part 2: Service

This tutorial assumes that you know how to make basic Activity. On this tutorial, we are going to tackle how to make and run Services. A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use. In simple terms, it's an application that runs in background.

There are two types of Service: started and bound. A started service is when an application component (such as an Activity) starts it by calling startService(). A Bound service is when an application component binds to a service by calling bindService().

service_lifecycle.png

The way you create a service is very similar way you create an activity. You must create a class that extends Service.

public class MyService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public void onCreate() {
		Toast.makeText(this, "Service created", Toast.LENGTH_LONG).show();
	}

	@Override
	public void onDestroy() {
		Toast.makeText(this, "Service destroyed", Toast.LENGTH_LONG).show();
	}

}

If you noticed, returned null in the onBind() method. It's to make a distinction that this is a started service and not a bound one. The way you run a service is similar to the way you run an Activity:

Intent intent = new Intent(this, MyService.class);
startService(intent);

We create an intent object, passing 'this' in the parameter as we want the service to run in "this" Activity. The second parameter is the Service class itself. We can exit the application, and the service will still continue to run! We can stop an activity by using another method called stopService().

Intent intent = new Intent(this, MyService.class);
stopService(intent);

Again, we must pass an intent object to the stopService() method.

A Bound service is more complex. We must also extend from the Service class, but this time, we must make it a Bound service.

public class MyBound extends Service {

   private final IBinder mBinder = new LocalBinder();
    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
   public class LocalBinder extends Binder {
    	MyBound getService() {
         // Return this instance of LocalService so clients can call public methods
    		return MyBound.this;
      }
   }

   @Override
   public IBinder onBind(Intent intent) {
      return mBinder;
   }

}

As you can see, we created an inner class called LocalBinder, which extends the Binder class. The class has a method called getService(), which returns MyBound service itself, of Binder class.

In the Activity part of the application, we have to do quite a few tedious things. First, we'll need to create three member variables type MyBound (our bound service), a boolean which keeps track if the application has binded to the service or not, and finally a ServiceConnection variable that defines callbacks for service binding.

   MyBound mService;
   boolean mBound = false;
   private ServiceConnection mConnection = new ServiceConnection() {
      public void onServiceConnected(ComponentName className,
                IBinder service) {
         // We've bound to LocalService, cast the IBinder and get LocalService instance
         LocalBinder binder = (LocalBinder) service;
         mService = binder.getService();
         mBound = true;
      }

      public void onServiceDisconnected(ComponentName arg0) {
         mBound = false;
      }
   };

mConnection is a ServiceConnection object which overrides the onServiceConnected() and onServiceDisconnected() methods. In onServiceConnected() method, binder (LocalBinder) calls getService() which returns the bounded service that we created, finally sets mBound to true (note that we set this to false in onServiceDisconnected() )

Finally, in the onStart() and onStop() methods, we do the following:

   @Override
   protected void onStart() {
      super.onStart();
      // Bind to LocalService
      Intent intent = new Intent(this, MyBound.class);
      bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
      Toast.makeText(this, "onStart: Bind to LocalService", Toast.LENGTH_SHORT).show();
    }
    
    @Override
   protected void onStop() {
      super.onStop();
      // Unbind from the service
      if (mBound) {
         unbindService(mConnection);
         mBound = false;
         Toast.makeText(this, "onStop: Unbind from the service", Toast.LENGTH_SHORT).show();
      }
   }

We create an Intent object for our MyBound bound service. Then we pass it to the bindService() class which finally runs it. mConnection is our ServiceConnection variable type which is responsible for callbacks and connection between the bound service and application. We pass it to unbindService() method if we wish to unbind the bound service itself from the application.

If we wish to run a method from the bound service, we simply do the following:

mService.METHODNAME();

That's all for this tutorial! Please see the Android Developers site for more information.

Android Development Part 1: Activity

I was inspired by my professor of ECL500 class, Jordan Anastasiade, to make this blog post about Android Development. As you are aware, Android apps are developed in Java. As long as you know the basics of Java development, you shouldn't have problems developing apps for Android. There are, however, a couple of new conventions you need to learn and get familiar with before you can develop one. First of all, we will be developing apps in Eclipse. So I suggest that you download the latest version of Eclipse Classic (Indigo).

After that, you will need to download and install the Android SDK. Finally, you will need to install the Android ADT plugin in Eclipse. For more information, please follow this tutorial starting from Step 3. After you have set everything up, you will need to install a couple of packages from the Android SDK manager. Please install everything under "Tools" and "Android 4.0.3 (API 15)" - we will be developing apps using the latest version of Android. The following packages are essential throughout this tutorial and future ones:

  • SDK Platform
  • Documentation for Android SDK
  • ARM EABI v7a System Image - this image is needed for the Android emulator!

The first thing we will tackle on this post is Activity. In Android, an Activity is an application component that provides a screen in which users can interact. The following diagram shows the important state paths of an Activity. The square rectangles represent callback methods you can implement to perform operations when the Activity moves between states. The colored ovals are major states the Activity can be in.

activity_lifecycle

To create an activity, one must create a subclass of Activity class. As you can see in the diagram, an activity has a couple of callback methods that the operating system automatically calls on each cycle. These methods are pretty self-explanatory, but in order to work with them, you must override them in a class you create extending the Activity class.

Create a new project in Eclipse:

  1. Click "File" then under "New", click "Project..."
  2. Expand "Android", select "Android Project" then click "Next"
  3. Type a Project Name, then click "Next"
  4. Check "Android 4.0.3" for the build target then click "Next".
    Note: You may choose whatever you wish, it will still work for this tutorial. But please note that newer versions have newer methods and features
  5. Type a Package Name (eg. test.part1), then click "Finish"

Eclipse will create a bunch of files. The important ones are under "src" and "res" directories and the "AndroidManifest.xml" file. Open that one Java file in "src" directory under the package name you made up. There, you should see something similar to this:

package test.part1;

import android.app.Activity;
import android.os.Bundle;

public class TestActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

As you can see, it already override the onCreate() method for you. The first thing it does is call the onCreate() method of the parent. The next line set its content view or the layout of your activity. On this case, it is saying to use the "main" layout, which also Eclipse have created for you.

The main layout is located under the "res" directory, expand it. There, you should see some or all of the following directories:

  • drawable-hdpi
  • drawable-ldpi
  • layout
  • values

Everything under "res" sets the feel and looks of your app. Starting from the resolution of the phone, to the layout and to the values in a layout. Expand the "layout" directory and you should see "main.xml", open it. These layouts are defined in an XML format. But if you open it in Eclipse, it should show you the Graphical view of it.

eclipse_android_mainxml

Eclipse makes it easy for you because you can easily drag and drop buttons, widgets, images, etc. into the layout. Click the "main.xml" tab to see the XML version of it.

Before we can run this app, we need to create our emulator! In Eclipse, click the "Android Virtual Device Manager" icon:

click_emulator_eclipse

It should open the "Android Virtual Device Manager" window. On that window, Click "New" and make up a name. The target of course should be "Android 4.0.3 (API 15)". You may also set the size of the SD Card. After that, click "Create AVD".

Now, let's compile and run this app in the emulator! Do the following:

  1. In Eclipse, click "Run", then click "Run Configurations..."
  2. Double click the "Android Application" at the left-hand side and it should create a new run configuration for you
  3. Click "Browse" and choose the Test project
  4. Click the "Target" tab, then choose the AVD you created.
  5. Click "Apply", then click "Run"!
    NOTE: Please wait for a while to load. The app should be installed to it once it's finished!

Now that we've created and run our first app, is it possible to add more activities to it? The answer is yes! Let's go back to your Test project and create a new Activity class:

  1. Click "File", then under "New", click "Class"
  2. Make up whatever name for your second activity
  3. In "Superclass:", click "Browse..." and search for "android.activity" and select the first result
  4. Make sure that you have "android.app.Activity" as your Superclass, since that's the class we want to extend. Click "Finish"

The new class should roughly contain the following:

package test.part1;

import android.app.Activity;

public class SecondActivity extends Activity {

}

The next step is to create a new layout for this new activity. Do the following:

  1. Under res/layout, right click the directory "layout", then under "New", click "Other"
  2. Expand "Android", choose "Android XML Layout File", then click "Next"
  3. Make up a name, then click "Finish"

This should create a new XML file for layout and open the graphical interface. Try to play around with it, make sure you save it after. If you wish to add a string, you must define it in "strings.xml" file under "values" directory, open it. Go to the XML version of "strings.xml" because it is easier. You should roughly see the following:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="hello">Hello World, TestActivity!</string>
    <string name="app_name">Test</string>

</resources>

Just add another string element, with a unique name for it. If you want to refer to this string in your newly created layout, first of all, you must drag and drop a TextView from widget to the layout. After that, go to the XML version of the layout. You should see the "TextView" element. It should have an attribute called "android:text". Erase all everything in it and add the following: @string/whatever_name_of_your_string - this should refer to the string you created in "strings.xml"

Now that we've customized our newly created layout, we must tell our new activity to use it! We do that by doing the same way as our first activity, we override onCreate() and call the setContentView() method:

public class SecondActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.the_name_of_your_second_layout);
    }
}

We set the content view to our new layout. If the name of our new layout is "second.xml", we pass "R.layout.second" to setContentView() method.

So how do we run this new activity alongside with the existing one? We have two activities! Which activity runs first? This setting is defined under "AndroidManifest.xml" file. In order to use this new activity we created, we must define it first in the "AndroidManifest.xml" file:

  1. Open "AndroidManifest.xml" file
  2. Go to "Application" tab"
  3. Under "Application Nodes", right click and click "Add..."
  4. Double click "Activity", then browse for the new activity you created, choose it
  5. Save and close the "AndroidManifest.xml" file

Now let's open our very first Activity and add the following method inside it:

    public boolean onKeyDown(int keyCode, KeyEvent event) {
       if(keyCode == event.KEYCODE_DPAD_CENTER) {
          Intent newActivity = new Intent(this, SecondActivity.class);
          startActivity(newActivity);
       }
       
       return super.onKeyDown(keyCode, event);
    }

Let me explain what this do line by line. The first line checks for the key that is being pressed. If the center pad is pressed, if statement should be true and therefore run whatever's under it. The next line creates an Intent object. We need to create an Intent object to tell the Android OS that we intend to do something. On this case, we intend to start a new activity when the center key pad is pressed. We use the startActivity() method to run the intent that we have created. This should open the new activity that we have created!

All in all, this is a pretty straight forward tutorial with Android Activity. There are a couple of things I haven't touched such as saving instance state (how to keep the state of your current activity if you decided to open a new one) or creating fragments and use them alongside with Activities. But I leave it up to you if you want to learn more about those two.

NoSQL - MongoDB: The Schemaless Database

I came across this new broad class of database management called NoSQL ("not only SQL"). It's really interesting because it differs in many ways than the classic model of the relational database management system (which sometimes refer to as a "structured storage"). NoSQL databases do not use SQL as their query language - they do not require to have a fixed table schema as well. And they avoid joins most of the time. So why is this good? Why is NoSQL better? Well, there is no "better" database system. I believe that NoSQL is just an alternative for people or companies depending on what they are going to use a database for. The rise of NoSQL database systems roots from the needs of having a better performance and real-time flexibility/web which the traditinoal RDBMS solutions could not cope with. The sacrifice for that is of course consistency and many others. But if other people's needs is to have a better performance and real-time flexibility/web then why not? In this blog post, I'm going to discuss how MongoDB works alongside with PHP, its advantages and as well as its disadvantages.

MongoDB is a NoSQL database. A MongoDB table is often refer to as a "collection". And yes, it is a schemaless collection! Each data that gets inserted to a collection is basically treated as a "document" of its own. In order to use it alongside with PHP, you will need the drive for it. Unfortunately, the MongoDB drive is not available in PHP by default, so you will have to install it manually. I wouldn't get into too much detail as to how to install MongoDB drive for PHP. But if you are using CentOS, all you'll have to do is use the pecl command like this pecl install mongo (of course, make sure that you have the MongoDB server itself installed!), and everything just gets installed and configured like magic (in older versions, I believe you'll have to edit the php.ini file). You may also install it manually by downloading the package, extract, install, configure, etc, but yeah, there are various ways - just research how if you are unsure.

To establish a connection, simply instantiate the Mongo class:

$mongo = new Mongo();

Or you may also instantiate with addresss:

$mongo = new Mongo('127.0.0.1:1111');

Now, you must select a database:

$db = $mongo->rainulfdatabase;
// or we can also use
$db = $mongo->selectDB('rainulfdatabase');

Note that if the database doesn't exists, it will auto create it like magic.

As I mentioned, a MongoDB table is refer to as "collection". Basically, it's a collection of documents. Creating or retrieving a collection is as follows:

$collection = $db->rainulfcollection;
// or like above
$collection = $db->selectCollection('rainulfcollection');

Just like above, it will also create collection you specified if it doesn't exists - like magic! The selectCollection method or its shortcut version should return a MongoCollection object; It throws a MongoConnectionException otherwise.

Inserting data to a collection is really easy! Do something like this:

$names = $db->names; // or $db->selectCollection('names');
$name = array(
    'first_name'=>'Rainulf',
    'last_name' =>'Pineda',
    'website'=>'http://rainulf.ca/'
);
$names->insert($name);

According to the documentation of insert, there is a second optional parameter called 'safe' you can include which accepts boolean or integer. If false (default), the program continues executing without waiting for a database response. If true, the program will wait for the database response and throw a MongoCursorException if the insert did not succeed. In any case, if safe is set to true, the insert returns an array containing the status of the insert, otherwise returns a boolean if array is not empty.

Please note that in every insert, MongoDB includes a unique MongoId object which is typically the primary key in a traditional database. Keep in mind that MongoId is an object! So if you plan to retrieve something by ID, you will have to instantiate a MongoId object and use it instead of a string!

Retrieving is as easy as inserting! MongoCollection has a method called "find" which can help you retrieve data. Do something like this:

$filter = array(
    'first_name'=>'Rainulf'
);
$res = $names->find($filter);
foreach($res as $one) {
    echo $one['first_name'] . "<br />";
    echo $one['last_name'] . "<br />";
    echo $one['website'] . "<br />";
}

To retrieve with ID, you must instantiate a MongoID object with the ID string in its constructor like this:

$name_id = new MongoId("4cffb213726e24640d000000");
$filter = array('_id'=>$name_id);
$name = $names->findone($filter);

Again, check the documentation to learn more about find, findone and MongoId.

The way you use update and remove (or delete) is also the same way or similar as the others. This is what makes MongoDB easy to use, not only it's easy to visualize the data that gets in and out, it's also easy to relate to them because of the use of objects and arrays.

Now, seeing how it has many advantages, one would assume that NoSQL is the thing or "the best". I disagree, it's not the end for traditional databases. Even MongoDB has its disadvantages. One major disadvantage (and perhaps advantage too) with MongoDB and also most NoSQL databases is that datas that gets inserted is stored in the memory. Since it's stored in the memory, the retrieval and insertion of data is way a lot faster - this is actually the secret as to why MongoDB is way a lot faster compare to traditional database like mySQL. But this also means that it's not stored in the harddisk yet - so in case of crash or failure, the chances of data loss is high. There have been a lot of cases in MongoDB with data loss. Limitation in 32-bit systems is also a huge issue in MongoDB. It seems that they've added a 2.5GB limitation of data you're allowed to store. If you are running a 32-bit system and you don't see any reason to upgrade it to 64-bit, then using MongoDB is out of question if you plan to store more than 2.5GB worth of data. I guess it's only a disadvantage for some, but this clearly shows the amount of things they have to sacrifice in order to achieve faster speed and flexibility.

In the end, NoSQL isn't necessarily "the best" but an alternative. While it suits the needs for some, it simply not for others. For companies and individuals that requires mirroring of datas and 0% loss, MongoDB is not a good choice. For others that require consistency of data, schemaless is not a good idea. But for others that requires faster speed and freedom from schemas, then MongoDB or any other NoSQL databases is an option.