android example - onActivityResult no se llama en Fragmento




fragments tutorial (25)

La actividad que alberga este fragmento tiene su onActivityResult cuando la actividad de la cámara regresa.

Mi fragmento inicia una actividad para obtener un resultado con la intención enviada para que la cámara tome una fotografía. La aplicación de imagen se carga bien, toma una imagen y regresa. El onActivityResult sin embargo nunca se golpea. He establecido puntos de interrupción, pero nada se activa. ¿Puede un fragmento tener onActivityResult ? Yo creo que sí, ya que es una función proporcionada. ¿Por qué no se está activando esto?

ImageView myImage = (ImageView)inflatedView.findViewById(R.id.image);
myImage.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(cameraIntent, 1888);
    }
});

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if( requestCode == 1888 ) {
        Bitmap photo = (Bitmap) data.getExtras().get("data");
        ((ImageView)inflatedView.findViewById(R.id.image)).setImageBitmap(photo);
    }
}

Answers

PARA FRAGMENTOS ANULADOS (por ejemplo, cuando se utiliza un ViewPager)

En tu actividad principal:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
}

En su fragmento principal de nivel superior (fragmento ViewPager):

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    YourFragment frag = (YourFragment) getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());
    frag.yourMethod(data);  // Method for callback in YourFragment
    super.onActivityResult(requestCode, resultCode, data);
}

En YourFragment (fragmento anidado):

public void yourMethod(Intent data){
    // Do whatever you want with your data
}

Si el problema anterior se enfrenta al inicio de sesión de Facebook , puede usar el código siguiente en una actividad principal de su fragmento como:

Fragment fragment = getFragmentManager().findFragmentById(android.R.id.tabcontent);
fragment.onActivityResult(requestCode, resultCode, data);

O:

Fragment fragment = getFragmentManager().findFragmentById("fragment id here");
fragment.onActivityResult(requestCode, resultCode, data);

Y añada la siguiente llamada en su fragmento ...

callbackManager.onActivityResult(requestCode, resultCode, data);

La actividad de alojamiento anula onActivityResult() , pero no realizó una llamada a super.onActivityResult() para los códigos de resultados no super.onActivityResult() . Aparentemente, aunque el fragmento es el que realiza la llamada startActivityForResult() , la actividad obtiene la primera oportunidad de manejar el resultado. Esto tiene sentido cuando se considera la modularidad de los fragmentos. Una vez que implementé super.onActivityResult() para todos los resultados no super.onActivityResult() , el fragmento tuvo una oportunidad de manejar el resultado.

Y también de la respuesta @siqing:

Para obtener el resultado en su fragmento, asegúrese de llamar a startActivityForResult(intent,111); en lugar de getActivity().startActivityForResult(intent,111); dentro de tu fragmento.


La mayoría de estas respuestas siguen diciendo que debe llamar a super.onActivityResult(...) en su Activity host para su Fragment . Pero eso no parecía estar funcionando para mí.

Por lo tanto, en su Activity host, debe llamar a su Fragments onActivityResult(...) lugar. Aquí hay un ejemplo.

public class HostActivity extends Activity {

    private MyFragment myFragment;

    protected void onActivityResult(...) {
        super.onActivityResult(...);
        this.myFragment.onActivityResult(...);
    }
}

En algún momento de su HostActivity , deberá asignar a this.myFragment el Fragment que está utilizando. O use FragmentManager para obtener el Fragment lugar de mantener una referencia a él en su HostActivity . Además, compruebe si hay un null antes de intentar llamar a this.myFragment.onActivityResult(...); .


También enfrenté el mismo problema una vez que cambié este bloque de código fuera de un Fragmento a una Clase de Utilidad , con parentActivity pasado como argumento ,

Intent intent = new Intent(parentActivity, CameraCaptureActivity.class);
parentActivity.startActivityForResult(intent,requestCode);

Entonces no estaba obteniendo ningún valor en el método onActivityResult de ese Fragmento . Después, cambié el argumento a Fragmento , por lo que la definición revisada de método parecía

Intent intent = new Intent(fragment.getContext(), CameraCaptureActivity.class);
fragment.startActivityForResult(intent,requestCode);

Después de eso, pude obtener valor en onActivityResult en el Fragmento


Su código tiene un fragmento anidado. Llamar a super.onActivityForResult no funciona

No desea modificar todas las actividades desde las que se puede llamar a su fragmento ni hacer una solución para llamar a cada fragmento en la cadena de fragmentos.

Aquí está una de las muchas soluciones de trabajo. cree un fragmento sobre la marcha y conéctelo directamente a la actividad con el administrador de fragmentos de soporte. Luego llame a startActivityForResult desde el fragmento recién creado.

private void get_UserEmail() {

    if (view == null) {
        return;
    }
    ((TextView) view.findViewById(R.id.tvApplicationUserName))
            .setText("Searching device for user accounts...");

    final FragmentManager fragManager = getActivity().getSupportFragmentManager();

    Fragment f = new Fragment() {
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            startActivityForResult(AccountPicker.newChooseAccountIntent(null, null,
                    new String[]{"com.google"}, false, null, null, null, null), REQUEST_CODE_PICK_ACCOUNT);
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode,
                                     Intent data) {
            if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
                String mEmail = "";
                if (resultCode == Activity.RESULT_OK) {
                    if (data.hasExtra(AccountManager.KEY_ACCOUNT_NAME)) {
                        mEmail = data
                                .getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                    }
                }
                if (mActivity != null) {
                    GoPreferences.putString(mActivity, SettingApplication.USER_EMAIL, mEmail);
                }
                doUser();
            }
            super.onActivityResult(requestCode, resultCode, data);
            fragManager.beginTransaction().remove(this).commit();
        }
    };
    FragmentTransaction fragmentTransaction = fragManager
            .beginTransaction();
    fragmentTransaction.add(f, "xx" + REQUEST_CODE_PICK_ACCOUNT);
    fragmentTransaction.commit();
}

En mi caso, se trata de un error de Android ( http://technet.weblineindia.com/mobile/onactivityresult-not-getting-called-in-nested-fragments-android/ ), si utiliza FragmentActivity compatible, debe usar getSupportFragmentManager en getSupportFragmentManager lugar. de getChildFragmentManager :

List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
    for (Fragment fragment : fragments) {
        if(fragment instanceof UserProfileFragment) {
            fragment.onActivityResult(requestCode, resultCode, data);
        }
    }
}

Si está utilizando fragmentos anidados, esto también funciona:

getParentFragment().startActivityForResult(intent, RequestCode);

Además de esto, debe llamar a super.onActivityResult de la actividad principal y completar el método onActivityResult del fragmento.


Dentro de tu fragmento, llama

this.startActivityForResult(intent, REQUEST_CODE);

Cuando this se refiere al fragmento. De lo contrario, haz lo que dijo @Clevester:

Fragment fragment = this;
....
fragment.startActivityForResult(intent, REQUEST_CODE);

También tuve que llamar

super.onActivityResult(requestCode, resultCode, data);

en la actividad de los padres, onActivityResult para que funcione.

(Adapté esta respuesta de la respuesta de @Clevester).


Puedo agregar dos consejos si alguien todavía no puede hacerlo. En el archivo Manifest.xml, asegúrese de que la actividad de hospedaje no haya finalizado cuando se devuelva la llamada y que la actividad a comenzar tenga el modo de inicio como estándar. Vea los detalles a continuación:

Para la actividad de Hosting, establezca la propiedad sin historial como falsa si tiene

android:noHistory="false"

Para que se inicie la actividad, configure el modo de inicio como estándar si tiene

android:launchMode="standard"

En caso de que no sepa fragmentos en su actividad, simplemente enumérelos todos y envíe los argumentos de los resultados de la actividad:

// In your activity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    for (Fragment fragment : getSupportFragmentManager().getFragments()) {
        fragment.onActivityResult(requestCode, resultCode, data);
    }
}

PARA MUCHOS FRAGMENTOS ANULADOS (por ejemplo, cuando se utiliza un ViewPager en un fragmento)

En tu actividad principal :

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
}

En tu fragmento:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    for (Fragment fragment : getChildFragmentManager().getFragments()) {
        fragment.onActivityResult(requestCode, resultCode, data);
    }
}

En tu fragmento anidado

Actividad de llamada

getParentFragment().startActivityForResult(intent, uniqueInstanceInt);

uniqueInstanceInt : reemplácelo con un int que sea único entre los fragmentos anidados para evitar que otro fragmento trate la respuesta.

Recibir respuesta

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == uniqueInstanceInt ) {
        // TODO your code
    }
}

Atención

Es necesario utilizar un número entre 0 y 65536 en uniqueInstanceInt para evitar el error "Solo se pueden usar 16 bits más bajos para requestCode".


Un punto que nadie ha mention que asegúrese de que el modo de inicio de la Actividad del Host no se debe configurar en singleInstance o singleTask .

onActivityResult no funcionará si su modo de inicio está establecido en SingleInstance o SingleTask. o llamas a tu actividad usando estos IntentFilters

standard modo de lanzamiento standard o singleTop funcionará bien.


Si hay problemas con el método onActivityResult que está dentro de la clase de fragmento y desea actualizar algo que también está dentro de la clase de fragmento, use:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(resultCode == Activity.RESULT_OK)
    {
        // If the user had agreed to enabling Bluetooth,
        // populate the ListView with all the paired devices.
        this.arrayDevice = new ArrayAdapter<String>(this.getContext(), R.layout.device_item);
        for(BluetoothDevice bd : this.btService.btAdapater.getBondedDevices())
        {
            this.arrayDevice.add(bd.getAddress());
            this.btDeviceList.setAdapter(this.arrayDevice);
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Solo agrega la this.variable como se muestra en el código anterior. De lo contrario, se llamará al método dentro de la actividad principal y la variable no se actualizará de la instancia actual.

También lo probé poniendo este bloque de código en MainActivity , reemplazándolo con la clase HomeFragment y teniendo las variables estáticas. Obtuve resultados como esperaba.

Entonces, si desea que la clase de fragmento tenga su propia implementación de onActivityResult , el ejemplo de código anterior es la respuesta.


Estoy teniendo este mismo problema con ChildFragmentManager . El administrador no pasará el resultado al fragmento anidado, debe hacerlo manualmente en su fragmento base.

public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    Fragment fragment = (Fragment) getChildFragmentManager().findFragmentByTag(childTag);
    if (fragment != null) {
        fragment.onActivityResult(requestCode, resultCode, intent);
    }
}

Simplemente use el siguiente código para el fragmento.

@Override
public void onOtherButtonClick(ActionSheet actionSheet, int index) {

    if (index == 1)
    {
        Intent intent = new Intent(Intent.ACTION_PICK,
                                   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/*");
        startActivityForResult(Intent.createChooser(intent,
                                                    "Select Picture"), 1);
     }
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == 1) {
        if (requestCode == 1) {
            Uri selectedImageUri = data.getData();
            //selectedImagePath = getPath(selectedImageUri);
        }
    }
}

onActivityResult llamará sin llamar a su padre.


Creo que getActivity().startActivityForResult(intent,111); . Debe llamar a startActivityForResult(intent,111); .


Una de las formas más simples es comenzar una actividad desde su fragmento.

startActivity(ActivityName);

Luego, agregue lo que llama startActivityForResult(intent,"1"); de su actividad y agregue onActivityResult en su actividad

startActivityForResult(intent,"1");

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane);
    fragment.onActivityResult(requestCode, resultCode, data);
// perform other activity result like fetching from Uris or handling cursors

finish(); // finish the activity will  get to back to your fragment.
}

En breve,

En fragmento, declare Fragment fragment = this ;

después de eso use fragment.startActivityForResult .

El resultado volverá en activityResult.


public class takeimage extends Fragment {

    private Uri mImageCaptureUri;
    private static final int PICK_FROM_CAMERA = 1;
    private static final int PICK_FROM_FILE = 2;
    private String mPath;
    private ImageView mImageView;
    Bitmap bitmap = null;
    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.activity_send_image, container, false);
        final String[] items = new String[] { "From Camera", "From SD Card" };
        mImageView = (ImageView)view.findViewById(R.id.iv_pic);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.select_dialog_item, items);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("Select Image");

        builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int item) {
                if (item == 0) {
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    File file = new File(Environment.getExternalStorageDirectory(), "tmp_avatar_"
                        + String.valueOf(System.currentTimeMillis())
                        + ".jpg");
                    mImageCaptureUri = Uri.fromFile(file);

                    try {
                        intent.putExtra(
                            android.provider.MediaStore.EXTRA_OUTPUT,
                            mImageCaptureUri);
                        intent.putExtra("return-data", true);

                        getActivity().startActivityForResult(intent,
                            PICK_FROM_CAMERA);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    dialog.cancel();
                } else {
                    Intent intent = new Intent();

                    intent.setType("image/*");
                    intent.setAction(Intent.ACTION_GET_CONTENT);

                    getActivity().startActivityForResult(
                        Intent.createChooser(intent,
                            "Complete action using"), PICK_FROM_FILE);
                }
            }
        });
        final AlertDialog dialog = builder.create();

        Button show = (Button) view.findViewById(R.id.btn_choose);
        show.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // Switch the tab content to display the list view.
                dialog.show();
            }
        });

    return view;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode != Activity.RESULT_OK)
            return;

        if (requestCode == PICK_FROM_FILE) {
            mImageCaptureUri = data.getData();
            // mPath = getRealPathFromURI(mImageCaptureUri); //from Gallery

            if (mPath == null)
                mPath = mImageCaptureUri.getPath(); // from File Manager

            if (mPath != null)
                bitmap = BitmapFactory.decodeFile(mPath);
        } else {
            mPath = mImageCaptureUri.getPath();
            bitmap = BitmapFactory.decodeFile(mPath);
        }
        mImageView.setImageBitmap(bitmap);  
    }

    public String getRealPathFromURI(Uri contentUri) {
        String [] proj = {MediaStore.Images.Media.DATA};
        Cursor cursor = managedQuery(contentUri, proj, null, null,null);

        if (cursor == null) return null;

        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }
} 

Tengo una fuerte sospecha de que todas las respuestas aquí no son más que hacks. Los he probado todos y muchos otros, pero sin ninguna conclusión confiable, ya que siempre hay algún tipo de problema estúpido. Por mi parte, no puedo confiar en resultados inconsistentes. Si miras la documentación oficial de la API de Android para Fragmentos, verás que Google establece claramente lo siguiente:

Llame a startActivityForResult (Intent, int) desde la actividad que contiene el fragmento.

Ver: API de fragmento de Android

Por lo tanto, parece que el enfoque más correcto y confiable sería llamar a startActivityForResult () desde la actividad de alojamiento y también manejar el onActivityResult () resultante desde allí.


También me encontré con este problema en un fragmento. Y llamé a startActivityForResult en un DialogFragment .

Pero ahora este problema se ha resuelto:
FragmentClassname.this.startActivityForResult .


Solución 1:

Llame a startActivityForResult(intent, REQUEST_CODE); en lugar de getActivity().startActivityForResult(intent, REQUEST_CODE); .

Solución 2:

When startActivityForResult(intent, REQUEST_CODE); se llama onActivityResult(requestCode,resultcode,intent) la actividad onActivityResult(requestCode,resultcode,intent) se invoca, y luego se pueden llamar fragments onActivityResult() desde aquí, pasando el requestCode, resultCode and intent .


Acabo de hacer un método de solución:

public static Fragment _tempFragment = null;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(_tempFragment != null)
        _tempFragment.onActivityResult(requestCode, resultCode, data);
}

En tu Fragmento, antes de startActivityResult, establece

MainActivity._tempFragment = this;

Después de onActivityResult <- en Fragmento

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
     super.onActivityResult(requestCode, resultCode, data);

     // Do your job
     {

     }
     MainActivity._tempFragment = null;
}

muy simple

Bitmap tempBMP = BitmapFactory.decodeResource(getResources(),R.drawable.image);






android android-fragments android-activity