Подтвердить что ты не робот

Создание наложения системы, где домашние кнопки все еще работают?

Я пытаюсь создать кнопку, которая всегда находится на экране.

  • Кнопка должна быть интерактивной и ничего прямо под кнопкой не следует активировать при нажатии.
  • Работа или домашний экран за кнопкой все равно работать, что пользователь должен по-прежнему способность взаимодействовать с домом экрана или приложения.
  • Программная клавиша кнопки должны по-прежнему работать: дома, назад, меню и т.д.

Следующий код содержит # 1 и # 2, но кнопки софт-клавиш больше не работают:

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
        WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
        PixelFormat.TRANSLUCENT);

Изменение этого параметра отключает наложение от кликов, но # 2 и # 3 работают:

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,

Наконец, в этом примере накладывается оверлей и то, что прямо за ним:

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,

Как я могу изменить это так, чтобы наложение было кликабельным, что непосредственно под ним не доступно для кликов, и все, что находится за пределами наложения, включая домашние кнопки?

Пример приложения, выполняющего все это, - это Super Manager.

UPDATE: я обнаружил, что следующее позволяет использовать кнопку дома, но все же не остальные кнопки:

        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | 
            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
            WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH

4b9b3361

Ответ 1

  • Вы не можете использовать типы окон OR. Вы создадите некоторый случайный другой тип. И, честно говоря, типы окон, которые вы используете, действительно не предназначены для использования приложениями (поэтому у них есть слово "система" ).

  • Что вы подразумеваете под словом "мягкие клавиши больше не работают"? Нельзя прекращать работу дома, если это большая проблема (я хотел бы знать код для этого). Другие клавиши доставляются в текущий ключевой фокус; если вы не хотите сфокусироваться, используйте FLAG_NOT_FOCUSABLE.

  • Документация для каждого из этих флагов должна быть довольно четкой, что она делает, поэтому выберите флаги, которые делают то, что вы хотите. FLAG_NOT_FOCUSABLE, потому что вы не хотите принимать ключевые события. FLAG_NOT_TOUCH_MODAL, потому что вы не хотите блокировать события касания, которые находятся за пределами вашего окна. Вы не говорите, что хотите узнать о прессах за окном, поэтому нет причин использовать FLAG_WATCH_OUTSIDE_TOUCH.

Ответ 2

Я вижу, что pcm2a не опубликовал рабочего решения, поэтому я мог бы сделать это для него.

Примечание. Хотя я представляю рабочее решение, использование таких методов не на 100% прав в отношении дизайна архитектуры Android. Я рекомендую просить кого-то из команды разработчиков Android для получения дополнительной информации (и, пожалуйста, напишите свой ответ здесь, чтобы все мы могли видеть).

Разрешения

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

Сервис

package com.vidmind.test.service.video;
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.VideoView;

public class TestVideoService extends Service {

    /** Command to the service to display a message */
    public static final int MSG_PLAY_VIDEO = 1;
    public static final int MSG_VIDEO_LOOP_MODE = 2;


    /** Bundle Strings */
    public static final String KEY_VIDEO_URL = "KEY_VIDEO_URL";
    public static final String KEY_VIDEO_LOOP_MODE = "KEY_VIDEO_LOOP_MODE";


    // Binder given to clients
    private static final String TAG = "TestVideoService";
    final Messenger mMessenger = new Messenger(new IncomingHandler());
    private LinearLayout mOverlay;
    private VideoView mVideoView;
    private boolean mVideoLoop = true;


    /** ****************** Handler implementation class ****************** **/

    /**
     * Handler of incoming messages from clients.
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            Bundle bundle;
            switch (msg.what) {
                case MSG_PLAY_VIDEO:
                    bundle = msg.getData();
                    String url = bundle.getString(KEY_VIDEO_URL);
                    play(url);
                    break;

                case MSG_VIDEO_LOOP_MODE:
                    bundle = msg.getData();
                    boolean looping = bundle.getBoolean(KEY_VIDEO_LOOP_MODE);
                    setVideoLoop(looping);
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    /** ****************************************************************** **/

    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }


    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "Service has started");

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Serice destroyed");

        // Remove view from WindowManager
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.removeView(mOverlay);

        mOverlay = null;
        mVideoView = null;
    }


    /** ****************** Private Functions ****************** **/

    /**
     * Set video loop mode
     * @param value
     */
    private void setVideoLoop(boolean value) {
        mVideoLoop = value;
    }

    /**
     * Start playing the movie
     * @param url
     * @returns success/failure
     */
    private boolean play(String url) {
        boolean isSuccess = false;

        if (mOverlay != null && mVideoView.isPlaying()) {
            Log.w(TAG, "Cannot recreate video overlay");
            return isSuccess;
        }

        // Create overlay video
        createOverlay(mOverlay != null);
        if (!mVideoView.isPlaying()) {
            mVideoView.setOnPreparedListener(new OnPreparedListener() {

                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.setLooping(mVideoLoop);
                } 
            });

            mVideoView.setVideoURI(Uri.parse(url));
            mVideoView.requestFocus();
            mVideoView.start();
            isSuccess = true;
        }
        return isSuccess;
    }

    /**
     * Create video overlay
     * 
     * @param isCreated
     */
    private void createOverlay(boolean isCreated) {
        if (isCreated) return;

        // Create System overlay video
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.FILL_PARENT, 150,
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.BOTTOM;

        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        mOverlay = (LinearLayout) inflater.inflate(R.layout.main, null);
        mVideoView = (VideoView) mOverlay.findViewById(R.id.video_player);

        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mOverlay, params);

    }
}

layout.main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <VideoView
        android:id="@+id/video_player"
        android:layout_width="120dp"
        android:layout_height="120dp"/>

</LinearLayout>

Счастливое кодирование!
<я > Amir