mardi 14 juin 2016

Android RunTimeException: Parcel: unable to marshal value

NOTE:

The code shown below may be a bit hard to read, but i hope it can help. Sorry for that.

I get this error whenever i press HOME button and my app goes background.

java.lang.RuntimeException: Parcel: unable to marshal value elektro_fr.newapplication.FragmentsActivity$3@a6c25e4

I'm new to android programming and i would like to create a class which can offer me all the functions without implementing them each time.

I made a My_Activity class:

package elektro_fr.my_android;

import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.WindowManager;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public abstract class My_Activity extends AppCompatActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{

    private int myLayout;

    protected Bundle mySettings;

    private boolean gesturesEnabled=false;
    private GestureDetectorCompat myGestureDetector;

    private boolean canStart=false;

    private boolean menuEnabled=false;
    private HashMap<String,Action> menuEntries;

    protected List<My_Fragment> fragmentsList=new LinkedList<>();

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        myGestureDetector = new GestureDetectorCompat(this,this);

        if (savedInstanceState==null){

            canStart=true;
        }

        init();
        setContentView(myLayout);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {

        super.onSaveInstanceState(outState);

        outState.putSerializable("LIST",menuEntries);

        for (int counter=0;counter<fragmentsList.size();counter++){

            getSupportFragmentManager().putFragment(outState,"FRAGMENT_SETTINGS_"+counter,fragmentsList.get(counter));
        }
    }

    @Override
    protected void onStart() {

        super.onStart();
        if (canStart) setGraphics();
        canStart=false;
    }

    protected abstract void init();
    protected abstract void setGraphics();

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {

        super.onRestoreInstanceState(savedInstanceState);

        if (savedInstanceState!=null){

            menuEntries=(HashMap<String, Action>) savedInstanceState.getSerializable("LIST");
            int size=getSupportFragmentManager().getFragments().size();

            for (int counter=0;counter<size;counter++){

                fragmentsList.add(counter,(My_Fragment)getSupportFragmentManager().getFragment(savedInstanceState,"FRAGMENT_SETTINGS_"+counter));
            }
        }

        refreshState();
    }

    abstract protected void refreshState();

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        return menuEnabled;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        super.onOptionsItemSelected(item);

        if (menuEntries.get(item.getTitle())!=null){

            menuEntries.get(item.getTitle()).doAction();
        }

        return menuEnabled;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {

        super.onPrepareOptionsMenu(menu);

        if (menuEnabled){

            if (menuEntries.size()!=0){

                menu.clear();
                int counter=0;

                for (String s: menuEntries.keySet()){

                    menu.add(Menu.NONE,counter,Menu.NONE,s);
                    counter++;
                }
            }
        }

        return menuEnabled;
    }

    protected void setGestures(boolean enabled){

        gesturesEnabled=enabled;
    }

    protected void setMenu(boolean enabled){

        menuEnabled=enabled;
        menuEntries=new HashMap<>();
    }

    protected HashMap<String, Action> getMenuEntries(){

        return menuEntries;
    }

    public My_Fragment addFragment(Class<? extends My_Fragment> fragmentClass, int fragmentContainer, int fragmentID, Bundle fragmentArgs){

        My_Fragment fragment = null;

        try {

            fragment = fragmentClass.newInstance();

        }
        catch (InstantiationException e){

        }
        catch (IllegalAccessException e){

            e.printStackTrace();
        }

        fragment.setArguments(fragmentArgs);
        getSupportFragmentManager().beginTransaction().add(fragmentContainer, fragment).commit();

        fragmentsList.add(fragment);

        return fragment;
    }

    protected My_Fragment getFragment(Class<? extends My_Fragment> fragmentClass){

        for (My_Fragment f: fragmentsList){

            if (fragmentClass.isInstance(f)){

                return f;
            }
        }
        return null;
    }

    public void removeFragment(My_Fragment fragment,boolean addToBackStack){

        if (fragment.isAdded()){

            FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
            if (addToBackStack)transaction.addToBackStack(null);
            transaction.remove(fragment);
            transaction.commit();
            getSupportFragmentManager().executePendingTransactions();
            if (!addToBackStack)fragmentsList.remove(fragment);
        }
    }

    protected void setFullScreen(boolean fullScreen){

        WindowManager.LayoutParams attrs = getWindow().getAttributes();

        if (fullScreen) {

            attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
        }
        else {

            attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
        }

        getWindow().setAttributes(attrs);
    }

    protected void hideActionBar(boolean hidden){

        if (hidden){

            getSupportActionBar().hide();
        }
        else getSupportActionBar().show();
    }

    protected void setLayout(int layoutID){

        myLayout=layoutID;
    }

    public boolean onTouchEvent(MotionEvent event) {

        if (gesturesEnabled){

            this.myGestureDetector.onTouchEvent(event);
        }

        return true;
    }

    public boolean onSingleTapConfirmed(MotionEvent e) {

        My_AndroidTools.KeyboardTools.closeInputKeyboard(getCurrentFocus());
        return true;
    }

    public boolean onDoubleTap(MotionEvent e) {

        return true;
    }

    public boolean onDoubleTapEvent(MotionEvent e) {

        return true;
    }

    public boolean onDown(MotionEvent e) {

        return true;
    }

    public void onShowPress(MotionEvent e) {

    }

    public boolean onSingleTapUp(MotionEvent e) {

        return true;
    }

    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

        return true;
    }

    public void onLongPress(MotionEvent e) {

    }

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

        return false;
    }
}

This is FragmentsActivity, which extends and implements My_Activity:

package elektro_fr.newapplication;

import android.os.Bundle;
import android.util.Log;
import android.widget.RelativeLayout;

import elektro_fr.my_android.Action;
import elektro_fr.my_android.My_Activity;
import elektro_fr.my_android.My_Fragment;
import elektro_fr.newapplication.R;

public class FragmentsActivity extends My_Activity implements My_Fragment.fragmentOperations {

    private MyTopFragment topFragment;
    private MyBottomFragment bottomFragment;

    @Override
    protected void init() {

        setLayout(R.layout.fragments);
        setGestures(true);
        setMenu(true);
    }

    @Override
    protected void setGraphics() {

        Bundle args=new Bundle();
        args.putInt(MyTopFragment.LAYOUT_ID,R.layout.ts_fragment);
        args.putInt(My_Fragment.CENTER_HORIZONTAL,RelativeLayout.CENTER_HORIZONTAL);

        topFragment = (MyTopFragment) addFragment(MyTopFragment.class,R.id.MainLayout,R.layout.ts_fragment,args);

        Bundle args2=new Bundle();

        args2.putInt(My_Fragment.LAYOUT_ID,R.layout.bs_fragment);

        args2.putInt(My_Fragment.LAYOUT_WIDTH,RelativeLayout.LayoutParams.MATCH_PARENT);
        args2.putInt(My_Fragment.LAYOUT_HEIGHT,RelativeLayout.LayoutParams.WRAP_CONTENT);

        args2.putInt(My_Fragment.BELOW, R.id.ts);
        args2.putInt(My_Fragment.CENTER_HORIZONTAL,RelativeLayout.CENTER_HORIZONTAL);

        bottomFragment = (MyBottomFragment) addFragment(MyBottomFragment.class,R.id.MainLayout,R.layout.bs_fragment,args2);

        getMenuEntries().put("Menu Item #1", new Action() {

            @Override
            public void doAction() {

                Log.i("Ciccio","you pressed 1");
            }
        });

        getMenuEntries().put("Menu Item #2", new Action() {

            @Override
            public void doAction() {

                Log.i("Ciccio","you pressed 2");
            }
        });

        getMenuEntries().put("Menu Item #3", new Action() {
            @Override
            public void doAction() {

                Log.i("Ciccio","you pressed 3");
            }
        });
    }

    protected void refreshState(){

        topFragment = (MyTopFragment) getFragment(MyTopFragment.class);
        bottomFragment = (MyBottomFragment) getFragment(MyBottomFragment.class);
    }

    @Override
    public void ClickButtonOperation(Object[] arguments) {

        switch((Integer)arguments[0]){

            case 0:

                bottomFragment.setText((String)arguments[1],(String)arguments[2]);
            break;
        }
    }
}

This is My_Fragment class:

package elektro_fr.my_android;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.text.Layout;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

public abstract class My_Fragment extends Fragment {

    public final static String LAYOUT_ID="layout_id";
    public final static String LAYOUT_WIDTH="layout_width";
    public final static String LAYOUT_HEIGHT="layout_height";

    public final static String BELOW="layout_below";
    public final static String ABOVE="layout_above";

    public final static String ALIGN_PARENT_BOTTOM="align_parent_bottom";
    public final static String CENTER_HORIZONTAL="center_horizontal";

    private String[] params={

            LAYOUT_ID,LAYOUT_WIDTH, LAYOUT_HEIGHT, ALIGN_PARENT_BOTTOM, CENTER_HORIZONTAL, BELOW, ABOVE
    };

    protected int fragmentLayout;

    protected fragmentOperations myActivity;
    protected Bundle mySettings;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        if (savedInstanceState!=null){

            mySettings=new Bundle();
            mySettings.putAll(savedInstanceState);
        }
        else mySettings=getArguments();
        fragmentLayout=mySettings.getInt(LAYOUT_ID);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {

        super.onActivityCreated(savedInstanceState);

        if (savedInstanceState != null) {

            mySettings.putAll(savedInstanceState);
            refreshState();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {

        super.onSaveInstanceState(outState);

        setState();
        outState.putAll(mySettings);
    }

    public interface fragmentOperations{

        void ClickButtonOperation(Object[] arguments);
    }

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

        View view=inflater.inflate(fragmentLayout,container,false);

        int widthSettings=mySettings.getInt(params[1]);
        int heightSettings=mySettings.getInt(params[2]);

        view.setLayoutParams(new RelativeLayout.LayoutParams((widthSettings==0?RelativeLayout.LayoutParams.WRAP_CONTENT:widthSettings),(heightSettings==0?RelativeLayout.LayoutParams.WRAP_CONTENT:heightSettings)));

        RelativeLayout.LayoutParams layoutConfig= (RelativeLayout.LayoutParams) view.getLayoutParams();

        for (int counter=3;counter<params.length;counter++){

            int settings=mySettings.getInt(params[counter]);

            if (settings!=0){

                if (counter==5){

                    layoutConfig.addRule(RelativeLayout.BELOW,settings);
                }
                else if (counter==6){

                    layoutConfig.addRule(RelativeLayout.ABOVE,settings);
                }
                else{

                    layoutConfig.addRule(settings);
                }
            }
        }

        init(view);

        return view;
    }

    protected abstract void init(View v);
    protected abstract void setState();
    protected abstract void refreshState();

    @Override
    public void onAttach(Context context) {

        super.onAttach(context);
        myActivity=(fragmentOperations)getActivity();
    }
}

Aucun commentaire:

Enregistrer un commentaire