I am creating bound service for socket connection.Which means it is creating a long polling connection and listens my server.If user closes the app in task manager my service is killing i have no problem with this.But when user presses the back button I am calling activity.finish() method for close app.But with this method my service doesn't kill,it is still connected to socket server.
Is this normal ? And Could be this drain the battery ?
My service:
public class SocketService extends Service {
//you need constants to tell servise and activity what you are sending a message for
public static final int REGISTER_CHAT_ACTIVITY = 1;
public static final int MESSAGE_RECEIVED = 2;
final Messenger mMessenger = new Messenger(new IncomingHandler());
Messenger chat;
private Socket socket;
#Override
public void onCreate() {
try {
socket = IO.socket("ip");
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
}
}).on("connected", new Emitter.Listener() {
#Override
public void call(Object... args) {
}
}).on("message", new Emitter.Listener() {
#Override
public void call(Object... args) {
try {
chat.send(android.os.Message.obtain(null, MESSAGE_RECEIVED, args[0]));
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
//and add all the other on listeners here
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (socket != null) {
socket.disconnect();
socket.connect();
} else {
try {
socket = IO.socket("ip");
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
class IncomingHandler extends Handler {
#Override
public void handleMessage(android.os.Message msg) {
switch(msg.what){
case REGISTER_CHAT_ACTIVITY:
chat = msg.replyTo;
break;
}
}
}
public class LocalBinder extends Binder {
SocketService getService() {
return SocketService.this;
}
}
}
I had something similar a while ago i solved the issue by using shared preferences.(Note: I dont think it's the best answer but it solved my problem)
I saved in preferences a boolean to register when i dont need the service anymore but lost reference of it.
public class YourService extends Service {
private YourService serv;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
serv = this;
Then Somehwere on your code that the service does frequently.
if(!sharedPref.getBoolean("TurnOffService", false)){
serv.stopSelf();
}
Hope it helps.
Related
i have a problem in my service, the service is runnig from MainActivity (i am doing test) and extends of service.
i want to use the service from foreground and background (when the app is closed) and i already have my first problem:
my service(have a counter that is displayed by LOG) is restarting when i close the app.
also i want to be able to use the service with the open app and close app, in other words to use both the Service Started and Link Service
public class MyService extends Service {
private Thread backgroundThread;
private boolean isRunning;
public MyService() {
Log.e("MyService","constructor");
}
#Override
public void onCreate() {
super.onCreate();
isRunning = false;
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
Log.e("onStartCommand","Servicio Llamado");
if (!this.isRunning) {
Log.e("onStartCommand","hilo iniciandose");
this.backgroundThread = new Thread(myTask);
runTask();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("onDestroy","servicio destuido");
}
private void runTask(){
this.isRunning = true;
this.backgroundThread.start();
}
private Runnable myTask = new Runnable() {
public void run() {
Log.e("myTask","hilo iniciado");
int i = 0;
do{
pauseService();
Log.e("myTask","hilo contador: "+i);
//Toast.makeText(getApplicationContext(),"CONTADOR = "+j, Toast.LENGTH_SHORT).show(); //no working :(
i++;
}while (i<10);
/*
//linea de detencion del servicio
//stopSelf();
isRunning=false;
backgroundThread.interrupt();
//backgroundThread = new Thread(myTask);
*/
Log.e("myTask","hilo cerrado");
}
};
private void pauseService(){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
In main Activity
Intent intent = new Intent(MainActivity.this,MyService.class);
intent.putExtra("iteraciones",10);
startService(intent);
why because the service restarts when I close the application and how can I avoid it?
I created a service class in my application to run some task in the background. When I close the application the service still running and it's ok. But the problem is, When I run the application again, a new service running and every time when I restart the application a new service create. Here's my code
public class myService extends Service {
Socket socket;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
connectSocket();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
socket.disconnect();
}
private void connectSocket() {
try {
socket = IO.socket("http://192.168.1.52:2500");
socket.on(Socket.EVENT_CONNECT, onConnected);
socket.on(Socket.EVENT_CONNECT_ERROR, onConnectionError);
socket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectionTimout);
socket.on(Socket.EVENT_DISCONNECT, onDisconnect);
socket.on("test_callback", eventCallback );
socket.connect();
} catch (URISyntaxException e) {
Log.d(getClass().getSimpleName(), "Socket Connection Exception");
e.printStackTrace();
}
}
private Emitter.Listener onConnected = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d("SocketIO","onConnected");
socket.connect();
}
};
private Emitter.Listener onConnectionError = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d("SocketIO","onConnectionError");
socket.connect();
}
};
private Emitter.Listener onConnectionTimout = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d("SocketIO","onConnectionTimout");
socket.connect();
}
};
private Emitter.Listener onDisconnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d("SocketIO","onDisconnect");
socket.disconnect();
}
};
int notno = 0;
private Emitter.Listener eventCallback = new Emitter.Listener() {
#Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
String message;
try {
message = data.getString("message").toString();
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(myService.this)
.setSmallIcon(R.drawable.head)
.setContentTitle("Message")
.setContentText(message);
NotificationManager nfm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
nfm.notify(notno ,mBuilder.build());
notno++;
} catch (JSONException ignored) {
}
}
};
}
and in onCreate method in main class run this code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
startService(new Intent(getBaseContext(), myService.class));
}
This is by design. Every time startService is called, onStartCommand will be called. This allows it to be started wth different intents. However it will only be created once (unless stopped for resources, of course). If you want to only have a single instance of a socket or thread, its your job to make sure you only instantiate them the first time onStartCommand is called.
Also, your code as is won't work. Services do not have their own threads or processes by default. That mean you need to launch a new Thread to do your socket work, or you'll get a NetworkOnMainThreadErrror.
I tried to start socket connection and maintain it in a service. The service work well, but i cant connect to the my socket. Is it my code wrong or there some other way to do it?
This is my code
public class SocketService extends Service {
private Socket mSocket;
{
try {
mSocket = IO.socket("http://192.91.25.99:3000");
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mSocket.connect();
mSocket.on("message", handleIncomingMessages);
Toast.makeText(getApplicationContext(),"Start Service",Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}
private Emitter.Listener handleIncomingMessages = new Emitter.Listener(){
#Override
public void call(final Object... args){
System.out.println(args[0].toString());
Toast.makeText(getApplicationContext(),"LALALALA",Toast.LENGTH_LONG).show();
}
};
}
Thanks in advance
I'm attempting to create a program in Android which communicates rapidly with a remote service (~40,000/sec), however all Android IPC seems to fall short of being able to accomplish this task. My first attempt involved a standard Messenger system which was unable to do more then ~2,000/second and equally bad was that it seemed punctuated with intermittent lag.
MainActivity (Test with Messengers)
public class MainActivity extends Activity implements ServiceConnection{
Messenger mServiceMessenger;
Messenger mClientMessenger = new Messenger(new ClientHandler());
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,TestService.class);
bindService(intent,this, Context.BIND_AUTO_CREATE);
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mServiceMessenger = new Messenger(service);
Message m = Message.obtain();
m.replyTo = mClientMessenger;
try {
mServiceMessenger.send(m);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {}
public class ClientHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Log.d("Spam","Message Received");
}
}
}
RemoteService (Test with Messengers)
public class TestService extends Service {
private Messenger mServiceMessenger = new Messenger(new ServiceHandler());
private Messenger mClientMessenger;
private Random r = new Random();
public TestService() {
super();
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public IBinder onBind(Intent intent) {
return mServiceMessenger.getBinder();
}
public void initSpam(){
for(int i=0;i<10;i++) {
TimerTask task = new TimerTask() {
#Override
public void run() {
Bundle b = new Bundle();
b.putInt("INT",r.nextInt());
b.putLong("LONG",r.nextLong());
b.putBoolean("BOOL",r.nextBoolean());
b.putFloat("FLOAT",r.nextFloat());
b.putDouble("DOUBLE",r.nextDouble());
b.putString("STRING",String.valueOf(r.nextInt()));
Message msg = Message.obtain();
msg.setData(b);
try {
mClientMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task,1,1);
}
}
public class ServiceHandler extends Handler {
#Override
public void handleMessage(Message msg) {
mClientMessenger = msg.replyTo;
initBarrage();
}
}
}
The second attempt was done with AIDL. Although this also implements Binders for IPC, I assumed had significantly less overhead. However, AIDL proved to not be significantly more efficient then Messengers and it also did not solved the issue with stuttering.
MainActivity (Test with AIDL)
public class MainActivity extends Activity implements ServiceConnection{
IRemoteService mService;
TextView countTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,TestService.class);
bindService(intent,this, Context.BIND_AUTO_CREATE);
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IRemoteService.Stub.asInterface(service);
try {
mService.registerCallback(mClientBinder);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {}
public final IServiceAidlCallback.Stub mClientBinder = new IServiceAidlCallback.Stub(){
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat, double aDouble, String aString){
Log.d("Spam","Callback Received");
}
};
}
RemoteService (Test with AIDL)
public class TestService extends Service {
private Random r = new Random();
private IServiceAidlCallback mClientCallback;
public TestService() {
super();
}
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
public void registerCallback(IBinder callback){
mClientCallback = IServiceAidlCallback.Stub.asInterface(callback);
initSpam();
}
};
public void initSpam(){
for(int i=0;i<10;i++) {
TimerTask task = new TimerTask() {
#Override
public void run() {
try {
mClientCallback.basicTypes(
r.nextInt(),
r.nextLong(),
r.nextBoolean(),
r.nextFloat(),
r.nextDouble(),
String.valueOf(r.nextInt()));
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task,1,1);
}
}
}
Am I doing something wrong in either of these cases which would prevent me from getting above ~5,000/second? or is there another system for Android IPC that I was not aware of?
do something like that:
MainActivity
// use it for writing: stream.write(byte[])
// (make sure to write as biggest data chunks as possible)
// or wrap it around some other streams like DataOutputStream
private OutputStream stream;
// ServiceConnection implementation
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
stream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);
Parcel data = Parcel.obtain();
FileDescriptor readFileDescriptor = pipe[0].getFileDescriptor();
data.writeFileDescriptor(readFileDescriptor);
service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
} catch (Exception e) {
e.printStackTrace();
}
Log.d(TAG, "onServiceConnected " + stream);
}
RemoteService
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind ");
return binder;
}
IBinder binder = new Binder() {
#Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
ParcelFileDescriptor pfd = data.readFileDescriptor();
final InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
// do something with a 'stream', start a new Thread for example and read data in a loop
...
...
return true;
}
};
I am facing a grave problem. Inside a service I am opening Wifi connection and closing it after my task completes. Since, a service exits at any point i face a problem wherein the connection opens and remains open.
Is there a way i can handle this as i am using START_STICKY or i will have to handle it programmatically only?
EDIT : Can i share my intent information across couple of receivers (BroadcastReceiver). For example, I will write another receiver for action android.net.wifi.wifi_state_changed and my existing receiver is for android.intent.action.PHONE_STATE.
IF that can be achieved i can do something about it.
EDIT2 : My code is as follows:
public class CallReceiver extends BroadcastReceiver {
private static final String LOG_TAG = "CallReceiver";
private static final String CALL_ACTION = "android.intent.action.PHONE_STATE";
#Override
public void onReceive(Context context, Intent callIntent)
{
Log.d(LOG_TAG, "----------------Inside onReceive of CallReceiver----------------");
if (callIntent.getAction().equals(CALL_ACTION))
{
try
{
Intent myIntent = new Intent(context, MyService.class);
context.startService(myIntent);
}
catch (Exception e)
{
e.printStackTrace();
Log.d(LOG_TAG,"----------------Exception occured while starting service----------------");
}
}
}
}
public class MyService extends Service {
private Context context;
private static final String LOG_TAG = "MyService";
private Thread thread = null;
public MyService()
{
super();
Log.d(LOG_TAG, "----------------Inside Email Service constructor----------------");
}
public int onStartCommand(Intent myIntent, int flags, int startId)
{
Log.d(LOG_TAG, "----------------Email Service Command Started----------------");
try
{
context = getApplicationContext();
if(thread == null || !thread.isAlive())
{
thread = new Thread(new MyRunnable("Email Sender", myIntent));
thread.start();
}
}
catch (Exception e)
{
e.printStackTrace();
Log.d(LOG_TAG,
"----------------Exception occured in Email Service onStartCommand----------------");
}
return START_REDELIVER_INTENT;
}
class MyRunnable implements Runnable {
String name;
Intent myIntent;
public MyRunnable(String name, Intent myIntent) {
this.name = name;
this.myIntent = myIntent;
}
#Override
public void run()
{
try
{
doStuff(emailIntent);
}
catch (NumberFormatException e)
{
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
catch (InterruptedException e)
{
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
catch (Exception e)
{
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
finally
{
stopSelf();
}
}
}
private void doStuff(Intent emailIntent) throws InterruptedException, Exception
{
if (context != null)
{
boolean isWifiConnection = false;
try
{
// Check if WiFi connection is available ,if yes try opening it;
// Attempt to open WiFi connection
isWifiConnection = Utility.isEnableWifiSuccessful(getApplicationContext());
Log.d(LOG_TAG, "----------------Wifi conn enabled = " + isWifiConnection
+ "----------------");
if (isWifiConnection)
{
// Do more stuff
}
}
catch (Exception e)
{
e.printStackTrace();
throw e;
}
finally
{
// Code never reaches here !! Somehow, the service stops and by
// the time the service stops,
// WiFi has been enabled
try
{
if (isWifiConnection)
{
Utility.isDisableWifiSuccessful(getApplicationContext());
}
}
catch (Exception e)
{
e.printStackTrace();
Log.d(LOG_TAG,
"----------------Error occured while closing network connections----------------");
}
}
}
else
{
Log.d(LOG_TAG, "----------------Context is null----------------");
}
}
#Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
}
Now, if i have another receiver as NetworkReceiver
public class NetworkReceiver extends BroadcastReceiver {
private static final String ACTION = "android.net.wifi.WIFI_STATE_CHANGED";
private static final String LOG_TAG = "NetworkReceiver";
#Override
public void onReceive(Context context, Intent networkIntent)
{
if(networkIntent.getAction().equals(ACTION))
{
Log.d(LOG_TAG, "----------------Inside Network Receiver----------------");
//Do something which will keep track who has opened the WiFi connection
}
}
}
then can myIntent and networkIntent share information and can MySerivce read that information.
Any help would be really grateful.
Service exits when the memory is too low, since you are already using START_STICKY, the service will be restarted once the memory resources are available. I beleive you might need to check if the connection is opened and you are done with the task, then you have stop the service by using stopSelf().
Hope this helps.
Thanks,
Ramesh