title: Detecting incoming call and opening a service in background on top of the dialer app
body: <p>After detecting the incoming call, I am opening a messenger like chat icon on incoming call. But I am facing two issues :
  <br>1.The incoming call is not detected when my application is closed (not running even in background).
  <br>2.When my phone is locked, the chat icon does not appear. The chat icon hides behind the dialer app on an incoming call.
  <br><br>
  I am using <code>Broadcast Receiver</code> to receive the incoming call using <code>PhoneCallReceiver</code> class which calls methods <code>defined</code> under <code>CallReceiver</code> class and on detecting incoming call I am starting the service <code>ChatHeadService</code> which opens a chat like icon. I have attached screenshot of how the chat icon appears. I have been facing this problem since past 6 months and was not able to solve it. Any help would be appreciated.<br><br>
  compileSdkVersion 23
  <br>
  buildToolsVersion '27.0.3'
  <br>
  targetSdkVersion 23
  <br><br>
  I tested the app on two devices with API level 18 and API level 26. In API level 18, my app worked fine and both of the above issues were fixed. But in API level 26, my app worked didn't work and the chat icon was hidden behind the dialer app.
  <br><br>
  I am facing the following error on incoming call in Oreo API 26.<br>
  <code>06-13 16:22:23.969 1238-4375/? W/BroadcastQueue: Permission Denial: receiving Intent { act=android.intent.action.PHONE_STATE flg=0x1000010 (has extras) } to com.skype.m2/com.skype.nativephone.connector.NativePhoneCallReceiver requires android.permission.READ_PHONE_STATE due to sender android (uid 1000)</code>
  <br><br>
  <b>API level 26</b><br>
  <a href="https://i.stack.imgur.com/r588P.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/r588P.jpg" alt="API level 26"></a></p>
  
  <p><b>API level 18</b><br>
  <a href="https://i.stack.imgur.com/POROA.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/POROA.jpg" alt="API level 18"></a></p>
  
  <p><br>
  <b>AndroidManifest.xml</b></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      package="com.tarun.notifyme2"&gt;
  
      &lt;uses-sdk
          android:minSdkVersion="16"
          android:targetSdkVersion="23" /&gt;
  
      &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
      &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
      &lt;uses-permission android:name="android.permission.READ_PHONE_STATE" /&gt;
      &lt;uses-permission android:name="android.permission.CALL_PHONE" /&gt;
      &lt;uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /&gt;
      &lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /&gt;
      &lt;uses-permission android:name="android.permission.Settings.ACTION_MANAGE_OVERLAY_PERMISSION" /&gt;
      &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
      &lt;uses-permission
          android:name="android.permission.MODIFY_PHONE_STATE"
          tools:ignore="ProtectedPermissions" /&gt;
  
      &lt;application
          android:allowBackup="true"
          android:enabled="true"
          android:icon="@drawable/app_icon"
          android:label="@string/app_name"
          android:supportsRtl="true"
          android:theme="@style/AppTheme"&gt;
          &lt;activity android:name=".SignUp"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.MAIN" /&gt;
  
                  &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
              &lt;/intent-filter&gt;
          &lt;/activity&gt;
          &lt;activity android:name=".SendNoti" /&gt;
  
          &lt;receiver android:name=".CallReceiver"
              android:enabled="true"&gt;
              &lt;intent-filter android:priority="1000"&gt;
                  &lt;action android:name="android.intent.action.PHONE_STATE" /&gt;
              &lt;/intent-filter&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.NEW_OUTGOING_CALL" /&gt;
              &lt;/intent-filter&gt;
          &lt;/receiver&gt;
  
  
          &lt;service
              android:name=".ChatHeadService"
              android:exported="true"
              android:enabled="true"/&gt;
  
          &lt;service android:name=".FirebaseMessagingService"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="com.google.firebase.MESSAGING_EVENT" /&gt;
              &lt;/intent-filter&gt;
          &lt;/service&gt;
          &lt;service android:name=".FirebaseInstanceIDService"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="com.google.firebase.INSTANCE_ID_EVENT" /&gt;
              &lt;/intent-filter&gt;
          &lt;/service&gt;
  
          &lt;activity
              android:name=".MainActivity"
              android:label="@string/title_activity_main"
              android:theme="@style/AppTheme.NoActionBar" /&gt;
          &lt;activity android:name=".MainChat" /&gt;
          &lt;activity android:name=".ChatRoom" /&gt;
          &lt;activity android:name=".Feedback" /&gt;
      &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p><b>PhonecallReceiver.java</b></p>
  
  <pre><code>import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;
  import android.telephony.TelephonyManager;
  import java.util.Date;
  
  public abstract class PhonecallReceiver extends BroadcastReceiver
  {
      private static int lastState = TelephonyManager.CALL_STATE_IDLE;
      private static Date callStartTime;
      private static boolean isIncoming;
      private static String savedNumber;
  
      @Override
      public void onReceive(Context context, Intent intent)
      {
          try
          {
              if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
              {
                  savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
              }
              else
              {
                  String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
                  String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
                  int state = 0;
                  if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE))
                  {
                      state = TelephonyManager.CALL_STATE_IDLE;
                  }
                  else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
                  {
                      state = TelephonyManager.CALL_STATE_OFFHOOK;
                  }
                  else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING))
                  {
                      state = TelephonyManager.CALL_STATE_RINGING;
                  }
  
                  onCallStateChanged(context, state, number);
              }
          }
          catch (Exception e)
          {
              e.printStackTrace();
          }
      }
  
      //Derived classes should override these to respond to specific events of interest
      protected void onIncomingCallStarted(Context ctx, String number, Date start){}
      protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end){}
  
      public void onCallStateChanged(Context context, int state, String number)
      {
          if(lastState == state)
          {
              //No change, debounce extras
              return;
          }
          switch (state)
          {
              case TelephonyManager.CALL_STATE_RINGING:
                  isIncoming = true;
                  callStartTime = new Date();
                  savedNumber = number;
                  onIncomingCallStarted(context, number, callStartTime);
                  break;
  
              case TelephonyManager.CALL_STATE_OFFHOOK:
                  if (isIncoming)
                  {
                      onIncomingCallEnded(context,savedNumber,callStartTime,new Date());
                  }
  
              case TelephonyManager.CALL_STATE_IDLE:
                  if(isIncoming)
                  {
                      onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
                  }
          }
          lastState = state;
      }
  }
  </code></pre>
  
  <p><b>CallReceiver.java</b></p>
  
  <pre><code>import android.app.Activity;
  import android.app.Dialog;
  import android.app.Notification;
  import android.content.ComponentName;
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.graphics.drawable.ColorDrawable;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.Window;
  import android.widget.Button;
  import android.widget.Toast;
  import android.os.Handler;
  import java.util.Date;
  
  public class CallReceiver extends PhonecallReceiver
  {
      Context context;
  
      @Override
      protected void onIncomingCallStarted(final Context ctx, String number, Date start)
      {
          Toast.makeText(ctx,"New Incoming Call"+ number,Toast.LENGTH_LONG).show();
          context =   ctx;
          final Intent intent = new Intent(context, ChatHeadService.class);
          intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
          intent.putExtra("phone_no",number);
          SharedPreferences.Editor editor = ctx.getSharedPreferences("Notify", Context.MODE_PRIVATE).edit();
          editor.putString("incomingNo",number);
          editor.commit();
          new Handler().postDelayed(new Runnable()
          {
              @Override
              public void run()
              {
                  //start service which opens a chat icon after 2 seconds wait
                  context.startService(intent);
              }
          },2000);
  
      }
  
      @Override
      protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end)
      {
          final Intent intent = new Intent(context, ChatHeadService.class);
          ctx.stopService(intent);
          Toast.makeText(ctx,"Bye Bye"+ number,Toast.LENGTH_LONG).show();
      }
  }
  </code></pre>
  
  <p><b>ChatHeadService.java</b></p>
  
  <pre><code>import android.app.Service;
  import android.content.Intent;
  import android.graphics.PixelFormat;
  import android.os.IBinder;
  import android.util.Log;
  import android.view.Gravity;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.WindowManager;
  import android.widget.ImageView;
  import android.widget.Toast;
  
  public class ChatHeadService extends Service {
  
      private WindowManager windowManager;
      private ImageView chatHead;
      WindowManager.LayoutParams params;
      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
          int res = super.onStartCommand(intent, flags, startId);
          return res;
      }
      @Override
      public void onCreate() {
          super.onCreate();
  
          windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
          chatHead = new ImageView(this);
          chatHead.setImageResource(R.drawable.bell2);
          chatHead.setClickable(true);
  
          params= new WindowManager.LayoutParams(
                  WindowManager.LayoutParams.WRAP_CONTENT,
                  WindowManager.LayoutParams.WRAP_CONTENT,
                  WindowManager.LayoutParams.TYPE_PHONE,
                  WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                  PixelFormat.TRANSLUCENT);
          params.gravity = Gravity.TOP | Gravity.LEFT;
          params.x = 0;
          params.y = 400;
  
          windowManager.addView(chatHead, params);
  
          chatHead.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View view) {
                  startActivity(new Intent(ChatHeadService.this, SendNoti.class)
                                  .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
                  stopSelf();
              }
          });
  
          //this code is for dragging the chat head
          chatHead.setOnTouchListener(new View.OnTouchListener() {
              private int initialX;
              private int initialY;
              private float initialTouchX;
              private float initialTouchY;
              int flag=0;
  
              @Override
              public boolean onTouch(View v, MotionEvent event) {
                  switch (event.getAction()) {
                  case MotionEvent.ACTION_DOWN:
                      initialX = params.x;
                      initialY = params.y;
                      initialTouchX = event.getRawX();
                      initialTouchY = event.getRawY();
                      if(flag==3){
                          flag=1;
                          return true;
                      }else{
                          flag=1;
                          return false;
                      }
                  case MotionEvent.ACTION_UP:
                      if(flag==3){
                          flag=2;
                          return true;
                      }else{
                          flag=2;
                          return false;
                      }
                  case MotionEvent.ACTION_MOVE:
                      flag=3;
                      params.x = initialX
                              + (int) (event.getRawX() - initialTouchX);
                      params.y = initialY
                              + (int) (event.getRawY() - initialTouchY);
                      windowManager.updateViewLayout(chatHead, params);
                      return true;
                  default:
                      Toast.makeText(getApplicationContext(),"You ckiced the imageview",Toast.LENGTH_LONG).show();
                      Log.i("tag","You clicked the imageview");
                  /*
                  Intent i = new Intent(view.getContext(),SendNoti.class);
                  startActivity(i);
                  stopSelf();*/
                      return true;
                  }
              }
          });
          /*
          Snackbar.make(chatHead, "Replace with your own action", Snackbar.LENGTH_LONG)
                  .setAction("Action", null).show();*/
  
      }
  
      @Override
      public void onDestroy() {
          super.onDestroy();
          if (chatHead != null)
              windowManager.removeView(chatHead);
          stopSelf();
      }
  
      @Override
      public IBinder onBind(Intent intent) {
          // TODO Auto-generated method stub
          return null;
      }
  }
  </code></pre>