After i have made my SOCKET.IO server for a multiple room chat application
how do i create the android client using https://github.com/socketio/socket.io-client-java ?
I have searched a lot and haven`t found up to date examples on the client side of socket.io for android , most of the tutorials and examples are for the server side with node.js.
private static NetworkManager mInstance;
private static NetworkInterface mNetworkInterface;
private Socket mSocket;
private int RECONNECTION_ATTEMPT = 10;
private long CONNECTION_TIMEOUT = 30000;
/**
* The purpose of this method is to get the call back for any type of connection error
*/
private Emitter.Listener testing = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("Response", args[0].toString());
}
};
/**
* The purpose of this method is to get the call back for any type of connection error
*/
private Emitter.Listener onConnectionError = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("Response", "onConnectionError");
mNetworkInterface.networkCallReceive(NetworkSocketConstant.SERVER_CONNECTION_ERROR, args);
}
};
/**
* The purpose of this method to get the call back for connection getting timed out
*/
private Emitter.Listener onConnectionTimeOut = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("Response", "onConnectionTimeOut");
mNetworkInterface.networkCallReceive(NetworkSocketConstant.SERVER_CONNECTION_TIMEOUT, args);
}
};
/**
* The purpose of this method is to receive the call back when the server get connected
*/
private Emitter.Listener onServerConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("Response", "onServerConnected");
mNetworkInterface.networkCallReceive(NetworkSocketConstant.SERVER_CONNECTED, args);
}
};
/**
* The purpose of this method is to receive the call back when the server get disconnected
*/
private Emitter.Listener onServerDisconnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("Response", "onServerDisconnection");
mNetworkInterface.networkCallReceive(NetworkSocketConstant.SERVER_DISCONNECTED, args);
}
};
public static NetworkManager getInstance(Context context) {
if (mInstance == null) {
mInstance = new NetworkManager();
}
return mInstance;
}
public void registerInterface(NetworkInterface interfaces) {
mNetworkInterface = interfaces;
}
/**
* The purpose of this method to create the socket object
*/
public void connectToSocket() {
try {
IO.Options opts = new IO.Options();
opts.timeout = CONNECTION_TIMEOUT;
opts.reconnection = true;
opts.reconnectionAttempts = RECONNECTION_ATTEMPT;
opts.reconnectionDelay = 1000;
opts.forceNew = true;
mSocket = IO.socket(NetworkSocketConstant.SOCKET_CONNECTION_URL, opts);
makeConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The purpose of the method is to return the instance of socket
*
* #return
*/
public Socket getSocket() {
return mSocket;
}
/**
* The purpose of this method is to connect with the socket
*/
public void makeConnection() {
if (mSocket != null) {
registerConnectionAttributes();
mSocket.connect();
}
}
/**
* The purpose of this method is to disconnect from the socket interface
*/
public void disconnectFromSocket() {
unregisterConnectionAttributes();
if (mSocket != null) {
mSocket.disconnect();
mSocket = null;
mInstance = null;
BaseApplicationActivty.networkManager = null;
}
}
/**
* The purpose of this method is to register default connection attributes
*/
public void registerConnectionAttributes() {
try {
if (mSocket != null) {
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectionError);
mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectionTimeOut);
mSocket.on(Socket.EVENT_DISCONNECT, onServerDisconnect);
mSocket.on(Socket.EVENT_CONNECT, onServerConnect);
registerHandlers();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The purpose of this method is to unregister default connection attributes
*/
public void unregisterConnectionAttributes() {
try {
if (mSocket != null) {
mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectionError);
mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, onConnectionTimeOut);
mSocket.off(Socket.EVENT_DISCONNECT, onServerDisconnect);
mSocket.off(Socket.EVENT_CONNECT, onServerConnect);
unRegisterHandlers();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The purpose of this method is to unregister the connection from the socket
*/
private void unRegisterHandlers() {
try {
//unregister your all methods here
mSocket.off("hello", testing);
mSocket.off("android", testing);
mSocket.off("hello2", testing);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The purpose of this method is to register the connection from the socket
*/
private void registerHandlers() {
try {
//register you all method here
mSocket.on("hello", testing);
mSocket.on("android", testing);
mSocket.on("hello2", testing);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The purpose of this method is register a single method on server
*
* #param methodOnServer
* #param handlerName
*/
public void registerHandler(String methodOnServer, Emitter.Listener handlerName) {
try {
if (mSocket != null) {
mSocket.on(methodOnServer, handlerName);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The purpose of this method is to unregister a single method from server
*
* #param methodOnServer
* #param handlerName
*/
public void unRegisterHandler(String methodOnServer, Emitter.Listener handlerName) {
try {
if (mSocket != null) {
mSocket.off(methodOnServer, handlerName);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The purpose of this method is to send the data to the server
*
* #param methodOnServer
* #param request
*/
public void sendDataToServer(String methodOnServer, JsonObject request) {
try {
if (mSocket != null && mSocket.connected()) {
Log.e("JSON ", request.toString());
mSocket.emit(methodOnServer, request);
} else {
mNetworkInterface.networkCallReceive(NetworkSocketConstant.SERVER_CONNECTION_ERROR);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public interface NetworkInterface {
void networkCallReceive(int responseType, Object... args);
}
public abstract class BaseActivity extends AppCompatActivity {
/**
* The purpose of this method is to receive the callback from the server
*/
private NetworkManager.NetworkInterface networkInterface = new NetworkManager.NetworkInterface() {
#Override
public void networkCallReceive(int responseType, Object... args) {
switch (responseType) {
case NetworkSocketConstant.SERVER_CONNECTION_TIMEOUT:
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(BaseActivity.this, getResources().getString(R.string.sorry_no_internet_connection), Toast.LENGTH_SHORT).show();
}
});
break;
case NetworkSocketConstant.SERVER_CONNECTION_ERROR:
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(BaseActivity.this, (getResources().getString(R.string.connection_error)), Toast.LENGTH_SHORT).show();
}
});
break;
case NetworkSocketConstant.SERVER_CONNECTED:
SharedPreferenceUtility sharedPreferenceUtility = new SharedPreferenceUtility(BaseActivity.this);
if (sharedPreferenceUtility.getUserId() != null && !sharedPreferenceUtility.getUserId().isEmpty()) {
SocketEmitter.emitSocketConnectionService(BaseActivity.this);
SocketEmitter.emitTesting(BaseActivity.this, "android");
}
break;
case NetworkSocketConstant.SERVER_DISCONNECTED:
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(BaseActivity.this, getResources().getString(R.string.disconnected), Toast.LENGTH_SHORT).show();
}
});
break;
}
};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
socketInit();
}
// initialization socket
private void socketInit() {
if (BaseApplicationActivty.networkManager == null) {
BaseApplicationActivty.networkManager = NetworkManager.getInstance(getApplicationContext());
BaseApplicationActivty.networkManager.registerInterface(networkInterface);
BaseApplicationActivty.networkManager.connectToSocket();
} else {
BaseApplicationActivty.networkManager.registerInterface(networkInterface);
}
}
/**
* This Method must call all ui fragment/activity using Rx subs.
*/
protected abstract void onPermissionResult(int requestCode, boolean isPermissionGranted);
/**
* This Method must call all ui fragment/activity using Rx subs.
*/
protected abstract void onSocketApiResult(int requestCode, Object... args);
/**
* Request For Permission of particular type.
*
* #param requestCode
* #param permission
* #return
*/
public boolean requestPermission(int requestCode, String... permission) {
boolean isAlreadyGranted = false;
isAlreadyGranted = checkPermission(permission);
if (!isAlreadyGranted)
ActivityCompat.requestPermissions(this, permission, requestCode);
return isAlreadyGranted;
}
protected boolean checkPermission(String[] permission) {
boolean isPermission = true;
for (String s : permission)
isPermission = isPermission && ContextCompat.checkSelfPermission(this, s) == PackageManager.PERMISSION_GRANTED;
return isPermission;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onPermissionResult(requestCode, true);
} else {
onPermissionResult(requestCode, false);
Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_LONG).show();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}
it has an example chat app implemented in android link below:
https://github.com/nkzawa/socket.io-android-chat
any way, for using socket.io in android, i think best way is using it inside a service something like this:
public class ChatService extends Service {
public void connectSocket() {
try {
IO.Options options = new IO.Options();
socket = IO.socket("http://192.168.1.1:8080", options);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
}
}).on("error", new Emitter.Listener() {
#Override
public void call(Object... args) {
}
});
socket.connect();
} catch (Exception ignored) {
}
}
#Override
public void onDestroy() {
socket.disconnect();
super.onDestroy();
}
}
Related
I'm trying to keep a socket open during lifecycle changes in a headless fragment with setRetainInstance(true); in onCreate. However, when my app comes back the following exception occurs.
E/Client: Receiving thread loop error
java.net.SocketException: Socket closed
at libcore.io.Posix.recvfromBytes(Native Method)
at libcore.io.Posix.recvfrom(Posix.java:189)
at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:250)
at libcore.io.IoBridge.recvfrom(IoBridge.java:549)
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:481)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
at java.io.InputStreamReader.read(InputStreamReader.java:233)
at java.io.BufferedReader.fillBuf(BufferedReader.java:145)
at java.io.BufferedReader.readLine(BufferedReader.java:397)
at com.gm.popper_6.ConnectionFragment$Client$ReceivingThread.run(ConnectionFragment.java:183)
at java.lang.Thread.run(Thread.java:818)
Here's the code for the fragment
public class ConnectionFragment extends Fragment {
private InetAddress mGoAddress;
private int mGoPort;
private Client mClient;
private static final String TAG = "Connection";
private Server mServer;
private Socket mSocket;
private ConnectionFragmentListener listener;
private String mMessage;
public static ConnectionFragment newInstance(InetAddress address, int port){
Bundle bundle = new Bundle();
bundle.putSerializable("GoAddress", address);
bundle.putInt("GoPort", port);
ConnectionFragment fragment = new ConnectionFragment();
fragment.setArguments(bundle);
return fragment;
}
public interface ConnectionFragmentListener{
void onMessageRcvd(String message);
}
public void setConnectionFragmentListener(ConnectionFragmentListener listener){
this.listener = listener;
}
private void readBundle(Bundle bundle){
if (bundle != null){
mGoAddress = (InetAddress)bundle.getSerializable("GoAddress");
mGoPort = bundle.getInt("GoPort");
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
readBundle(getArguments());
mGoAddress = (InetAddress) getArguments().getSerializable("GoAddress");
mGoPort = getArguments().getInt("GoPort");
mServer = new Server();
}
#Override
public void onStart() {
super.onStart();
}
// THE SERVER CLASS
private class Server{ //DECLARATION
ServerSocket mServerSocket = null;
Thread mThread = null;
public Server(){ //CONSTRUCTOR
mThread = new Thread(new ServerThread());
mThread.start();
}
public void tearDown(){
mThread.interrupt();
try {
mServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Error closing server socket");
}
}
class ServerThread implements Runnable{
#Override
public void run() {
//REMOVE OR COMMENT OUT FOR FINAL
//android.os.Debug.waitForDebugger();
try {
mServerSocket = new ServerSocket(mGoPort, 50, mGoAddress);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()){
try {
mSocket = mServerSocket.accept();
Log.d(TAG, "Connected");
if (mClient == null){
mClient = new Client();
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
}
//THE CLIENT CLASS
private class Client { //DECLARATION
private final String CLIENT_TAG = "Client";
private Thread mSendThread;
private Thread mRecThread;
public Client() { //CONSTRUCTOR
Log.d(CLIENT_TAG, "Creating Client");
mSendThread = new Thread(new SendingThread());
mSendThread.start();
}
class SendingThread implements Runnable { //an inner class of Client
BlockingQueue<String> mMessageQueue;
private int QUEUE_CAPACITY = 10;
public SendingThread() {
mMessageQueue = new ArrayBlockingQueue<String>(QUEUE_CAPACITY);
}
#Override
public void run() {
mRecThread = new Thread(new ReceivingThread());
mRecThread.start();
while (true){
try {
String msg = mMessageQueue.take();
sendMessage(msg);
} catch (InterruptedException e) {
Log.d(CLIENT_TAG, "Sending loop interrupted, exiting");
}
}
}
} //closes SendingThread, an inner class of Client
class ReceivingThread implements Runnable{ //an inner class of Client
#Override
public void run() {
BufferedReader input;
try {
//android.os.Debug.waitForDebugger();
input = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
while (!Thread.currentThread().isInterrupted()){
String messageStr = null;
messageStr = input.readLine(); //Line 183
if (messageStr!= null){
Log.d(CLIENT_TAG, "Read from the stream: " + messageStr);
mMessage = messageStr;
updateMessages(false);
}
else{
Log.d(CLIENT_TAG, "The null!!!");
}
}
input.close();
} catch (IOException e) {
Log.e(CLIENT_TAG, "Receiving thread loop error", e);
e.printStackTrace();
}
} //closes run method
} //closes ReceivingThread, an inner class of Client
public void tearDown(){ //a method of Client
try {
getSocket().close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String msg){ //a method of Client
try {
Socket socket = getSocket(); //should return mSocket
if (socket == null) {
Log.d(CLIENT_TAG, "Socket is null");
} else if (socket.getOutputStream() == null) {
Log.d(CLIENT_TAG, "Socket output stream in null");
}
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(getSocket().getOutputStream())), true);
out.println(msg);
out.flush();
mMessage = msg;
updateMessages(true);
} catch (UnknownHostException e){
Log.d(CLIENT_TAG, "Unkown host", e);
} catch (IOException e) {
Log.d(CLIENT_TAG, "I/O exception", e);
} catch (Exception e){
Log.d(CLIENT_TAG, "Error 3", e);
}
Log.d(CLIENT_TAG, "Message sent: " + msg);
} //closes sendMessage, a method of the inner Client class
} //closes Client class, an inner class of Connection
private Socket getSocket() {
return mSocket;
}
public synchronized void updateMessages(boolean local){
Log.i(TAG, "Updating message: " + mMessage);
if (local){
mMessage = "me: " + mMessage;
}
else{
mMessage = "them: " + mMessage;
}
if (listener!= null){
listener.onMessageRcvd(mMessage);
}
} //closes updateMessages
public void sendMessage(String msg){ //CALL FROM MAIN ACTIVITY
if(mClient != null){ //TO SEND A STRING MESSAGE
mClient.sendMessage(msg);
}
}
public void tearDown(){
mServer.tearDown();
mClient.tearDown();
}
#Override
public void onDestroy() {
tearDown();
super.onDestroy();
}
} //closes class declaration
And here's the main activity
public class MainActivity extends Activity implements ChannelListener, DeviceActionListener,
ConnectionInfoListener, ConnectionFragment.ConnectionFragmentListener{
//CLASS DECLARATIONS
public static final String TAG = "Popper";
private WifiP2pManager manager;
private Boolean isWifiP2pEnabled = false;
ArrayList<Target> mTargets = new ArrayList<Target>(0);
Target mTarget;
TextView rcvd;
TextView ip;
EditText mssg;
String goAddress = "";
InetAddress goInetAddress;
int prefixedPort;
//declare and initialize an intent filter
private final IntentFilter intentFilter = new IntentFilter();
//private final IntentFilter serverFilter = new IntentFilter();
private Channel channel;
private BroadcastReceiver receiver = null;
private ConnectionInfoListener infoListener;
private Intent serverServiceIntent;
ConnectionFragment mConnection;
//????
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
this.isWifiP2pEnabled = isWifiP2pEnabled;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//register app w/p2p framework with call to initialize
//channel is my apps connection to the p2p framework
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
receiver = new P2pReceiver(manager, channel, this);
rcvd = (TextView)findViewById(R.id.rcvd);
rcvd.setMovementMethod(new ScrollingMovementMethod());
//initialize filter and setup to listen for the following broadcast intents
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
Resources res = getResources();
prefixedPort = res.getInteger(R.integer.GOport);
}
#Override
public void onMessageRcvd(String message) {
addLine(message);
}
#Override
protected void onResume() {
super.onResume();
receiver = new P2pReceiver(manager, channel, this);
registerReceiver(receiver, intentFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.action_items, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.atn_direct_discover:
if (!isWifiP2pEnabled) {
NotificationToast.showToast(MainActivity.this, "Enable P2P!!!");
return true;
}
final TargetListFragment fragment = (TargetListFragment) getFragmentManager()
.findFragmentById(R.id.frag_list);
fragment.onInitiateDiscovery();
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
NotificationToast.showToast(MainActivity.this, "Discovery initiated");
}
#Override
public void onFailure(int reason) {
NotificationToast.showToast(MainActivity.this, "Discovery failed");
}
});
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override //this is associated with ChannelListener
public void onChannelDisconnected() { //removal causes error.
}
#Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
goAddress = info.groupOwnerAddress.getHostAddress(); //this returns a string rep of add.
goInetAddress = info.groupOwnerAddress; //this returns actual inet add.
ip = (TextView) findViewById(R.id.ip);
mssg = (EditText) findViewById(R.id.mssg);
ip.setText(goAddress + ":" + "8080"); //display GO address and IP
startConnectionFragment();
}
//this override method is triggered by TargetListFragment's DeviceActionListener
#Override
public void connect(WifiP2pConfig config) {
manager.connect(channel, config, new ActionListener() {
#Override
public void onSuccess() {
//maybe use this to gray out and disable the listview object that connected
}
#Override
public void onFailure(int reason) {
}
});}
public void startConnectionFragment(){
mConnection = ConnectionFragment.newInstance(goInetAddress, prefixedPort);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(mConnection, "TAG_1");
ft.commit();
mConnection.setConnectionFragmentListener(this);
}
public void addLine(String line){
final String msg = line;
runOnUiThread(new Runnable(){
#Override
public void run() {
rcvd.append("\n" + msg);
}
});
}
#Override
public void onTargetListClick(Target target) {
mTarget = target;
}
public void stopServer() {
if(serverServiceIntent != null)
{
stopService(serverServiceIntent);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mConnection != null){
//mConnection.tearDown();
}
stopServer();
}
public void SendMessage(View v){
EditText txt = (EditText) this.findViewById(R.id.mssg);
String str = txt.getText().toString();
mConnection.sendMessage(str);
txt.getText().clear();
}
}
Could this have something to do with detaching when the app goes on pause or stop and not re-attaching when it comes back to life? Are there other things I should be considering?
Ultimately the app needs to keep communication open to about 5 or 6 devices over p2p. if there is a better strategy I'm open to suggestions. Thanks.
Update - So I've confirmed that both the onDestroy and onDetach methods of the fragment are firing when the main activity goes onStop. Since I have a method to close the sockets on death of the fragment they are getting closed. The big question now is how to keep the fragment alive?
You should maybe create a helper class that will open/close sockets on behalf of other classes, such as that fragment, that helper class won't be subjected to any life cycle events, and can be kept running as long as the Application process is alive
I am making my first Socket.io based android application. The socket sends and receives data from a web service. There are a number of screens in the application for different features. How do i use the same socket connection in these different activities.
I have tried setting and storing the Socket Object in the Application class and it appears to work well but when the application goes into the background and left there for some time the application is killed and the socket object is then NULL causing the aoo to crash with a null pointer exception.
public class MyApplication extends Application {
private Socket mSocket;
private final String TAG = "Application Class";
public Socket getSocket() {
return mSocket;
}
public Socket createSocket() {
try {
Manager manager = new Manager(new URI("http://0.0.0.0"));
} catch (URISyntaxException URIse) {
URIse.printStackTrace();
}
return mSocket;
}
}
Access the socket in the activities
MyApplication app;
app = (MyApplication ) getApplication();
app.getSocket;
You can create a singleton manager class for socket. It will allow you to keep single socket connection accessible to entire app. See following code and change it according to your requirement
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.util.Log;
import com.myapp.app.ui.adapter.OnSocketConnectionListener;
import java.util.ArrayList;
import java.util.List;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
/**
* Created by penguin on 6/30/2016.
* <p/>
* SocketManager manages socket and internet connection.
* It also provide listeners for connection status
*/
public class SocketManager {
/**
* The constant STATE_CONNECTING.
*/
public static final int STATE_CONNECTING = 1;
/**
* The constant STATE_CONNECTED.
*/
public static final int STATE_CONNECTED = 2;
/**
* The constant STATE_DISCONNECTED.
*/
public static final int STATE_DISCONNECTED = 3;
/**
* The constant CONNECTING.
*/
public static final String CONNECTING = "Connecting";
/**
* The constant CONNECTED.
*/
public static final String CONNECTED = "Connected";
/**
* The constant DISCONNECTED.
*/
public static final String DISCONNECTED = "Disconnected";
private static SocketManager instance;
private SocketManager() {
}
/**
* Gets instance.
*
* #return the instance
*/
public synchronized static SocketManager getInstance() {
if (instance == null) {
instance = new SocketManager();
}
return instance;
}
/**
* The constant TAG.
*/
public static final String TAG = SocketManager.class.getSimpleName();
private Socket socket;
private List<OnSocketConnectionListener> onSocketConnectionListenerList;
/**
* Connect socket.
*
* #param token the token
* #param userId the user id
* #param host the host
* #param port the port
*/
public void connectSocket(String token,String userId, String host, String port) {
try {
if(socket==null){
String serverAddress = host+":"+port;
IO.Options opts = new IO.Options();
opts.forceNew = true;
opts.reconnection = true;
opts.reconnectionAttempts=5;
opts.secure = true;
opts.query = "token=" + token + "&" + "user_id=" + userId;
socket = IO.socket(serverAddress, opts);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
fireSocketStatus(SocketManager.STATE_CONNECTED);
Log.i(TAG, "socket connected");
}
}).on(Socket.EVENT_RECONNECTING, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(TAG, "Socket reconnecting");
fireSocketStatus(SocketManager.STATE_CONNECTING);
}
}).on(Socket.EVENT_RECONNECT_FAILED, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(TAG, "Socket reconnection failed");
// fireSocketStatusIntent(SocketManager.STATE_DISCONNECTED);
}
}).on(Socket.EVENT_RECONNECT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(TAG, "Socket reconnection error");
// fireSocketStatus(SocketManager.STATE_DISCONNECTED);
}
}).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(TAG, "Socket connect error");
fireSocketStatus(SocketManager.STATE_DISCONNECTED);
socket.disconnect();
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(TAG, "Socket disconnect event");
fireSocketStatus(SocketManager.STATE_DISCONNECTED);
}
}).on(Socket.EVENT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
try {
final String error = (String) args[0];
Log.e(TAG + " error EVENT_ERROR ", error);
if (error.contains("Unauthorized") && !socket.connected()) {
if (onSocketConnectionListenerList != null) {
for (final OnSocketConnectionListener listener : onSocketConnectionListenerList) {
new Handler(Looper.getMainLooper())
.post(new Runnable() {
#Override
public void run() {
listener.onSocketEventFailed();
}
});
}
}
}
} catch (Exception e) {
Log.e(TAG, e.getMessage() != null ? e.getMessage() : "");
}
}
}).on("Error", new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, " Error");
}
});
socket.connect();
}else if(!socket.connected()){
socket.connect();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private int lastState = -1;
/**
* Fire socket status intent.
*
* #param socketState the socket state
*/
public synchronized void fireSocketStatus(final int socketState) {
if(onSocketConnectionListenerList !=null && lastState!=socketState){
lastState = socketState;
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
for(OnSocketConnectionListener listener: onSocketConnectionListenerList){
listener.onSocketConnectionStateChange(socketState);
}
}
});
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
lastState=-1;
}
},1000);
}
}
/**
* Fire internet status intent.
*
* #param socketState the socket state
*/
public synchronized void fireInternetStatusIntent(final int socketState) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
if(onSocketConnectionListenerList !=null){
for(OnSocketConnectionListener listener: onSocketConnectionListenerList){
listener.onInternetConnectionStateChange(socketState);
}
}
}
});
}
/**
* Gets socket.
*
* #return the socket
*/
public Socket getSocket() {
return socket;
}
/**
* Sets socket.
*
* #param socket the socket
*/
public void setSocket(Socket socket) {
this.socket = socket;
}
/**
* Destroy.
*/
public void destroy(){
if (socket != null) {
socket.off();
socket.disconnect();
socket.close();
socket=null;
}
}
/**
* Sets socket connection listener.
*
* #param onSocketConnectionListenerListener the on socket connection listener listener
*/
public void setSocketConnectionListener(OnSocketConnectionListener onSocketConnectionListenerListener) {
if(onSocketConnectionListenerList ==null){
onSocketConnectionListenerList = new ArrayList<>();
onSocketConnectionListenerList.add(onSocketConnectionListenerListener);
}else if(!onSocketConnectionListenerList.contains(onSocketConnectionListenerListener)){
onSocketConnectionListenerList.add(onSocketConnectionListenerListener);
}
}
/**
* Remove socket connection listener.
*
* #param onSocketConnectionListenerListener the on socket connection listener listener
*/
public void removeSocketConnectionListener(OnSocketConnectionListener onSocketConnectionListenerListener) {
if(onSocketConnectionListenerList !=null
&& onSocketConnectionListenerList.contains(onSocketConnectionListenerListener)){
onSocketConnectionListenerList.remove(onSocketConnectionListenerListener);
}
}
/**
* Remove all socket connection listener.
*/
public void removeAllSocketConnectionListener() {
if(onSocketConnectionListenerList !=null){
onSocketConnectionListenerList.clear();
}
}
/**
* The type Net receiver.
*/
public static class NetReceiver extends BroadcastReceiver {
/**
* The Tag.
*/
public final String TAG = NetReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
SocketManager.getInstance().fireInternetStatusIntent(
isConnected?SocketManager.STATE_CONNECTED:SocketManager.STATE_DISCONNECTED);
if (isConnected) {
if(SocketManager.getInstance().getSocket()!=null
&& !SocketManager.getInstance().getSocket().connected()){
SocketManager.getInstance().fireSocketStatus(SocketManager.STATE_CONNECTING);
}
PowerManager powerManager =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn;
if (android.os.Build.VERSION.SDK_INT
>= android.os.Build.VERSION_CODES.KITKAT_WATCH) {
isScreenOn = powerManager.isInteractive();
}else{
//noinspection deprecation
isScreenOn = powerManager.isScreenOn();
}
if (isScreenOn && SocketManager.getInstance().getSocket() !=null) {
Log.d(TAG, "NetReceiver: Connecting Socket");
if(!SocketManager.getInstance().getSocket().connected()){
SocketManager.getInstance().getSocket().connect();
}
}
}else{
SocketManager.getInstance().fireSocketStatus(SocketManager.STATE_DISCONNECTED);
if(SocketManager.getInstance().getSocket() !=null){
Log.d(TAG, "NetReceiver: disconnecting socket");
SocketManager.getInstance().getSocket().disconnect();
}
}
}
}
}
Connecting socket
You can connecting/disconnect socket from any activity or background service
SocketManager.getInstance().connectSocket(user.getToken(), user.getUserId(),
getResources().getString(R.string.host), "8000");
Update
If in background your app is killed socket will also destroy. If you want socket to remain connected in background you have to make you own logic with background service which has nothing to do with socket.
implement OnSocketConnectionListener
public interface OnSocketConnectionListener {
void onSocketEventFailed();
void onSocketConnectionStateChange(int socketState);
void onInternetConnectionStateChange(int socketState);
}
I am developing an app that connects to a Chromecast, everything works fine when I do it from one activity, the problem is, that I want that activity to be fullscreen with no action bar, and no soft buttons. I am achiving that, hiding them when the users connects to the Chromecast, but it would be better if the users connect from the first activity (with action bar) and then goes to the second activity and the magic occurs there. But I can't pass the session between the activities. I have follow this tutorial to make the communication with the chromecast but tried to change a little to make the 2 acitivites communication.
Of course I have tested it and it returns a NullPointerException.
ConnectionFailedListener.java
public class ConnectionFailedListener implements GoogleApiClient.OnConnectionFailedListener {
private String TAG;
private MyConnectionCallbacks myConnectionCB;
public ConnectionFailedListener(String _TAG)
{
this.TAG=_TAG;
}
private void setMyConnectionCallBack(MyConnectionCallbacks _ConnectionCallbacks)
{
this.myConnectionCB = _ConnectionCallbacks;
}
#Override
public void onConnectionFailed(ConnectionResult result)
{
Log.e(TAG, "onConnectionFailed ");
myConnectionCB.teardown();
}
}
Channel.java
public class EventChannel implements Cast.MessageReceivedCallback
{
private Context myContext;
private String TAG;
/**
* #return custom namespace
*/
public EventChannel(Context _context, String _TAG)
{
this.myContext = _context;
this.TAG = _TAG;
}
public String getNamespace()
{
return myContext.getString(R.string.namespace);
}
/*
* Receive message from the receiver app
*/
#Override
public void onMessageReceived(CastDevice castDevice, String namespace,String message)
{
Log.d(TAG, "onMessageReceived: " + message);
}
}
ConnectionCallbacks.java
public class MyConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks
{
private String TAG;
private Context myContext;
public CastDevice mSelectedDevice;
private GoogleApiClient mApiClient;
private boolean mWaitingForReconnect;
private EventChannel mEventChannel;
private String mSessionId;
private boolean mApplicationStarted;
private EventChannel myChannel;
public MyConnectionCallbacks(Context _context, String _TAG)
{
this.myContext=_context;
this.TAG = _TAG;
}
public void setApiClient(GoogleApiClient _newApiClient)
{
this.mApiClient = _newApiClient;
}
#Override
public void onConnected(Bundle connectionHint)
{
Log.d(TAG, "onConnected");
if (mApiClient == null)
{
// We got disconnected while this runnable was pending execution.
return;
}
try
{
if (mWaitingForReconnect)
{
mWaitingForReconnect = false;
// Check if the receiver app is still running
if ((connectionHint != null) && connectionHint.getBoolean(Cast.EXTRA_APP_NO_LONGER_RUNNING))
{
Log.d(TAG, "App is no longer running");
teardown();
}
else
{// Re-create the custom message channel
try
{
Cast.CastApi.setMessageReceivedCallbacks(mApiClient,mEventChannel.getNamespace(),mEventChannel);
}
catch (IOException e)
{
Log.e(TAG, "Exception while creating channel", e);
}
}
}
else
{// Launch the receiver app because is connected
Cast.CastApi.launchApplication(mApiClient,myContext.getString(R.string.app_id), false).setResultCallback(
new ResultCallback<Cast.ApplicationConnectionResult>()
{
#Override
public void onResult(Cast.ApplicationConnectionResult result) {
Status status = result.getStatus();
Log.d(TAG,"ApplicationConnectionResultCallback.onResult: statusCode"+ status.getStatusCode());
if (status.isSuccess())
{
ApplicationMetadata applicationMetadata = result.getApplicationMetadata();
mSessionId = result.getSessionId();
String applicationStatus = result.getApplicationStatus();
boolean wasLaunched = result.getWasLaunched();
Log.d(TAG,"application name: "+ applicationMetadata.getName()
+ ", status: "+ applicationStatus
+ ", sessionId: "+ mSessionId
+ ", wasLaunched: "+ wasLaunched);
mApplicationStarted = true;
// Create the custom message channel
mEventChannel = new EventChannel(myContext,TAG);
try
{
Cast.CastApi.setMessageReceivedCallbacks(mApiClient,mEventChannel.getNamespace(),mEventChannel);
}
catch (IOException e)
{
Log.e(TAG,"Exception while creating channel",e);
}
// set the initial instructions on the receiver
sendMessage("starting from mobile");
}
else
{
Log.e(TAG,"application could not launch");
teardown();
}
}
});
}
}
catch (Exception e)
{
Log.e(TAG, "Failed to launch application", e);
}
}
#Override
public void onConnectionSuspended(int cause)
{
Log.d(TAG, "onConnectionSuspended");
mWaitingForReconnect = true;
}
public void sendMessage(String message)
{
if (mApiClient != null && mEventChannel != null)
{
try
{
Cast.CastApi.sendMessage(mApiClient,mEventChannel.getNamespace(), message)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status result)
{
if (!result.isSuccess())
{
Log.e(TAG, "Sending message failed");
}
}
});
}
catch (Exception e)
{
Log.e(TAG, "Exception while sending message", e);
}
}
else
{
Toast.makeText(myContext, message, Toast.LENGTH_SHORT).show();
}
}
public void teardown()
{
Log.d(TAG, "teardown");
if (mApiClient != null)
{
if (mApplicationStarted)
{
if (mApiClient.isConnected() || mApiClient.isConnecting())
{
try
{
Cast.CastApi.stopApplication(mApiClient, mSessionId);
if (myChannel != null)
{
Cast.CastApi.removeMessageReceivedCallbacks(mApiClient,myChannel.getNamespace());
myChannel = null;
}
}
catch (IOException e)
{
Log.e(TAG, "Exception while removing channel", e);
}
mApiClient.disconnect();
}
mApplicationStarted = false;
}
mApiClient = null;
}
mSelectedDevice = null;
mWaitingForReconnect = false;
mSessionId = null;
}
}
MediaRouterCallback.java
public class MyMediaRouterCallback extends MediaRouter.Callback {
private GoogleApiClient mApiClient;
private Cast.Listener mCastListener;
private Context myContext;
private ConnectionFailedListener mConnectionFailedListener;
public MyConnectionCallbacks mConnectionCallbacks;
public String TAG;
//private String mSessionId;
public MyMediaRouterCallback(Context _context, String _TAG)
{
this.myContext = _context;
this.TAG = _TAG;
mConnectionCallbacks = new MyConnectionCallbacks(myContext,TAG);
}
#Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "onRouteSelected");
mConnectionCallbacks.mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
launchReceiver();
}
#Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "onRouteUnselected: info=" + info);
mConnectionCallbacks.teardown();
mConnectionCallbacks.mSelectedDevice = null;
}
private void launchReceiver()
{
try
{
mCastListener = new Cast.Listener() {
#Override
public void onApplicationDisconnected(int errorCode) {
Log.d(TAG, "application has stopped");
mConnectionCallbacks.teardown();
}
};
//Constructors for Google Play Services Connection
//mConnectionCallbacks = new MyConnectionCallbacks(myContext,TAG);
mConnectionFailedListener = new ConnectionFailedListener(TAG);
Cast.CastOptions.Builder apiOptionsBuilder =
Cast.CastOptions.builder(mConnectionCallbacks.mSelectedDevice, mCastListener);
// ApiClient to Connect to Google Play services
mApiClient = new GoogleApiClient.Builder(myContext)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(mConnectionCallbacks)
.addOnConnectionFailedListener(mConnectionFailedListener)
.build();
mConnectionCallbacks.setApiClient(mApiClient);//setting ApiClient to achieve sendMessage
//Connect to Google Play services
mApiClient.connect();
}
catch (Exception e)
{
Log.e(TAG, "Failed launchReceiver", e);
}
}
}
FirstActivity (where the chromecast is connected)
public class ConnectCastActivity extends ActionBarActivity {
private static final String TAG = ConnectCastActivity.class.getSimpleName();
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
actionBar.setBackgroundDrawable(new ColorDrawable(android.R.color.transparent));
setContentView(R.layout.activity_connect_cast);
// Configure Cast device discovery
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder().addControlCategory(CastMediaControlIntent.categoryForCast(getResources().getString(R.string.app_id))).build();
mMediaRouterCallback = new MyMediaRouterCallback(getApplicationContext(),TAG);
TextView myTextView = (TextView)findViewById(R.id.txt_helloworld);
myTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(getApplicationContext(),MainActivity.class);
startActivity(i);
}
});
}
#Override
protected void onStart() {
super.onStart();
// Start media router discovery
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
#Override
protected void onStop() {
// End media router discovery
Log.w(TAG, "onStop");
//mMediaRouter.removeCallback(mMediaRouterCallback);
super.onStop();
}
#Override
public void onDestroy() {
Log.w(TAG, "onDestroy");
// mMediaRouterCallback.onRouteUnselected(mMediaRouter,null);
super.onDestroy();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_connect_cast, menu);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat.getActionProvider(mediaRouteMenuItem);
// Set the MediaRouteActionProvider selector for device discovery.
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);
return true;
}
}
SecondActivity (the one that will send the message)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MediaRouter mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mConnectionCallbacks = new MyConnectionCallbacks(getApplicationContext(),TAG);
setContentView(R.layout.activity_main);
//What should I put here?
}
If you have an application with multiple activities, you are better off if you do not tie the cast connectivity and related states to any of those activities, instead you can have a singleton, or use your Application instance or use a background service or ... to maintain the connection and access the required pieces that are maintained in that global place. If it fits your requirement, you might want to use the CastCompanionLibrary that already does most of the routine stuff for you; if not, you can take a look at it and the see how the CastVideos sample app uses that and try to do something similar for your application.
I am trying to discover local server(apache tomcat) running on http://localhost:8080 through my android device.To achieve that i thought of using jmdns library from heere
but i am really confused about how to proceed with as i don't understand the networking much.
here is the codei have written with little googling but any help would a be a great help.
public class DnssdDiscovery extends Activity {
protected static final String TAG = DnssdDiscovery.class.getSimpleName();
android.net.wifi.WifiManager.MulticastLock lock;
android.os.Handler handler = new android.os.Handler();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
handler.postDelayed(new Runnable() {
public void run() {
setUp();
}
}, 1000);
} /** Called when the activity is first created. */
// private String type = "_workstation._tcp.local.";_http._tcp.local.
private String type = "_http._tcp.local.";
private JmDNS jmdns = null;
private ServiceListener listener = null;
private ServiceInfo serviceInfo;
private void setUp() {
android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) getSystemService(android.content.Context.WIFI_SERVICE);
lock = wifi.createMulticastLock("mylockthereturn");
lock.setReferenceCounted(true);
lock.acquire();
try {
InetAddress Address = InetAddress.getLocalHost();
Log.e("Local :", Address.getHostName());
jmdns = JmDNS.create(Address);
jmdns.addServiceListener(type, listener = new ServiceListener() {
#Override
public void serviceResolved(ServiceEvent ev) {
notifyUser("Service resolved: " + ev.getInfo().getQualifiedName() + " port:" + ev.getInfo().getPort());
}
#Override
public void serviceRemoved(ServiceEvent ev) {
notifyUser("Service removed: " + ev.getName());
}
#Override
public void serviceAdded(ServiceEvent event) {
// Required to force serviceResolved to be called again (after the first search)
jmdns.requestServiceInfo(event.getType(), event.getName(), 1);
}
});
serviceInfo = ServiceInfo.create("_http._tcp.local.", "AndroidTest", 8080, "plain test service from android");
jmdns.registerService(serviceInfo);
} catch (IOException e) {
e.printStackTrace();
return;
}
}
private void notifyUser(final String msg) {
handler.postDelayed(new Runnable() {
public void run() {
TextView t = (TextView)findViewById(R.id.text);
t.setText(msg+"\n=== "+t.getText());
}
}, 1);
}
#Override
protected void onStart() {
super.onStart();
//new Thread(){public void run() {setUp();}}.start();
}
#Override
protected void onStop() {
if (jmdns != null) {
if (listener != null) {
jmdns.removeServiceListener(type, listener);
listener = null;
}
jmdns.unregisterAllServices();
try {
jmdns.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jmdns = null;
}
//repo.stop();
//s.stop();
lock.release();
super.onStop();
}
}
I have successfully integrated Twilio SDK for android but when i am trying to make call with it its not connecting and showing error message in logcat i am getting following errors:
1) Failed to hangup call due to error code: 70015, message: pjsua_call_hangup(): Object already exists (PJ_EEXISTS)
2) Connection disconnected with error code 31000 and message Generic error
this both errors occurs when i am calling disconnect method if i comment this method then my calling is working fine and i make call but if i call this method phone.disconnect(), i am getting error shown as above.
This is my methods which i am using to make calls and to disconnect the calls.
////// To Make Calls
public void connect(String phoneNumber) {
Map parameters = new HashMap();
parameters.put("PhoneNumber", phoneNumber);
connection = device.connect(parameters, null /* ConnectionListener */);
if (connection == null)
Log.w(TAG, "Failed to create new connection");
}
// To Disconnect Phone
public void disconnect() {
if (connection != null) {
connection.disconnect();
connection = null; // will null out in onDisconnected()
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnecting();
}
}
and on my OnClick event:
public void onClick(View view) {
if (view.getId() == R.id.dialButton)
Toast.makeText(getApplicationContext(), "Dialing...", Toast.LENGTH_LONG).show();
phone.connect("PHONE NUMBER");
if (view.getId() == R.id.hangupButton)
Toast.makeText(getApplicationContext(), "Call Disconnected...", Toast.LENGTH_LONG).show();
phone.disconnect();
Please suggest me and help me because i tried all possible thing for hangout but still not able to solve it.Thanks in advance. ![enter image description here][1]
I am sharing my working class for twilio SDK setup.
This the calls which is working perfectly for me.I would like to share my class so any one can take reference of it.
This is the Base class which handle all the events of twillio Calling and Disconnecting the call.
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.media.AudioManager;
import android.util.Log;
import android.view.Gravity;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import com.twilio.client.Connection;
import com.twilio.client.Connection.State;
import com.twilio.client.ConnectionListener;
import com.twilio.client.Device;
import com.twilio.client.DeviceListener;
import com.twilio.client.PresenceEvent;
import com.twilio.client.Twilio;
public class MonkeyPhone implements Twilio.InitListener, DeviceListener, ConnectionListener {
private static final String TAG = "MonkeyPhone";
private Device device;
private Connection connection;
private final Context context;
private BasicConnectionListener basicConnectionListener;
private BasicDeviceListener basicDeviceListener;
private Connection pendingIncomingConnection;
InputMethodManager imm;
private boolean speakerEnabled;
private boolean muteEnabled;
public interface BasicConnectionListener {
public void onIncomingConnectionDisconnected();
public void onConnectionConnecting();
public void onConnectionConnected();
public void onConnectionFailedConnecting(Exception error);
public void onConnectionDisconnecting();
public void onConnectionDisconnected();
public void onConnectionFailed(Exception error);
}
public interface BasicDeviceListener {
public void onDeviceStartedListening();
public void onDeviceStoppedListening(Exception error);
}
public MonkeyPhone(Context context) {
this.context = context;
Twilio.initialize(context, this /* Twilio.InitListener */);
}
public void setListeners(BasicConnectionListener basicConnectionListener, BasicDeviceListener basicDeviceListener) {
this.basicConnectionListener = basicConnectionListener;
this.basicDeviceListener = basicDeviceListener;
}
/* Twilio.InitListener method */
#Override
public void onInitialized() {
Log.d(TAG, "Twilio SDK is ready");
try {
// String capabilityToken =
// HttpHelper.httpGet("http://------/mobile/auth.php");
String capabilityToken = HttpHelper.httpGet("http:------/auth.php");
device = Twilio.createDevice(capabilityToken, null /* DeviceListener */);
} catch (Exception e) {
Log.e(TAG, "Failed to obtain capability token: " + e.getLocalizedMessage());
}
}
/* Twilio.InitListener method */
#Override
public void onError(Exception e) {
Log.e(TAG, "Twilio SDK couldn't start: " + e.getLocalizedMessage());
}
#Override
protected void finalize() {
if (device != null)
device.release();
if (connection != null)
connection.disconnect();
}
// To Make Calls
public void connect(String phoneNumber) {
Toast toast = Toast.makeText(context, "Dialing...", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("PhoneNumber", phoneNumber);
String capabilityToken;
try {
// capabilityToken =
// HttpHelper.httpGet("http://------/mobile/auth.php");
capabilityToken = HttpHelper.httpGet("http://------/mobile/auth.php");
device = Twilio.createDevice(capabilityToken, null /* DeviceListener */);
} catch (Exception e1) {
e1.printStackTrace();
}
try {
device.disconnectAll();
} catch (Exception e) {
e.printStackTrace();
}
connection = device.connect(parameters, null /* ConnectionListener */);
if (connection == null) {
Log.w(TAG, "Failed to create new connection");
}
}
// To Disconnect Phone
public void disconnect() {
Toast toast = Toast.makeText(context, "Call Disconnected...", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
if (connection != null) {
connection.disconnect();
connection = null; // will null out in onDisconnected()
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnecting();
}
}
public void setSpeakerEnabled(boolean speakerEnabled) {
if (speakerEnabled != this.speakerEnabled) {
this.speakerEnabled = speakerEnabled;
updateAudioRoute();
}
}
private void updateAudioRoute() {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(speakerEnabled);
}
public void setMuteEnabled(boolean muteEnabled) {
if (muteEnabled != this.muteEnabled) {
this.muteEnabled = muteEnabled;
updateAudioRouteForMute();
}
}
private void updateAudioRouteForMute() {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setMicrophoneMute(muteEnabled);
}
public State status() {
connection.getState();
State statusHere = connection.getState();
return statusHere;
}
#Override
public void onConnected(Connection arg0) {
updateAudioRoute();
updateAudioRouteForMute();
if (basicConnectionListener != null) {
basicConnectionListener.onConnectionConnected();
}
}
#Override
public void onConnecting(Connection arg0) {
if (basicConnectionListener != null) {
basicConnectionListener.onConnectionConnecting();
}
}
#Override
public void onDisconnected(Connection inConnection) {
if (inConnection == connection) {
connection = null;
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnected();
} else if (inConnection == pendingIncomingConnection) {
pendingIncomingConnection = null;
if (basicConnectionListener != null)
basicConnectionListener.onIncomingConnectionDisconnected();
}
}
#Override
public void onDisconnected(Connection inConnection, int arg1, String inErrorMessage) {
if (inConnection == connection) {
connection = null;
if (basicConnectionListener != null)
basicConnectionListener.onConnectionFailedConnecting(new Exception(inErrorMessage));
}
}
#Override
public void onPresenceChanged(Device arg0, PresenceEvent arg1) {
}
#Override
public void onStartListening(Device arg0) {
if (basicDeviceListener != null) {
basicDeviceListener.onDeviceStartedListening();
}
}
#Override
public void onStopListening(Device arg0) {
if (basicDeviceListener != null) {
basicDeviceListener.onDeviceStoppedListening(null);
}
}
#Override
public void onStopListening(Device arg0, int arg1, String arg2) {
}
#Override
public boolean receivePresenceEvents(Device arg0) {
return false;
}
}
You can use this class like:
private MonkeyPhone phone;
//On create
phone = new MonkeyPhone(getApplicationContext());
//On Call Button Click
#Override
public void onClick(View view) {
if (view.getId() == R.id.btnCallHere) {
phone.connect(newContact);
} else if (view.getId() == R.id.btnDisconnectHere) {
phone.disconnect();
}