Android: Không thể thêm cửa sổ. Quyền bị từ chối đối với loại cửa sổ này


85

Tôi đang làm việc trên một ứng dụng mà tôi cần hiển thị một cửa sổ với một số thông tin TRÊN Màn hình khóa (KeyGuard) mà không cần mở khóa điện thoại. Tôi nghĩ rằng tôi có thể làm điều đó với WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG

Nhưng mỗi khi ứng dụng của tôi gặp sự cố với lỗi sau:

android.view.WindowManager $ BadTokenException: Không thể thêm cửa sổ android.view.ViewRootImpl$W@40ec8528 - quyền bị từ chối đối với loại cửa sổ này

Các bài viết này ( đây , đâyđây ) đều đưa ra câu trả lời giống nhau. Để thêm quyền sau vào tệp kê khai.

android.permission.SYSTEM_ALERT_WINDOW

Giải pháp mà tôi đã thực hiện nhưng tôi vẫn gặp lỗi tương tự. Bất kỳ ý tưởng về những gì tôi đang làm sai?

Đây là các quyền trong tệp kê khai của tôi:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.droidpilot.keyguardwindow" >

<uses-sdk
    android:minSdkVersion="16"
    android:targetSdkVersion="21" />

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />

Và đây là mã tôi sử dụng để thêm Cửa sổ vào màn hình khóa

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    LayoutInflater mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    mView = mInflater.inflate(R.layout.lock_screen_notif, null);

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
            PixelFormat.TRANSLUCENT
    );

    wm.addView(mView, params);

Có ai có ý kiến ​​gì không?

PS Tôi đang thử nghiệm trên HTC Desire 620 DS chạy Android 4.4.2

Câu trả lời:


30

Vì những lý do hoàn toàn rõ ràng, các Ứng dụng thông thường không được phép tạo các cửa sổ tùy ý trên đầu màn hình khóa . Bạn nghĩ tôi có thể làm gì nếu tôi tạo một cửa sổ trên màn hình khóa của bạn có thể bắt chước hoàn hảo màn hình khóa thực khiến bạn không thể phân biệt được?

Lý do kỹ thuật cho lỗi của bạn là việc sử dụng TYPE_KEYGUARD_DIALOGcờ - nó yêu cầu android.permission.INTERNAL_SYSTEM_WINDOWđó là quyền cấp chữ ký. Điều này có nghĩa là chỉ những Ứng dụng được ký bằng cùng một chứng chỉ với người tạo ra quyền mới có thể sử dụng nó.

Tác giả của chính android.permission.INTERNAL_SYSTEM_WINDOWlà hệ thống Android, vì vậy, trừ khi Ứng dụng của bạn là một phần của Hệ điều hành, bạn sẽ không có cơ hội.

Có nhiều cách được xác định rõ ràng và được lập thành văn bản để thông báo cho người dùng về thông tin từ màn hình khóa . Bạn có thể tạo các thông báo tùy chỉnh hiển thị trên màn hình khóa và người dùng có thể tương tác với chúng.


2
Cá nhân tôi đang tìm kiếm thứ gì đó giống như thông báo trên màn hình khóa của ứng dụng Facebook. Tôi đã biết về các thông báo trên màn hình khóa mới nhưng chúng chỉ hoạt động trong Android 22 hiện tại. Tôi cần một giải pháp hoạt động trên Android 16 trở lên. Nhưng câu trả lời của bạn hoàn toàn có lý và tôi sẽ chấp nhận nó như vậy. Mặc dù vậy, tôi đã quản lý để hiển thị một cửa sổ trên màn hình khóa nhưng nó không phải là thứ tôi cần, tôi sẽ đăng giải pháp mà tôi tìm thấy bên dưới.
DroidPilot

1
Nếu ứng dụng cần quyền đó, nó có thể được cấp sau khi cài đặt và mở.
SkorpEN

Tôi nghĩ rằng vì Oreo, đây là câu trả lời đúng stackoverflow.com/a/48481628/504179
ATom

107

nếu bạn sử dụng apiLevel >= 19, không sử dụng

WindowManager.LayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT 

gặp lỗi sau:

android.view.WindowManager $ BadTokenException: Không thể thêm cửa sổ android.view.ViewRootImpl$W@40ec8528 - quyền bị từ chối đối với loại cửa sổ này

Sử dụng cái này thay thế:

LayoutParams.TYPE_TOAST or TYPE_APPLICATION_PANEL

3
Tôi đã hoạt TYPE_SYSTEM_ALERTđộng tốt trên Android 5.1 với điều kiện android.permission.SYSTEM_ALERT_WINDOWđược cấp trong tệp kê khai.
Sam

Tôi phải sử dụng android.permission.SYSTEM_ALERT_WINDOWvới LayoutParams.TYPE_TOAST?
t0m 21/02/17

1
Tôi đã thử LayoutParams.TYPE_TOAST. Nó hoạt động cho tôi trên Lollipop và Marshmallow cả API cấp 6.0.1. Trước đó, tôi đã sử dụng WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, chỉ hoạt động cho Lollipop.
Prashant

tiếc là nó gây ra “Lớp phủ màn hình phát hiện” trong trường hợp một số hộp thoại yêu cầu xin cấp phép (nếu tầm nhìn của bạn đang hoạt động)
Siarhei

Điều này sẽ không hoạt động nếu bạn đang cố gắng hiển thị cửa sổ từ bên trong một dịch vụ hoặc bộ thu phát sóng
FindOutIslamNow

78

Tôi đoán bạn nên phân biệt mục tiêu (trước và sau Oreo)

int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}

params = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.WRAP_CONTENT,
    LAYOUT_FLAG,
    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
    PixelFormat.TRANSLUCENT);

Tôi đang cố gắng sử dụng một kỹ thuật tương tự nhưng studio android không thể nhận ra Build.VERSION_CODES.O& WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY. Mục tiêu của tôiSdkVersion là 26
Gabe O'Leary

Đánh giá cao sự giúp đỡ của bạn +1 từ phía tôi.
Saveen

@ GabeO'Leary Tôi đang gặp phải vấn đề tương tự, bạn có giải pháp cho việc này không?
Sagar

50

Tôi đã cố gắng hết sức để thử tất cả các ví dụ có sẵn cho vấn đề này. Cuối cùng, tôi đã có câu trả lời cho điều này, tôi không biết nó đáng tin cậy đến mức nào nhưng ứng dụng của tôi hiện không bị lỗi.

windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
    //here is all the science of params
    final LayoutParams myParams = new LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            LayoutParams.TYPE_SYSTEM_ERROR,
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
            PixelFormat.TRANSLUCENT
    );

Trong tệp kê khai của bạn, chỉ cần cấp quyền

 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Ngoài ra, bạn cũng có thể kiểm tra cấp API nếu> = 23 thì

 if(Build.VERSION.SDK_INT >= 23) {
    if (!Settings.canDrawOverlays(Activity.this)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, 1234);
    }
}
            else
{
    Intent intent = new Intent(Activity.this, Service.class);
    startService(intent);
}

Tôi hy vọng nó sẽ giúp ai đó ở đâu đó. Ví dụ đầy đủ https://anam-android-codes.blogspot.in/?m=1


13

Đối với cấp API Android 8.0.0, bạn nên sử dụng

WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

thay vì

LayoutParams.TYPE_TOAST or TYPE_APPLICATION_PANEL

hoặc SYSTEM_ALERT.


TYPE_APPLICATION_OVERLAY không có trong danh sách các tùy chọn được trình bày trong Android Studio. Tôi nhận được "không thể giải quyết loại biểu tượng". Tôi đang thiếu gì?
philcruz

11

thử mã này hoạt động hoàn hảo

int layout_parms;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 

    {  
         layout_parms = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

    }

     else {

            layout_parms = WindowManager.LayoutParams.TYPE_PHONE;

    }

    yourparams = new WindowManager.LayoutParams(       
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            layout_parms,
            WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);

bạn đã cứu cuộc đời tôi
Fo Nko

@BakaWaii nơi bạn muốn hiển thị widget để đặt mã này trong đó sẽ làm việc tốt
shakirullah orakzai

6

Tìm kiếm

Vẽ qua các ứng dụng khác

trong cài đặt của bạn và bật ứng dụng của bạn. Đối với Android 8 Oreo, hãy thử

Cài đặt> Ứng dụng & thông báo> Thông tin ứng dụng> Hiển thị trên các ứng dụng khác> Bật


1
bạn là một người cứu hộ
Noor Hossain

5

Trước hết, bạn đảm bảo rằng bạn có quyền thêm vào tệp kê khai.

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Kiểm tra xem ứng dụng có lấn át các ứng dụng khác hay không? Quyền này theo mặc định có sẵn cho API <23. Nhưng đối với API> 23, bạn phải yêu cầu quyền trong thời gian chạy.

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {

    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
            Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, 1);
} 

Sử dụng mã này:

public class ChatHeadService extends Service {

private WindowManager mWindowManager;
private View mChatHeadView;

WindowManager.LayoutParams params;

public ChatHeadService() {
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();

    Language language = new Language();
    //Inflate the chat head layout we created
    mChatHeadView = LayoutInflater.from(this).inflate(R.layout.dialog_incoming_call, null);


    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
        params.x = 0;
        params.y = 100;
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(mChatHeadView, params);

    } else {
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                PixelFormat.TRANSLUCENT);


        params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
        params.x = 0;
        params.y = 100;
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(mChatHeadView, params);
    }

    TextView tvTitle=mChatHeadView.findViewById(R.id.tvTitle);
    tvTitle.setText("Incoming Call");

    //Set the close button.
    Button btnReject = (Button) mChatHeadView.findViewById(R.id.btnReject);
    btnReject.setText(language.getText(R.string.reject));
    btnReject.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //close the service and remove the chat head from the window
            stopSelf();
        }
    });

    //Drag and move chat head using user's touch action.
    final Button btnAccept = (Button) mChatHeadView.findViewById(R.id.btnAccept);
    btnAccept.setText(language.getText(R.string.accept));


    LinearLayout linearLayoutMain=mChatHeadView.findViewById(R.id.linearLayoutMain);



    linearLayoutMain.setOnTouchListener(new View.OnTouchListener() {
        private int lastAction;
        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:

                    //remember the initial position.
                    initialX = params.x;
                    initialY = params.y;

                    //get the touch location
                    initialTouchX = event.getRawX();
                    initialTouchY = event.getRawY();

                    lastAction = event.getAction();
                    return true;
                case MotionEvent.ACTION_UP:
                    //As we implemented on touch listener with ACTION_MOVE,
                    //we have to check if the previous action was ACTION_DOWN
                    //to identify if the user clicked the view or not.
                    if (lastAction == MotionEvent.ACTION_DOWN) {
                        //Open the chat conversation click.
                        Intent intent = new Intent(ChatHeadService.this, HomeActivity.class);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);

                        //close the service and remove the chat heads
                        stopSelf();
                    }
                    lastAction = event.getAction();
                    return true;
                case MotionEvent.ACTION_MOVE:
                    //Calculate the X and Y coordinates of the view.
                    params.x = initialX + (int) (event.getRawX() - initialTouchX);
                    params.y = initialY + (int) (event.getRawY() - initialTouchY);

                    //Update the layout with new X & Y coordinate
                    mWindowManager.updateViewLayout(mChatHeadView, params);
                    lastAction = event.getAction();
                    return true;
            }
            return false;
        }
    });
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (mChatHeadView != null) mWindowManager.removeView(mChatHeadView);
}

}


bạn có thể chia sẻ mã xml của bạn và xem trong github hoặc một cái gì đó khác nó sẽ hữu ích cho tôi.
pavel

4

thay đổi cờ của bạn cờ Windowmanger "TYPE_SYSTEM_OVERLAY" thành "TYPE_APPLICATION_OVERLAY" trong dự án của bạn để tương thích với Android O

WindowManager.LayoutParams.TYPE_PHONE đến WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY


3

Cuối cùng, tôi đã quản lý để hiển thị một cửa sổ trên màn hình khóa với việc sử dụng TYPE_SYSTEM_OVERLAYthay vìTYPE_KEYGUARD_DIALOG . Điều này hoạt động như mong đợi và thêm cửa sổ trên màn hình khóa.

Vấn đề với điều này là cửa sổ được thêm vào trên tất cả mọi thứ có thể.Có nghĩa là, cửa sổ thậm chí sẽ xuất hiện trên bàn phím / khóa hình mẫu của bạn trong trường hợp màn hình khóa an toàn. Trong trường hợp màn hình khóa không an toàn, nó sẽ xuất hiện trên đầu khay thông báo nếu bạn mở từ màn hình khóa.

Đối với tôi, đó là điều không thể chấp nhận được. Tôi hy vọng rằng điều này có thể giúp bất kỳ ai khác đang đối mặt với vấn đề này.


Cảm ơn bạn rất nhiều cho giải pháp. Có cách nào để loại bỏ nó không? Tôi không thể loại bỏ hộp thoại khi thêm nó vào TYPE_SYSTEM_OVERLAY. SetOnDismissListener của tôi trên AlertDialog không được gọi.
Tom Taylor

3

Tôi chỉ thêm chế độ xem đơn giản vào WindowManagerbằng các bước sau:

  1. Tạo một tệp bố cục để hiển thị (dummy_layout trong trường hợp của tôi)
  2. Thêm quyền trong tệp kê khai và động.
// 1. Show view
private void showCustomPopupMenu()
{
    windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
    // LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    // View view = layoutInflater.inflate(R.layout.dummy_layout, null);
    ViewGroup valetModeWindow = (ViewGroup) View.inflate(this, R.layout.dummy_layout, null);
    int LAYOUT_FLAG;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    } else {
        LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
    }
    WindowManager.LayoutParams params=new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        LAYOUT_FLAG,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT);

    params.gravity= Gravity.CENTER|Gravity.CENTER;
    params.x=0;
    params.y=0;
    windowManager.addView(valetModeWindow, params);
}

// 2. Get permissions by asking
if (!Settings.canDrawOverlays(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, 1234);
}

Với điều này, bạn có thể thêm một chế độ xem vào WM.

Đã thử nghiệm trong Pie.


2

LayoutParams.TYPE_PHONE không được dùng nữa. Tôi đã cập nhật mã của mình như thế này.

parameters = if (Build.VERSION.SDK_INT > 25) {
        LayoutParams(
                minHW * 2 / 3, minHW * 2 / 3,
                LayoutParams.TYPE_APPLICATION_OVERLAY,
                LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT)
    }else {
        LayoutParams(
                minHW * 2 / 3, minHW * 2 / 3,
                LayoutParams.TYPE_PHONE,
                LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT)
    }

LayoutParams.TYPE_APPLICATION_OVERLAY yêu cầu api cấp 26 trở lên.


0

Lý do chính cho việc từ chối quyền là chúng tôi không có quyền vẽ trên các ứng dụng khác, Chúng tôi phải cung cấp quyền cho Vẽ trên các ứng dụng khác có thể được thực hiện bằng mã sau

Yêu cầu mã cho quyền

    public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;

thêm cái này vào MainActivity của bạn


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
            askPermission();
}


private void askPermission() {
        Intent intent= new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
        startActivityForResult(intent,ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}

Thêm cái này nữa

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE){
            if(!Settings.canDrawOverlays(this)){
                askPermission();
            }
        }
    }


0

Tôi đấu tranh để tìm ra giải pháp làm việc với ApplicationContextTYPE_SYSTEM_ALERTvà thấy khó hiểu giải pháp, Trong trường hợp bạn muốn hộp thoại sẽ được mở từ bất kỳ hoạt động thậm chí hộp thoại là một singleton bạn phải sử dụng getApplicationContext(), và nếu muốn hộp thoại nênTYPE_SYSTEM_ALERT bạn sẽ cần các bước sau :

trước tiên hãy lấy phiên bản hộp thoại với chủ đề chính xác, ngoài ra bạn cần quản lý khả năng tương thích của phiên bản như tôi đã làm trong đoạn mã sau:

AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext(), R.style.Theme_AppCompat_Light);

Sau khi đặt tiêu đề, thông báo và các nút, bạn phải xây dựng hộp thoại như sau:

AlertDialog alert = builder.create();

Bây giờ các typetrò chơi đóng vai trò chính ở đây, vì đây là lý do của sự cố, tôi đã xử lý tính tương thích như sau:

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        alert.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - 1);

    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    }

Lưu ý : nếu bạn đang sử dụng hộp thoại tùy chỉnh với AppCompatDialognhư sau:

AppCompatDialog dialog = new AppCompatDialog(getApplicationContext(), R.style.Theme_AppCompat_Light);

bạn có thể xác định trực tiếp kiểu của mình cho AppCompatDialogtrường hợp như sau:

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - 1);

    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    }

Đừng quên thêm quyền cho tệp kê khai:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

0
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            PixelFormat.TRANSLUCENT);

    params.gravity = Gravity.START | Gravity.TOP;
    params.x = left;
    params.y = top;
    windowManager.addView(view, params);

} else {
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            PixelFormat.TRANSLUCENT);


    params.gravity = Gravity.START | Gravity.TOP;
    params.x = left;
    params.y = top;
    windowManager.addView(view, params);
}

0

Đảm bảo đã WindowManager.LayoutParams.TYPE_SYSTEM_ERRORđược thêm vào phiên bản hệ điều hành <Oreo vì phiên bản này không được dùng nữa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.