报警管理器启动命令

发布于 2024-11-16 01:46:24 字数 26505 浏览 3 评论 0 原文

我在 Android 上开发了一个 GPS 跟踪应用程序。 我使用 AlarmManager 每 5 分钟唤醒一次设备。 我开发了一个日志文件,该文件显示该应用程序运行良好,直到我收到 public int onStartCommand(Intent Intent, int flags, int startId) with startId = 1 再次..在这种情况下,我注意到所有变量都被重置,所以我再次初始化所有变量..问题是,一旦发生这种情况,我就会不断得到再次发生 startID = 1 的相同事件,几次调用后应用程序就会停止,直到我打开 ActivityForm 并再次与服务绑定!

不良事件的日志在这里:

@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*/
}

I develop a GPS Tracking app on android.
I use AlarmManager to wake up the device every 5 minutes.
I developed a log file that shows that the application works great until a moment when I receieve
public int onStartCommand(Intent intent, int flags, int startId) with startId = 1 again .... in this case I noticed that all variables are reset so I initialize all variables again .. the issue is that once this happens I keep getting same event with startID = 1 again and after few calls the app just stops until i open the ActivityForm and bind with service again !!!

the log is here for the bad events:

@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 Service code is here:

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*/
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谎言 2024-11-23 01:46:24

我在这里可以看到很多问题。

首先,onStart(Intent Intent, int startId) 已被弃用,您不需要实现此方法(特别是如果您所做的只是 super.onStart(intent, startId);)。

其次,您无需在设置重复闹钟之前取消它,因为闹钟管理器会为您执行此操作。

最重要的是,您应该仅在 onStartCommand 方法的持续时间内获取唤醒锁。在开始时获取它,然后在最后释放它 - 最好在finally块内,以便在发生异常时锁仍然被释放。第一次收到意图时会获取锁,然后一直保持到服务终止,防止 CPU 在无事可做时休眠——这会影响电池寿命。

至于重复传递意图 - 如果您的服务变量正在重新初始化,那么听起来 Android 正在重新启动您的服务,因为它已经死了。您是否在 logcat(连接运行时)中检查过任何堆栈跟踪?也许将进程 ID 添加到日志输出中,以便您可以发现何时发生这种情况。

如果 Android 认为您的服务已变得无响应,则它可能会终止您的服务。您已经进行了大量的处理,您可能需要考虑将其分解为单独的类 - 然后会更容易理解服务正在做什么以及哪里出了问题。

I can see a number of issues here.

First, onStart(Intent intent, int startId) is deprecated, you don't need to implement this method (especially if all you do is super.onStart(intent, startId);).

Second, you don't need to cancel the repeating alarm before you set it, as the alarm manager will do that for you.

Most importantly, you should only acquire the wake lock for the duration of your onStartCommand method. Acquire it at the beginning, then release it at the end - ideally inside a finally block so that in the event of an exception the lock is still released. At the moment the lock is acquired the first time an intent is received, and then held until the service is terminated, preventing the CPU from hibernating when it has nothing to do - this will affect battery life.

As for repeated delivery of the intent - if your service variables are being re-initialised then it sounds like your service is being restarted by Android because it died. Have you checked in the logcat (when running connected) for any stack traces? Maybe add the process ID to your log output so you can spot when this is happening.

It is possible that Android is killing your service, if it thinks it has become unresponsive. You've put quite a bit of processing in, you might want to think about decomposing this into separate classes - then it will be easier to comprehend what the service is doing and where it is going wrong.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文