Android: How to enable button when service complete its task? - java

I have two buttons StartButton and StopButton on MainActivity.java . When I press StartButton a Service is created and StartButton get disable. On pressing StopButton Service get destroyed and StartButton get enable.
What I wanted to do is to enable my Start Button as Service completed its task; it returns any notification or trigger type event or message value on my MainActivity.java so my Start Button get enable.
Please give me any idea, concept or code to make it easy for me to understand.

To understand the communication between service and application take a look at the examples in the android developer docs.
You can enable and disable your buttons in the onServiceDisconnected() and onServiceConnected() methods.
Keep in mind that the service runs in the same thread as your app by default.

Have you tried,
MyButton.setClickable(false);
It will make the button disabled.
and
MyButton.setClickable(true);
It will enable the button.
However, if you want to hide or show the button, you can use,
MyButton.setVisibiity(VIEW.VISIBLE); and MyButton.setVisibiity(VIEW.INVISIBLE);
Edit- As you want to enable the button, once its task is completed, you could open the mainActivity with a flag value true, something like this,
Intent i= new Intent(getBaseContext(), myActivity.class);
i.putExtra("flag", true);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(i);
and in the mainActivity, check the value of flag,
Boolean flag;
flag = this.getIntent().getBooleanExtra("flag", false);
if(flag == true) {
MyButton.setClickable(true);
}
But for it, you should keep the value of flag initially to false.
and once you click the button, you could then set it as not clickable.

There can be many ways to achieve this. Let me tell you one with Broadcast Receiver. I hope you are aware of BroadcastReceiver Concepts.
Changes requires in your activity
1) Create a Broadcast receiver as inner class in your activity.
2) Register it with some action, suppose "MY_ACTION".(remember to unregister this receiver on onPause/onDestroy methods)
3) Suppose service completed its task, and you are into onReceive method of Broadcast receiver, now write your code to enable/disable button(i hope you know how to do it)
Changes requires in your Service
1) find out code where you think its task has completed.
2) Create an intent with same action ("MY_ACTION").
3) Broadcast message with sendBroadcast , intent as param. and you are done. :)
let me know if in any point you feel you are stuck ,

Related

Check whether an activity is active or not from a different activity

I have a flow in my application like this:
For new users:
Splash Screen --> Login Activity --> Home Activity
For already registered users:
Splash Screen --> Home Activity
Basically the Splash Screen has an if else to decide which activity to go to. Once a first time user logs in, his status is saved in a preference variable for the splash screen to decide next time not to open the login activity.
Now the situation is that. If a new user logs in and goes to the home activity, and then logs out. He is redirected to the Login screen which is pretty much what should happen. But, in case an existing user opens the app, he is shown the Splash screen and directly moved to the Home Activity. Now if the user logs out, he gets out of the app. This happens because the Login Activity does not have any instance created and thus finishing the Home Activity finishes the whole app. Logout actually finishes the Home Activity, naturally the last active activity should open up. Which is not happening.
What I want to do is that, I want to implement a logic which will check that the Login Activity is available or not. If its available then finish() will be called else the Login Activity will be called via intent.
Please tell me how to achieve this.
P.S: My app uses a custom theme with a customized action bar. If I call finish and Intent together or I use flags to clear existing activities then there is a weird transition effect which shows the black standard action bar for a split second thus creating a bad user experience.
Now if the user logs out, he gets out of the app. This happens because
the Login Activity does not have any instance created and thus
finishing the Home Activity finishes the whole app.
If i understood your question, why dont you just call the Login Activity manually after user click a logout button?
Its what i always did with apps that have flow like yours
when user login finish login activity and start home activity.
when user logout finish home activity and start login activity
You always can call Login Activity via intent. If the activity is available, android will show this activity. Else android will create new activity automatically.
Actually that's why we use intents to show activity instead of creating activityes manually. System catches this intents and does all dirty work.
EDIT:
Hmm, but wouldn't you have the transition problem anyways? (If you were already logged in, and then log out - using intent/finish() you will have the same black action bar issue no?)
Maybe consider following ( I actually did this in my app):
Merge Splash screen and Login into one activity and depending whether you are logged in - display the login fields or proceed to home screen. Then you have a out of box consistent stack of activities regardless of use cases and no mambo-jumbo with do I already have this or not.
I can't comment because of I lack 4 rep, so I'll post as answer here:
I think #Blaze Tama is right. You can also use FLAG_ACTIVITY_CLEAR_TOP on intent to avoid stack flow problems:
From docs:
If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.
Always start Login activity and start Home activity right away if the user already logged in.
In the Splash Screen activity
Intent intent = new Intent(this, Login.class);
If (user already logged in)
{
intent.putextra("Logged in", true);
}
startActivity(intent);
In the Login activity
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent != null)
{
if (intent.getBooleanExtra("Logged in", false))
{
startActivityForResult(new Intent(this, Home.class), requestCode);
}
}
else
{
// The existing code here
}
}
In Home activity send back a code to indicate if the user logged out or just BackPress. If BackPress finish this Login activity.

App won't close after finish() [duplicate]

This question already has answers here:
How to exit from the application and show the home screen?
(22 answers)
Closed 5 months ago.
So, I'm trying to create an app which have a function like an alarm clock for Android phones, it will alert the user at their chosen time. When the alert screen show up, the user has an option to push a notification or snooze, and the app will push a notification and then close.
However, when I click the snooze or the notification button, the app did not close. Instead, the app stop the alarm sound and minimized (just as when the user touch the home button). If I touch the recent app, I then can open the alert screen again.
Edit: I know that there're some codes such as System.exit() or killProcess, since those code are not recommended, I prefer avoid using them.
The reason I ask is because I tested the real clock app that come with my phone (4.3), and the it's alert screen will close after the I press the snooze or dismiss button. So there must be a way for me to do the same, right ?
Answer
Okay, so as Sagar Pilkhwal explained below, and after reading others related problems, I found out that there's no "good" method to close you app by codes, you have to leave that option to the users or OS. Unless you want to use System.exit or killProcess, but they're bad ways to force your app to close.
Sagar Pilkhwal also have a alternatively method to this problem, if you don't want your alert screen show up in recent app, you bring up another activity.
However, as for this case and Alarm Manager in general, open MainActivity will lead to nasty stuffs, since MainActivity is when we handle Alarm events. Then I found out another solution, if you don't want your alert screen show up in recent app, simply add
android:excludeFromRecents="true"
to your Alert.class Activity in the Manifest, or add Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTSto the intent used to start Alert.class.
This will lead to other problem, as when the user press the Home button, the alarm won't turn off, and the user can't open recent app to access the alert screen (he'll has to open the app to do so). I fix this problem by try to detect the home button pressed event. Detail answer are below.
well im thinknig.
System.exit(0);
maybe? im new to android thou..but i sometimes use it..
Put the following to Manifest, in your Alert activity :
android:excludeFromRecents="true" //this will make the Activity be exclude from recents list.
You can also add android:launchMode="singleInstance" and android:taskAffinity="" (if you know what they do)
In the Alert class, use this to detect home button pressed event:
#Override
public void onPause() {
if (!isFinishing()) {
createNotf(); //Handle home button press here.
}
super.onPause();
}
Use this to handle back button pressed: (You have to have this code if you want to detect home button press using isFinishing();
#Override
public void onBackPressed() {
//Handle BackButton event here.
}
For my case only, when the user press home button, I will create a notification, so he can either click on the notification or open the app again to access to Alert Screen.:
private void createNotf() {
Intent screenIntent = new Intent(MyAlert.this, MyAlert.class);
screenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
screenIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
PendingIntent pIntent = PendingIntent.getActivity(MyAlert.this, MainActivity.SEND_ALARM_CODE, screenIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification.Builder ntfBuilder = new Notification.Builder(this)
.setAutoCancel(true)
.setContentTitle("ALARM_RUNNING")
.setLargeIcon(bitmap)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText("CLICK_TO_OPEN_ALERTSCREEN.")
.setContentIntent(pIntent);
NotificationManager myNotfM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
myNotfM.notify(999, ntfBuilder.build());
}
When the Alert stop, that notification will also be clear:
#Override
public void onDestroy() {
super.onDestroy();
NotificationManager mntfM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mntfM.cancel(999);}
System.exit(0);
That right there will close your application out leaving nothing running in the background.However,use this wisely and don't leave files open, database handles open, etc.These things would normally be cleaned up through the finish() command.
I personally HATE when I choose Exit in an application and it doesn't really exit.

Android GCM: different way of handling push depending on whether the app is visible or not

I've got a couple of activities and an intent service which handles GCM incoming messages.
Right now for every push, I'm sending a Notification, and after the user clicks it, he is redirected to appropriate screen.
I would like to alter this behavior that if the app is visible (any activity is in the foreground), instead of the notification a dialog message is shown (with appropriate action).
Any idea how to implement it?
I have 2 ideas but none of them is perfect:
Keep track of every activity in the application, if the activity is visible, don't show notification, but sent an intent to the activity (not nice solution)
register/unregister the second broadcast receiver in each activity's onResume/onPause, "catch" the incoming GCM broadcast (I'm not sure if it is possible).
Any other solutions?
A possible solution (idea 1):
To detect whether your app is running back- or foreground, you can simply set a boolean in onPause/onResume:
#Override
protected void onResume() {
super.onResume();
runningOnBackground = false;
}
#Override
protected void onPause() {
super.onPause();
runningOnBackground = true;
}
When you start a new intent from an notification this method gets called: (if you are using singleTop), with the boolean you can determine what to do in the onNewIntent method.
#Override
protected void onNewIntent (Intent intent){
if(runningOnBackground){
//do this
}
else{
//do that
}
}
Hope it helps!
I didn't test it, but the docs say you can get the number of running activities per each task.
Try to find your application's task among currently running tasks:
ActivityManager acitivityManager = (ActivityManager)
context.getSystemService(Context.ACTIVITY_SERVICE);
// Get the top of running tasks, limit by 100
List<RunningTaskInfo> tasks = acitivityManager.getRunningTasks(100);
for (RunningTaskInfo taskInfo : tasks) {
if (YOUR_PACKAGE_NAME.equals(taskInfo.baseActivity.getPackageName())) {
if (taskInfo.numRunning > 0) {
// Show dialog
} else {
// Show notification
}
break;
}
}
Google added a note on getRunningTasks():
Note: this method is only intended for debugging and presenting task management user interfaces. This should never be used for core logic in an application, such as deciding between different behaviors based on the information found here. Such uses are not supported, and will likely break in the future. For example, if multiple applications can be actively running at the same time, assumptions made about the meaning of the data here for purposes of control flow will be incorrect.
So use it at your own risk.
Also check if GCM broadcasts are ordered. If so, you can "override" your default BroadcastReceiver with the other ones in each Activity. Just play with the priority of IntentFilters. When the BroadcastReceiver with higher priority receives the message, it can abort it's further propagation. For your application this means that when some Activity is running, it registers the receiver which shows the dialog and aborts broadcast. If no activity is active, then your default receiver shows the notification.

Android, Opening app only if it is closed through intent action

I am working on a phonegap application, with some native pieces.
So far I have notifications running natively, to make sure javascript and phonegap is not required at all. The problem I am having however, is when the notification is clicked I'd like to open the app, or otherwise just bring the app to the front.
How do I do this? I tried setting the main activity in the intent, but it restarts my application every time.
Intent notificationIntent = new Intent(context, main.app.class);
notificationIntent.putExtra(NOTIF_RESPOND, runThis);
notificationIntent.setAction(Intent.ACTION_VIEW);
notificationIntent = notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Actually in Android there is almost no such thing as "restarting application". Basically the Application - is a bundle of all your services/activities/providers etc. It's either running or not.
If user starts a new Activity - system will check, if application is running - it will create this activity inside the application. If no - will create new Application instance.
So I think you mean that if you set intent for your Main activity - another instance of Activity is launching, am I right?
If so - take a look at the following flag for activity, you should try to set in in the Manifest(or whatever in PhoneGap, sorry). http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
<activity android:name=".YourActivity"
android:launchMode="singleTask"
...
This flag will tell the system not to create a new Activity each type it will be needed, but to reuse already-existing one. Be careful, you should properly implement onNewIntent method in this case to handle this "relaunches", and I'm not 100% sure that it's implemented in PhoneGap.
Good luck

Close acivity 'used as dialog' on Android

I have an activity, which I used as a custom loading dialog (the dialog is pretty complex and has custom UI, which fits the customer colors schemes, etc.).
The loading dialog is created and shown from class, which is not derived from Activity class (this I am mentioning becuase the startActivityForResult() cannot be called):
private void showLoadingDialog()
{
Intent intent = new Intent( this, ActivityDialogLoading.class );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity( intent );
isLoadingDialogShown = true;
}
The dialog is shown when long running asynchronous tasks are performed by the application on background.
Now when the background tasks if finished I want to close the loading dialog (The loading dialog has also the Cancel button, so client can interrupt the task, but this is other story).
I did not found a way to get the reference to the instance of the running ActivityDialogLoading class to call the finish() method...
The way I am using is a bit complicated - I override BroadcastReceiver so it takes the reference to the ActivityDialogLoading in its constructor. In OnResume() method of the ActivityDialogLoading I register as a receiver for broadcasted intent.
When I need to close the loading dialog i broadcast the intent... Is there a better way?
Saying the same with other words: What is the best way to close an activity when the close action is caused by some background event in application engine?

Categories