I have implemented code in which the UI has a button. On button press, I will prompt an email chooser from an intent.
Problem is when I press the button multiple times, the intent popup shows one by one. Can I stop this by using flags? This is a Xamarin Android project.
Code:
Intent intent = new Intent();
intent.SetAction(Intent.ActionSend);
intent.SetType(FileType);
intent.PutExtra(Intent.ExtraSubject, emailMessage.Subject);
if (!emailMessage.IsLinkInclude && !emailMessage.IsAlternateFileInclude){
intent.PutExtra(Intent.ExtraStream, AssetPathHelper.GetAssetUri(item, context));
}
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
intent.AddFlags(ActivityFlags.NewTask);
intent.AddFlags(ActivityFlags.ResetTaskIfNeeded);
intent.PutExtra(Intent.ExtraText, Html.FromHtml(emailMessage.Message));
if (intent.ResolveActivity(context.PackageManager) != null){
context.StartActivity(Intent.CreateChooser(intent, AndroidStringLoader.GetStringValue(Resource.String.SendEmailText)));
}
Disable the button in onClick() and once the intended operation is done, enable the button.
public void onClick(View view) {
btn.setEnabled(false);
//some operation may be async
}
public void onOperationFinished() {
btn.setEnabled(true);
}
I have faced the same problem, here is my solution to avoid it by placing a timer between two consecutive click.
private static final long INTERVAL = 1000;
private long lastClickTime = 0;
// onClick of your button code below
#Override
public final void onClick(View v) {
long currentTime = SystemClock.elapsedRealtime();
if (currentTime - lastClickTime > INTERVAL) {
lastClickTime = currentTime;
//perform the task here of click
}
}
The other way is setEnabled(false), but for a very fast tapping on button , is not efficient.
Seems there is no flag for the intent to passed in this scenario , So i have implemented it by following , we can get the fail and success status from it
https://developer.android.com/guide/components/activities.html#StartingAnActivityForResult
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (resultCode == Result.Canceled)
{
this.shareAssetPopup.isPopupWindowActive = false;
}
}
Related
Is there any way to disable in an activity the back button (to prevent show the previous activities), but also when you double press it, use it for exit??
I use this code that I found, but it only makes the second part. Close the app with double press..
What I try to do, is also prevent to go back and show the last visited activities. Thank you.
boolean doubleBackToExitPressedOnce = false;
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press again back for exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
UPDATE
I make the changes that you suggest, but now, it shows with the double back all the previous visited activities.
static final long THRESHOLD = 2000;
long backLastPressed;
boolean doubleBackToExitPressedOnce = false;
#Override
public void onBackPressed() {
if (System.currentTimeMillis() - backLastPressed < THRESHOLD) {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press again back for exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
backLastPressed = 0;
return;
}
backLastPressed = System.currentTimeMillis();
// Otherwise, ignore this BACK press
}
You could store an internal variable that marks the time of when the BACK button was pressed. Every time in onBackPressed check if the time now is within your double-tap threshold and if so, register it as a double-tap.
Try something like this:
static final long THRESHOLD = 2000;
long backLastPressed = 0;
#Override
public void onBackPressed() {
if (System.currentTimeMillis() - backLastPressed < THRESHOLD) {
// TODO: Register double-tapped BACK button, put your "exit" code here
backLastPressed = 0;
return;
}
backLastPressed = System.currentTimeMillis();
// Otherwise, ignore this BACK press
}
Don't call super.onBackPressed() if you're trying to override the BACK button behavior.
I still don't have the reputation to comment.
To prevent visiting the previous activities, you could, in addition to the code to do something when you double-tap back button, clear the tasks when you enter in this activity.
This guide shows how to achive this: https://developer.android.com/guide/components/activities/tasks-and-back-stack.html
TL;DR: use flags in the intent to clear the activity back stack.
In the intent:
Intent intent = new Intent(this, YourActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish(); // call this to finish the previous activity
You can try my code :
private static long back_press;
#Override
public void onBackPressed() {
if (back_press + 2000 > System.currentTimeMillis()) {
super.onBackPressed();
} else {
Toast.makeText(getBaseContext(), "Please press again to exit!",
Toast.LENGTH_SHORT).show();
back_press = System.currentTimeMillis();
}
}
It worked for me, i hope it will help you.
Please, take a look at this sample app: https://github.com/IvanShafran/android-stackoverflow/tree/master/BackButtonHandle
Main point is:
private boolean mIsBackButtonPressedBefore = false
#Override
public void onBackPressed() {
if (mIsBackButtonPressedBefore) {
Toast.makeText(this, "Second back button press", Toast.LENGTH_SHORT).show();
super.onBackPressed();
} else {
mIsBackButtonPressedBefore = true;
Toast.makeText(this, "First back button press", Toast.LENGTH_SHORT).show();
}
}
It has described behaviour as you can see at the gif below:
If your code is similar to this but doesn't work you should look for a problem outside of this scope.
I am trying to pass some strings from A to B and B to A, but it is not working for some reason. Here is what I try doing:
In A, I have two global variables: minuteValue and hourValue, and they are defaulted to 00. They are updated when I pass the some strings from B, with the same names but different values, to A. Regardless of whether the exchange happens, I pass those value from A to B.
In B, I only pass those values if the user presses a button: timerButton and this is done in the setUpTimerButton method
It seems that I never go into my onActivityResult method in A since I have print statements and I never see any of them.
Code for A:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if(requestCode == 3){
//the values for the timer
String hourValue = data.getStringExtra("hourValue");
String minuteValue = data.getStringExtra("minuteValue");
//find the values from the timer if the user had set it earlier
if (hourValue != null) { this.hourValue = hourValue;
System.out.println("HOUR IS " + hourValue ); }
if (minuteValue != null) { this.minuteValue = minuteValue;
System.out.println("minute IS " + minuteValue); }
else{
System.out.println("timer minute value is NULL");
}
}
}
...
//going from A to B
Intent timerActivity = new Intent(MainActivity.this, CustomTimer.class);
timerActivity.putExtra("minuteValue", minuteValue);
System.out.println("passing back");
timerActivity.putExtra("hourValue", hourValue);
System.out.println("passing back hour");
startActivityForResult(timerActivity, 3);
Code for B:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_timer);
hourValue = (EditText) findViewById(R.id.hour_value);
minuteValue = (EditText) findViewById(R.id.minute_value);
timerButton = (Button) findViewById(R.id.start_timer_button);
//grabs the values from A
if(getIntent().getStringExtra("hourValue") != null)
hourValue.setText(getIntent().getStringExtra("hourValue"));
if(getIntent().getStringExtra("minuteValue") != null)
minuteValue.setText(getIntent().getStringExtra("minuteValue"));
else{
System.out.println("could not find values");//this never occurs
}
setUpHourValue();
setUpMinuteValue();
setUpTimerButton();
}
private void setUpTimerButton(){
timerButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
//startTime = SystemClock.uptimeMillis();
// handler.postDelayed(updateTimerThread, 0);
System.out.println("TIMER CLICKED************");
//send the list of audio titles back to the main activity
Intent intent = getIntent();
System.out.println("**** hour and minute values are: " +
hourValue.getText().toString() + " : " + minuteValue.getText().toString());
intent.putExtra("hourValue", hourValue.getText().toString());
intent.putExtra("minuteValue", minuteValue.getText().toString());
setResult(RESULT_OK, intent);
finish();//go back to the previous page
}
});
}
private void setUpHourValue(){
hourValue.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
hourValue.setText(v.getText().toString());
return false;
}
});
}
private void setUpMinuteValue(){
minuteValue.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
minuteValue.setText(v.getText().toString());
return false;
}
});
}
I know the timerButton works since I print out the values when the button is clicked, but I never go into onActivityResult for some reason and I think that's the real problem...
startActivityForResult instead of startActivity while going from from A to B. You can use this constructor, and use requestCode if you have different navigations from A to some other screens as well
public void startActivityForResult(Intent intent, int requestCode)
startActivity(timerActivity);
That line of code is the culprit here.
You have to use this:
startActivityForResult(Intent intent, int requestCode);
To be able to use setResult(int result) in B.
I am confused and have no idea on how to use the startActivityResults and setResults to get data from previous activity. I have a view class and a activity class.
Basically in my view class i have this dialog and it will actually start the activity class called the colorActivity class. When user selects yes also it will pass the name of the selected circle to the colorActivity class. At the colorActivity class, users are allowed to enter color code for a particular circle and i would like to pass the color code back to the view class. I have problems passing values from activity back to view using the startActivityForResult and setResult method. Adding on, how to make use of the fetched data afterthat?
my code are as follows
Ontouchevent code from my view class:
#Override
public boolean onTouchEvent(MotionEvent event) {
x = event.getX();
y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
for (int i = 0; i < circles.size(); i++) {
if (circles.get(i).contains(x, y)) {
circleID = i;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
AlertDialog.Builder builder = new Builder(
getContext());
final EditText text = new EditText(getContext());
builder.setTitle("Adding colors to circles").setMessage(
"Proceed to Enter color");
builder.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di,
int i) {
Intent intent = new Intent(
getContext(),
colorActivity.class);
intent.putExtra("circlename", circleNameList.get(circleID));
startActivityForResults(intent, 1); // error incurred here : The method startActivityForResult(Intent, int) is undefined for the type new DialogInterface.OnClickListener(){}
}
});
builder.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di,
int i) {
}
});
builder.create().show();
}
}, 3000);
break;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) { // Please, use a final int instead of hardcoded
// int value
if (resultCode == RESULT_OK) {
ccode = (String) data.getExtras().getString("colorcode");
}
}
}
public static String getColorCode() {
return ccode;
}
In the colorActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_ecolor);
circlenametextview = (TextView)findViewById(R.id.circlenametextview);
String circlename = super.getIntent().getStringExtra("circlename");
circlenametextview.setText(circlename);//get the circle name
savebutton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(colorActivity.this, ?????);//how to return back to the view class?
colorcode = colorEditText.getText().toString();// I am able to get value right up till this point
Intent resultIntent = new Intent();
resultIntent.putExtra("colorcode", colorcode );
setResult(Activity.RESULT_OK, resultIntent);
finish();
}// onclick
});
}
After correcting the other code so that you can run the program, you can retrieve parameters back from your activity colorActivity in this way:
Step1: return some value from colorActivity
Intent resultIntent = new Intent();
resultIntent.putExtra("NAME OF THE PARAMETER", valueOfParameter);
...
setResult(Activity.RESULT_OK, resultIntent);
finish();
Step 2: collect data from the Main Activity
Overriding #onActivityResult(...).
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) { // Please, use a final int instead of hardcoded int value
if (resultCode == RESULT_OK) {
String value = (String) data.getExtras().getString("NAME OF THE PARAMETER");
References
http://developer.android.com/training/basics/intents/result.html
How to manage `startActivityForResult` on Android?
http://steveliles.github.io/returning_a_result_from_an_android_activity.html
STARTACTIVITYFORRESULT IS NOW DEPRECATED
Alternative to it and recommended solution is to use Activity Result API
You can use this code, written in Kotlin language:
Create ResultLauncher:
private var resultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
if (null != data && data.getBooleanExtra("REFRESH_PAGE", false)) {
//do your code here
}
}
}
start Activity by using above result launcher:
val intent = Intent(this, XYZActivity::class.java)
resultLauncher.launch(intent)
Return result from XYZActivity by
val resultIntent = Intent()
resultIntent.putExtra("REFRESH_PAGE", true)
setResult(Activity.RESULT_OK, resultIntent)
finish()
try using
ActivityName.this.startActivityForResult(intent,int)
Oh, and 1 small thing, in your code you have used
startActivityForResults(intent,int) ..replace that with
startActivityForResult(intent,int)
I have a onClick listener which starts an activity using intent, but how to make the listener to fire the Activity intent only when the user click five times or more?
public boolean onClick(View v) {
Intent myIntent = new Intent(activity, loginActivity.class);
activity.startActivity(myIntent);
return false;
}
Here I am going to login Activity. How can I get back to previous activity after login successful?
public void onClick(View v) {
String username = Username.getText().toString();
String password = Password.getText().toString();
if(username.equals("guest") && password.equals("guest")) {
lResult.setText("Login successful.");
} else {
lResult.setText("Login failed");
}
}
Have a static variable in program which will increment on each click.
When you click count reach 5 then trigger code to start LoginActivity.
static int i = 0;
#override
public void onClick(View view) {
i++;
if (i == 5) {
i = 0;
Intent myIntent = new Intent(activity, loginActivity.class);
activity.startActivity(myIntent);
}
}
You can try to build a counter which count the clicks and from the 5th clicks let him go forward
To turn back to the previous activity just call
finish();
Add a static counter to your activity.
static int clickCount;
In your onClick:
if(clickCount++<5){return;}
For the fist question just a a counter variable on the class and increment in on onClick() and check it its >= 5 before starting the intent.
int clickCounter;
public boolean onClick(View v) {
clickCounter++;
if (clickCounter >= 5) {
Intent myIntent = new Intent(activity, loginActivity.class);
activity.startActivity(myIntent);
}
return false;
}
For the second question you must take into account whether previous Activity must keep exactly the same aspect or update with user data. Take a look at Activity.startActivityForResult (Intent intent, int requestCode) for calling an activity and get a result value from it.
-
Android 2.1 via eclipse
I have an activity that opens a dialog themed activity via checkbox onChecked function
Im creating this new dialog themed activity with an Intent.
Problem is, how do i dismiss the dialog themed activity once i finish with it? (the way it stands now, i have to send a new intent in order to go back to the previous activity via click of a button)
Any help would be greatly apprieciated!
Code snippet:
Main activity:
cbReminder.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
{
Intent intent = new Intent(getApplicationContext(), DateTimeDialog.class);
startActivity(intent);
}
}
});
Dialog themed activity:
public void onClick(View v) {
if (v.getId() == R.id.b_datetime_save)
{
}
else if (v.getId() == R.id.b_datetime_cancel)
{
finish();
Intent intent = new Intent(getApplicationContext(), MakeNoteActivity.class);
startActivity(intent);
}
}
As you specified, the intent was indeed not needed to return to the previous activity and should be removed.
To uncheck the checkbox after returning from the dialog, you can use startActivityForResult and set a callback for when you return.
Open your dialog like this:
Intent intent = new Intent( getApplicationContext(), DateTimeDialog.class );
startActivityForResult( intent, UNIQUE_IDENTIFIER );
Then add a callback to that same activity:
#Override
protected void onActivityResult( int requestCode, int resultCode, Intent data )
{
if ( requestCode == UNIQUE_IDENTIFIER )
{
cbReminder.setChecked( false );
}
}
The UNIQUE_IDENTIFIER can be any number that uniquely identifies this dialog. Let me know if you have any more questions.