11

Я должен реализовать окно Overlay, например, приложение True Caller. Но проблема, которую я получаю, заключается в том, что во время любого входящего или исходящего вызова моя служба автоматически приближается или уничтожается.Оверлей Окно Сервис в Android

Класс обслуживания

public class OverlayService extends Service implements View.OnClickListener,NotifyHardwareChanges,UpdateSoundDB{ 

private WindowManager windowManager; 
WindowManager.LayoutParams params; 
View view; 
Button btnEndCall; 
public static TextView textView; 
public static Context cntxt; 

@Nullable 
@Override 
public IBinder onBind(Intent intent) { 
    return null; 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    // Let it continue running until it is stopped. 
    return START_NOT_STICKY; 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 
    this.cntxt = getApplicationContext(); 
    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); 

    params= new WindowManager.LayoutParams(
      WindowManager.LayoutParams.MATCH_PARENT, 
      WindowManager.LayoutParams.WRAP_CONTENT, 
      WindowManager.LayoutParams.TYPE_PHONE, 
      WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
      PixelFormat.TRANSLUCENT); 

    params.gravity = Gravity.CENTER; 
    params.x = 0; 
    params.y = 100; 

    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    view = inflater.inflate(R.layout.list_item, null); 

    textView = (TextView) view.findViewById(R.id.textView); 

    btnEndCall = (Button) view.findViewById(R.id.end_call); 
    //btnEndCall.set 
    btnEndCall.setOnClickListener(this); 


    //this code is for dragging the chat head 
    view.setOnTouchListener(new View.OnTouchListener() { 
     private int initialX; 
     private int initialY; 
     private float initialTouchX; 
     private float initialTouchY; 

     @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(); 
        return true; 
       case MotionEvent.ACTION_UP: 
        return true; 
       case MotionEvent.ACTION_MOVE: 
        params.x = initialX 
          + (int) (event.getRawX() - initialTouchX); 
        params.y = initialY 
          + (int) (event.getRawY() - initialTouchY); 
        windowManager.updateViewLayout(view, params); 
        return true; 
      } 
      return false; 
     } 
    }); 

    windowManager.addView(view, params); 
    Utillities.start(OverlayService.this, 1, OverlayService.this); 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    if (view != null) 
     windowManager.removeView(view); 

    Utillities.stop(OverlayService.this,1,OverlayService.this); 
} 

@Override 
public void onClick(View v) { 
    if(view!=null){ 
     Utillities.stop(OverlayService.this,1,OverlayService.this); 
     windowManager.removeView(view); 
     view = null; 
    } 
} 

@Override 
public void getNotify(String str) {} 

@Override 
public void setProcess(double signalEMA) { 
    int progress = ((int) signalEMA - Preferences.readInteger(getApplicationContext(), Preferences.CALIBRATION, 0)) ; 
    textView.setText("Your Sound Level :" + progress +"db"); 
    if ((Preferences.readInteger(cntxt, Preferences.SOUND_LEVEL, 0) > 0) && (progress > Preferences.readInteger(cntxt, Preferences.SOUND_LEVEL, 0))) { 
     textView.setTextColor(cntxt.getResources().getColor(R.color.red)); 
    }else{ 
     textView.setTextColor(cntxt.getResources().getColor(R.color.black)); 
    } 
} 

}

И здесь Ниже приведен BroadcastReceiver для обнаружения входящих и исходящих вызовов, а также используется для запуска и остановки Overlayservice.

public class ServiceReceiver extends BroadcastReceiver{ 

    TelephonyManager telephonyManager; 

    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) @Override 
    public void onReceive(Context context, Intent intent) { 
     // TODO Auto-generated method stub 
     if(Preferences.readBoolean(context, Preferences.APP_ON_OFF, false) == true){ 
      //The other intent tells us the phone state changed. Here we set a listener to deal with it 
      TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 
      telephony.listen(new PhonecallStartEndDetector(context), PhoneStateListener.LISTEN_CALL_STATE); 
     } 
    } 

    public class PhonecallStartEndDetector extends PhoneStateListener { 

     int lastState = TelephonyManager.CALL_STATE_IDLE; 
     boolean isIncoming; 
     Context cntx; 

     public PhonecallStartEndDetector(Context context) { 
      this.cntx = context; 
     } 

     //Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up 
     //Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up 
     @Override 
     public void onCallStateChanged(int state, String incomingNumber) { 
      super.onCallStateChanged(state, incomingNumber); 
      if (lastState == state) { 
       //No change, debounce extras 
       return; 
      } 
      switch (state) { 
       case TelephonyManager.CALL_STATE_RINGING: 
        isIncoming = true; 
        //cntx.startService(new Intent(cntx, OverlayService.class)); 
        //Toast.makeText(cntx, "onIncomingCallStarted", Toast.LENGTH_SHORT).show(); 
        break; 
       case TelephonyManager.CALL_STATE_OFFHOOK: 
        //Transition of ringing->offhook are pickups of incoming calls. Nothing donw on them 
        if (lastState != TelephonyManager.CALL_STATE_RINGING) { 
         isIncoming = false; 
         cntx.startService(new Intent(cntx, OverlayService.class)); 
         //Toast.makeText(cntx, "onOutgoingCallStarted", Toast.LENGTH_SHORT).show(); 
        }else{ 
         isIncoming = true; 
         cntx.startService(new Intent(cntx, OverlayService.class)); 
        } 

        break; 
       case TelephonyManager.CALL_STATE_IDLE: 
        //Went to idle- this is the end of a call. What type depends on previous state(s) 
        if (lastState == TelephonyManager.CALL_STATE_RINGING) { 
         //Ring but no pickup- a miss 
         cntx.stopService(new Intent(cntx, OverlayService.class)); 
         //Toast.makeText(cntx, "onMissedCall", Toast.LENGTH_SHORT).show(); 
        } else if (isIncoming) { 
         cntx.stopService(new Intent(cntx, OverlayService.class)); 
         //Toast.makeText(cntx, "onIncomingCallEnded", Toast.LENGTH_SHORT).show(); 
        } else { 
         cntx.stopService(new Intent(cntx, OverlayService.class)); 
         //Toast.makeText(cntx, "onOutgoingCallEnded", Toast.LENGTH_SHORT).show(); 
        } 
        break; 
      } 
      lastState = state; 
     } 
    } 
} 
+0

Не могли бы вы опубликовать stacktrace (используя отладчик) в методе onDetachedFromWindow() представления, которое вы добавляете в диспетчер окон. Также попробуйте изменить WindowManager.LayoutParams.TYPE_PHONE на TYPE_SYSTEM_ALERT и посмотреть, не изменилось ли что-нибудь? –

+0

@TinTran, Спасибо за ваши отзывы. Мне нужно показать наложение из класса Service, тогда я не знаю, как получить stacktrace (используя отладчик) в методе onDetachedFromWindow() представления, которое вы добавляете в диспетчер окон. –

+0

Вы когда-нибудь писали пользовательский вид? Вы пытались изменить WindowManager.LayoutParams.TYPE_PHONE на TYPE_SYSTEM_ALERT –

ответ

1

Переднего плана службы имеют высокий приоритет, поэтому попробуйте создать службу в качестве службы переднего плана и проверьте, работает ли это. Для создания службы переднего плана вам необходимо предоставить уведомление, чтобы пользователи знали, что работает служба переднего плана.

Вот как вы можете создать foreground service

Но прежде чем сделать свой первый план обслуживания, отладки, почему ваш текущий сервис убитого путем проверки журналов.

+0

Привет Винс, спасибо за ваш ответ. Можете ли вы привести мне пример. Поскольку я не осведомлен о обслуживании переднего плана. –

0

Экземпляр BroadcastReceiver будет автоматически очищен системой после получения намерения. Таким образом, ссылка на телефонную службу также будет убита, в результате чего ваша текущая ошибка выполнения, которая, в свою очередь, будет соответствовать условиям сертификации на основе вашей текущей реализации, вызовет стоп-сервис, и служба будет уничтожена. Слушайте изменения вызова и для каждого полученного намерения извлекайте информацию и перейдите к сервису и обработайте его там.

 Смежные вопросы

  • Нет связанных вопросов^_^