Я должен реализовать окно 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;
}
}
}
Не могли бы вы опубликовать stacktrace (используя отладчик) в методе onDetachedFromWindow() представления, которое вы добавляете в диспетчер окон. Также попробуйте изменить WindowManager.LayoutParams.TYPE_PHONE на TYPE_SYSTEM_ALERT и посмотреть, не изменилось ли что-нибудь? –
@TinTran, Спасибо за ваши отзывы. Мне нужно показать наложение из класса Service, тогда я не знаю, как получить stacktrace (используя отладчик) в методе onDetachedFromWindow() представления, которое вы добавляете в диспетчер окон. –
Вы когда-нибудь писали пользовательский вид? Вы пытались изменить WindowManager.LayoutParams.TYPE_PHONE на TYPE_SYSTEM_ALERT –