Android Application, Activities, and UI Thread - android

I'm working on an Android project that consists of several different Activities all associated with the same Application. We have some common tasks coded in the Application so that we don't have to duplicate them, and one of these tasks is regularly verifying a TCP connection to a dedicated server -- a heartbeat, I suppose.
If it's detected that the connection to the server is lost, I need to notify the user and I'd like to do this in a way that doesn't require me to check all the possible activities to see which is currently "on top".
Is there a way to call runOnUiThread() on whatever activity may be on the UI thread without knowing it explicitly??
Thanks,
R.

Regularly verifying a TCP connection
Sounds like this should be implemented using a service..
If the alert is very simple, and has minimal importance, I would suggest using a Toast.
If the alert is crucial, but it doesn't require the user's immediate attention, use a Notification.
If the alert demands immediate user attention, you should use a Dialog. You won't be able to start a dialog directly from a service or broadcast receiver because they don't have a window associated with them, but you can use an intent to start an activity on a new task. You can style the activity to be whatever you want. It could even look like a dialog box (or show a dialog box when it's started). Starting the activity in a new task will make sure the user can navigate back to whatever they're doing.

You can notify your Activities by sending Intent and registering BroadcastReceiver in each Activity you want to be notified.
service or application can be your context:
Intent i = new Intent("MY_ACTION_FROM_SERVICE_STRING");
context.sendBroadcast(i);
activity:
public class MyActivity extends Activity {
private ActivityBroadcastReceiver recvr;
public void onReceiveCommand() {
//do something
}
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
recvr = new ActivityBroadcastReceiver(this);
this.registerReceiver(recvr,
new IntentFilter("MY_ACTION_FROM_SERVICE_STRING"));
}
}
receiver:
public class ActivityBroadcastReceiver extends BroadcastReceiver {
private MyActivity target;
public ActivityBroadcastReceiver(MyActivity target) {
this.target = target;
}
#Override
public void onReceive(Context context, Intent intent) {
target.onReceiveCommand();
}
}

One of the simple way (which I've adopted for my project too) is to create a base Activity class (preferably Abstracted) and then make your normal activity classes to extend it. By this, you may put a general piece of code in the abstracted class which may help you to detect currently visible activity.
Moreover, you may set a BroadcastReceiver in your base activity class which will always be ready to listen broadcasts regardless of setting it individually in your child activities and then set it to listen for broadcasts sent from your tcp thinggy.

Do not do any trickery. Implement Observer pattern, so any activity would register its listener in onResume() and unregister in onPause() and whatever will happend your Application object code needs just to tell about that to registered listeners, no matter what Activity they are in

Related

Show Dialog everywhere if I don't know the current context?

I have to show a Dialog in the foreground activity as a result of a background http operation.
When the dialog has to come up it could be everywhere, the context can be changed, for example I have started a new Activity.
If I use the applicationContext to show the dialog I get:
05-04 17:32:32.560: E/AndroidRuntime(3663):
android.view.WindowManager$BadTokenException: Unable to add window --
token null is not for an application
so... How can I achieve my aim?
any suggestions?
Whenever/wherever you create the dialog you would be in an activity right? Why not just use that activity as the context?
In my own code, I create a helper class that creates a dialog for me. Into that helper class, I pass in the current activity, title and message. It constructs the dialog and returns an AlertDialog object which I can manage.
You could try that, but you would still need to know the context/activity where you want your dialog to display.
You need a way to notify your foreground Activity that the operation is complete, you can do this by registering a listener, since you have not posted any code, I will make assumptions.
There are two ways you can notify a foreground Activity that I know of, the first way is using broadcast intents, there is a question here relating to them Android BroadcastReceiver within Activity. You can fire of a broadcast intent from your background operation and register your activity as a receiver.
See here http://developer.android.com/reference/android/content/Context.html#sendOrderedBroadcast%28android.content.Intent,%20java.lang.String,%20android.content.BroadcastReceiver,%20android.os.Handler,%20int,%20java.lang.String,%20android.os.Bundle%29 and here
http://developer.android.com/reference/android/content/BroadcastReceiver.html
The second way is to register a listener with your class that performs the background operation, for instance (pseudo code)
#Override
protected void onResume() {
BackgroundOperator.registerListener(this);
}
#Override
protected void onPause() {
BackgroundOperator.unregisterListener(this);
}
public void onOperationComplete(...) {
// TODO: Show your dialog here
}
Where your listener could be something like this (which your Activity could implement):
interface BackgroundOperatorListener {
void onOperationComplete(...);
}
The idea here is your foreground activity will be the current registered listener, so it will be the recipient of the onOperationComplete(...) callback, and you can then show your dialog, the ... could be any number of arguments to pass to your activity when the operation is complete.
I think what you need is get the top activity of the task(current showing activity), then use it to show dialog.
so see this thread :How to get any identifier of the topmost activity?
Edit: Showing a dialog from background is not a good user experience, you can send notification or just make a long time toast.
In my opinion the best way is creating one new activity and using it like a dialog.
The steps:
Create new activity , for example (to being original) MainActivy.
Fill the activity_main.xml asociated as you need.
In the your AndroidManifest.xml re-write this lines.
<activity
android:theme="#style/AppTheme.Dialog"
android:name="com.myapp.original.example"
android:label="#string/timy_titlle" >
Call your MainActivity, now converted to Dialog, from others activies using the Intent class.
If you are using Action Bar Compact you can follow this others steps.

Using AsyncTask to call another application

I want to use AsyncTask to call another application. I have a main app that does its own thing but when I launch it, it does an AsyncTask to call a "messages" application which checks to see if there are any unread messages and then displays a notification in the status bar.
However, when I called execute(), the messages application jumps to the front and I have to press the back button to get to my main application.
Code is as follows (my main application)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MessageUpdate update = new MessageUpdate(this);
System.out.println("Calling Update");
update.execute(null);
....
My AsyncTask:
public class MessageUpdate extends AsyncTask{
Context ctx;
public MessageUpdate(Context ctx){
this.ctx = ctx;
}
#Override
protected Object doInBackground(Object... params) {
Intent notificationIntent = new Intent();
notificationIntent.setClassName("com.test.messages", "com.test.messages.MessageCheck");
ctx.startActivity(notificationIntent);
return null;
}
}
Can anyone tell my why the MessagesCheck jumps to the front and how to stop it? Or if what I'm doing is even feasible?
As others have pointed out, a service is the way to go. However, if you use bindService() the service will only last as long as it's bound.
Just to clarify some of the issues:
Using startActivity to communicate with a background task is not what you want, as an Activity is a user interface component, which will come to the front when activated.
The suggestion is that you add a service to your "messages" application, not the main application.
You can then communicate with the "messages" application from the main application by binding to the service. If you do this (using bindService), the service will not run indefinitely.
The details of how to do this are here.
You could do all this without an AsyncTask, however it may help to avoid blocking the UI thread if the service takes significant time to do its job. Alternatively, your service could use a background thread of its own to check for messages and post the notification.
Have you considered make com.test.messages.MessageCheck a Service not an Activity, then calling startService(...)
You are starting an Activity in your ASyncTask, so your current Activity is brought to the back.
In order to prevent that, you'll have to use a different way to check if there is a new message. You could either do that verification in your ASyncTask and display the notification from it, or use a Service.

android log out help

I have an application that has a user log in and log out. On a log in it tells my DataBase that the user is online. Problem I am having is that when the user doesnt use the app for a while and the processor kills my app is there a method or something where i can run my last piece of code to log them out? I looked at the android life cycle and i cannot use destroy because that only ties with that activity. Thanks!
I found a solution for this - not perfect but worked for me.
1.) Create a service to run in the background which is started when the first activity is created.
2.) Each activity binds to this service so it can "check-in" (i.e. it is alive and onPause) hasn't been called)
3.) In each activity register a broadcast receiver that listens for an intent fired by the service on a regular basis.
4.) On receiving the chech-in intent, it calls a service method which basically lets the service now there is an activity that is still alive (I tent to only respond to the intent if it had windowFocus
5.) If there is a check-in the service sleeps and then re-requests a checkin, if there was no check-in it sleeps for a shorter period of time, before re-requesting a check-in, if none respond then the app logs out. (The reason for the second re-quest when no check-ins were found was to account for issues surrounding check-in during an activity transition, i.e. starting a new activity and closing the current one).
As I said this isn't the nicest way to do it but seems to work for my needs so far.
why can't you use onDestroy method of your activity? if you have a lot of activities, you can create your own base activity class and derive all your activities from this base class.
public abstract class BaseActivity extends Activity {
....
#Override
public void onDestroy() {
super.onDestroy();
// do your stuff here
}
}
and thenm create all your activities like this:
public class YourActivity extends BaseActivity {
...
}
In AndroidManifest you've got name. Now create
public class MyName extends Application {
}
this is your Application class which is automatically created once user open your app. Now simply override onTerminate() method inside MyName class.
#Override
public void onTerminate() {
user.logOut();
super.onTerminate();
}
You can use your MyName class in every Activity simply with this code:
MyName myName= (MyName) this.getApplication();
myName.logUser(user);

help with binding a local service

I Need some help here, I have a service which I can start or stop whenever I want and using the onStart() command to pass some extras using putExtras() from my activity
But I need some serious basic instructions on how to interact with the already created service.
Please don't refer me to another webpage which already have some implementations, just give me the needed code to interact from my UI activity to the service:
something like this:
public class myActivity extends Activity {
Object ReceivedObjectFromService;
onCreate()
{
some stuff here
myMethod()
}
public class myMethod()
{
//do some stuff with the ReceivedObjectFromService
//Don't know how to call this method from the service btw
}
please some help, I don't understand the tutorials on how to interact service to activity or viceversa
Interaction with already created service is no different to starting a brand new service. You just simply call startService() so your client code is no different.
Now, the part which is different is the service itself. In your service, onCreate() must start a background thread or a timer to carry on doing a work. onStart() will receive all startService cases and must in fact add the data it receives in the Intent to an internal list or queue and then in the timer's callback start processing from this queue.
Now you can pass any messages or data you want (even closing the service) using startService and passing data in the Intent that your service understands.
Hope this helps.

How can i determine when my application is running?

I have an application that uses a Service to fetch data in the background both while the application is running and when it's not.
When it is not running i would like to show a notification when there is new data, but not when the app is running.
How do i determine in my service whether the app is running or not?
I think you want to check whether a certain activity is shown. If that is true, I would use the Activity.onCreate() method to set a flag in the application instance, i.e. extend the class Application with a field "uiRunning" and check this field in your service. onDestroy() should be used to unflag the attribute. Don't forget to use your Application class also in the Manifest.xml
I would agree with the use of onCreate()/onDestroy() for a single Activity application, though an Application with multiple activities would be better off using Application.onCreate()/onTerminate() in order to avoid triggering the uiRunning state when switching activities.
This is dead easy. You use a named Mutex.
Put this in the application you want to check:
bool createdNew;
Mutex mutex = new Mutex(true, #"Global\YourAppNameHere", out createdNew);
if (createdNew)
{
var app = new YourProcess();
app.run();
mutex.Close();
}
Put this in the application that checks to make sure the other app is running:
bool createdNew;
Mutex mutex = new Mutex(true, #"Global\YourAppNameHere", out createdNew);
if (createdNew)
{
Console.WriteLine("App not running");
mutex.Close();
} else {
Console.WriteLine("App is running");
}
Another option is to implement a listener pattern and have your service manage a list of listeners with methods on your service interface for addListener() and removeListener(). Your activity can add itself as a listener after it connects to the service and remove itself onStop() (i.e. when the app is no longer visible to the user or has shutdown completely).
In your service, check the count of listeners. If there are no listeners then you know you should create your notification.
Another way to accomplish is to de-couple your data receiver to a 'service' which will always run in the background. you can have your application bind to the service and will display the data fetched by the service.
The problem with having the application in background is that Android will kill the application once it gets too old. Its always better to have such background running application as service rather then activity.
What i did do was to use a flag in my service, that the root activity sets and clears on onStart/onStop. This works pretty well.
This is how I did it and is working flawlessly with just a few lines of code:
In extended App class:
public static boolean isAppInFront = false;
In you main activity:
#Override
public void onStart() {
super.onStart();
MyApplication.isAppInFront = true;
}
#Override
public void onStop() {
super.onStop();
if (isFinishing())
MyApplication.isAppInFront = false;
}

Categories

Resources