在被os杀死后重启应用程序时出现BadParcelableException

时间:2013-12-16 20:59:32

标签: android parcelable ondestroy badparcelableexception

我有一个基于tabbar的应用程序,使用在片段/活动之间使用parcelable对象的片段。它由4个片段组成 - 主要是mapview(第一个)和列表视图(第二个)。该应用程序进入后台并再次加载没有任何问题。但是,当我加载大量其他应用程序以减少可用内存后应用程序被杀,并且我重新启动应用程序时,它会崩溃并显示下面的日志输出...

任何指导都会非常感激,因为我发现很难调试这个,因为调试器在应用程序终止并重新启动后没有运行,并且崩溃日志不会告诉我太多!

干杯

FATAL EXCEPTION: main
12-16 16:04:36.195 E/AndroidRuntime( 6795): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.appco.myapp/com.myapp.MainActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.braesloantrail.model.Place
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.os.Handler.dispatchMessage(Handler.java:99)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.os.Looper.loop(Looper.java:130)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.app.ActivityThread.main(ActivityThread.java:3687)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at java.lang.reflect.Method.invokeNative(Native Method)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at java.lang.reflect.Method.invoke(Method.java:507)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at dalvik.system.NativeStart.main(Native Method)
12-16 16:04:36.195 E/AndroidRuntime( 6795): Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.appco.model.Place
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.os.Parcel.readParcelable(Parcel.java:1958)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.appco.model.Places.<init>(Places.java:115)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.appco.model.Places.<init>(Places.java:111)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.braesloantrail.model.Places$1.createFromParcel(Places.java:121)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.braesloantrail.model.Places$1.createFromParcel(Places.java:1)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.os.Parcel.readParcelable(Parcel.java:1981)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.os.Parcel.readValue(Parcel.java:1846)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.os.Parcel.readMapInternal(Parcel.java:2083)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.os.Bundle.unparcel(Bundle.java:208)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.os.Bundle.getParcelable(Bundle.java:1100)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.braesloantrail.fragments.ListViewFragment.readPlacesBundle(ListViewFragment.java:128)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.braesloantrail.fragments.ListViewFragment.onCreate(ListViewFragment.java:57)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.support.v4.app.Fragment.performCreate(Fragment.java:1455)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:893)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:1872)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:215)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at com.braesloantrail.MainActivity.onCreate(MainActivity.java:126)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-16 16:04:36.195 E/AndroidRuntime( 6795): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
12-16 16:04:36.195 E/AndroidRuntime( 6795): ... 11 more

我认为错误的主要活动来自......

public class MainActivity extends FragmentActivity implements MyLocationListener{

    // TAB ID CONSTANTS
    private final String TAB_MAP_VIEW = "TAB_MAP_VIEW";
    private final String TAB_LIST_VIEW = "TAB_LIST_VIEW";
    private final String TAB_SONAR = "TAB_SONAR";
    private final String TAB_SETTINGS = "TAB_SETTINGS";

    public static final String LATITUDE_BUNDLE_EXTRA = "latitude";
    public static final String LONGITUDE_BUNDLE_EXTRA = "longitude";

    private FragmentTabHost mTabHost;

    // Contains all places model
    private Places places;

    private Bundle placesBundle;

    // Identifier for places bundle object
    public static final String PLACES_BUNDLE = "places_bundle";

    private String current_fragment_id;

    private GPSTracker gpsTracker;

    final int RQS_GooglePlayServices = 1;

    // Keeps current location
    private Location location;

    // stores previous sonar name between sonar fragment refreshing
    private String previousPlaceName = "";

    // flag to store google maps and api support
    private boolean hasMapSupport = true;

    // flag to see if first run to show showgps alert and log how many times shown
    SharedPreferences userPrefs = null;

    @Override
    protected void onPause() {
        super.onPause();
        if (current_fragment_id != TAB_SONAR) {
            gpsTracker.stopUsingGPS();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        location = gpsTracker.getLocation();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String modelData = Utils.loadAsset(this, "places.txt");
        Assert.assertTrue(modelData != null);
        current_fragment_id = TAB_MAP_VIEW;

        gpsTracker = new GPSTracker(this, this);
        this.setLocation(gpsTracker.getLocation());

        try {
            this.parseModel(modelData);
            this.createPlacesBundle();
            this.addTabs();
            this.setTabColor(mTabHost);
        } catch (JSONException je) {
            je.printStackTrace();
        }
        userPrefs = getSharedPreferences("com.appco.myapp", MODE_PRIVATE);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        int menu_layout_id = 0;
        if (current_fragment_id.equals(TAB_MAP_VIEW)) {
            menu_layout_id = R.menu.menu_mapview;
        }else if (current_fragment_id.equals(TAB_LIST_VIEW)){
            menu_layout_id = R.menu.menu_listview;
        }else if(current_fragment_id.equals(TAB_SONAR)){
            menu_layout_id = R.menu.menu_sonar;
        }else if(current_fragment_id.equals(TAB_SETTINGS)){
            menu_layout_id = R.menu.menu_settings;
        }

        MenuInflater inflater = getMenuInflater();
        inflater.inflate(menu_layout_id, menu);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_about:
                startActivity(new Intent(this, AboutActivity.class));
                return true;
            case R.id.action_info:
                if(current_fragment_id == TAB_LIST_VIEW){
                    final Dialog dialog = new Dialog(this);
                    dialog.setContentView(R.layout.dialog_listview_info);
                    dialog.setTitle(getResources().getString(R.string.information));
                    dialog.show();
                }else if(current_fragment_id == TAB_MAP_VIEW){
                    final Dialog dialog = new Dialog(this);
                    dialog.setContentView(R.layout.dialog_mapview);
                    dialog.setTitle(getResources().getString(R.string.information));
                    dialog.show();
                }
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }


    private void addTabs() {
        mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
        mTabHost.setOnTabChangedListener(new OnTabChangeListener() {

            @Override
            public void onTabChanged(String tabId) {
                setTabColor(mTabHost);
                current_fragment_id = tabId;
            }
        });

        mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);

        // check if google play installed
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());

        if (resultCode == ConnectionResult.SUCCESS && isGoogleMapsInstalled()){
            mTabHost.addTab(
                            mTabHost.newTabSpec(TAB_MAP_VIEW).setIndicator(
                                                                           getResources().getString(R.string.MapView)),
                            MapViewFragment.class, this.placesBundle);
            hasMapSupport = true;
        }else{
            Toast.makeText(getApplicationContext(),
                           "You must have Google Play Services and Google Maps installed via the Play Store in order to make full use of this app.",
                           Toast.LENGTH_LONG).show();
            hasMapSupport = false;
        }


        mTabHost.addTab(
                        mTabHost.newTabSpec(TAB_LIST_VIEW).setIndicator(
                                                                        getResources().getString(R.string.ListView)),
                        ListViewFragment.class, this.placesBundle);
        mTabHost.addTab(
                        mTabHost.newTabSpec(TAB_SONAR).setIndicator(
                                                                    getResources().getString(R.string.Sonar)),
                        SonarFragment.class, this.placesBundle);
        mTabHost.addTab(
                        mTabHost.newTabSpec(TAB_SETTINGS).setIndicator(
                                                                       getResources().getString(R.string.Settings)),
                        SettingsFragment.class, null);
    }

    private void parseModel(String modelData) throws JSONException {
        JSONObject places = new JSONObject(modelData);
        this.places = new Places();
        this.places.deserialise(places);
    }

    private void createPlacesBundle(){
        this.placesBundle = new Bundle();
        this.placesBundle.putParcelable(PLACES_BUNDLE, this.places);
        if (this.location != null) {
            this.placesBundle.putDouble(LATITUDE_BUNDLE_EXTRA, location.getLatitude());
            this.placesBundle.putDouble(LONGITUDE_BUNDLE_EXTRA, location.getLongitude());
        }
    }


    public boolean isGoogleMapsInstalled()
    {
        try
        {
            ApplicationInfo info = getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0 );
            return true;
        }
        catch(PackageManager.NameNotFoundException e)
        {
            return false;
        }
    }

    public OnClickListener getGoogleMapsListener()
    {
        return new OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.apps.maps"));
                startActivity(intent);

                //Finish the activity so they can't circumvent the check
                finish();
            }
        };
    }

    @Override
    public void onLocationChanged(Location location) {
        this.location = location;
        double latitude = (double) (location.getLatitude());
        double longitude = (double) (location.getLongitude());

        if (current_fragment_id == TAB_LIST_VIEW) {
            ListViewFragment listFrag = (ListViewFragment)getSupportFragmentManager().findFragmentByTag(current_fragment_id);
        }
        else if(current_fragment_id == TAB_SONAR){
            SonarFragment sonarFrag = (SonarFragment)getSupportFragmentManager().findFragmentByTag(current_fragment_id);
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    @Override
    public void onNoLocationProviderFound() {

    }

    public boolean getMapSupportStatus(){
        return hasMapSupport;
    }

}

这是我的对象实现了parcelable ......

public class Place implements ISerializable, Parcelable, Comparable<Place> {

    // MEMBER DEFINITION //
    private String othercaptions = "";
    private String mainphoto = "";
    private String description = "";
    private String maincaption = "";
    private String name = "";
    private String otherphotos = "";
    private String longitude = "";
    private String latitude = "";
    private String uniqueid = "";
    private float distance = 0;

    public Place(){

    }

    // ISERIALIZABLE DEFINITION //
    public void deserialise(JSONObject source) throws JSONException {
        othercaptions = source.getString("otherCaptions");
        mainphoto = source.getString("mainPhoto");
        description = source.getString("description");
        maincaption = source.getString("mainCaption");
        name = source.getString("name");
        otherphotos = source.getString("otherPhotos");
        longitude = source.getString("longitude");
        latitude = source.getString("latitude");
        uniqueid = source.getString("uniqueId");
    }

    // PARCELABLE IMPLEMENTATION //
    @Override
    public int describeContents() {
        return 1;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.othercaptions);
        dest.writeString(this.mainphoto);
        dest.writeString(this.description);
        dest.writeString(this.maincaption);
        dest.writeString(this.name);
        dest.writeString(this.otherphotos);
        dest.writeString(this.longitude);
        dest.writeString(this.latitude);
        dest.writeString(this.uniqueid);
    }

    private Place(Parcel in) {
        this.othercaptions = in.readString();
        this.mainphoto = in.readString();
        this.description = in.readString();
        this.maincaption = in.readString();
        this.name = in.readString();
        this.otherphotos = in.readString();
        this.longitude = in.readString();
        this.latitude = in.readString();
        this.uniqueid = in.readString();
    }

1 个答案:

答案 0 :(得分:0)

发现了问题 - 它存放在我的parcelable类中,我存储了我的数据。我传入null为ClassLoader(我相信选择默认的类加载器),但这可能会有问题 -

private Places(Parcel in) {
        int length = in.readInt();
        this.places = new Place[length];
        for(int i=0; i<length; i++){
            this.places[i] = in.readParcelable(null);
        }
    }

它应该是以下 -

private Places(Parcel in) {
        int length = in.readInt();
        this.places = new Place[length];
        for(int i=0; i<length; i++){
            this.places[i] = in.readParcelable(this.getClass().getClassLoader());
        }
    }