Я реализовал службу намерений в своем приложении, целью которой является постоянный мониторинг сотрясения устройства. Согласно требованию, при обнаружении сотрясения эта информация должна отправляться на сервер приложений. Когда я начал эту реализацию, у меня была дилемма, использовать ли службу или службу намерений, но я выбрал последнюю. В настоящее время я могу обнаружить дрожание, и эта информация передается на мой сервер приложений, но иногда от 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) Я попытался сделать службу намерений на переднем плане. Но ни один из этих двух вариантов не «поддерживает» непрерывный фоновый мониторинг дрожания на моем устройстве.
Следующий код я пробовал, но тщетно:
@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");
}
Что я делаю неправильно? Что я должен сделать, чтобы моя служба намерений работала непрерывно в фоновом режиме (и смысл дрожал навсегда). Любая помощь приветствуется. Спасибо!