11

Ich muss ein Overlay-Fenster wie True Caller App implementieren. Aber das Problem, das ich bekomme, ist, während jeder eingehenden oder ausgehenden Anruf mein Service automatisch schließen oder zerstört.Overlay-Fenster-Service In Android

Service-Klasse

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)); 
    } 
} 

}

Und hier folgt eine BroadcastReceiver den eingehenden und ausgehenden Anrufen und auch Start und Stop Overlayservice ist zu erkennen, verwendet.

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

Könnten Sie bitte den Stacktrace (mit dem Debugger) auf onDetachedFromWindow() -Methode der Ansicht, die Sie Fenstermanager hinzufügen. Versuchen Sie auch, WindowManager.LayoutParams.TYPE_PHONE zu TYPE_SYSTEM_ALERT zu ändern und zu sehen, ob sich irgendetwas ändert? –

+0

@TinTran, Vielen Dank für Ihr Feedback. Ich muss ein Overlay von der Service-Klasse zeigen, dann weiß ich nicht, StackTrace (mit dem Debugger) auf onDetachedFromWindow() -Methode der Ansicht, die Sie Fenstermanager hinzufügen. –

+0

Haben Sie jemals eine benutzerdefinierte Ansicht geschrieben? Haben Sie versucht, WindowManager.LayoutParams.TYPE_PHONE in TYPE_SYSTEM_ALERT zu ändern –

Antwort

1

Der Vordergrunddienst hat eine hohe Priorität. Versuchen Sie also, Ihren Dienst als Vordergrunddienst zu erstellen, und prüfen Sie, ob das funktioniert. Zum Erstellen eines Vordergrunddienstes müssen Sie eine Benachrichtigung bereitstellen, damit die Benutzer erkennen, dass ein Vordergrunddienst ausgeführt wird.

Hier ist, wie Sie ein erstellen foreground service

Aber vor Ihrem Dienst Vordergrund zu machen, zu debuggen, warum Ihr aktueller Service wird durch die Überprüfung der Protokolle jämmerlich.

+0

Hallo Vins, danke für deine Antwort. Können Sie mir ein Beispiel geben? Da ist mir Vordergrund-Service nicht bekannt. –

0

Die Instanz des BroadcastReceivers wird vom System automatisch gelöscht, nachdem eine Absicht empfangen wurde. So wird der referenzierte Telefoniedienst auch getötet, was Ihren aktuellen Implementierungsbuggy verursacht, der unter Bedingungen auf der Grundlage Ihrer aktuellen Implementierung wiederum einen Stoppdienst aufrufen würde und der Dienst würde zerstört werden. Achten Sie auf Anrufänderungen und extrahieren Sie für jede empfangene Absicht die Informationen und übergeben Sie sie an den Dienst und bearbeiten Sie sie dort.

Verwandte Themen