I'm trying to create a service where I want to detect something about user, let's say when user lays the device on a table, the thing is that I have that action detected but I have it on a MainActivty
and I want it to put on Service
.
The thing is that on my MainActivity()
I had my registerAction()
and on my onResume()
were called and in onPause()
I call the unregisterListener()
from my sensor
, as well I have a HandlerThread
where I start it on my onCreate()
how do I change it to Service
? Would be a problem? I see that there aren't the same methods...
I've created my Service
and I've got :
public class MyService extends Service {
public MyService() {
}
@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();
Log.d("CREATE","ONCREATE");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("DESTROY","ONDESTROY");
}
}
Also my MainActivity
I have put implements SensorEventListener
.
A skeleton of my class is :
public class MainActivity extends Activity implements SensorEventListener {
private HandlerThread mSensorThread;
private SensorManager mSensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensorThread = new HandlerThread("sensor_thread");
mSensorThread.start();
}
private void registerSensorListener() {
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST, new Handler(mSensorThread.getLooper()));
}
@Override
public void onSensorChanged(SensorEvent event) {
//DO stuff
if (isLayed()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d("LAY","LAYLAY");
}
});
mSensorManager.unregisterListener(this);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private boolean isLayed() {
return stuff;
}
@Override
protected void onResume() {
super.onResume();
registerSensorListener();
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
}
EDIT
I'm using szamani20 code, but I'm having problems with runOnUiThread
because I can not call from my Service
also, I'm having this issue
java.lang.RuntimeException: Unable to start service com.example.developer.qwe.MyService@d8c613b with null: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Intent.getAction()' on a null object reference
You can register SensorManager inside service in OnStartCommand.Also try using startForeground as android os will kill your service when app is killed
First of all you need to decide whether you want the user to be aware of your running service or not. Take a review on Background Execution Limits in android Oreo:
So considering your case where it seems there are lots of work to do in many situations, it would be a better approach to use a foreground service. As android document says about foreground services:
Since you mentioned that you have the action detected I won't enter that part of your code. So you need to create a subclass of
Service
as you did and use thestartService
method to get it'sonCreate
called. One thing you need to notice is that theonCreate
method of service is called once you callstartService
on that service for the first time, no matter how many times you callstartService
again theonCreate
method won't get called and only theonStartCommand
get called. We use that fact alongside that you could provide a string action within yourintent
to properly register and unregister your listener.In
MainActivity.java
:and then in
MyService.java
:Finally don't forget to unregister your listener in
onDestroy
in case of android kill your service (which is very rare):