0

I'm so lost with all that workflow of notifications and services in Android. My sceneario is this:

I have an Android application that communicate to a MySQL database through a web-service using JSON-RPC. The data retrieved from the service will be displayed in the application.

The data will get updated over time, so the application needs to listen for changes of this and, if a change occur, show a notification and update the data displayed in the app.

To listen for changes I will need to run an "infinite"(until the app is destroyed or maybe until the app destroys it) thread that from time to time will call a method on th web-service which will return the changes since the last check.

UPDATE: Ok, I have been trying using Service and IntentService, but non of them fits my needs: a Service execute in the Main Thread, so If I perform an infinite loop there my app will freeze, IntentService has it's own worker thread but there is no comunication with the App, and I need it, or at least I need a way to know if the app is in foreground (in this case the notification will not popup but the data will be passed and updated) or in background (int this case the notification will pop up and on click it will direct the user to the app with the updated data)

lordscales91
  • 423
  • 1
  • 8
  • 22
  • Use `AlarmManager` to trigger a broadcast periodically and a `BroadcastReceiver` to receive the broadcast and then start an `IntentService` to perform the connection to the server. Keep a local copy of the data (`SQLiteDatabase` perhaps) and update any `Activity` in `onResume()`. – Squonk Jul 01 '14 at 11:51
  • Am I right that the database service in somewhere on the web, while your app is of course on a phone/tablet? This would mean that your service ___is not___ an Android service, and no broadcasts from that service are possible. – 18446744073709551615 Jul 01 '14 at 12:17

2 Answers2

0

#1 You can fire a broadcast message from your Service and define a Broadcast receiver in your Activity to receive this broadcast.

SEND BROADCAST-from Service

Intent i = new Intent("ALERT_CHANGE");
i.putExtra("DATA","News");
sendBroadcast(i);

RECEIVE BROADCAST-in Activity

registerReceiver(uiUpdated, new IntentFilter("ALERT_CHANGE"));


private BroadcastReceiver uiUpdated= new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) 
{
String DATA = i.getStringExtra("Data");
txt.settext(DATA);
}
};
Parth Kapoor
  • 1,494
  • 12
  • 23
  • And may I show a notification from the Service and launch an Intent to the activity instead? – lordscales91 Jul 01 '14 at 11:27
  • It depends on several factors, but may be updated very often. Are you asking that because it may end with a bunch of notifications at the same time? Don't worry I aready read on Android developers that you can update a previous notification if necessary. However it's not explained how to show one from a Service. – lordscales91 Jul 01 '14 at 11:35
  • On receiving an update, 1. your app might be in use or 2. can be killed/background. How do wish to handle these two cases? This was the reason behind the question. – Parth Kapoor Jul 01 '14 at 11:38
  • @Eu.Dr. : **"Another way could be you can have a static reference of your textView in your Activity."** - Don't EVER do this. The lifecycle of an `Activity` means it may not exist and therefore the `TextView` won't exist in any useful way. NEVER create `public static` fields or methods in an `Activity` and expect them to work in any predictable or stable way. Please remove your second suggestion. – Squonk Jul 01 '14 at 11:40
  • @Eu.Dr. if the application is in use the notification is not needed, instead just pass the data to the app, if it's on the background it should be passed to front. And obviously pass the data to it. – lordscales91 Jul 01 '14 at 11:46
  • @Squonk : Completely True, I have removed it.But my question is, having a static variable in a activity, does this mean all data members of the Activity ie, bitmaps, UI components-Buttons etc, all are retained in memory just because of one static variable? If yes, then how about I create a separate class Communication.java and have only one variable in it, public static int DATA, and use this in my activity and service like, Communication.data. Is this way prone to ambiguity as well? Seeking a kind explanation:) – Parth Kapoor Jul 01 '14 at 12:46
  • @Eu.Dr. : My point is simply that using `public static` variables or methods in an `Activity` is a bad design approach. In theory a `public static final` field *might* be OK but any `public static` variable (not `final`) has the possibility of unpredictable behaviour depending on how the `Activity` might use it or in what state the `Activity` is in WRT its lifecycle. Also references to anything `static` held by other app components will prevent garbage collection and cause memory leaks. – Squonk Jul 01 '14 at 15:19
  • @Eu.Dr. : A separate class with a `static` variable can be used by an `Activity` however as the reference will be released when the `Activity` is destroyed. – Squonk Jul 01 '14 at 15:20
  • @Squonk : Thanks for the explanation, though I will have to read more stuff on this to get to its root. :) – Parth Kapoor Jul 02 '14 at 06:07
  • @Squonk : http://developer.android.com/guide/faq/framework.html- #3 : This tends to suggests there is nothing wrong in using public static. – Parth Kapoor Jul 02 '14 at 07:32
  • @Eu.Dr. : Sorry but I strongly disagree that documentation (or at least the wording which is highly misleading). My point is that depending on how it is implemented, any `public` field or method in an `Activity` can easily cause unpredictable behaviour. I've seen many questions here on SO where apps either crashed or didn't behave as expected due to an `Activity` exposing a `public` or `public static` field or variable. My point is an `Activity` should be self-contained due to its life-cycle. I'm not saying it *can't* be done, I'm saying it's bad design approach and there are better solutions. – Squonk Jul 02 '14 at 08:23
  • @Eu.Dr. I have updated the question with some more info, I hope you can help me now. – lordscales91 Jul 02 '14 at 08:27
  • @lordscales91 You can use the #1 in my answer. It will do the needful for you. If your Activity(That receives the broadcast) is not in foreground, it will not be updated. However you can still update ur MySQL database. – Parth Kapoor Jul 02 '14 at 09:41
  • @Squonk : I will say it is a bad approach only if not managed properly. Otherwise if used in safe way, it can do heavy data passing b/w android components. However, I will still be watchful. I also request an example/scenario from you where this approach is prone to inconsistency. – Parth Kapoor Jul 02 '14 at 09:44
  • @Eu.Dr. : **"I will say it is a bad approach only if not managed properly."** : And that's my point. Many new Android devs wouldn't know how to manage it properly and more experienced Android devs know there are much better ways of doing things depending on what needs to be done. In your #2 answer you suggested `public static TextView txt` in an `Activity` but there's no guarantee it will actually exist. What exactly will the `Service` do if that `TextView` doesn't exist? – Squonk Jul 02 '14 at 10:59
  • @Squonk: if(Activity.txt == null) => Activity is killed, so no need to update the textView. – Parth Kapoor Jul 02 '14 at 11:09
  • @Squonk : See frankly speaking, I too have a doubt, a gut feel that this is not a best way. But I really want to understand a scenario where using a public static may lead to some abnormal behavior. It will be really helpful if you can share one. :) – Parth Kapoor Jul 02 '14 at 11:11
  • @Eu.Dr. : Create an `Activity` with a `TextView tv`. Then, in `onCreate(...)` after `setContentView(...)` call `tv = (TextView) findViewById(...)`. OK so far. Add a `public static` method to that `Activity` which uses `tv` - what exactly is going to happen if that method is called from another app component if the `Activity` has never been created? An `Activity` is basically a UI framework which needs to be created, started, resumed to be useful direct access from outside of it makes little sense and can be prone to problems if not designed properly. This is why my approach is never to do it. – Squonk Jul 02 '14 at 20:51
  • @Squonk: Thanks again for the explanation and I agree with it. But what if a static member of activity A is used ONLY in activity B. Further, Activity B can only be reached from Activity A. I guess in this case it is safe to use a static member. Moreover, I really need to dive deeper into this, to be sure. Anyways Mr Squonk, thanks for your time and valuable inputs. Cheers :) – Parth Kapoor Jul 03 '14 at 06:02
0

Ok, after a lot of testing and thanks to the info given here I finally found a way to handle with the issue, so I will share it here:

On the IntentService I have a public static AtomicBoolean to control the end of the loop and be able to stop the service.

Then to determine if the Activity is in foreground or not I use the method suggested here https://stackoverflow.com/a/5504711/3107765

With the difference that I use the static modifier there, so I can check it from the service.

if the activity is in foreground I send a broadcast as it was suggested here by Eu. Dr. otherwise I use a notification that once clicked will let the user to the activity.

Community
  • 1
  • 1
lordscales91
  • 423
  • 1
  • 8
  • 22