android 8.0以上创建悬浮窗口

示例源码:

package com.example.jnotification;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;

public class CustomCreateNotification extends Activity {

	private View view;
	private WindowManager wm;
	private boolean showWm = true;// 默认是应该显示悬浮通知栏
	private WindowManager.LayoutParams params;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		if (Build.VERSION.SDK_INT >= 23) {
			if (!Settings.canDrawOverlays(CustomCreateNotification.this)) {
				Intent intent = new Intent(
						Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
						Uri.parse("package:" + getPackageName()));
				startActivityForResult(intent, 88);
			} else {
				createFloatView();
			}
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == 88) {
			if (!Settings.canDrawOverlays(this)) {
				Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show();
			} else {
				Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
				createFloatView();
			}
		}
	}

	private void createFloatView( ) {
        wm = (WindowManager) getApplicationContext().getSystemService(
                Context.WINDOW_SERVICE);
        params  = new WindowManager.LayoutParams();
        /*//这里需要着重说明的是LayoutParam里的type变量。这个变量是用来指定窗口类型的。
        //在设置这个变量时,需要注意一个坑,那就是需要对不同版本的Android系统进行适配。
        //在Android 8.0之前,悬浮窗口设置可以为TYPE_PHONE,这种类型是用于提供用户交互操作的非应用窗口。
             //而Android 8.0对系统和API行为做了修改,包括使用SYSTEM_ALERT_WINDOW权限的应用无法再使用以下窗口类型来在其他应用和窗口上方显示提醒窗口
        // TYPE_PHONE
        ///TYPE_PRIORITY_PHONE
        //TYPE_SYSTEM_ALERT
        // TYPE_SYSTEM_OVERLAY
        //TYPE_SYSTEM_ERROR
          //如果需要实现在其他应用和窗口上方显示提醒窗口,那么必须该为TYPE_APPLICATION_OVERLAY的新类型。
          //如果在Android 8.0以上版本仍然使用TYPE_PHONE类型的悬浮窗口,则会出现如下异常信息:*/
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        	params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
        	params.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        params.format = PixelFormat.TRANSPARENT;
        //设置必须触摸通知栏才可以关掉
        params.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                | WindowManager.LayoutParams.FLAG_FULLSCREEN
                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

        // 设置通知栏的长和宽
        params.width = wm.getDefaultDisplay().getWidth();
        params.height = 200;
        params.gravity =Gravity.TOP;
        view = LayoutInflater.from(this).inflate(R.layout.notification, null);
        //在这里你可以解析你的自定义的布局成一个View
        if (showWm){
            wm.addView(view, params);
            showWm = false;
        }else {
            wm.updateViewLayout(view,params);
        }


        view.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction())
                {
                    case MotionEvent.ACTION_DOWN:
                        wm.removeViewImmediate(view);//触摸到悬浮窗口区域即消失窗口
                        view = null;
                        break;
                    case MotionEvent.ACTION_MOVE:

                        break;
                }
                return true;
            }
        });

    }
}

备注【代码一】:
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            params.type = WindowManager.LayoutParams.TYPE_PHONE;
 }

当你在 AndroidMainfest.xml文件中声明了下面权限

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

且也动态申请了权限 ,但运行应用仍出现异常,是因为没在在实现中加入上面的【代码一】源码,

引申阅读:

 Android悬浮窗的实现

Android8.0通知栏和悬浮窗新改动

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您可以参考下面的代码实现: 1. 在 AndroidManifest.xml 文件中添加悬浮窗权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> ``` 2. 创建一个悬浮窗 Service: ```java public class FloatWindowService extends Service { private WindowManager mWindowManager; private WindowManager.LayoutParams mLayoutParams; private View mFloatView; @Override public void onCreate() { super.onCreate(); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mLayoutParams = new WindowManager.LayoutParams(); mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; mLayoutParams.format = PixelFormat.RGBA_8888; mLayoutParams.gravity = Gravity.START | Gravity.TOP; mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; // 创建悬浮窗视图 mFloatView = LayoutInflater.from(this).inflate(R.layout.float_window, null); // 设置悬浮窗视图的点击事件 mFloatView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 点击悬浮窗执行的操作 } }); // 将悬浮窗视图添加到窗 mWindowManager.addView(mFloatView, mLayoutParams); } @Override public void onDestroy() { super.onDestroy(); // 销毁悬浮窗视图 mWindowManager.removeView(mFloatView); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } ``` 3. 创建一个悬浮窗布局文件 float_window.xml: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/float_window_icon"/> </RelativeLayout> ``` 4. 在需要显示悬浮窗的地方启动 FloatWindowService: ```java Intent intent = new Intent(this, FloatWindowService.class); startService(intent); ``` 以上就是一个简单的悬浮窗实现方法,您可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值