Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service is NOT running always even after I have used START_STICKY

Issues

Service is NOT running always even after I have used START_STICKY.

Sometimes I dont get any Toast Action for Outgoing call, is that mean service stops after some time ?

My Requirment

Application shows a Toast whenever user makes a outgoing call from the phone. For this I am using a BroadcastReceiver to tap the call action and a service (to run Receiver always). once I start this activity, it starts showing toast when a outgoing call get initiated ..but not Always.

Below is the complete code -

MainActivity.class

public class MainActivity extends Activity 
{
    CallNotifierService m_service;
    boolean isBound = false;

    private ServiceConnection m_serviceConnection = new ServiceConnection() 
    {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) 
        {
            m_service = ((CallNotifierService.MyBinder)service).getService();
            Toast.makeText(MainActivity.this, "Service Connected", Toast.LENGTH_LONG).show();
            isBound = true;
            Intent intent = new Intent(MainActivity.this, CallNotifierService.class);
            startService(intent);
        }

        @Override
        public void onServiceDisconnected(ComponentName className) 
        {
            m_service = null;
            isBound = false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent(this, CallNotifierService.class);
        bindService(intent, m_serviceConnection, Context.BIND_AUTO_CREATE);
    }
    .
    .
    .
}

CallNotifierService.class

public class CallNotifierService extends Service 
{
    private final IBinder myBinder = new MyBinder();
    private static final String ACTION_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";

    private CallBr br_call;

    @Override
    public IBinder onBind(Intent arg0) 
    {
        return myBinder;
    }

    @Override
    public void onDestroy() 
    {
        Log.d("service", "destroy");
        this.unregisterReceiver(this.br_call);
        Toast.makeText(CallNotifierService.this, "Receiver Un-Registered", Toast.LENGTH_LONG).show();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        final IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_OUTGOING_CALL);
        this.br_call = new CallBr();
        this.registerReceiver(this.br_call, filter);
        Toast.makeText(CallNotifierService.this, "onStartCommand Called", Toast.LENGTH_LONG).show();
        return START_STICKY;
    }

    public class MyBinder extends Binder 
    {
        CallNotifierService getService() 
        {
            return CallNotifierService.this;
        }
    }

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

        @Override
        public void onReceive(Context context, Intent intent) 
        {
            Toast.makeText(context, "Action:"+intent.getAction(), Toast.LENGTH_LONG).show();
        }
    }
}
like image 613
Bharat Avatar asked Feb 26 '16 09:02

Bharat


1 Answers

You are getting the wrong approach here, by mixing a simple idea (that would work if done correctly) with more complicated ideas (that cannot work).

Keep in mind: services are not "always running" components, even when using START_STICKY.

The Android system will not hesitate to kill your service if it needs memory somewhere else. START_STICKY only means that the Android system will re-start your service when it can, calling onStartCommand as specified in the documentation.

If you need a service to really stick around, then you must use a foreground service. But it will have consequences on the UI (annoying notification icon always showing), and battery life, and you do not need this here.

Now here is the magic trick: your app does not need to be running for your BroadcastReceiver to work. All you need to do is to register it in your AndroidManifest.xml with the correct intent-filter:

<receiver android:name=".broadcastreceivers.CallBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
    </intent-filter>
</receiver>

(also make sure your app has the required permissions, namely PROCESS_OUTGOING_CALLS).

Then all you need in code is:

public class CallBroadcastReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        Toast.makeText(context, "Action: " + intent.getAction(), Toast.LENGTH_LONG).show();
    }
}

No activity (except to ask for the PROCESS_OUTGOING_CALLS permission on Android 6+), no service, nothing. Simple and battery-efficient !

like image 200
personne3000 Avatar answered Sep 23 '22 12:09

personne3000