Android : 창을 추가 할 수 없습니다. 이 창 유형에 대한 권한이 거부되었습니다.


85

나는 약간의 정보가있는 창을 표시해야하는 응용 프로그램에서 일하고 있어요 ON 전화를 잠금 해제하지 않고 잠금 화면 (키 가드). 아마도 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG로 할 수 있다고 생각했습니다.

하지만 내 앱이 다음 오류와 함께 충돌 할 때마다 :

android.view.WindowManager $ BadTokenException : 창을 추가 할 수 없음 android.view.ViewRootImpl$W@40ec8528-이 창 유형에 대한 권한이 거부되었습니다.

이 게시물 ( here , herehere )은 모두 동일한 답변을 제공합니다. Manifest 파일에 다음 권한을 추가하려면.

android.permission.SYSTEM_ALERT_WINDOW

구현 한 솔루션이지만 여전히 동일한 오류가 발생합니다. 내가 뭘 잘못하고 있는지 알아?

내 매니페스트 파일의 권한은 다음과 같습니다.

<?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" />

그리고 이것은 잠금 화면에 Window를 추가하는 데 사용하는 코드입니다.

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

아는 사람있어?

PS Android 4.4.2를 실행하는 HTC Desire 620 DS에서 테스트 중입니다.

답변:


30

완전히 명백한 이유 때문에 일반 앱은 잠금 화면 위에 임의의 창을 만들 수 없습니다 . 잠금 화면에 실제 잠금 화면을 완벽하게 모방하여 차이를 구분할 수없는 창을 만들면 어떻게 할 수 있을까요?

오류의 기술적 이유는 TYPE_KEYGUARD_DIALOG플래그를 사용하기 때문 android.permission.INTERNAL_SYSTEM_WINDOW입니다. 서명 수준의 권한이 필요합니다 . 이는 권한 작성자 와 동일한 인증서 로 서명 된 앱만 사용할 수 있음을 의미합니다.

제작자 android.permission.INTERNAL_SYSTEM_WINDOW는 Android 시스템 자체이므로 앱이 OS의 일부가 아닌 이상 기회가 없습니다.

잠금 화면에서 정보를 사용자에게 알리는 잘 정의되고 문서화 된 방법이 있습니다. 잠금 화면에 표시되는 사용자 지정 알림을 만들 수 있으며 사용자가 상호 작용할 수 있습니다.


2
개인적으로 저는 Facebook 앱의 잠금 화면 알림과 같은 것을 찾고있었습니다. 새로운 잠금 화면 알림에 대해 이미 알고 있었지만 현재로서는 Android 22에서만 작동합니다. Android 16 이상에서 작동하는 솔루션이 필요합니다. 그러나 당신의 대답은 완벽하게 이해가되며 나는 그것을 받아 들일 것입니다. 잠금 화면에 창을 표시했지만 필요한 것은 아니지만 아래에서 찾은 솔루션을 게시하겠습니다.
DroidPilot 2015-08-26

1
앱에 해당 권한이 필요한 경우 설치하고 연 후에 부여 할 수 있습니다.
SkorpEN

나는 Oreo 이후 이것이 정답이라고 생각합니다. stackoverflow.com/a/48481628/504179
ATom

107

사용하는 경우 사용 apiLevel >= 19하지 마십시오

WindowManager.LayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT 

다음과 같은 오류가 발생합니다.

android.view.WindowManager $ BadTokenException : 창을 추가 할 수 없음 android.view.ViewRootImpl$W@40ec8528-이 창 유형에 대한 권한이 거부되었습니다.

대신 사용 :

LayoutParams.TYPE_TOAST or TYPE_APPLICATION_PANEL

3
내가있어 한 TYPE_SYSTEM_ALERT와 안드로이드 5.1에서 잘 작동 android.permission.SYSTEM_ALERT_WINDOW매니페스트에 부여.
Sam

android.permission.SYSTEM_ALERT_WINDOW와 함께 사용해야 LayoutParams.TYPE_TOAST합니까?
t0m

1
LayoutParams.TYPE_TOAST 시도했습니다. Lollipop과 Marshmallow에서 모두 API 레벨 6.0.1에서 작동합니다. 그 전에는 Lollipop에서만 작동하는 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT를 사용했습니다.
Prashant

안타깝게도 일부 응용 프로그램이 권한 대화 상자를 요청하는 경우 "화면 오버레이 감지"가 발생합니다 (보기가 활성화 된 경우)
Siarhei

서비스 또는 브로드 캐스트 수신기 내에서 창을 표시하려는 경우 작동하지 않습니다.
FindOutIslamNow

78

타겟을 구분해야 할 것 같아요 (오레오 전후)

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

비슷한 기술을 사용하려고하는데 안드로이드 스튜디오가 Build.VERSION_CODES.O& WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY. 내 targetSdkVersion은 26
Gabe O'Leary

내 편에서 +1 도움을 주셔서 감사합니다.
Saveen

@ GabeO'Leary 나는 같은 문제에 직면하고 있는데, 이것에 대한 해결책이 있습니까?
Sagar

49

이 문제에 사용할 수있는 모든 예제를 시도하기 위해 최선을 다했습니다. 마침내 나는 이것에 대한 답을 얻었습니다. 얼마나 신뢰할 수 있는지 모르겠지만 내 앱이 지금 충돌하지 않습니다.

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

매니페스트 파일에서 권한을 부여하십시오.

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

이것에 추가하면 API 레벨이> = 23이면 확인할 수 있습니다.

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

누군가 어딘가에 도움이되기를 바랍니다. 전체 예 https://anam-android-codes.blogspot.in/?m=1


13

Android API 레벨 8.0.0의 경우 다음을 사용해야합니다.

WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

대신에

LayoutParams.TYPE_TOAST or TYPE_APPLICATION_PANEL

또는 SYSTEM_ALERT.


TYPE_APPLICATION_OVERLAY는 Android 스튜디오에 표시된 옵션 목록에 없습니다. "심볼 유형을 확인할 수 없습니다"라는 메시지가 나타납니다. 내가 무엇을 놓치고 있습니까?
philcruz

11

이 코드가 완벽하게 작동하도록 시도하십시오.

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

당신은 내 생명을 구했습니다
Fo Nko

이 코드를 넣어 위젯을 표시 할 경우 @BakaWaii 잘이 작동에
shakirullah orakzai

6

검색

다른 앱 위에 그리기

설정에서 앱을 활성화하십시오. Android 8 Oreo의 경우

설정> 앱 및 알림> 앱 정보> 다른 앱 위에 표시> 사용


1
당신은 생명의 은인입니다
Noor Hossain

5

먼저 매니페스트 파일에 추가 권한이 있는지 확인하십시오.

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

응용 프로그램이 다른 응용 프로그램 권한 위에 그려 졌는지 확인하십시오. 이 권한은 기본적으로 API <23에 사용할 수 있습니다. 그러나 API> 23의 경우 런타임에서 권한을 요청해야합니다.

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

이 코드를 사용하십시오.

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

}


xml 코드를 공유하고 github 또는 다른 것을 볼 수 있습니까?
pavel

4

Android O와 호환되도록 프로젝트에서 플래그 Windowmanger 플래그 "TYPE_SYSTEM_OVERLAY"를 "TYPE_APPLICATION_OVERLAY"로 변경하십시오.

WindowManager.LayoutParams.TYPE_PHONE ...에 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY


3

TYPE_SYSTEM_OVERLAY대신을 사용하여 잠금 화면에 마침내 창을 표시했습니다 TYPE_KEYGUARD_DIALOG. 이것은 예상대로 작동하며 잠금 화면에 창을 추가합니다.

이것의 문제는 가능한 모든 것 위에 창이 추가 된다는 것입니다. 즉, 보안 잠금 화면의 경우이 창이 키패드 / ​​패턴 잠금 상단에도 나타납니다. 보안되지 않은 잠금 화면의 경우 잠금 화면에서 열면 알림 트레이 상단에 나타납니다.

나에게는 그것은 용납 할 수없는 일입니다. 나는 이것이이 문제에 직면 한 다른 사람에게 도움이되기를 바랍니다.


해결 해주셔서 감사합니다. 그것을 무시할 수있는 방법이 있습니까? 로 추가 할 때 대화 상자를 닫을 수 없습니다 TYPE_SYSTEM_OVERLAY. AlertDialog의 setOnDismissListener가 호출되지 않습니다.
Tom Taylor

3

WindowManager다음 단계 를 통해 간단한보기를 추가했습니다 .

  1. 표시 할 하나의 레이아웃 파일 만들기 (제 경우에는 dummy_layout)
  2. 매니페스트에 동적으로 권한을 추가합니다.
// 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);
}

이를 통해 WM에보기를 추가 할 수 있습니다.

파이에서 테스트되었습니다.


2

LayoutParams.TYPE_PHONE은 더 이상 사용되지 않습니다. 나는 이와 같이 내 코드를 업데이트했습니다.

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에는 API 레벨 26 이상이 필요합니다.


0

권한을 거부하는 주된 이유는 다른 앱에 그림을 그릴 수있는 권한이 없기 때문입니다. 다음 코드로 수행 할 수있는 다른 앱에 그림을 그릴 권한을 제공해야합니다.

권한 요청 코드

    public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;

이것을 MainActivity에 추가하십시오 .


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

이것도 추가

    @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

나는 함께 작업 솔루션을 찾기 위해 노력 ApplicationContext하고을 TYPE_SYSTEM_ALERT경우 당신이 대화 상자가 모든 활동에서 열 수 있어야합니다 및 솔루션 혼란을 발견 심지어 대화하는 당신은 사용이 싱글 getApplicationContext()하고, 원하는 경우 대화 상자가해야 TYPE_SYSTEM_ALERT다음 단계가 필요합니다 :

먼저 올바른 테마로 대화 상자의 인스턴스를 가져 오십시오. 또한 다음 스 니펫에서했던 것처럼 버전 호환성을 관리해야합니다.

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

제목, 메시지 및 버튼을 설정 한 후 대화 상자를 다음과 같이 작성해야합니다.

AlertDialog alert = builder.create();

이제 type여기 에서 연극이 메인 롤이됩니다. 이것이 충돌의 이유이므로 호환성을 다음과 같이 처리했습니다.

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

참고 : AppCompatDialog아래와 같이 사용자 정의 대화 상자를 사용하는 경우 :

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

AppCompatDialog다음과 같이 인스턴스에 유형을 직접 정의 할 수 있습니다 .

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

매니페스트 권한을 추가하는 것을 잊지 마십시오.

<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

WindowManager.LayoutParams.TYPE_SYSTEM_ERROROS 버전 <Oreo가 더 이상 사용되지 않으므로 추가 되었는지 확인하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.