2011-10-23 61 views
7

我想知道我是否可以在取消它之後再次安排定時器。這裏陳述了http://www.coderanch.com/t/452066/java/java/Exception-timer-IllegalStateException,一旦你取消了定時器,就不可能在同一個定時器上安排任何東西,除非我創建一個新的定時器。而且,我遇到了以下錯誤,java.lang.IllegalStateException:Timer被取消。 我想出來定時器,會定期執行Wifi掃描。但是我希望「暫停」,或者如果沒有,在掃描後執行一些計算時取消定時器。只有在完成計算並返回一些結果後,我才能恢復定時器。任何人都可以告訴我如何解決這個問題?已調整。定時器取消後給「java.lang.IllegalStateException:定時器取消。」

忘記提到,我會啓動計時器,只有在我完成加載圖像,我使用AsyncTask來做到這一點。

我試圖實現這一個單獨的線程,以便它不會阻止UI線程。

這裏是節目的粗糙骨架和啓動定時器,其中當只有後的圖像已經完全加載時elasped它會執行的WiFi掃描(後「load.execute(上下文);」):

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 [email protected] 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 [email protected] 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) 

回答

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(); 
} 
0

您是否嘗試過使用Runnable處理程序並將其設置爲定期間隔?類似這樣的:

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

您可以根據需要指定延遲,並且您可以在run()中執行任何您需要的操作。

+0

看來,當我把做一個WiFi掃描編碼,似乎什麼都沒有做。 – user918197

+0

你可以發佈一些你的代碼,以便我們可以看到你迄今爲止做了什麼嗎? –

+0

添加了以前基於此示例的編碼,http://stackoverflow.com/questions/3045227/android-stop-image-scaling-down。 – user918197

13

是的,取消定時器終止其線程,所以你不能再次使用它。計時器沒有任何內置的暫停方法。當你想「暫停」時,你可以取消定時器,當你想「恢復」時,你可以製作一個新的定時器。

+12

因此,一旦調用.cancel(),您必須創建一個Timer的新實例? – JesusS

+0

@JesusS http://stackoverflow.com/a/21492729/2647910它是 – aswzen

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.."); 
} 

}