Search code examples
androidandroid-broadcastreceiverwindow-managers

Duplication of views using WindowManager


I have build an app where I need to show card on an incoming call. It works fine in Kitkat, but in Android L, M, N the card appears twice, why?

Result (Kitkat) enter image description here

Result (Lollipop-Nougat-Marshmallow) enter image description here

My code

 package tutorials.hackro.com.callincoming;

import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * Created by hackro on 4/03/17.
 */
public class MyPhoneBroadcastReceiver extends BroadcastReceiver {

    private WindowManager wm;
    private WindowManager.LayoutParams params;
    private LinearLayout ly;
    private View view;
    private TextView lblCelular,nameContact;
    private Button btnExpediente;
    private int height;
    private Context context;
    private String number;
    private Display display;
    private LayoutInflater mInflater;
    private Bundle bundle;
    private TelephonyManager telephony;
    private boolean callincoming;
    public void onReceive(final Context cc, Intent intent) {
        this.context= cc;
        bundle = intent.getExtras();
        number = bundle.getString("incoming_number");
        intializeElements();
        initializeUI();
        initializeValuesElements();
        events();

        telephony = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

    }

    private PhoneStateListener phoneStateListener = new PhoneStateListener() {
        public void onCallStateChanged(int state, String incomingNumber) {

            if (state == TelephonyManager.CALL_STATE_RINGING) {
                if(!callincoming){
                    wm.addView(ly, params);
                    Log.e("a","a");
                    callincoming = !callincoming;
                }
            }
            if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
                System.exit(0);

            }

            if (state == TelephonyManager.CALL_STATE_IDLE) {
                System.exit(0);
            }
        }
    };


    private void intializeElements() {
        wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        ly = new LinearLayout(context);
        mInflater = LayoutInflater.from(context);
        view = mInflater.inflate(R.layout.call,null);
        display = wm.getDefaultDisplay();
        height = display.getHeight();
        initializeParams();
        ly.addView(view,params);
    }


    public void events(){

        ly.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);
                        wm.updateViewLayout(ly, params);
                        return true;
                }
                return false;
            }
        });




        btnExpediente.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                params.height = 0;
                ly.removeView(view);
                wm.updateViewLayout(ly,params);
                Intent i = new Intent(context,Main2Activity.class);
                i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(i);
            }
        });

    }
    public static String getContactName(Context context, String phoneNumber) {
        ContentResolver cr = context.getContentResolver();
        Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
        Cursor cursor = cr.query(uri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null);
        if (cursor == null) {
            return null;
        }
        String contactName = null;
        if(cursor.moveToFirst()) {
            contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
        }
        if(cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
        return contactName;
    }

    private void initializeParams(){

        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSPARENT);

        int SDK_INT = android.os.Build.VERSION.SDK_INT;
        if(SDK_INT >= Build.VERSION_CODES.KITKAT && SDK_INT <= Build.VERSION_CODES.LOLLIPOP){
            params.height = (height/2);
        }
        else if(SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SDK_INT <= Build.VERSION_CODES.M){
            params.height = (height/4) + (height/15);
        }
        else if(SDK_INT >= Build.VERSION_CODES.M && SDK_INT <= Build.VERSION_CODES.N){
            params.height = (height/4) + (height/15);
        }

        else if(SDK_INT >= Build.VERSION_CODES.N){
            params.height = (height/4) + (height/15);
        }
        params.height = (height/2);

        params.width = WindowManager.LayoutParams.MATCH_PARENT;
        params.gravity = Gravity.TOP;
        params.format = PixelFormat.TRANSLUCENT;

    }

    public void initializeUI(){
        lblCelular = (TextView) view.findViewById(R.id.lblCelular);
        nameContact= (TextView) view.findViewById(R.id.nameContact);
        btnExpediente = (Button) view.findViewById(R.id.btnExpediente);

    }

    public void initializeValuesElements(){
        nameContact.setText(getContactName(context,number));
        lblCelular.setText(number);
    }


    public void onDestroy() {
        telephony.listen(null, PhoneStateListener.LISTEN_NONE);
    }
}

Solution

  • I solved my problem.

    The problem is multiple call onReceive

    SOLUTION

     public static final String TAG = "PHONE STATE";
        private static String mLastState;
    
      String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
    
            if (!state.equals(mLastState)) {
                mLastState = state;
                Log.e(TAG, state);
    
                telephony = (TelephonyManager) context
                        .getSystemService(Context.TELEPHONY_SERVICE);
                telephony.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    
            }
    

    You can see more details here