onPause:Parcelable遇到IOException,编写可序列化对象

时间:2015-06-30 23:18:30

标签: android serialization android-mediaplayer

当我关闭我的应用程序时,我收到以下错误:onPause:

Process: za.co.neilson.alarm, PID: 26280
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = za.co.neilson.alarm.preferences.AlarmPreferenceListAdapter)
        at android.os.Parcel.writeSerializable(Parcel.java:1316)
        at android.os.Parcel.writeValue(Parcel.java:1264)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
        at android.os.Bundle.writeToParcel(Bundle.java:1692)
        at android.os.Parcel.writeBundle(Parcel.java:636)
        at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2755)
        at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3313)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5487)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.io.NotSerializableException: za.co.neilson.alarm.preferences.AlarmPreferencesActivity
        at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364)
        at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
        at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
        at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
        at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
        at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
        at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
        at android.os.Parcel.writeSerializable(Parcel.java:1311)
            at android.os.Parcel.writeValue(Parcel.java:1264)
            at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
            at android.os.Bundle.writeToParcel(Bundle.java:1692)
            at android.os.Parcel.writeBundle(Parcel.java:636)
            at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2755)
            at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3313)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5487)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

我不明白的是,类AlarmPreferenceListAdapter是serliazable,这个错误仍然存​​在....

AlarmPreferencesActivity类(当onPause操作和错误发生时):

public class AlarmPreferencesActivity extends BaseActivity {

    private Alarm alarm;
    private MediaPlayer mediaPlayer;

    private ListAdapter listAdapter;
    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        setContentView(R.layout.alarm_preferences);

        Bundle bundle = getIntent().getExtras();
        if (bundle != null && bundle.containsKey("alarm")) {
            setMathAlarm((Alarm) bundle.getSerializable("alarm"));
        } else {
            setMathAlarm(new Alarm());
        }
        if (bundle != null && bundle.containsKey("adapter")) {
            setListAdapter((AlarmPreferenceListAdapter) bundle.getSerializable("adapter"));
        } else {
            setListAdapter(new AlarmPreferenceListAdapter(this, getMathAlarm()));
        }

        getListView().setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> l, View v, int position, long id) {
                final AlarmPreferenceListAdapter alarmPreferenceListAdapter = (AlarmPreferenceListAdapter) getListAdapter();
                final AlarmPreference alarmPreference = (AlarmPreference) alarmPreferenceListAdapter.getItem(position);

                AlertDialog.Builder alert;
                v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
                switch (alarmPreference.getType()) {
                    case BOOLEAN:
                        CheckedTextView checkedTextView = (CheckedTextView) v;
                        boolean checked = !checkedTextView.isChecked();
                        ((CheckedTextView) v).setChecked(checked);
                        switch (alarmPreference.getKey()) {
                            case ALARM_ACTIVE:
                                alarm.setAlarmActive(checked);
                                break;
                            case ALARM_VIBRATE:
                                alarm.setVibrate(checked);
                                if (checked) {
                                    Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
                                    vibrator.vibrate(1000);
                                }
                                break;
                        }
                        alarmPreference.setValue(checked);
                        break;
                    case STRING:

                        alert = new AlertDialog.Builder(AlarmPreferencesActivity.this);

                        alert.setTitle(alarmPreference.getTitle());

                        // Set an EditText view to get user input
                        final EditText input = new EditText(AlarmPreferencesActivity.this);

                        input.setText(alarmPreference.getValue().toString());

                        alert.setView(input);
                        alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {

                                alarmPreference.setValue(input.getText().toString());

                                if (alarmPreference.getKey() == Key.ALARM_NAME) {
                                    alarm.setAlarmName(alarmPreference.getValue().toString());
                                }

                                alarmPreferenceListAdapter.setMathAlarm(getMathAlarm());
                                alarmPreferenceListAdapter.notifyDataSetChanged();
                            }
                        });
                        alert.show();
                        break;
                    case LIST:
                        alert = new AlertDialog.Builder(AlarmPreferencesActivity.this);

                        alert.setTitle(alarmPreference.getTitle());

                        CharSequence[] items = new CharSequence[alarmPreference.getOptions().length];
                        for (int i = 0; i < items.length; i++)
                            items[i] = alarmPreference.getOptions()[i];

                        alert.setItems(items, new OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                switch (alarmPreference.getKey()) {

                                    case ALARM_TONE:
                                        // Setting deafault to silent unless clicking
                                        alarm.setAlarmTonePath(alarmPreferenceListAdapter.getAlarmTonePaths()[0]);
                                        alarm.setAlarmTonePath(alarmPreferenceListAdapter.getAlarmTonePaths()[which]);
                                        if (alarm.getAlarmTonePath() != null) {
                                            if (mediaPlayer == null) {
                                                mediaPlayer = new MediaPlayer();
                                            } else {
                                                if (mediaPlayer.isPlaying())
                                                    mediaPlayer.stop();
                                                mediaPlayer.reset();
                                            }
                                            try {
                                                // mediaPlayer.setVolume(1.0f, 1.0f);
                                                mediaPlayer.setVolume(0.2f, 0.2f);
                                                mediaPlayer.setDataSource(AlarmPreferencesActivity.this, Uri.parse(alarm.getAlarmTonePath()));
                                                mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
                                                mediaPlayer.setLooping(false);
                                                mediaPlayer.prepare();
                                                mediaPlayer.start();

                                                // Force the mediaPlayer to stop after 3
                                                // seconds...
                                                if (alarmToneTimer != null)
                                                    alarmToneTimer.cancel();
                                                alarmToneTimer = new CountDownTimer(3000, 3000) {
                                                    @Override
                                                    public void onTick(long millisUntilFinished) {

                                                    }

                                                    @Override
                                                    public void onFinish() {
                                                        try {
                                                            if (mediaPlayer.isPlaying())
                                                                mediaPlayer.stop();
                                                        } catch (Exception e) {

                                                        }
                                                    }
                                                };
                                                alarmToneTimer.start();
                                            } catch (Exception e) {
                                                try {
                                                    if (mediaPlayer.isPlaying())
                                                        mediaPlayer.stop();
                                                } catch (Exception e2) {

                                                }
                                            }
                                        }
                                        break;
                                    default:
                                        break;
                                }
                                alarmPreferenceListAdapter.setMathAlarm(getMathAlarm());
                                alarmPreferenceListAdapter.notifyDataSetChanged();
                            }

                        });

                        alert.show();
                        break;
                    case MULTIPLE_LIST:

                        alert = new AlertDialog.Builder(AlarmPreferencesActivity.this);

                        alert.setTitle(alarmPreference.getTitle());

                        CharSequence[] multiListItems = new CharSequence[alarmPreference.getOptions().length];
                        for (int i = 0; i < multiListItems.length; i++)
                            multiListItems[i] = alarmPreference.getOptions()[i];

                        // Handling when it's NULL, ie. No days selected...
                        boolean[] checkedItems = new boolean[multiListItems.length];
                        for (Alarm.Day chosenDay : getMathAlarm().getChosenDays()) {
                            checkedItems[chosenDay.ordinal()] = true;
                        }

                        alert.setMultiChoiceItems(multiListItems, checkedItems, new OnMultiChoiceClickListener() {

                            @Override
                            public void onClick(final DialogInterface dialog, int which, boolean isChecked) {

                                Alarm.Day thisDay = Alarm.Day.values()[which];

                                if (isChecked) {
                                    alarm.addChosenDay(thisDay);
                                } else {

                                    // Remove and allow checking no days
                                    alarm.removeChosenDay(thisDay);

                                }

                            }
                        });
                        alert.setOnCancelListener(new OnCancelListener() {
                            @Override
                            public void onCancel(DialogInterface dialog) {
                                alarmPreferenceListAdapter.setMathAlarm(getMathAlarm());
                                alarmPreferenceListAdapter.notifyDataSetChanged();

                            }
                        });
                        alert.show();
                        break;

                    case TIME:
                        TimePickerDialog timePickerDialog = new TimePickerDialog(AlarmPreferencesActivity.this, new OnTimeSetListener() {

                            @Override
                            public void onTimeSet(TimePicker timePicker, int hours, int minutes) {
                                Calendar newAlarmTime = Calendar.getInstance();
                                newAlarmTime.set(Calendar.HOUR_OF_DAY, hours);
                                newAlarmTime.set(Calendar.MINUTE, minutes);
                                newAlarmTime.set(Calendar.SECOND, 0);
                                alarm.setAlarmTime(newAlarmTime);
                                alarmPreferenceListAdapter.setMathAlarm(getMathAlarm());
                                alarmPreferenceListAdapter.notifyDataSetChanged();
                            }
                        }, alarm.getAlarmTime().get(Calendar.HOUR_OF_DAY), alarm.getAlarmTime().get(Calendar.MINUTE), true);
                        timePickerDialog.setTitle(alarmPreference.getTitle());
                        timePickerDialog.show();
                        break;
                /* Notes: 6/23/2015:

                - Need to add a date selection (after the time selection)
                - Need to change the repeat from list to checkbox
                - If select repeat yes, opens the usual dialog to select the days
                    and adds an extra row with the days that the event is repeating
                - If un-selecting the repeat, will clear those days previously selected (basically just automate un-checking that days list)

                */
                    case DATE:
                        DatePickerDialog datePickerDialog = new DatePickerDialog(AlarmPreferencesActivity.this, new DatePickerDialog.OnDateSetListener() {
                            @Override
                            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {

                                Calendar newAlarmDate = Calendar.getInstance();

                                newAlarmDate.set(Calendar.YEAR, year);
                                newAlarmDate.set(Calendar.MONTH, monthOfYear);
                                newAlarmDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);

                                // Prevent setting to a previous date:
                                if (newAlarmDate.before(Calendar.getInstance())) {
                                    // Then set to current date:
                                    newAlarmDate = Calendar.getInstance();
                                    Toast.makeText(getApplicationContext(), "Cannot Set Event in Past", Toast.LENGTH_LONG).show();
                                }

                                alarm.setAlarmDate(newAlarmDate);
                                alarmPreferenceListAdapter.setMathAlarm(getMathAlarm());
                                alarmPreferenceListAdapter.notifyDataSetChanged();
                            }
                        }, alarm.getAlarmDate().get(Calendar.YEAR), alarm.getAlarmDate().get(Calendar.MONTH), alarm.getAlarmDate().get(Calendar.DAY_OF_MONTH));
                        datePickerDialog.setTitle(alarmPreference.getTitle());
                        datePickerDialog.show();
                        break;

                    default:
                        break;
                }
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        boolean result = super.onCreateOptionsMenu(menu);
        menu.findItem(R.id.menu_item_new).setVisible(false);
        return result;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_item_save:

                // Input Sanitation:
                Calendar setTimeValues = Calendar.getInstance();
                setTimeValues.set(Calendar.HOUR, alarm.getAlarmTime().get(Calendar.HOUR));
                setTimeValues.set(Calendar.MINUTE, alarm.getAlarmTime().get(Calendar.MINUTE));

                // If repeating alarm, setting before the present time, should increment to the next day it will be active
                if (alarm.getChosenDays().length != 0 && alarm.getAlarmDate().before(Calendar.getInstance())
                        && setTimeValues.before(Calendar.getInstance())) {

                    Toast.makeText(getApplicationContext(), "Repeat: time is before present - set alarm to next active day", Toast.LENGTH_LONG).show();
                    alarm.getAlarmDate().add(Calendar.DAY_OF_MONTH, 1);

                    // Trouble is, if today ie, Sunday, is one of the days chosen for repeating...it gets caught up
                    // Then iterate to the next day the alarm should be activated
                    while (!Arrays.asList(alarm.getChosenDays()).contains(Alarm.Day.values()[alarm.getAlarmDate().get(Calendar.DAY_OF_WEEK) - 1])) {
                        alarm.getAlarmDate().add(Calendar.DAY_OF_MONTH, 1);
                    }

                }

                if (alarm.getChosenDays().length != 0 && alarm.getAlarmDate().before(Calendar.getInstance())
                        && setTimeValues.equals(Calendar.getInstance())) {

                    Toast.makeText(getApplicationContext(), "Repeat: time is before present - set alarm to next active day", Toast.LENGTH_LONG).show();
                    alarm.getAlarmDate().add(Calendar.DAY_OF_MONTH, 1);

                    // Trouble is, if today ie, Sunday, is one of the days chosen for repeating...it gets caught up

                    // Then iterate to the next day the alarm should be activated
                    while (!Arrays.asList(alarm.getChosenDays()).contains(Alarm.Day.values()[alarm.getAlarmDate().get(Calendar.DAY_OF_WEEK) - 1])) {
                        alarm.getAlarmDate().add(Calendar.DAY_OF_MONTH, 1);
                    }

                }

                if (alarm.getChosenDays().length != 0) {
                    while (!Arrays.asList(alarm.getChosenDays()).contains(Alarm.Day.values()[alarm.getAlarmDate().get(Calendar.DAY_OF_WEEK) - 1])) {
                        alarm.getAlarmDate().add(Calendar.DAY_OF_MONTH, 1);
                    }
                }

                // If individual alarm and setting time before presentm should not allow saving at all
                if (alarm.getChosenDays().length == 0 && alarm.getAlarmDate().before(Calendar.getInstance())
                        && setTimeValues.equals(Calendar.getInstance())
                        ||
                        alarm.getChosenDays().length == 0 && alarm.getAlarmDate().before(Calendar.getInstance())
                                && setTimeValues.before(Calendar.getInstance())) {

                    Toast.makeText(getApplicationContext(), "Cannot set event in past", Toast.LENGTH_LONG).show();
                } else {

                    // Everthing else is allowed
                    Database.init(getApplicationContext());
                    if (getMathAlarm().getId() < 1) {
                        Database.create(getMathAlarm());
                    } else {
                        Database.update(getMathAlarm());
                    }
                    callMathAlarmScheduleService();
                    Toast.makeText(AlarmPreferencesActivity.this, getMathAlarm().getTimeUntilNextAlarmMessage(), Toast.LENGTH_LONG).show();

                    finish();

                }

                break;
            case R.id.menu_item_delete:
                AlertDialog.Builder dialog = new AlertDialog.Builder(AlarmPreferencesActivity.this);
                dialog.setTitle("Delete");
                dialog.setMessage("Delete this alarm?");
                dialog.setPositiveButton("Ok", new OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        Database.init(getApplicationContext());
                        if (getMathAlarm().getId() < 1) {
                            // Alarm not saved
                        } else {
                            Database.deleteEntry(alarm);
                            callMathAlarmScheduleService();
                        }
                        finish();
                    }
                });
                dialog.setNegativeButton("Cancel", new OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
                dialog.show();

                break;
        }
        return super.onOptionsItemSelected(item);
    }

    private CountDownTimer alarmToneTimer;

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putSerializable("alarm", getMathAlarm());
        outState.putSerializable("adapter", (AlarmPreferenceListAdapter) getListAdapter());
    }

    ;

    @Override
    protected void onPause() {
        super.onPause();

        if(mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.reset();
            mediaPlayer.release();
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    public Alarm getMathAlarm() {
        return alarm;
    }

    public void setMathAlarm(Alarm alarm) {
        this.alarm = alarm;
    }

    public ListAdapter getListAdapter() {
        return listAdapter;
    }

    public void setListAdapter(ListAdapter listAdapter) {
        this.listAdapter = listAdapter;
        getListView().setAdapter(listAdapter);

    }

    public ListView getListView() {
        if (listView == null)
            listView = (ListView) findViewById(android.R.id.list);
        return listView;
    }

    public void setListView(ListView listView) {
        this.listView = listView;
    }

    @Override
    public void onClick(View v) {

    }
}

0 个答案:

没有答案