我在我的应用程序中实现了一个意向服务,其目的是持续监视设备的抖动。根据要求,每当检测到抖动时,应将此信息发送到应用服务器。 当我开始这个实现时,我遇到了使用服务或意图服务的困境,但我选择后者。目前,我能够检测到震动并且这些信息被转发到我的应用服务器,但有时从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");
}
我做错了什么?我该怎么做才能使我的意图服务在后台持续运行(并且感觉永远震撼)。 感谢任何帮助。谢谢!
答案 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);