Android 应用内悬浮窗

悬浮窗是指一种可以悬浮在应用界面上方的窗口,它可以在应用运行的过程中显示在其他应用的上方。在Android应用开发中,悬浮窗可以用于实现一些实用的功能,如浮动的音乐播放器、实时的天气信息显示等。本文将介绍如何在Android应用中创建一个悬浮窗,并提供代码示例。

实现思路

在Android中,要实现应用内悬浮窗,可以使用系统的WindowManager类来创建一个Window,并设置Window的一些属性,使其显示在其他应用的上方。在创建悬浮窗时,需要添加一些权限并处理用户权限申请的逻辑。

下面是一个实现应用内悬浮窗的步骤:

  1. 在AndroidManifest.xml中添加悬浮窗权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
  1. 创建一个Service来管理悬浮窗的显示和隐藏:
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;
        // 设置Window的一些属性,如宽高、位置等
        // ...

        // 创建悬浮窗的布局
        mFloatView = LayoutInflater.from(this).inflate(R.layout.float_window, null);
        // 初始化悬浮窗的控件和事件
        // ...
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 显示悬浮窗
        mWindowManager.addView(mFloatView, mLayoutParams);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 隐藏悬浮窗
        mWindowManager.removeView(mFloatView);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
  1. 在需要显示悬浮窗的地方启动Service,例如在MainActivity中:
public class MainActivity extends AppCompatActivity {
    private static final int REQUEST_CODE = 100;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 检查是否已经获取悬浮窗权限
        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, REQUEST_CODE);
        } else {
            // 启动Service显示悬浮窗
            startService(new Intent(this, FloatWindowService.class));
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(this)) {
                // 启动Service显示悬浮窗
                startService(new Intent(this, FloatWindowService.class));
            }
        }
    }
}

类图

classDiagram
    class FloatWindowService {
        +onCreate()
        +onStartCommand()
        +onDestroy()
        +onBind()
    }
    class MainActivity {
        -onCreate()
        -onActivityResult()
    }
    class WindowManager {
        #addView()
        #removeView()
        #updateViewLayout()
    }
    class LayoutInflater {
        +inflate()
    }
    class View {
        #setVisibility()
        +setOnClickListener()
    }
    class Intent {
        constructor()
    }
    class Settings {
        +canDrawOverlays()
    }

甘特图

gantt
    dateFormat  MM-DD
    title       悬浮窗开发流程
    section 创建悬浮窗
    创建Service                            :done, 01-01, 3d
    添加悬浮窗权限                        :done, 01-01, 1d
    设置Window属性                       :done, 01-02, 1d
    创建悬浮窗布局                         :done, 01-03, 1d
    初始化悬浮窗控件和事件                  :done, 01-