Complete steps for Android to create a floating window

Time:2021-9-21

There are three steps to create a floating window in Android

1. Application authority

2. Use the service to start the suspended window

3. Set the suspended window parameters and add them to WindowManager

I won’t say much below. Let’s take a look at the detailed implementation process

Apply for permission

First, you need to apply for floating window permission and add it under manifest in the manifest file

<!--  Permissions required for lower version floating window -- >
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Dynamically request permission in activity

public class MainActivity extends Activity {
	/**Suspended window permission identification code*/
    public static final int CODE_WINDOW = 0;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Apply for suspended window permission
		if (Build.VERSION.SDK_INT >= 23) {
            if (!Settings.canDrawOverlays(this)) {
                Toast. Maketext (this, "please open the suspended window permission of this application - Shendi", toast. Length_short). Show();
                startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_WINDOW);
            }
        }
        
        //Close the current activity so that only the floating window is displayed
        finish();
    }

	//Callback after successful permission application
	@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        	//Exit without permission
            case Permission.CODE_WINDOW:
                if (resultCode != Activity.RESULT_OK) System.exit(0);
                break;
            default:
                Toast. Maketext (this, "unknown permission callback:" + requestcode, toast. Length_short). Show();
        }
    }
}

Start the hover window using the service

WindowManager is mainly used for the operation of suspended windows

Create a service and register it in the manifest file


public class TestService extends Service {
	@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

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

Register the service in the application of the manifest file


<service android:name=".TestService" />

Start service in activity


Intent intent = new Intent(this, TestService.class);
startService(intent);

Next, you need to create the interface of the suspended window, which is convenient for demonstration and can be created directly with code

You can also change the XML file into a view object using the inflate function


View.inflate(context, R.layout.main_activity, null);

In the onstartcommand function of the service, the contents are as follows


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	Button btn = new Button(this);
	btn.setText("hello,world");
	
    return super.onStartCommand(intent, flags, startId);
}

Set the floating window parameters and add them to WindowManager

Here, go directly to the code and look at the comments

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	Button btn = new Button(this);
	btn.setText("hello,world");
	
	//Get WindowManager
	WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
	//Create layout parameters
	WindowManager.LayoutParams params = new WindowManager.LayoutParams();
	/**Set parameters*/
	params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
	WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
                WindowManager.LayoutParams.TYPE_PHONE;
    params.format = PixelFormat.RGBA_8888;
    //Set the code of conduct for the window
    params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
    //Set transparency
    params.alpha = 1.0f;
    //Set the alignment of the internal view. The position here is left and top
    params.gravity = Gravity.LEFT | Gravity.TOP;
    //Coordinates of the upper left corner of the window
    params.x = 0;
    params.y = 0;
    //Set the width and height of the window, which is automatic
    params.width = WindowManager.LayoutParams.WRAP_CONTENT;
    params.height = WindowManager.LayoutParams.WRAP_CONTENT;

	//Add to WindowManager
	wm.addView(btn, params);
    return super.onStartCommand(intent, flags, startId);
}

The complete code is as follows

TestActivity

package shendi.app.game.robot;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.Toast;

public class TestActivity extends Activity {

    /**Suspended window permission identification code*/
    public static final int CODE_WINDOW = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Apply for suspended window permission
        if (Build.VERSION.SDK_INT >= 23) {
            if (!Settings.canDrawOverlays(this)) {
                Toast. Maketext (this, "please open the suspended window permission of this application - Shendi", toast. Length_short). Show();
                startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_WINDOW);
            }
        }

        Intent intent = new Intent(this, TestService.class);
        startService(intent);

        //Close the current activity so that only the floating window is displayed
        finish();
    }

    //Callback after successful permission application
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            //Exit without permission
            case Permission.CODE_WINDOW:
                if (resultCode != Activity.RESULT_OK) System.exit(0);
                break;
            default:
                Toast. Maketext (this, "unknown permission callback:" + requestcode, toast. Length_short). Show();
        }
    }

}

TestService

package shendi.app.game.robot;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.IBinder;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.Button;

public class TestService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Button btn = new Button(this);
        btn.setText("hello,world");

        //Get WindowManager
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        //Create layout parameters
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        /**Set parameters*/
        params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
                WindowManager.LayoutParams.TYPE_PHONE;
        params.format = PixelFormat.RGBA_8888;
        //Set the code of conduct for the window
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        //Set transparency
        params.alpha = 1.0f;
        //Set the alignment of the internal view. The position here is left and top
        params.gravity = Gravity.LEFT | Gravity.TOP;
        //Coordinates of the upper left corner of the window
        params.x = 0;
        params.y = 0;
        //Set the width and height of the window, which is automatic
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;

        //Add to WindowManager
        wm.addView(btn, params);
        return super.onStartCommand(intent, flags, startId);
    }

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

Run the app, and you can see the hello and world buttons in the upper left corner of the screen

Drag effect

Adding a touch event to the suspension component can achieve the drag effect, but the button component is not applicable

Here is a simple implementation code fragment

private int upX, upY;
//View movement processing
view.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                upX = (int) event.getRawX();
                upY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                //If the difference from the previous position is less than 5, it will not move
                if (event.getRawX() - upX > 5 || event.getRawY() - upY > 5) {
                    params.x = (int) event.getRawX();
                    params.y = (int) event.getRawY();
                    wm.updateViewLayout(view, params);
                }
                break;
            case MotionEvent.ACTION_UP:
                //If the difference is less than 5, it means click
                if (event.getRawX() - upX < 5 && event.getRawY() - upY < 5) {
                    // TODO
                }
                break;
        }
        return false;
    }
});

Remove the suspended window

It can be removed in the ondestry function


@Override
public void onDestroy() {
    wm.removeView(view);
    super.onDestroy();
}

summary

This is the end of this article about creating a floating window for Android. For more information about Android floating window, please search previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!