【问题标题】:Display a view using windowmanager on lock screen在锁定屏幕上使用窗口管理器显示视图
【发布时间】:2013-08-11 10:25:13
【问题描述】:

我有一个浮动图标,它停留在所有活动的顶部,但是当设备被锁定时,它会消失,直到设备被解锁。

另一个含义,我想使用服务中的窗口管理器在锁定屏幕上显示一个视图(FloatIcon)。

这是我目前的代码。

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

我在谷歌上找不到有用的东西。

【问题讨论】:

  • 这个问题你解决了吗?如果是这样,你能告诉我你是怎么做到的吗?

标签: android android-windowmanager


【解决方案1】:

使用 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR 代替 WindowManager.LayoutParams.TYPE_PHONE 可以解决问题。这将使视图能够监听触摸事件。但是你也可以使用 WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY 但它不会监听触摸事件

【讨论】:

  • @Kmeixner 如果您使用 SYSTER_ERROR 作为 windowmanager 参数的类型,它将使使用该参数添加的视图出现在锁屏和所有其他所有触摸事件都工作的屏幕中,但是您也可以使用 SYSTEM_OVERLAY使视图出现在包括锁屏在内的所有屏幕中,但不会有任何触摸事件
  • 虽然这确实适用于几乎所有设备,但不幸的是我在三星 S3 上进行了测试,但它不起作用。来电屏幕和锁屏都与我添加到 WindowManager 的视图重叠。
【解决方案2】:

虽然问题得到了解答,但还是有一些解释:- 使用带有 FLAG_SHOW_WHEN_LOCKEDTYPE_PHONE 窗口只会在该窗口全屏时显示在锁定屏幕上 - 访问 android reference,而使用 TYPE_SYSTEM_ERROR 窗口类型没有全屏限制,从而解决问题。

正如@milosmns 所要求的那样,解决方法可以是在您的代码中添加大约 100 毫秒的延迟,在来电屏幕上显示窗口的代码将像魅力一样工作。

【讨论】:

    【解决方案3】:

    不要在 OnCreate 本身中添加视图。而是制作一个广播接收器并将意图传递给它。这将仅在屏幕锁定时显示您的图标。当屏幕解锁时它会消失。 以下是代码sn-p。不要忘记在清单中列出您的服务。

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

    }

    只有在有人可以帮助我使这个图标浮动的情况下。就像我们可以在活动中使用 FAB 一样。

    【讨论】:

    • FLAG_SHOW_WHEN_LOCKED 已弃用。有什么选择?
    猜你喜欢
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    • 2022-01-10
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 1970-01-01
    相关资源
    最近更新 更多