I'm trying to explicitly launch an intent to a new Activity, but I would like some code in the current Activity to finish executing first. I've done a bit of research, and have a couple of ideas to accomplish this but am thinking "there's gotta be an easier way to do this". Here is the relevant block of code:
cpuToast(dmg);
if (player_.getStatus() == false)
{
playerWon_ = false;
Intent intent = new Intent(Main.this, Death.class);
startActivity(intent);
}
dmg is an int. cpuToast simply makes a String to display the damage and then calls show(). getStatus() returns whether or not the player was killed. In the event that player was killed, I launch a new intent which will play an animation of the players death. Unfortunately the "Death" Activity is being launched before the Toast even becomes visible, and then it becomes visible during the Death Activity which I do not want.
Does anyone know a simple way to ensure that the Toast executes fully prior to launching the Death Activity? From what I've found it looks like I'll have to create a "Timer" object when really all I want is a simple while loop like "while(Toast.isVisable) {}" to tie up the execution for a couple of seconds.
Some example code for updating the UI in response to timed events can be found at http://developer.android.com/resources/articles/timed-ui-updates.html.
At the time you begin your toast, you can also post a delayed message to your current activity; the runnable of that delayed message can start the new intent.
Does it have to be a toast?
If you are up for the idea of using a custom dialog (removed title, buttons etc.) that is probably your best bet. Use a handler to dismiss the dialog after given time and start the new activity.
Related
I have a basic Activity which mainly allows the user to change settings and save them. I also have a BroadcastReceiver which is launched on SMS_RECEIVED.
The main point of the app is to vibrate whenever a certain message is received until the user taps a button to make it stop. The activity is only there to allow the user to change settings and press the "Stop" button.
In my onReceive method (BroadcastReceiver), I get the content of the last message received and make the phone vibrate if the message is equal to a certain string. All of that is working perfectly, the problem is when I want to make it stop. Right now, I'm trying to make a "Stop" button appear in the Activity when the phone starts vibrating.
I understand that UI elements should remain in the Activity and so what I'm trying to do is communicate between the Activity and my BroadcastReceiver. I've found here how to do that with an Observer. The problem though is that I want the app to function at any time, even at boot time. It's very easy with a BroadcastReceiver but since it requires the Activity to be shown to allow the user to stop the vibration, I have to start the activity if it isn't started already.
So what I do is this:
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("SMSReceived", true);
context.startActivity(i);
ObservableObject.getInstance().updateValue(true);
The problem is, when there is no instance launched, it creates a new one and sends the extra boolean correctly but the updateValue method doesn't seem to get called at all (due to the previous instance I suppose?) and inversely, when there is an instance launched (in the background) the extra boolean doesn't get passed and the updateValue method gets called correctly.
I suppose I could just launch the Activity on boot and immediately put it in the background but it could cause problems if the user closes the application, at which point it would simply stop working until the user started it again since the Observer would have no instance to send data to.
Do you guys have any idea of what I could do to solve my problem?
If it's not clear I can try to explain further.
Summary
Can I start a new activity from a background service when its application is in the background, without bringing the application to the front?
Background
Suppose I'm developing MyApp for Android. This app handles very sensitive information, so we need to lock the app when the user has been inactive for a little while.
MyApp has a service, MyService. Different user interactions with the app resets an inactivity timer in MyService. When the inactivity timer expires, the service starts a new activity, LockActivity, which acts as a screen lock for MyApp. The user has to reauthenticate herself to get past the LockActivity and resume working with the app.
This all works, with one problem: when the LockActivity is started, it brings the app to the front. Since the user may be doing something else (browsing Facebook or whatever), she will be annoyed, and rightly so.
The code I'm using for starting the activity from the background is:
Activity topActivity = magicallyFindMyTopActivity(); // This part is not important; it works though
Intent intent = new Intent(this, LockActivity.class);
topActivity.startActivity(intent);
Do you know any way to avoid this?
An Activity is almost every time something that shows up to the user, so the user can interact with it.
I think what best fits what you are trying to archive is to use OnResume event and check for a field which tells if the app is secured.
Something like this:
onResume(..){
if(isSecured){
_secureMyApp();
}
}
Have a look at this:
Check the security thing in background service at some interval, now have a flag
boolean secure = true;
When the time expires update the flag secure = false;
In your main activity check the flag every time if its false ask the user to authenticate. (Don't create any new activity)
Don't blindly start lock activity when inactivity timer expires, just set some variable and when your app resumes or starts check variable state and show lock screen first.
Many times in android apps, users click a button/view and start a new activity, where the new activity pops up in front of what the user was previously looking at, and loads data.
Would there be any difference from a user perspective if the data started loading (from network or disk or both) when the user clicked the button before the next activity started. And then that data was returned to the new activity in a broadcast receiver.
This is compared to starting the process in the oncreate of the activity. Assuming these network and i/o processes only take milliseconds either way, would it make a difference to the user if the methods were started in onCreate of the new activity, or started in the old activity onClick.
First way, starting I/O and changing views after I/O finishes
//first activity
public void onClick(View v){
startActivity(new Intent(this, NewActivity.class);
}
//NewActivity.class
onCreate(Bundle mBundle){
super.onCreate(mBundle);
setContentView(R.layout.mView);
mObject = networkCall(); //after network call, the view objects in this layout will reflect data from the network call
}
second way, starting the I/O in the first activity
//first activity
public void onClick(View v){
IntentService networkCall = new IntentService();
//start network call
startActivity(new Intent(this, NewActivity.class);
}
//second activity on create just sets the view and also broadcast receiver
My GUESS is that in the split second that it takes for the activity to pop up, the data from the intent service could become available. But at the same time, passing data via intent could take just as long making the benefits marginal
Insight appreciated
In my experience the onCreate() of your new activity is called almost instantly from when you call startActivity(). The new activity doesn't show up right way because it has to take time to render your layout.
You could play around with timings yourself by using the Log.d() function. Something like Log.d(TAG, "This happend at: " + System.currentTimeMillis()); at different points in your code to see when things happen. Watch the LogCat while your apps runs and you can decide for your self which way is better.
I'm making a SIP application, and I've got pretty much everything working that i want to except one thing. I cant get the activity to launch when a SIP call occurs.
I'm working with a SIP library that starts a 'phone' service which deals with the handling of incoming calls etc, and when i create an instance of the 'phone' I then register listeners which detail what i want to happen. So to handle incoming calls i register an 'OnIncommingCall' listener.
If the app isn't currently open at the time i want it to launch the app. so my listener is:
thisPhone.setIncomingCallListener(new OnIncomingCallListener()
{
public void OnIncomingCall(String remoteContact, int accountId)
{
if(MainActivity.this.getIsOpen())
{
MainActivity.this.setIsCallIncomming(true);
MainActivity.this.setCurrentCaller(remoteContact);
MainActivity.this.setMainUIEles();
}
else
{
Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.putExtra("isCallIncomming", true);
i.putExtra("currentCaller", remoteContact);
i.putExtra("isRegistered", true);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
}); //incoming call listener
However when the call comes, it rings but the app wont open, but if i open the app from the launcher whilst the call is still ringing then it will open and know the call is there.
Is the problem because I'm trying to start the Activity which defined the listener?
I've tried all sorts of flags and combinations (SINGLE_TOP etc) can i can't get it to work.
Any help would be appreciated!
DJOodlen
Well this was a silly mistake on my part.
After putting in some toasts so I could see where in the code each bit was going I realised that getIsOpen() never returned false. That's because it wasn't being called on the onPause() method as wells as the onDestroy() method...
Ooops!
I have an app which I want to open, use, and then at the push of a button close. My question is do I need to keep singleton data of the application status in order to make this happen? I mean if I go with the solution of doing finish on resume() that means that I should need to keep a global data that each activity looks at to close out? This is a fine, albeit awkward way to close an app, but I'll go with it unless I hear another way soon.
Thanks.
PS please do not respond with android will decide when and what to do with your app. I'm sorry but I know my user does want to see this app again after they click Finish! And in the end that's what matters and they are not at all interested in what android needs to do with the app nor should they be.
Maybe you can use System.exit(0) if you want to kill your app.
As came up from comments, you need to do it from the main activity. My way (though there might be a cleaner way) is to add a static handler in the main activity:
static Handler handler = new Handler() {
#Override
public void handleMessage(Message msg)
{
System.exit(2);
}
}
and a static method:
static public Handler getExitHandler()
{
return handler;
}
and in each class I obtain this handler and send it a message when I want to exit:
MyMainActivity.getExitHandler().sendEmptyMessage(0);
again, not so clean, but the same about System.exit(2);
Well, there is a reason why everyone says that, and is the same as "you don't close a web page". I don't know what your users might expect, but this is the way Android/iOS works.
I've used, for something like what you want to do, the flag ACTIVITY_CLEAR_TOP (you set the flag on the intent to open the activity which contains the close button), so in this way the activity stack is deleted, only the current activity remaning: so when you do finish(); the app "closes".
Intent intent = new Intent(this, Some.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
You could pop up a dialogue that informs the user: "the app will close in x seconds" and start a timer that calls finish() on the activity when it ends.