Search code examples
javaandroidmultithreadingservicemessenger

Send data to activity from already running sticky service


I created sticky background service, that should be started on boot:

public class AutostartReceiver extends BroadcastReceiver
{
    public AutostartReceiver()
    {
    }

    @Override
    public void onReceive(Context context, Intent intent)
    {
        context.startService(new Intent(context, MyService.class));
    }
}

My service is intended to do some work in background, it's implemented by creating thread for this. Also there is Messenger class used for sending work status to my main activity:

@Override
  public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.i(TAG, "Service onStartCommand " + startId);

        final int currentId = startId;

        Messenger callback = null;
        if(intent!=null)
        {
            callback = intent.getParcelableExtra("messenger");
        }


        final Messenger finalCallback = callback;
        Runnable r = new Runnable()
        {
            public void run()
            {
                ... do something, then stop

                stopSelf();
            }
        };




        if(t == null)
        {
            t = new Thread(r);
            t.start();
        }


        return Service.START_STICKY;
    }

Main activity receives messages sent from background thread running inside my service (some commands, that service is sending periodically:

Handler mHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what)
            {
                case 0:
                    Toast.makeText(MainActivity.this,"Service runing", Toast.LENGTH_LONG).show();
                    break;
            }
        }
    };

This works only if I start my service from activity, with activity's context. Obviously, if service is started on boot, or my app was closed (removed from last app list) and opened again, my activity is unable to get any messages from service any more.

If I invoke start service while service is already running, it will simply run OnStartCommand again, so either new thread will be created (I don't want it) or I need to destroy running thread and run thread again.

Is there any way to get my activity receiving messages from service, without actually touching already running thread inside it? I know about bound services, but it's not clear for me how to use them in my specific case.


Solution

  • As Alternate way You can use LocalBroadcastManager to send Data from Service to Activity.

    Broadcast Your message from Service:

    private void broadcastMessage(Context context){
         Intent intent = new Intent("UI_UPDATE_BROADCAST");
         intent.putExtra("MESSAGE", "MyMessage");
         LocalBroadcastManager.getInstance(context).sendBroadcast(intent);        
    } 
    

    Register Broadcast Receiver in your activity to receive messages:

    @Override
    public void onResume() {
        super.onResume();
        LocalBroadcastManager.getInstance(mContext).registerReceiver(mMessageReceiver, new IntentFilter("UI_UPDATE_BROADCAST"));
    }
    
    
    @Override
    public void onPause() {
         super.onPause();
         LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mMessageReceiver);
    }
    
    private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             //Do Something With Received Data
             String msg = intent.getStringExtra("MESSAGE");
         }
    };