2013-12-16 27 views
0

나는 프래그먼트/액티비티 사이의 분할 가능한 객체를 사용하는 조각을 사용하여 탭바 기반 앱을 사용합니다. 그것은 네 조각으로 구성되어 있습니다 - 주요 것들은 mapview (첫 번째)와 목록보기 (초)입니다. 앱이 백그라운드로 들어가서 문제없이 다시로드됩니다. 그러나 사용할 수있는 메모리를 줄이기 위해 다른 많은 응용 프로그램을로드 한 후 응용 프로그램이 종료되고 응용 프로그램이 다시 시작되면 아래 로그 출력과 충돌합니다.os에 의해 살해 된 후 앱을 다시 시작할 때 BadParcelableException 발생

모든 지침을 찾을 수있을 것입니다. 응용 프로그램이 종료되고 재시작 된 후에 디버거가 실행되지 않아서이 디버깅을 디버그하는 것이 매우 어렵습니다. 그리고 충돌 로그는별로 알려주지 않습니다!

건배 나는 다음과 같습니다에서 오류가오고 가정

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(); 
    } 
+0

일반적인 대답 : 때 앱이 평소와 다르게 다시 시작되면 필요에 따라 데이터가 다시 만들어 지도록해야합니다. 다른 상황에 근거하여 어떤 것이 있다고 가정하는 상황이있을 수 있습니다. 이것이 이러한 유형의 오류의 원인입니다. 귀하의 상황에서, 활동/파편 간의 인 텐트 또는 번들로 전달 된 데이터가 예상 한 것과 다를 수 있습니다. –

답변

0

문제를 발견했습니다. 데이터를 저장 한 소급 클래스였습니다. 나는 (I 기본 클래스 로더를 선택 생각)이 클래스 로더에 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(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()); 
     } 
    }