I need a design patter to make a rabbitmq singleton connection that I can that will restart on connection loss/ internet provider switch.
My problem is that the connection is realised on another thread (asynctask) due to android main thread policy.
I use this connection for two services that consume and push.
public class RabbitSingletonConnection {
public static RabbitSingletonConnection instance;
private Connection connection;
private RabbitSingletonConnection() {
}
public static RabbitSingletonConnection getInstance() {
if (instance == null) {
instance = new RabbitSingletonConnection();
}
return instance;
}
public void Connect(RabbitMQConnectionCallback callback) {
if (connection != null && connection.isOpen()) {
LogUtil.hecsLog("RabbitSingletonConnection", "already connected");
callback.onConnect(connection);
return;
}
new RabbitConnectAsync(callback).execute("ip","user", "pass");
}
public void setConnection(Connection connection) {
this.connection = connection;
}
public Connection getConnection() {
return connection;
}
}
Problem is that this LogUtil.hecsLog("RabbitSingletonConnection", "already connected"); never occurs.
I have been digging and discovered something "Thread safe singleton using classloader declaration or ENUM approach", but this does not include a callback method.
EDIT
RabbitSingletonConnection.getInstance().Connect(new RabbitMQConnectionCallback() {
#Override
public void onConnect(Connection result) {
if (result != null && result.isOpen()){
RabbitSingletonConnection.getInstance().setConnection(result);
LogUtil.hecsLog(LOG, "Service has started");
}
}
});
This is a example Is it necessary to rebuild RabbitMQ connection each time a message is to be sent but I cannot make the connection in the constructor because it needs a thread to handle TimeoutException.
My goal is to start service after the rabbitMQ async task connects.
Do I need dependency injection?
I think I figured it out, I was starting/stopping the services on connectivity gain/loss. I looked at the facebook app and the services never stop, so the logic answer is to reset the workflow in the service not the service itslef.
Related
I want to know, does any way exist to communicate with system during instrumentation test execution.
For example:
I have a phone with IR port on onboard & I can work with it through private SDK, also I can tune it with my application. In my Instrumentation test cases I want test app behavior based on external events which I want to configure before test separate test execution.
It's looks like
#Test
public void test() throws Exception {
setupExternalCondition(condition1_ON); // setup external transiver
assertNotNull(IR.read());
assertTrue(assertIR.write());
setupExternalCondition(condition1_OFF);
assertNotNull(IR.read());
assertFalse(IR.write());
}
It's very simple example but there is a lot of "conditions", and sdk updating frequencies to high. I can't do all of this verification manually, and can't ask "transiver&SDK team" make a mock states list for writing just a unit test for coverage. So I want somehow inject external component execution to TestRuner for receiving events(or testName before test case execution) on local machine(or CI machine) to setup external condition.
Simple solution(I think) to run a tcp server on appUnderTest and request external condition change - I am not sure does it possible, and not sure about stable connection(wifi), so may be it's possible to do over adb.
Any suggestions?
P.S: test device has root permissions.
So, find not bad but not ideal solution.
Still wait for better proposition, if not may be this answer will be helpful for someone;
For "building the bridge" between local machine and AndroidJUnitTest I add next class to tests:
class IPCServiceBridge extends BroadcastReceiver {
private static final String FILTER_ID = "IPC_SERVICE";
private static IPCServiceBridge sInstance;
private boolean mIsPermitted;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("ipc.service.action")) {
mIsPermitted = true;
}
}
public static IPCServiceBridge getInstance() {
if (sInstance == null) {
sInstance = new IPCServiceBridge();
IntentFilter filter = new IntentFilter();
filter.addAction("ipc.service.action");
Context context = InstrumentationRegistry.getContext();
context.registerReceiver(sInstance, filter);
}
return sInstance;
}
public void sendIpcCommand(String commandName) {
try {
int i = 30;
mIsPermitted = false;
while (i > 0) {
pub("request:" + commandName);
Thread.sleep(1000);
if (mIsPermitted) {
break;
}
i--;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!mIsPermitted) {
throw new RuntimeException("IPC service does not respond");
}
}
private static void pub(String msg) {
Log.e(FILTER_ID, msg);
}
}
Than I start adb logcat -s "filter_name", parse and check which condition should be applied for InsttUnit test. When conditions is ready i send back broadcast receiver with required action.
#Test
public void test2() throws Exception {
IPCServiceBridge.getInstance().sendIpcCommand("CONDITION#123");
}
Work good, but I'm not sure that it will be super stable.
I have an application that access to a server. When I quit the application, I have to disconnect from the server first, then close the application.
I would like to know if it's possible (and how) to make a Robospice service (background task) that disconnect from the server even if the application is closed (and the Robospice service is still running to finish the deconnection, and then auto kill itself after).
The problem is that the deconnection is too long (sometimes more than 5 secondes) and I would like to avoid blocking the phone during the deconnection, and allow the user to use it's phone.
Another question : is the Robospice librairy will be maintained and improved in the future (if necessary) ?
Yes, RoboSpice works just as well when attached to a Service Context as it works with an Activity one.
But you should probably try executing disconnect in the com.octo.android.robospice.SpiceService#onDestroy method of your implementation. This service is stopped whenever it has no meaningful work to do, so I guess it is the most appropriate solution for your use case.
I've solved my problem (that may be wasn't really a problem !) by ending my application with finish()
In my MainActivity, I use a Robospice service :
private final class LogoutListener implements PendingRequestListener<String> {
#Override
public void onRequestFailure(SpiceException spiceException) {
Log.e(TAG, spiceException.getMessage());
}
#Override
public void onRequestSuccess(String result) {
// nothing special
}
#Override
public void onRequestNotFound() {
Log.w(TAG, "Not found");
}
}
private void Alarm_Logout(boolean exit) {
Logout request = new Logout(url);
spiceManager.execute(request, new LogoutListener());
this.finish();
}
And the Lougout class :
public class Logout extends OkHttpSpiceRequest<String> {
private String url_logout;
public Logout(String url) {
super(String.class);
this.url_logout = url;
}
#Override
public String loadDataFromNetwork() throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url_logout)
.build();
Response response = client.newCall(request).execute();
return "ok";
}
}
Before I closed the app with System.exit(0) in onRequestSuccess, so I had to wait the Logout complete. Now the app close (with finish()), but the Logout continue in background, and then, when done, the service finish...
I am using Twilio android client. device.connect() is working fine but can't able to disconnect the connected call, though the user (I dialed to) if hangup then the call will be disconnected. I have tried with device.disconnectAll() and connection.disconnect(), both are not working. Please guide me wher i'm wrong.
Simple:
Caller can't be able to disconnect the call while callee can.
Thank in Advance.
To connect the call
HashMap<String, String> p = new HashMap<String, String>();
p.put("PhoneNumber", personToCall);
p.put(Connection.IncomingParameterFromKey, (String) device.getCapabilities().get(Device.Capability.CLIENT_NAME));
p.put(Connection.IncomingParameterToKey, personToCall);
device.connect(p, this);
and to disconnect
connection.disconnect()
It's not clear in your code how you're obtaining the connection object, which is one of two pivotal pieces of the Twilio client.
The Twilio Client documentation has an example on making outbound calls:
import com.twilio.client.Connection;
import com.twilio.client.Device;
import com.twilio.client.Twilio;
public class MonkeyPhone implements Twilio.InitListener
{
private Device device;
private Connection connection;
/* ... other methods ... */
public void connect()
{
connection = device.connect(null /* parameters */, null /* ConnectionListener */);
if (connection == null)
Log.w(TAG, "Failed to create new connection");
}
#Override
protected void finalize()
{
if (connection != null)
connection.disconnect();
if (device != null)
device.release();
}
}
In the example, when you call device.connect(), a connection object is returned and stored as a property in the object so it can be referenced again later on. In the finalize method, we call connection.disconnect() to terminate the call.
If you're not calling disconnect on the connection object returned from device.connect() the call may not disconnect properly. See the Twilio documentation for Device.connect for more details.
I connect to the node server with socketio.SocketIO running as a service.And, When Service restarts,opens socket.io without socket.io closure.That's a problem.
A device making multiple socketIO connection on the server side.So the server is swelling..
! I am using gottox/socketio-java-client on android.
Check Socket is connected or not using socket.isConnected().
This will return true if socket is connected
Its just an idea so i don't know the limitations. pls let me know.
You can ping the server to check if the connection is alive.
In android
socket.emit("ping","ping");
socket.on("pong",pingHandler); //EmitterListener
private Emitter.Listener pingHandler=new Emitter.Listener(){
#Override
public void call(final Object... args) {
Log.d("SocketStatus","Connection is active");
});
}
and make the server return response for the ping
socket.on("ping",function(data){
socket.emit("pong","pong"); //from your server ex.Node.js
});
You can check the socket.connected property:
var socket = io.connect();
console.log('Connected status before onConnect', socket.socket.connected);
socket.on('connect', function() {
console.log('Connected status onConnect', socket.socket.connected);
});
It's updated dynamically, if the connection is lost it'll be set to false until the client picks up the connection again. So easy to check for with setInterval or something like that.
Another solution would be to catch disconnect events and track the status yourself.
The following is an expansion/modification of Rafique Mohammed answer above. The correct way is to try to reconnect on client side.
Internet drops (server cannot communicate disconnection to client). Server crashes (server may/may not be able to tell client. Server Restart (server can tell but that just extra work). After reconnection you will also like to rejoin the room for seamless communication
public void connectAfterDisconnectSocket(String senderActivity) {
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
boolean isConnected = false;
isConnected = mSocket != null && mSocket.connected();
if (!isConnected) {
SocketIOClient socketIOClient = new SocketIOClient();
socketIOClient.connectToSocketIO();
if (senderActivity.equals("A")) {
A.joinChatRoom(room);
}
if (senderActivity.equals("B")) {
B.joinChatRoom(room);
}
}
}
}, 0, 1000); //put here time 1000 milliseconds=1 second
}
I am having a problem with using the JmDNS library for an Android app.
Since Bonjour does not send periodic keep-alive messages, I am closing and opening a new JmDNS instance every 30 seconds, so that I can have the serviceAdded and serviceResolved functions called.
But in between these instance creations, if I switch off and on the Wifi, although the creation of the JmDNS instance succeeds, my serviceAdded and serviceResolved functions are not called.
My main doubts are:
1) Is it ok to re-create these instance again and again and therefore effect a kind-of polling? Or is there a better way?
2) If the network is switched off and on, is there something I need to do each time I create the JmDNS instance?
Here's a snippet of my code:
private void _startJmDnsService() throws IOException {
if (mJmdns != null) {
if (mJmDnsServiceListener != null) {
mJmdns.removeServiceListener(mBonjourServiceType, mJmDnsServiceListener);
mJmDnsServiceListener = null;
}
mJmdns.close();
mJmdns = null;
}
Log.d(TAG, "starting JmDNS");
mJmdns = JmDNS.create(getInet4Address());
mJmDnsServiceListener = new ServiceListener() {
public void serviceResolved(ServiceEvent ev) {
ServiceInfo serviceInfo = ev.getInfo();
Log.w(TAG, "serviceResolved for device " + serviceInfo.getName());
}
public void serviceRemoved(ServiceEvent ev) {
ServiceInfo serviceInfo = ev.getInfo();
Log.w(TAG, "serviceRemoved for device " + serviceInfo.getName());
CDevice.removeDevice(deviceId);
}
public void serviceAdded(ServiceEvent event) {
// Required to force serviceResolved to be called again
// (after the first search)
ServiceInfo serviceInfo = event.getInfo();
Log.w(TAG, "serviceAdded for device " + serviceInfo.getName());
mJmdns.requestServiceInfo(event.getType(), event.getName(), 1);
}
};
mJmdns.addServiceListener(mBonjourServiceType, mJmDnsServiceListener);
Log.w(TAG, "mJmdns Service Listener added!");
}
For anyone that might have a similar problem. There was nothing in the JmDNS library that had a problem. In my code, I was closing the multicast socket between instance calls, which was creating a problem.