意图服务在一段时间后被杀死

时间:2013-12-30 08:40:18

标签: android android-service android-sensors intentservice

我在我的应用程序中实现了一个意向服务,其目的是持续监视设备的抖动。根据要求,每当检测到抖动时,应将此信息发送到应用服务器。 当我开始这个实现时,我遇到了使用服务或意图服务的困境,但我选择后者。目前,我能够检测到震动并且这些信息被转发到我的应用服务器,但有时从15分钟到2分钟小时(发布应用程序后)我注意到这个意图服务似乎不再发现任何震动(似乎它自己被杀)。 这是我的代码:


            public class TheftAlertService1 extends IntentService {

                /* The connection to the hardware */
                private SensorManager mySensorManager;

                /* Here we store the current values of acceleration, one for each axis */
                private float xAccel;
                private float yAccel;
                private float zAccel;

                /* And here the previous ones */
                private float xPreviousAccel;
                private float yPreviousAccel;
                private float zPreviousAccel;

                private static int SyncRunningFlag = 0;
                private double latitude; // latitude
                private double longitude; // longitude

                /* Used to suppress the first shaking */
                private boolean firstUpdate = true;

                /* What acceleration difference would we assume as a rapid movement? */
                private final float shakeThreshold = .75f;

                /* Has a shaking motion been started (one direction) */
                private boolean shakeInitiated = false;

                public TheftAlertService1() {
                    super("TheftAlertService1");
                    Log.d("TheftAlertService1", "inside constr");
                    // TODO Auto-generated constructor stub
                }

                @Override
                protected void onHandleIntent(Intent arg0) {
                    mySensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); // (1)
                    mySensorManager.registerListener(mySensorEventListener,
                            mySensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                            SensorManager.SENSOR_DELAY_NORMAL); // (2)
                    Log.d("TheftAlertService1", "Inside shake onHandleEvent");
                }


                /* The SensorEventListener lets us wire up to the real hardware events */
                private final SensorEventListener mySensorEventListener = new SensorEventListener() {

                    public void onSensorChanged(SensorEvent se) {
                        updateAccelParameters(se.values[0], se.values[1], se.values[2]); // (1)
                        if ((!shakeInitiated) && isAccelerationChanged()) { // (2)
                            shakeInitiated = true;
                        } else if ((shakeInitiated) && isAccelerationChanged()) { // (3)
                            executeShakeAction();
                        } else if ((shakeInitiated) && (!isAccelerationChanged())) { // (4)
                            shakeInitiated = false;
                        }
                    }

                    @Override
                    public void onAccuracyChanged(Sensor arg0, int arg1) {
                        // TODO Auto-generated method stub

                    }
                };

                /* Store the acceleration values given by the sensor */
                private void updateAccelParameters(float xNewAccel, float yNewAccel,
                        float zNewAccel) {
                    /*
                     * we have to suppress the first change of acceleration, it results from
                     * first values being initialized with 0
                     */
                    if (firstUpdate) {
                        xPreviousAccel = xNewAccel;
                        yPreviousAccel = yNewAccel;
                        zPreviousAccel = zNewAccel;
                        firstUpdate = false;
                    } else {
                        xPreviousAccel = xAccel;
                        yPreviousAccel = yAccel;
                        zPreviousAccel = zAccel;
                    }
                    xAccel = xNewAccel;
                    yAccel = yNewAccel;
                    zAccel = zNewAccel;
                }

                /*
                 * If the values of acceleration have changed on at least two axises, we are
                 * probably in a shake motion
                 */
                private boolean isAccelerationChanged() {
                    float deltaX = Math.abs(xPreviousAccel - xAccel);
                    float deltaY = Math.abs(yPreviousAccel - yAccel);
                    float deltaZ = Math.abs(zPreviousAccel - zAccel);
                    return (deltaX > shakeThreshold && deltaY > shakeThreshold)
                            || (deltaX > shakeThreshold && deltaZ > shakeThreshold)
                            || (deltaY > shakeThreshold && deltaZ > shakeThreshold);
                }

                private void executeShakeAction() {

                    Log.d("TheftAlertService1", "inside executeShakeAction");
                    if (SyncRunningFlag == 0)
                        new SendTheftAlertToBackend().execute();
                }

                /******************************************************************************************************/
                class SendTheftAlertToBackend extends AsyncTask<String, String, String> implements LocationListener{

                    JSONParser jsonParser = new JSONParser();
                    TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
                    String device_id = tm.getDeviceId();

                    @Override
                    protected void onPreExecute() {
                        super.onPreExecute();
                        SyncRunningFlag = 1;

                        LocationManager locationManager;
                        Location location; // location

                        locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
                        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0, this);

                        if (locationManager != null) {
                             location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                                Log.d("TheftAlertService1", "Latitude - " +latitude + "longitude - "+longitude);
                            }
                        }

                        Log.d("TheftAlertService1", "Sending Theft Alert to app server");
                    }

                    protected String doInBackground(String... args) {

                        String theft_alert_time = new SimpleDateFormat(
                                "yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance()
                                .getTime());
                        List<NameValuePair> params = new ArrayList<NameValuePair>();
                        params.add(new BasicNameValuePair("device_id", device_id));
                        params.add(new BasicNameValuePair("theft_alert_time",theft_alert_time));
                        params.add(new BasicNameValuePair("theft_alert_longitude","lon -" + longitude));
                        params.add(new BasicNameValuePair("theft_alert_latitude","lat -" + latitude));

                        // getting JSON Object
                        JSONObject json = jsonParser.makeHttpRequest(
                                AppConstants.url_theft_alert, "POST", params);

                        try {
                            Log.d("TheftAlertService1,Response from server : ",
                                    json.toString());
                        } catch (Exception e1) {
                            e1.printStackTrace();
                            SyncRunningFlag = 0;
                        }

                        // check for success tag
                        try {
                            int success = json.getInt(AppConstants.TAG_SUCCESS);
                            String tagDeviceId = json.getString(AppConstants.TAG_DEVICE_ID);

                            if (success == 1 && tagDeviceId.equals(device_id)) {
                                Log.d("TheftAlertService1",
                                        "Theft Alert successfully logged in server");
                                SyncRunningFlag = 0;
                            } else {
                                Log.d("TheftAlertService1",
                                        "Failed to log Theft Alert in server");
                                SyncRunningFlag = 0;
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            SyncRunningFlag = 0;
                        }
                        return null;
                    }

                    protected void onPostExecute(String file_url) {
                        Log.d("TheftAlertService1", "inside onPost of async task");
                    }

                    @Override
                    public void onLocationChanged(Location location) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void onProviderDisabled(String provider) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void onProviderEnabled(String provider) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void onStatusChanged(String provider, int status, Bundle extras) {
                        // TODO Auto-generated method stub

                    }
                }
            }

这是我迄今为止所尝试过的:

1)我已经覆盖onStartCommand并将其返回为START REDELIVER INTENT

2)我试图在前台制作意图服务。 但是这两个选项中的nethier已“持续”持续监控我的设备上的震动。

以下代码我尝试但徒劳无功:


            @Override
            public void onCreate() {
                super.onCreate();
            }

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


                final int myID = 1234;

                //The intent to launch when the user clicks the expanded notification
                Intent intentService = new Intent(this, Staff.class);
                intentService.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intentService, 0);

                //This constructor is deprecated. Use Notification.Builder instead
                Notification notice = new Notification(R.drawable.ic_launcher, "Ticker text", System.currentTimeMillis());

                //This method is deprecated. Use Notification.Builder instead.
                notice.setLatestEventInfo(this, "Title text", "Content text", pendIntent);

                notice.flags |= Notification.FLAG_NO_CLEAR;
                startForeground(myID, notice);      


                return START_REDELIVER_INTENT;
            }

            @Override
            public void onDestroy() {
                super.onDestroy();
                Log.d("TheftAlertService1","Service got killed");
            }

我做错了什么?我该怎么做才能使我的意图服务在后台持续运行(并且感觉永远震撼)。 感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:1)

正如Pankaj Kumar建议我在服务中创建我的震动检测而不是IntentService(正如我之前尝试过的那样,以前曾经无法检测到震动)。我在设备上测试了我的服务48小时(如nexus4,galaxy grand)并且能够在设备振动时检测上述测试期间的震动。 为了使服务无限期生效,我使服务成为前台并返回START_STICKY,如下所示。以下是完整代码:


            public class ShakeService extends Service {

                /* The connection to the hardware */
                private SensorManager mySensorManager;

                /* Here we store the current values of acceleration, one for each axis */
                private float xAccel;
                private float yAccel;
                private float zAccel;

                /* And here the previous ones */
                private float xPreviousAccel;
                private float yPreviousAccel;
                private float zPreviousAccel;

                /* Used to suppress the first shaking */
                private boolean firstUpdate = true;

                /* What acceleration difference would we assume as a rapid movement? */
                private final float shakeThreshold = .75f;

                /* Has a shaking motion been started (one direction) */
                private boolean shakeInitiated = false;
                private BackgroundThread backGroundThread = null;
                SensorEventListener mySensorEventListener;

                @Override
                public IBinder onBind(Intent intent) {
                    return null;
                }

                @Override
                public void onCreate() {
                    super.onCreate();
                    if (backGroundThread == null) {
                        backGroundThread = new BackgroundThread();
                    }
                }

                @Override
                public int onStartCommand(Intent intent, int flags, int startId) {
                    if (backGroundThread == null)
                        backGroundThread = new BackgroundThread();

                    if ((backGroundThread.getState() == Thread.State.NEW) || (backGroundThread.getState() == Thread.State.TERMINATED)) {
                        if (backGroundThread.getState() == Thread.State.TERMINATED)
                            backGroundThread = new BackgroundThread();

                        backGroundThread.start();

                        Notification localNotification = new Notification(R.drawable.ic_launcher, "", System.currentTimeMillis());
                        localNotification.setLatestEventInfo(this,AppConstants.NOTIFICATION_NAME,AppConstants.NOTIFICATION_DESCRIPTION, null);
                        localNotification.flags = Notification.FLAG_NO_CLEAR;
                        startForeground(377982, localNotification);

                        mySensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
                        mySensorManager.registerListener(mySensorEventListener,mySensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
                        Log.d("ShakeService", "Inside shake onStartCommand");   
                    }

                    return START_STICKY;
                }

                @Override
                public void onDestroy() {
                    super.onDestroy();
                    BackgroundThread.yield();
                    backGroundThread = null;
                }

                class BackgroundThread extends Thread {

                    @Override
                    public void run() {

                        /* The SensorEventListener lets us wire up to the real hardware events */
                        mySensorEventListener = new SensorEventListener() {

                            public void onSensorChanged(SensorEvent se) {
                                updateAccelParameters(se.values[0], se.values[1], se.values[2]);
                                if ((!shakeInitiated) && isAccelerationChanged()) {
                                    shakeInitiated = true;
                                } else if ((shakeInitiated) && isAccelerationChanged()) {
                                    executeShakeAction();
                                } else if ((shakeInitiated) && (!isAccelerationChanged())) {
                                    shakeInitiated = false;
                                }
                            }

                            @Override
                            public void onAccuracyChanged(Sensor arg0, int arg1) {

                            }

                            /* Store the acceleration values given by the sensor */
                            private void updateAccelParameters(float xNewAccel, float yNewAccel,float zNewAccel) {
                                /*
                                 * we have to suppress the first change of acceleration, it results from
                                 * first values being initialized with 0
                                 */
                                if (firstUpdate) {
                                    xPreviousAccel = xNewAccel;
                                    yPreviousAccel = yNewAccel;
                                    zPreviousAccel = zNewAccel;
                                    firstUpdate = false;
                                } else {
                                    xPreviousAccel = xAccel;
                                    yPreviousAccel = yAccel;
                                    zPreviousAccel = zAccel;
                                }
                                xAccel = xNewAccel;
                                yAccel = yNewAccel;
                                zAccel = zNewAccel;
                            }

                            /*
                             * If the values of acceleration have changed on at least two axises, we are
                             * probably in a shake motion
                             */
                            private boolean isAccelerationChanged() {
                                float deltaX = Math.abs(xPreviousAccel - xAccel);
                                float deltaY = Math.abs(yPreviousAccel - yAccel);
                                float deltaZ = Math.abs(zPreviousAccel - zAccel);
                                return (deltaX > shakeThreshold && deltaY > shakeThreshold) || (deltaX > shakeThreshold && deltaZ > shakeThreshold) || (deltaY > shakeThreshold && deltaZ > shakeThreshold);
                            }

                            private void executeShakeAction() {
                                Log.d("ShakeService", "inside executeShakeAction");
                                    // Or do something like post the shake status to app server
                            }
                        };
                    }
                }   
            }

答案 1 :(得分:0)

newIntent(GcmIntentService.this,TheftAlertService1.class); startService(theftAlertIntent);

替换它
  

newIntent(getApplicationContext(),TheftAlertService1.class); startService(theftAlertIntent);