Jak zarządzać startActivityForResult na Androidzie?

W mojej aktywności nazywam drugą Aktywność od głównej aktywności przez startActivityForResult. W moim drugim ćwiczeniu są metody, które kończą to ćwiczenie (może bez rezultatu), jednak tylko jedna z nich zwraca wynik.

Na przykład, z głównego działania, nazywam drugą. W tej czynności sprawdzam niektóre funkcje telefonu, takie jak czy ma aparat. Jeśli nie ma, zamknę tę działalność. Również podczas przygotowywania MediaRecorder lub MediaPlayer Jeśli pojawi się problem, zamknę tę działalność.

Jeśli jego urządzenie ma kamerę i nagrywanie odbywa się całkowicie, to po nagraniu wideo, jeśli użytkownik kliknie przycisk Gotowe, wyślę wynik (adres nagranego wideo) z powrotem do głównej aktywności.

Jak sprawdzić wynik z głównej aktywności?

Author: Nmk, 2012-05-02

12 answers

Z twojego FirstActivity wywołaj SecondActivity używając metody startActivityForResult()

Na przykład:

int LAUNCH_SECOND_ACTIVITY = 1
Intent i = new Intent(this, SecondActivity.class);
startActivityForResult(i, LAUNCH_SECOND_ACTIVITY);

W swoim SecondActivity ustaw dane, do których chcesz wrócić FirstActivity. Jeśli nie chcesz wracać, Nie ustawiaj żadnych.

Na przykład: w SecondActivity jeśli chcesz przesłać dane zwrotne:

Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(Activity.RESULT_OK,returnIntent);
finish();

Jeśli nie chcesz zwracać danych:

Intent returnIntent = new Intent();
setResult(Activity.RESULT_CANCELED, returnIntent);
finish();

Teraz w swojej klasie FirstActivity wpisz następujący kod dla metody onActivityResult().

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

    if (requestCode == LAUNCH_SECOND_ACTIVITY) {
        if(resultCode == Activity.RESULT_OK){
            String result=data.getStringExtra("result");
        }
        if (resultCode == Activity.RESULT_CANCELED) {
            //Write your code if there's no result
        }
    }
}//onActivityResult

Aby zaimplementować przekazywanie danych między dwoma działaniami w znacznie lepszy sposób w Kotlinie proszę przejść przez ten link 'lepszy sposób przekazywania danych między działaniami '

 2545
Author: Nishant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-03 22:14:18

Jak sprawdzić wynik z głównej aktywności?

Musisz nadpisać Activity.onActivityResult() następnie sprawdź jego parametry:

  • requestCode określa, która aplikacja zwróciła te wyniki. Jest to definiowane przez Ciebie, gdy wywołujesz startActivityForResult().
  • resultCode informuje, czy ta aplikacja się powiodła, zawiodła, czy coś innego
  • data przechowuje wszelkie informacje zwracane przez tę aplikację. Może to być null.
 52
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-13 05:03:27

Przykład

Aby zobaczyć cały proces w kontekście, oto odpowiedź uzupełniająca. Zobacz moja pełniejsza odpowiedź po więcej wyjaśnień.

Tutaj wpisz opis obrazka

główna aktywność.java

public class MainActivity extends AppCompatActivity {

    // Add a different request code for every activity you are starting from here
    private static final int SECOND_ACTIVITY_REQUEST_CODE = 0;

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

    // "Go to Second Activity" button click
    public void onButtonClick(View view) {

        // Start the SecondActivity
        Intent intent = new Intent(this, SecondActivity.class);
        startActivityForResult(intent, SECOND_ACTIVITY_REQUEST_CODE);
    }

    // This method is called when the second activity finishes
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // check that it is the SecondActivity with an OK result
        if (requestCode == SECOND_ACTIVITY_REQUEST_CODE) {
            if (resultCode == RESULT_OK) { // Activity.RESULT_OK

                // get String data from Intent
                String returnString = data.getStringExtra("keyName");

                // set text view with string
                TextView textView = (TextView) findViewById(R.id.textView);
                textView.setText(returnString);
            }
        }
    }
}

druga aktywność.java

public class SecondActivity extends AppCompatActivity {

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

    // "Send text back" button click
    public void onButtonClick(View view) {

        // get the text from the EditText
        EditText editText = (EditText) findViewById(R.id.editText);
        String stringToPassBack = editText.getText().toString();

        // put the String to pass back into an Intent and close this activity
        Intent intent = new Intent();
        intent.putExtra("keyName", stringToPassBack);
        setResult(RESULT_OK, intent);
        finish();
    }
}
 49
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-17 17:50:33

Uzupełniając odpowiedź od @Nishant, najlepszym sposobem na zwrócenie wyniku aktywności jest:

Intent returnIntent = getIntent();
returnIntent.putExtra("result",result);
setResult(RESULT_OK,returnIntent);
finish();

Miałem problem z

new Intent();

Potem dowiedziałem się, że prawidłowym sposobem jest użycie

getIntent();

Aby uzyskać aktualny zamiar

 45
Author: Julian Alberto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-26 20:40:47

Dla tych, którzy mają problem z błędnym requestCode w onActivityResult

Jeśli wywołujesz startActivityForResult() z Fragment, kod żądania jest zmieniany przez aktywność, która jest właścicielem fragmentu.

Jeśli chcesz uzyskać poprawny kod wyniku w swojej aktywności, spróbuj tego:

Zmiana:

startActivityForResult(intent, 1); do:

getActivity().startActivityForResult(intent, 1);

 12
Author: Tomasz Mularczyk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:53

Jeśli chcesz zaktualizować interfejs użytkownika o wynik aktywności, nie możesz użyć this.runOnUiThread(new Runnable() {} W ten sposób interfejs użytkownika nie będzie odświeżany z nową wartością. Zamiast tego możesz to zrobić:

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

    if (resultCode == RESULT_CANCELED) {
        return;
    }

    global_lat = data.getDoubleExtra("LATITUDE", 0);
    global_lng = data.getDoubleExtra("LONGITUDE", 0);
    new_latlng = true;
}

@Override
protected void onResume() {
    super.onResume();

    if(new_latlng)
    {
        PhysicalTagProperties.this.setLocation(global_lat, global_lng);
        new_latlng=false;
    }
}
To wydaje się głupie, ale działa całkiem dobrze.
 10
Author: DaviF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-08 13:54:56

Activiresultregistry jest zalecanym podejściem

ComponentActivity teraz dostarcza ActivityResultRegistry, który pozwala obsługiwać startActivityForResult()+onActivityResult() jak również requestPermissions()+onRequestPermissionsResult() przepływy bez nadpisywania metod w Activity lub Fragment, zwiększają bezpieczeństwo typu poprzez ActivityResultContract i zapewniają Hooki do testowania tych przepływów.

Zdecydowanie zaleca się stosowanie interfejsów API wyników aktywności wprowadzonych w AndroidX Activity 1.2.0-alpha02 i Fragment 1.3.0-alpha02.

Dodaj to do swojego build.gradle

def activity_version = "1.2.0-beta01"

// Java language implementation
implementation "androidx.activity:activity:$activity_version"
// Kotlin
implementation "androidx.activity:activity-ktx:$activity_version"

Jak korzystać z umowy przedwstępnej?

Ten nowy API ma następujące wbudowane funkcje

  1. TakeVideo
  2. PickContact
  3. GetContent
  4. GetContents
  5. OpenDocument
  6. OpenDocuments
  7. OpenDocumentTree
  8. CreateDocument
  9. Wybierz
  10. TakePicture
  11. RequestPermission
  12. RequestPermissions

Przykład, który wykorzystuje takePicture kontrakt:

private val takePicture = prepareCall(ActivityResultContracts.TakePicture()) { bitmap: Bitmap? ->
    // Do something with the Bitmap, if present
}
    
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    button.setOnClickListener { takePicture() }
}
Co tu się dzieje? Rozwalmy to trochę. takePicture jest tylko wywołaniem zwrotnym, które zwraca nullable Bitmap - to, czy jest null, zależy od tego, czy proces onActivityResult zakończył się sukcesem. prepareCall następnie zarejestruje to wywołanie do nowej funkcji na ComponentActivity o nazwie ActivityResultRegistry - wrócimy do tego później. ActivityResultContracts.TakePicture() jest jednym z wbudowanych helperów, które Google dla nas stworzyło, i wreszcie wywołanie takePicture faktycznie wyzwala intencję w ten sam sposób, w jaki ty wcześniej z Activity.startActivityForResult(intent, REQUEST_CODE).

Jak napisać niestandardową umowę?

Prosta umowa, która pobiera Int jako dane wejściowe i zwraca łańcuch, który żądana aktywność zwraca w wyniku intencji.

class MyContract : ActivityResultContract<Int, String>() {

    companion object {
        const val ACTION = "com.myapp.action.MY_ACTION"
        const val INPUT_INT = "input_int"
        const val OUTPUT_STRING = "output_string"
    }

    override fun createIntent(input: Int): Intent {
        return Intent(ACTION)
            .apply { putExtra(INPUT_INT, input) }
    }

    override fun parseResult(resultCode: Int, intent: Intent?): String? {
        return when (resultCode) {
            Activity.RESULT_OK -> intent?.getStringExtra(OUTPUT_STRING)
            else -> null
        }
    }
}

class MyActivity : AppCompatActivity() {

    private val myActionCall = prepareCall(MyContract()) { result ->
        Log.i("MyActivity", "Obtained result: $result")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        button.setOnClickListener {
            myActionCall(500)
        }
    }
}

Sprawdź to oficjalna dokumentacja, aby uzyskać więcej informacji.

 9
Author: Darish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-05 05:47:26

Najpierw używasz startActivityForResult() z parametrami w first Activity i jeśli chcesz wysłać dane z second Activity do first Activity, następnie przekaż wartość za pomocą metody Intent z setResult() i pobierz te dane wewnątrz metody onActivityResult() W first Activity.

 2
Author: Dharmendra Pratap,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 11:57:38

Napiszę nową "drogę" z androidx w krótkiej odpowiedzi (bo w niektórych przypadkach nie trzeba custom registry lub umowy). Jeśli chcesz uzyskać więcej informacji zobacz: https://developer.android.com/training/basics/intents/result

Ważne: W rzeczywistości jest błąd z kompatybilnością wsteczną androidx, więc musisz dodać fragment_version do pliku gradle. W przeciwnym razie otrzymasz wyjątek " New result API error : Can only use lower 16 bits for requestCode " .

dependencies {

    def activity_version = "1.2.0-beta01"
    // Java language implementation
    implementation "androidx.activity:activity:$activity_version"
    // Kotlin
    implementation "androidx.activity:activity-ktx:$activity_version"

    def fragment_version = "1.3.0-beta02"
    // Java language implementation
    implementation "androidx.fragment:fragment:$fragment_version"
    // Kotlin
    implementation "androidx.fragment:fragment-ktx:$fragment_version"
    // Testing Fragments in Isolation
    debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}

Teraz wystarczy dodać tę zmienną członkowską swojej aktywności. Używa się w tym celu predefiniowanego rejestru i umowy generycznej.

public class MyActivity extends AppCompatActivity{

   ...

    /**
     * Activity callback API.
     */
    // https://developer.android.com/training/basics/intents/result
    private ActivityResultLauncher<Intent> mStartForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),

            new ActivityResultCallback<ActivityResult>() {

                @Override
                public void onActivityResult(ActivityResult result) {
                    switch (result.getResultCode()) {
                        case Activity.RESULT_OK:
                            Intent intent = result.getData();
                            // Handle the Intent
                            Toast.makeText(MyActivity.this, "Activity returned ok", Toast.LENGTH_SHORT).show();
                            break;
                        case Activity.RESULT_CANCELED:
                            Toast.makeText(MyActivity.this, "Activity canceled", Toast.LENGTH_SHORT).show();
                            break;
                    }
                }
            });

Przed nowym API miałeś:

btn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MyActivity .this, EditActivity.class);
                startActivityForResult(intent, Constants.INTENT_EDIT_REQUEST_CODE);
            }
        });

Możesz zauważyć, że kod żądania jest teraz generowany (i przechowywany) przez Google framework. Twój kod staje się.

 btn.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(MyActivity .this, EditActivity.class);
                    mStartForResult.launch(intent);
                }
            });

Mam nadzieję, że moja odpowiedź pomoże niektórym ludziom !

 2
Author: Zhar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-06 11:17:54

Bardzo częsty problem w Androidzie
można go podzielić na 3 części
1) rozpocznij ćwiczenie B (dzieje się w ćwiczeniu A)
2) ustaw żądane dane (dzieje się w ćwiczeniu B)
3) Odbiór żądanych danych (dzieje się w ćwiczeniu A)

1) startActivity B

Intent i = new Intent(A.this, B.class);
startActivity(i);

2) ustaw wymagane dane

W tej części decydujesz, czy chcesz wysłać dane z powrotem, Czy nie, gdy wystąpi określone zdarzenie.
Np: w ćwiczeniu B jest EditText i dwa przyciski b1, b2.
Kliknięcie przycisku b1 wysyła dane z powrotem do aktywności a
Kliknięcie na przycisk b2 nie wysyła żadnych danych.

Wysyłanie danych

b1......clickListener
{
   Intent resultIntent = new Intent();
   resultIntent.putExtra("Your_key","Your_value");
   setResult(RES_CODE_A,resultIntent);
   finish();
}

Nie wysyłanie danych

b2......clickListener
    {
       setResult(RES_CODE_B,new Intent());
       finish();
    }

Użytkownik kliknie przycisk Wstecz
Domyślnie wynik jest ustawiany jako Activity.RESULT_CANCEL response code

3) Pobierz wynik

Dla tej metody override onActivityResult

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

if (resultCode == RES_CODE_A) {

     // b1 was clicked 
   String x = data.getStringExtra("RES_CODE_A");

}
else if(resultCode == RES_CODE_B){

   // b2 was clicked

}
else{
   // back button clicked 
}
}
 1
Author: Rohit Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-06 12:14:05
You need to override Activity.onActivityResult()

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

if (resultCode == RESULT_CODE_ONE) {


   String a = data.getStringExtra("RESULT_CODE_ONE");

}
else if(resultCode == RESULT_CODE_TWO){

   // b was clicked

}
else{

}
}
 0
Author: Nitesh Dev Kunwar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-24 13:38:57

W Twojej głównej aktywności

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

    findViewById(R.id.takeCam).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent=new Intent(getApplicationContext(),TakePhotoActivity.class);
            intent.putExtra("Mode","Take");
            startActivity(intent);
        }
    });
    findViewById(R.id.selectGal).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent=new Intent(getApplicationContext(),TakePhotoActivity.class);
            intent.putExtra("Mode","Gallery");
            startActivity(intent);
        }
    });
}

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

}

W drugim ćwiczeniu do wyświetlenia

private static final int CAMERA_REQUEST = 1888;
private ImageView imageView;
private static final int MY_CAMERA_PERMISSION_CODE = 100;
private static final int PICK_PHOTO_FOR_AVATAR = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_take_photo);

    imageView=findViewById(R.id.imageView);

    if(getIntent().getStringExtra("Mode").equals("Gallery"))
    {
        pickImage();
    }
    else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE);
            } else {
                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(cameraIntent, CAMERA_REQUEST);
            }
        }
    }
}
public void pickImage() {
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == MY_CAMERA_PERMISSION_CODE)
    {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
        {
            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(cameraIntent, CAMERA_REQUEST);
        }
        else
        {
            Toast.makeText(this, "Camera Permission Denied..", Toast.LENGTH_LONG).show();
        }
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
        Bitmap photo = (Bitmap) data.getExtras().get("data");
        imageView.setImageBitmap(photo);
    }
        if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) {
            if (data == null) {
                Log.d("ABC","No Such Image Selected");
                return;
            }
            try {
                Uri selectedData=data.getData();
                Log.d("ABC","Image Pick-Up");
                imageView.setImageURI(selectedData);
                InputStream inputStream = getApplicationContext().getContentResolver().openInputStream(selectedData);
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                Bitmap bmp=MediaStore.Images.Media.getBitmap(getContentResolver(),selectedData);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch(IOException e){

            }
    }
}
 0
Author: Sagar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-15 03:37:47