使用 WindowManager 复制视图
Duplication of views using WindowManager
我构建了一个应用程序,需要在来电时出示卡片。它在 Kitkat 中工作正常,但在 Android L、M、N 中,卡片出现了两次,为什么?
结果(Kitkat)
结果(棒棒糖-牛轧糖-棉花糖)
我的代码
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);
}
}
我解决了我的问题。
问题是多次调用onReceive
解决方案
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);
}
您可以看到更多详情here
我构建了一个应用程序,需要在来电时出示卡片。它在 Kitkat 中工作正常,但在 Android L、M、N 中,卡片出现了两次,为什么?
结果(Kitkat)
结果(棒棒糖-牛轧糖-棉花糖)
我的代码
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);
}
}
我解决了我的问题。
问题是多次调用onReceive
解决方案
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);
}
您可以看到更多详情here