关闭应用程序时,服务意图崩溃

时间:2016-12-24 17:50:55

标签: java android android-service

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());
    }
}

这是我的代码,我试图让它在特定时间发送通知。这个代码似乎在我的应用程序运行时起作用,但是一旦我关闭应用程序(点击小方块并轻扫应用程序),服务强制关闭。任何想法为什么会这样?

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 com.example.danny.schoolassist.RSSPullService@8acbb1e 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;
}

1 个答案:

答案 0 :(得分:0)

您将从START_STICKY返回onStartCommand()。这告诉Android“嘿,如果你出于某种原因终止了我的流程,请稍后重启,并再次致电onStartCommand()

然而,它不会做的是给你旧的Intent。您将null获得Intent

使用Intent将数据传递到服务适用于非粘性服务,或作为粘性服务的优化。但是,粘性服务需要能够独立运行,因为您要求它是独立重新创建的。您当前通过Intent传递的数据需要保留(数据库,SharedPreferences或其他类型的文件),以便粘性服务即使没有{{{}也可以获取该数据1}}使用。

但总的来说,拥有像这样的永久服务通常被认为是Android中的反模式。在您的特定情况下,它将无法正常工作,因为当设备处于睡眠状态时 - 通常移动设备在大多数时间处于浩大的睡眠状态 - 您将失去“在特定时间发送通知”的能力次”。