Использование службы для запуска фона и создания уведомлений

Я хочу, чтобы мое приложение запускало службу, когда нажимается кнопка, и служба должна работать в фоновом режиме, чтобы показать уведомление в определенное время суток. Для этого у меня есть следующий код. Но он показывает ошибки, которые я не понимаю. Я новичок в Android, и это мое первое приложение, использующее Service. Любая помощь будет оценена по достоинству. Заранее спасибо.

AndroidManifest.xml

               

CreateNotificationActiviy.java

 package com.example.newtrial; import android.os.Bundle; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Intent; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class CreateNotificationActiviy extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.create_notification_activiy); Button b=(Button)findViewById(R.id.button1); b.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub startService(new Intent(CreateNotificationActiviy.this, UpdaterServiceManager.class)); } }); } public void createNotification(View view) { // Prepare intent which is triggered if the // notification is selected Intent intent = new Intent(this, ResultActivity.class); PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0); // Build notification // Actions are just fake Notification noti = new Notification.Builder(this) .setContentTitle("Notification Title") .setContentText("Click here to read").setSmallIcon(R.drawable.ic_launcher) .setContentIntent(pIntent) .build(); NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // hide the notification after its selected noti.flags |= Notification.FLAG_AUTO_CANCEL; notificationManager.notify(0, noti); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.create_notification_activiy, menu); return true; } } 

UpdaterServiceManager.java

 package com.example.newtrial; import java.util.Calendar; import java.util.Timer; import java.util.TimerTask; import android.app.AlertDialog; 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.os.IBinder; import android.util.Log; import android.view.View; public class UpdaterServiceManager extends Service { private final int UPDATE_INTERVAL = 60 * 1000; private Timer timer = new Timer(); private static final int NOTIFICATION_EX = 1; private NotificationManager notificationManager; CreateNotificationActiviy not; public UpdaterServiceManager() { not=new CreateNotificationActiviy(); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // code to execute when the service is first created super.onCreate(); Log.i("MyService", "Service Started."); showNotification(); } public void showNotification() { final Calendar cld = Calendar.getInstance(); int time = cld.get(Calendar.HOUR_OF_DAY); if(time>12) { not.createNotification(null); } else { AlertDialog.Builder alert=new AlertDialog.Builder(this); alert.setMessage("Not yet"); alert.setTitle("Error"); alert.setPositiveButton("OK", null); alert.create().show(); } } @Override public void onDestroy() { if (timer != null) { timer.cancel(); } } @Override public int onStartCommand(Intent intent, int flags, int startid) { return START_STICKY; } private void stopService() { if (timer != null) timer.cancel(); } } 

ResultActivity.java

 package com.example.newtrial; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.widget.TextView; public class ResultActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_result); TextView tv=(TextView)findViewById(R.id.textView1); tv.setText("After notification is clicked" ); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.result, menu); return true; } } 

Logcat

 12-10 12:14:04.286: I/Process(872): Sending signal. PID: 872 SIG: 9 12-10 12:14:11.774: I/MyService(893): Service Started. 12-10 12:14:12.094: D/AndroidRuntime(893): Shutting down VM 12-10 12:14:12.094: W/dalvikvm(893): threadid=1: thread exiting with uncaught exception (group=0x414c4700) 12-10 12:14:12.124: E/AndroidRuntime(893): FATAL EXCEPTION: main 12-10 12:14:12.124: E/AndroidRuntime(893): java.lang.RuntimeException: Unable to create service com.example.newtrial.UpdaterServiceManager: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application 12-10 12:14:12.124: E/AndroidRuntime(893): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2587) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.app.ActivityThread.access$1600(ActivityThread.java:141) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1338) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.os.Handler.dispatchMessage(Handler.java:99) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.os.Looper.loop(Looper.java:137) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.app.ActivityThread.main(ActivityThread.java:5103) 12-10 12:14:12.124: E/AndroidRuntime(893): at java.lang.reflect.Method.invokeNative(Native Method) 12-10 12:14:12.124: E/AndroidRuntime(893): at java.lang.reflect.Method.invoke(Method.java:525) 12-10 12:14:12.124: E/AndroidRuntime(893): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 12-10 12:14:12.124: E/AndroidRuntime(893): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 12-10 12:14:12.124: E/AndroidRuntime(893): at dalvik.system.NativeStart.main(Native Method) 12-10 12:14:12.124: E/AndroidRuntime(893): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application 12-10 12:14:12.124: E/AndroidRuntime(893): at android.view.ViewRootImpl.setView(ViewRootImpl.java:563) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:269) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.app.Dialog.show(Dialog.java:281) 12-10 12:14:12.124: E/AndroidRuntime(893): at com.example.newtrial.UpdaterServiceManager.showNotification(UpdaterServiceManager.java:65) 12-10 12:14:12.124: E/AndroidRuntime(893): at com.example.newtrial.UpdaterServiceManager.onCreate(UpdaterServiceManager.java:41) 12-10 12:14:12.124: E/AndroidRuntime(893): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2577) 12-10 12:14:12.124: E/AndroidRuntime(893): ... 10 more 

Вопрос относительно старый, но я надеюсь, что этот пост все же может иметь значение для других.

TL; DR: используйте AlarmManager для планирования задачи, используйте IntentService, см. Здесь пример кода;

Что это за тест-приложение (и инструкция):

Простое приложение helloworld, которое отправляет вам уведомление каждые 2 часа. Нажатие на уведомление – открывает вторичную активность в приложении; удаление дорожек уведомлений.

Когда вы его используете:

Как только вам нужно выполнить определенную задачу по расписанию. Мой собственный случай: один раз в день я хочу получать новый контент с сервера, составлять уведомление на основе содержимого, которое я получил, и показывать его пользователю.

Что делать:

  1. Во-первых, давайте создадим 2 действия: MainActivity, которая запускает службу уведомлений и NotificationActivity, которая будет запущена путем нажатия уведомления:

    activity_main.xml

         

    MainActivity.java

     public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onSendNotificationsButtonClick(View view) { NotificationEventReceiver.setupAlarm(getApplicationContext()); } } 

    и NotificationActivity – любая случайная деятельность, которую вы можете придумать. NB! Не забудьте добавить оба действия в AndroidManifest.

  2. Затем давайте создадим приемник WakefulBroadcastReceiver , я назвал NotificationEventReceiver в коде выше.

    Здесь мы будем настраивать AlarmManager для PendingIntent каждые 2 часа (или с любой другой частотой) и указывать обработанные действия для этого намерения в onReceive() . В нашем случае – активируйте IntentService , который мы укажем в последующих шагах. Этот IntentService будет генерировать уведомления для нас.

    Кроме того, этот приемник будет содержать некоторые вспомогательные методы, такие как создание PendintIntents, которые мы будем использовать позже

    NB1! Поскольку я использую WakefulBroadcastReceiver , мне нужно добавить дополнительное разрешение в мой манифест:

    NB2! Я использую его в бодрствовавшей версии широковещательного приемника, так как хочу, чтобы устройство не возвращалось спать во время моей работы IntentService . В привет-мире это не так важно (у нас нет долговременной работы на нашем сервисе, но представьте себе, если вам нужно извлечь некоторые относительно огромные файлы с сервера во время этой операции). Узнайте больше об устройстве Awake здесь .

    NotificationEventReceiver.java

     public class NotificationEventReceiver extends WakefulBroadcastReceiver { private static final String ACTION_START_NOTIFICATION_SERVICE = "ACTION_START_NOTIFICATION_SERVICE"; private static final String ACTION_DELETE_NOTIFICATION = "ACTION_DELETE_NOTIFICATION"; private static final int NOTIFICATIONS_INTERVAL_IN_HOURS = 2; public static void setupAlarm(Context context) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent alarmIntent = getStartPendingIntent(context); alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, getTriggerAt(new Date()), NOTIFICATIONS_INTERVAL_IN_HOURS * AlarmManager.INTERVAL_HOUR, alarmIntent); } @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Intent serviceIntent = null; if (ACTION_START_NOTIFICATION_SERVICE.equals(action)) { Log.i(getClass().getSimpleName(), "onReceive from alarm, starting notification service"); serviceIntent = NotificationIntentService.createIntentStartNotificationService(context); } else if (ACTION_DELETE_NOTIFICATION.equals(action)) { Log.i(getClass().getSimpleName(), "onReceive delete notification action, starting notification service to handle delete"); serviceIntent = NotificationIntentService.createIntentDeleteNotification(context); } if (serviceIntent != null) { startWakefulService(context, serviceIntent); } } private static long getTriggerAt(Date now) { Calendar calendar = Calendar.getInstance(); calendar.setTime(now); //calendar.add(Calendar.HOUR, NOTIFICATIONS_INTERVAL_IN_HOURS); return calendar.getTimeInMillis(); } private static PendingIntent getStartPendingIntent(Context context) { Intent intent = new Intent(context, NotificationEventReceiver.class); intent.setAction(ACTION_START_NOTIFICATION_SERVICE); return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } public static PendingIntent getDeleteIntent(Context context) { Intent intent = new Intent(context, NotificationEventReceiver.class); intent.setAction(ACTION_DELETE_NOTIFICATION); return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } } 
  3. Теперь давайте создадим IntentService для создания уведомлений.

    Там мы указываем onHandleIntent() который является ответом на намерение NotificationEventReceiver , которое мы передали в методе startWakefulService .

    Если это действие «Удалить» – мы можем его зарегистрировать в нашей аналитике, например. Если это намерение «Начать уведомление», то с помощью NotificationCompat.Builder мы создаем новое уведомление и показываем его NotificationManager.notify . При составлении уведомления мы также устанавливаем ожидающие намерения для кликов и удаления действий. Довольно легко.

    NotificationIntentService.java

     public class NotificationIntentService extends IntentService { private static final int NOTIFICATION_ID = 1; private static final String ACTION_START = "ACTION_START"; private static final String ACTION_DELETE = "ACTION_DELETE"; public NotificationIntentService() { super(NotificationIntentService.class.getSimpleName()); } public static Intent createIntentStartNotificationService(Context context) { Intent intent = new Intent(context, NotificationIntentService.class); intent.setAction(ACTION_START); return intent; } public static Intent createIntentDeleteNotification(Context context) { Intent intent = new Intent(context, NotificationIntentService.class); intent.setAction(ACTION_DELETE); return intent; } @Override protected void onHandleIntent(Intent intent) { Log.d(getClass().getSimpleName(), "onHandleIntent, started handling a notification event"); try { String action = intent.getAction(); if (ACTION_START.equals(action)) { processStartNotification(); } if (ACTION_DELETE.equals(action)) { processDeleteNotification(intent); } } finally { WakefulBroadcastReceiver.completeWakefulIntent(intent); } } private void processDeleteNotification(Intent intent) { // Log something? } private void processStartNotification() { // Do something. For example, fetch fresh data from backend to create a rich notification? final NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setContentTitle("Scheduled Notification") .setAutoCancel(true) .setColor(getResources().getColor(R.color.colorAccent)) .setContentText("This notification has been triggered by Notification Service") .setSmallIcon(R.drawable.notification_icon); PendingIntent pendingIntent = PendingIntent.getActivity(this, NOTIFICATION_ID, new Intent(this, NotificationActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent); builder.setDeleteIntent(NotificationEventReceiver.getDeleteIntent(this)); final NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(NOTIFICATION_ID, builder.build()); } } 
  4. Почти готово. Теперь я также добавляю широковещательный приемник для событий BOOT_COMPLETED, TIMEZONE_CHANGED и TIME_SET, чтобы переустановить мой AlarmManager, как только устройство было перезагружено или изменился часовой пояс (например, пользователь перелетел из США в Европу, и вы не хотите, чтобы уведомление всплывало в середине ночи, но был липким по местному времени :-)).

    NotificationServiceStarterReceiver.java

     public final class NotificationServiceStarterReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { NotificationEventReceiver.setupAlarm(context); } } 
  5. Мы также должны зарегистрировать все наши услуги, широковещательные приемники в AndroidManifest:

                              

Это оно!

Исходный код этого проекта вы можете найти здесь . Надеюсь, вы найдете эту статью полезной.

Ваша ошибка в UpdaterServiceManager в методе onCreate и showNotification.

Вы пытаетесь показать notification из Service using Activity Context . В то время как у Every Service has its own Context, просто используйте это. Вам не нужно pass a Service an Activity's Context. Я не понимаю, зачем вам нужен конкретный Activity's Context to show Notification.

Поместите свой метод createNotification в UpdateServiceManager.class . И удалите CreateNotificationActivity, а не службу.

Вы не можете отобразить окно / диалог приложения через контекст, который не является активностью. Попробуйте передать действительную ссылку на действительность

  • Как всегда запускать службу в фоновом режиме?
  • Служба Android должна запускаться всегда (никогда не останавливать или останавливать)
  • SpeechRecognizer вызывает ANR ... Мне нужна помощь с Android-речевым API
  • Уведомление Push неправильно работает, когда приложение находится в фоновом режиме или не работает
  • Как перезапустить службу после того, как приложение было убито из недавних задач
  • Попытка запуска службы при загрузке на Android
  • Как сохранить фон соединения Bluetooth?
  • Android onCreate или onStartCommand для запуска службы
  • Как создать активность и службу Android, которые используют отдельные процессы
  • .aspx vs .ashx ОСНОВНАЯ разница
  • Сервис против IntentService
  • Interesting Posts

    Чтение iphone app sms

    Как использовать SSH для запуска сценария оболочки на удаленной машине?

    Когда я должен действительно использовать noexcept?

    Несколько параметров для селектора jQuery?

    Какой стиль комментариев следует использовать в пакетных файлах?

    Как открыть веб-браузер по умолчанию с помощью java

    Как сравнить перечисление со связанными значениями, игнорируя его связанное значение в Swift?

    использование статических библиотек вместо динамических библиотек в opencv

    Что это значит, когда диски DVD-RW только считывают компакт-диски?

    Примитивный тип «короткий» – литье в Java

    Невозможно вставить gnome-терминал из Keepas2, запущенного через моно

    Подчеркивание текста в UIButton

    Ярлык для минимизации всех окон на OS X

    Насколько быстрее память обычно, чем диск?

    Сообщение об ошибке «Не удается установить или запустить приложение. Для приложения требуется stdole Version 7.0.3300.0 в GAC “

    Давайте будем гением компьютера.