tutorial - navegar entre fragments android studio




onActivityResult no se llama en Fragmento (20)

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);
    }
}

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.


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
}

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;
}

Como mencionó Ollie C, hay un error activo para la biblioteca de soporte que usa valores devueltos para onActivityResult cuando está usando fragmentos anidados. Acabo de golpearlo :-(.

Ver code.google.com/p/android/issues/detail?id=15394 .


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).


En breve,

En fragmento, declare Fragment fragment = this ;

después de eso use fragment.startActivityForResult .

El resultado volverá en activityResult.


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);
        }
    }
}

Este es uno de los temas más populares. Podemos encontrar un montón de hilo con respecto a este problema. Pero ninguno de ellos es útil para MÍ.

Así que he resuelto este problema utilizando esta solución.

Primero entendamos por qué esto está sucediendo.

Podemos llamar a startActivityForResult directamente desde Fragment, pero en realidad todos los mecánicos están controlados por Activity.

Una vez que llame a startActivityForResult desde un Fragmento, requestCode se cambiará para adjuntar la identidad del Fragmento al código. Eso permitirá a Activity rastrear quién envía esta solicitud una vez que se recibe el resultado.

Una vez que se haya vuelto a navegar la actividad, el resultado se enviará a Activity's OnActivityResult con el requestCode modificado que se descodificará a requestCode original + identidad del fragmento. Después de eso, la Actividad enviará el Resultado de la Actividad a ese Fragmento a través de onActivityResult. Y todo está hecho.

El problema es:

La actividad podría enviar el resultado solo al Fragmento que se ha adjuntado directamente a la Actividad pero no al anidado. Esa es la razón por la cual onActivityResult de fragmento anidado nunca se llamaría sin importar qué.

Solución:

1) Inicia la Intención en tu Fragmento por el siguiente código:

       /** Pass your fragment reference **/
       frag.startActivityForResult(intent, REQUEST_CODE); // REQUEST_CODE = 12345

2) Ahora en su actividad de padres anular ** onActivityResult() : **

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

Tienes que llamar a esto en la actividad de los padres para que funcione.

3) En tu llamada de fragmento:

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

       }
}

Eso es. Con esta solución, podría aplicarse a cualquier fragmento individual, ya sea que esté anidado o no. Y sí, también cubre todo el caso! Además, los códigos también son bonitos y limpios.


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(...); .


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".


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"

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.


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.


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 .


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


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í.


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.
}

Opción 1:

Si llama a startActivityForResult() desde el fragmento, debería llamar a startActivityForResult() , no a getActivity().startActivityForResult() , ya que dará como resultado el fragmento onActivityResult ().

Si no está seguro de dónde está llamando en startActivityForResult() y cómo llamará a los métodos.

Opcion 2:

Dado que la Actividad obtiene el resultado de onActivityResult() , deberá anular el onActivityResult() la actividad y llamar a super.onActivityResult() para propagarse al fragmento respectivo para los códigos de resultados no super.onActivityResult() o para todos.

Si las dos opciones anteriores no funcionan, consulte la opción 3, ya que definitivamente funcionará.

Opción 3:

Una llamada explícita desde el fragmento a la función onActivityResult es la siguiente.

En la clase de actividad principal, anule el método onActivityResult () e incluso anule el mismo en la clase Fragment y llame al siguiente código.

En la clase padre:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane);
    fragment.onActivityResult(requestCode, resultCode, data);
}

En la clase infantil:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // In fragment class callback
}

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();
}




android-activity