Android在屏幕上使用灰色叠加作为调光,淡化

时间:2017-01-12 21:29:09

标签: java android overlay window-managers

我给自己买了一个安卓车载单元,得出的结论是夜间开车时最低亮度仍然很明亮。有一个聪明的应用程序称为屏幕过滤器(我认为它的工作原理)在屏幕上使用覆盖来伪造屏幕变暗。我想自己做这个,因为我希望在日落时启用它并在日出后禁用它。

在网上搜索后,我发现了一个可用的代码。 使用名为Overlayservice的服务创建Main活动。该服务在我启动应用程序时运行,并且叠加层也可正常运行。

我想做的下一件事是代码,所以我可以改变叠加透明度。我希望程序在日落开始时开始淡化,例如半小时后透明度为50%。 我面临的问题是,当覆盖在服务中处于活动状态时,我无法设置新的颜色和透明度。

我厌倦了在服务中创建一个定时器,在5秒后设置颜色但我遇到了错误:

  

只有创建视图层次结构的原始线程才能触及其视图。

我现在的代码如下:

    package erik.autostart;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.LinearLayout;

import java.util.Timer;
import java.util.TimerTask;


public class OverlayService extends Service {

    String color;
    LinearLayout oView;
    WindowManager.LayoutParams localLayoutParams;

    private static Timer timer = new Timer();


    @Override
    public IBinder onBind(Intent i) {

        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        this.color = intent.getExtras().getString("color");
        Log.v("Message","Intent: " + Color.parseColor(this.color));

        oView = new LinearLayout(getBaseContext());
        localLayoutParams = new WindowManager.LayoutParams();

        oView.setBackgroundColor(Color.parseColor(this.color)); //De eerste 2 waardes zijn de density ff is volledig en 00 is weg de laatste 6 waardes zijn hex color waardes, kan dus zwart zijn.
        WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
        WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));


        localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
        localLayoutParams.gravity = Gravity.TOP;
        localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|

                // this is to enable the notification to recieve touch events
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |

                // Draws over status bar
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

        localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        localLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        localLayoutParams.format = PixelFormat.TRANSLUCENT;

        manager.addView(oView, localLayoutParams);

        timer.scheduleAtFixedRate(new Task(), 0, 500);

        return START_STICKY;
    }

    private class Task extends TimerTask
    {
        public void run()
        {
            Log.v("Message", "Tasker");
            runtask();


        }
    }

    void runtask()
    {
        if(oView!=null){
            oView.setBackgroundColor(Color.parseColor("#ff000000"));
            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            wm.updateViewLayout(oView, oView.getLayoutParams());
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.v("Message", "OverlayService started");
    }


    @Override
    public void onDestroy() {
        if(oView!=null){
            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            wm.removeView(oView);
        }
        Log.v("Message", "Destroying OverlayService");
        super.onDestroy();
    }

}

我想在某处运行任务器,以便我可以设置新颜色并更新叠加层。 为了解决这个问题,我想也许停止服务并用新颜色再次启动它会有所帮助,所以我在Mainactivity中取得了一个接受者并停止了服务并开始了一个不同颜色的新服务。问题在于屏幕闪烁。

我希望有人可以帮我解决这个问题。甚至可以做我想做的事情吗?

1 个答案:

答案 0 :(得分:0)

我之前承诺的完整答案。对于未经测试的代码,我很抱歉,我在大约半年内没有对Android开发做任何事情,也没有准备好测试代码。

那说,最好的方法可能就是使用Handler。 Handler初始化为在主(UI)线程上运行,以便它可以修改UI。 Dimmer在UI线程上执行,从而避免了您遇到的问题。

...


public class OverlayService extends Service {

    Handler handler;

    ...


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

        ...

        manager.addView(oView, localLayoutParams);

        handler.postDelayed(new Dimmer("#ff000000"), 500);

        return START_STICKY;
    }

    private class Dimmer implements Runnable {
        private String color;

        public Dimmer (String color) {
            this.color = color;
        }

        public void run() {
            if(oView!=null){
                oView.setBackgroundColor(Color.parseColor(color));
                WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
                wm.updateViewLayout(oView, oView.getLayoutParams());
            }
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.v("Message", "OverlayService started");

        handler = new Handler(Looper.getMainLooper());
    }

    ...

}