onKeyDown / onBackPressed is not firing - android

In which cases are onKeyDown, onBackPressed not firing?
In my case I have a TabActivity with a ActivityGroup in background where all the upcoming views/activities are stored. The ActivityGroup takes care of adding and removing views. So when I start a new Activity in my main tab the startChildActivity method of ActivityGroup is called:
public void startChildActivity(String viewId, Intent intent) {
Window window = getLocalActivityManager().startActivity(viewId, intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
if(window != null) {
history.add(new HistoryContainer(viewId));
setContentView(window.getDecorView());
}
}
If I now start the Activity Dummy in this way the mentioned keyEvents like onKeyDown or onBackPressed are not firing anymore. What's happening is the app is closing.
public class Dummy extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dummy);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
MazdaGroup.group.back();
return true;
}
#Override
public void onBackPressed() {
MazdaGroup.group.back();
}
}
Would be glad for your help!

Related

Disable a button when an event occure in main activity

I have two activities named Main activity and Second Activity. Main activity has an event handler. I need to disable a button in second activity when an event occurs.
Main activity
public void myEventListener(int eventID){
switch (eventID) {
case : 0
// disable button of second activity here
break;
}
}
This is an easy one.
Use SharedPreference of changing data(boolean maybe) in MainAcitivity
Use SharedPreference.OnSharedPreferenceChangeListener in SecondActivity for listening to that specific data and changing button state at runtime in.
MainActivity.java
public class MainActivity extends AppCompatActivity {
SharedPreferences.Editor editor;
public void myEventListener(int eventID){
switch (eventID) {
case 0:
editor = getSharedPreferences("pref",MODE_PRIVATE).edit();
editor.putBoolean("event",true);
break;
}
}
}
SecondActivity
public class SecondActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
SharedPreferences sharedPreferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
}
#Override
protected void onStart() {
super.onStart();
sharedPreferences=getSharedPreferences("pref",MODE_PRIVATE);
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onStop() {
super.onStop();
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals("event") && sharedPreferences.getBoolean(key,false))
{
//add your code to disable your button or any action you want
}
}
}
It's very simple to disable a button. Follow the below steps to achieve your problem.
Define a global boolean value as "false"
In onClickEvent override, the boolean value as "true".
Then check with the boolean value as follows
private boolean isClicked = false;
if(isClicked){
button.disabled(true);
} else {
button.disabled(false);
}
Please let me know if you have any issues while applying.
In you First Activity make Boolean static variable.
Example:
FirstActivity
create a Boolean static global variable
public static Boolean clicked = false;
onFirstActivity if Event occurs.
event occurred => clicked = true; otherwise it is false
SecondActivity
in second activity get the value to static boolean from FirstActivity
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (FirstActivity.clicked){
//Do Nothing
}else{
//Perform action
}
}
});
first make reference of second activity and set button visibility GONE or INVISIBLE It's Work
SeconActivity sa; //reference of second activity
public void myEventListener(int eventID){
switch (eventID) {
case : 0
sa.btnofsecondactivity.setVisibilty(View.GONE);
break;
}
}
You can go with LocalBroadCastManager.
in MainActivity wherever you want to trigger the method
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("event-occured"));
in SecondActivity register the LocalBroadcastManager and receive it.
public class SecondActivity extends AppCompatActivity {
private BroadcastReceiver mainActivityReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
mainActivityReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do whatever you want to do
Log.d("TAG", "broadcast received");
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(mainActivityReceiver, new IntentFilter("main-activity-initialized"));
}
#Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mainActivityReceiver);
}
Don't forget to unregister the listener in SecondActivity's onDestroy method. Taken reference from here.

Android implementing onBackPress on Fragment cause of disable exit from application

In my application i have some fragment and i can exit from application by click on back on phone without problem, but when i implementing onBackPress on that i can't exit from application
My code:
#Override
public void onResume() {
super.onResume();
if (getView() == null) {
return;
}
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
if (slider_call_phones.isOpened()) {
slider_call_phones.closeLayer(true);
}
return true;
}
return false;
}
});
}
I want to handle onBackPressed on fragment not Activities
Here's how I do it,
create an interface that would receive onBackPressed() in any class
that implements it and would return true if it's handling the method or false otherwise. This would make sure that your app would exit when your return false.
create a stack of these interfaces in your Activity, then add any of such interfaces to it.
override onBackPressed() in your activity, then anytime it's called, get a listener from the stack and call its own onBackPressed() if it returns true. If it returns false, then it's not handling onBackPressed() so Activity can take over and remove fragment or exit the application.
Here's a sample implementation.
In your Activity
public class MyActivity extends Activity {
//a stack of OnBackPressedListeners, stack one when you want it to receive onBackPressed() from
//this activity.
//PS used stack so that by LIFO, the last listener would be the first to be called.
private Stack<OnBackPressedListener> onBackPressedListeners = new Stack<>();
#Override
public void onBackPressed() {
if (!onBackPressedListeners.isEmpty()) {
if (onBackPressedListeners.peek().onBackPressed()) //if interface is handling onBackPressed(), return. Otherwise super would be called below.
return;
}
//if no listeners, then do super. This would ensure natural behaviour such as closing the app or popping a fragment when no listeners are using onBackPressed()
super.onBackPressed();
}
//listener interface
public static interface OnBackPressedListener {
/**
* #return true if you're handling onBackPressed, false otherwise to let super.onBackPressed() take over
*/
public boolean onBackPressed();
}
public void addOnBackPressedListener(OnBackPressedListener listener) {
onBackPressedListeners.add(listener);
}
public void removeOnBackPressedListener(OnBackPressedListener listener) {
onBackPressedListeners.remove(listener);
}
}
In your Fragment
//implement OnBackPressedListener in your fragment.
public class MyFragment extends Fragment implements OnBackPressedListener {
//find somewhere to add the listener to your Activity, most likely in onCreateView(...)
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
...
((MyActivity)getActivity()).addOnBackPressedListener(this);
...
return view;
}
//overide onBackPressed(), then return true if you're handling the onBackPressed(), false otherwise.
#Override
public boolean onBackPressed() {
if (slider_call_phones.isOpened()) {
slider_call_phones.closeLayer(true);
return true;
}
return false;
}
//lastly remember to remove the listener when your fragment is destroyed, so that it stops receiving callbacks,
//if you don't do this, you might get a NullPointerException.
#Override
public void onDestroy() {
super.onDestroy();
((MyActivity)getActivity()).removeOnBackPressedListener(this);
}
}
I mostly use a single Activity and a whole lot of Fragment's in my Android apps, this is exactly how I solve such problems you are having, for example closing a drawer in a Fragment if its open when the back button is pressed, or exiting the application if it's closed.
You should call onBackPressed() in the following manner in order to exit from the app:
public void onBackPressed(){
finishAffinity();
}

Android get EventBus event on fragment not working

after define event class and post event on Activity onBackPressed() i cant get event on fragment, some my activities opening above this fragment which that is child of MainActivity. i want to get some events that post from other opening activitis, but my code doesnt get this event on Fragment, but i can post event from Activity onBackPressed()
SignalActivityMarketDetailStateEvents class:
public class SignalActivityMarketDetailStateEvents {
private boolean activityMarketDetailState;
public SignalActivityMarketDetailStateEvents(boolean activityMarketDetailState) {
this.activityMarketDetailState = activityMarketDetailState;
}
public boolean isActivityMarketDetailState() {
return activityMarketDetailState;
}
}
ActivitySecond :
#Override
public void onBackPressed() {
EventBus.getDefault().post(new SignalActivityMarketDetailStateEvents(true));
}
Fragment to get event:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(SignalActivityMarketDetailStateEvents event) {
Log.e("EventBus ","Received");
}
#Override
public void onStart() {
EventBus.getDefault().register(this);
super.onStart();
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
#Override
public void onResume() {
EventBus.getDefault().register(this);
super.onResume();
}
in my Fragment this line doesnt work after post event:
Log.e("EventBus ","Received");
You are not mindful of the life cycle's of those activities. You could use the sticky events (postSticky) . Or update the state in some singleton and read that in onResume.

Application Level onResume Android

Problem
The idea is very simple. Whenever an user comes back to my app from the Recents I want to show a simple dialog prompting with the password.
I know how to prompt the dialog with password, but my problem is how do I understand that the user has entered my app from the recents. If I put the prompt in the onResume in every activity, then it will get triggered everytime even if the user doesn't enter from the Recents menu.
There are lots of activities and fragments in my app. So, I would love to have a more generic or application level solution.
Implement Application.ActivityLifecycleCallbacks, that will provide all activity callback in your application class.
public class AppController extends Application implements
Application.ActivityLifecycleCallbacks
{
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
You could try with this flag FLAG_ACTIVITY_LAUNCHER_FROM _HISTORY:
if((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY )!=0){
Log.d(TAG, "Called from history");
//clear flag from history
Intent intent = getIntent().setFlags( getIntent().getFlags() & (~ Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY));
setIntent(intent);
}
Source : Android - detecting application launch from home or history
When "A" Activity is start from recent, this flag is present.
Now this flag will be also present if "A" activity call "B" activity and on "B" user press back.
So you have to check flag and when you detect it you have clear intent by removing this flag, source: Remove a Paint Flag in Android
Try below sample
/**
* TODO : After update to API level 14 (Android 4.0),
* We should implement Application.ActivityLifecycleCallbacks
*/
public class GlobalApplication extends android.app.Application
{
private boolean inForeground = true;
private int resumed = 0;
private int paused = 0;
public void onActivityResumed( Activity activity )
{
++resumed;
if( !inForeground )
{
// Don't check for foreground or background right away
// finishing an activity and starting a new one will trigger to many
// foreground <---> background switches
//
// In half a second call foregroundOrBackground
}
}
public void onActivityPaused( Activity activity )
{
++paused;
if( inForeground )
{
// Don't check for foreground or background right away
// finishing an activity and starting a new one will trigger to many
// foreground <---> background switches
//
// In half a second call foregroundOrBackground
}
}
public void foregroundOrBackground()
{
if( paused >= resumed && inForeground )
{
inForeground = false;
}
else if( resumed > paused && !inForeground )
{
inForeground = true;
}
}
}
Put below code in your all activities.
public class BaseActivity extends android.app.Activity
{
private GlobalApplication globalApplication;
#Override
protected void onCreate()
{
globalApplication = (GlobalApplication) getApplication();
}
#Override
protected void onResume()
{
super.onResume();
globalApplication.onActivityResumed(this);
}
#Override
protected void onPause()
{
super.onPause();
globalApplication.onActivityPaused(this);
}
#Override
public void onDestroy()
{
super.onDestroy();
}
}
I would suggest using LifecycleObserver. If your Application class implements this interface it marks a class as a LifecycleObserver, it does not have any methods, instead, it relies on OnLifecycleEvent annotated methods. The usage is simple:
public class AndroidApplication extends Application implements LifecycleObserver {
#OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onAppStart() {
//enter code here
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onAppStop() {
//enter code here
}
...etc
}
With Lifecycle.Event you can access all lifecycle states through Enum. It is part of androidx.

Free up memory on Android when push Back Button

I have 2 activities, Activity1 and Activity2. In Activity1 I have a button to go to Activity2.
Activity2 has a lot of Edittext and other Views.
When I start the app, the memory of the process is 10mb. If I click on the button and Activity2 is loaded, my memory's process is about 59mb.
The issue is, in Activity2, if I push Back Button, I return to Activity1 and my memory's process is about 59mb, and I don't need this information about Activity2.
Now, If I click again the button, I have an OutOfMemory.
How can I force to free up the memory when I push Back Button?
I try to call finish() and System.gc() but It doesn't work.
Thank you
try this one....
first close your activity...
use following code...
public class ur_clss extends Activity {
private ur_class c1;
//ur content here
#Override
public void onBackPressed () {
c1.finishActivity(0);
}
}
You need to override the BackButton and free up the memory when it is pressed.
#Override
public void onBackPressed()
{
Activity.finish() // the activity that you want to terminate
}
Or, there is another way to do it. When you start the new activity, the old activity goes onPause(). You could try calling finish() in the onPause() of the old activity.
This is the structure of the code:
public class Activity2 extends Activity {
// Global variables
private CarregaOperacions carrega_operacions;
private TableLayout taula;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Some code of UI
// Show a ProgressBar
loadProgress();
carrega_operacions = new CarregaOperacions(Activity2.this);
carrega_operacions.execute(null);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK))
{
finish();
}
return super.onKeyDown(keyCode, event);
}
static class CarregaOperacions extends AsyncTask<Void, Void, Void> {
WeakReference<Activity2> context;
Activity2 act;
public CarregaOperacions(Activity2 activity) {
context = new WeakReference<Activity2>(activity);
act = context.get();
}
#Override
protected Void doInBackground(Void... arg0) {
act.carregaOperacions();
return null;
}
protected void onPostExecute(Void result) {
ArrayList<LinearLayout> llista = act.getLlistaFiles();
for (int i = 0; i < llista.size(); i++ ) {
act.getTable().addView(llista.get(i));
}
act.getScroll().setVisibility(View.VISIBLE);
act.treuProgres();
}
}
With this code, I explain a bit:
The real case is, Activity1 calls a TabActivity, that has the Activity2. Activity2 loads a lot of registers, and I do this asynchronously. I Override onKeyDown in Activity2 and on the TabActivity, but it seems that only is onKeyDown's Activity2 executed.

Categories

Resources