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?
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 '
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łujeszstartActivityForResult()
. -
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
.
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ń.
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();
}
}
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
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);
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.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
- TakeVideo
- PickContact
- GetContent
- GetContents
- OpenDocument
- OpenDocuments
- OpenDocumentTree
- CreateDocument
- Wybierz
- TakePicture
- RequestPermission
- 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.
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
.
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 !
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
}
}
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{
}
}
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){
}
}
}
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