Android Open Source - BerryTube Berry Tube






From Project

Back to project page BerryTube.

License

The source code is released under:

GNU General Public License

If you think the Android project BerryTube listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * BerryTube Service/*www . j a  v  a2 s.c om*/
 * Copyright (C) 2012 Daniel Triendl <trellmor@trellmor.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.trellmor.berrytube;

import io.socket.SocketIO;

import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

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

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

/**
 * BerryTube handles to communication with the BerryTube Server and provides
 * synchronous callbacks for an UI application.
 * 
 * This is an android service intended to run in the same process as the main
 * application
 * 
 * @author Daniel Triendl
 * @see android.app.Service
 */
public class BerryTube extends Service {
  private static final String TAG = BerryTube.class.getName();
  
  private SocketIO mSocket = null;
  private WeakReference<BerryTubeCallback> mCallback = new WeakReference<>(null);

  private String mUsername;
  private String mPassword;
  private String mNick = null;
  private Poll mPoll = null;
  private final ArrayList<ChatMessage> mChatMsgBuffer = new ArrayList<>();
  private int mChatMsgBufferSize = 100;
  private final ArrayList<ChatUser> mUsers = new ArrayList<>();
  private int mDrinkCount = 0;
  private final Handler mHandler = new Handler();
  private NotificationManager mNotificationManager;
  private NotificationCompat.Builder mServiceNotification = null;
  private NotificationCompat.Builder mMessageNotification = null;
  private final ArrayList<String> mMessageNotificationText = new ArrayList<>(5);
  private int mMessageNotificationCount = 0;

  private static final int KEY_NOTIFICATION_SERVICE = 1000;
  private static final int KEY_NOTIFICATION_MESSAGE = 2000;

  @Override
  public void onCreate() {
    super.onCreate();

    mNotificationManager = (NotificationManager) getApplicationContext()
        .getSystemService(Context.NOTIFICATION_SERVICE);
  }

  @Override
  public void onDestroy() {
    if (mSocket != null && mSocket.isConnected())
      mSocket.disconnect();

    mSocket = null;

    stopForeground(true);
    
    super.onDestroy();
  }

  @Override
  public IBinder onBind(Intent intent) {
    return new BerryTubeBinder(this);
  }

  @Override
  public int onStartCommand(Intent intent, int flag, int startId) {
    return START_NOT_STICKY;
  }

  /**
   * Connect to default BerryTube Server
   * 
   * @param username
   *            Username to set
   * @param password
   *            Password to set, may be null if the user doesn't have an
   *            account
   * @throws MalformedURLException
   * @throws IllegalStateException
   */
  public void connect(String username, String password, NotificationCompat.Builder notification)
      throws MalformedURLException, IllegalStateException {
    connect(new URL("http://socketio.berrytube.multihoofdrinking.com:8344"), username, password,
        notification);
  }

  /**
   * Connect to a BerryTube (compatible) server
   * 
   * @param url
   *            Socket.io endpoint
   * @param username
   *            Username to set
   * @param password
   *            Password to set, may be null if the user doesn't have an
   *            account
   * @throws MalformedURLException
   * @throws IllegalStateException
   */
  public void connect(String url, String username, String password, NotificationCompat.Builder notification)
      throws MalformedURLException, IllegalStateException {
    connect(new URL(url), username, password, notification);
  }

  /**
   * Connect to a BerryTube (combatible) server
   * 
   * @param url
   *            Socket.io endpoint
   * @param username
   *            Username to set
   * @param password
   *            Password to set, may be null if the user doesn't have an
   *            account
   * @throws IllegalStateException
   */
  public void connect(URL url, String username, String password, NotificationCompat.Builder notification)
      throws IllegalStateException {
    if (mSocket != null && mSocket.isConnected())
      throw new IllegalStateException("Already connected");

    if (username == null)
      throw new NullPointerException("username == null");

    mUsername = username;

    mPassword = password;

    mSocket = new SocketIO(url);
    mSocket.connect(new BerryTubeIOCallback(this));

    mServiceNotification = notification;
    notification.setContentText(getText(R.string.connecting));
    notification.setTicker(getText(R.string.connecting));
    startForeground(KEY_NOTIFICATION_SERVICE, notification.build());
  }

  /**
   * Check if the socket is currently connected to the BerryTube server
   * 
   * @return Connection status
   */
  public boolean isConnected() {
    return mSocket != null && mSocket.isConnected();
  }

  /**
   * Set the callback handler
   * 
   * @param callback
   *            Callback implementation instance
   */
  public void setCallback(BerryTubeCallback callback) {
    mCallback = new WeakReference<>(callback);

    // Clear old notifications
    mMessageNotificationText.clear();
    mMessageNotificationCount = 0;
  }

  /**
   * Convenience for <code>sendChat(String, 0)</code>
   * 
   * @param message
   *            Chat message to send
   */
  public void sendChat(String message) {
    sendChat(message, 0);
  }

  /**
   * Submits a chat message to the server
   * 
   * @param message
   *            Chat message to send
   * @param flair
   *            Number of flair to display, use 0 to show now flair
   */
  public void sendChat(String message, int flair) {
    try {
      JSONObject msg = new JSONObject();
      msg.put("msg", message);

      JSONObject metadata = new JSONObject();
      metadata.put("flair", flair);
      msg.put("metadata", metadata);

      mSocket.emit("chat", msg);
    } catch (JSONException e) {
      Log.w(TAG, e);
    }
  }

  /**
   * Submit a vote on the current poll
   * 
   * @param option
   *            Index of the poll option to vote for
   */
  public void votePoll(int option) {
    try {
      JSONObject msg = new JSONObject();
      msg.put("op", option);

      mSocket.emit("votePoll", msg);
    } catch (JSONException e) {
      Log.w(TAG, e);
    }
  }

  /**
   * Get the current running poll
   * 
   * @return Current Poll or null if no poll is open
   */
  public Poll getPoll() {
    return mPoll;
  }

  /**
   * Get the chat message list
   * 
   * To configure the size of this list use
   * <code>setChatMsgBufferSize(int)</code>
   * 
   * @return ArrayList containing chat messages
   * @see com.trellmor.berrytube.BerryTube setChatMsgBufferSize(int)
   */
  public ArrayList<ChatMessage> getChatMsgBuffer() {
    return mChatMsgBuffer;
  }

  /**
   * Get the configured chat message buffer size
   * 
   * @return chat message buffer max size
   */
  public int getChatMsgBufferSize() {
    return mChatMsgBufferSize;
  }

  /**
   * Set how many ChatMessages are kept in the ChatMsgBuffer
   * 
   * Use 0 to disable the ChatMsgBuffer Use -1 to set it to unlimited
   * 
   * @param chatMsgBufferSize  Size of the chat message buffer
   */
  public void setChatMsgBufferSize(int chatMsgBufferSize) {
    mChatMsgBufferSize = chatMsgBufferSize;

    if (mChatMsgBufferSize == 0)
      mChatMsgBuffer.clear();
    while (mChatMsgBuffer.size() > mChatMsgBufferSize)
      mChatMsgBuffer.remove(0);
  }

  /**
   * Get the nick that was returned from the server
   * 
   * @return Server side nick
   */
  public String getNick() {
    return mNick;
  }

  /**
   * Get the list of chat users
   * 
   * @return User list
   */
  public ArrayList<ChatUser> getUsers() {
    return mUsers;
  }

  /**
   * Get the number of drinks for the current video
   * 
   * @return Drink count
   */
  public int getDrinkCount() {
    return mDrinkCount;
  }

  /**
   * Set a notification that should be displayed if the users name is
   * mentioned
   * 
   * ContentTitle, ContentText and Style will be set on demand
   * 
   * @param notification
   *            NotificationCompate.Builder object initialized with default
   *            values
   */
  public void setNotification(NotificationCompat.Builder notification) {
    mMessageNotification = notification;
  }

  public static boolean isServiceRunning(Context context) {
    ActivityManager manager = (ActivityManager) context
        .getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager
        .getRunningServices(Integer.MAX_VALUE)) {
      if (BerryTube.class.getName()
          .equals(service.service.getClassName())) {
        return true;
      }
    }
    return false;
  }

  Handler getHandler() {
    return mHandler;
  }

  public void disableVideoMessages() {
    if (mSocket != null) {
      mSocket.emit("chatOnly");
    }
  }

  class ConnectTask implements Runnable {
    public void run() {
      if (mSocket == null)
        return;

      try {
        JSONObject login = new JSONObject();
        login.put("nick", mUsername);
        login.put("pass", mPassword);

        mSocket.emit("setNick", login);
      } catch (JSONException e) {
        Log.w(TAG, e);
      }
      mServiceNotification.setContentText(getText(R.string.connected));
      mServiceNotification.setTicker(getText(R.string.connected));
      mNotificationManager.notify(KEY_NOTIFICATION_SERVICE,
          mServiceNotification.build());
    }
  }

  class DisconnectTask implements Runnable {
    @Override
    public void run() {
      if (mCallback.get() != null) {
        mCallback.get().onDisconnect();
      }

      mServiceNotification.setContentText(getText(R.string.disconnected));
      mServiceNotification.setTicker(getText(R.string.disconnected));
      mNotificationManager.notify(KEY_NOTIFICATION_SERVICE,
          mServiceNotification.build());

      stopForeground(true);
      mNotificationManager.cancel(KEY_NOTIFICATION_SERVICE);
      mNotificationManager.cancel(KEY_NOTIFICATION_MESSAGE);
      BerryTube.this.stopSelf();
    }

  }

  class ChatMsgTask implements Runnable {
    private final ChatMessage mChatMsg;

    public ChatMsgTask(ChatMessage chatMsg) {
      this.mChatMsg = chatMsg;
    }

    public void run() {
      if (mChatMsgBufferSize != 0)
        mChatMsgBuffer.add(mChatMsg);

      if (mChatMsgBufferSize > 0) {
        while (mChatMsgBuffer.size() > mChatMsgBufferSize)
          mChatMsgBuffer.remove(0);
      }

      if (mCallback.get() != null) {
        mCallback.get().onChatMessage(mChatMsg);
      }

      if (mCallback.get() == null && mMessageNotification != null) {
        if (mNick != null && mNick.length() > 0
            && mChatMsg.isHighlightable()
            && !mChatMsg.getNick().equals(mNick)
            && mChatMsg.getMsg().contains(mNick)) {

          String msg = mChatMsg.toString();
          mMessageNotificationCount++;

          while (mMessageNotificationText.size() > 5) {
            mMessageNotificationText.remove(0);
          }

          mMessageNotificationText.add(msg);

          String title = msg;
          if (mMessageNotificationCount > 1) {
            title = String.format(getString(R.string.new_messages),
                mMessageNotificationCount);
            NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
            inboxStyle.setBigContentTitle(title);
            for (String line : mMessageNotificationText) {
              inboxStyle.addLine(line);
            }
            mMessageNotification.setStyle(inboxStyle);
          } else {
            mMessageNotification.setStyle(null);
          }

          mMessageNotification.setTicker(msg);
          mMessageNotification.setContentTitle(title);
          mMessageNotification.setContentText(msg);
          mNotificationManager.notify(KEY_NOTIFICATION_MESSAGE,
              mMessageNotification.build());
        }
      }
    }

  }

  class SetNickTask implements Runnable {
    private final String nick;

    public SetNickTask(String nick) {
      this.nick = nick;
    }

    public void run() {
      mNick = nick;

      if (mCallback.get() != null) {
        mCallback.get().onSetNick(nick);
      }
    }
  }

  class LoginErrorTask implements Runnable {
    private final String mError;

    public LoginErrorTask(String error) {
      mError = error;
    }

    public void run() {
      if (mCallback.get() != null) {
        mCallback.get().onLoginError(mError);
      }
    }
  }

  class UserJoinPartTask implements Runnable {
    public final static int ACTION_JOIN = 0;
    public final static int ACTION_PART = 1;

    private final ChatUser user;
    private final int action;

    public UserJoinPartTask(ChatUser user, int action) {
      this.user = user;
      this.action = action;
    }

    public void run() {
      switch (action) {
      case ACTION_JOIN:
        mUsers.add(user);
        break;
      case ACTION_PART:
        mUsers.remove(user);
        break;
      }
    }
  }

  class UserResetTask implements Runnable {
    public void run() {
      mUsers.clear();
    }
  }

  class DrinkCountTask implements Runnable {
    private final int count;

    public DrinkCountTask(int count) {
      this.count = count;
    }

    public void run() {
      mDrinkCount = count;
      if (mCallback.get() != null) {
        mCallback.get().onDrinkCount(this.count);
      }
    }
  }

  class KickedTask implements Runnable {
    public void run() {
      mPoll = null;
      mUsers.clear();

      if (mCallback.get() != null) {
        mCallback.get().onKicked();
      }

      if (mSocket.isConnected())
        mSocket.disconnect();

      BerryTube.this.stopSelf();
    }
  }

  class NewPollTask implements Runnable {
    private final Poll mPoll;

    public NewPollTask(Poll poll) {
      this.mPoll = poll;
    }

    public void run() {
      BerryTube.this.mPoll = mPoll;

      if (mCallback.get() != null) {
        mCallback.get().onNewPoll(mPoll);
      }
    }
  }

  class UpdatePollTask implements Runnable {
    private final int[] mVotes;

    public UpdatePollTask(int[] votes) {
      mVotes = votes;
    }

    public void run() {
      if (mPoll != null) {
        mPoll.update(mVotes);
      }

      if (mCallback.get() != null) {
        mCallback.get().onUpatePoll(mPoll);
      }
    }
  }

  class ClearPollTask implements Runnable {
    public void run() {
      mPoll = null;

      if (mCallback.get() != null) {
        mCallback.get().onClearPoll();
      }
    }
  }

  class NewVideoTask implements Runnable {
    private final String mName;
    private final String mId;
    private final String mType;

    public NewVideoTask(String name, String id, String type) {
      this.mName = name;
      this.mId = id;
      this.mType = type;
    }

    public void run() {
      if (mCallback.get() != null) {
        mCallback.get().onVideoUpdate(mName, mId, mType);
      }
    }
  }
}




Java Source Code List

com.trellmor.berrytube.BerryTubeBinder.java
com.trellmor.berrytube.BerryTubeCallback.java
com.trellmor.berrytube.BerryTubeIOCallback.java
com.trellmor.berrytube.BerryTube.java
com.trellmor.berrytube.ChatMessage.java
com.trellmor.berrytube.ChatUser.java
com.trellmor.berrytube.Poll.java
com.trellmor.berrytubechat.BerryTubeUtils.java
com.trellmor.berrytubechat.ChatActivity.java
com.trellmor.berrytubechat.ChatMessageAdapter.java
com.trellmor.berrytubechat.ChatMessageFormatter.java
com.trellmor.berrytubechat.FlairGetter.java
com.trellmor.berrytubechat.MainActivity.java
com.trellmor.berrytubechat.SettingsActivity.java
com.trellmor.berrytubechat.SettingsFragment.java
com.trellmor.berrytubechat.SimpleCrypto.java