1

I'm trying to save my fragment instance (at least i'd like to save model instance) in my app. I have a bottom navigation activity and this fragment get a straem of data from a ble device. I want to give te opportunity to the user so navigate in fragments while receiving data. I can do it but when I came back to the acquisition fragment it creates another instance of the object that get data so I lose controll of the one is currently working. So I want to save fragment instance. I tried every answer from this and from android developers description. As you can see from my code here I save only a boolean now to try if it works.

@Override
public void onSaveInstanceState(@NonNull Bundle saved) {
    // call superclass to save any view hierarchy

    out.println("Saving...");
    out.println(start);
    if (!start)
    {
        /*Gson gson = new Gson();
        String json= gson.toJson(model);
        out.println(json);
        outState.putString("MODEL", json);*/
        saved.putBoolean("START", start);
    }
    super.onSaveInstanceState(saved);


}

Anyway when I change fragment nothing happens, but I can save it calling this function in onDestroy callback.

    @Override
public void onDestroyView()
{
    super.onDestroyView();
    Bundle saved = new Bundle();
    this.onSaveInstanceState(saved);
    model.stop();
    model.disconnect();
    out.println("Destroy yourself");

}

But in onCreateView and in onCreate my bundle is still null. I don't understand why.

    @Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    out.println(savedInstanceState);
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        start = savedInstanceState.getBoolean("START");
        out.println(start);
    } else {
        start = false;
    }
}

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    out.println(savedInstanceState);
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        start = savedInstanceState.getBoolean("START");
        out.println(start);
    } else {
        start = false;
    }
    model = new ViewModelProvider(this).get(AcquisitionModel.class);


    model.getFreq().observe(getViewLifecycleOwner(), freq -> {
        updateFreq(freq);
    });
    model.getOrder().observe(getViewLifecycleOwner(), order -> {
        updateOrder(order);
    });
    model.getToDrawn().observe(getViewLifecycleOwner(),  toDrown-> {
        draw(toDrown);
    });
    View root = inflater.inflate(R.layout.fragment_acquisition, container, false);

    graph = (GraphView) root.findViewById(R.id.line_graph);
    graph.getViewport().setXAxisBoundsManual(true);
    GridLabelRenderer gridLabel = graph.getGridLabelRenderer();
    //gridLabel.setPadding(64);
    util = new AppUtilis(this.getContext());
    //graph.getViewport().setMaxX(5);

    series = new LineGraphSeries<>();
    graph.getViewport().setScalable(true);
    graph.getViewport().setScrollable(true);
    //series.setThickness(3);

    graph.addSeries(series);

    text= root.findViewById(R.id.frequenza);
    RG = (RadioGroup) root.findViewById(R.id.RG);
    RG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
    {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            // checkedId is the RadioButton selected

            String nonso = "";
            if (checkedId== R.id.ecg_switch) {
                TextView text= (TextView) root.findViewById(R.id.label);
                text.setText("Frequenza cardiaca (BPM)");
                nonso = "ecg";
            }
            else
            {
                TextView text= (TextView) root.findViewById(R.id.label);
                text.setText("Frequenza respiratoria");
                nonso = "resp";
            }
            model.scambio(nonso);
        }
    });

    B_start= (Button) root.findViewById(R.id.start_stop);
    B_start.setOnClickListener(new View.OnClickListener()
    { //utente pigia il bottone

        @Override

        public void onClick(View v) {

            //controllo se esiste il dispositivo
            if (model.isConnected() || disp != null) {
                boolean ans;
                if (start) {
                    ans = model.stop();
                    if (ans) {
                        start = false;//chiama lo stop
                        B_start.setText("Start");

                        //set colore standard
                        B_start.setBackgroundColor(Color.rgb(3, 218, 197));
                    }
                } else {
                    ans = model.start();
                    if (ans) {
                        start = true;
                        graph.removeAllSeries();
                        series = new LineGraphSeries<>();
                        series.setThickness(3);
                        graph2LastXValue = 0d;
                        graph.addSeries(series);
                        B_start.setText("Stop");
                        B_start.setBackgroundColor(Color.rgb(255, 0, 0));
                    }
                }
            }
            else
            {
                util.alert("Attenzione", "Non sei connesso!");
            }

        }

    });
    B_export = (Button) root.findViewById(R.id.exp);
    B_export.setOnClickListener(new View.OnClickListener()
    { //utente pigia il bottone
        @Override

        public void onClick(View v) {
            Log.d("saving", "premuto");
            if (model.isConnected() || disp != null) {


                util.loading("Sto salvando", false);
                model.stop();
                start = false;//chiama lo stop
                B_start.setText("Start");
                B_start.setBackgroundColor(Color.rgb(3, 218, 197));

                boolean ans = model.saveAll();
                analyzeCough(model.getResp().getFile(), model.fc);

                util.loadingFinished();
                if (ans)
                {
                    util.alert("Successo", "Esportazione avvenuta! Cerca nella cartella Registrazioni nella memoria interna del telefono");
                }
                else {
                    util.alert("Errore", "Esportazione fallita");
                }

            }
            else
            {
                util.alert("Attenzione", "Non sei connesso!");
            }
        }
    });
    share = root.findViewById(R.id.share);
    share.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (model.isConnected() || disp != null) {
                //funzione per condividere i file
                //controllo se non sia già stato fatto un export
                util.loading("Sto salvando", false);
                //model.disconnect();
                start = false;//chiama lo stop
                B_start.setText("Start");
                B_start.setBackgroundColor(Color.rgb(3, 218, 197));
                model.stop();
                boolean ansi = model.saveAll();
                analyzeCough(model.getResp().getFile(), model.fc);
                ArrayList<File> fil = model.getAllFiles();
                util.loadingFinished();
                if (ansi) {
                    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
                    StrictMode.setVmPolicy(builder.build());
                    //provo la condivisione
                    //prendi i path con una funzione dal model
                    try {
                        Intent sharingIntent = new Intent();
                        sharingIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
                        sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "Here are some files.");
                        sharingIntent.setType("text/*");
                        ArrayList<Uri> files = new ArrayList<Uri>();
                        for (int i = 0; i < fil.size(); i++) {
                            files.add(Uri.fromFile(fil.get(i)));
                        }
                        sharingIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, files);
                        startActivity(Intent.createChooser(sharingIntent, "Condividi con"));
                        out.println("Post sharing");
                    } catch (Exception e) {
                        e.printStackTrace();
                        util.alert("Errore", "Condivisione fallita!");
                    }

                } else {
                    util.alert("Errore", "Condivisione fallita");
                }
            }
            else
            {
                util.alert("Attenzione", "Non sei connesso!");
            }

        }
    });
    return root;
}

I also tried to save the fragment from activity as mentioned by someone as answer in the link I posted before but it doesn't work too. Has someone any idea? Thanks in advance.

EDIT Here is my onCreate in Activity

    @Override
protected void onCreate(Bundle savedInstanceState) {
    model = new ViewModelProvider(this).get(ConnectionViewModel.class);
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.INTERNET},
            REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
        // solo funzioni nuove e solo se non è già stato accettato
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
        Uri uri = Uri.fromParts("package", this.getPackageName(), null);
        intent.setData(uri);
        startActivity(intent);
    }
    try {
        setTheme(R.style.splashScreenTheme);
        super.onCreate(savedInstanceState);
        sleep(2000);
    } catch (Exception e) {
        e.printStackTrace();
    }
    setTheme(R.style.Theme_Ble);
    setContentView(R.layout.activity_main3);
    BottomNavigationView navView = findViewById(R.id.nav_view);
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
            R.id.tosse, R.id.grafici, R.id.elettrodi)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);

    util = new AppUtilis(this);
    NavigationUI.setupWithNavController(navView, navController);
    Button easter;
    easter = (Button) findViewById(R.id.easterEgg);
    easter.setOnClickListener(new View.OnClickListener()
    {

        @Override
        public void onClick(View v)
        {
            System.out.println("uovooooo");
            Intent intent = new Intent(util.getContext(), SettingsActivity.class);
            System.out.println("Vado a cercare roba");
            startActivityForResult(intent, 3);

        }
    });
    Ble = (ImageButton) findViewById(R.id.IconaBle);
    Ble.setOnClickListener(new View.OnClickListener()
    {

        @Override
        public void onClick(View v)
        {
            final BluetoothManager bluetoothManager =
                    (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();


            // Ensures Bluetooth is available on the device and it is enabled. If not,
            // displays a dialog requesting user permission to enable Bluetooth.
            final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled() ||  !manager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
                /*
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);*/
                util.alert("GPS e Bluetooth", "Per trovare dispositivi devi attivare GPS e Bluetooth");
            }
            else
            {
                Intent intent = new Intent(util.getContext(), BleScan.class);
                System.out.println("Vado a cercare roba");
                startActivityForResult(intent, 2);
            }

        }
    });

}
Sam
  • 51
  • 6

1 Answers1

0

If you save any data in onDestoryView() it means app is closed. And savedInstanceState doesn't survive app close unless it is forcibly closed by system it self. So, onCreate() will print null even you saved the instance. Plus onDestroyView() doesn't necessariliy called always. Sometime os doesn't call onDestroyView(). You should try saving the object inside onPause() or onStop() if user is not leaving the app and you are loading the saved instance.

  • Ok, it makes sense, but how can i avoid onDestroy when I change fragment? I mean when i go to another fragment onDestroy is called anyway so my instance is deleted in any case... – Sam Jul 09 '21 at 09:23
  • Can i see your code how you are switching between two fragments? – Anirudhdhsinh Jadeja Jul 09 '21 at 09:34
  • Of course, but in my activity I do nothing to switch activities, so do you mean xml code? Or where i can find the java code that handles this operation? – Sam Jul 09 '21 at 09:40
  • Where i can find it? Sorry, i am a noob – Sam Jul 09 '21 at 09:42
  • Ok maybe i've found it i update the original post – Sam Jul 09 '21 at 09:44
  • I find no fragment transaction in your java file. You are simply starting new activity. – Anirudhdhsinh Jadeja Jul 09 '21 at 09:46
  • Check now i posted my main acitivity where i host my fragments – Sam Jul 09 '21 at 09:48
  • There is only one fragment in your java file. So, whenever you start new activity that fragment is getting destroyed. You are going to activity from fragment. instead try to create another fragment and go to that fragment from this fragment. – Anirudhdhsinh Jadeja Jul 09 '21 at 09:54
  • Thank you! How can I do that? I need to touch something in my activity too? – Sam Jul 09 '21 at 10:03
  • 1
    You need to first understand your code. And try to implement the code written in your next activity in your second fragment. And then you should switch between fragments. – Anirudhdhsinh Jadeja Jul 09 '21 at 10:14