How to pass data to Activity itself after the camera is called?

Asked

Viewed 287 times

0

I have a Activity with a EditText and a Button. When the button is clicked, the typed text is saved in a Activity and the camera is opened with the method startActivityForResult().

When the user takes the photo and clicks save, the method onActivityResult() is called but the attribute is null.

I researched about and found that depending on some settings can prevent the Activity to be destroyed, but should only be used as a last resort. I then followed the most recommended way and none of the techniques I read on Stackoverflow (except SharedPreferences) worked out.

Below is what I tried:

package cadastro.caelum.com.br.testfragment;

import android.app.Activity;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.PersistableBundle;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends ActionBarActivity {

    private String parameter;
    private RetainedFragment dataFragment;
    private static final int CONFIGURATION_CHANGE = 1335;
    private static final String EXTRA_KEY = "extrakey";
    private static final String SHARED_KEY = "sharedkey";

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

        // find the retained fragment on activity restarts
        FragmentManager fm = getFragmentManager();
        dataFragment = (RetainedFragment) fm.findFragmentByTag("data");

        // create the fragment and data the first time
        if (dataFragment == null) {
            // add the fragment
            dataFragment = new RetainedFragment();
            fm.beginTransaction().add(dataFragment, "data").commit();
            // load the initial value of the String
            dataFragment.setData("My String");
        }

        // the data is available in dataFragment.getData()

        // On button clicked, open the camera for testing cofiguration changes
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Try to save the typed value at parameter
                EditText editText = (EditText) findViewById(R.id.edit);
                parameter = editText.getText().toString();
                // Open the camera
                Intent openCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                openCamera.putExtra(EXTRA_KEY, editText.getText().toString());
                startActivityForResult(openCamera, MainActivity.CONFIGURATION_CHANGE);
            }
        });

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // store the data in the fragment
        // saves the EditText's value into the fragment's data
        EditText edit = (EditText)findViewById(R.id.edit);
        dataFragment.setData(edit.getText().toString());
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CONFIGURATION_CHANGE){
            if(resultCode == Activity.RESULT_OK){
                // Try to get the fragment String
                String string = dataFragment.getData();
                if(string == null){
                    Log.i("happens", "fragment string is null");
                }else {
                    Log.i("happens", "fragment string = "+string);
                }
                // Try to get the extras String
                Bundle extras = data.getExtras();
                string = extras.getString(EXTRA_KEY);
                if(string == null){
                    Log.i("happens", "extra string is null");
                }else {
                    Log.i("happens", "extra string = "+string);
                }
                // Try to get the parameter String
                string = parameter;
                if(string == null){
                    Log.i("happens", "parameter string is null");
                }else {
                    Log.i("happens", "parameter string = "+string);
                }
            }
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outState.putString("myName", "Felipe");
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        EditText edit = (EditText) findViewById(R.id.text);
        String string = savedInstanceState.getString("myName");
        if(string==null){
            Log.i("happens", "bundle string is null");
        }else {
            edit.setText(string);
            Log.i("happens", "bundle string = " +string);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

And the class RetainedFragment:

package cadastro.caelum.com.br.testfragment;

import android.app.Fragment;
import android.os.Bundle;

/**
 * Created by WindowsLipe on 05/08/2015.
 */
public class RetainedFragment extends Fragment {

    // data object we want to retain
    private String data;

    // this method is only called once for this fragment
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // retain this fragment
        setRetainInstance(true);
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }

}

The logcat was the following

08-06 13:22:23.059  20736-20736/cadastro.caelum.com.br.testfragment I/happens﹕ bundle string is null
08-06 13:22:23.059  20736-20736/cadastro.caelum.com.br.testfragment I/happens﹕ fragment string is null
08-06 13:22:23.069  20736-20736/cadastro.caelum.com.br.testfragment I/happens﹕ extra string is null
08-06 13:22:23.069  20736-20736/cadastro.caelum.com.br.testfragment I/happens﹕ parameter string is null
  • What do you intend to do with openCamera.putExtra(EXTRA_KEY, editText.getText().toString());?

  • @ramaral Pass the value of EditText to the camera because I think they will be returned automatically in the method onActivityResult of MainActivity within the parameter Intent data.

  • What will this Edittext have? It is the way to the photo?

  • @ramaral No, I just want to save the values of my attributes MainActivity why when the camera is opened, the Activity is destroyed and loses all its attributes. I tried to follow the tutorial of the android site called Handling Runtime Changes but there is a class (DataFragment) that they do not show the code and that it seems to be a subclass of the class they create (RetainedFragment) because they do the attribute of the type RetainedFragment receive an instant from this DataFragment. Replaces then Data->Retained.

  • There are many values you want to keep?

  • @ramaral Actually no, just a string.

  • I just noticed the attribute parameter remains intact if and only if the person takes the photo without ending in a different orientation from when started. So it seems that actually open the camera does not destroy the MainActivity: she keeps spinning foreground. When the person finishes with the camera, goes back to the previous Activity and changes the orientation, and as the Activities are destroyed when they change orientation, the attribute is lost.

Show 2 more comments

1 answer

0

The simplest way to persist a value during Activity destruction/recreation is to do the override of the method onSaveInstanceState() and keep this value in Bundle passed to him.

private String valor;
@Override
public void onSaveInstanceState(Bundle bundle)
{
    super.onSaveInstanceState(bundle);
    bundle.putString("valor", valor);
}  

This value can then be recovered, in the method onCreate(), at the time when Activity is recreated.

public void onCreate(Bundle savedInstanceState)
{
    if (savedInstanceState != null){

        valor = savedInstanceState.getString("valor");
    }

}
  • The page Handling Runtime Changes says we can use both the onCreate as to the onRestoreInstanceState. In case I used the onRestoreInstanceState in my code and it didn’t work. I just tried onCreate and appeared the same thing: 08-10 23:21:03.923 7120-7120/cadastro.caelum.com.br.testfragment I/happens﹕ bundle string is null

  • Do as I say in the answer. The first time Activity is created savedInstanceState is void after there is a Configuration change the method onCreate() is called and is passed the Bundle savedInstanceState with the data saved in the method onSaveInstanceState()

Browser other questions tagged

You are not signed in. Login or sign up in order to post.