Java tutorial
/* * 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); } }