2016-12-24 8 views
-1
public class RSSPullService extends Service { 

private ArrayList<String> stringArrayList; 
private int i = 0; 

@Nullable 
@Override 
public IBinder onBind(Intent intent) { 
    return null; 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    stringArrayList = intent.getStringArrayListExtra("Array"); 
    final Calendar[] calendars = getCalendars(); 

    final Handler handler = new Handler(); 
    Thread thread = new Thread() { 
     @Override 
     public void run() { 
      try { 
       while(true) { 
        Calendar calendar = Calendar.getInstance(); 
        if ((calendar.get(Calendar.MINUTE) + 
          calendar.get(Calendar.HOUR_OF_DAY) * 60) 
          == (calendars[i].get(Calendar.MINUTE) + 
          calendars[i].get(Calendar.HOUR_OF_DAY) * 60)) 
        { 
         setNotification(stringArrayList.get(i)); 
         i++; 
        } 
        sleep(60000); 
        handler.post(this); 
       } 
      } 
      catch (InterruptedException e) {e.printStackTrace();} 
     } 
    }; 

    thread.start(); 
    return START_STICKY; 
} 

private Calendar[] getCalendars() { 
    int[] nums = lessonNum(); int len = nums.length; 
    Calendar[] calendars = new Calendar[len]; 
    for (int i = 0; i < len; i++) 
     calendars[i] = setCalendar(nums[i]); 
    return calendars; 
} 

private Calendar setCalendar(int i) { 
    Calendar calendar = Calendar.getInstance(); 
    switch (i) { 
     case 0: 
      calHelper(calendar, 6, 0); 
      break; 
     case 1: 
      calHelper(calendar, 7, 0); 
      break; 
     case 2: 
      calHelper(calendar, 8, 0); 
      break; 
     case 3: 
      calHelper(calendar, 8, 55); 
      break; 
     case 4: 
      calHelper(calendar, 9, 50); 
      break; 
     case 5: 
      calHelper(calendar, 10, 55); 
      break; 
     case 6: 
      calHelper(calendar, 11, 50); 
      break; 
     case 7: 
      calHelper(calendar, 12, 45); 
      break; 
     case 8: 
      calHelper(calendar, 13, 40); 
      break; 
     case 9: 
      calHelper(calendar, 14, 25); 
      break; 
     case 10: 
      calHelper(calendar, 15, 15); 
      break; 
     default: 
      calHelper(calendar, 0, 0); 
      break; 
    } 
    return calendar; 
} 

private void calHelper(Calendar calendar, int hour, int minute) { 
    calendar.set(Calendar.HOUR_OF_DAY, hour); 
    calendar.set(Calendar.MINUTE, minute); 
} 

private int[] lessonNum() { 
    int size = stringArrayList.size(); 
    int[] nums = new int[size]; 
    for (int i = 0; i < size; i++) 
     nums[i] = Integer.parseInt(stringArrayList.get(i).substring(0,1)); 
    return nums; 
} 

private void setNotification(String s) { 
    Notification.Builder builder = new Notification.Builder(this); 
    builder.setContentTitle(getResources().getString(R.string.next)); 
    builder.setContentText(s); 
    builder.setSmallIcon(R.drawable.notify); 

    NotificationManager notificationManager = 
      (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
     notificationManager.notify(325, builder.build()); 
    } 
} 

Это мой код, я пытаюсь отправить ему уведомление в определенное время. Этот код, похоже, работает, когда мое приложение запущено, но как только я закрою приложение (щелкните по маленькому квадрату и проведите по экрану приложение), сервисная сила закрывается. Любые идеи, почему это происходит?Служба Intent падает, когда я закрываю приложение

Edit1:

12-24 20:40:04.008 9063-9063/? E/AndroidRuntime: FATAL EXCEPTION: main 
               Process: com.example.danny.schoolassist, PID: 9063 
               java.lang.RuntimeException: Unable to start service [email protected] with null: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.ArrayList android.content.Intent.getStringArrayListExtra(java.lang.String)' on a null object reference 
                at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3343) 
                at android.app.ActivityThread.-wrap21(ActivityThread.java) 
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1582) 
                at android.os.Handler.dispatchMessage(Handler.java:102) 
                at android.os.Looper.loop(Looper.java:154) 
                at android.app.ActivityThread.main(ActivityThread.java:6119) 
                at java.lang.reflect.Method.invoke(Native Method) 
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
                Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.ArrayList android.content.Intent.getStringArrayListExtra(java.lang.String)' on a null object reference 
                at com.example.danny.schoolassist.RSSPullService.onStartCommand(RSSPullService.java:28) 
                at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3326) 
                at android.app.ActivityThread.-wrap21(ActivityThread.java)  
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1582)  
                at android.os.Handler.dispatchMessage(Handler.java:102)  
                at android.os.Looper.loop(Looper.java:154)  
                at android.app.ActivityThread.main(ActivityThread.java:6119)  
                at java.lang.reflect.Method.invoke(Native Method)  
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)  
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)  

я запустить службу, как так:

protected void onCreate(Bundle savedInstanceState) { 
... 
Intent mServiceIntent = new Intent(this, RSSPullService.class); 
mServiceIntent.putExtra("Array", staticArrayList); 
if (!isServiceRunning(RSSPullService.class)) startService(mServiceIntent); 
} 

private boolean isServiceRunning(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; 
} 
+0

[Только сервис работает, когда он активно доставляет ценность пользователю] (https://commonsware.com/blog/2014/07/27/role-services.html). Наблюдение за тиканием часов не доставляет потребителю значительную ценность. Используйте 'AlarmManager' или' JobScheduler', чтобы организовать контроль в фоновом режиме на периодической основе. Кроме того, [используйте LogCat для проверки трассировки стека Java, связанной с вашим сбоем] (https://stackoverflow.com/questions/23353173/unappro-myapp-has-stopped-how-can-i-solve-this). – CommonsWare

+0

Я не знаю о JobScheduler, но AlarmManager требует интервала для работы. Времена, которые я использую, несовместимы, поэтому было бы проблематично использовать их с AlarmManger –

+0

«AlarmManager требует интервал для работы с» - не больше, чем ваш текущий код. Вызовите 'set()' или 'setExact()' для ближайшего события (в хронологическом порядке). Когда вы обрабатываете это событие, помимо всего, что вы делаете, вызывайте 'set()' или 'setExact()' для планирования следующего ближайшего события. – CommonsWare

ответ

0

Вы возвращаетесь START_STICKY из onStartCommand(). Это говорит Android «эй, если по какой-то причине вы прекратите мой процесс, перезагрузите его когда-нибудь в ближайшее время и снова вызовите onStartCommand()».

Однако, что бы он не сделал, это дать вам свой старый Intent назад. Вы получите null за это Intent.

Использование Intent для передачи данных в службу отлично подходит для нелипких услуг или для оптимизации для липких сервисов. Тем не менее, липкая услуга должна работать независимо, так как вы просите ее повторно создавать самостоятельно. Данные, которые вы сейчас проходите через этот Intent, должны быть сохранены (база данных, SharedPreferences или другой вид файла), чтобы липкая услуга могла получить эти данные, даже если нет Intent для работы.

Но, в целом, наличие вечного обслуживания, подобного этому, как правило, считается анти-шаблоном в Android. В вашем конкретном случае это не сработает, так как когда устройство засыпает —, и обычно мобильное устройство спит огромным в большинстве случаев — вы теряете возможность «отправлять уведомление в определенное время».

+0

Спасибо! Вы очень помогли! –

Смежные вопросы