2011-06-17 70 views
1

我在android上開發了一個GPS跟蹤應用程序。 我使用AlarmManager每5分鐘喚醒一次設備。 我開發了一個日誌文件,顯示應用程序工作良好,直到我接受public int onStartCommand(Intent intent,int flags,int startId),再次startId = 1 ....在這種情況下,我注意到所有變量被重置,所以我重新初始化所有變量..問題是,一旦發生這種情況,我不斷獲得與startID = 1相同的事件,幾次調用後,應用程序停止,直到我打開ActivityForm並再次與服務綁定!AlarmManager&onStartCommand

日誌是這裏的壞事件:

@Jun 17, 2011 3:29:31 AM onStartCommand:flags:0:startId:3:intent:Intent { cmp=com.usegps2_1/.LocationService } 
@Jun 17, 2011 3:34:10 AM onStartCommand:flags:0:startId:1:intent:Intent { cmp=com.usegps2_1/.LocationService } 
@Jun 17, 2011 3:34:10 AM StartService with mbServiceStarted=TRUE 
@Jun 17, 2011 3:34:11 AM call InitGPS 
@Jun 17, 2011 3:34:11 AM lastKnownLocation: Location[mProvider=gps,mTime=1308274198000,mLatitude=30.10493179906883,mLongitude=31.379563305705755,mHasAltitude=true,mAltitude=85.0,mHasSpeed=true,mSpeed=0.0,mHasBearing=true,mBearing=313.8908,mHasAccuracy=true,mAccuracy=10.0,mExtras=Bundle[mParcelledData.dataSize=4]] 
@Jun 17, 2011 4:48:17 AM onStartCommand:flags:0:startId:1:intent:Intent { cmp=com.usegps2_1/.LocationService } 
@Jun 17, 2011 4:48:17 AM StartService with mbServiceStarted=TRUE 
@Jun 17, 2011 4:48:17 AM call InitGPS 
@Jun 17, 2011 4:48:17 AM lastKnownLocation: Location[mProvider=gps,mTime=1308274198000,mLatitude=30.10493179906883,mLongitude=31.379563305705755,mHasAltitude=true,mAltitude=85.0,mHasSpeed=true,mSpeed=0.0,mHasBearing=true,mBearing=313.8908,mHasAccuracy=true,mAccuracy=10.0,mExtras=Bundle[mParcelledData.dataSize=4]] 

GPS服務代碼是在這裏:

import java.text.DateFormat; 
import java.util.Date; 
import java.util.Timer; 
import java.util.TimerTask; 
import java.util.concurrent.TimeUnit; 
import android.app.AlarmManager; 
import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.location.Location; 
import android.location.LocationManager; 
import android.os.Binder; 
import android.os.IBinder; 
import android.os.PowerManager; 
import android.os.SystemClock; 
import android.telephony.TelephonyManager; 
import android.util.Log; 
import android.widget.Toast; 
import android.media.*; 

public class LocationService extends Service { 

    /* ------------------------------------- Attributes */ 
    int NOTIFICATION_ID = 11283; 
    private NotificationManager mNotificationManager; 
    public MainActivity mMainActivity = null; 
    protected PowerManager.WakeLock mWakeLock; 
    protected AlarmManager mAlarMgr; 
    protected PendingIntent AlarmIntent ; 

    protected Notification mNotification; 
    protected PendingIntent mContentIntent; 

    protected static final double d2r = Math.PI/180.0; 

    // Location Variables 
    protected static final int mAlarmRepeatRate = 5 * 60 * 1000; 
    protected static final int mLocationTimeMinUpdate = 20000;  // minimum time for wait between signals. 
    protected static final int mLocationDistanceMinUpdate = 25; // minimum meters before call back 
    protected static final int TWO_MINUTES = 2 * 60 * 1000;  // used to define old readings 

    // TODO : This should be a function in speed. with min & max value. 
    protected static final int MIN_MapRefreshRate= 10000 ; // rate used to send to webservice. 

    protected long mLocationNextSentTime; 
    public String mDeviceID=null; 
    public String mBatteryLevel=null; 
    protected String mMobileServiceURL = "http://locationbook.net/Tracking.asmx"; 
    public Boolean mUseGPSOnly; 
    public Boolean mEnableBeeps ; 
    public Boolean mEnableDebug; 
    public String mSpeedText="0"; 
    public boolean mbBeepStarted = false; 
    public boolean mbStarted = false; 


    public boolean mbServiceStarted = false; 

    public Location mLastLocation =null; 


    protected LocationManager mlocManager ; 
    protected MainGpsListener mMainGpsListener; 
    protected MainLocationListener mlocListenerGPS; 
    protected MainLocationListener mlocListenerNW; 

    protected ToneGenerator mTG; 
    protected float mSpeed; 
    // This is the object that receives interactions from clients. See 
    // RemoteService for a more complete example. 
    private final IBinder mBinder = new LocalBinder(); 

    /* EOF Attributes */ 


    /** 
    * Class for clients to access. Because we know this service always 
    * runs in the same process as its clients, we don't need to deal with 
    * IPC. 
    */ 
    public class LocalBinder extends Binder { 
     LocationService getService() { 
      return LocationService.this; 
     } 
    } 

    /** 
    * @see android.app.Service#onBind(Intent) 
    */ 
    @Override 
    public IBinder onBind(Intent intent) { 
     // TODO Put your code here 
     return mBinder; 
    } 

    /** 
    * @see android.app.Service#onCreate() 
    */ 
    @Override 
    public void onCreate() { 
     super.onCreate(); 


     // TODO: Input this here to re-create when alarm calls. 
     mbServiceStarted = false; 
     com.usegps2_1.Logger.Log(getBaseContext(), "onCreate"); 

    } 

    /** 
    * @see android.app.Service#onStart(Intent,int) 
    */ 
    @Override 
    public void onStart(Intent intent, int startId) { 
     // TODO Put your code here 
     super.onStart(intent, startId); 

    } 


    @Override 
    public void onDestroy() { 

     if (mEnableDebug)Logger.Log(getBaseContext(), "onDestroy"); 

     mAlarMgr.cancel(AlarmIntent); 

     if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_0,1500); 
     if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_2,2500); 

     // Cancel the persistent notification. 
     mNotificationManager.cancel(NOTIFICATION_ID); // Remove Notification 

     if (mbStarted == true) 
     { 
      mlocListenerNW.mLocationService=null; 
      mlocListenerGPS.mLocationService=null; 
      mMainGpsListener.mLocationService=null; 
      mlocManager.removeUpdates(mlocListenerNW); 
      mlocManager.removeUpdates(mlocListenerGPS); 
      mlocManager=null; 
     } 


     /** I assume that this function will not be called except when I want to close 
     * as mWakeLock prevent it from closing. so we can allow closing the screen here. 
     */ 
     mWakeLock.release(); 

     // Tell the user we stopped. 
     Toast.makeText(this, "Service Exit", Toast.LENGTH_SHORT).show(); 


     super.onDestroy(); 
    } 


    public int onStartCommand(Intent intent, int flags, int startId) { 
      // We want this service to continue running until it is explicitly 
      // stopped, so return sticky. 

      /** 
      * http://android-developers.blogspot.com/2010/02/service-api-changes-starting-with.html 
      * 1- An application calls startService(). 
      * 2- That service gets onCreate(), onStart(), and then spawns a background thread to do some work. 
      * 3- The system is tight on memory, so has to kill the currently running service. 
      * 4- Later when memory is free, the service is restarted, and gets onCreate() called but not onStart() 
      * because there has not been another call to startService() with a new Intent command to send it. 
      * START_STICKY is basically the same as the previous behavior, 
      * 
      * where the service is left "started" and will later be restarted by the system. 
      * The only difference from previous versions of the platform is that 
      * it if it gets restarted because its process is killed, 
      * onStartCommand() will be called on the next instance of the service with a null Intent instead of not being called at all. 
      * Services that use this mode should always check for this case and deal with it appropriately. 
      * 
      * from Android Book. 
      * [2] The flag parameter can be used to discover how the Service was started. In particular you can use the 
      * code snippet shown in Listing 9-2 to determine if either of the following cases is true: 
      * ? START_FLAG_REDELIVERY Indicates that the Intent parameter is a redelivery caused by the 
      * system run time’s having terminated the Service before it was explicitly stopped by a call to stopSelf. 
      * ? START_FLAG_RETRY Indicates that the Service has been restarted after an abnormal termination. 
      * Passed in when the Service was previously set to START_STICKY. 
      */ 


      com.usegps2_1.Logger.Log(getBaseContext(), "onStartCommand:flags:" + String.valueOf(flags) + ":startId:" + String.valueOf(startId)+ ":intent:" + intent.toString()); 

      if (intent == null) 
      { 
       // TODO If it’s a restart, do something. 
       updateNotification("Restarted"); 
       if (mTG != null) 
       { 
        if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_5,2000); 
       } 
      } 



      //mAlarMgr.cancel(null); 

      // see [2] 
      if ((flags & START_FLAG_RETRY) == 0) { 
       // FROM DEBUGGING the above condition is wrong it should be != 0. 
       // PLease check and review before writing code here. 
      } 
      else { 
       // TODO Alternative background process. 
      } 

      StartService(); 

      return START_STICKY; 
     } 

    /** 
     * Read preference settings and apply them. 
     */ 
    public void ApplyPreferenceSttings() 
    { 
     mMobileServiceURL = CustomPreferenceManager.GetServiceURL(getApplication()); 
     mUseGPSOnly= CustomPreferenceManager.GetGPSOnly(getApplication()); 
     mEnableBeeps= CustomPreferenceManager.GetBeepsEnabled(getApplication()) ; 
     mEnableDebug = CustomPreferenceManager.GetDebugEnabled(getApplication()); 
    } 

    /** 
     * Called from outside to start service. 
     */ 
    public void StartService() 
    { 


     if (mbServiceStarted == false) 
     { 
      mbServiceStarted = true; 

      // TODO: please remember to use PARTIAL_WAKE_LOCK instead of .SCREEN_DIM_WAKE_LOCK 
      PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
      mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag"); 
      mWakeLock.acquire(); 

      ApplyPreferenceSttings(); 

      if (mEnableDebug)Logger.Log(getBaseContext(), "StartService re-initialize=TRUE"); 


      TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
      mDeviceID = telephonyManager.getDeviceId(); 


      showNotification(); 

      mTG = new ToneGenerator (1,80); 

      if (mAlarMgr != null) 
      if (mEnableDebug)Logger.Log(getBaseContext(), "mAlarMgr is true"); 

      mAlarMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE); 
      Intent intentToFire = new Intent (GPSBroadcastReceiver.ReceiverName); 
      AlarmIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0); 
      mAlarMgr.cancel(AlarmIntent); //Remove any alarms with a matching Intent. [BUG] avoid creating many alarms ... caused multipl alarm call with mbServiceStarted=False when check debugging files. 
      mAlarMgr.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + mAlarmRepeatRate , mAlarmRepeatRate, AlarmIntent); 

      // Register in Battery 
      this.registerReceiver(this.mBatInfoReceiver,new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 

      StartLocation(); 
     } 
     else 
     { 

      //updateNotification("called again while running"); 
     } 

     // */ 
    } 



    protected void showNotification() 
     { 
      mNotificationManager = (NotificationManager) getSystemService (Context.NOTIFICATION_SERVICE); 
      // Define Notification 
      mNotification = new Notification(R.drawable.step, "Tracking on", System.currentTimeMillis()); 
      mNotification.flags = Notification.FLAG_ONGOING_EVENT; 
      // Define Notification Action 
      Intent intent = new Intent(getApplicationContext(), MainActivity.class); 
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); 
      mContentIntent = PendingIntent.getActivity(LocationService.this, 0,intent, PendingIntent.FLAG_CANCEL_CURRENT); 

      // Set Notification 
      mNotification.setLatestEventInfo(LocationService.this,getText(R.string.app_name),"click to display main screen",mContentIntent); 
      // Add it 
      mNotificationManager.notify(NOTIFICATION_ID, mNotification); 
     } 

    protected void updateNotification (CharSequence Description) 
     { 
      if (mNotification ==null) return ; 
      mNotification.when=System.currentTimeMillis(); 
      // Set Notification 
      mNotification.setLatestEventInfo(LocationService.this,getText(R.string.app_name),Description,mContentIntent); 
      // Add it 
      mNotificationManager.notify(NOTIFICATION_ID, mNotification); 
     } 
    /*-------------------------------------------------GPS Methods*/ 

     protected void StartLocation() 
     { 
      if (mbStarted == true) 
      { 
       Toast.makeText(getApplicationContext(),"already running",Toast.LENGTH_SHORT).show(); 
       return ; 
      } 

      if (mEnableDebug)Logger.Log(getBaseContext(), "InitGPS true"); 

      mbStarted = true; 
      mLocationNextSentTime = 0 ; // Send once u get data 
      if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_1,1000); 




      // Use the LocationManager class to obtain GPS locations 
      mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); 
      Toast.makeText(getApplicationContext(),"Started",Toast.LENGTH_SHORT).show(); 


      Location loc= mlocManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 

      // try to read current position 
      if(loc != null){ 
       mLastLocation=loc; 
       if (mEnableDebug)Logger.Log(getBaseContext(), "lastKnownLocation: " + loc.toString()); 
      } 
      else 
      { 
       updateNotification ("getting location"); 

      } 

      mlocListenerGPS = new MainLocationListener(this); 
      mlocListenerNW = new MainLocationListener(this); 
      mlocListenerGPS.mProvider="GPS"; 
      mlocListenerNW.mProvider="NW"; 

      mMainGpsListener = new MainGpsListener(this); 
      // Define a listener that responds to location updates 


      mlocManager.addGpsStatusListener(mMainGpsListener); 
      mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, mLocationTimeMinUpdate, mLocationDistanceMinUpdate, mlocListenerGPS); 
      mlocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, mLocationTimeMinUpdate, mLocationDistanceMinUpdate, mlocListenerNW); 

      if (mEnableDebug)Logger.Log(getBaseContext(), "GPS reinitialized"); 

      // */ 
     } 



     public void UpdateLocation (Location loc, String Provider) 
     { 

      try 
      { 
       if (mUseGPSOnly && (Provider != "GPS")) return ; 

       if (mbStarted == false) 
       { 
        updateNotification("false"); 
       } 


       if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_9,200); 

       String E = loc.toString(); 
       if (mEnableDebug)Logger.Log(getBaseContext(), "New Location"); 
       if (mEnableDebug)Logger.Log(getBaseContext(), loc.toString()); 

       if (isBetterLocation (loc,mLastLocation)==false) 
       { 
        updateNotification ("location ignored"); 
        return ; 
       } 


       mLastLocation = loc; 

       mMainActivity.mtxtTime.setText(DateFormat.getDateInstance().format(new Date())); 
       mMainActivity.mtxtLatitude.setText(loc.getLatitude() + " lat"); 
       mMainActivity.mtxtLongitude.setText(loc.getLongitude() + " lng"); 

       float speed = loc.getSpeed(); // value if set by GetSpeed that is called insite isBetterLocation 
       mSpeedText=Float.toString(speed) ; 
       mMainActivity.mtxtSpeed.setText(mSpeedText + " km/s"); 



       if ((loc.getTime() > mLocationNextSentTime)) 
       { 

        mLocationNextSentTime = (long) (loc.getTime() + MIN_MapRefreshRate * (140 - speed)/ 140); 

        if (mEnableDebug)Logger.Log(getBaseContext(), "Next HTTP: " + String.valueOf(mLocationNextSentTime)); 

        WebMethodProxy client = new WebMethodProxy(mMobileServiceURL + "/UpdateLocation"); 
        client.AddParam("guid", mDeviceID); 
        client.AddParam("latitude",Double.toString(loc.getLatitude())); 
        client.AddParam("longitude", Double.toString(loc.getLongitude())); 
        client.AddParam("speed", mSpeedText); 
        client.AddParam("battery",mBatteryLevel);  

        //if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_5,500); 

        try { 
         client.Execute(WebMethodProxy.RequestMethod.POST_JSON); 
        } catch (Exception e) { 
         e.printStackTrace(); 

         // TODO : error message cannot connect to server 
         if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_9,2500); 
         String err = (e.getMessage() == null)?"GPS Error":e.getMessage(); 

         if (mEnableDebug)Logger.Log(getBaseContext(), "Failed: " + err); 

         Log.e("TrackGPS",err); 
         mMainActivity.mtxtMessage.setText("Cannot reach Internet to update location."); 
         return ; 
        } 

        String response = client.getResponse(); 
        response = (response ==null)?"no web reply":response; 

        if (mEnableDebug)Logger.Log(getBaseContext(), "HTTP DONE: " + response); 


        Toast.makeText(getApplicationContext(),"Updated[" + Provider + "]:" + response,Toast.LENGTH_SHORT).show(); 
        updateNotification ("location updated"); 

       } 
       else 
       { 
        updateNotification ("location ignored."); 
       } 
      } 
      catch (Exception e) 
      { 
       if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_2,2500); 
       String err = (e.getMessage() == null)?"GPS Error":e.getMessage(); 
       Log.e("TrackGPS",err); 
       updateNotification ("DEBUG1: " + e.getMessage()); 
       return ; 
      } 

     } 


     /** 
     * Returns distance in meters between two points. 
     * @param NewLocation 
     * @param CurrentLocation 
     * @return 
     */ 
     protected float CalculateSpeed (Location NewLocation, Location CurrentLocation) { 
      try 
      { 
      double dlong = (NewLocation.getLongitude() - CurrentLocation.getLongitude()) * d2r; 
      double dlat = (NewLocation.getLatitude() - CurrentLocation.getLatitude()) * d2r; 
      double a = Math.pow(Math.sin(dlat/2.0), 2) + Math.cos(CurrentLocation.getLatitude()*d2r) * Math.cos(NewLocation.getLatitude()*d2r) * Math.pow(Math.sin(dlong/2.0), 2); 
      double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
      double d = 6367000 * c; 
      double TimeDelta = NewLocation.getTime() - CurrentLocation.getTime(); 
      return (float) (d/TimeDelta) * 3600; 
      } 
      catch (Exception e) 
      { 
       if (mEnableBeeps) mTG.startTone(android.media.ToneGenerator.TONE_DTMF_2,2500); 
       Log.e("TrackGPS",e.getMessage()); 
       updateNotification ("DEBUG2: " + e.getMessage()); 
       return 0; 
      } 

     } 

     /** Determines whether one Location reading is better than the current Location fix 
     * Logic: 
     * if too old return FALSE. 
     * if too new return TRUE anyway as the current is too old. 
     * if more accurate then return TRUE 
     * if newer and same or more accurate then return TRUE. 
     * if newer and less accurate but same provider return TRUE. 
     * ------------------------------------------------------ 
     * Time  Accuracy Same Provider  Return 
     * ------------------------------------------------------ 
     * Too Old   x   x    FALSE 
     * Too New   x   x    TRUE 
     * Older   Plus   x    TRUE 
     * Newer   Plus   x    TRUE 
     * Newer   Same   x    TRUE 
     * Newer   Less  TRUE    TRUE 
     * ====================================================== 
     * @param location The new Location that you want to evaluate 
     * @param currentBestLocation The current Location fix, to which you want to compare the new one 
     */ 
     protected boolean isBetterLocation(Location location, Location currentBestLocation) { 
      try 
      { 
      location.setSpeed(0); // preset 

      if (currentBestLocation == null) { 
       // A new location is always better than no location 
       if (mEnableDebug)Logger.Log(getBaseContext(), "Accepted: first location"); 
       return true; 
      } 

      // Check whether the new location fix is newer or older 
      long timeDelta = location.getTime() - currentBestLocation.getTime(); 
      boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; 
      boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; 
      boolean isNewer = timeDelta > 0; 

      // If it's been more than two minutes since the current location, use the new location 
      // because the user has likely moved 
      if (isSignificantlyNewer) { 
       if (mEnableDebug)Logger.Log(getBaseContext(), "Accepted: isSignificantlyNewer"); 
       return true; 
      // If the new location is more than two minutes older, it must be worse 
      } else if (isSignificantlyOlder) { 
       if (mEnableDebug)Logger.Log(getBaseContext(), "Rejected: isSignificantlyOlder"); 
       return false; 
      } 

      // Check whether the new location fix is more or less accurate 
      int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); 
      boolean isLessAccurate = accuracyDelta > 0; 
      boolean isMoreAccurate = accuracyDelta < 0; 
      boolean isSignificantlyLessAccurate = accuracyDelta > 200; 

      // Check if the old and new location are from the same provider 
      boolean isFromSameProvider = isSameProvider(location.getProvider(), 
        currentBestLocation.getProvider()); 

      // Determine location quality using a combination of timeliness and accuracy 
      if (isMoreAccurate) { 
       location.setSpeed(CalculateSpeed (location,currentBestLocation)); 
       if (mEnableDebug)Logger.Log(getBaseContext(), "Accepted: isMoreAccurate"); 
       return true; 
      } else if (isNewer && !isLessAccurate) { 
       location.setSpeed(CalculateSpeed (location,currentBestLocation)); 
       if (mEnableDebug)Logger.Log(getBaseContext(), "Accepted: isNewer and not isLessAccurate"); 
       return true; 
      } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { 
       location.setSpeed(CalculateSpeed (location,currentBestLocation)); 
       if (mEnableDebug)Logger.Log(getBaseContext(), "Accepted: isNewer and LessAccurate but from same provider"); 

       return true; 
      } 

      if (mEnableDebug)Logger.Log(getBaseContext(), "Rejected: ???"); 

      return false; 
      } 
      catch (Exception e) 
      { 
       updateNotification ("Debug3: " + e.getMessage()); 
       return false; 
      } 
     } 

     /** Checks whether two providers are the same */ 
     protected boolean isSameProvider(String provider1, String provider2) { 
      if (provider1 == null) { 
       return provider2 == null; 
      } 
      return provider1.equals(provider2); 
     } 

     /*GPS Methods:EOF*/ 



     /*-------------------------------------------------BAT Methods*/ 
     protected BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){ 

      @Override 

      public void onReceive(Context arg0, Intent intent) { 

       int level = intent.getIntExtra("level", 0); 
       double voltage= intent.getIntExtra("voltage", 0) ; 
       double batteryTemperature = intent.getIntExtra("temperature", 0); 

       // update battery level. 
       mBatteryLevel = String.valueOf(level); 

       if (level < 31) 
       { 
        mMainActivity.mtxtBatteryInfo.setText("level: " + Double.toString(level) + " pls connect to charger."); 
        mMainActivity.mtxtBatteryInfo.setTextColor(0xffff0033); 
       } 
       else 
       { 
        mMainActivity.mtxtBatteryInfo.setText("level: " + Double.toString(level) + "% voltage: " + String.valueOf(Double.toString(voltage/1000.0)) + " Temp: " + Double.toString(batteryTemperature /10.0) + " c"); 
        mMainActivity.mtxtBatteryInfo.setTextColor(0xff99ff33); 
       } 
      } 

      }; 
     /*BAT Methods:EOF*/ 
} 
+0

在這裏發佈您的代碼。 – 2011-06-17 17:27:38

回答

1

我可以在這裏看到了一些問題。首先,onStart(Intent intent,int startId)已被棄用,您不需要實現此方法(特別是如果您所做的全部是super.onStart(intent, startId);)。

其次,您不需要在設置之前取消重複警報,因爲警報管理器會爲您執行此操作。

最重要的是,您應該只在onStartCommand方法期間獲取喚醒鎖。在開始時獲取它,然後在最後釋放它 - 理想情況下在finally塊內,以便在發生異常時仍然釋放鎖。在第一次收到意圖時獲取鎖定,然後保持到服務終止,從而防止CPU無所事事地休眠 - 這會影響電池壽命。

至於意圖的重複交付 - 如果您的服務變量正在重新初始化,那麼它聽起來像你的服務正在由Android重新啓動,因爲它死了。你有沒有檢查logcat(當運行連接)的任何堆棧跟蹤?也許將進程ID添加到日誌輸出中,以便發現這種情況。

如果Android認爲它沒有響應,那麼Android可能會終止您的服務。您已經進行了相當多的處理,您可能需要考慮將其分解爲單獨的類 - 然後理解服務在做什麼以及出錯的位置會更容易。