Android 如果应用关闭,每 15 分钟通知一次崩溃
Android notification every 15 minutes crashes if app is closed
所以我是 Android Studio 的新手,我正在尝试制作一个简单的应用程序来执行以下操作:
该应用程序在 /res/values 文件夹中设置了一个名为 "frases" 的字符串数组。
Main activity 包含一个按钮,当它被按下时,它会递增一个表示要使用的数组索引的变量(我称之为 "iterador")并将 textView 设置为 frases 的值[迭代器].
然后在 MainActivity 的 onCreate 方法上,我有一个带有 setRepeating 的警报,它调用 class 每 15 分钟接收一次通知。这样做的目的是在 MainActivity 中有一个 textview 和一个可以显示 frases[iterador].
值的通知
这里的问题是每当我的应用程序关闭时(不是从 android 设置菜单停止,只是关闭)我收到一条错误消息,指出字符串数组为空。更糟糕的是,在第一次通知之后,如果我没有在我的 phone 中打开应用程序(即使它没有关闭),有时即使在 15 分钟后第二个通知也不会出现。
我试图通过将两个变量设为静态来解决此问题,以便我可以从通知中访问它们 class,但仍然不起作用。
有没有办法解决这个问题,让通知即使在应用程序关闭时也能显示?
我的 MainActivity
变量和 onCreate
方法:
public class MainActivity extends Activity implements View.OnClickListener {
//MY CODE
public static boolean primera; //APP OPENED FOR THE FIRST TIME
private Button b_corazon, b_carta;
private TextView t_frase;
public static final String PREFS_NAME = "MyPrefsFile";
//-------------------------STRING SHOW VARIABLES----------------------
public static String[] frases; //STRING ARRAY
public static int iterador; // INDEX FOR THE ARRAY
AlarmManager alarmManager; //ALARM MANAGER
@Override
protected void onCreate(Bundle savedInstanceState) {
Resources res=getResources(); //GET THE RESOURCES
frases=res.getStringArray(R.array.cartas); //ASIGN THE STRING ARRAY TO THE VARIABLE
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
//MI CODIGO
Intent intent = new Intent(getApplicationContext(), RecibeNotif.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),0,intent,0);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar firing = Calendar.getInstance(); //SCHEDULED TIME
Calendar current = Calendar.getInstance(); //CURRENT TIME
firing.set(Calendar.HOUR_OF_DAY,14);
firing.set(Calendar.MINUTE,20);
firing.set(Calendar.SECOND,0);
long intendedTime=firing.getTimeInMillis(); //SCHEDULED TIME
long currentTime=current.getTimeInMillis(); //CURRENT TIME
if(intendedTime>=currentTime){ //IF IT ISN'T THE TIME YET
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime,AlarmManager.INTERVAL_FIFTEEN_MINUTES,pendingIntent);
}
else{ //IF THE TIME HAS ALREADY PASSED
firing.add(Calendar.MINUTE,15); //ADD 15 MINUTES FOR THE NEXT ALARM
intendedTime=firing.getTimeInMillis();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime,AlarmManager.INTERVAL_FIFTEEN_MINUTES,pendingIntent);
}
//SAVE THE VALUE OF ITERADOR IN THE APPLICATION DATA
SharedPreferences settings = getSharedPreferences(PREFS_NAME,0); //GUARDAR DATO DE ITERADOR
primera=getSharedPreferences("PREFERENCE",MODE_PRIVATE).getBoolean("primera", true);
iterador=settings.getInt("iterador",iterador);
init();
}
我的 BroadcastReceiver
通知 class:
public class RecibeNotif extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String[] frasesaux;
int iteraux;
iteraux=MainActivity.iterador;
frasesaux=MainActivity.frases;
if(iteraux==frasesaux.length){
iteraux=0;
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent redir = new Intent(context,direct.class);
redir.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 100, redir, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.message) //ICONO DE LA NOTIFICACION
.setContentTitle(".////.")
.setContentText(frasesaux[iteraux])
.setAutoCancel(true);
notificationManager.notify(100,builder.build());
}
}
<------------编辑------------>
好的,现在已经修复了,通知效果很好。唯一仍然让我发疯的是如何在通知 class 结束时更新 iterador
的值,使其与 iteraux
.
匹配
到目前为止,我已经尝试使用 SharedPreferences.editor
编辑 iterador
的值,但它似乎不起作用。
有什么想法吗?
public void onReceive(Context context, Intent intent) {
String[] finale;
int iteraux;
SharedPreferences settings = context.getSharedPreferences(PREFS_NAME,0); //GUARDAR DATO DE ITERADOR
iteraux = settings.getInt("iterador",iterador);
Resources res= context.getResources(); //GET THE RESOURCES
finale=res.getStringArray(R.array.cartas); //ASIGN THE STRING ARRAY TO THE VARIABLE
//iteraux=MainActivity.iterador;
if(iteraux==finale.length){
iteraux=0;
}
else{
iteraux++;
}
//<-----------UPDATE ITERADOR VAR IN MAINACTIVITY
SharedPreferences.Editor editor2 = settings.edit();
editor2.putInt("iterador",iteraux);
editor2.commit();
// frasesaux=MainActivity.frases;
当您收到通知时,您的 activity 不是 alive
,因此如果您尝试访问 Activity
的字段而不是 alive
,则会出现异常
解决方案
1.) 使用context
得到getStringArray(R.array.cartas)
2.) 使用相同的 context
从 SharedPreferences
获取数据
public class RecibeNotif extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String[] frasesaux;
int iteraux;
SharedPreferences settings = context.getSharedPreferences("MyPrefsFile",0);
iteraux = settings.getInt("iterador",0);
// ^^ your default value
//iteraux=MainActivity.iterador;
frasesaux=context.getResources().getStringArray(R.array.cartas);
// ^^ fetch the array
if(iteraux==frasesaux.length){
iteraux=0;
}
//...
}
}
注意:static
不会有任何区别,因为你的数组只会在 onCreate
被 android OS 调用时初始化,所以这是并非如此,因此您的 static
字段将保持 un-initialized 表示 null 和 0.
所以我是 Android Studio 的新手,我正在尝试制作一个简单的应用程序来执行以下操作:
该应用程序在 /res/values 文件夹中设置了一个名为 "frases" 的字符串数组。 Main activity 包含一个按钮,当它被按下时,它会递增一个表示要使用的数组索引的变量(我称之为 "iterador")并将 textView 设置为 frases 的值[迭代器].
然后在 MainActivity 的 onCreate 方法上,我有一个带有 setRepeating 的警报,它调用 class 每 15 分钟接收一次通知。这样做的目的是在 MainActivity 中有一个 textview 和一个可以显示 frases[iterador].
值的通知这里的问题是每当我的应用程序关闭时(不是从 android 设置菜单停止,只是关闭)我收到一条错误消息,指出字符串数组为空。更糟糕的是,在第一次通知之后,如果我没有在我的 phone 中打开应用程序(即使它没有关闭),有时即使在 15 分钟后第二个通知也不会出现。
我试图通过将两个变量设为静态来解决此问题,以便我可以从通知中访问它们 class,但仍然不起作用。
有没有办法解决这个问题,让通知即使在应用程序关闭时也能显示?
我的 MainActivity
变量和 onCreate
方法:
public class MainActivity extends Activity implements View.OnClickListener {
//MY CODE
public static boolean primera; //APP OPENED FOR THE FIRST TIME
private Button b_corazon, b_carta;
private TextView t_frase;
public static final String PREFS_NAME = "MyPrefsFile";
//-------------------------STRING SHOW VARIABLES----------------------
public static String[] frases; //STRING ARRAY
public static int iterador; // INDEX FOR THE ARRAY
AlarmManager alarmManager; //ALARM MANAGER
@Override
protected void onCreate(Bundle savedInstanceState) {
Resources res=getResources(); //GET THE RESOURCES
frases=res.getStringArray(R.array.cartas); //ASIGN THE STRING ARRAY TO THE VARIABLE
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
//MI CODIGO
Intent intent = new Intent(getApplicationContext(), RecibeNotif.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),0,intent,0);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar firing = Calendar.getInstance(); //SCHEDULED TIME
Calendar current = Calendar.getInstance(); //CURRENT TIME
firing.set(Calendar.HOUR_OF_DAY,14);
firing.set(Calendar.MINUTE,20);
firing.set(Calendar.SECOND,0);
long intendedTime=firing.getTimeInMillis(); //SCHEDULED TIME
long currentTime=current.getTimeInMillis(); //CURRENT TIME
if(intendedTime>=currentTime){ //IF IT ISN'T THE TIME YET
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime,AlarmManager.INTERVAL_FIFTEEN_MINUTES,pendingIntent);
}
else{ //IF THE TIME HAS ALREADY PASSED
firing.add(Calendar.MINUTE,15); //ADD 15 MINUTES FOR THE NEXT ALARM
intendedTime=firing.getTimeInMillis();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime,AlarmManager.INTERVAL_FIFTEEN_MINUTES,pendingIntent);
}
//SAVE THE VALUE OF ITERADOR IN THE APPLICATION DATA
SharedPreferences settings = getSharedPreferences(PREFS_NAME,0); //GUARDAR DATO DE ITERADOR
primera=getSharedPreferences("PREFERENCE",MODE_PRIVATE).getBoolean("primera", true);
iterador=settings.getInt("iterador",iterador);
init();
}
我的 BroadcastReceiver
通知 class:
public class RecibeNotif extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String[] frasesaux;
int iteraux;
iteraux=MainActivity.iterador;
frasesaux=MainActivity.frases;
if(iteraux==frasesaux.length){
iteraux=0;
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent redir = new Intent(context,direct.class);
redir.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 100, redir, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.message) //ICONO DE LA NOTIFICACION
.setContentTitle(".////.")
.setContentText(frasesaux[iteraux])
.setAutoCancel(true);
notificationManager.notify(100,builder.build());
}
}
<------------编辑------------>
好的,现在已经修复了,通知效果很好。唯一仍然让我发疯的是如何在通知 class 结束时更新 iterador
的值,使其与 iteraux
.
到目前为止,我已经尝试使用 SharedPreferences.editor
编辑 iterador
的值,但它似乎不起作用。
有什么想法吗?
public void onReceive(Context context, Intent intent) {
String[] finale;
int iteraux;
SharedPreferences settings = context.getSharedPreferences(PREFS_NAME,0); //GUARDAR DATO DE ITERADOR
iteraux = settings.getInt("iterador",iterador);
Resources res= context.getResources(); //GET THE RESOURCES
finale=res.getStringArray(R.array.cartas); //ASIGN THE STRING ARRAY TO THE VARIABLE
//iteraux=MainActivity.iterador;
if(iteraux==finale.length){
iteraux=0;
}
else{
iteraux++;
}
//<-----------UPDATE ITERADOR VAR IN MAINACTIVITY
SharedPreferences.Editor editor2 = settings.edit();
editor2.putInt("iterador",iteraux);
editor2.commit();
// frasesaux=MainActivity.frases;
当您收到通知时,您的 activity 不是 alive
,因此如果您尝试访问 Activity
的字段而不是 alive
,则会出现异常
解决方案
1.) 使用context
得到getStringArray(R.array.cartas)
2.) 使用相同的 context
从 SharedPreferences
public class RecibeNotif extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String[] frasesaux;
int iteraux;
SharedPreferences settings = context.getSharedPreferences("MyPrefsFile",0);
iteraux = settings.getInt("iterador",0);
// ^^ your default value
//iteraux=MainActivity.iterador;
frasesaux=context.getResources().getStringArray(R.array.cartas);
// ^^ fetch the array
if(iteraux==frasesaux.length){
iteraux=0;
}
//...
}
}
注意:static
不会有任何区别,因为你的数组只会在 onCreate
被 android OS 调用时初始化,所以这是并非如此,因此您的 static
字段将保持 un-initialized 表示 null 和 0.