Disable button after returning from an intent - java

Afternoon all I need to call an intent and upon returning disable the button for X seconds.
I have tried variations of the following, which either disable the button immediately and then enable or do not do what I need full stop.
Guarding.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Guarding.setEnabled(false);
SharedPref.write(SharedPref.SCANTYPE,"GUARDING");
Intent intent = new Intent(Menu.this, CmxScanner.class);
startActivity(intent);
Guarding.postDelayed(new Runnable() {
public void run() {
Guarding.setEnabled(true);
//Log.d(TAG,"resend1");
}
},10000);
}
});
So on first entry to the menu i have a button that is enabled, after clicking it must call the intent and upon returning disable the button again for X seconds. Before it will enable and allow a second request to the Intent

You can register your calling activity for a result as explained in the Android docs here. Then in the result callback you simply enable the button after 10 seconds:
ActivityResultLauncher<String> mGetContent = registerForActivityResult(new GetContent(),
new ActivityResultCallback<Uri>() {
#Override
public void onActivityResult(Uri uri) {
Guarding.postDelayed(new Runnable() {
public void run() {
Guarding.setEnabled(true);
}
}, 10000);
}
}
});

Related

When multiple clicks on activity navigation click, why 2nd activity lifecycle methods calling double times

When i multiple taps on a activity passing button, it takes activity1 has been pause state and after a few seconds activity2 has been come to foreground/visible to the user state.
my problem is , when we are moving on activities with multiple taps, it takes few seconds to user has been wait for next activity come to the visible state. it's really a bad practice.
Here is Call Logs of acticity lifecycle methods:
calling pause - Activity1
call: calling noti create - Activity2
call: calling noti start - Activity2
call: calling noti resume- Activity2
call: calling noti pause- Activity2
//2nd time calls of lifecycle methods
calling noti create- Activity2
call: calling noti start- Activity2
call: calling noti resume- Activity2
Here is Button click of activity navigation:
#OnClick({R.id.card_notification})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.card_notification:
startActivity(new Intent(context, NotificationsActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
break;
}
}
if i remove setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP), activity2 opens multiple times when multiple taps on button click.
I tried with set launch mode in the manifest file.
<activity android:launchMode=”singleTop” />
in this case also activity 2 takes few mill seconds to come to visible state.
Note: When single tap/click everything works fine.
Please help me, what's going wrong in this scenario.
Here 2nd activity code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_noti_detail);
Log.e("call", "noti create");
context = this;
ButterKnife.bind(this);
setToolbar();
callApi("");
etSearchh.setOnEditorActionListener((v, actionId, event) ->
{
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
isSearch = true;
//membersList = null;
callApi(etSearchh.getText().toString().trim());
CommonUtils.hideKeyboard(this);
return true;
}
return false;
});
etSearchh.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().length() > 0) {
iv_clearSearch.setVisibility(View.VISIBLE);
} else {
iv_clearSearch.setVisibility(View.INVISIBLE);
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
iv_clearSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
iv_clearSearch.setVisibility(View.GONE);
etSearchh.setText("");
//membersList = null;
callApi("");
}
});
}
private void callApi(String searchBy) {
new NotificationController(apiCallBack, context, searchBy).callTokenAPI();
}
private void setToolbar() {
toolbarTitle.setText(MyApplication.getLabelModel().getLabels().getTT_NOTIFICATIONS());
etSearchh.setHint(MyApplication.getLabelModel().getLabels().getSEARCH_NOTIFICATION());
}
private void setRecycler(List<Notifications> notifications) {
mAdapter = new NotificationAdapter(notifications, context);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
}
#OnClick(R.id.iv_back)
public void onViewClicked() {
onBackPressed();
}
#Override
protected void onStart() {
Log.e("Call", "calling noti start");
super.onStart();
}
#Override
protected void onResume() {
Log.e("Call", "calling noti resume");
super.onResume();
}
#Override
protected void onStop() {
Log.e("Call", "calling noti stop");
super.onStop();
}
#Override
protected void onPause() {
Log.e("Call", "calling noti pause");
super.onPause();
}
To prevent multiple executions of button presses, you need to add a boolean variable that you use to remember that the button has been clicked and ignore the button click as "noise" if you see it again. Using your example, do this:
Add a boolean member variable to your class:
private boolean buttonClicked;
In onViewClicked() method, set the variable buttonClicked and ignore the click if it was already set:
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.card_notification:
// Ignore if already clicked
if (buttonClicked) {
return;
}
startActivity(new Intent(context, NotificationsActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
// Remember that the button was clicked
buttonClicked = true;
break;
}
This will prevent multiple clicks from starting multiple copies of NotificationsActivity. When the user returns to this Activity, you will want to reset buttonClicked in onResume() so that the user can again click the button (otherwise the user will only be able to click the button once!).

Delay between two functions of one method

I am new to Android Studio. I want to put delay between Animation of button AND opening of second activity, So that animation runs and then splashActivity opens.
btn.setOnClickListener(new View.OnClickListener(){
public void onClick(View arg0){
Animation anim4 = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.splash_anim);
btn.startAnimation(anim4);
startActivity(new Intent(MainActivity.this, splashActivity.class));
}
});
int Delay_time_of_animation=500;
btn.setOnClickListener(new View.OnClickListener(){
public void onClick(View arg0){
Animation anim4 = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.splash_anim);
btn.startAnimation(anim4);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(MainActivity.this, splashActivity.class));
}
}, Delay_time_of_animation);
}
});
I use the native java Timer for the delay. if you want to delay between two method then you have to pass the delay time in milliseconds.
int DELAY_TIME=2000
//start your animation
new Timer().schedule(new TimerTask() {
#Override
public void run() {
//this code will run after the delay time which is 2 seconds.
startActivity(new Intent(MainActivity.this, splashActivity.class));
}
}, DELAY_TIME);
2000 millisecond means 2 second you can increase this time

How to update Activity from thread started in another activity?

I have a Main activity and after click on button I start thread (but the thread is hidden in library and I have only callback in Main activity.
Now I want to start another activity (call A) where I want to put results from the thread.
Below is simplified code:
public class Main extends Activity {
XManager.ResultsCallback xResultsCallback = new XManager.ResultsCallback() {
// the method is called every 10 sec.
#Override
public void onResult(ArrayList<String> texts) {
}
};
XManager xManager = new xManager(xResultsCallback);
View.OnClickListener onClick = new View.OnClickListener() {
#Override
public void onClick(View arg0) {
XManager.start();
Intent i = new Intent(Main.this, A.class);
startActivity(i);
}
};
}
I want to update the content of A activity each time when onResult() method is called. How to do that?
Use LocalBroadcastManager,
In your Main Activity create function :
private void sendResult() {
Log.d("sender", "Broadcasting message");
Intent intent = new Intent("custom-event-name");
// You can also include some extra data.
intent.putExtra("message", "This is my result!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
and add BroadcastReceiver in your A Activity
private BroadcastReceiver onResult= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("jazzy","onReceive called");
}
};
add on OnCreate
#Override
public void onCreate(Bundle savedInstanceState) {
// Register to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
add onDestroy
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
I have a suggestion that you should do as follows:
Start Your Activity A on button click
Inside Activity A declare your XManager instance with a callback present in A itself
Then start your XManager as XManager.start(); that way you would be getting all the callbacks in your desired activity.
Have a great day!
I think if you want to decouple the logic, beside you can use the Android BroadcastReceiver, the another flexible choice is to use the Bus
And you can integrate it with gradle easily
dependencies {
compile 'com.squareup:otto:+'
}

How to restore to exact activity after coming from Paused or Resumed state in android

I have two simple activities MainActivity and ThreadActivity. I call ThreadActivity from MainActivity.
The code ofMainActivity:
public class MainActivity extends Activity {
private Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.btn2);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ThreadActivity.class);
startActivity(intent);
}
});
}
}
And the code of ThreadActivity:
public class ThreadActivity extends Activity{
private Thread myThread=null;
Button btn;
int i = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runThread();
}
});
}
void runThread(){
myThread = new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
Log.d("Thread", "I am running " + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
}
};
myThread.start();
}
}
When I start ThreadActivity I run a simple thread and change button text.
My Problem
When I loose focus from application, i.e when application becomes partially visible, and I come back I am redirected to ThreadActivity and the thread is still running.
When I leave application running and open a new application, and then come back, I am again redirected to ThreadActivity.
The problem is when I press back button, I am being redirected to first activity MainActivity. But instead when back button is being pressed I want my application to exit. In a few words MainActivity should not exist in the stack.
I tried setting android:noHistory="true" for MainActivity but I could not keep the behavior explained in bullet points working. I mean when I pause the application and restore it back, it redirected me to MainActivity instead of ThreadActivity.
Just call finish() when starting the ThreadActivity:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ThreadActivity.class);
startActivity(intent);
finish();
}
});
BUT there is a problem with your app. Use a Timer to set the text of the Button! By using a Thread like you do you are creating a memory leak and that is very bad. Try this:
private int i = 0;
private Timer timer;
private final TimerTask timerTask = new TimerTask() {
#Override
public void run() {
btn.post(new Runnable() {
#Override
public void run() {
btn.setText("#" + i++);
}
});
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer = new Timer();
timer.schedule(timerTask, 300, 300);
}
});
}
#Override
public void onPause() {
super.onPause();
if(timer != null) {
timer.cancel();
}
}
From your comments to other peoples' answers, it seems like you want the ThreadActivity to always be resumed instead of the MainActivity when your thread is running.
Do the thread in a Service - the service will mean your application's VM is likely to be kept alive longer. An app with no foreground activities can be killed off quite quickly (even if it has background threads running).
You need to persist that the thread is running, and the progress (if, in the real code that is applicable). Currently you could persist the value of i in your while loop.
Your application's default launcher activity (MainActivity) will launch when you click on it from your launcher. Check if the persisted value has been set, and act as though the user started the ThreadActivity in onCreate, if you finish() in onCreate, the user won't see any UI from the MainActivity
Depending on what you're actually trying to do, you might be able to resume the thread depending on the progress persisted - in this example, you could start from the persisted value of i (instead of 0).
What I had to is set android:noHistory="true" for MainActivity and in the ThreadActivity I had to add the solution mention by #NeTeInStEiN in this quesiotn
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(true);
return true;
}
return super.onKeyDown(keyCode, event);
}

Android back button freezes when using onkeydown method or overriding onbackbuttonpressed

public boolean onKeyDown(int keyCode, KeyEvent event){
if (isSub2&&keyCode == KeyEvent.KEYCODE_BACK) {
Intent intent = new Intent(ctxx, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
isReturning = true;
return false;
}
else {
return super.onKeyDown(keyCode, event);
}
}
}
There are two Activities Main--Sub2.
When you push a button in Main you can go to Sub2.
This code is in Sub2. I want to use back button on the bottom to make the MainActivity put on the top of stack not killing Sub2.
When I run it on the phone it works all right at first,
but after few more times of going back in Sub2 and going to Sub2 again
the back button stops working.
I don't know what is making the back button freeze.. any ideas?
ps) i've tried using handlers inside the method and overriding onBackButtonPressed() instead of using onKeyDown..
but no difference at all..
Not sure why your button freezes. It would be helpful to see what you are doing in the main activity. Here's an example that works for me and does not freeze:
You can put this in the main activity:
#Override
protected void onStart() {
super.onStart();
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, SubActivity.class);
//****** Uncomment the following line if you want to re-use the subactivity instead of launching a new one
//intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
});
}
And this in the sub-activity:
#Override
public void onBackPressed() {
//super.onBackPressed();
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}

Categories

Resources