App crash when rotating tablet (single to dual pane display)

363 views Asked by At

Ive tried to solve my Portrait/Landscape segment in my project using this tutorial: http://www.cs.dartmouth.edu/~campbell/cs65/lecture09/lecture09.html

Everything seems to work fine (both landscape and portrait), but if i rotate from portrait to landscape or visa verse the app crashes with this: error

11-26 13:42:38.822  22594-22594/picturedtalk.com.picturedtalk E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: picturedtalk.com.picturedtalk, PID: 22594
java.lang.RuntimeException: Unable to start activity ComponentInfo{picturedtalk.com.picturedtalk/picturedtalk.com.picturedtalk.Signs.SignActivity}: android.app.Fragment$InstantiationException: Unable to instantiate fragment picturedtalk.com.picturedtalk.Signs.DetailsFragment: make sure class name exists, is public, and has an empty constructor that is public
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2338)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3930)
        at android.app.ActivityThread.access$900(ActivityThread.java:151)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327)
        at android.os.Handler.dispatchMessage(Handler.java:110)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:5292)
        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:824)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment picturedtalk.com.picturedtalk.Signs.DetailsFragment: make sure class name exists, is public, and has an empty constructor that is public
        at android.app.Fragment.instantiate(Fragment.java:601)
        at android.app.FragmentState.instantiate(Fragment.java:98)
        at android.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1759)
        at android.app.Activity.onCreate(Activity.java:899)
        at picturedtalk.com.picturedtalk.Signs.SignActivity.onCreate(SignActivity.java:16)

Any suggestion how i can stop the app from crashing when changing from portrait to landscape view?

That part of my app:

SignActivity.java

public class SignActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.signs_layout);

}

}

ListFragment.java

public class ListFragment extends android.app.ListFragment {

private ArrayList<Signs> storage;
boolean mDualPane;
int mCurrentCheckPosition = 0;


@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    SignAdapter adapter = new    
SignAdapter(Storage.get(getActivity()).getStorageOfSigns());
    setListAdapter(adapter);

    //Check if the we are using layout-land version of the XML to figure out if  
portrait/landscape
    View detailsFrame = getActivity().findViewById(R.id.details);
    mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE;

    //restore last state
    if (savedInstanceState != null) {
        mCurrentCheckPosition = savedInstanceState.getInt("curChoice", 0);
    }

    if (mDualPane) {
        //only select one item at the time
        getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        showDetails(mCurrentCheckPosition);

    } else {
        getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        getListView().setItemChecked(mCurrentCheckPosition, true);
    }


}

//Handle flipping during fragment use
//DOES NOT WORK
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    savedInstanceState.putInt("curChoice", mCurrentCheckPosition);
}

private void showDetails(int index) {
    mCurrentCheckPosition = index;

    if (mDualPane) {

        getListView().setItemChecked(index, true);
        DetailsFragment details = (DetailsFragment) getFragmentManager().findFragmentById(R.id.details);
        if (details == null || details.getShownIndex() != index) {

            UUID startId = ((SignAdapter) getListAdapter()).getItem(0).getId();
            details = new DetailsFragment(startId);

            //  Execute a transaction, replacing any existing fragment
            //  with this one inside the frame.
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.replace(R.id.details, details);
            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            ft.commit();
        }

    } else {

        Intent intent = new Intent();
        intent.setClass(getActivity(), DetailsActivity.class);
        intent.putExtra("index", index);
        startActivity(intent);
    }
}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {

    if(!mDualPane){
    Signs signs = ((SignAdapter) getListAdapter()).getItem(position);
    Intent intent = new Intent(getActivity(),   
picturedtalk.com.picturedtalk.Signs.DetailsActivity.class);
    intent.putExtra(DetailsFragment.EXTRA_SIGN_ID, signs.getId());
    startActivity(intent);
    }
    else{
    UUID signId = ((SignAdapter) getListAdapter()).getItem(position).getId();
    DetailsFragment fragment = new DetailsFragment(signId);
    FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.details, fragment);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        ft.commit();
    }
}


private class SignAdapter extends ArrayAdapter<Signs> {

    public SignAdapter(ArrayList<Signs> sSigns) {
        super(getActivity(), 0, sSigns);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //If we were given a view, inflate one
        if (convertView == null) {
            convertView = getActivity().getLayoutInflater().inflate(R.layout.signs_row, 
null);
        }
        //Configure the view for this Crime
        Signs signs = getItem(position);
        TextView titleTextView = (TextView) convertView.findViewById(R.id.label);
        titleTextView.setText(signs.getName());

        return convertView;
    }
}}

DetailsActivity.java

public class DetailsActivity extends Activity {

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

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        UUID mSignId;
        mSignId = (UUID)getIntent().getSerializableExtra(DetailsFragment.EXTRA_SIGN_ID);
        DetailsFragment details = new DetailsFragment(mSignId);
        getFragmentManager().beginTransaction().replace(android.R.id.content, details).commit();
        UUID STOPTHIs = mSignId;
    }
    else {
        UUID mSignId;
        mSignId = (UUID)getIntent().getSerializableExtra(DetailsFragment.EXTRA_SIGN_ID);
        DetailsFragment details = new DetailsFragment(mSignId);
        getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
    }



}}

DetailsFragment.java

public class DetailsFragment extends Fragment {

public int getShownIndex() {
    return getArguments().getInt("index", 0);
}

public static final String EXTRA_SIGN_ID = "sign_id";
private UUID extraSignId;
//  private static DetailsFragment detailsFragment;
private View view;
private TextView title;
private ImageView illustrativeView;
private ImageView pictureView;
private VideoView videoView;
private Signs mSign;
private String TAG = "DETAILFRAGMENT";

public DetailsFragment(UUID signId) {
    this.extraSignId = signId;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSign = Storage.get(getActivity()).getSigns(extraSignId);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    view = inflater.inflate(R.layout.signs_details, container, false);

    title = (TextView) view.findViewById(R.id.title);
    illustrativeView = (ImageView) view.findViewById(R.id.illustrateImage);
    pictureView = (ImageView) view.findViewById(R.id.pictureImage);
    videoView = (VideoView) view.findViewById(R.id.videoView);

    title.setText(mSign.getName());

    try {
        Bitmap illuBitmap = BitmapFactory.decodeFile(mSign.getIllustrativeURL());
        illustrativeView.setImageBitmap(illuBitmap);
    } catch (Exception e) {
        Log.d(TAG, "failed loading illustrative image");
    }
    try {
        Bitmap picBitmap = BitmapFactory.decodeFile(mSign.getImageURL());
        pictureView.setImageBitmap(picBitmap);
    } catch(Exception e){
        Log.d(TAG, "failed loading picture image");
    }

    try {

        Uri uri = Uri.parse(mSign.getVideoURL());
        videoView.setVideoURI(uri);
        videoView.requestFocus();

        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.setLooping(true);
            }
        });

        videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {

                videoView.setBackgroundResource(R.drawable.simp);
                return true;
            }
        });
        videoView.start();

    } catch (Exception e) {
        Log.d(TAG, "failed loading video");
    }



    return view;
}}

Signs.java

public class Signs {

UUID id;
String name;
String videoURL;
String imageURL;
String illustrativeURL;

public Signs(String name,  String imageURL,String videoURL, String illustrativeURL){
    this.id = UUID.randomUUID();
    this.name = name;
    this.videoURL = videoURL;
    this.imageURL = imageURL;
    this.illustrativeURL = illustrativeURL;
}

public UUID getId() {
    return id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getVideoURL() {
    return videoURL;
}

public void setVideoURL(String videoURL) {
    this.videoURL = videoURL;
}

public String getImageURL() {
    return imageURL;
}

public void setImageURL(String imageURL) {
    this.imageURL = imageURL;
}

public String getIllustrativeURL() {
    return illustrativeURL;
}

public void setIllustrativeURL(String illustrativeURL) {
    this.illustrativeURL = illustrativeURL;
}}

signs_layout.xml (layout)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<fragment
    android:id="@+id/titles"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="picturedtalk.com.picturedtalk.Signs.ListFragment" />

signs_layout.xml (/layout-land)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal" >

<fragment
    android:id="@+id/titles"
    android:layout_width="0px"
    android:layout_height="match_parent"
    android:layout_weight="1"
    class="picturedtalk.com.picturedtalk.Signs.ListFragment" />

<FrameLayout
    android:id="@+id/details"
    android:layout_width="0px"
    android:layout_height="match_parent"
    android:layout_weight="3"
    android:background="?android:attr/detailsElementBackground" />

</LinearLayout>

signs_details.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50dp"
android:text="TitleHere"
android:id="@+id/title"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="98dp" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/illustrateImage"
android:layout_below="@id/title"
android:layout_toRightOf="@+id/pictureImage"
android:background="@drawable/signs_logo"/>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/pictureImage"
android:layout_centerVertical="true"
android:layout_below="@+id/title"
android:layout_centerHorizontal="true"
android:background="@drawable/simp"/>

<VideoView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/videoView"
android:layout_below="@id/title"
android:layout_toLeftOf="@+id/pictureImage"/>
</RelativeLayout>

signs_listview.xml

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

signs_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >

<TextView
    android:id="@+id/label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@+id/label"
    android:textSize="20px" >
</TextView>

</LinearLayout>
1

There are 1 answers

5
Fatti Khan On BEST ANSWER

You can avoid activity recreation by adding following to your application's manifest file. as

android:configChanges="keyboardHidden|orientation|screenSize" 

and

   <activity
            android:name=".your activity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/app_name" >
        </activity>