根据莫尔斯代码 - Android的闪烁闪光。 如何避免ANR次数由于睡觉? (火炬APP)

2019-10-18 11:23发布

所以,我做了一个火把应用...正常火炬功能完全正常,没有任何问题。

下面介绍以下功能,可能会导致可能的ANR的说,我想通过闪烁的闪光灯发出SOS信息(莫尔斯电码)。 (其111-000-111),所以它开 - 开 - 开 - 关 - 关 - 和重复。

(慢慢读)我“开”是一小会儿,然后微微一晃,“开”再次 - 这是区分两个连续“开” S ......这就是我得到三个不同的闪烁。

麻烦的是,对于延时,我把线程睡眠。(这种方法的工作最适合我)

下面是我的示例功能,它闪烁出SOS:(我有一个SOS按钮,单独)

public void sos(View v) {

        String myString = "111000111";

        for (int x = 0; x < myString.length(); x++) {
            if (myString.charAt(x) == '1') {

                p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                c.setParameters(p);
                c.startPreview();
                flag = true;

            } else {

                p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                c.setParameters(p);
                flag = false;
            }

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            c.setParameters(p);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        c.setParameters(p);
    }

}

上述闪烁出SOS一次。 不过,虽然这闪烁,闪烁是怎么回事,我的应用程序被冻结了。 闪烁SOS是完美的。 但它并没有任何按钮点击,甚至后退按钮响应中途停止。

我认为这是因为线程(UI)正在睡觉,因此它并不关心用户正在做)......但肯定点击注册,如果按照到Android如果没有后在规定的看着的时间(我想了几秒钟)期...该应用程序进入ANR。

所以,我需要与我定义的间隔短暂的停顿(正如上面我用300毫秒)。 但我也想知道如何让应用同时响应说按钮点击或后退按钮按下,以避免ANR的,并给予用户关闭在任何时候闪烁的能力。

这个怎么做 ?

编辑 Waza_Be的解决方案:

好吧,这里是根据Waza_Be我修改的功能。 这个问题似乎是,它等待300毫秒(在我的情况)......但我有几个postDelay功能 - 因此,我认为它实际上是排队的所有功能于一体,与300毫秒的等待期是有些重叠。 这一时期结束后,所有的代码运行起来一次,使得它毫无意义。

当我尝试这样做,闪光灯闪烁而迅速,不与微妙的停顿和闪烁效果我想要的。

public void sos(View v) {
        String myString = "111000111";
        Handler handler = new Handler();

        for (int x = 0; x < myString.length(); x++) {
            if (myString.charAt(x) == '1') {
                     handler.postDelayed(new Runnable() {
                    public void run() {
                        p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                        c.setParameters(p);
                        c.startPreview();
                    }
                }, 300);

            } else {

                handler.postDelayed(new Runnable() {
                    public void run() {
                        p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                        c.setParameters(p);
                    }
                }, 300);

            }


            handler.postDelayed(new Runnable() {
                public void run() {
                    p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                    c.setParameters(p);
                }
            }, 300);
        }

        p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        c.setParameters(p);
}
}

我需要单独暂停。 后或每TURN_ON或TURN_OFF为Flash之前说。 在每一个循环中,应该单独地等待在处理程序中运行每一段代码()。

Answer 1:

我个人使用处理器postDelayed时,我想“休眠”

// "SLEEP" 2 SECONDS HERE ...
Handler handler = new Handler(); 
handler.postDelayed(new Runnable() { 
     public void run() { 
          p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); // Or watherver you want
          c.setParameters(p);
     } 
}, 2000); 

你也可以使用一个线程睡眠的方法,以避免阻塞UI线程。

编辑:这是你可以写一个递归处理:这将允许你在其他后发上的所有部分莫尔斯

Handler handler = new Handler();
int i = 0;
Runnable myRunnable = new Runnable() {
        @Override
        public void run() {

            Log.d("handler is running", "true" + System.currentTimeMillis());
            if(i>5)
               handler.removeCallback(myRunnable);
            else{
                i++;
                handler.postDelayed(myRunnable, 100); // here is self calling
            }

        }
    };
}
handler.postDelayed(myRunnable, 100);


Answer 2:

我解决了这个使用线程有点不同。 莫尔斯电码通过点击按钮生成。

    OnClickListener goMorse = new OnClickListener() {

    @Override
    public void onClick(View v) {

        new Thread () {
            public void run() {
                if(myMorseString != null){
                for (int x = 0; x < myMorseString.length(); x++) {
                    if (myMorseString.charAt(x) == '2') {
                        cam = Camera.open();
                        sleepTime = 500;
                        Parameters p = cam.getParameters();
                        p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                        cam.setParameters(p);
                        cam.startPreview();
                        try {
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // power off after signal
                        cam.stopPreview();
                        cam.release();
                        cam = null;
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    if (myMorseString.charAt(x) == '1') {
                        cam = Camera.open();
                        sleepTime = 250;
                        Parameters p = cam.getParameters();
                        p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                        cam.setParameters(p);
                        cam.startPreview();
                        try {
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        // power off after signal
                        cam.stopPreview();
                        cam.release();
                        cam = null;
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    if (myMorseString.charAt(x) == '0') {
                        cam = Camera.open();
                        sleepTime = 250;
                        Parameters p = cam.getParameters();
                        cam.setParameters(p);
                        //cam.startPreview();
                        cam.stopPreview();
                        cam.release();
                        cam = null;

                        try {
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }           
            }}}
        }.start();
    }

};


文章来源: Blinking Flash according to Morse Code- Android. How to avoid ANRs due to sleeping ? (Torch App)