11

Tôi phải triển khai Cửa sổ Lớp phủ như Ứng dụng Người gọi Đúng. Nhưng vấn đề tôi nhận được là Trong bất kỳ cuộc gọi đến hoặc đi nào, dịch vụ của tôi sẽ tự động đóng hoặc hủy.Dịch vụ Cửa sổ Lớp phủ Trong Android

lớp Service

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

}

Và đây Sau đây là một BroadcastReceiver để phát hiện các cuộc gọi đến và đi và cũng có thể được sử dụng để bắt đầu và ngừng 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

Bạn có thể gửi stacktrace (sử dụng trình gỡ rối) trên phương thức onDetachedFromWindow() của chế độ xem mà bạn thêm vào trình quản lý cửa sổ hay không. Ngoài ra, hãy thử thay đổi WindowManager.LayoutParams.TYPE_PHONE thành TYPE_SYSTEM_ALERT và xem liệu nó có thay đổi gì không? –

+0

@TinTran, Cảm ơn phản hồi của bạn. Tôi cần phải hiển thị một lớp phủ từ lớp dịch vụ sau đó tôi không biết để có được stacktrace (bằng cách sử dụng trình gỡ lỗi) trên phương pháp onDetachedFromWindow() của khung nhìn mà bạn thêm vào trình quản lý cửa sổ. –

+0

Bạn đã bao giờ viết chế độ xem tùy chỉnh chưa? Bạn đã cố gắng thay đổi WindowManager.LayoutParams.TYPE_PHONE thành TYPE_SYSTEM_ALERT –

Trả lời

1

Dịch vụ mặt trước có ưu tiên cao, vì vậy hãy thử tạo dịch vụ của bạn làm dịch vụ nền trước và kiểm tra xem dịch vụ có hoạt động hay không. Để tạo dịch vụ nền trước, bạn cần cung cấp thông báo để người dùng biết rằng dịch vụ nền trước đang diễn ra.

Đây là cách bạn có thể tạo một foreground service

Nhưng trước khi thực hiện foreground dịch vụ của bạn, gỡ lỗi tại sao dịch vụ hiện tại của bạn đang bị giết bằng cách kiểm tra các bản ghi.

+0

Hi Vins, cảm ơn câu trả lời của bạn. Bạn có thể cho tôi một ví dụ không. Vì tôi không biết dịch vụ tiền cảnh. –

0

Phiên bản của BroadcastReceiver sẽ tự động bị xóa bởi hệ thống sau khi nhận được ý định. Vì vậy, dịch vụ điện thoại được tham chiếu cũng sẽ bị hủy, khiến lỗi triển khai hiện tại của bạn sẽ được xác nhận theo các điều kiện dựa trên việc triển khai hiện tại của bạn sẽ gọi dịch vụ dừng và dịch vụ sẽ bị hủy. Lắng nghe các thay đổi cuộc gọi và cho mỗi mục đích nhận được trích xuất thông tin và chuyển đến dịch vụ và xử lý nó ở đó.

Các vấn đề liên quan