I know than this bug was commented in other blogs but I've tried to correct this and I did not succeed.
Only happend in android 8+, but in simulator of Android Studio works fine.
I have an app than activate a notification in some specific date, this notification remember some task for user. This works fine in android 7 or lower but in Android 8+ don't works. App works fine, but notification don't appear and in google Play is activated an ERROR.
My app never crash, only shows that error into Google Play console.
This is the bug in PlayStore Console:
java.lang.RuntimeException:
at android.app.ActivityThread.handleReceiver (ActivityThread.java:3606)
at android.app.ActivityThread.access$1300 (ActivityThread.java:237)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1796)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:214)
at android.app.ActivityThread.main (ActivityThread.java:7045)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:964)
Caused by: java.lang.IllegalStateException:
at android.app.ContextImpl.startServiceCommon (ContextImpl.java:1666)
at android.app.ContextImpl.startService (ContextImpl.java:1611)
at android.content.ContextWrapper.startService (ContextWrapper.java:677)
at android.content.ContextWrapper.startService (ContextWrapper.java:677)
at com.example.tomas.memoru.R_Activate.onReceive (R_Activate.java:45)
at android.app.ActivityThread.handleReceiver (ActivityThread.java:3597)
And this is my source code:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tomas.memoru" >
<permission android:name="com.example.tomas.memoru.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:name="com.example.tomas.memoru.R_Variables1"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar" >
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<receiver
android:name=".R_Activate">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name="com.example.tomas.memoru.R_Activate_generador" />
<service android:name="com.example.tomas.memoru.GcmIntentService" />
<receiver android:name="com.example.tomas.memoru.R_NotificationPublisher" />
<activity
android:name="com.example.tomas.memoru.R_Pantalla_Main"
android:screenOrientation="portrait"
android:configChanges="orientation|screenSize"
android:launchMode="singleInstance"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
R_Activate.java
package com.example.tomas.memoru;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.util.ArrayList;
public class R_Activate extends BroadcastReceiver {
Integer cont1 = 0;
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
intent = new Intent(context,R_Activate_generador.class);
context.startService(intent);
Log.i("Autostart", "started");
}
}
}
R_Activate_generator.java
package com.example.tomas.memoru;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.IBinder;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
public class R_Activate_generador extends Service {
ArrayList<String> task_cargar = new ArrayList<>();
Integer cont1=0;
static final int READ_BLOCK_SIZE = 100;
private static final String TAG = "MyService";
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
@Override
public void onStart(Intent intent, int startid) {
cargadatosfile(); //this works fine, only charge information to check date and tasks
if(cont1>0){
scheduleNotification(getNotification("30 second delay"), 0);//this put notification
}
}
private void cargadatosfile() {
//this function works fine, only charge information to schedule the tasks
}
private void scheduleNotification(Notification notification, int delay) {
R_Variables1 comparteVariables = ((R_Variables1) getApplicationContext());
String s = "";
Integer temp_id = 0, masXdias=0;
String[] strValues_temp1;
Calendar today = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
cont1 = 0;
while (cont1 < task_cargar.size()) {
strValues_temp1 = task_cargar.get(cont1).split(";");
String[] strValues_time1 = strValues_temp1[11].split(" ");
String[] strValues_time2 = strValues_time1[1].split(":");
String[] strValues_date1 = strValues_time1[0].split("-");
Calendar cal = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
cal.set(Calendar.DATE, Integer.valueOf(strValues_date1[2]) + masXdias); //1-31
cal.set(Calendar.MONTH, Integer.valueOf(strValues_date1[1]) - 1); //first month is 0!!! January is zero!!!
cal.set(Calendar.YEAR, Integer.valueOf(strValues_date1[0]));//year...
cal.set(Calendar.HOUR_OF_DAY, Integer.valueOf(strValues_time2[0])); //HOUR
cal.set(Calendar.MINUTE, Integer.valueOf(strValues_time2[1])); //MIN
cal.set(Calendar.SECOND, 0); //SEC
if (cal.after(today) ) {//fecha futura es la de File
Intent notificationIntent = new Intent(this, R_NotificationPublisher.class);
notificationIntent.putExtra(R_NotificationPublisher.NOTIFICATION_ID, Integer.valueOf(strValues_temp1[0]));// se reemplazo 1 por max_id
// notificationIntent.putExtra(R_NotificationPublisher.NOTIFICATION, notification);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, Integer.valueOf(strValues_temp1[0]), notificationIntent, PendingIntent.FLAG_ONE_SHOT);//FLAG_UPDATE_CURRENT // se reemplazo 0 por max_id
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if(Build.VERSION.SDK_INT < 23){
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
}
else{
alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(cal.getTimeInMillis(), pendingIntent), pendingIntent);
}
masXdias=0;
cont1++;
}
else{
masXdias=masXdias+1;
}
}
}
private Notification getNotification(String content) {
Notification.Builder builder = new Notification.Builder(this);
builder.setContentTitle("Scheduled Notification");
builder.setContentText(content);
builder.setSmallIcon(getNotificationIcon());
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.movando2_xx));
builder.setAutoCancel(true);
return builder.build();
}
private int getNotificationIcon() {
boolean useWhiteIcon = (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP);
return useWhiteIcon ? R.drawable.movando2_xxbl : R.drawable.movando2_xx;
}
}
There are other java modules in my application, but the bug is in somewhere place of these code.
Thank you very much for your help, any hint and feedback is appreciated!.
Edwin