The service does not run if the app is killed - android

So I have a service that checks if the Screen is ON or OFF (from here).
This is the main activity:
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onCreate();
}
public void onCreate() {
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
}
#Override
protected void onPause() {
if (ScreenReceiver.screenOff) {
System.out.println("SCREEN TURNED OFF");
} else {
System.out.println("this is when onPause() is called when the screen state has not changed ");
}
super.onPause();
}
#Override
protected void onResume() {
// only when screen turns on
if (!ScreenReceiver.screenOff) {
System.out.println("SCREEN TURNED ON");
} else {
System.out.println(" this is when onResume() is called when the screen state has not changed ");
}
super.onResume();
}
}
The Service class:
public class UpdateService extends Service {
public void onCreate() {
super.onCreate();
// register receiver that handles screen on and screen off logic
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onStart(Intent intent, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if (!screenOn) {
System.out.println("Screen is off");
} else {
System.out.println("Screen is on");
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Receiver:
public class ScreenReceiver extends BroadcastReceiver {
public static boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("onReceive ");
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
System.out.println("SCREEN TURNED OFF on BroadcastReceiver");
Log.d("Check", "SCREEN TURNED OFF" );
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = false;
System.out.println("SCREEN TURNED ON on BroadcastReceiver");
Log.d("Check", "SCREEN TURNED ON" );
}
Intent i = new Intent(context, UpdateService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
}
}
The above service runs perfectly when the app is sent to the background. But when the app is killed using the task manager, the service does not work anymore. I need the service to work even when the app is killed.
What should I do to enable that? Any ideas?

The reason is that your service is running on the same process as the application. If you set android:process=":yourServiceName" in the manifest file, your service will start a new process and you can see your service.
Also, do check if your service is actually running using this method
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
To restart the service you can use an AlarmManager inside your onTaskRemoved method of the service.
#Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartService = new Intent(getApplicationContext(), this.getClass());
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartService, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME, 5000, pendingIntent);
}

If they run in the same process, it is obviously that the service is terminated together with your desktop application.
Run your service as a Windows Service / Linux daemon, they have a different lifecycle compared to the processes created by the user. For example, your application will be terminated automatically on logout.

Related

Screen Receiver Broadcast not working

i want to receive a broad cast when the screen is turned off in android. I have written the following code. This is the Receiver's code.
#Override
public void onReceive(Context context, Intent intent) {
helper = new FeedReaderDBHelper(context);
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
System.out.println("Screen Off Receiver just received something");
if(helper.getValue(FeedReaderContract.FeedEntry.onlock).equals("YES"))
{
helper.lockAll();
wasScreenOn = false;
}
else if(helper.getValue(FeedReaderContract.FeedEntry.onLock3).equals("YES"))
{
System.out.println("Running 3 minutes thread");
Runner runner = new Runner(context);
Thread t = new Thread(runner);
t.setName("LockThreeThread");
t.start();
}
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// and do whatever you need to do here
wasScreenOn = true;
}
}
I am registering and unregistering the Receiver in a Service. The code is as follows.
Registring Receiver in onStartCommand method
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
isScreenOn = pm.isScreenOn();
RegisterReceiver();
//Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_SHORT).show();
//System.out.println("StartRemove");
helper = new FeedReaderDBHelper(this);
names = helper.getNames();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
startChecker();
}
});
t.start();
return START_STICKY;
}
And this is how i unregister in onDestroy of the Service method.
private void RegisterReceiver()
{
receiver = Factory.getScreeReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(receiver, filter);
}
Please let me know what could be the problem. I have been digging into it for long time. Last two days were wasted on this. Nothing seems to work.
I think you're overly complicating this.
This is the activity you would need
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent startServiceIntent = new Intent(this, MyService.class);
startService(startServiceIntent);
}
This is the service
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 int onStartCommand(Intent intent, int flags, int startId) {
Log.i("APP", "Service started");
ScreenOffReceiver receiver = new ScreenOffReceiver();
registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
return START_STICKY;
}
}
And this is the Broadcast Receiver
public class ScreenOffReceiver extends BroadcastReceiver {
public ScreenOffReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Log.i("APP", "EVENT occured");
}
}
I just tried out this code and the logging worked fine.
When you start this via a service, and start a new thread to do the job in the onStartCommand() method, be noted that the thread will start every time you invoke the onCreate() of the activity.
Hope this helps

Service that detects screen lock: "Unable to start service Intent"

I'm trying to catch when my device screen is turned off or on. I looked at this answer here. However I haven't quite figured it out. When I test it, I get a warning saying that the service wasn't able to be created: Unable to start service Intent... not found. I'm new to services so I was hoping someone could look over the code and see what I'm doing wrong. Here is my Receiver and Service:
public class MyReceiver extends BroadcastReceiver {
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
Home.locked = true;
Log.i("screenstate", "off");
} else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.i("screenstate", "on");
}else if(intent.getAction().equals(Intent.ACTION_ANSWER)) {
}
Intent i = new Intent(context, UpdateService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
}}
Service:
public class UpdateService extends Service {
BroadcastReceiver mReceiver;
Boolean isRunning;
Context context;
Thread backgroundThread;
#Override
public void onCreate() {
super.onCreate();
context = this;
isRunning = false;
// register receiver that handles screen on and screen off logic
Log.i("UpdateService", "Started");
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_ANSWER);
mReceiver = new MyReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onDestroy() {
unregisterReceiver(mReceiver);
isRunning = false;
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if (!screenOn) {
Log.i("screenON", "Called");
Toast.makeText(getApplicationContext(), "Awake", Toast.LENGTH_LONG)
.show();
} else {
Log.i("screenOFF", "Called");
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}}
Here is my main activity:
public class Home extends Activity {
static boolean locked = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(Home.this, UpdateService.class));
if(locked)
setContentView(R.layout.activity_home2);
else
showApps(null);
}
public void showApps(View v){
locked = false;
Intent i = new Intent(this, AppsList.class);
startActivity(i);
}}
Thanks in advance.
It looks like the service hasn't been declared in the manifest file. Add its declaration within the <application> tag:
<service android:name=".UpdateService"/>

Android: How to detect when phone is active and idle?

I want to create an app that will know when user is using the phone(start the screen and close the screen). After a period of time I need to call doSomething() method.
Question:
1.How can I know when user start using the phone and when he close the screen?
2.Should I use Service or IntentService? Which is better in my case?
You can try something like this using a BroadcastReceiver and a Service:
Your class using The BroadcastReceiver:
public class ScreenReceiver extends BroadcastReceiver {
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = false;
}
Intent i = new Intent(context, UpdateService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
}
}
And the service:
public static class ScreenService extends Service {
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onStart(Intent intent, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if (!screenOn) {
//Implement here your code
} else {
//Implement here your code
}
}
}

leaked Intent Receiver missing a call to unregisterReceiver

please before you don't like my question , please read the details .. what i am trying to do is to use a broadcast receiver when screen-off , so i want my app to start if the screen goes off .. here is my broadcast receiver code :
public class BootReceiver extends BroadcastReceiver {
public boolean screenoff;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenoff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenoff = false;
}
Intent intent1 = new Intent(context, ShakeService.class);
intent1.putExtra("screen_state", screenoff);
context.startService(intent1);
}
and here is the service code :
public class ShakeService extends Service{
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stu
return null;
}
#Override
public void onCreate() {
super.onCreate();
// REGISTER RECEIVER THAT HANDLES SCREEN ON AND SCREEN OFF LOGIC
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new BootReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try{
Intent intent1 = new Intent(getApplicationContext(), SplashScreen.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent1);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return START_STICKY;
}
}
and here is my splash screen activity that i call from the service :
public class SplashScreen extends Activity {
private static int SPLASH_TIME_OUT=3000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash_screen);
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
new Handler().postDelayed(new Runnable(){
public void run(){
Intent i =new Intent(SplashScreen.this,HomeScreen.class);
startActivity(i);
finish();
}
},SPLASH_TIME_OUT);
}
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
BroadcastReceiver mReceiver = new BootReceiver();
registerReceiver(mReceiver, filter);
super.onResume();
}
#Override
protected void onPause() {
// mSensorManager.unregisterListener(mShakeDetector);
BroadcastReceiver mReceiver = new BootReceiver();
unregisterReceiver(mReceiver);
super.onPause();
}
}
and as you can noticed i have unregistered my receiver but still i keep seeing this in the logcat :
leaked Intent Receiver are you missing a call to unregisterReceiver??
I agree with the method of registering the receiver in onResume() and unregistering it in onPause(). This helps when the app goes in and out of scope. I'm somewhat confused on what you're trying to do with your app, but initially I see that you create a new instance of the braodcast receiver in onPause() and unregister that. Try unregistering using the same instance . Also, if you want your service to remain running in the background, you may want to look into implementation of a partial wake lock, that keeps the CPU running for your app while the screen remains off. Could you provide one more details about the purpose of the app?

Start app when screen off

I want to open my MainActivity class when screen is off. In order to do that i make two class
ScreenReceiver.java to handle Screen OFF & Screen ON Intents:
public class ScreenReceiver extends BroadcastReceiver {
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = false;
}
Intent i = new Intent(context, UpdateService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
}
}
And UpdateService for implementing ScreenReceiver:
public class UpdateService extends Service {
#Override
public void onCreate() {
super.onCreate();
// register receiver that handles screen on and screen off logic
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
}
public void onStart(Context context, Intent intent, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if (!screenOn) {
// your code
Intent intent11 = new Intent(context,MainActivity.class);
intent11.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent11);
} else {
// your code
Intent intent11 = new Intent(context,MainActivity.class);
intent11.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
So, when i install my app, there are no event when screen is off. please show me the problem.
Did you start the UpdateService in foreground somewhere in your application??
Firstly, intents ACTION_SCREEN_OFF and ACTION_SCREEN_ON can only be handled by a receiver registered via function registerReceiver(). Defining an IntentFilter in manifest.xml does not work for these intents.
Then, you need to make sure UpdateService:onCreate() be called in your application, otherwise ScreenReceiver:onReceiver() will never be called. You may want to do this when get intent BOOT_COMPLETED.
You may change the code to this, and do not forget define the service in manifest:
public class UpdateService extends Service {
BroadcastReceiver mReceiver = new BroadcastReceiver {
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = false;
}
handleScreenAction(screenOff);
}
private void handleScreenAction(boolean screenOff) {
if (screenOff) {
// your code
Intent intent11 = new Intent(context,MainActivity.class);
intent11.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent11);
} else {
// your code
Intent intent11 = new Intent(context,MainActivity.class);
intent11.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
}
#Override
public void onCreate() {
super.onCreate();
// register receiver that handles screen on and screen off logic
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mReceiver, filter);
}
#Override
public void onDestory() {
super.onDestory();
unRegisterReceiver(mReceiver);
}
public void onStart(Context context, Intent intent, int startId) {
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}

Categories

Resources