在循环中服务崩溃 - Android Studio

在循环中服务崩溃 - Android Studio

问题描述:

我基本搭售打开一项服务,每10秒钟,将显示吐司说“10秒过去” 这就是我想要做的, 经过许多研究发现,要循环服务我 需要使用while(true) - sleep ... method ... 但服务或我的应用程序崩溃每次我开始服务 在循环中服务崩溃 - Android Studio

什么是我的问题(或每次定时器溢出时间是精确的)?

我的猜测是,也许我传递给敬酒contaxt是错误的? 也许还有另一种方式来显示在循环(在一个serivice中)每10秒钟吐司?

这里是我的服务代码>

package com.greenroad.candidate.mywallpaperchanger; 

import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
import android.widget.Toast; 

/** 
* Created by pitsponet on 31/08/2015. 
*/ 
public class myService extends Service { 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

@Override 
public void onCreate() { 
    super.onCreate(); 

    Toast.makeText(getApplicationContext(), "service created", 
      Toast.LENGTH_LONG).show(); 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 

    //try to run loop for showing up a toast 
    new Thread(new Runnable(){ 
     public void run() { 
      // TODO Auto-generated method stub 
      while(true) 
      { 
       try { 
        Thread.sleep(10000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       //REST OF CODE HERE// 
       Toast.makeText(getApplicationContext(), "service started", 
         Toast.LENGTH_LONG).show(); 
      } 

     } 
    }).start(); 


    return super.onStartCommand(intent, flags, startId); 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 

    Toast.makeText(getApplicationContext(), "service stoped", 
      Toast.LENGTH_LONG).show(); 
} 
} 
+0

如果它崩溃了,你应该能够得到一个堆栈跟踪。尝试发布,因为它将提供更多的细节,以了解发生了什么。 – Acapulco

+0

哎阿卡普尔科,unfortuntly我不能堆栈跟踪它becouse我建立这个作为一个APK文件,并将其上传到我的设备,目前的Android Studio不会看到我的设备,而且在它的模拟器不工作,所以我无法以其他方式检查它。 –

+0

我更新了我的答案。我希望你现在很清楚。 – DavidH

的原因坠毁,由布拉德解释说,是因为您试图从非UI执行UI操作Thread

为了达到你想要做的,在服务中使用下面的代码是什么。首先,删除你ThreadonStartCommand()

public class MyService extends Service { 
    private Handler mHandler; 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 


    @Override 
    public void onCreate() { 
     super.onCreate(); 
     mHandler = new Handler(); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     mHandler.postDelayed(ToastTask, 10000); // Starts the loop here 
     super.onStartCommand(intent, flags, startId); 
    } 
    @Override 
    public void onDestroy() { 
     // Stop the loop 
     mHandler.removeCallbacks(ToastTask); 
     super.onDestroy(); 
    } 
    private Runnable ToastTask = new Runnable() { 
     @Override 
     public void run() { 
      Toast.makeText(MyService.this, "10 Seconds have passed", Toast.LENGTH_SHORT).show(); 
      // Schedule this Runnable to run again after 10 sec 
      mHandler.postDelayed(this, 10000); 
     } 
    } 
} 
+0

我不相信,因为他正在创造一个新的线程无限的,这是正确的,同时循环在onStartCommand()方法。 – Bradford2000

+0

@ Bradford2000对不起。我现在看到了。我的解决方案虽然会工作。我认为它和你的一样,尽管我的看起来更加完整。 – DavidH

+0

试图将它添加到我的onStartCommand,但没有奏效,因为它输出配发错误的,你在哪里加呢?以及你如何调用这个循环? –

的原因,该服务崩溃是因为你想在主线程之外运行的UI任务(干杯)。既然你正在创建while循环无限辅助线程,你需要发表您的吐司调用主尺蠖如下:

final Handler mainHandler = new Handler(getApplicationContext().getMainLooper()); 
mainHandler.post(new Runnable() { 
    @Override 
    public void run() { 
     Toast.makeText(getApplicationContext(), "Text to display", Toast.LENGTH_LONG).show(); 
    } 
}); 

话虽这么说,我非常使用Thread.sleep()方法阻止任何将在设备上运行的代码,因为这可能会导致一些严重的问题。您应该能够使用Timer来完成相同的操作(并且还可以摆脱无限循环)。

要使用Timer,你应该能够做到像下面这样:

// Schedules a TimerTask to execute every 10 seconds after a 10 second delay. 
final Timer timer = new Timer(); 
timer.schedule(new TimerTask() { 
    @Override 
    public void run() { 
     // Your Toast code here. 
    } 
}, 10000, 10000); 

这里有一个完整的例子:

public class MyService extends Service { 
    private Handler mainHandler; 
    private Timer timer; 

    public void onStartCommand(final Intent intent, final int flags, final int startId) { 
     mainHandler = new Handler(getApplicationContext().getMainLooper()); 
     timer = new Timer(); 
     timer.schedule(new MyTimerTask(), 10000, 10000); 
    } 

    public void onDestroy() { 
     timer.cancel(); 
    } 

    private class MyTimerTask extends TimerTask { 
     @Override 
     public void run() { 
      mainHandler.post(new Runnable() { 
       @Override 
       public void run() { 
        Toast.makeText(getApplicationContext(), "Text to display", Toast.LENGTH_LONG).show(); 
       } 
      }); 
     } 
    } 
} 
+0

太棒了,这确实显示了敬酒,但我如何循环呢?你有我需要投入的计时器的代码示例吗?试图寻找它徒劳的 –

+0

编辑包括计时器的例子。此外,@DavidH在上面发布的答案在功能上是等价的,只是使用Handler而不是Timer来进行循环。 – Bradford2000