Android'de startActivityForResult nasıl yönetilir?


969

Etkinliğimde, tarafından ana faaliyetten ikinci bir etkinlik arıyorum startActivityForResult. İkinci etkinliğimde, bu etkinliği bitiren bazı yöntemler var (belki sonuçsuz), ancak bunlardan sadece biri bir sonuç döndürüyor.

Örneğin, ana faaliyetten, ikinci bir etkinlik diyorum. Bu aktivitede, bir kamera var gibi yakışıklı bazı özelliklerini kontrol ediyorum. Eğer yoksa, bu etkinliği kapatacağım. Ayrıca, hazırlanırken MediaRecorderveya MediaPlayerbir sorun olursa, bu aktiviteyi kapatırım.

Cihazında bir kamera varsa ve kayıt tamamen yapılırsa, bir video kaydettikten sonra bir kullanıcı tamam düğmesine tıklarsa sonucu (kaydedilen videonun adresi) ana etkinliğe geri gönderirim.

Ana faaliyetin sonucunu nasıl kontrol ederim?


Yanıtlar:


2446

Senin itibaren FirstActivityçağrı SecondActivitykullanarak startActivityForResult()yöntemi

Örneğin:

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

Sizin de SecondActivitysette veri hangi geri dönmek istiyorum FirstActivity. Geri dönmek istemiyorsanız, ayarlamayın.

Örneğin: SecondActivityVerileri geri göndermek istiyorsanız:

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

Verileri iade etmek istemiyorsanız:

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

Şimdi FirstActivitysınıfınızda onActivityResult()yöntem için aşağıdaki kodu yazın .

@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

Bu bağlantıyı 'geçmesi lütfen KOTLIN çok daha iyi bir şekilde iki faaliyetleri arasında veri geçirmeden uygulamak için Aktiviteler arasında veri aktarmak için daha iyi bir yolu '


1
SetResult içinde (RESULT_CANCELED, returnIntent) RESUT_CANCELLED olduğunda bir niyet belirtmenin amacı nedir;
İsmail Şahin

4
varsayalım @ismail SecondActivitybazı istisna bu durumda da sonucu dönmek gerekiyor oluştu FirstActivitysiz sonucunu ayarlayabilirsiniz böylece, "RESULT_CANCELLED"catch bloğundaki ve geri dönüş için FirstActivtyve de FirstActivity's' 'onActivityResult()size başarı veya başarısızlık sonucu aldığım kontrol edebilirsiniz.
Nishant

10
Bu nedenle size kalmış, iptal nedenini bilmeniz gerekmiyorsa, sadece setResult (RESULT_CANCELED) kullanabilirsiniz; niyetsiz
İsmail Şahin

2
@Lei Leyba startActivityForResult () çağrıldıktan sonra hiçbir bitirme () çağrılmaz. İlk Eylem durumu duraklatmak için hareket eder.
Nishant

6
Benim için çalışmıyor -.- Android hakkında soooo'dan çok nefret ediyorum - bu sistem çok güvenilmez: - /
Martin Pfeffer

50

Ana aktiviteden sonuç nasıl kontrol edilir?

Geçersiz Activity.onActivityResult()kılmanız ve parametrelerini kontrol etmeniz gerekir :

  • requestCodehangi uygulamanın bu sonuçları döndürdüğünü tanımlar. Aradığınızda bu sizin tarafınızdan tanımlanır startActivityForResult().
  • resultCode bu uygulamanın başarılı, başarısız veya farklı bir şey olup olmadığını size bildirir
  • dataBu uygulama tarafından döndürülen herhangi bir bilgi tutar. Bu olabilir null.

Bu, requestCode'un yalnızca ilk etkinlikte kullanıldığı ve hiçbir zaman 2. etkinlikte kullanılmadığı anlamına mı gelir? 2. etkinliğin farklı yaklaşımları varsa, değişir, ancak requestCode tarafından değil, amaç ekstralarına dayalı olarak, değil mi? Düzenleme: Evet, stackoverflow.com/questions/5104269/…
JCarlosR

44

@ Nishant'ın cevabını tamamlayan etkinlik sonucunu döndürmenin en iyi yolu:

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

İle sorun yaşıyordum

new Intent();

Sonra doğru yolun

getIntent();

şimdiki amacı elde etmek


IntentYalnızca a'yı tutmak için var olan Bundleve bir eylem veya bileşen gibi normal değerlere sahip olmayan yeni bir tane oluşturmak biraz garip geliyor . Ancak Intentmevcut etkinliği başlatmak için kullanılanı değiştirmek biraz garip (ve potansiyel olarak tehlikeli?) . Bu yüzden Android'in kaynağını araştırdım Intentve sonuç olarak kullanmak için her zaman yeni bir tane oluşturduklarını gördüm . Örneğin, github.com/aosp-mirror/platform_frameworks_base/blob/…
spaaarky21

Merhaba spaaarky21, yorumunuz için teşekkür ederiz. Maalesef bu çözümü nasıl bulduğumu tam olarak açıklamakta çok açık değildim. Üç yıl önceydi ve uygulamamın "yeni Niyet" nedeniyle çöktüğünü hatırlıyorum, "Sorun yaşıyorum" dediğimde bunu kastediyorum. Aslında "getIntent" ile denedim, çünkü o zaman mantıklıydı ve işe yaradı! Bu nedenle çözümümü paylaşmaya karar verdim. Belki "en iyi yol" ya da "doğru yol" demek için en iyi kelime seçimi değil, ama benim çözümümün yanındayım. Sorunumu ve diğer insanları da çözen şey buydu. Teşekkürler
Julian Alberto

1
Vaov! harika çalışıyor. getIntent()verileri, etkinliğin çağrıldığı bilinmeyen etkinliğe döndürmek için mükemmel bir yol gibi görünüyor. Teşekkürler!
sam

43

Misal

Tüm süreci bağlam içinde görmek için burada ek bir cevap var. Daha fazla açıklama için daha eksiksiz cevabımı görün .

resim açıklamasını buraya girin

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

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

Bu iki farklı uygulama A ve uygulama b tarafından yapılabilir mi? stackoverflow.com/questions/52975645/…
Jerry Abraham


10

Kullanıcı arayüzünü etkinlik sonucu ile güncellemek istiyorsanız Bunu yaparak kullanıcı arayüzü this.runOnUiThread(new Runnable() {} yeni bir değerle yenilenmez. Bunun yerine şunları yapabilirsiniz:

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

Bu aptalca görünüyor ama oldukça iyi çalışıyor.


2

İlk startActivityForResult()önce parametrelerle kullanın Activityve ikinciden Activityilke veri göndermek istiyorsanız , yöntemi Activitykullanarak değeri geçirin ve ilk önce bu yöntemi yöntem içine alın .IntentsetResult()onActivityResult()Activity


1

Android'de çok yaygın bir problem
3 parçaya bölünebilir
1) başlangıç ​​Aktivite B (Aktivite A'da olur)
2) İstenen verileri ayarlayın (aktivite B'de olur)
3) İstenen verileri alın (A aktivitesinde olur)

1) startActivity B

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

2) İstenen verileri ayarlayın

Bu bölümde, belirli bir olay meydana geldiğinde verileri geri göndermek isteyip istemediğinize karar verirsiniz.
Örnek: B aktivitesinde bir EditText ve iki düğme b1, b2 vardır.
B1 Düğmesine tıklamak verileri etkinliğe geri gönderir A
b2 Düğmesine tıklamak hiçbir veri göndermez.

Veri gönderme

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

Veri göndermiyor

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

kullanıcı geri düğmesini tıklatır
Varsayılan olarak, sonuç Activity.RESULT_CANCEL yanıt kodu ile ayarlanır.

3) Sonucu alın

Bunun için onActivityResult yöntemini geçersiz kılma

@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

ActivityResultRegistry önerilen yaklaşımdır

ComponentActivityartık + ve + akışlarını, yöntemlerinizde geçersiz kılmadan ActivityResultRegistryele almanıza olanak tanıyan veya aracılığıyla daha fazla tür güvenliği sağlar ve bu akışları sınamak için kancalar sağlar. startActivityForResult()onActivityResult()requestPermissions()onRequestPermissionsResult()ActivityFragmentActivityResultContract

AndroidX Activity 1.2.0-alpha02 ve Fragment 1.3.0-alpha02'de sunulan Etkinlik Sonucu API'larının kullanılması önemle tavsiye edilir.

Bunu build.gradle

def activity_version = "1.2.0-alpha03"

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

Önceden oluşturulmuş sözleşme nasıl kullanılır?

Bu yeni API aşağıdaki önceden oluşturulmuş işlevlere sahiptir

  1. Video çek
  2. PickContact
  3. İçeriğe eriş
  4. GetContents
  5. OpenDocument
  6. opendocuments
  7. OpenDocumentTree
  8. CreateDocument
  9. tuşlamak
  10. Fotoğraf çek
  11. RequestPermission
  12. RequestPermissions

TakePicture sözleşmesini kullanan bir örnek:

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

Peki burada neler oluyor? Hadi biraz parçalayalım. takePictureyalnızca boş bir Bitmap döndüren bir geri aramadır - boş olup olmadığı onActivityResultişlemin başarılı olup olmadığına bağlıdır . prepareCalldaha sonra bu çağrıyı ComponentActivityadlı yeni bir özelliğe kaydeder ActivityResultRegistry- buna daha sonra geri döneceğiz. ActivityResultContracts.TakePicture()Google'ın bizim için oluşturduğu yerleşik yardımcılardan biridir ve son olarak çağırmak takePicture, Niyeti daha önce yaptığınız şekilde tetikler Activity.startActivityForResult(intent, REQUEST_CODE).

Özel bir sözleşme nasıl yazılır?

Int'yi bir Girdi olarak alan ve Etkinlik'in sonuç Niyetinde döndürmesini isteyen bir Dize döndüren basit sözleşme.

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

Kontrol bu daha fazla bilgi için resmi belgeler.


0
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{

}
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.