我正在使用调用REST API的后台服务,并在获取数据后将其发送给用户本地通知,但我在android 9中遇到了Service.startForeground()的问题。请查看代码并为我提供帮助。
NotificationEventReceiver类
public class NotificationEventReceiver extends BroadcastReceiver
{
static AlarmManager alarmManager;
static PendingIntent pendingIntent;
static int count=0;
static Context mcon;
public static void setupAlarm(Context context) {
mcon=context;
enableBootReciever();
AppSession.put(Constants.SERVICE_CALL,1);
Intent service = new Intent(context, NotificationEventReceiver.class);
service.setAction("Start");
pendingIntent = PendingIntent.getBroadcast(context, 0, service, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.setTime(new Date());
System.out.println("Log: In the Notification Event Receiver");
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
10800*1000,
pendingIntent);
}
public static void disableAlarm(Context context) {
if (alarmManager!=null)
alarmManager.cancel(pendingIntent);
}
static void enableBootReciever(){
ComponentName receiver = new ComponentName(mcon, NotificationServiceStarterReceiver.class);
mcon.getPackageManager().setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals("Start")) {
//Log.d("asdkl",Integer.toString(count));
Intent i = new Intent(context, Service.class);
//context.startService(i);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(i);
} else {
context.startService(i);
}
}}}
NotificationServiceStarterReceiver类
public final class NotificationServiceStarterReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
NotificationEventReceiver.setupAlarm(context);
System.out.print("Log: In the Notification Service Starter Receiver");
}}
服务等级
public class Service extends IntentService {
String CHANNEL_ID = "999";
private static String CHANNEL_NAME="My Channel";
private static String CHANNEL_DESCRIPTION="My Channel Description";
public Service() {
super(Service.class.getSimpleName());
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
StartListening(getApplicationContext());
}
@Override
public void onCreate() {
super.onCreate();
System.out.print("Log: In the Service");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
createNotification();
}else{
this.startForeground(1,new Notification());
}
//getApplicationContext().startForeground(1,new Notification());
}
private void createNotification()
{
createNotificationChannel();
Bitmap largeIcon = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.ic_launcher);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("fromNotification", true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
ShortcutBadger.applyCount(getApplicationContext(), AppSession.getInt(Constants.NOTIFICATION_COUNT));
}
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setContentTitle("Scheduled Notification")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Quiz Alert")
.setContentText("A New Quiz has been scheduled on " + AppSession.get(Constants.QUIZ_DATE_TIME) + ". Kindly don't forget to Join.")
.setChannelId(CHANNEL_ID)
.setLargeIcon(largeIcon)
.setNumber(AppSession.getInt(Constants.NOTIFICATION_COUNT))
.setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL)
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000})
.setAutoCancel(true)
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
.setColor(getResources().getColor(R.color.colorAccent))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setStyle(new NotificationCompat.BigTextStyle().bigText("A New Quiz has been scheduled on " + AppSession.get(Constants.QUIZ_DATE_TIME) + ". Kindly don't forget to Join."))
.setGroup("TEST");
final NotificationManagerCompat manager = NotificationManagerCompat.from(this);
manager.notify(2, builder.build());
}
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(CHANNEL_DESCRIPTION);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
}
@Override
public void onDestroy() {
super.onDestroy();
this.stopSelf();
}
public void StartListening(final Context mcontext) {
Log.d("In StartListening",("Listening " + Integer.toString(count)));
System.out.println("In StartListening " + Integer.toString(count));
// Toast.makeText(mcontext, "In StartListening", Toast.LENGTH_SHORT).show();
new RestCaller(new iResponseHandler() {
@Override
public void onSuccess(Call call, Response response, int reqCode) {
if (reqCode == Constants.REQUEST_CODE_QUIZ_DATE) {
AppSession.put(Constants.KEY_API_CALL,0);
QuizDatePOJO quizDatePojo = (QuizDatePOJO) response.body();
if(quizDatePojo.getResponse().getDate()==null){
}else{
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
SimpleDateFormat outputFormat = new SimpleDateFormat("dd-MM-yyyy");
Date date = null;
try {
date = inputFormat.parse(quizDatePojo.getResponse().getDate());
} catch (ParseException e) {
e.printStackTrace();
}
String formattedDate = outputFormat.format(date);
String time =quizDatePojo.getResponse().getTime();
AppSession.put(Constants.QUIZ_DATE_TIME,formattedDate+" "+time);
createNotification();
}
}
}
@Override
public void onFailure(Call call, Response response, int reqCode) {
AppSession.put(Constants.KEY_API_CALL,"FAILED");
StartListening(mcontext);
Loading.cancel();
}
@Override
public void onApiCrash(Call call, Throwable t, int reqCode) {
AppSession.put(Constants.KEY_API_CALL,"FAILED");
StartListening(mcontext);
Loading.cancel();
}
}, MainApplication.getRestClient()
.getApiServices().getQuizDate(), Constants.REQUEST_CODE_QUIZ_DATE);
}}
请在此处指导需要进行哪些更改。此问题在Android 9中出现,并且通知弹出后,应用就会崩溃
日志致命异常:android.app.RemoteServiceException:Context.startForegroundService()然后未调用Service.startForeground():ServiceRecord {a341388 u0 com.developer.emten / .services.Service}在android.app.ActivityThread $ H.handleMessage + 2112(ActivityThread.java:2112)在android.os.Handler.dispatchMessage + 112(Handler.java:112)在android.os.Looper.loop + 216(Looper.java:216)在android.app.ActivityThread.main + 7593(ActivityThread.java:7593)在java.lang.reflect.Method.invoke(Method.java)在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run + 524(RuntimeInit.java:524)在com.android.internal.os.ZygoteInit.main + 987(ZygoteInit.java:987)
<manifest ...>
...
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
...
<application ...>
...
</manifest>