finishAndRemoveTask() available on API 21 - java

I would terminate my app and cancel it from the list of recent task.
finishAndRemoveTask() is available only on API 21.
What should I use on API lower than 21??

Make an intent to the first activity in the stack and finish the current activity:
Intent intent = new Intent(this, FirstActivity.class);
intent.putExtra(EXTRA_FINISH, true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
And, in the onResume method of the FirstActivity, something like this to finish the last activity in the stack (and hopefully removing the app from the recent apps list):
if (getExtras() != null && getIntentExtra(EXTRA_FINISH, false)) {
finish();
}

I had a similar use case where I needed to finish all activities. Here is one way to do it without finishAndRemoveTask().
Make all your activities extend a base class with the following things in it:
private Boolean mHasParent = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mHasParent = extras.getBoolean("hasParent", false);
}
}
// Always start next activity by calling this.
protected void startNextActivity(Intent intent) {
intent.putExtra("hasParent", true);
startActivityForResult(intent, 199);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == 199 && resultCode == FINISH_ALL) {
finishAllActivities();
}
}
protected void finishAllActivities() {
if (mHasParent) {
// Return to parent activity.
setResult(FINISH_ALL);
} else {
// This is the only activity remaining on the stack.
// If you need to actually return some result, do it here.
Intent resultValue = new Intent();
resultValue.putExtra(...);
setResult(RESULT_OK, resultValue);
}
finish();
}
Simply call finishAllActivities() in any activity, and all the activities will unwind. Ofcourse if you don't care what result the last activity returns, the code can be made much simpler.

Related

How do I know/get notified that my activity (android) has ended? [duplicate]

In my activity, I'm calling a second activity from the main activity by startActivityForResult. In my second activity, there are some methods that finish this activity (maybe without a result), however, just one of them returns a result.
For example, from the main activity, I call a second one. In this activity, I'm checking some features of a handset, such as does it have a camera. If it doesn't have then I'll close this activity. Also, during the preparation of MediaRecorder or MediaPlayer if a problem happens then I'll close this activity.
If its device has a camera and recording is done completely, then after recording a video if a user clicks on the done button then I'll send the result (address of the recorded video) back to the main activity.
How do I check the result from the main activity?
From your FirstActivity, call the SecondActivity using the startActivityForResult() method.
For example:
int LAUNCH_SECOND_ACTIVITY = 1
Intent i = new Intent(this, SecondActivity.class);
startActivityForResult(i, LAUNCH_SECOND_ACTIVITY);
In your SecondActivity, set the data which you want to return back to FirstActivity. If you don't want to return back, don't set any.
For example: In SecondActivity if you want to send back data:
Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(Activity.RESULT_OK,returnIntent);
finish();
If you don't want to return data:
Intent returnIntent = new Intent();
setResult(Activity.RESULT_CANCELED, returnIntent);
finish();
Now in your FirstActivity class, write the following code for the onActivityResult() method.
#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
To implement passing data between two activities in a much better way in Kotlin, please go through 'A better way to pass data between Activities'.
How to check the result from the main activity?
You need to override Activity.onActivityResult() and then check its parameters:
requestCode identifies which app returned these results. This is defined by you when you call startActivityForResult().
resultCode informs you whether this app succeeded, failed, or something different
data holds any information returned by this app. This may be null.
Example
To see the entire process in context, here is a supplemental answer. See my fuller answer for more explanation.
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();
}
}
Complementing the answer from Nishant, the best way to return the activity result is:
Intent returnIntent = getIntent();
returnIntent.putExtra("result",result);
setResult(RESULT_OK,returnIntent);
finish();
I was having a problem with
new Intent();
Then I found out that the correct way is using
getIntent();
to get the current intent.
startActivityForResult: Deprecated in Android X
For the new way we have registerForActivityResult.
In Java :
// You need to create a launcher variable inside onAttach or onCreate or global, i.e, before the activity is displayed
ActivityResultLauncher<Intent> launchSomeActivity = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
// your operation....
}
}
});
public void openYourActivity() {
Intent intent = new Intent(this, SomeActivity.class);
launchSomeActivity.launch(intent);
}
In Kotlin :
var resultLauncher = registerForActivityResult(StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
// your operation...
}
}
fun openYourActivity() {
val intent = Intent(this, SomeActivity::class.java)
resultLauncher.launch(intent)
}
Advantage:
The new way is reduce complexity which we faced when we call the activity from a fragment or from another activity
Easily ask for any permission and get callback
For those who have problem with wrong requestCode in onActivityResult
If you are calling startActivityForResult() from your Fragment, the requestCode is changed by the Activity that owns the Fragment.
If you want to get the correct resultCode in your activity try this:
Change:
startActivityForResult(intent, 1); To:
getActivity().startActivityForResult(intent, 1);
The ActivityResultRegistry is the recommended approach
ComponentActivity now provides an ActivityResultRegistry that lets you handle the startActivityForResult()+onActivityResult() as well as requestPermissions()+onRequestPermissionsResult() flows without overriding methods in your Activity or Fragment, brings increased type safety via ActivityResultContract, and provides hooks for testing these flows.
It is strongly recommended to use the Activity Result APIs introduced in Android 10 Activity 1.2.0-alpha02 and Fragment 1.3.0-alpha02.
Add this to your 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"
How to use the pre-built contract
This new API has the following pre-built functionalities
TakeVideo
PickContact
GetContent
GetContents
OpenDocument
OpenDocuments
OpenDocumentTree
CreateDocument
Dial
TakePicture
RequestPermission
RequestPermissions
An example that uses the takePicture contract:
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() }
}
So what’s going on here? Let’s break it down slightly. takePicture is just a callback which returns a nullable Bitmap - whether or not it’s null depends on whether or not the onActivityResult process was successful. prepareCall then registers this call into a new feature on ComponentActivity called the ActivityResultRegistry - we’ll come back to this later. ActivityResultContracts.TakePicture() is one of the built-in helpers which Google have created for us, and finally invoking takePicture actually triggers the Intent in the same way that you would previously with Activity.startActivityForResult(intent, REQUEST_CODE).
How to write a custom contract
A simple contract that takes an Int as an input and returns a string that the requested Activity returns in the result Intent.
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)
}
}
}
Check this official documentation for more information.
If you want to update the user interface with the activity result, you can't to use this.runOnUiThread(new Runnable() {}. Doing this, the UI won't refresh with the new value. Instead, you can do this:
#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;
}
}
This seems silly, but it works pretty well.
In Kotlin
Suppose A & B are activities the navigation is from A -> B
We need the result back from A <- B
in A
// calling the Activity B
resultLauncher.launch(Intent(requireContext(), B::class.java))
// we get data in here from B
private var resultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
when (result.resultCode) {
Activity.RESULT_OK -> {
result.data?.getStringExtra("VALUE")?.let {
// data received here
}
}
Activity.RESULT_CANCELED -> {
// cancel or failure
}
}
}
In B
// Sending result value back to A
if (success) {
setResult(RESULT_OK, Intent().putExtra("VALUE", value))
} else {
setResult(RESULT_CANCELED)
}
It is a very common problem on Android
It can be broken down into three pieces
Start Activity B (happens in Activity A)
Set requested data (happens in activity B)
Receive requested data (happens in activity A)
startActivity B
Intent i = new Intent(A.this, B.class);
startActivity(i);
Set requested data
In this part, you decide whether you want to send data back or not when a particular event occurs.
E.g.: In activity B there is an EditText and two buttons b1, b2.
Clicking on Button b1 sends data back to activity A.
Clicking on Button b2 does not send any data.
Sending data
b1......clickListener
{
Intent resultIntent = new Intent();
resultIntent.putExtra("Your_key", "Your_value");
setResult(RES_CODE_A, resultIntent);
finish();
}
Not sending data
b2......clickListener
{
setResult(RES_CODE_B, new Intent());
finish();
}
The user clicks the back button
By default, the result is set with Activity.RESULT_CANCEL response code
Retrieve result
For that override onActivityResult method
#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{
// The back button was clicked
}
}
I will post the new "way" with Android X in a short answer (because in some case you does not need custom registry or contract). If you want more information, see: Getting a result from an activity
Important: there is actually a bug with the backward compatibility of Android X so you have to add fragment_version in your Gradle file. Otherwise you will get an exception "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"
}
Now you just have to add this member variable of your activity. This use a predefined registry and generic contract.
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;
}
}
});
Before new API you had :
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);
}
});
You may notice that the request code is now generated (and hold) by the Google framework.
Your code becomes:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity .this, EditActivity.class);
mStartForResult.launch(intent);
}
});
First you use startActivityForResult() with parameters in the first Activity and if you want to send data from the second Activity to first Activity then pass the value using Intent with the setResult() method and get that data inside the onActivityResult() method in the first Activity.
In your Main Activity
#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);
}
In Second Activity to Display
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){
}
}
}
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{
}
}

How do you pass data back and forth between activities in Android?

I have two activities that should pass data back and forth to each other using intents. I'm not sure where to place some of the puts and gets though.
For Activity1 (MainActivity), I have a button, and on press it creates an intent, and then puts it to Activity2, then starts it using startActivity(intent).
btn.setOnClickListener((v) -> {
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("test", testClass);
startActivity(intent);
});
Then in Activity2, I get that information in the onCreate() function using getIntent.
Now what I want to do is have a button in Activity2 that will pass data to Activity1, but won't necessarily "start/show" the activity.
So I'm wondering how this can be done.
My idea is to have the following similar to before:
Activity2:
btn.setOnClickListener((v) -> {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("info", info);
});
But I'm confused about two things
Can I do this without starting the activity right away
Where would I do the getIntent call in MainActivity to retrieve this data
You can use startActivityForResult to start Activity2 and receive a result back to Activity1
Activity 1
int LAUNCH_ACTIVITY_TWO = 1;
Intent i = new Intent(this, Activity2.class);
i.putExtra("test", testClass);
startActivityForResult(i, LAUNCH_ACTIVITY_TWO);
//onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_ACTIVITY_TWO) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
}
}
}
Activity 2
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
setResult(Activity.RESULT_OK, returnIntent);
finish();
Full Activity 1 code:
public class MainActivity extends AppCompatActivity {
public static int LAUNCH_ACTIVITY_TWO = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener((v) -> {
Intent i = new Intent(this, Activity2.class);
i.putExtra("test", testClass);
startActivityForResult(i, LAUNCH_ACTIVITY_TWO);
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_ACTIVITY_TWO) {
if(resultCode == Activity.RESULT_OK){
String result= data.getStringExtra("result");
}
}
}
}
Full Activity 2 code:
public class Activity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(getIntent().getExtras() != null) {
// Get intent extras from Activity 1
}
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener((v) -> {
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
setResult(Activity.RESULT_OK, returnIntent);
finish();
});
}
}
You can for example create a list in activity2 to which you add the data you want to pass to activity1. Before starting activity1 you get the values out of your array and add them as extras to the input.
You can have the data added to a JSONObject and use a serializer so you don't have to add your items all by yourself.
If you want to pass your data to activity1 without starting it,so activity1 processes the data, that is not possible. Activity doesnt execute anything while you are in activity2, for such cases you use fragments.
If you use fragments you can put all data in a viewmodel which is bound to the activity instead of each fragment.
There are several ways you can achieve this pending on what type of data you're looking at passing.
If it's an entire class object then make the class parcable. You can copy and paste the class in this website http://www.parcelabler.com/ and it auto formats it for you. All you do is pass it as an intent extra.
If you're looking at data that needs an action performed on it and then passed to another activity I would suggest using and intent service. You can perform certain actions pending the intents received in the service.
If you're looking at performing certain actions only after XYZ has occurred in your application then used shared preferences. These can be accessed anywhere quite easily.
Lastly, if you're using bulk data consistently that needs to remain persistent, use a local database storage and just query when you need to.
You can use SharedPreferences or static variables/fields for that.

Android Studio: Activity only finishes when you call the finish() for second time

So, we're working with intents at school and I'm having trouble with the intents when I try to pass data from the "Activity2" to the "Activity1", when I do the setResult() and stuff. The problem is it won't go back to the first activity when I trigger the event the first time, but it will the second.
I've been working with Android studio only for about 12h so I really lack a lot of understanding.
Here is what I'm doing:
First I call this form the main activity.
public void CheckPassword(View view) {
password = PasswordManagement.getPassword(this);
TextView txtPassword = findViewById(R.id.txtPassword);
if (txtPassword.getText().toString().equals(password)) {
Intent intent;
intent = new Intent(this, WelcomeActivity.class);
intent.putExtra("password", password);
startActivityForResult(intent, 1);
startActivity(intent);
} else {
Intent intent;
intent = new Intent(this, RestrictedActivity.class);
startActivityForResult(intent, 1);
startActivity(intent);
}
}
Then, when I'm done from the second activity I run this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_restricted);
lblRestrictedArea = findViewById(R.id.lblRestrictedArea);
lblRestrictedArea.setOnLongClickListener(
new OnLongClickListener() {
public boolean onLongClick(View view) {
intent = new Intent();
intent.putExtra(EXTRA_RESPONSE, true);
setResult(RESULT_OK, intent);
finish();
return false;
}
});
}
And back to the main activity I overwrote this to act according to the response:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
if (data.getBooleanExtra(RestrictedActivity.EXTRA_RESPONSE,false)){
LinearLayoutPasswordActivity.setBackgroundColor(getResources().getColor(R.color.red));
}else{
LinearLayoutPasswordActivity.setBackgroundColor(getResources().getColor(R.color.white));
}
}
}
}
If anyone can help I would be very glad, meanwhile I'll try to solve it my own.
Thanks!
Your are calling startActivity twice. So there are two instance of the same Activity and then you have to finish twice.
Keep your startActivityForResult(...) and delete startActivity in CheckPassword(View view)
->
public void CheckPassword(View view) {
password = PasswordManagement.getPassword(this);
TextView txtPassword = findViewById(R.id.txtPassword);
if (txtPassword.getText().toString().equals(password)) {
Intent intent;
intent = new Intent(this, WelcomeActivity.class);
intent.putExtra("password", password);
startActivityForResult(intent, 1);
// startActivity(intent);
} else {
Intent intent;
intent = new Intent(this, RestrictedActivity.class);
startActivityForResult(intent, 1);
//startActivity(intent);
}
}
Plus, note that you are using the same requestCode (1) for two different activities. The requestCode is very important for onActivityResult method.

Passing ArrayList from SecondActivity to MainActivity Android

my problem is simple, I'm trying to pass an arraylist from my second activity to my mainActivity.
However when my onRestart() in my main activity is called when the user presses back from secondActivity the arraylist seems to be null.
IN MAIN ACTIVITY
#Override public void onRestart() {
super.onRestart();
DefaultLocations = (ArrayList<String>) getIntent().getSerializableExtra("updated");
///default locations is null
}
SECOND ACTIVITY
#Override public void onPause() {
super.onPause();
Intent intent = new Intent(ManageLocations.this, MainActivity.class);
intent.putExtra("updated",locationsavailable)///size is 2 currently;
this.setIntent(intent);
}
I've looked around as I know there are many examples but none helped me pass an arraylist BACK to my mainActivity.
All help is appreciated!
In second activity:
ArrayList < String > locationsavailable = new ArrayList < String > ();
locationsavailable.add("location1");
locationsavailable.add("location2");
Intent sentIntent = new Intent(SecondActivity.this, FirstActivity.class);
sentIntent.putExtra("string-array", locationsavailable);
startActivity(sentIntent);
In first activity:
Intent intent = getIntent();
String [] DefaultLocations = intent.getStringArrayExtra("string-array");
Edited:
In your case, I suggest use startActivityForResult to start second activity
and override onActivityResult in first activity.
The best solution for your situation would be to start the Second Activity using the startActivityForResult method. Here is an example of what you should do:
MainActivity
public class MainActivity extends AppCompatActivity {
private static final int GET_LOCATIONS_REQUEST_CODE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout layout = findViewById(R.id.mylayout);
Intent intent = new Intent(this, SecondActivity.class);
startActivityForResult(intent, GET_LOCATIONS_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == GET_LOCATIONS_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
ArrayList<String> locations = data.getStringArrayListExtra("result");
for(String location : locations) {
System.out.println(String.format("Location from SecondActivity %1$s", location));
}
}
if (resultCode == Activity.RESULT_CANCELED) {
//Write your code if there's no result
}
}
}
}
SecondActivity
public class SecondActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<String> locationsavailable = new ArrayList<>();
locationsavailable.add("location1");
locationsavailable.add("location1");
Intent returnIntent = new Intent();
returnIntent.putExtra("result", locationsavailable);
setResult(Activity.RESULT_OK, returnIntent);
finish();
}
}
If you don't want to start it as an Activity for result, you should override your #OnStart method in the MainActivity.
you just have to write simple code of some lines to solve your problem.
step 1:
while sending intent from main activity to second activity use startActivityForResult().
//Main Activity
private static final int GET_LOCATION_LIST=1; //you can give any value to variable
Intent intent = new Intent(context,SecondActivity.class);
startActivityForResult(intent,GET_LOCATION_LIST);
step 2: now in Second Activity you have to send the location list back in Main Activity.
//Second Activity
Intent intent = new Intent();
intent.putExtra("updated", locationsavailable);
setResult(Activity.RESULT_OK, intent);
SubmissionMailerClientContactList.this.finish();
step 3: now again in main activity you have to receive that intent using onActivityResult()
//Main Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
DefaultLocations=(ArrayList<String>)getIntent().getSerializableExtra("updated");
}

Android activity does not finish and does not launch previous activity

I have 2 Activities the main activity I have called Map activity and the second that I have called Question activity when the app launch the Map activity is shown then you click the play button and the Question activity is launched with StartActivityForResult(), then when you have answered the question right the Question activity should be destroyed and created again and check the number of right answered questions and change the layout. then if you have scored 5 then Question activity should be destroyed and the Map activity will be shown but this is not happen. Here is my code
Map.class
public void OnClick_Question(View v){
Intent i = new Intent(MapActivity.this, QuestionActivity.class);
startActivityForResult(i, 1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(SharedPrefs.TAG, "OnActivityResult Entry");
if (resultCode == RESULT_OK) {
Log.d(SharedPrefs.TAG, "MAPActivity OnActivityResult Entry resultCode");
AssignContentView(requestCode);
}
}
Question.class
public void Next() {
Intent i = new Intent(this, QuestionActivity.class);
startActivity(i);
finish();
}
public void LevelUp() {
Log.e(SharedPrefs.TAG, "LevelUp");
super.finish();
finish(); /*This don't happen*/
}
When I see LogCat shows me this message:
09-01 11:23:03.911 901-1485/? W/ActivityManager﹕ startActivity called from finishing ActivityRecord{43386100 u0 com.example.gbb/.QuestionActivity t50 f}; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { cmp=com.example.gbb/.QuestionActivity }
Why I am doing this, is because I want to change the layout of Map Activity depending in your score.
What I'm doing wrong?
I had the same problem. I solved it by adding android:launchMode="singleTask" in the Android Manifest. Hope it works for you too.
I solved this by turning off Instant Run and re-running my code.
You can try the below code:
We need to keep the request code to be in global and static variable to access in onActivityResult method
private static final int REQUEST_CODE = 111;
public void OnClick_Question(View v){
Intent i = new Intent(MapActivity.this, QuestionActivity.class);
startActivityForResult(i, REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.d(SharedPrefs.TAG, "OnActivityResult Entry");
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_CODE:
Log.d(SharedPrefs.TAG, "MAPActivity OnActivityResult Entry resultCode");
AssignContentView(requestCode);
break;
default:
break;
}
}
}
I think there is no problem in your Map class, the problem is in second class.i.e., you need to set the RESULT_OK in that intent and then you can check if (resultCode == RESULT_OK) in onActivityResult method. Below you can find the code for that
Intent intent = new Intent();
setResult(activity.RESULT_OK, intent);
finish();
Hope this is helpful:)

Categories