Android Open Source - android-messenger Messenger Activity






From Project

Back to project page android-messenger.

License

The source code is released under:

MIT License

If you think the Android project android-messenger 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

/** 
 * Copyright (c) 2013 Unclouded.io// w  w w.j  a va  2s  . c om
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 */

package com.unclouded.app.messenger;

import java.net.InetAddress;
import java.util.ArrayList;

import com.unclouded.android.*;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class MessengerActivity extends Activity {
  
  // Unclouded event loop
  private Unclouded unclouded;
  
  // Flag to indicate whether device is connected to the network or not
  private boolean isOnline;
  
  // Name that is entered in the splash activity
  private String myName;
  
  // Adapter to update the list view with string messages
  private ArrayAdapter<String> conversationArrayAdapter;
  
  // List of remote references to other devices in the network
  private ArrayList<RemoteReference> buddyList;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_messenger);
    
    buddyList = new ArrayList<RemoteReference>();
    isOnline = false;
    
    Intent intent = getIntent();
    myName = intent.getStringExtra("NAME");
    
    ListView conversationView = (ListView) findViewById(R.id.conversation_view);
    Button sendButton = (Button) findViewById(R.id.send_button);
    
    conversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
    conversationView.setAdapter(conversationArrayAdapter);
    // Make listView to scroll down automatically
    conversationView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    
    // When entering a message, clear the field and broadcast the message
    sendButton.setOnClickListener(new OnClickListener(){

      @Override
      public void onClick(View arg0) {
        EditText msgField = (EditText) findViewById(R.id.msg_field);
        String msg = msgField.getText().toString();
        msgField.setText("");
        broadcastMessage(msg);
      }
      
    });
    
    // Obtain Unclouded event loop
    unclouded = Unclouded.getInstance();
    
    // Go online and connected to the network
    Network network = unclouded.goOnline();
    
    // Monitor the network connection to update the isOnline flag
    network.whenever(new NetworkListener(){
      
      @Override
      public void isOnline(InetAddress ip){
        isOnline = true;
      }
        
      @Override
      public void isOffline(InetAddress ip){
        isOnline = false;
        buddyList.clear();
      }
        
    });
    
    // MESSENGER type tag to associate with the messenger service 
    TypeTag MESSENGER_TYPETAG = new TypeTag("MESSENGER");
    
    // New instance of the Messenger class.
    Messenger myMessenger = new Messenger();
    
    // myMessenger is broadcasted by reference (because Messenger implements UObject)
    // This makes a remote reference to this object to be spread across the network
    unclouded.broadcast(MESSENGER_TYPETAG, myMessenger);
    
    // Listen for remote reference associated with the MESSENGER_TYPETAG type tag
    unclouded.whenever(MESSENGER_TYPETAG, new ServiceListener<RemoteReference>(){
      
      String buddyName;

      @Override
      public void isDiscovered(RemoteReference remoteReference) {
        // When discovering a buddy, register the remote reference to its Messenger object
        buddyList.add(remoteReference);
        // Asynchronously ask for his name
        Promise promise = remoteReference.asyncInvoke("getName");
        // Listen for the name to be returned
        promise.when(new PromiseListener<String>(){

          @Override
          public void isResolved(String name) {
            // When name is returned, store it and print message on the screen
            buddyName = name;
            printBuddyJoinedMessage(name);  
          }
        });
      }
      
      @Override
      public void isDisconnected(RemoteReference remoteReference){
        // When disconnected, remove buddy from list
        buddyList.remove(remoteReference);
        // If name is already resolved, print disconnection message on the screen
        if(buddyName != null){ // Null in case disconnection occurs before name is resolved
          printBuddyDisconnectedMessage(buddyName);  
        }
      }
      
      @Override 
      public void isReconnected(RemoteReference remoteReference){
        // When reconnecting, check whether name has been resolved before
        if(buddyName == null){
          // If not, treat like a new connection
          isDiscovered(remoteReference);
        } else {
          // Otherwise, add reference to list and print message on the screen
          buddyList.add(remoteReference);
          printBuddyJoinedMessage(buddyName);  
        }
      }
      
    });
    
    
  }

  @Override
  public boolean onCreateOptionsMenu(final Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.messenger, menu);
    return true;
  }
  
  @Override
  // Dynamically change menu depending on network status
  public boolean onPrepareOptionsMenu(Menu menu) {
      menu.clear();
      getMenuInflater().inflate(R.menu.messenger, menu);
      MenuItem item = menu.findItem(R.id.action_change_network_status);
      if(isOnline){
        // If connected to the network, show `go offline' action
        item.setTitle(R.string.action_go_offline);
      } else {
        // If disconnected from the network, show `go online' action
        item.setTitle(R.string.action_go_online);  
      }  
      return super.onPrepareOptionsMenu(menu);
  }
  
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
      switch (item.getItemId()) {
          case R.id.action_change_network_status:
            if(isOnline){
              // When clicked and network is online, go offline
              unclouded.goOffline();              
            } else {
              // When clicked and network is offline, go online
              unclouded.goOnline();
            }
              return true;
          default:
              return super.onOptionsItemSelected(item);
      }
  }

  
  // Broadcast a message in the network
  private void broadcastMessage(String msg){
    // Loop over all discovered buddies...
    for(RemoteReference reference: buddyList){
      // ... and asynchronously invoke their receiveMsg method;
      // No need to wait for return value here
      reference.asyncInvoke("receiveMsg", myName, msg);
    }
    // Print message to the screen
    printMessage(myName, msg);
  }
  
  private void printMessage(final String name, final String msg){
    addToAdapter(name+": "+msg);
  }
  
  
  private void printBuddyJoinedMessage(final String name){
    addToAdapter(name+" has joined the conversation.");
  }
  
  private void printBuddyDisconnectedMessage(final String name){
    addToAdapter(name+" has left the conversation.");
  }
  
  // Main method to print something on the screen
  private void addToAdapter(final String msg){
    // Necessary because most invocations are initiated by the Unclouded event loop
    runOnUiThread(new Runnable(){
      public void run(){
        conversationArrayAdapter.add(msg);
      }  
    });  
  }
  
  
  // ------------------------------------------
  
  // Instances of the Messenger class are spread across the network
  // and allow other devices to share messages
  protected class Messenger implements UObject {
    
    public String getName(){ return myName; }
    
    public void receiveMsg(String name, String msg){
      printMessage(name, msg);
    }
    
  }
  
}




Java Source Code List

com.unclouded.app.messenger.MessengerActivity.java
com.unclouded.app.messenger.Splash.java