我有一个基于标签栏的应用程序,它使用在片段/活动之间使用可打包对象的片段。它由 4 个片段组成 - 主要片段是地图视图(第一个)和列表视图(第二个)。该应用程序进入后台并再次加载,没有任何问题。但是,当我加载许多其他应用程序以减少可用内存后应用程序被终止,并且我重新启动应用程序时,它会崩溃并显示下面的日志输出......
任何指导都将不胜感激,因为我发现调试器在应用程序终止并重新启动后没有运行,并且崩溃日志并没有告诉我太多信息,因此很难调试它!
干杯
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();
}