2015-08-31 87 views
1

我基本搭售打開一項服務,每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

回答

1

的原因墜毀,由布拉德解釋說,是因爲您試圖從非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,但沒有奏效,因爲它輸出配發錯誤的,你在哪裏加呢?以及你如何調用這個循環? –

1

的原因,該服務崩潰是因爲你想在主線程之外運行的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