Display a view using windowmanager on lock screen
Asked Answered
S

3

12

I have a float icon that stays on top of all activities, but when the device get locked it disappear until the device get unlocked.

Another meaning, I want to display a view (FloatIcon) on lock screen using windowmanager from service.

This is my code so far.

public class FloatIcon extends Service {

    private WindowManager windowManager;
    private ImageView floatIcon;

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

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

        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        floatIcon = new ImageView(this);
        floatIcon.setImageResource(R.drawable.ic_launcher);
        floatIcon.setClickable(true);
        floatIcon.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getBaseContext(), MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                getApplication().startActivity(intent);
            }
        });

        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                    + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 0;
        params.y = 100;

        windowManager.addView(floatIcon, params);

    }

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

I could not get something useful when I google it.

Spicy answered 11/8, 2013 at 10:25 Comment(1)
Have you solved this problem? If so, could you please tell me how you made it?Floaty
F
12

Use WindowManager.LayoutParams.TYPE_SYSTEM_ERROR instead of WindowManager.LayoutParams.TYPE_PHONE that will solve the issue. This will make the view able to listen to touch events,. However you can use WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY also but it wont listen to touch events

Fermat answered 5/6, 2015 at 19:41 Comment(2)
@Kmeixner If you use SYSTER_ERROR as type for the windowmanager params it will make the view which is added with that params appear in lockscreens and all other screens with all touch events working, however you can also use SYSTEM_OVERLAY to make the view appear in all the screens including lockscreen but it wont have any touch eventsFermat
Though this does work on almost all devices, unfortunately I tested on Samsung S3, where it didn't work. The incoming call screen and lockscreen both overlap the View I was adding to the WindowManager.Toadinthehole
B
7

although the question is answered, some explanation:- using the TYPE_PHONE window with FLAG_SHOW_WHEN_LOCKED will only show on lock screen if that window is full screen -visit android reference, whereas using TYPE_SYSTEM_ERROR window type doesn't have the full screen restriction, thus solving the problem.

and as asked by @milosmns, a workaround for this can be adding a delay say about 100ms ,to your code that is displaying a window on incoming call screen will work like a charm.

Baring answered 26/5, 2016 at 11:45 Comment(0)
P
0

Don't add view in the OnCreate itself. Instead make a Broadcast receiver and pass the intent to it. This will show your icon only when the screen is locked. And it will go away when the screen is unlocked. Following is the code snippet. Don't forget to list your service in the manifest.

public class FloatingIconService extends Service {

private BroadcastReceiver mReceiver;
private boolean isShowing = false;
private WindowManager windowManager;
public ImageView icon;
private WindowManager.LayoutParams params;

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

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    Log.i("onStart", "FloatingIconService");

    return super.onStartCommand(intent,flags,startId);
}

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

    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

    //add icon and its properties
    icon = new ImageView(this);
    icon.setImageResource(R.drawable.ic_action_name);
    icon.setClickable(true);
    icon.setPadding(10, 10, 10, 10);
    icon.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View view) {

            Log.i("onStart", "FloatingIconService when long press on icon");
            ((Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE)).vibrate(1000);

            Intent i = new Intent(getApplicationContext(), Dashboard.class);
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            startActivity(i);
            return true;
        }
    });

    //set parameters for the icon
    params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
            PixelFormat.TRANSLUCENT);
    params.gravity = Gravity.BOTTOM;
    params.x=0;
    params.y=0;

    //Register receiver for determining screen off and if user is present
    mReceiver = new FloatingIconReceiver();
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
    filter.addAction(Intent.ACTION_USER_PRESENT);

    registerReceiver(mReceiver, filter);
}

private class FloatingIconReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            //if screen is turn off show the icon
            if (!isShowing) {
                windowManager.addView(icon, params);
                isShowing = true;
            }
        } else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
            //Handle resuming events if user is present/screen is unlocked remove the icon immediately
            if (isShowing) {
                windowManager.removeViewImmediate(icon);
                isShowing = false;
            }
        }
    }
}

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

    if (mReceiver != null) {
        unregisterReceiver(mReceiver);
    }

    //remove view if it is showing and the service is destroy
    if (isShowing) {
        windowManager.removeViewImmediate(icon);
        isShowing = false;
    }
    super.onDestroy();
}

}

Only if someone could help me make this icon float. Like we can do it in activities using FAB.

Patton answered 24/8, 2018 at 9:15 Comment(1)
FLAG_SHOW_WHEN_LOCKED deprecated. whats the alternative?Braunstein

© 2022 - 2024 — McMap. All rights reserved.