调用BroadcastReceiver时应用程序崩溃

时间:2015-12-23 07:30:27

标签: android broadcastreceiver android-broadcast

我使用此 BroadcastReceiver 每周使用新数据更新我的应用程序的 JSON 数据,它在大多数情况下都能正常运行,但是对于某些用户来说,它很容易崩溃的 的NullPointerException

我如何设置闹钟:

    public static void setAlarm(int i, Context context){
    AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, UpdateReceiver.class);
    PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

    if (i == 0) {
        alarmTime = 0;
        //Toast.makeText(context, "Setting alarm for first time", Toast.LENGTH_LONG).show();
    } else if (i == -2) {
        alarmTime = new GregorianCalendar().getTimeInMillis()+24*60*60*1000; // a day
        //Toast.makeText(context, "NO WIFI RESTARTING AFTER A DAY" + alarmTime, Toast.LENGTH_LONG).show();
    }else {
        alarmTime = UpdateReceiver.getAlermTimeInMillis();
        //Toast.makeText(context, "Setting alarm for next tuesday", Toast.LENGTH_LONG).show();
    }
    // With setInexactRepeating(), you have to use one of the AlarmManager interval
    // constants--in this case, AlarmManager.INTERVAL_DAY.
    alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, alarmTime,
            AlarmManager.INTERVAL_DAY, alarmIntent);

}

BrodcastReceiver:我的catch块中有代码,因为当设备关闭时,应用程序在尝试更新时崩溃,所以我抓住异常并重新调用代码,这是一个好习惯吗?

public class UpdateReceiver extends BroadcastReceiver {

private static long alarmTime = 0;
private static final String TAG = UpdateReceiver.class.getSimpleName();

@Override
public void onReceive(Context context, Intent intent) {

    alarmTime = NextTuesday.nextDayOfWeek(Calendar.TUESDAY).getTimeInMillis();

        File file = context.getFileStreamPath("video_games.json");
        if (!file.exists()) {
            //Toast.makeText(context, "FIRST BOOT", Toast.LENGTH_LONG).show();
            if (isConnectedToInternet(context)) {
                UpcomingFragment.setAlarm(-1, context);
                UpcomingFragment.getInstance().update();
            } else {
                //a day from now
                UpcomingFragment.setAlarm(-2, context);
            }
        } else {

            //Toast.makeText(context, "FILE EXISTS", Toast.LENGTH_LONG).show();

            if (isConnectedToInternet(context)) {
                try {
                    Intent intentUpcoming = new Intent(context, MainActivity.class);
                    intentUpcoming.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(intentUpcoming);
                    UpcomingFragment.setAlarm(-1, context);
                    UpcomingFragment fragment = (UpcomingFragment) MainActivity.allFragments.get(0);
                    fragment.update();
                } catch (Exception e){
                    //Toast.makeText(context, e.getMessage() + "Crashed setAlarm(0) to update now and it won't crash this time", Toast.LENGTH_LONG).show();
                    UpcomingFragment.setAlarm(0, context);
                }

            } else {
                //a day from now
                UpcomingFragment.setAlarm(-2, context);
            }
        }

}

public static long getAlermTimeInMillis(){
    return alarmTime;
}

private boolean isConnectedToInternet(Context context) {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork= connectivityManager.getActiveNetworkInfo();
    return  activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}

}

Logcat:

java.lang.RuntimeException: Unable to start receiver domain.com.app.UpdateReceiver: java.lang.NullPointerException: 
Attempt to invoke virtual   method 'void domain.com.app.UpcomingFragment.update()' on a null object reference
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:3029)
    at android.app.ActivityThread.access$1800(ActivityThread.java:179)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1539)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5972)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void domain.com.app.UpcomingFragment.update()' on a null object reference
    at domain.com.app.UpdateReceiver.onReceive(UpdateReceiver.java:39)
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:3022)

如果logcat是任何指示,我猜它是因为更新不是静态的,不幸的是我不能使它静态。

1 个答案:

答案 0 :(得分:1)

似乎在调用更新时,您的Fragment不会保留任何实例。我建议更新您的数据库或SharedPreferrences。至少,他们没有生命周期,很难预测和管理。

所以onReceive()

SharedPreferences.Editor editor = getSharedPreferences().edit();
editor.putString("TOKEN", myJSON);
editor.apply();

Token是您要保存的JSON。在片段的某些方面,例如,onResume()调用

SharedPreferences sharedPreferences = getSharedPreferences();
        String token = sharedPreferences.getString("TOKEN", null);