安卓应用程序崩溃后如何停止后台服务

4

首先,我想为我的糟糕英语道歉。

这是我的问题:

我有一个在Android上运行的服务,当活动正在运行时,它在后台运行(此服务使用指定的时间间隔将用户数据与服务器同步)。

public class CService extends Service
{
   private Boolean isDestroyed;



@Override
    public int onStartCommand (Intent intent, int flags, int startId)
    {
            if (intent != null)
            {
                   new Thread(new Runnable()
                   {
                   //run new thread to disable flush memory for android and destroy this service
                           @Override
                           public void run ()
                           {
                                     this.isDestroyed = Boolean.FALSE
                                     while(!this.isDestroyed)
                                     {
                                     //loop until service isn't destroyed
                                     }
                            }

                    }).start();
            }
            return Service.START_NOT_STICKY;

    }

    @Override
    public void onDestroy ()
    {
           //THIS ISNT CALLED FROM uncaughtException IN ACTIVITY BUT from onDestroy method is this called.

           //when is service destroyed then onDestroy is called and loop finish
           this.isDestroyed = Boolean.TRUE;
    }

}

这个功能从onCreate方法中开始执行,该活动实现了Thread.UncaughtExceptionHandler并在onCreate方法中注册以捕获活动中的所有意外异常。当活动中的某些内容抛出异常时,uncaughtException方法被调用,并且服务应该使用stopService(serviceIntent)停止。但是,在服务中没有调用onDestoy。但是,当用户按下后退按钮并调用活动中的onDestroy方法时,服务成功停止并调用CService中的onDestoroy。

    public class CActivity extends Activity implements Thread.UncaughtExceptionHandler
    {
            private Thread.UncaughtExceptionHandler defaultUEH;

        @Override
        protected void onCreate (Bundle savedInstanceState)
        {

            this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();

            // create intent for service
            Intent serviceIntent = new Intent(this, CService.class);
            // run service
            startService(serviceIntent);

            //set default handler when application crash
            Thread.setDefaultUncaughtExceptionHandler(this);
            super.onCreate(savedInstanceState);
        }

        @Override
        public void uncaughtException (Thread thread, Throwable ex)
        {
            //THIS DOESN'T WORK

            //when global exception in activity is throws then this method is called. 
            Intent serviceIntent = new Intent(this, CService.class);
            //method to service stop is called. BUT THIS METHOD DON'T CALL onDestroy in CService
            stopService(serviceIntent);
            defaultUEH.uncaughtException(thread, ex);       
        }

        @Override
        public void onDestroy ()
        {
            //this work fine
            Intent serviceIntent = new Intent(this, CService.class);
            stopService(serviceIntent);
            super.onDestroy();
            }


    }

我需要在活动崩溃时停止后台服务。因为当Android关闭活动并在堆栈中启动先前的活动(即登录屏幕)时,没有用户登录。
谢谢您的建议。

你的服务是从另一个进程运行的吗? - Korniltsev Anatoly
服务在同一个活动中运行和停止,在onCreate方法中运行,在uncaughtException方法中停止。 - Kamikazee
2个回答

2

试试这个

    Thread.currentThread().setUncaughtExceptionHandler(this);

更新
这是默认的Android异常处理程序。

private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
        public void uncaughtException(Thread t, Throwable e) {
            try {
                // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
                if (mCrashing) return;
                mCrashing = true;

                if (mApplicationObject == null) {
                    Slog.e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
                } else {
                    Slog.e(TAG, "FATAL EXCEPTION: " + t.getName(), e);
                }

                // Bring up crash dialog, wait for it to be dismissed
                ActivityManagerNative.getDefault().handleApplicationCrash(
                        mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
            } catch (Throwable t2) {
                try {
                    Slog.e(TAG, "Error reporting crash", t2);
                } catch (Throwable t3) {
                    // Even Slog.e() fails!  Oh well.
                }
            } finally {
                // Try everything to make sure this process goes away.
                Process.killProcess(Process.myPid());
                System.exit(10);
            }
        }
    }

我认为你没有收到onDestroy()的调用,因为默认的Android异常处理程序会简单地销毁整个进程System.exit()。你可以尝试不调用defaultUEH.uncaughtException(thread, ex);或在(if)你的服务被销毁后再调用它。

这个不起作用。因为setUncaughtExceptionHandler(this);是静态方法,而currentThread()不是静态方法。但还是谢谢回复。 - Kamikazee
1
setDefaultUncaughtExceptionHandler是静态的。 - Korniltsev Anatoly
你说得对,我正在使用静态方法。但是如果我使用非静态方法setUncaughtExceptionHandler,stopService()也不会调用onDestroy。 - Kamikazee

1
兄弟,顺便问一下,为什么你要在onCreate方法中执行操作呢? 正如文档所说,这个方法是从主线程调用的,我真的很想知道它是如何工作的。你应该在另一个线程中进行任何繁重的计算。

http://developer.android.com/reference/android/app/Service.html

当服务组件被创建时,无论出于何种原因,系统实际上所做的只是实例化该组件并在主线程上调用其onCreate()和任何其他适当的回调。由服务来实现这些回调,并采取适当的行为,例如在其中创建一个辅助线程以执行其工作。

抱歉我在这里发布问题时犯了错误,因为我是从onStartCommand而不是onCreate中运行服务的。我已经更正了第一篇帖子并纠正了问题。我没有将代码复制粘贴到问题中,当我编写代码时出现了错误。我使用另一个线程来防止Android销毁服务。 - Kamikazee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接