The main tasks of the program include the execution of methods in the background, which uses Android Services.

It is necessary to start the Service in such a way that after the MainActivity is closed, the service remains in working condition and can generate notifications, and also, in the event of a system shutdown or a reboot, it is restored on its own.

At the moment, the main problem is to maintain life in MyService after closing the user interface.

AutoStart:

In AndroidManifest.xml were written

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETE"/> 

 <receiver android:name="ru.package.BootReceiver"> <intent-filter> <action android:name = "android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> 

In BootReceiver.java:

 @Override public void onReceive(Context context, Intent intent) { Intent serviceIntent = new Intent(context, MyService.class); context.startService(serviceIntent); } 

Service:

In AndroidManifest.xml spelled:

 <service android:name="ru.package.MyService" android:enabled="true" android:exported="true" android:process=":AnyProcessName"> </service> 

MyService.java contains the following code, with the exception of some parts (the most important elements are described, which may contain errors that do not allow solving the set task):

 public void onCreate() { super.onCreate(); notificationManager = (NotificationManager) this.getSystemService(this.NOTIFICATION_SERVICE); } 

 public int onStartCommand(Intent intent, int flags, int startId) { sendNotification("Service started", "Service", "started"); return Service.START_STICKY; } 

 public void sendNotification(String Ticker,String Title,String Text) { Intent notificationIntent = new Intent(this, MainActivity.class); notificationIntent.setAction(Intent.ACTION_MAIN); notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER); PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setContentIntent(contentIntent) .setOngoing(true) //invulnerable .setTicker(Ticker) .setContentTitle(Title) .setContentText(Text) .setWhen(System.currentTimeMillis()); Notification notification; if (android.os.Build.VERSION.SDK_INT<=15) { notification = builder.getNotification(); // API 15 and lower }else { notification = builder.build(); } startForeground(DEFAULT_NOTIFICATION_ID,notification); 

 @Override public IBinder onBind(Intent intent) { return new Binder(); } @Override public void onRebind(Intent intent) { super.onRebind(intent); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onDestroy() { //Removing any notifications notificationManager.cancel(DEFAULT_NOTIFICATION_ID); //Disabling service stopSelf(); super.onDestroy(); } 

MyService from MainActivity starts as follows:

 Intent intentService; 

 @Override protected void onCreate(Bundle savedInstanceState) { intentService = new Intent(this,MyService.class); } 

 public void runService() { boolean working = isMyServiceRunning(MyService.class); if (!working) { startService(intentService); } else { stopService(intentService); } } 

 public 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; } 

Please indicate the mistakes made during programming, adding them with third-party materials (examples) or keywords to search for.

  • And what class does your service expand? Service or IntentService ? - Yuriy SPb
  • Currently: public class MyService extends Service{ . It is necessary to replace with: public class MyService extends IntentService { Adding: public MyService() { super("anyname"); }@Override protected void onHandleIntent(Intent intent) { } public MyService() { super("anyname"); }@Override protected void onHandleIntent(Intent intent) { } ? - Mikhail Kolesnikov
  • IntentService does not seem to have to work constantly. It performs the task and ends. - Yuriy SPb
  • As an example of work, I can offer the application "Alarm Clock Xtreme" for analysis. The application automatically starts with the service after the smartphone is loaded, and is also restored after closing in recentTaskBar. All this happens in the background, i.e. the user interface does not open every time, however, in the list of notifications there is always a message stating that the service is in working condition. There is only one process in the dispatcher to which the Service is attached. In the case of closing the process automatically restart. - Mikhail Kolesnikov
  • one
    Yes, a detailed answer will be extremely interesting and useful. We are waiting) - YuriySPb

1 answer 1

For all the requirements for the "immortal" service to work adequately, it was necessary to uninstall the non-working version from the device, and then download the fresh build. It was caused, most likely, by permissions. I started building my program almost from scratch, so after the first installation, the application was issued with an insufficient number of permissions to implement the functions of the "immortal" service. At the moment, the application uses only two permissions: Notifications and Autostart. This idea was prompted to me by the full performance of the application on all other devices.

I will try to reflect in this answer all the elements of the code necessary for the operation of the "immortal" service.

Android Manifest:

 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <service android:name=".MyService" android:enabled="true" android:exported="true" > </service> <receiver android:name=".MyReceiver" android:permission="android.permission.RECEIVE_BOOT_COMPLETED" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> <action android:name="android.intent.action.REBOOT"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> 

MainActivity:

 public class MainActivity extends AppCompatActivity { Intent intentService; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); intentService = new Intent(this,MyService.class); } public void click_Service(View v) { if (!isMyServiceRunning(MyService.class)) { startService(intentService); } else { stopService(intentService); } } 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; } } 

MyService:

 public class MyService extends Service { private NotificationManager notificationManager; public static final int DEFAULT_NOTIFICATION_ID = 101; public void onCreate() { super.onCreate(); notificationManager = (NotificationManager) this.getSystemService(this.NOTIFICATION_SERVICE); } public int onStartCommand(Intent intent, int flags, int startId) { //Send Foreground Notification sendNotification("Ticker","Title","Text"); //Task doTask(); //return Service.START_STICKY; return START_REDELIVER_INTENT; } //Send custom notification public void sendNotification(String Ticker,String Title,String Text) { //These three lines makes Notification to open main activity after clicking on it Intent notificationIntent = new Intent(this, MainActivity.class); notificationIntent.setAction(Intent.ACTION_MAIN); notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER); PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setContentIntent(contentIntent) .setOngoing(true) //Can't be swiped out .setSmallIcon(R.mipmap.ic_launcher) //.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.large)) // большая картинка .setTicker(Ticker) .setContentTitle(Title) //Заголовок .setContentText(Text) // Текст уведомления .setWhen(System.currentTimeMillis()); Notification notification; if (android.os.Build.VERSION.SDK_INT<=15) { notification = builder.getNotification(); // API-15 and lower }else{ notification = builder.build(); } startForeground(DEFAULT_NOTIFICATION_ID, notification); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { super.onDestroy(); //Removing any notifications notificationManager.cancel(DEFAULT_NOTIFICATION_ID); //Disabling service stopSelf(); } } 

MyReceiver:

 public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent intentService = new Intent(context, MyService.class); context.startService(intentService); } } 

Thus, we get a service that automatically starts after the start of the system. The user interface can be invoked by clicking on a notification that cannot be removed from the notification panel. After opening the user interface, the service can be turned off or on manually by pressing the appropriate button. If the application is closed, including the application's swipe from the Recent Task Bar, the service will remain on and continue its work.

The only possible way to finish MyService without using the user interface is to close the Application process using Force Stop in the list of applications, or to stop the process manually in the system settings menu.

  • Did you have a friend? - elik
  • 2
    specially registered to say this is the wrong answer. need to wake the device and keep the service in awake mode - Vyacheslav
  • one
    Moreover, it is correct to use the alarmmanager, and not this “type correctly”. - Vyacheslav
  • 2
    The process on modern equipment can be killed by the system in general, and it will not save anything. - Vyacheslav