我的代码连续切换飞行模式

发布于 2024-10-04 05:25:29 字数 2690 浏览 0 评论 0原文

我有一个屏幕(活动)执行以下操作:它有一个切换飞行模式的切换按钮;它通过使用产生新线程的服务来实现这一点。它还有一个按钮,可以以完全相同的方式执行完全相同的操作。正如下面的代码片段所示,确实没有什么特别的。虽然切换按钮的一切都按预期工作(如果当前手机未处于飞行模式,则飞行模式更改为“打开”;如果当前处于飞行模式,则更改为“关闭”),但单击该按钮时,飞行模式会连续切换(飞行模式从“开”到“关”,再回到“开”,然后再到“关”...)就好像它陷入了循环。在互联网上进行了一些研究后,我怀疑这与 Android 中触发电话/服务状态的 Intent/broadcastReceiver 的方式有关;因为切换按钮有两种状态,这有效地防止了意图再次广播。这是正确的吗?如果是这样,使用按钮(相对于单选按钮或切换按钮)切换飞行模式的正确方法是什么?

/** Handler for the button. */
runToggleAirplaneModeServiceBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
    startService(new Intent(SleepScheduleController.this, AirplaneModeService.class));
}
});
/** Handler for the toggle button. */
airplaneModeToggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    startService(new Intent(SleepScheduleController.this, AirplaneModeService.class));
}
});
/** In the same screen as the toggle button and the button.
 * Need this to update the state of the toggle button once 
 * the toggling command is executed.
 */
intentFilter = new IntentFilter("android.intent.action.SERVICE_STATE");
receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        displayAirplaneMode();
    }};
registerReceiver(receiver, intentFilter);

private void displayAirplaneMode() {
    if(airplaneModeToggler.isInAirplaneMode()){
        airplaneModeToggleButton.setChecked(true);
        airplaneModeTextView.setText(R.string.airplane_mode_on);
    }else{
     airplaneModeToggleButton.setChecked(false);
     airplaneModeTextView.setText(R.string.airplane_mode_off);
    }
}

/** Code snippet in AirplaneModeService*/
@Override
public void onCreate() {
    airplaneModeToggler = new AirplaneModeToggler(this);
    Thread mThread = new Thread(null, airplaneModeToggleTask, "AirplaneModeToggleTask");
    mThread.start();
}

private Runnable airplaneModeToggleTask = new Runnable() {
    @Override
    public void run() {
        airplaneModeToggler.toggle(null);
        AirplaneModeService.this.stopSelf();
    }
};

/** Code snippet in the Utility class used by AirplaneModeService.*/
public Boolean toggleAirplaneMode(Boolean enabling) {
    boolean _enabling = enabling == null ? !isInAirplaneMode() : enabling.booleanValue();
Settings.System.putInt(mContext.getContentResolver(),
            Settings.System.AIRPLANE_MODE_ON, 
            _enabling ? AIRPLANE_MODE_ON : AIRPLANE_MODE_OFF);
    Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
    intent.putExtra("state", _enabling);
    mContext.sendBroadcast(intent);
    return _enabling;
}

I have a screen (Activity) that does the following: it has a toggle button that toggles the airplane mode; it does it by using a service that spawn off a new Thread. It also has a button that does exactly the same thing in exactly the same way. There is really nothing fancy as the code snippets below show. While everything works as expected for the toggle button (airplane mode changes to "on" if currently the phone is not in airplane mode; changes to "off" if currently in airplane mode), when the button is clicked, the airplane mode toggles continuously (airplane mode toggles from "on" to "off" and back to "on" and then to "off"...) as if it falls into a loop. After some research on the internet, I suspected this had something to do with the way the intent/broadcastReceiver for the phone/service state was fired in Android; as the toggle button had two states which effectively prevented the intent from being broadcast again. Is this correct?? If so, what would be the right way of toggling airplane mode using a button (vs. a radiobutton or a togglebutton)?

/** Handler for the button. */
runToggleAirplaneModeServiceBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
    startService(new Intent(SleepScheduleController.this, AirplaneModeService.class));
}
});
/** Handler for the toggle button. */
airplaneModeToggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    startService(new Intent(SleepScheduleController.this, AirplaneModeService.class));
}
});
/** In the same screen as the toggle button and the button.
 * Need this to update the state of the toggle button once 
 * the toggling command is executed.
 */
intentFilter = new IntentFilter("android.intent.action.SERVICE_STATE");
receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        displayAirplaneMode();
    }};
registerReceiver(receiver, intentFilter);

private void displayAirplaneMode() {
    if(airplaneModeToggler.isInAirplaneMode()){
        airplaneModeToggleButton.setChecked(true);
        airplaneModeTextView.setText(R.string.airplane_mode_on);
    }else{
     airplaneModeToggleButton.setChecked(false);
     airplaneModeTextView.setText(R.string.airplane_mode_off);
    }
}

/** Code snippet in AirplaneModeService*/
@Override
public void onCreate() {
    airplaneModeToggler = new AirplaneModeToggler(this);
    Thread mThread = new Thread(null, airplaneModeToggleTask, "AirplaneModeToggleTask");
    mThread.start();
}

private Runnable airplaneModeToggleTask = new Runnable() {
    @Override
    public void run() {
        airplaneModeToggler.toggle(null);
        AirplaneModeService.this.stopSelf();
    }
};

/** Code snippet in the Utility class used by AirplaneModeService.*/
public Boolean toggleAirplaneMode(Boolean enabling) {
    boolean _enabling = enabling == null ? !isInAirplaneMode() : enabling.booleanValue();
Settings.System.putInt(mContext.getContentResolver(),
            Settings.System.AIRPLANE_MODE_ON, 
            _enabling ? AIRPLANE_MODE_ON : AIRPLANE_MODE_OFF);
    Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
    intent.putExtra("state", _enabling);
    mContext.sendBroadcast(intent);
    return _enabling;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

毁梦 2024-10-11 05:25:29

所以我找到了这个错误。这是由切换按钮的 OnCheckedChangeListener 重新执行我的代码中的命令引起的。假设之前以编程方式调用切换命令,或者通过单击另一个按钮,那么这些将导致切换按钮上的选中状态更改,随后将执行相同的切换命令,这将导致另一轮选中状态更改切换按钮。

So I tracked down the bug. It's caused by the OnCheckedChangeListener of the toggleButton re-excuting the command in my code. Say if the toggling command was previously called programmatically, or by clicking on the other button, then these would cause the checked state change on the toggleButton, which would subsequently execute the same toggling command, which would result in another round of checked state change on the toggleButton.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文