Skip to content

Instantly share code, notes, and snippets.

@SmartDengg
Forked from Tagakov/DevButton.java
Created May 17, 2016 05:07
Show Gist options
  • Save SmartDengg/8e6b1688167a7b57e1a3e6e0ad2e8a8f to your computer and use it in GitHub Desktop.
Save SmartDengg/8e6b1688167a7b57e1a3e6e0ad2e8a8f to your computer and use it in GitHub Desktop.
Hidden button for debugging purposes. Should be used with: debugCompile 'com.squareup:seismic:1.0.2'
import android.app.Application;
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by tagakov on 16.09.15.
* Hidden button for debugging purposes.
* Invoking provided function on device shaking
*
* Should be used with:
*
* debugCompile 'com.squareup:seismic:1.0.2'
*
* Typical use is:
* @<code>
* if (BuildConfig.DEBUG) {
* DevButton.init(getApplicationContext()).onShake(new Runnable() {
* @Override
* public void run() {
* //do something
* }
* });
* }
* </code>
*/
@SuppressWarnings("TryWithIdenticalCatches")
public enum DevButton {
BUTTON;
private static final long SHAKING_THRESHOLD_MS = 500;
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
private Application application;
private volatile Runnable onShakeRun;
private volatile boolean shakerInitialized;
@NonNull
public DevButton init(Application application) {
this.application = application;
return this;
}
/**
* Do some work after device shaking
*
* @param run - function that would be invoked on shake detection
* @return - self for chaining
*/
public synchronized DevButton onShake(@Nullable Runnable run) {
if (application == null) {
throw new IllegalStateException("The DevButton is not initialized! Please initialize it with Application context!");
}
onShakeRun = run;
enableShakeDetection();
return this;
}
private synchronized void enableShakeDetection() {
if (shakerInitialized) return;
SensorManager sensorManager = (SensorManager) application.getSystemService(Context.SENSOR_SERVICE);
if (sensorManager == null) return; //nothing to do here
try {
Class<?> shakersListenerClass = Class.forName("com.squareup.seismic.ShakeDetector$Listener");
Class<?> shakerClass = Class.forName("com.squareup.seismic.ShakeDetector");
Constructor<?> constructor = shakerClass.getConstructor(shakersListenerClass);
Method shakerStart = shakerClass.getMethod("start", SensorManager.class);
Object listener = Proxy.newProxyInstance(shakersListenerClass.getClassLoader(), new Class[]{shakersListenerClass}, new InvocationHandler() {
long lastInvoked;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (System.currentTimeMillis() - lastInvoked > SHAKING_THRESHOLD_MS) {
if (onShakeRun != null) {
mainThreadHandler.postDelayed(onShakeRun, 0);
}
lastInvoked = System.currentTimeMillis();
}
return null;
}
});
shakerStart.invoke(constructor.newInstance(listener), sensorManager);
shakerInitialized = true;
} catch (ClassNotFoundException ignore) {
//Ok we can't do the fancy stuff for debugging
} catch (NoSuchMethodException ignore) {
//Ok we can't do the fancy stuff for debugging
} catch (InvocationTargetException ignore) {
//Ok we can't do the fancy stuff for debugging
} catch (InstantiationException ignore) {
//Ok we can't do the fancy stuff for debugging
} catch (IllegalAccessException ignore) {
//Ok we can't do the fancy stuff for debugging
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment