如何在Android服务中运行自定时方法?

时间:2015-10-01 19:21:46

标签: android multithreading

我正在开发一个运行检查房间噪音水平的服务的应用程序,活动是一个每250毫秒运行一次的处理程序,但我的问题是,它只在屏幕处于活动状态时运行,根据我的研究,处理程序运行在UI线程,因此很有可能它只在UI线程上运行,这就是为什么它只在我看的时候运行的原因,你能帮我一个方法来运行下面的代码:

    handler = new Handler();

    final Runnable r = new Runnable() {

        int count = 0;
        public void run() {

            // Get the volume from 0 to 255 in 'int'
            double volume = 10 * mSensor.getTheAmplitude() / 32768;
            volumeToSend = (int) volume;
            volumeVisual = "";

            for( int i=0; i<volumeToSend; i++){
                volumeVisual += "|";
                updateUI();

                Log.d("HandlerLooper", "Oscillating :" + count+1);
            }
            handler.postDelayed(this, 250); // amount of delay between every cycle of volume level detection + sending the data  out
        }
    };

    // Is this line necessary? --- YES IT IS, or else the loop never runs
    // this tells Java to run "r"
    handler.postDelayed(r, 250);

在我的服务中没有在UI线程上运行,只是在我的服务中运行?

这是我的完整服务代码:

public class VolumeListerner extends Service {

private static String volumeVisual = "";
private static  int volumeToSend;
private Handler handler;
private SoundMeter mSensor;
/** interface for clients that bind */
IBinder mBinder;
/** indicates whether onRebind should be used */
boolean mAllowRebind;
/** The service is starting, due to a call to startService() */

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

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


private void soundLevelCheck()
{
    mSensor = new SoundMeter();
    try {
        mSensor.start();
        Toast.makeText(getBaseContext(), "Sound sensor initiated.", Toast.LENGTH_SHORT).show();
    } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    handler = new Handler();

    final Runnable r = new Runnable() {

        int count = 0;
        public void run() {

            // Get the volume from 0 to 255 in 'int'
            double volume = 10 * mSensor.getTheAmplitude() / 32768;
            volumeToSend = (int) volume;
            volumeVisual = "";

            for( int i=0; i<volumeToSend; i++){
                volumeVisual += "|";
                updateUI();

                Log.d("HandlerLooper", "Oscillating :" + count+1);
            }
            handler.postDelayed(this, 250); // amount of delay between every cycle of volume level detection + sending the data  out
        }
    };

    // Is this line necessary? --- YES IT IS, or else the loop never runs
    // this tells Java to run "r"
    handler.postDelayed(r, 250);
}



private void updateUI()
{


    Intent intent = new Intent( "UI_UPDATER" );
    intent.putExtra("VolumeBars", "Volume Bars: " +  String.valueOf(volumeVisual));
    intent.putExtra("volumeLevel","Volume Levels: " +  String.valueOf(volumeToSend));
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

}

所有帮助都将提前感谢您。

2 个答案:

答案 0 :(得分:2)

Android Service将始终在UI线程中运行,但IntentService除外,它将为您创建工作线程。

因此,当您在服务中创建Handler时,它将附加到UI线程。

我建议您使用包含可以传递给HandlerThread的循环器的Handler。示例如下。

HandlerThread handlerThread = new HandlerThread("NoiceHandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());

答案 1 :(得分:1)

postDelayed()不是Service的绝佳解决方案。如您所知,它与主应用程序线程相关联,通常我们希望服务在主应用程序线程上工作。

使用其他标准Java计时机制like ScheduledExecutorService