I work with the service.

In my case, the service reads info from the server and if it has changed, it sends a notification.

But the problem is that the service periodically works: if you close the application through the task manager, the service may turn off and notifications do not arrive until I log into the application.

And I need the service to work around the clock. It does not matter whether the application is closed or not.

MyService:

package com.hodite.com.shcherbuk; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; import android.os.IBinder; import android.support.annotation.RequiresApi; import android.util.Log; import java.io.IOException; import java.util.Timer; import java.util.TimerTask; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Headers; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; public class MyService extends Service implements Constants { NotificationManager nm; SharedPreferences sp; public MyService() { } @Override public void onCreate() { super.onCreate(); sp = getSharedPreferences(CHECK_SETTINGS, Context.MODE_PRIVATE); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Timer myTimer = new Timer(); // Создаем таймер myTimer.schedule(new TimerTask() { // Определяем задачу @Override public void run() { push(); } }, 1L*1000, 2L * 1000); // 600 миллисекунд до первого запуска,1800 return START_STICKY; } public void push() { try { new asynchronousGet().run(); Log.i("Good","good"); } catch (Exception e) { Log.i("Eror","errorororor"); e.printStackTrace(); } } public void pushText(String str1,String str2){ //String url="http://"+str2; Context context = getApplicationContext(); Intent intent=new Intent(context,WebActivity.class); intent.putExtra(KEY_INTENT,str2); PendingIntent pendingIntent=PendingIntent.getActivity(context,0,intent,PendingIntent.FLAG_CANCEL_CURRENT); Notification.Builder builder = new Notification.Builder(this); // оставим только самое необходимое builder.setContentIntent(pendingIntent) .setSmallIcon(R.mipmap.ico) .setContentTitle("Hodite") .setContentText(str1); // Текст уведомления Notification notification = builder.build(); notification.defaults = Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE; // ставим флаг, чтобы уведомление пропало после нажатия notification.flags |= Notification.FLAG_AUTO_CANCEL; nm=(NotificationManager)getSystemService(NOTIFICATION_SERVICE); nm.notify((str1+str2).hashCode(),notification); } /*---------------------КЛАСС ДЛЯ СЧИТЫВАНИЕ ТЕКСТА ИЗ ФАЙЛА-----------*/ public class asynchronousGet { private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url(URL_TEXT_TXT) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void onResponse(Call call, Response response) throws IOException { try (ResponseBody responseBody = response.body()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0, size = responseHeaders.size(); i < size; i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } // Log.i("Good",responseBody.string()); // System.out.print(responseBody.string().toString());//СЧИТАННЫЙ ТЕКСТ String string=responseBody.string(); int count=0; String[] strings=new String[2]; for (String str : string.split("\n")) { Log.i("str",str); strings[count]=str; count++; } String s1; String s2; s1=sp.getString(notif_text, "notif_text"); Log.i("s1",s1); s2=sp.getString(notif_url, "notif_url"); Log.i("s2",s2); if(!(s1.equals(strings[0]) && s2.equals(strings[1]))){ /*Отправляем строки в уведомление*/ pushText(strings[0],strings[1]); /*Сохранение переменных в SharedPreference*/ SharedPreferences.Editor e = sp.edit(); e.putString(notif_text, strings[0]); e.putString(notif_url, strings[1]); e.commit(); // не забудьте подтвердить изменения } } } }); } } /**------------------------------------------------------------------**/ @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } } 

WebActivity

 public class WebActivity extends AppCompatActivity implements Constants{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /**Растянуть окно на весь экран**/ this.requestWindowFeature(Window.FEATURE_NO_TITLE); //this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_web); if(!isMyServiceRunning(MyService.class)){ startService(new Intent(this,MyService.class)); } refresh=(ImageView)findViewById(R.id.refresh); refresh.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { loadWeb(); refresh.setVisibility(View.INVISIBLE); } }); // Toast.makeText(this,"Данное приложение может взымать большое количество интернет-трафика",Toast.LENGTH_LONG).show(); loadWeb(); } public void loadWeb(){ //Intent intent=getIntent(); url=getIntent().getStringExtra(KEY_INTENT); web=(XWalkView) findViewById(R.id.web_xwalkview); web.setResourceClient(new ResourceClient(web)); web.setUIClient(new UIClient(web)); web.clearCache(true); web.load(url, null); //progressBar.setVisibility(ProgressBar.INVISIBLE); } /**-----------------------------ПРОВЕРКА НА ЗАПУСК СЕРВИСА--------------------**/ 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; } /*----------------------------------------------------------------------------------*/ @Override public void onBackPressed() { new AlertDialog.Builder(this) .setTitle("Выход") .setMessage("Ты уверен,что хочешь выйти?") .setNegativeButton(android.R.string.no, null) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface arg0, int arg1) { //finish(); //эмулируем нажатие на HOME, сворачивая приложение Intent i = new Intent(Intent.ACTION_MAIN); i.addCategory(Intent.CATEGORY_HOME); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(i); //в зависимости от версии оси намертво убиваем приложение if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { finishAndRemoveTask(); } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { finishAffinity(); } else { finish(); } } //System.exit(0); //MainActivity.super.onBackPressed(); } }).create().show(); } /* @Override public void onBackPressed() { startActivity(new Intent(getApplicationContext(),MainActivity.class)); overridePendingTransition(R.anim.fadein,R.anim.fadeout); //Переход с затуханием finish(); }*/ @Override protected void onResume() { super.onResume(); if(!isMyServiceRunning(MyService.class)){ startService(new Intent(this,MyService.class)); } } @Override protected void onRestart() { super.onRestart(); if(!isMyServiceRunning(MyService.class)){ startService(new Intent(this,MyService.class)); } } @Override protected void onStop() { super.onStop(); if(!isMyServiceRunning(MyService.class)){ startService(new Intent(this,MyService.class)); } } @Override protected void onDestroy() { super.onDestroy(); if(!isMyServiceRunning(MyService.class)){ startService(new Intent(this,MyService.class)); } } } 

Update: read about Android-Job and did not understand how to use it for my case.

There are no Russian sources in this library.

who used, help me for my example, write code using Android-Job!

  • 2
    Go to the JobService and Job'es in general, AlarmManager is not a very reliable thing. In the 8m android services generally turned into a pumpkin. B so as not to write your bike for different versions of android, immediately take github.com/evernote/android-job - Yura Ivanov
  • Than the AlarmManager is not reliable? For the JobService only works with Android 5.0, and I need with 4.0 - shcherbuk
  • 2
    In the evernote, they thought about this api14 +:
  • @YuraIvanov please tell us the principle of this library. How does it work? Does it replace the Service or how can it work when the application is turned off? - shcherbuk
  • You just need to read about jobs in Android and how energy saving works in new api (doze mode ...). Practically everything that was written for the earlier versions needs to be redone. The library, depending on the android on the device, uses the most suitable option for performing background tasks, starting with the alarm manager for old api and job for new ones, so you do not need to think about where to use AM or JS or Firebase and so on ... - Yura Ivanov

1 answer 1

There is such a small trick - to make the service a "foreground service." Those. start writing in the notification line. Together with AlarmManager, you can make an "almost" unkillable service (But this is not a 100% option for Android 8+).

Here is a description of how services work.

I will give an example from Android Developer (here they are asking, links may become irrelevant):

 Notification notification = new Notification(R.drawable.icon,getText(R.string.ticker_text), System.currentTimeMillis()); Intent notificationIntent = new Intent(this, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent); startForeground(ONGOING_NOTIFICATION_ID, notification); 

You can also try JobSheduler. An example from a habr. I will not throw the code, a lot of it.

So for Android <5 can be done on a regular service, and for 5 <on JobSheduler.

  • foreground does not fit. I have already tried AlarmManager with BroadcastReceiver, but the first one also works only time, and then, with the times, stops working, if you do not run the application - shcherbuk
  • @shchrbuk, what have you tried? On dev-4.4--7.0 everything worked well for me. Are you sure that the service gets up due to memory cuts? Override onTrimMemory or onTaskRemoved methods - MrBin
  • Could you write a complete example of your code? - shcherbuk
  • @shcherbuk, Here , + I had a stream on it with a suspended Broadcast. True, this was my first project, so I would rewrite a lot myself, do not look at it. - MrBin
  • so you are doing through the foreground, but I do not need an eternal notification that the curtain was - shcherbuk