at.vcity.androidimsocket.services.IMService.java Source code

Java tutorial

Introduction

Here is the source code for at.vcity.androidimsocket.services.IMService.java

Source

/* 
 * Copyright (C) 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package at.vcity.androidimsocket.services;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.github.nkzawa.socketio.client.Ack;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.widget.Toast;

import at.vcity.androidimsocket.Login;
import at.vcity.androidimsocket.Messaging;
import at.vcity.androidimsocket.R;
import at.vcity.androidimsocket.UnApprovedFriendList;
import at.vcity.androidimsocket.chatting.Chatting;
import at.vcity.androidimsocket.chatting.socketIO.SocketOperator;
import at.vcity.androidimsocket.chatting.interfaces.ChattingInterface;
import at.vcity.androidimsocket.chatting.interfaces.UpdateDataInterface;
import at.vcity.androidimsocket.chatting.interfaces.SocketInterface;
import at.vcity.androidimsocket.chatting.tools.FriendController;
import at.vcity.androidimsocket.chatting.tools.LocalStorageHandler;
import at.vcity.androidimsocket.types.FriendInfo;
import at.vcity.androidimsocket.types.MessageInfo;
import at.vcity.androidimsocket.types.NetworkCommand;

/**
 *
 * <p>Notice the use of the {@link NotificationManager} when interesting things
 * happen in the service.  This is generally how background services should
 * interact with the user, rather than doing something more disruptive such as
 * calling startActivity().
 */
public class IMService extends IntentService implements ChattingInterface, UpdateDataInterface {
    //   private NotificationManager mNM;

    public static String currentUserId;
    public static final String TRY_LOGIN = "Try_Login";
    public static final String TAKE_MESSAGE = "Take_Message";
    public static final String FRIEND_LIST_UPDATED = "Take Friend List";
    public ConnectivityManager conManager = null;
    private final int UPDATE_TIME_PERIOD = 10000;//15000;
    private final int WAKE_TIME_PERIOD = 300000;//300000;

    SocketInterface socketOperator = new SocketOperator(this);
    //10.88.26.103
    //192.168.33.86

    public IMService() {
        super("IMService");
    }

    private final IBinder mBinder = new IMBinder();
    private String username;
    private String password;
    private boolean authenticatedUser = false;
    // timer to take the updated data from server
    private Timer waitTimer;

    private LocalStorageHandler localstoragehandler;

    boolean heartIsBeating = false;
    private NotificationManager mNM;

    public class IMBinder extends Binder {
        public ChattingInterface getService() {
            return IMService.this;
        }

    }

    @Override
    protected void onHandleIntent(Intent intent) {

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String myToken = intent.getStringExtra("myToken");

        if (!heartIsBeating) {
            if (myToken != null) {
                username = intent.getStringExtra("username");
                password = intent.getStringExtra("password");
                socketOperator.setToken(myToken);
                Log.i("Wake up now....................!!!!", "");
                startHeartbeat();
            }
        }
        return START_REDELIVER_INTENT;
    }

    @Override
    public void onCreate() {
        mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        localstoragehandler = new LocalStorageHandler(this);
        // Display a notification about us starting.  We put an icon in the status bar.
        conManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
        //new LocalStorageHandler(this);
        IntentFilter i = new IntentFilter();
        i.addAction("AlarmReceiver");
        registerReceiver(alarmReceiver, i);
    }

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

    public String getUserId() {
        //return this.username;
        return currentUserId;
    }

    public String getUserName() {
        //return this.username;
        return this.username;
    }

    String randomString(int length) {
        Random gen = new Random();
        String ALLOWED_CHARACTERS = "01FGHJK2ert4567ypasdDLZklzTYUI389qwOXCVBfxcvbnmQWERghjPAuioSNM";
        StringBuilder stringBuilder = new StringBuilder();
        char temp;
        for (int i = 0; i < length; i++) {
            stringBuilder.append(ALLOWED_CHARACTERS.charAt(gen.nextInt(ALLOWED_CHARACTERS.length())));
        }
        return stringBuilder.toString();
    }

    public void signUpUser(String username, String password, String email, final Chatting.UICallback callback) {
        JSONObject param = new JSONObject();
        try {
            param.put("username", username);
            param.put("password", password);
            param.put("email", email);
        } catch (JSONException e) {

        }
        //Log.i("PARAMS", params);
        socketOperator.send(NetworkCommand.SIGNUP_USER, param, new Ack() {
            @Override
            public void call(Object... args) {
                try {
                    JSONObject params = new JSONObject(args[0].toString());
                    String result = params.getString(NetworkCommand.RESULT);
                    if (result.equals(NetworkCommand.SUCCESSFUL)) {
                        callback.successfullcallback();
                    } else {
                        callback.failedcallback(result);
                    }
                } catch (JSONException e) {
                }
            }
        });
    }

    public void addNewFriendRequest(String friendUsername, final Chatting.UICallback callback) {
        JSONObject param = new JSONObject();
        try {
            param.put("friendUserName", friendUsername);
        } catch (JSONException e) {

        }
        //Log.i("PARAMS", params);
        socketOperator.send(NetworkCommand.ADD_NEW_FRIEND, param, new Ack() {
            @Override
            public void call(Object... args) {
                CheckNetworkResult(callback, args);

            }
        });
    }

    public void sendFriendsReqsResponse(ArrayList<FriendInfo> approvedFriends, ArrayList<FriendInfo> discardFriends,
            final Chatting.UICallback callback) {
        JSONObject param = new JSONObject();
        try {
            JSONArray approved = new JSONArray();
            for (int i = 0; i < approvedFriends.size(); i++) {
                FriendInfo f = approvedFriends.get(i);
                JSONObject p = new JSONObject();
                p.put(FriendInfo.USER_ID, f.userId);
                approved.put(i, p);
            }
            param.put("approved", approved);

            JSONArray discard = new JSONArray();
            for (int i = 0; i < discardFriends.size(); i++) {
                FriendInfo f = discardFriends.get(i);
                JSONObject p = new JSONObject();
                p.put(FriendInfo.USER_ID, f.userId);
                discard.put(i, p);
            }
            param.put("discarded", discard);
        } catch (JSONException e) {

        }
        //Log.i("PARAMS", params);
        socketOperator.send(NetworkCommand.RESPONSE_OF_FRIEND_REQ, param, new Ack() {
            @Override
            public void call(Object... args) {
                CheckNetworkResult(callback, args);
                getFriendList();
            }
        });

    }

    private void CheckNetworkResult(final Chatting.UICallback callback, Object... args) {
        try {
            JSONObject params = new JSONObject(args[0].toString());
            String result = params.getString(NetworkCommand.RESULT);
            if (needVeryft(result)) {
                // callback.failedcallback();
            } else if (result.equals(NetworkCommand.SUCCESSFUL)) {
                callback.successfullcallback();
            } else {
                callback.failedcallback();
            }
        } catch (JSONException e) {
        }
    }

    public void sendMessage(MessageInfo message, final Chatting.UICallback callback)// throws UnsupportedEncodingException
    {
        localstoragehandler.insert(message);
        JSONObject param = new JSONObject();
        try {
            param.put("toUserId", message.toUserId);
            param.put("content", message.content);
            param.put("type", message.type);
        } catch (JSONException e) {

        }
        //Log.i("PARAMS", params);
        socketOperator.send(NetworkCommand.SEND_MESSAGE, param, new Ack() {
            @Override
            public void call(Object... args) {
                CheckNetworkResult(callback, args);
            }
        });
    }

    public void sendReadAck(ArrayList<MessageInfo> readAckList, final Chatting.UICallback callback) {
        JSONObject params = new JSONObject();
        try {
            JSONArray messages = new JSONArray();

            for (int i = 0; i < readAckList.size(); i++) {

                String id = readAckList.get(i).messageId;
                JSONObject emitid = new JSONObject();
                emitid.put(MessageInfo.MESSAGEID, id);
                messages.put(i, emitid);
            }
            params.put("messages", messages);
        } catch (JSONException e) {

        }

        socketOperator.send(NetworkCommand.SEND_MESSAGE_READ_ACK, params, new Ack() {
            @Override
            public void call(Object... args) {
                CheckNetworkResult(callback, args);
            }
        });
    }

    boolean needVeryft(String result) {
        if (result.equals(NetworkCommand.SOCKET_EXPIRED)) {
            verify();
            return true;
        } else
            return false;
    }

    public void getFriendList() {
        // after authentication, server replies with friendList xml

        JSONObject param = new JSONObject();
        if (socketOperator == null) {
            Log.i("socketoperator is null", "");
        }
        socketOperator.send(NetworkCommand.GET_FRIEND_LIST, param, new Ack() {
            @Override
            public void call(Object... args) {
                try {
                    JSONObject params = new JSONObject(args[0].toString());
                    String result = params.getString(NetworkCommand.RESULT);
                    if (result.equals(NetworkCommand.SUCCESSFUL)) {

                        JSONArray friendarray = params.getJSONArray(FriendInfo.FRIEND_LIST);
                        ArrayList<FriendInfo> friends = new ArrayList<FriendInfo>();

                        for (int i = 0; i < friendarray.length(); i++) {
                            JSONObject friend = friendarray.getJSONObject(i);
                            FriendInfo f = new FriendInfo();
                            f.userId = friend.getString(FriendInfo.USER_ID);
                            f.userName = friend.getString(FriendInfo.USERNAME);
                            friends.add(f);
                        }

                        FriendController.setFriendsInfo(friends);

                        Intent friendlistIntent = new Intent(FRIEND_LIST_UPDATED);
                        sendBroadcast(friendlistIntent);
                    }
                } catch (JSONException e) {
                }
            }
        });
    }

    public void receiveFriendReqsResponse(Object... args) {
        getFriendList();
    }

    public void verify() {
        socketOperator.send(NetworkCommand.VERIFY, new JSONObject(), new Ack() {
            @Override
            public void call(Object... args) {
                try {
                    JSONObject param = new JSONObject(args[0].toString());
                    String result = param.getString(NetworkCommand.RESULT);
                    if (result.equals(NetworkCommand.TOKEN_EXPIRED)) {
                        authenticateUser(username, password);
                    } else
                        authenticationResult(args);
                } catch (JSONException e) {
                }
            }
        });
    }

    /**
     * authenticateUser: it authenticates the user and if succesful
     * it returns the friend list or if authentication is failed 
     * it returns the "0" in string type
     * @throws UnsupportedEncodingException 
     * */
    public void authenticateUser(String usernameText, String passwordText)// throws UnsupportedEncodingException
    {
        this.username = usernameText;
        this.password = passwordText;

        this.authenticatedUser = false;
        // socketOperator.setToken("efgh5678");
        // socketOperator.setToken("abcd1234");
        //verify();

        socketOperator.send(NetworkCommand.AUTHENTICATE_USER, getAuthenticateUserParams(username, password),
                new Ack() {
                    @Override
                    public void call(Object... args) {
                        try {
                            JSONObject param = new JSONObject(args[0].toString());
                            if (param.getString("result").equals(NetworkCommand.SUCCESSFUL)) {
                                String token = param.getString("token");
                                socketOperator.setToken(token);
                                verify();
                            }
                        } catch (JSONException e) {

                        }
                    }
                });
    }

    public void authenticationResult(Object... args) {
        this.authenticatedUser = true;
        try {
            JSONObject param = new JSONObject(args[0].toString());
            String result = param.getString("result");
            if (result.equals(NetworkCommand.SUCCESSFUL)) {
                //currentUserId=param.getString("userId");
                FriendInfo f = new FriendInfo();
                f.userName = username;
                f.userId = param.getString("userId");
                Chatting.setCurrentUser(f);

                // getFriendList();

                AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
                Intent intent = new Intent(this, IMService.class);
                intent.putExtra("myToken", socketOperator.getToken());
                intent.putExtra("username", username);
                intent.putExtra("password", password);
                PendingIntent pintent = PendingIntent.getService(this, 0, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
                alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        SystemClock.elapsedRealtime() + WAKE_TIME_PERIOD, WAKE_TIME_PERIOD, pintent);

                Intent loginintent = new Intent(TRY_LOGIN);
                loginintent.putExtra("AUTHENTICATION_RESULT", NetworkCommand.SUCCESSFUL);
                sendBroadcast(loginintent);

                // Start heartbeat
                heartIsBeating = true;
                startHeartbeat();
            } else {
                Toast.makeText(this, "Wrong user name", Toast.LENGTH_SHORT).show();
            }
        } catch (JSONException e) {
        }
        ;
    }

    private void startHeartbeat() {
        alarmReceiver.SetAlarm(this);
    }

    private AlarmReceiver alarmReceiver = new AlarmReceiver();

    public class AlarmReceiver extends BroadcastReceiver {

        Context context;

        @Override
        public void onReceive(final Context context, final Intent intent) {
            Log.i("heart is beating....", "");
            waitTimer = new Timer();
            waitTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    verify();
                }
            }, 30000);

            try {
                JSONObject param = new JSONObject();
                ////LEFT HERE///////////////////////
                socketOperator.send(NetworkCommand.HEARTBEAT, param, new Ack() {
                    @Override
                    public void call(Object... args) {
                        waitTimer.cancel();
                        try {
                            JSONObject param = new JSONObject(args[0].toString());
                            String result = param.getString("result");
                            Log.i("Heartbeat result:", result);
                            if (needVeryft(result)) {
                            } else if (result.equals(NetworkCommand.TOKEN_EXPIRED)) {
                                authenticateUser(username, password);
                            } else {
                                //startHeartbeat();
                                SetAlarm(context);
                            }
                        } catch (JSONException e) {
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void SetAlarm(Context c) {
            context = c;
            AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent("AlarmReceiver");
            PendingIntent pintent = PendingIntent.getBroadcast(context, 0, intent, 0);

            alarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + UPDATE_TIME_PERIOD,
                    pintent);
        }
    };

    private JSONObject getAuthenticateUserParams(String usernameText, String passwordText)// throws UnsupportedEncodingException
    {
        JSONObject param = new JSONObject();
        try {
            param.put("username", usernameText);
            param.put("password", passwordText);
            param.put("action", NetworkCommand.AUTHENTICATE_USER);
        } catch (JSONException e) {

        }
        return param;
        //return params;
    }

    public boolean isUserAuthenticated() {
        return authenticatedUser;
    }

    @Override
    public void onDestroy() {
        try {
            unregisterReceiver(alarmReceiver);
        } catch (IllegalArgumentException e) {
        }

        AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(this, IMService.class);
        PendingIntent pintent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        alarm.cancel(pintent);

        Log.i("IMService is being destroyed", "...");
        //   super.onDestroy();
    }

    public void exit() {
        unregisterReceiver(alarmReceiver);
        socketOperator.exit();
        socketOperator = null;
        this.stopSelf();
    }

    public void receiveFriendReq(Object... args) {
        try {
            JSONObject params = new JSONObject(args[0].toString());
            JSONArray friendarray = params.getJSONArray(FriendInfo.FRIEND_LIST);
            ArrayList<FriendInfo> unapprovedfriends = new ArrayList<FriendInfo>();

            for (int i = 0; i < friendarray.length(); i++) {
                JSONObject friend = friendarray.getJSONObject(i);
                FriendInfo f = new FriendInfo();
                f.userId = friend.getString(FriendInfo.USER_ID);
                f.userName = friend.getString(FriendInfo.USERNAME);
                unapprovedfriends.add(f);
            }
            FriendController.setUnapprovedFriendsInfo(unapprovedfriends);

            String title = "AndroidIM: You got friend request(s)! ";
            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.stat_sample).setContentTitle(title).setAutoCancel(true);
            //.setContentText(text);

            Intent i = new Intent(this, UnApprovedFriendList.class);

            PendingIntent contentIntent = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);

            // Set the info for the views that show in the notification panel.
            // msg.length()>15 ? MSG : msg.substring(0, 15);
            mBuilder.setContentIntent(contentIntent);

            //TODO: it can be improved, for instance message coming from same user may be concatenated
            // next version

            // Send the notification.
            // We use a layout id because it is a unique number.  We use it later to cancel.
            mNM.notify(R.string.new_friend_request_exist, mBuilder.build());
        } catch (JSONException e) {
        }
    }

    public void receiveReadAck(Object... args) {
        try {
            Ack ack = (Ack) args[args.length - 1];
            JSONObject callbackParams = new JSONObject();
            callbackParams.put(NetworkCommand.RESULT, NetworkCommand.SUCCESSFUL);
            ack.call(callbackParams);
        } catch (JSONException e) {

        }
    }

    public void receiveMessage(Object... args) {
        try {
            JSONObject param = new JSONObject(args[0].toString());
            JSONArray messagearray = param.getJSONArray("messages");
            ArrayList<MessageInfo> mUnreadMessages = new ArrayList<MessageInfo>();
            JSONArray emits = new JSONArray();

            for (int i = 0; i < messagearray.length(); i++) {
                MessageInfo message = new MessageInfo();
                JSONObject messagejson = messagearray.getJSONObject(i);
                message.toUserId = Chatting.getCurrentUserId();
                message.fromUserId = messagejson.getString(MessageInfo.FROM);
                message.content = messagejson.getString(MessageInfo.CONTENT);
                message.type = messagejson.getString(MessageInfo.TYPE);
                message.messageId = messagejson.getString(MessageInfo.MESSAGEID);
                message.read = false;
                JSONObject emitid = new JSONObject();
                emitid.put(MessageInfo.MESSAGEID, message.messageId);
                emits.put(i, emitid);
                mUnreadMessages.add(message);
            }
            for (MessageInfo m : mUnreadMessages) {
                messageReceived(m);//m.fromUserId,m.content);
                //i++;
            }

            Intent friendlistIntent = new Intent(FRIEND_LIST_UPDATED);
            sendBroadcast(friendlistIntent);

            Ack ack = (Ack) args[args.length - 1];
            JSONObject callbackParams = new JSONObject();
            callbackParams.put(NetworkCommand.RESULT, NetworkCommand.SUCCESSFUL);
            callbackParams.put("emits", emits);
            ack.call(callbackParams);

        } catch (JSONException e) {

        }
    }

    public void messageReceived(MessageInfo msg)//String userId, String message)
    {
        if (msg != null) {
            Intent i = new Intent(TAKE_MESSAGE);
            localstoragehandler.insert(msg);
            i.putExtra(MessageInfo.MESSAGE, msg);
            sendBroadcast(i);
            FriendInfo activeFriend = FriendController.getActiveFriend();
            if (activeFriend == null)//|| activeFriend.userId.equals(msg.fromUserId) == false) {{
                new AsyncTask<MessageInfo, Void, MessageInfo>() {
                    @Override
                    protected MessageInfo doInBackground(MessageInfo... m) {
                        while (!FriendController.isFriendListReady()) {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                            }
                        }
                        return m[0];
                    }

                    @Override
                    protected void onPostExecute(MessageInfo msg) {
                        //super.onPostExecute(aVoid);
                        showNotification(msg);//msg.fromUserId, message, msg.type);
                    }
                }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, msg);

        }
        Log.i("TAKE_MESSAGE broadcast sent by im service", "");
    }

    /**
     * Show a notification while this service is running.
     * @param msg
     **/
    private void showNotification(MessageInfo msg)//String userId, String msg, String msgtype)
    {
        //FriendInfo f=FriendController.getFriendInfo(userId);
        // Set the icon, scrolling text and TIMESTAMP

        // Get User name from friend controller

        String title = "AndroidIM: You got a new Message! ";
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.stat_sample).setContentTitle(title).setAutoCancel(true);
        //.setContentText(text);

        FriendInfo friend = FriendController.getFriendInfo(msg.fromUserId);

        if (msg.type.equals(MessageInfo.MessageType.TEXT))
            mBuilder.setContentText("New message from " + friend.userName + ": " + msg.content);
        else if (msg.type.equals(MessageInfo.MessageType.IMAGE)) {
            mBuilder.setContentText("New image from " + friend.userName);
        } else {
            mBuilder.setContentText("New voice clip from " + friend.userName);
        }
        Intent i;

        String packagename = this.getPackageName();
        if (isForeground(packagename))
            i = new Intent(this, Messaging.class);
        else
            i = new Intent(this, Login.class);

        i.putExtra(MessageInfo.MESSAGE, msg);
        i.putExtra(FriendInfo.FRIEND, friend);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);

        // Set the info for the views that show in the notification panel.
        // msg.length()>15 ? MSG : msg.substring(0, 15);
        mBuilder.setContentIntent(contentIntent);

        //TODO: it can be improved, for instance message coming from same user may be concatenated
        // next version

        // Send the notification.
        // We use a layout id because it is a unique number.  We use it later to cancel.
        mNM.notify((msg.fromUserId).hashCode(), mBuilder.build());
    }

    public boolean isForeground(String myPackage) {
        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.getRunningTasks(1);
        ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
        return componentInfo.getPackageName().equals(myPackage);
    }
}