Thursday, 30 April 2015

Make WhatsApp Clone Easily Using Kii Cloud

The market for messaging apps is exploding. People are looking for alternatives to standard text messaging. Since the opportunity huge, why not create a messaging app? In this post, we’ll walk you through a bare bones WhatsApp clone (we’ll call it KiiChat) for Android that you can build with minimal effort by leveraging Kii Cloud. Good news is that with the rise of mobile backend services such as Kii.com, it has become very easy to create such applications very quickly 
If you live on another planet, you probably don’t know that WhatsApp (recently bought by Facebook) is the most popular cross-platform mobile messaging app which allows you to exchange messages (without having to pay for SMS), create groups, send unlimited images, video and audio media messages between members all over the world.
KiiChat Icon

Development of server-side functionality is essential to creating instant messanging apps like Skype, WhatsApp or LINE and, until now, individual developers had to implement all of it (which was a big gotcha). Fortunately, with the availability of backend services like Kii, you can quickly develop a very functional app in a matter of hours. At the end of this post you will have the opportunity to download the complete sample project. The app allows you to do the following (via our Android SDK):
  1. Support groups of users (and group scope object buckets)
  2. Change default data storage permissions (by setting a new ACL in an object bucket)
  3. Send messages to users subscribed to a topic (via the Push to user feature)
  4. Notify the app of new chat messages (via the Push to app feature)
  5. Query for objects on the cloud (messages, photos, etc)
  6. Upload photos (via upload of object bodies)
  7. Download photos (via download of object bodies)
  8. Login with Facebook account

Creating the App Backend

In order to use the Android SDK you must first register your application on Kii’s developer portal. Once registered, your application will have an associated App Key and App ID that you’ll use to initialize the SDK.

Register an Application

  1. Log in on the developer portal: https://developer.kii.com
  2. Press the “Create App” button.This bring up the “Create An App” menu.
  3. Enter the name of your app, select the desired server location and the mobile platforms you’d like to use (for this project you should select Android) and then click on the “Create” button.
  4. These are your application’s credentials which will be used by Kii Cloud to uniquely identify your application.
Copy these credentials and add them to the project’s constants file called ApplicationConst.java. This will be used in the next step: initializing the backend.

Initializing the Backend

It’s now time to link your actual app to the app backend that you created in the previous step. In a nutshell you’ll have to add our small SDK library to your Android project and initialize Kii with the App ID and App Key. Let’s take a closer look at this.

Configuring your Project

Follow the steps below to add the Kii Cloud SDK to your application’s project:
  1. Copy the latest Kii library (KiiCloudStorageSDK-xxx.jar) to your project’s libs directory {your android application project root}/libs
    Make sure it’s included in your project’s properties as a referenced library.
  2. Add the following permissions to your application’s AndroidManifest.xml:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="com.kii.sample.chat.permission.C2D_MESSAGE" />
    <permission android:name="com.kii.sample.chat.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    C2DM permissions are necessary to perform push notifications for messaging in the app.
  3. Add the following code to initialize the SDK on the class KiiChatApplication.
    import com.kii.cloud.storage.*;
    
    // Configures the SDK to use the specified Application ID and Key.
    // It must be called prior to any API calls.
    // It is ok to call this method multiple times
    Kii.initialize(ApplicationConst.APP_ID, ApplicationConst.APP_KEY, Kii.Site.JP);
    KiiAnalytics.initialize(context, ApplicationConst.APP_ID, ApplicationConst.APP_KEY, KiiAnalytics.Site.JP);
    Insert your application’s credentials (i.e. APP_ID and APP_KEY) in the placeholder parameters of this method. Also pass the Server Location (Site.US,Site.JP or Site.CN) that you’ve specified on the developer portal (defines the location of the backend server, the closer it is to your users the faster).

The Object Model

Let take a look at the object model for this messenger app:
kichat_objectmodel
  • IUser: an interface for the basic user info (username, e-mail and uri).
  • KiiObjectWrapper: It’s just a wrapper to quickly get and set key/value pairs on aKiiObject as well as to get low level object info (id, created time and modified time).
  • ChatUser: a wrapper for ChatUser objects that extends KiiObjectWrapper and implements the IUser interface. This is simply an abstraction for users of the messaging system. ChatUser objects use an app scope bucket for storage.
  • ChatFriend: also a wrapper for ChatFriend objects that extends KiiObjectWrapperand implements the IUser interface. It’s similar to ChatUser but difffers from it since objects are stored in a user scope buckets (which makes sense since only a user should be allowed to see his/her friends).
  • ChatMessage: a wrapper for ChatMessage objects that extends KiiObjectWrapper(the message itself will be a KiiObject).
  • ChatRoom: an abstraction for a chat room of users in a KiiGroup and an associated message list.
  • ChatStamp: a wrapper for ChatStamp objects that extends KiiObjectWrapper (the stamp itself will be a KiiObject). Stamps are images that can be sent as messages in a conversation.
We’ll explain each class of the model in more detail as we introduce the app’s functionality (more below).

Onboarding Users

The MainActivity

In the project you’ll see that in the AndroidManifest.xml file the main activity iscom.kii.sample.chat.ui.MainActivity. If there’s a stored authentication token for the user (Kii supports auth by token so users don’t have to login again next time they open the app) this activity will use it to log in and directly start the main chat activity (ChatMainActivity):
String token = PreferencesManager.getStoredAccessToken();
if (!TextUtils.isEmpty(token)) {
  KiiUser.loginWithToken(new KiiUserCallBack() {
    @Override
    public void onLoginCompleted(int token, KiiUser user, Exception e) {
        if (e == null) {
          ChatRoom.ensureSubscribedBucket(user);
          Intent intent = new Intent(MainActivity.this, ChatMainActivity.class);
          intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
          startActivity(intent);
        } else {
          PreferencesManager.setStoredAccessToken("");
          Intent intent = new Intent(MainActivity.this, SigninActivity.class);
          intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
          startActivity(intent);
        }
    }
  },token);
} else {
  Intent intent = new Intent(MainActivity.this, SigninActivity.class);
  intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
  startActivity(intent);
}
Note that we use a KiiUserCallback for the login method (Kii Cloud supports asyc non-blocking calls across the API so you can keep doing work while you wait for the backend to return a result). Note that in this code snippet if there’s no token (or token based authentication fails in any way) then the SigninActivity will be started where you can use a standard form based login/registration screen (“Sign-in with your e-mail”) or Facebook based authentication:
kiichat_login
If you check “Remember Me” in the screen above then a Kii user token will be stored that will be later used for token based authentication (as it was explained above). When you click on “Create new account” you’ll see a typical registration form:
kiichat_signup

User Registration and Login

Kii supports user registration out-of-the-box and even allows you to validate users via e-mail/SMS. But most importantly the code needed to register/login a user is very simple. Let’s take a look at the most important part of a SignupTask (defined inSignupDialogFragment):
@Override
protected Boolean doInBackground(Void... params) {
  try {
    KiiUser.Builder builder = KiiUser.builderWithEmail(email);
    KiiUser kiiUser = builder.build();
    kiiUser.setDisplayname(username);
    kiiUser.register(password);
    Logger.i("registered user uri=" + kiiUser.toUri().toString());
    return super.doInBackground(params);
  } catch (Exception e) {
    Logger.e("failed to sign up", e);
    return false;
  }
}
With a Kii user builder you can build a user using a username, e-mail and/or phone. After you set the basic info on the builder the KiiUser.register() method just takes a password as parameter and you’re done! (We use the blocking register API call here since this is already part of an Android async task).
The signin fragment is pretty similar (SigninDialogFragment):
kiichat_signin
Once you enter an e-mail and password combination that belongs to an existing user you’ll get a response from the backend (success or failure via an exception). Again the code is very simple (see SigninDialogFragment) and requires a unique user identifier such as username, e-mail or phone (in this case e-mail) and a password to verify if they match:
KiiUser.logIn(new KiiUserCallBack() {
  @Override
  public void onLoginCompleted(int token, KiiUser user, Exception e) {
    if (e != null) {
      Logger.e("Unable to login.", e);
      ToastUtils.showShort(getActivity(), "Unable to login");
      SimpleProgressDialogFragment.hide(getFragmentManager());
      return;
    }
    if (checkRemember) {
      Logger.i(user.getAccessToken());
      PreferencesManager.setStoredAccessToken(user.getAccessToken());
    }
    new PostSigninTask(user.getDisplayname(), user.getEmail()).execute();
  }
}, email, password);
You probably noticed unlike the previous registration example we’re now passing an implicit callback to make an asynchronous call (the user registration call was inside an Android async task in the previous example so it wasn’t necessary to use a callback though you should know it’s available). The advantage of using Kii’s non-blocking APIs is that the communication with the backend runs on separate thread and the initiating method call returns right away (you process the backend result when the callback is called) which is useful to avoid blocking the UI.
Ok, by now we do have a valid user viar a user registration or login. That means that you can now call KiiUser.getCurrentUser() from anywhere in your code and you’ll have a Kii user to work with. But it becomes necessary to couple that user to our model class for users: ChatUser and initialize that user to be able to receive push notifications (used to send messages between users in this app). This is achieved in post signup/signin tasks performed by ChatUserInitializeTask.initializeChatUser():
KiiUser kiiUser = KiiUser.getCurrentUser();
ChatUser user = ChatUser.findByUri(kiiUser.toUri());
if (user == null) {
  user = new ChatUser(kiiUser.toUri().toString(), username, email);
  user.getKiiObject().save();
}
Besides obtaining a ChatUser other important tasks are performed during ChatUserInitializeTask.initializeChatUser() that prepare the user for receiving push notifications. We’ll cover the code on the next sections.

Facebook Login

To wrap-up the user onboarding mechanisms let’s take a look at the Facebook based authentication. Kii allows you to use Twitter and Facebook based app authentication via Kii Social Connect. With it you can let your users to sign-up and sign-in to your app with their Facebook accounts by just adding a few parameters in the developer portal and a few lines of code in your app and you will be social-ready!
First of all you’ll have to create an app on Facebook and then configure your app on Kii’s developer console to connect that Facebook app. The procedure is as follows:

Create a Facebook App

To get started, you first need to create a Facebook App and get your Facebook Application ID.
Please refer Facebook’s official guide for the detailed instructions. You can also get more information in one of our DZone’s external article.

Configure a Kii Application for Facebook

Please execute the following step on the developer portal to configure your application by setting your Facebook Application ID.
  1. Click on the “Edit” button in your application console at the developer portal.
  2. Click on “Settings” to bring up the application’s configuration menu.
  3. Paste your Facebook App ID.
The code below shows a KiiChat’s login using Kii Social Connect with Facebook:
KiiFacebookConnect connect = (KiiFacebookConnect) Kii.socialConnect(SocialNetwork.FACEBOOK);
connect.initialize(ApplicationConst.FACEBOOK_APP_ID, null, null);
Bundle options = new Bundle();
String[] permission = new String[] { "email" };
options.putStringArray(KiiFacebookConnect.FACEBOOK_PERMISSIONS, permission);
connect.logIn(SigninActivity.this, options, new KiiSocialCallBack() {
  public void onLoginCompleted(SocialNetwork network, KiiUser user, Exception exception) {
    if (exception == null) {
      if (checkRemember.isChecked()) {
        Logger.i(user.getAccessToken());
        PreferencesManager.setStoredAccessToken(user.getAccessToken());
      }
      new PostSigninTask(user.getDisplayname(), user.getEmail()).execute();
    } else {
      Logger.e("failed to sign up", exception);
      ToastUtils.showShort(SigninActivity.this, "Unable to sign up");
    }
  }
});
The code is fairly easy to follow:
  1. Creates a social network connector instance with the socialConnect method passing the target social network service name (SocialNetwork.FACEBOOK in this example).
  2. Initializes the social network connector with the initialize method passing the Facebook App ID.
  3. Starts the sign-in process with the logIn method. If the specified Facebook account is new, the SDK will first execute the sign-up process if necessary. This method is non-blocking, so it uses a callback to get the results.
In the above code, we are setting the permission for fetching email address from Facebook upon executing the logIn method. When a user logins with a new Facebook account with this option, Kii Cloud extracts his/her email address from Facebook and checks if there exists a Kii account with the same email address. If such an account exists and the email address is already verified, Kii Cloud will not execute the sign-up process, but it will link the specified Facebook account with this account. Similarly to the previously described user registration and login process, after a successful Facebook login the system will return a valid Kii User when you call KiiUser.getCurrentUser()
Don’t forget that the Android activity that handles the Facebook login must implement the onActivityResult method that must include code to wrap up the Facebook authentication:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  Kii.socialConnect(SocialNetwork.FACEBOOK).respondAuthOnActivityResult(requestCode, resultCode, data);
}
Note that you can also link and unlink Facebook accounts on Kii users as described in our Facebook integration guide.

Logging Out

The user can also log out from the app at any time. The logout code is inFriendListFragment and is extremely easy to follow:
PreferencesManager.setStoredAccessToken("");
KiiUser.logOut();
intent = new Intent(getActivity(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
That concludes out user onboarding functionality. Let’s now continue with the functionality to add friends for chatting after you successfully login to the app.

Adding Friends

When you click on the “+” sign on the top bar of the app (while in the Friends tab) you’re presented with a search bar that allows you to look for users in the backend so you can add them to your friends (in the screenshot you can see that I already added a friend called “pub2″):
kiichat_friend
Kii Cloud provides a powerful query system that allows you to quickly get the data you need. Once a search keyword is provide a UserListLoader takes care of fetching the users from the backend:
@Override
public List<ChatUser> loadInBackground() {
  List<ChatUser> users = new ArrayList<ChatUser>();
  try {
    List<ChatUser> results = ChatUser.searchByKeyword(keyword);
    for (ChatUser user : results) {
      if (!TextUtils.equals(user.getUri(), KiiUser.getCurrentUser().toUri().toString())) {
        users.add(user);
      }
    }
  } catch (Exception e) {
    Logger.e("Unable to list users", e);
  }
  return users;
}
The interesting method here (the one with Kii based code) isChatUser.searchByKeyword() which provides the underlying code to query the backend for ChatUsers:
public static List<ChatUser> searchByKeyword(String keyword) throws Exception {
  KiiQuery query = null;
  if (TextUtils.equals("*", keyword)) {
    query = new KiiQuery();
  } else {
    query = new KiiQuery(
      KiiClause.or(
        KiiClause.startsWith(FIELD_USERNAME, keyword),
        KiiClause.startsWith(FIELD_EMAIL, keyword)
      )
    );
  }
  List<ChatUser> users = new ArrayList<ChatUser>();
  List<KiiObject> objects = getBucket().query(query).getResult();
  for (KiiObject object : objects) {
    users.add(new ChatUser(object));
  }
  return users;
}
As you can see in the code if you use the keyword * as search term then a clause-less KiiQuery is created (equivalent to a “catch all” query) to get a list of every registered user.
kiichat_users
If the keyword is different then two KiiClauses are added to the query to constrain the results to match the beginning of a username or of an e-mail. After the query is built then it is passed to an object bucket (KiiBucket.query()) and results are fetched. After you get the list of users you can tap on a user in the list in order to add it as a friend:
kiichat_addfriend
When you add a friend the ChatUser is converted to a ChatFriend and it’s then maintained in a separate list of friends with very similar characteristics as to what was described for global users (except that friends are kept in a user scope bucketwhich is only visible to each user).

Sending Messages

Once you have added friends to your friend’s list you can invite them to chat by tapping on them:
kiichat_chat
The chat setup is performed in ChatListFragment.NewChatTask: and basically adds the involved parties to a KiiGroup and creates a KiiTopic to channel the invitations to chat:
@Override
protected KiiGroup doInBackground(Void... params) {
  try {
    String chatRoomName = ChatRoom.getChatRoomName(KiiUser.getCurrentUser(), this.chatFriend);
    String uniqueKey = ChatRoom.getUniqueKey(KiiUser.getCurrentUser(), this.chatFriend);
    for (int i = 0; i < getListView().getCount(); i++) {
      KiiGroup kiiGroup = (KiiGroup)getListView().getItemAtPosition(i);
      if (TextUtils.equals(uniqueKey, ChatRoom.getUniqueKey(kiiGroup))) {
        return kiiGroup;
      }
    }
    KiiGroup kiiGroup = Kii.group(chatRoomName);
    KiiUser target = KiiUser.createByUri(Uri.parse(this.chatFriend.getUri()));
    target.refresh();
    kiiGroup.addUser(target);
    kiiGroup.save();
    KiiBucket chatBucket = ChatRoom.getBucket(kiiGroup);
    KiiUser.getCurrentUser().pushSubscription().subscribeBucket(chatBucket);
    KiiTopic topic = target.topicOfThisUser(ApplicationConst.TOPIC_INVITE_NOTIFICATION);
    Data data = new Data();
    data.put(ChatRoom.CHAT_GROUP_URI, kiiGroup.toUri().toString());
    KiiPushMessage message = KiiPushMessage.buildWith(data).build();
    topic.sendMessage(message);
    Logger.i("sent notification to " + target.toUri().toString());
    return kiiGroup;
  } catch (Exception e) {
    Logger.e("failed to start chat", e);
    return null;
  }
}
In the above code you can see that a ChatRoom is matched to a KiiGroup. Then the target user (the one that will be contacted) is added to the group. A group scope bucket is used here to hold the messages sent by the users and the current user is subscribed to receive push notifications from it (all subscribed users to the group bucket will receive a notification when a new message is posted). Finally a message is built with the chat group URI to notify the target user of the invitation.
In the code above we don’t see any low level configuration of push notifications. However this is done as soon as a user registers or signs in. In the “User Registration and Login” section we described how a user was coupled to ChatUserduring an initialization process performed inChatUserInitializeTask.initializeChatUser(). That method also initializes the push notification system so users can send/receive messages. Let’s take a closer look at the code:
KiiUser kiiUser = KiiUser.getCurrentUser();
ChatUser user = ChatUser.findByUri(kiiUser.toUri());
if (user == null) {
  user = new ChatUser(kiiUser.toUri().toString(), username, email);
  user.getKiiObject().save();
}
KiiUser.pushInstallation().install(GCMUtils.register());
KiiTopic topic = KiiUser.topic(ApplicationConst.TOPIC_INVITE_NOTIFICATION);
try {
  topic.save();
} catch (ConflictException e) {
}
KiiACL acl = topic.acl();
acl.putACLEntry(new KiiACLEntry(KiiAnyAuthenticatedUser.create(), TopicAction.SEND_MESSAGE_TO_TOPIC, true));
try {
  acl.save();
} catch (ACLOperationException e) {
  Throwable t = e.getCause();
  if (!(t instanceof ConflictException)){
    throw e;
  }
}
KiiPushSubscription subscription = kiiUser.pushSubscription();
try {
  subscription.subscribe(topic);
} catch (ConflictException e) {
}
kiiUser.set(INITIALIZED_USER_KEY, true);
kiiUser.update();
As you can see above push notifications are initialized for the current user, aKiiTopic is created to receive invite notifications and its permissions are changed to allow any registered user to send an invitation. Finally the current user is subscribed to the topic so it can receive invitations.
This set the stage for the interchange of user messages. The class ChatActivityencapsulates all the chat interaction itself. Let’s take a look at the code called when the “Send” message button is clicked:
this.btnSend.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    btnSend.setEnabled(false);
    final ChatMessage message = new ChatMessage(kiiGroup);
    message.setMessage(editMessage.getText().toString());
    message.setSenderUri(KiiUser.getCurrentUser().toUri().toString());
    new SendMessageTask(message).execute();
  }
});
In the code above a ChatMessage is initialized on a the current user group, the message text is grabbed from the UI text box and the sender is set to the current user. Let’s take a look at the SendMessageTask main background method:
  @Override
  protected Boolean doInBackground(Void... params) {
    try {
      this.message.getKiiObject().save();
      ChatStamp.sendUsageEvent(this.message);
      return true;
    } catch (Exception e) {
      Logger.e("failed to send messsage", e);
      return false;
    }
Here the message is saved in the backend triggering a modification in the user group associated with it. All group members will get a push notification when this happens. Note that an analytics event is also sent (for detail seeChatStamp.sendUsageEvent()). Kii Cloud can aggregate this type of events (and also any stored data) to later offer you the chance to create metrics and slice and dice the information (with advanced visualization) from a convenient web console.
To wrap-up this section let’s review some of the details of how to receive this message notifications. In order to detect incoming push notification an AndroidBroadcastReceiver is set up:
private final BroadcastReceiver handleMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    updateMessage(false);
  }
};

private void updateMessage(boolean showProgress) {
  new GetMessageTask(showProgress).execute();
}
And GetMessageTask‘s main background process refreshes the list of messages (including the incoming one) using a ChatRoom that is associated to the relevant group:
@Override
protected List<ChatMessage> doInBackground(Void... params) {
  try {
    ChatRoom chatRoom = new ChatRoom(kiiGroup);
    List<ChatMessage> messages = null;
    if (lastGotTime == null) {
      messages = chatRoom.getMessageList();
    } else {
      messages = chatRoom.getMessageList(lastGotTime);
    }
    if (messages.size() > 0) {
      lastGotTime = messages.get(messages.size() - 1).getKiiObject().getCreatedTime();
    }
    return messages;
  } catch (Exception e) {
    Logger.e("failed to get message", e);
    return null;
  }
}

Sending Photos (Stamps)

With Kii Cloud it’s very easy to attach a files to objects that you save in the backend (you just upload/download them as object bodies). Here’s a screenshot of two friends sharing images:
kiichat_stamps
Image files are wrapped by the ChatStamp class which basically holds 3 members: a Kii object (representing the image abstraction and metadata in the backend), a Uri (a unique identifier for the object on the backend) and a File (the image binary itself which will be attached to the Kii object as an object body). Let’s see how the app saves and loads image stamps from the cloud:
public void save() throws Exception {
  this.kiiObject.save();
  if (this.imageFile != null) {
    this.uri = this.kiiObject.toUri().toString();
    KiiUploader uploader = this.kiiObject.uploader(KiiChatApplication.getContext(), this.imageFile);
    uploader.transfer(null);
    File cacheFile = StampCacheUtils.getCacheFile(this.kiiObject.toUri().toString());
    this.imageFile.renameTo(cacheFile);
  }
}
First of all the wrapped object is saved (this is exactly the same as saving an object on Kii Cloud that has no association to a file). Then, if the ChatStamp has an associated image, we retrieve a file uploader from the Kii object and transfer the image file to the cloud as an object body (the null parameter on transfer() means we’re not passing a callback to get feedback from the transfer outcome). If the object already has an object body on the cloud then uploading a new file will replace it. Note that if the upload gets interrupted it will be suspended and a SuspendedExceptionwill be thrown. In that case, you can resume the upload (see Resuming Uploads). Finally the associated image file is moved a local cache which will later help to accelerate image loading.
Loading a ChatStamp image is also simple with almost half the code dedicated to fetching the image from the cache if present:
public Bitmap getImage() {
  try {
    byte[] image = null;
    if (this.imageFile != null) {
      image = readImageFromLocal(this.imageFile);
    } else if (this.uri != null) {
      File cacheFile = StampCacheUtils.getCacheFile(this.uri);
      if (cacheFile.exists()) {
        image = readImageFromLocal(cacheFile);
      } else {
        Logger.i("downloading stamp image from KiiCloud");
        KiiDownloader downloader = this.kiiObject.downloader(KiiChatApplication.getContext(), cacheFile);
        downloader.transfer(null);
        image = readImageFromLocal(cacheFile);
      }
    }
    if (image != null) {
      return BitmapFactory.decodeByteArray(image, 0, image.length);
    }
    Logger.w("failed to download stamp image");
    return null;
  } catch (Exception e) {
    Logger.e("failed to download stamp image", e);
    return null;
  }
}
The concept is very similar to the image saving code but now we use a file downloader. and load the image directly into our local cache (if it’s not already present in it). Finally, from the local cache we return the image file as a bitmap for displaying.
With this low level file management management facilitated by Kii, the high level retrieval of the images comes down to pairing a ChatStamp image to an ImageView for display (see class ChatStampImageFetcher and ChatActivity for high level management of stamps):
if (chatMessage.isStamp()) {
  ChatStamp stamp = new ChatStamp(chatMessage);
  imageFetcher.fetchStamp(stamp, holder.stamp);
}

Wrap-Up and Project Download

As you can see Kii Cloud gives you all the functionality of a robust, scalable backend by just adding a library to your project and using a simple client side API designed to match your backend management needs but providing a higher level of abstraction.
We’re making available the full Android project for your reference so you can take a look at the details, learn and maybe use similar classes in your next Kii Cloud powered app. The project uses our own app credentials but you can easily swap those out and use your own. In the these final sections we’ll show you how to properly configure the project so you can run it with no problems:

Dependencies

  • android-support-v4.jar (rev. 19.1)
  • android-support-v7-appcompat.jar (rev. 19.1)
  • google-play-services.jar (for froyo rev. 16)

Project Setup

You need to import following project to your workspace if you use Eclipse.
{SDK-DIR}/extras/android/support/v7/appcompat
{SDK-DIR}/extras/google/google_play_services_froyo/libproject/google-play-services_lib
KiiChat uses GCM (Google Cloud Messaging) in order to send push notification and GCM needs google account.
So you need to set up the google account on your emulator.
  1. Make sure you are using emulator targetted on Google API
  2. Add account on emulator as setting->account

0 Comments
Disqus
Fb Comments
Comments :

0 comments:

Post a Comment