Featured Posts

Create a Simple Chat Application using Parse BaaS

This tutorial is going to demonstrate step by step how to create a simple chat application on Android 2.2 and above, with instant messaging, online user detection and new message notification using Parse.com Backend as a service.

I.> Create a new project

Open Eclipse (with Android SDK environment set up) and create a new Android Project.

For persistence,

Application Name: ParseChat

ProjectName: ParseChat

Package Name: example.chat

Create a new blank activity. Let’s say LoginActivity.

Some versions of Eclipse would automatically generate the corresponding layouts for the main view and the menu. If not, you’ll have to create new xml files in the corresponding folders in /res

II.> Designing GUI View:

There are 3 views needing to be mentioned: Login, Register, FriendList, and the Chat View. Let’s call the respective Activities for them LoginActivity (already created), RegisterActivity, FriendListActivity and ChatActivity.

Layout for login activity:

—————-

<?xml version=”1.0″ encoding=”utf-8″?>
<ScrollView xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:fillViewport=”true” >

<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical”
android:padding=”10dip” >

<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/username”
android:textColor=”#372c24″ />

<EditText
android:id=”@+id/login_email_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginBottom=”20dip”
android:layout_marginTop=”5dip”
android:hint=”@string/username”
android:singleLine=”true” />

<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/password”
android:textColor=”#372c24″ />

<EditText
android:id=”@+id/login_password_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”5dip”
android:hint=”@string/password”
android:inputType=”textPassword”
android:singleLine=”true” />

<Button
android:id=”@+id/btnLogin”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”10dip”
android:text=”@string/login” />

<TextView
android:id=”@+id/link_to_register”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginBottom=”40dip”
android:layout_marginTop=”10dip”
android:gravity=”center”
android:text=”@string/register”
android:textSize=”18dip” />
</LinearLayout>

</ScrollView>

—————-

Layout for register activity

—————-

 

<?xml version=”1.0″ encoding=”utf-8″?>
<ScrollView xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:fillViewport=”true” >

<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical”
android:padding=”10dip” >

<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/username”
android:textColor=”#372c24″ />

<EditText
android:id=”@+id/login_email_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginBottom=”20dip”
android:layout_marginTop=”5dip”
android:hint=”@string/username”
android:inputType=”textEmailAddress”
android:singleLine=”true” />

<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/password”
android:textColor=”#372c24″ />

<EditText
android:id=”@+id/login_password_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”5dip”
android:hint=”@string/password”
android:inputType=”textPassword”
android:singleLine=”true” />

<Button
android:id=”@+id/btnLogin”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”10dip”
android:text=”@string/login” />

<TextView
android:id=”@+id/link_to_register”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginBottom=”40dip”
android:layout_marginTop=”10dip”
android:gravity=”center”
android:text=”@string/register”
android:textSize=”18dip” />
</LinearLayout>

</ScrollView>

—————-

Layout for Friend List

—————-

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
xmlns:tools=”http://schemas.android.com/tools&#8221;
android:layout_width=”match_parent”
android:layout_height=”match_parent” >

<ListView
android:id=”@+id/friendlist”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical” />

</RelativeLayout>

—————-

Layout for Chat

—————-

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:orientation=”vertical” >

<ScrollView
android:layout_width=”fill_parent”
android:layout_height=”0dip”
android:layout_weight=”1″ >

<TextView
android:id=”@+id/chat_output_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:paddingLeft=”5dp”
android:paddingRight=”5dp”
android:paddingTop=”5dp” />
</ScrollView>

<LinearLayout
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:baselineAligned=”true”
android:orientation=”horizontal”
android:paddingBottom=”5dp”
android:paddingLeft=”5dp”
android:paddingRight=”5dp” >

<EditText
android:id=”@+id/chat_input_txt”
android:layout_width=”0dip”
android:layout_height=”60dip”
android:layout_weight=”1″
android:gravity=”top”
android:inputType=”textMultiLine”
android:scrollHorizontally=”false” >

<requestFocus>
</requestFocus>
</EditText>

<Button
android:id=”@+id/chat_send_btn”
android:layout_width=”80dp”
android:layout_height=”45dp”
android:text=”@string/send” >
</Button>
</LinearLayout>

</LinearLayout>

—————-

III.> Permission for Parse

Parse will need some specific permissions in order to run. Add the following lines into your manifest files, right before the <application> tag.

<uses-permission android:name=”android.permission.INTERNET” />
<uses-permission android:name=”android.permission.RECEIVE_BOOT_COMPLETED” />
<uses-permission android:name=”android.permission.VIBRATE” />
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />

IV.> Adding a model into your Android application

1> Model Interface

The model Interface contains all the methods and functions which will be called by the activities.

—————-

public interface Model {
LinkedList<ParseUser> getUsers();
HashMap<String, String> getChatMessages();
String getChannel();
boolean isAuthenticated();
void logout();
void updateUserList();
void sendChatMessage(String userKey, String message);
void login(String username, String password) throws Exception;
void register(String username, String password, String confirm) throws Exception;
void updateUserTracking();
}

—————-

2.> Implementing the model interface

We are going to write a subclass of the Application class to persist data. This class will be implementing the Model interface.

Declaring some static variables and constants:

public class ChatApplication extends Application implements Model {
private static final String APP_ID = “LO6YE92er8izDGLEvBzHUFbO1VrD7a1tRFBp85Ih”;
private static final String CLIENT_KEY = “U1w2aGIoNbkwdGrw5jniGWB9ADBUejO3qtz4dR4l”;
private static LinkedList<ParseUser> users;
private static HashMap<String, String> chatMessages;
private static String channel = “”;
private static ParseUser user = null;
private static PendingIntent pIntent;
private static AlarmManager alarm;
}

Override onCreate()

@Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, ChatApplication.APP_ID, ChatApplication.CLIENT_KEY);
ParseACL acl = new ParseACL();
acl.setPublicReadAccess(true);
ParseACL.setDefaultACL(acl, true);
users = new LinkedList<ParseUser>();
chatMessages = new HashMap<String, String>();
Intent sIntent = new Intent(this, UpdateService.class);
pIntent = PendingIntent.getService(this, 0, sIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
logout();
startTracking();
}

 Implement some simple functions

public LinkedList<ParseUser> getUsers() {
return users;
}

public HashMap<String, String> getChatMessages() {
return chatMessages;
}

public String getChannel() {
return channel;
}

public boolean isAuthenticated() {
return (user != null && user.isAuthenticated());
}

Authentication with Parse

public void login(String username, String password) throws Exception {
username = username.trim().toLowerCase();
validateCredentialsFormat(username, password);
ParseUser.logIn(username, password);
startTracking();
}

public void logout() {
if (user != null) {
ParseUser.logOut();
}
stopTracking();
}

Register a new user with Parse

public void register(String username, String password, String confirm) throws Exception {
username = username.trim().toLowerCase();
validateCredentialsFormat(username, password);
if (!password.equals(confirm)) {
throw new Exception(“Confirmation does not match”);
}
// Registration
ParseUser newUser = new ParseUser();
newUser.setUsername(username);
newUser.setPassword(password);
newUser.signUp();
startTracking();
}

Update the user list

public void updateUserList() {
ParseQuery query = ParseUser.getQuery();
// Only users with the last activities within 5 minutes
Date queryDate = new Date((new Date()).getTime() – 300000);
query.whereGreaterThan(“lastUpdate”, queryDate);
try {
List<ParseObject> list = query.find();
users.clear();
for (ParseObject o : list) {
users.add((ParseUser) o);
}
} catch (ParseException e) {
}
}

Send chat messages using Push Notification

public void sendChatMessage(String target, String message) {
try {
ParsePush push = new ParsePush();
push.setChannel(target);
push.setExpirationTimeInterval(86400);
push.setData(new JSONObject(“{” +
“”action”:”example.chat.MESSAGE”,” +
“”from”:”” + channel + “”,” +
“”to”:”” + target + “”,” +
“”message”:”” + message + “”}”));
push.sendInBackground();
} catch (JSONException e) {
}
}

Some private functions

private void validateCredentialsFormat(String username, String password) throws Exception {
// Some validations
if (username.length() * password.length() == 0) {
throw new Exception(“All fields must be filled”);
}
// The username should not be so complicated
if (!username.matches(“^([A-Za-z]+[A-Za-z0-9_]*)$”)) {
throw new Exception(“Username must start with a letter, and should only contain alphanumeric characters and underscores”);
}
}

private void startTracking() {
stopTracking();
ParseUser usr = ParseUser.getCurrentUser();
if (usr != null && usr.isAuthenticated()) {
channel = usr.getUsername();
user = usr;
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, pIntent);
}
}

private void stopTracking() {
channel = “”;
user = null;
alarm.cancel(pIntent);
}

public void updateUserTracking() {
if (user != null && user.isAuthenticated()) {
user.put(“lastUpdate”, new Date());
user.saveEventually();
}
}

3.> Auto update user’s states and auto refreshing

We have to update the current user’s information and retrieve the new information constantly (which I suggest every 4 minutes) so other users can retrieve the latest states of their friends. This is going to be achieved by calling updateUserTracking() function from the model using a service. An AlarmManager will be used for the timing. The timing is triggered in startTracking() and stopped in stopTracking()

public class UpdateService extends Service {

private Model model;

public UpdateService() {
model = (ChatApplication) getApplication();
}

@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
model.updateUserList();
model.updateUserTracking();
}

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

V.> The activities

The activities in Android are like the controllers in MVC. The activities receives the inputs from the XML layout, use the implemented model to perform certain tasks corresponding with certain events.

 

 

 

Standard

One thought on “Create a Simple Chat Application using Parse BaaS

Leave a comment