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

Cre*_*bit 1 java android process terminate android-things

我有一个运行 Android Things 的 Raspberry Pi 3。为简单起见,假设它仅旋转步进电机。

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

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

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

我尝试过 onDestroy() 和 onPause() 但都不能保证在程序关闭时调用它们。(他们也从未在我的情况下工作过)。

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

@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...
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Dev*_*red 5

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

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

下面是一个示例:

驱动程序.apk

class MotorDriverService : Service() { 

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

    override fun onDestroy() {
        super.onDestroy()
        stopMotor()
    }
}
Run Code Online (Sandbox Code Playgroud)

主程序.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) { }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样做效果更好的原因是因为绑定的服务连接是自动管理的。Android 在 Activity 想要绑定服务时创建服务,并在不再有客户端绑定时销毁服务(在这种情况下,main.apk 终止或崩溃时也会发生这种情况)。

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