Here's is a great news.We partnered with new experts so we change our blog.All our post goes their so please visit "Hack Cyber" and bookmark it.
visit hack cyber at
http://hackcyber.blogspot.in
Thank You
By Admin
Here's is a great news.We partnered with new experts so we change our blog.All our post goes their so please visit "Hack Cyber" and bookmark it.
visit hack cyber at
http://hackcyber.blogspot.in
Thank You
By Admin
ApplicationConst.java
. This will be used in the next step: initializing the backend.AndroidManifest.xml
:<uses-permission android:name="android.permission.INTERNET" />C2DM permissions are necessary to perform push notifications for messaging in the app.
<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" />
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);
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).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 extendsKiiObjectWrapper
and 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.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);
}
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: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;
}
}
SigninDialogFragment
):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);
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();
}
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.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");
}
}
});
socialConnect
method passing the target social network service name (SocialNetwork.FACEBOOK
in this example).initialize
method passing the Facebook App ID.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.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 callKiiUser.getCurrentUser()
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);
}
FriendListFragment
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);
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;
}
ChatUser.searchByKeyword()
which provides the underlying code to query the backend for ChatUser
s: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;
}
KiiQuery
is created (equivalent to a “catch all” query) to get a list of every registered user.KiiClause
s 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: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 bucket which is only visible to each user).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;
}
}
ChatRoom
is matched to a KiiGroup
. Then the target user (the one that will be contacted) is added to the group. A group scope bucketis 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.ChatUser
during an initialization process performed in ChatUserInitializeTask.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();
KiiTopic
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.ChatActivity
encapsulates 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();
}
});
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;
}
ChatStamp.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.BroadcastReceiver
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();
}
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;
}
}
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);
}
}
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 SuspendedException
will 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.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;
}
}
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);
}
{SDK-DIR}/extras/android/support/v7/appcompat
{SDK-DIR}/extras/google/google_play_services_froyo/libproject/google-play-services_lib
Copyright © 2013 GagBox™ is a registered trademark.
Designed by GagBox Inc. Desiged By Templateism.com. Blogger Hosting by Blogger.
GAGBOX is your one source to humor and fun