Resched。取消后的计时器给出“java.lang.IllegalStateException:Timer cancelled”。

时间:2011-10-23 13:15:24

标签: android timer

我想知道我取消后是否可以再次安排计时器。这里陈述http://www.coderanch.com/t/452066/java/java/Exception-timer-IllegalStateException,一旦你取消了计时器,就不可能在同一个计时器上安排任何东西,除非我创建一个新的计时器。而且,我遇到以下错误, java.lang.IllegalStateException:计时器被取消。 我试图推出一个定期执行Wifi扫描的定时器。但我希望“暂停”或者如果没有,则在扫描后执行某些计算时取消定时器。只有在完成计算并返回一些结果后,我才会恢复计时器。谁能告诉我如何解决这个问题呢?

忘了提到只有在我完成加载我使用AsyncTask这样做的图像后我才会启动计时器。

我试图让这个人成为一个单独的线程,以免它阻碍UI线程。

这是程序和启动计时器的粗略骨架,只有在图像完全加载后才会执行wifi扫描(在 load.execute(context); “):

public class LargeImageScroller extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {...}

@Override
public boolean onOptionsItemSelected(MenuItem item) {...}

//this is the class where the program would do all the UI and display images
private static class SampleView extends View {

    public SampleView(Context context) {
                    :
        loadMap load = new loadMap();
        load.execute(context);

        scanTask = new TimerTask(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
               handler.post(new Runnable() {
                        public void run() {
                         wifi = (WifiManager)context.getSystemService(WIFI_SERVICE);
                         context.registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
                         wifi.startScan();
                         Log.d("TIMER", "Timer set off");
                        }
               });
            }

        };

        scanTimer.schedule(scanTask, refreshRate);
    }

    public class wifiReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO Auto-generated method stub
            List<ScanResult> sc = wifi.getScanResults(); 
            for(int i=0; i<sc.size(); i++){
                Log.e("AndroidRuntime", sc.get(i).SSID);
            }
        }

    }
    public boolean onTouchEvent(MotionEvent event) {...}
    protected void onDraw(Canvas canvas) {...}
    private static Drawable LoadImageFromWebOperations(String url){...}
    private static Bitmap decodeFile(File f, int requiredSize){...}
    private class loadMap extends AsyncTask<Context, Void, ArrayList<Bitmap>>{...}
}

使用包含的权限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.DELETE_CACHE_FILES"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

广播接收器遇到错误:

10-25 05:53:04.903: ERROR/ActivityThread(1551): Activity android.wps.LargeImageScroller has leaked IntentReceiver android.wps.LargeImageScroller$SampleView$wifiReceiver@43d1bca0 that was originally registered here. Are you missing a call to unregisterReceiver()?
10-25 05:53:04.903: ERROR/ActivityThread(1551): android.app.IntentReceiverLeaked: Activity android.wps.LargeImageScroller has leaked IntentReceiver android.wps.LargeImageScroller$SampleView$wifiReceiver@43d1bca0 that was originally registered here. Are you missing a call to unregisterReceiver()?
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.app.ActivityThread$PackageInfo$ReceiverDispatcher.<init>(ActivityThread.java:797)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.app.ActivityThread$PackageInfo.getReceiverDispatcher(ActivityThread.java:608)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.app.ApplicationContext.registerReceiverInternal(ApplicationContext.java:724)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.app.ApplicationContext.registerReceiver(ApplicationContext.java:711)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.app.ApplicationContext.registerReceiver(ApplicationContext.java:705)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:308)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.wps.LargeImageScroller$SampleView$1$1.run(LargeImageScroller.java:187)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.os.Handler.handleCallback(Handler.java:587)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.os.Handler.dispatchMessage(Handler.java:92)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.os.Looper.loop(Looper.java:123)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at android.app.ActivityThread.main(ActivityThread.java:4363)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at java.lang.reflect.Method.invokeNative(Native Method)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at java.lang.reflect.Method.invoke(Method.java:521)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
10-25 05:53:04.903: ERROR/ActivityThread(1551):     at dalvik.system.NativeStart.main(Native Method)

4 个答案:

答案 0 :(得分:13)

是的,取消计时器会终止其线程,因此您无法再次使用它。计时器没有任何内置的暂停方法。当您想要“暂停”时可以取消定时器,并在想要“恢复”时再创建一个新定时器。

答案 1 :(得分:3)

最后我解决了这个问题:D 我没有时间解释它,但我想与你分享。

import java.util.Timer;  import java.util.TimerTask;  import sociatag.view.main_frame;  public class devices_pinger implements Runnable {




// PROPERTIES:

private int delay = 1000;   // delay for 1 seconds.
private int period = 6000;  // repeat every 6 seconds.
private boolean stop_timer = false;
// CONSTRACTOR:

public devices_pinger() {
}
// METHODES:

/*
 * because we implements Runnable in this class,
 * this methode run() has to run this class on a seperate thread.
 * - call the start pinger methode
 *
 * @param: event occured on the serial
 */
@Override
public void run() {
    run_pinger();

}

/*
 * this is the start point of this class
 * - create a scheduler to run every x seconds
 * - call the run methode every x seconds to:
 * - send 'P' through the serial
 * - wait x seconds
 * - call the ping analyser to get all the replyed pings and analyse them
 */
private void run_pinger() {

    new Timer().schedule(new TimerTask() {

        @Override
        public void run() {

            // 1) ping the connected device
            serial_connection.serial_write('P');
            System.out.println("> PING (Send P)");//<------TESTING--------------------------------------------
            // pause for 3 seonds to give time for all the devices to response 
            try {
                Thread.sleep(3000); // call the analyser after 3 seconds
            } catch (InterruptedException ex) {
                System.out.println("Error: while pausing the thread");
            } // 2) get the result of the ping to analyze it
            serial_listener.ping_analyser();

            if (stop_timer == true) {
                this.cancel();
            }
        }
    }, delay, period);
}

/*
 * stop the timer before pairing the devices or do other activities
 */
public void stop_pinger() {

    stop_timer = true;
    main_frame.display_notification("Device Pinger is paused.");
}

/*
 * restart the pinger by creating new instance of timer
 */
public void start_pinger() {
    stop_timer = false;
    run_pinger();
    main_frame.display_notification("Device Pinger is running..");
}

}

答案 2 :(得分:0)

您是否尝试过使用Runnable处理程序并将其设置为常规间隔?像这样:

private Handler mUpdateHandler = new Handler();
private Runnable mUpdateRunnable = new Runnable() {
    public void run() {
        mUpdateHandler.postDelayed(this, delay);
    }
};
mUpdateHandler.postDelayed(mUpdateRunnable, delay);

您可以根据需要指定延迟,并且可以在run()中执行任何操作。

答案 3 :(得分:0)

@Alan Moore:嗨,我想我终于做到了!这是能够执行wifi扫描并使用广播意图将响应发送回调用活动的代码。

LargeImageScoll.java(活动)

Intent intent;

public static Runnable scanTask;

public BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        //updateUI(intent); 
        //String returnedValue = intent.getStringExtra("data");
        Bundle bundle = intent.getExtras();
        String returnedValue = bundle.getString("data");
        Log.e("Waht", returnedValue);
    }
};

private static Handler handler = new Handler(){

    @Override
    public void handleMessage(Message msg) {
        // TODO Auto-generated method stub
        super.handleMessage(msg);
    }

};

public class LargeImageScroller extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));

        intent = new Intent(this, WifiScanning.class);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {...}

@Override
public boolean onOptionsItemSelected(MenuItem item) {...}

//this is the class where the program would do all the UI and display images
private static class SampleView extends View {

    public SampleView(Context context) {
                :
    loadMap load = new loadMap();
    load.execute(context);

    scanTask = new Runnable(){
    @Override
    public void run() {
    // TODO Auto-generated method stub
    startService(new Intent(context, WifiScanning.class));  
    };

    handler.removeCallbacks(scanTask);
    handler.postDelayed(scanTask, refreshRate);
}

public boolean onTouchEvent(MotionEvent event) {...}
protected void onDraw(Canvas canvas) {...}
private static Drawable LoadImageFromWebOperations(String url){...}
private static Bitmap decodeFile(File f, int requiredSize){...}
private class loadMap extends AsyncTask<Context, Void, ArrayList<Bitmap>>{...}

}//end of SampleView

protected void onResume() {
    // TODO Auto-generated method stub
    Log.e("AndroidRuntime", "onResume");
    handler.removeCallbacks(scanTask);
    handler.postDelayed(scanTask, refreshRate);
    registerReceiver(broadcastReceiver, new IntentFilter(WifiScanning.BROADCAST_ACTION));
    super.onResume();
}

@Override
protected void onStop() {
    // TODO Auto-generated method stub
    Log.e("AndroidRuntime", "onStop");
    unregisterReceiver(broadcastReceiver);
    stopService(new Intent(this, WifiScanning.class));
    handler.removeCallbacks(scanTask);
    super.onStop();
}
}//end of LargeImageScroll

WifiScanning.java(服务)

public static final String BROADCAST_ACTION = "android.wps.wifiscanning.broadcasttest";
int counter = 0;
Intent intent1;
WifiReceiver receiverWifi = new WifiReceiver();
WifiManager wifi;
StringBuilder sb;
List<ScanResult> wifiList;

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

    intent1 = new Intent(BROADCAST_ACTION); 
    Log.e(TAG, "Service creating");
    wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
    if(counter==0){
    Log.e("AndroidRuntime", "Scan for the "+counter+" time");
    wifi.startScan();
    counter++;
    }
}

class WifiReceiver extends BroadcastReceiver {
    public void onReceive(Context c, Intent intent) {
        sb = new StringBuilder();
        wifiList = wifi.getScanResults();
        for(int i = 0; i < wifiList.size(); i++){
            sb.append("["+ (wifiList.get(i).SSID).toString() + "][");
            sb.append((wifiList.get(i).BSSID).toString() + "][");
            sb.append((String.valueOf(wifiList.get(i).level)) + "]");
            sb.append("\n");
        }
        Log.e("AndroidRuntime", sb.toString());
        if(counter<4){
            Log.e("AndroidRuntime", "Scan for the "+counter+" time");
            wifi.startScan();
            counter++;
        }else{
            intent1 = new Intent(BROADCAST_ACTION);
            String test = sb.toString();
            intent1.putExtra("data", test);
            sendBroadcast(intent1);
        }
    }
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    unregisterReceiver(receiverWifi);
    super.onDestroy();
}