My Job executes perfectly if the app is open but if i close the app the jobservice is never executed. I have followed the tutorial here; Job Scheduler - Code In Flow and it just does not run (or maybe it runs and we do not know it runs?). I have put in notifications and Log.d methods with in my methods so i can see if the job runs and while the app is open the log msgs and notifications push through as expected.
Any help would be appreciated . Thank you
UPDATE 2
===============
I have discovered, since the job runs while the app is open, if i close the app the job gets cancelled without the onStopJob being called. theoretically if i am not wrong job scheduler should continue the job irrespective of the app running or not.
the Log.d msgs looks like this
D/global_PEA: Job Scheduled //Schedule Job Button Pressed
D/global_PEA: Job Started //ExJobService runs
D/global_PEA: run: 0
D/global_PEA: run: 1
D/global_PEA: run: 2
D/global_PEA: run: 3
D/global_PEA: run: 4
// App closed and the output and notifications stop
// in theory it should continue till 9
=======
UPDATE
===============
Here is the adb shell dump of my app. it looks like its scheduled?
I cant get any notification or Log.d msgs when i force run the job from adb like so
adb shell cmd jobscheduler run -f com.raaif.pea 902
which leads me to think that maybe the job does infact run but nothing is shown to the user about it like the notification. Is there any way it could notify the application, even if its openning the app when the job is done?
==============
here are my code files
public class HomeFragment extends Fragment {
private Context mContext;
private Button btn1;
private Button btn2;
#Override
public void onAttach(Context context) {
mContext = context;
super.onAttach(context);
}
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_home, container, false);
btn1 = root.findViewById(R.id.button1);
btn2= root.findViewById(R.id.button2);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
scheduleJob();
}
});
btn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
cancelJob();
}
});
return root;
}
public void scheduleJob(){
ComponentName componentName = new ComponentName(mContext, ExJobService.class);
JobInfo info = new JobInfo.Builder(JOB_ID_1, componentName)
.setRequiresCharging(false)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setPersisted(true)
.setPeriodic(15 * 60 * 1000)
.build();
JobScheduler scheduler = (JobScheduler) mContext.getSystemService(JOB_SCHEDULER_SERVICE);
int resultcode = scheduler.schedule(info);
if(resultcode==JobScheduler.RESULT_SUCCESS){
Log.d(globals.appTag,"Job Scheduled");
}else{
Log.d(globals.appTag,"Job Scheduling failed");
}
}
public void cancelJob(){
JobScheduler scheduler = (JobScheduler)getContext().getSystemService(JOB_SCHEDULER_SERVICE);
scheduler.cancel(JOB_ID_1);
Log.d(globals.appTag,"Job cancelled");
}
}
And here is my JobService class
import android.app.Notification;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import static com.raaif.pea.Constants.CHANNEL_ID_NOTIFICATION_HIGH;
import static com.raaif.pea.Constants.HIGH_NOTIF_ID;
public class ExJobService extends JobService {
private Globals globals = Globals.getInstance();
private boolean jobcancelled = false;
private boolean reschedulestatus = false;
#Override
public boolean onStartJob(JobParameters params) {
Log.d(globals.appTag, "Job Started");
//output low notification
notify("Scheduled JobService", "Starting Background Work");
doBackgroundWork(params);
return true;
}
private void doBackgroundWork(final JobParameters params) {
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
if (jobcancelled) return;
Log.d(globals.appTag, "run: " + i);
ExJobService.this.notify("Thread Iterator",
String.format("Iteration Count: %d", i));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.d(globals.appTag, "Job Finished");
ExJobService.this.notify("Scheduled JobService", "Background Work Finished");
jobFinished(params, reschedulestatus);
Log.d(globals.appTag, "Job Service Params returned with " + reschedulestatus);
ExJobService.this.notify("Scheduled JobService", "Job Params returned");
}
}).start();
}
#Override
public boolean onStopJob(JobParameters params) {
Log.d(globals.appTag, "Job Cancelled before completion");
jobcancelled = true;
notify("OnStopJob", "Job Cancelled");
return false;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return Service.START_STICKY;
return super.onStartCommand(intent, flags, startId);
}
public void notify(String title, String content) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
Notification notification =
new NotificationCompat.Builder(ExJobService.this, CHANNEL_ID_NOTIFICATION_HIGH)
.setSmallIcon(R.drawable.ic_memory_black_24dp)
.setContentTitle(title)
.setContentText(content)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOnlyAlertOnce(false)
.build();
notificationManager.notify(HIGH_NOTIF_ID, notification);
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.raaif.pea">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<!-- SERVICES -->
<service android:name=".ExJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I see here is a problem but i don't know how do you handle it?! look at this:
public class ExJobService extends JobService {
...
private boolean reschedulestatus = false;
#Override
public boolean onStartJob(JobParameters params) {
....
doBackgroundWork(params);
return true;
}
private void doBackgroundWork(final JobParameters params) {
new Thread(new Runnable() {
....
jobFinished(params, reschedulestatus);
....
}).start();
}
}
You are passing false to jobFinished method that unintentionally you do not reschedule the job.
When doing stuff periodically in the background — JobScheduler, WorkManager, AlarmManager etc. — you have to take into account that your process might not be around when it is time for you to do your work. Android will fork a process for you, but it is "starting from scratch". Anything that your UI might have set up in memory, such as a database, would have been for some prior process and might not be set up in the new process.
Related
I'm trying to execute a service without an activity, yet ADV emulator seems to not response to my application. As written at the title I would like to have Service applications that will run constantly without UI/activity.
Here is my code:
AndroidManifest.xml:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"></uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:allowBackup="false" >
<service android:name=".service.PublicStartService" android:exported="true" />
</application>
</manifest>
Java File
public class PublicStartService extends Service {
private static final String TAG = "ServiceLog";
// The onCreate gets called only one time when the service starts.
#Override
public void onCreate() {
Log.i(TAG, "onCreate ");
}
// The onStartCommand gets called each time after the startService gets called.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String param = intent.getStringExtra("PARAM");
ExecutorService executorService = Executors.newFixedThreadPool(4);
Runnable worker = new MyRunnable();
executorService.execute(worker);
return Service.START_STICKY;
}
// The onDestroy gets called only one time when the service stops.
#Override
public void onDestroy() {
Log.i(TAG, "onDestroy ");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
class MyRunnable implements Runnable {
#Override
public void run() {
while (true){
Log.i(TAG, "THREAD THREAD THREAD ");
try {
sleep(500);
} catch (InterruptedException ignored) {
}
}
}
}
}
Any Idea what do it miss to make it execute?
Thanks!
I am using geofence in my app and based on geofence events (Enter or Exit) I want to perform some action. Geofence documentation says that once you set geofence it will trigger events automatically and you can catch this events with IntentService. For that I have made intentservice as below:
GeofenceTransitionsIntentService.java
public class GeofenceTransitionsIntentService extends IntentService {
Handler mHandler;
public GeofenceTransitionsIntentService() {
super("GeofenceTransitionsIntentService");
mHandler = new Handler();
}
#Override
public void onCreate() {
super.onCreate();
Log.e("JK-->>","service started!");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e("JK-->>","onHandel--->>");
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
Log.e("JK-->>","geofenceEvent has error!");
return;
}
int geofenceTransitionType = geofencingEvent.getGeofenceTransition();
if (geofenceTransitionType == Geofence.GEOFENCE_TRANSITION_ENTER) {
Log.e("JK-->>","enter!");
mHandler.post(new DisplayToast(this,"Enter"));
} else if (geofenceTransitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
mHandler.post(new DisplayToast(this,"Exit"));
Log.e("JK-->>","exit");
}
}
public class DisplayToast implements Runnable {
private final Context mContext;
String mText;
public DisplayToast(Context mContext, String text){
this.mContext = mContext;
mText = text;
}
public void run(){
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
}
}
}
Now, problem is that when app is open(No matter foreground or background) and I enter or exit in geofence it works fine and show me a toast message and logcat shows log but when I remove app from recent apps there is no toast message showing to me or no log is showing in logcat.
I have tried to find solution on google but mostly all answers suggests to use the service but if i am not wrong then IntentService stops itself automatically after work is done and start itself when any intent received. So, I think it's more efficient to use IntentService to do this task.
UPDATE
I am registering geofence using following line of code.
geofencingClient.addGeofences(getGeofencingRequest(),getGeofencePendingIntent());
and in getGeofencePendingIntent() i am starting intent service using following line of code.
private PendingIntent getGeofencePendingIntent() {
if(geofencePendingIntent != null)
return geofencePendingIntent;
Intent in = new Intent(SetProfileOnlineActivity.this,GeofenceTransitionsIntentService.class);
geofencePendingIntent = PendingIntent.getService(SetProfileOnlineActivity.this,111451,in,PendingIntent.FLAG_UPDATE_CURRENT);
return geofencePendingIntent;
}
This Service will run always :
Goto project java -> right click->New->service->service
name it watchman
watchman.java
public class watchman extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "1";
public watchman() { }
#Override
public void onCreate()
{
try
{
mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this, null);
mBuilder.setContentTitle("Insta Promo")
.setContentText("We are ready to help you.")
.setSmallIcon(R.drawable.ic_launcher_background);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotifyManager.createNotificationChannel(notificationChannel);
}
else
{
mBuilder.setContentTitle("Insta Promo")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setVibrate(new long[]{100, 250})
.setLights(Color.YELLOW, 500, 5000)
.setAutoCancel(true);
}
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
mNotifyManager.notify(1, mBuilder.build());
startForeground(1, mBuilder.build());
}
catch(Exception e)
{
Log.d(TAG, "EXCEPTION IN SHOWING NOTIFICATION xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...\n");
Log.e("MY_APP", "exception", e);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
new Thread(new Runnable()
{
public void run()
{
while (true)
{
try
{
Log.d(TAG, "Thread : Running again...\n");
Thread.sleep(10000);
}
catch (InterruptedException e)
{
Log.d(TAG, "Thread : InterruptedException Error in service...\n");
}
}
}
}).start();
return START_STICKY;
}
#Override
public void onDestroy()
{
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
It will get automatically registered in manifest file as you created it as service, no need to update manifest file.
From main activity or from wherever you want to start it call it like
Log.d(TAG, " Good to Go \n");
Log.d(TAG, "Starting Service from main...\n");
Intent intent = new Intent(MainActivity.this, watchman.class);
startService(intent);
Log.d(TAG, "Main has started the service...\n");
Now you even if removed it from recents..., It will be there in memory running always for you, To check it keep eye on logcat. Hope it helps. Its working in project from 4.1 onwards upto latest 8.0 oreo
for showing notifications i am using vibration permission so also making manifest file available for you.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rushi.oreo">
<uses-permission android:name="android.permission.VIBRATE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".watchman"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
Hope it really helps you or someone else.
IntentService will stop automatically when the work assigned to it is finished.
If you want a service to run in background with very less chances of getting stopped, it has to be a Foreground Service. Please make sure to start your Service in a background worker thread because by default a Service runs on the main thread.
More details are here - https://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)
But please note that making a Service as foreground impacts your phone's battery life too much. And a making a Service as Foreground is also annoying to the user since it shows a notification always and cannot be closed.
You can better use a JobScheduler or Firebase JobDispatcher to schedule background works.
I had found an answer... there was no problem in my code and IntentService was also working perfectly but the mistake was in the testing. I was testing my application on android Oreo running device.
In android oreo google has updated their policy that in foreground they will send location updates any number of times but in background they will send location updates only few times in hour.
The main reason behind it to save the bettery life of device.
For more information about android oreo location updates you can check out this documentation.
Currently i am working with an application and my app has a feature that the user will be able to click on a Navigate button and my app will start the Google Map. Till now it's fine and i have done it. But the fact where i am stuck is that i want my app to perform some tasks. To achieve that i have used JobService and scheduled it to run after every 5 seconds even when the app is in background.
When the user presses the back button then inside onDestroy method i have cancelled the scheduler. But when the app is removed from the background by sliding or pressing the cross icon the JobService keeps running as the onDestroy method can be called or not by the os when it is removed from the background. How can i stop the scheduled job when the app is removed from the background?
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="javarank.com.serviceinbackground">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyJobService" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE" />
</application>
</manifest>
MyJobService class
public class MyJobService extends JobService {
#Override
public boolean onStartJob(final JobParameters jobParameters) {
Toast.makeText(getApplicationContext(), "Doing job", Toast.LENGTH_SHORT).show();
jobFinished(jobParameters, true);
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
return false;
}
}
Here is my MainActivity
public class MainActivity extends AppCompatActivity {
private static final int JOB_ID = 1;
private JobInfo jobInfo;
private JobScheduler scheduler;
private Button navigateButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ComponentName componentName = new ComponentName(this, MyJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, componentName);
builder.setPeriodic(5000);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
// if true this job exists even after a system reboot...
builder.setPersisted(false);
jobInfo = builder.build();
scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
navigateButton = (Button) findViewById(R.id.navigate_button);
navigateButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
StringBuffer url = new StringBuffer("https://www.google.com/maps/dir/?api=1");
url.append("&origin=23.755736,90.374627");
url.append("&destination=23.754047,90.371682");
url.append("&travelmode=driving");
Uri gmmIntentUri = Uri.parse(url.toString());
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
}
});
}
#Override
protected void onDestroy() {
Toast.makeText(getApplicationContext(), "Destroy called.", Toast.LENGTH_SHORT).show();
scheduler.cancel(JOB_ID);
super.onDestroy();
}
}
I think you need to override following onStop() method and put stopService() command to stop the JobService.
#Override
protected void onStop() {
// A service can be "started" and/or "bound". In this case, it's "started" by this Activity
// and "bound" to the JobScheduler (also called "Scheduled" by the JobScheduler). This call
// to stopService() won't prevent scheduled jobs to be processed. However, failing
// to call stopService() would keep it alive indefinitely.
stopService(new Intent(this, MyJobService.class));
super.onStop();
}
You can create a new service like
MyService.java
public class MyService extends Service {
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
//stop you jobservice from here
stopSelf();
}
}
and start it from MainActivity.java
startService(new Intent(MainActivity.this,MyService.class));
Android> 7 automatically saves battery power. You must turn on the application's battery saving stop feature.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent();
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
add this to AndroidManifest.xml
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
I faced this issue, but I found that after schedule job service, it can't be canceled (From view).
So I turned to stop it inside the job service by calling onStopJob(params)
and it worked.
I am not sure if I have this right or not, but I have some code that I need to run in the background of my android application, and once that is complete, I would like to wait 10 seconds, and then run the code again.
I currently have this working, but I am sure it ain't the right way to go about it and wondered if someone can give me a simple example, or tell me what I need to change to make this "the right way" to do it.
First I have my ScheduleService.java file. This is where my code that I want to run it, and as you can see, once it is finished, it puts the thread to sleep for 10 seconds and then calls itself again, but this means that the code never actually completes (you should see the length of the stack trace if I get an error!)
ScheduleService.java
public class ScheduleService extends Service {
private static final String TAG = "ScheduleService";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
startJob();
}
});
t.start();
return Service.START_STICKY;
}
private void startJob(){
// all my code is here, and i do what i need
// job completed. Rest for 10 seconds before doing another one
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//do job again
startJob();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy(){
super.onDestroy();
}
}
Now to start the service code, I have the following when my application starts (in my MainActivity.java file)
// stop just encase its already started
context.stopService(new Intent(context, ScheduleService.class));
// start service
context.startService(new Intent(context, ScheduleService.class));
In order to make sure that the service is started when the device restarts, I also have my StartOnBootReciever.java code
public class StartOnBootReciever extends BroadcastReceiver {
private static final String TAG = "Autostart";
/**
* Listens for Android's BOOT_COMPLETED broadcast and then executes
* the onReceive() method.
*/
#Override
public void onReceive(Context context, Intent arg1) {
Log.d(TAG, "BOOT_COMPLETED broadcast received. Executing starter service.");
// upload in background
Intent intent = new Intent(context, ScheduleService.class);
context.startService(intent);
// This code will start the application once the device has been restarted
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
Then in my AndroidManifest.xml file, I have the following
<receiver android:enabled="true" android:exported="true" android:name="StartOnBootReciever" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:enabled="true" android:exported="false" android:name="com.idamigo.ticketmachine.ScheduleService" />
This all works, but I feel that have code that is self-calling, and "never ending"
In your Service, you have used Thread.Sleep which is unnecessary. Because Service will run continuously in the background until you stop it or System stops it.
Example:
public class ScheduleService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Timer timer = new Timer();
timer.schedule(task,1,10000);
return Service.START_STICKY;
}
TimerTask task= new TimerTask() {
#Override
public void run() {
//do your task here.
}
};
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Go for Service only if you need to run a task continuously in the background. Otherwise, use IntentService. IntentService will be stopped when there is no work for it so you don't need to manage its state by yourself.
I made an app as a service which runs in background. This app is basically a battery alarm. It works fine but the only problem is that when this service is running it also displays this app in the active application task manager. So when I exit this app it stops that service as well. So what I want is to only stop this service when the user unchecks the box in the app settings. If it is checked then it should not be stopped even if it is closed in active application task manager.
How can I stop showing my app in task manager?
I think I should provide code over here This is my service class
public class BatteryService extends Service {
Notify notification = new Notify();
BatteryAlarm alarm = new BatteryAlarm();
private MediaPlayer mMediaPlayer;
boolean flag = false;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
//method to start service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
notification.initNotification(this, false);
this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
//Broadcast receiver to get battery info
private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context c, Intent i) {
//notification.initNotification(c);
int level = i.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int plugged = i.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
SharedPreferences getAlarm = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String alarms = getAlarm.getString("ringtones", "content://media/internal/audio/media/45"); // /system/media/audio/ringtones/ANDROMEDA.ogg , content://media/internal/audio/media/45
Uri uri = Uri.parse(alarms);
if(plugged == 2) {
if(level == 100) {
if(uri != null) {
if(flag == false) {
playAlarm(c, uri);
notification.initNotification(c, true);
Toast.makeText(c, "Battery charge is completed. Unplug your mobile phone!", Toast.LENGTH_LONG).show();
flag = true;
}
}
}
} else if (plugged == 0) {
if(uri != null) {
stopAlarm();
}
notification.cancelNotification(c);
//Toast.makeText(c, "Mobile is unplugged", Toast.LENGTH_LONG).show();
}
}
};
//play alarm method
private void playAlarm(Context c, Uri uri) {
mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(getBaseContext(), uri);
final AudioManager audioManager = (AudioManager) c.getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
} catch (Exception ex) {
ex.printStackTrace();
onDestroy();
}
}
//method to stop playing alarm
private void stopAlarm() {
mMediaPlayer.stop();
flag = false;
}
//method to stop service
public void onDestroy() {
super.onDestroy();
notification.cancelNotification(this);
unregisterReceiver(this.mBatInfoReceiver);
stopAlarm();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
}
This is my main activity
public class BatteryNotify extends PreferenceActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.xml.prefs);
addPreferencesFromResource(R.xml.prefs);
SharedPreferences getCB = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
boolean cb = getCB.getBoolean("checkbox", true);
final CheckBoxPreference checkboxPref = (CheckBoxPreference) getPreferenceManager().findPreference("checkbox");
if(cb == true) {
startService(new Intent(getBaseContext(), BatteryService.class));
} else if(cb == false) {
stopService(new Intent(getBaseContext(), BatteryService.class));
}
checkboxPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(newValue.toString().equals("true")) {
startService(new Intent(getBaseContext(), BatteryService.class));
} else {
stopService(new Intent(getBaseContext(), BatteryService.class));
}
return true;
}
});
}
}
and here is my menifest file
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".BatteryNotify"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".BatteryService"></service>
</application>
The best way to do this would be to create a BroadcastReceiver, register it in the manifest with the appropriate intent-filters and when it receives one it starts the Service or Activity to perform whatever task you need.
EDIT:
Create your BroadcastReceiver as a separate class and register it in the manifest. When it receives a battery event, create a PendingIntent to start the Service. That way it doesn't matter if your app isn't running. It will be started for you.
How can I stop showing my app in task manager?
You can't, for obvious security reasons.