0

I'm trying to follow a tutorial about sensor. It works fine with an activity. However, I want this to work in the background when the phone is locked. What's the best way to do that?

Here's the link to the tutorial http://jasonmcreynolds.com/?p=388

ShakeDetector class

public class ShakeDetector implements SensorEventListener {

/*
 * The gForce that is necessary to register as shake.
 * Must be greater than 1G (one earth gravity unit).
 * You can install "G-Force", by Blake La Pierre
 * from the Google Play Store and run it to see how
 *  many G's it takes to register a shake
 */
private static final float SHAKE_THRESHOLD_GRAVITY = 2.7F;
private static final int SHAKE_SLOP_TIME_MS = 500;
private static final int SHAKE_COUNT_RESET_TIME_MS = 3000;

private OnShakeListener mListener;
private long mShakeTimestamp;
private int mShakeCount;

public void setOnShakeListener(OnShakeListener listener) {
    this.mListener = listener;
}

public interface OnShakeListener {
    public void onShake(int count);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // ignore
}

@Override
public void onSensorChanged(SensorEvent event) {

    if (mListener != null) {
        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];

        float gX = x / SensorManager.GRAVITY_EARTH;
        float gY = y / SensorManager.GRAVITY_EARTH;
        float gZ = z / SensorManager.GRAVITY_EARTH;

        // gForce will be close to 1 when there is no movement.
        Float f = new Float(gX * gX + gY * gY + gZ * gZ);
        Double d = Math.sqrt(f.doubleValue());
        float gForce = d.floatValue();

        if (gForce > SHAKE_THRESHOLD_GRAVITY) {
            final long now = System.currentTimeMillis();
            // ignore shake events too close to each other (500ms)
            if (mShakeTimestamp + SHAKE_SLOP_TIME_MS > now) {
                return;
            }

            // reset the shake count after 3 seconds of no shakes
            if (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS < now) {
                mShakeCount = 0;
            }

            mShakeTimestamp = now;
            mShakeCount++;

            mListener.onShake(mShakeCount);
        }
    }
}
}

Main Acitivty

 public class MainActivity extends AppCompatActivity {

// The following are used for the shake detection
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShakeDetector mShakeDetector;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent intent = new Intent(MainActivity.this, ShakeService.class);
    startService(intent);

    // ShakeDetector initialization
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mAccelerometer = mSensorManager
            .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mShakeDetector = new ShakeDetector();
    mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {

        @Override
        public void onShake(int count) {
            Toast.makeText(getApplicationContext(), "shake",Toast.LENGTH_SHORT).show();
        }
    });
}

@Override
public void onResume() {
    super.onResume();
    // Add the following line to register the Session Manager Listener onResume
    mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}

@Override
public void onPause() {
    // Add the following line to unregister the Sensor Manager onPause
    mSensorManager.unregisterListener(mShakeDetector);
    super.onPause();
}

}

Shake Service

public class ShakeService extends Service {

private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShakeDetector mShakeDetector;

public ShakeService() {
}

@Override
public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public void onCreate() {
    super.onCreate();
    // ShakeDetector initialization
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mAccelerometer = mSensorManager
            .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mShakeDetector = new ShakeDetector();
    mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {

        @Override
        public void onShake(int count) {

            Intent i = getApplicationContext().getPackageManager().getLaunchIntentForPackage("com.facebook.katana");
            getApplicationContext().startActivity(i);

        }
    });
    mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}

@Override
public void onDestroy() {
    mSensorManager.unregisterListener(mShakeDetector);
    super.onDestroy();
}

}

Julia
  • 1,207
  • 4
  • 29
  • 47
  • What's wrong with your service? Did you get errors? – frogatto Aug 10 '16 at 20:05
  • actually it works. However, I want this to work even when my phone is locked. – Julia Aug 10 '16 at 20:30
  • When your phone is locked, the service is actually running, however when you shake the phone the activity won't start, because the screen is off. Have a loot at [this question](http://stackoverflow.com/questions/20113161/start-activity-screen-even-if-screen-is-locked-in-android), to find a way to start an activity when the screen is off. – frogatto Aug 10 '16 at 20:34
  • I don't need to start the activity when my screen is lock. I need the service to call a method in the service when the phone is shake. – Julia Aug 10 '16 at 20:48
  • So, isn't it calling the method? – frogatto Aug 10 '16 at 20:50
  • I want the service to call a method inside the service when shake without unlocking the phone or start an activity. – Julia Aug 10 '16 at 20:54
  • What's wrong? Doesn't it call the method? – frogatto Aug 10 '16 at 21:03
  • No, it doesn't work. It only works when my phone is on. After I lock, the shake doesn't work. – Julia Aug 10 '16 at 21:15
  • Please read this: http://stackoverflow.com/questions/17400940/is-it-possible-to-detect-motion-when-screen-is-off – frogatto Aug 10 '16 at 21:17
  • I got it. I put the listener on my Activity which doesn't work. When I moved it to my service class, I forgot to register it. After I register it in the service class and it works. Thanks a lot for your help. – Julia Aug 10 '16 at 21:27

2 Answers2

0

You need to use Threads, AsyncTask is the easiest to implement. Take a look at this, if that's what you're looking for: https://developer.android.com/guide/components/processes-and-threads.html

leonz
  • 1,107
  • 2
  • 10
  • 32
0

here is a goog example http://joerichard.net/android/android-shake-detector/

Steps: create a sensor event listener and then get from Activity. Create a service that fires when shake event happen.

Milon
  • 2,221
  • 23
  • 27