我在创建摇动检测服务时遇到问题
background_service
package com.likith.shakedetector;
import android.app.Service;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.widget.Toast;
public class Background_service extends Service implements SensorEventListener
{
SensorManager sensorManager;
int count=0;
private float lastX = 0;
private float lastY = 0;
private float lastZ = 0;
private static final int MIN_FORCE = 10;
private static final int MIN_DIRECTION_CHANGE = 3;
private static final int MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE = 200;
private static final int MAX_TOTAL_DURATION_OF_SHAKE = 400;
private long mFirstDirectionChangeTime = 0;
private long mLastDirectionChangeTime;
private int mDirectionChangeCount = 0;
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate()
{
super.onCreate();
}
public void onDestroy()
{
super.onDestroy();
sensorManager.unregisterListener(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_UI);
return START_STICKY;
}
public void onStart(Intent intent, int startId)
{
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_UI);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
}
@SuppressWarnings("deprecation")
private void getAccelerometer(SensorEvent event)
{
//Toast.makeText(getApplicationContext(),"Shaked",Toast.LENGTH_LONG).show();
float x = event.values[SensorManager.DATA_X];
float y = event.values[SensorManager.DATA_Y];
float z = event.values[SensorManager.DATA_Z];
float totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ);
if (totalMovement <= MIN_FORCE)
{
long now = System.currentTimeMillis();
if (mFirstDirectionChangeTime == 0)
{
mFirstDirectionChangeTime = now;
mLastDirectionChangeTime = now;
}
long lastChangeWasAgo = now - mLastDirectionChangeTime;
if (lastChangeWasAgo < MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE)
{
mLastDirectionChangeTime = now;
mDirectionChangeCount++;
lastX = x;
lastY = y;
lastZ = z;
if (mDirectionChangeCount >= MIN_DIRECTION_CHANGE)
{
long totalDuration = now - mFirstDirectionChangeTime;
if (totalDuration < MAX_TOTAL_DURATION_OF_SHAKE)
{
Toast.makeText(getApplicationContext(),"Shaked",Toast.LENGTH_LONG).show();
resetShakeParameters();
}
}
}
else
{
resetShakeParameters();
}
}
}
public void onSensorChanged(SensorEvent event)
{
getAccelerometer(event);
}
protected void onResume()
{
sensorManager.registerListener(this,sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_UI);
}
protected void onPause()
{
sensorManager.unregisterListener(this);
}
private void resetShakeParameters()
{
mFirstDirectionChangeTime = 0;
mDirectionChangeCount = 0;
mLastDirectionChangeTime = 0;
lastX = 0;
lastY = 0;
lastZ = 0;
}
当我运行此服务时,它会连续打印Toast消息。
如何更改代码,以便在摇动设备时只打印一次吐司信息?
答案 0 :(得分:1)
你有
float totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ);
您可能应该分别对每个轴进行操作 - 因为每个轴都会独立于其他轴进行更改。
float xMovement = Math.abs(x - lastX);
float yMovement = Math.abs(y - lastY);
float zMovement = Math.abs(z - lastZ);
if ((xMovement > MIN_FORCE) ||
(yMovement > MIN_FORCE) ||
(zMovement > MIN_FORCE)) {
// motion detected
}
我做了类似的事情,发现最好首先检查延迟(MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE)。
对于Android API 18,有一个重要的运动传感器,如果Android设备中存在可能对您有效。
请参阅http://developer.android.com/reference/android/hardware/Sensor.html#TYPE_SIGNIFICANT_MOTION
答案 1 :(得分:1)
试试这段代码
<强> Background_service.java 强>
package com.likith.shakedetector;
import com.likith.gesturelauncherPro.gestureDrawer;
import android.app.Service;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.os.IBinder;
public class Background_service extends Service implements com.likith.shakedetector.shake.Listener
{
@Override
public void onCreate()
{
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
shake sd = new shake(this);
sd.start(sensorManager);
}
@Override
public void hearShake()
{
//Toast.makeText(getApplicationContext(),"Shaked",Toast.LENGTH_LONG).show();
Intent notificationIntent = new Intent(this, gestureDrawer.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(notificationIntent);
}
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
<强> shake.java 强>
package com.likith.shakedetector;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import java.util.ArrayList;
import java.util.List;
/**
* Detects phone shaking. If > 75% of the samples taken in the past 0.5s are
* accelerating, the device is a) shaking, or b) free falling 1.84m (h =
* 1/2*g*t^2*3/4).
*
* @author Bob Lee (bob@squareup.com)
* @author Eric Burke (eric@squareup.com)
*/
public class shake implements SensorEventListener
{
private static final int ACCELERATION_THRESHOLD = 13;
public interface Listener
{
void hearShake();
}
private final SampleQueue queue = new SampleQueue();
private final Listener listener;
private SensorManager sensorManager;
private Sensor accelerometer;
public shake(Listener listener)
{
this.listener = listener;
}
public boolean start(SensorManager sensorManager)
{
if (accelerometer != null)
{
return true;
}
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// If this phone has an accelerometer, listen to it.
if (accelerometer != null)
{
this.sensorManager = sensorManager;
sensorManager.registerListener(this, accelerometer,SensorManager.SENSOR_DELAY_FASTEST);
}
return accelerometer != null;
}
/**
* Stops listening. Safe to call when already stopped. Ignored on devices
* without appropriate hardware.
*/
public void stop()
{
if (accelerometer != null)
{
sensorManager.unregisterListener(this, accelerometer);
sensorManager = null;
accelerometer = null;
}
}
@Override public void onSensorChanged(SensorEvent event)
{
boolean accelerating = isAccelerating(event);
long timestamp = event.timestamp;
queue.add(timestamp, accelerating);
if (queue.isShaking())
{
queue.clear();
listener.hearShake();
}
}
/** Returns true if the device is currently accelerating. */
private boolean isAccelerating(SensorEvent event)
{
float ax = event.values[0];
float ay = event.values[1];
float az = event.values[2];
// Instead of comparing magnitude to ACCELERATION_THRESHOLD,
// compare their squares. This is equivalent and doesn't need the
// actual magnitude, which would be computed using (expesive) Math.sqrt().
final double magnitudeSquared = ax * ax + ay * ay + az * az;
return magnitudeSquared > ACCELERATION_THRESHOLD * ACCELERATION_THRESHOLD;
}
/** Queue of samples. Keeps a running average. */
static class SampleQueue
{
/** Window size in ns. Used to compute the average. */
private static final long MAX_WINDOW_SIZE = 500000000; // 0.5s
private static final long MIN_WINDOW_SIZE = MAX_WINDOW_SIZE >> 1; // 0.25s
/**
* Ensure the queue size never falls below this size, even if the device
* fails to deliver this many events during the time window. The LG Ally
* is one such device.
*/
private static final int MIN_QUEUE_SIZE = 4;
private final SamplePool pool = new SamplePool();
private Sample oldest;
private Sample newest;
private int sampleCount;
private int acceleratingCount;
/**
* Adds a sample.
*
* @param timestamp in nanoseconds of sample
* @param accelerating true if > {@link #ACCELERATION_THRESHOLD}.
*/
void add(long timestamp, boolean accelerating)
{
// Purge samples that proceed window.
purge(timestamp - MAX_WINDOW_SIZE);
// Add the sample to the queue.
Sample added = pool.acquire();
added.timestamp = timestamp;
added.accelerating = accelerating;
added.next = null;
if (newest != null)
{
newest.next = added;
}
newest = added;
if (oldest == null)
{
oldest = added;
}
// Update running average.
sampleCount++;
if (accelerating)
{
acceleratingCount++;
}
}
/** Removes all samples from this queue. */
void clear() {
while (oldest != null) {
Sample removed = oldest;
oldest = removed.next;
pool.release(removed);
}
newest = null;
sampleCount = 0;
acceleratingCount = 0;
}
/** Purges samples with timestamps older than cutoff. */
void purge(long cutoff) {
while (sampleCount >= MIN_QUEUE_SIZE
&& oldest != null && cutoff - oldest.timestamp > 0) {
// Remove sample.
Sample removed = oldest;
if (removed.accelerating) {
acceleratingCount--;
}
sampleCount--;
oldest = removed.next;
if (oldest == null) {
newest = null;
}
pool.release(removed);
}
}
/** Copies the samples into a list, with the oldest entry at index 0. */
List<Sample> asList() {
List<Sample> list = new ArrayList<Sample>();
Sample s = oldest;
while (s != null) {
list.add(s);
s = s.next;
}
return list;
}
/**
* Returns true if we have enough samples and more than 3/4 of those samples
* are accelerating.
*/
boolean isShaking() {
return newest != null
&& oldest != null
&& newest.timestamp - oldest.timestamp >= MIN_WINDOW_SIZE
&& acceleratingCount >= (sampleCount >> 1) + (sampleCount >> 2);
}
}
/** An accelerometer sample. */
static class Sample {
/** Time sample was taken. */
long timestamp;
/** If acceleration > {@link #ACCELERATION_THRESHOLD}. */
boolean accelerating;
/** Next sample in the queue or pool. */
Sample next;
}
/** Pools samples. Avoids garbage collection. */
static class SamplePool {
private Sample head;
/** Acquires a sample from the pool. */
Sample acquire() {
Sample acquired = head;
if (acquired == null) {
acquired = new Sample();
} else {
// Remove instance from pool.
head = acquired.next;
}
return acquired;
}
/** Returns a sample to the pool. */
void release(Sample sample) {
sample.next = head;
head = sample;
}
}
@Override public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
<强>清单强>
<service android:name="com.likith.shakedetector.Background_service" />