关闭应用程序时服务意图崩溃
Service Intent crashes when I close the app
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());
}
}
这是我的代码,我试图让它在特定时间发送通知。当我的应用程序处于 运行ning 时,此代码似乎有效,但是一旦我关闭应用程序(单击小方块并将应用程序滑开),服务就会强制关闭。知道为什么会这样吗?
编辑1:
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;
}
您将从 onStartCommand()
返回 START_STICKY
。这告诉 Android "hey, if you terminate my process for some reason, please restart it sometime soonish, and call onStartCommand()
again".
然而,它不会做的就是把你原来的 Intent
还给你。 Intent
.
你会得到 null
使用 Intent
将数据传递给服务对于非粘性服务很好,或者作为对粘性服务的优化。但是,粘性服务需要能够独立运行,因为您要求它独立重新创建。您目前通过 Intent
传递的数据需要持久化(数据库、SharedPreferences
或其他类型的文件),这样即使没有 Intent
一起工作。
但是,总的来说,像这样的永久服务通常被认为是 Android 中的反模式。在您的具体情况下,它不会很好地工作,因为当设备睡着时 - 通常移动设备在 大量 大部分时间都处于睡眠状态 - 你失去了 "send a notification at specific times".
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());
}
}
这是我的代码,我试图让它在特定时间发送通知。当我的应用程序处于 运行ning 时,此代码似乎有效,但是一旦我关闭应用程序(单击小方块并将应用程序滑开),服务就会强制关闭。知道为什么会这样吗?
编辑1:
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;
}
您将从 onStartCommand()
返回 START_STICKY
。这告诉 Android "hey, if you terminate my process for some reason, please restart it sometime soonish, and call onStartCommand()
again".
然而,它不会做的就是把你原来的 Intent
还给你。 Intent
.
null
使用 Intent
将数据传递给服务对于非粘性服务很好,或者作为对粘性服务的优化。但是,粘性服务需要能够独立运行,因为您要求它独立重新创建。您目前通过 Intent
传递的数据需要持久化(数据库、SharedPreferences
或其他类型的文件),这样即使没有 Intent
一起工作。
但是,总的来说,像这样的永久服务通常被认为是 Android 中的反模式。在您的具体情况下,它不会很好地工作,因为当设备睡着时 - 通常移动设备在 大量 大部分时间都处于睡眠状态 - 你失去了 "send a notification at specific times".