Android (Things): 程序结束前如何清理?

Android (Things): How to do clean-up before program ends?

我有一个Raspberry Pi3运行宁Android的东西。为简单起见,假设它只旋转步进电机。

为了再次简化事情,步进电机通过逐个线圈告诉哪些充电哪些不充电来旋转。在 Raspberry Pi 中,您将四个输出引脚连接到步进电机的四个输入引脚。然后你以连续的顺序一个接一个地启动引脚,每个引脚之间有几毫秒 运行。

如果我在 Android Studio 中通过按停止 'MainActivity' 停止程序,程序代码将被终止,但 Raspberry Pi 中的输出引脚仍保持充电状态。就我而言,如果我在 Android Studio 中停止程序,我的步进电机线圈之一会保持充电状态(并过热)。

问题:在程序关闭前 Android 进行清理的最佳方法是什么?

我已经尝试过 onDestroy() 和 onPause() 但它们都不能保证在程序关闭时被调用。 (他们也从未在我的案例中工作过)。

我也试过添加一个关闭挂钩,但即使这样也没有关闭输出引脚。位于 MainActivity 的 onCreate() 方法中的 shutdownhook 如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Runtime.getRuntime().addShutdownHook(new Thread(){
        @Override
        public void run(){
            try{
                mRobotics.stopMotor();
            } catch (Exception e){
                // Ignore error
            }
        }
    });
// onCreate continues...

方法 stopMotor() 如下所示:

public void stopMotor(){
    this.motorHandler.removeCallbacksAndMessages(null);
    try {
        mStepper1.setValue(false);
        mStepper2.setValue(false);
        mStepper3.setValue(false);
        mStepper4.setValue(false);

    } catch (Exception e){
        // Nothing here
    }
}

有很多相关的问题,例如,在程序关闭时停止线程,但我没有从 Whosebug 中找到任何适合我的情况。

您是正确的,单击 Android Studio 中的停止按钮只是终止您的应用程序进程,而不调用任何生命周期方法。如果您的应用程序崩溃或 Android 由于内存压力需要终止您的应用程序,情况也是如此,因此它也可能在 运行 时间发生。您无法添加任何挂钩来预测每次可能发生的情况。

一种选择是将您的电机驱动器逻辑移动到一个单独的应用程序模块中,并通过 bound service 对其进行控制。这样,当主应用程序终止时(在开发期间或由于崩溃),驱动程序应用程序可以适当地管理它。以这种方式将您的驱动程序代码与您的主应用程序分开通常也是一个很好的关注点分离。

这是一个可能看起来像的例子:

driver.apk

class MotorDriverService : Service() { 

    override fun onCreate() {
        super.onCreate()
        startMotor()
    }

    override fun onDestroy() {
        super.onDestroy()
        stopMotor()
    }
}

main.apk

class MainActivity : Activity() { 

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val intent = ...
        bindService(intent, connection, Context.BIND_AUTO_CREATE)
    }

    override fun onDestroy() {
        super.onDestroy()
        unbindService(connection)
    }

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, service: IBinder) { }

        override fun onServiceDisconnected(name: ComponentName) { }
    }
}

之所以效果更好,是因为绑定的服务连接是自动管理的。 Android 在 activity 想要绑定到它时创建服务,并在没有更多客户端绑定时销毁它(在这种情况下也会在 main.apk 终止或崩溃时发生) .

驱动程序和主程序必须是两个独立的应用程序(而不是同一 APK 中的 activity/service),因为这仅在两个 运行 处于完全独立的进程中时才有效。