I want to create an empty service that will just run in the background once a certain fragment is open - the service will fill an array in the background but is not used in the current (calling fragment):
Code to create the service:
Intent intent = new Intent();
intent.putExtra(ServiceActions.class.getName(), ServiceActions.GET_LIST_FROM_API);
intent.putExtra("api_code_id", "12345");
managerProvider.getRequestManager().startRetrievalService(intent);
Register & Unregister listener:
manager.registerReceiver(backgroundListReceiver , new IntentFilter(ServiceBroadcasts.GET_LIST_FROM_API_RESULT.name()));
manager.unregisterReceiver(backgroundListReceiver );
Then handle the receiver:
backgroundListReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
boolean result = extras.getBoolean(ServiceBroadcasts.GET_LIST_FROM_API_RESULT.name());
// DO Nothing here as the list is loading in the background
// and stored in the application class
}
};
I do register and unregister it in fragment, I guess I asking is this correct way to do it or is there another better process? The reason for doing it here is that the chance of the user selecting the list is quite high so I'm trying to preload the list prior to them selecting it.
Code to handle loading list in background:
private void getListInBackground() {
RequestResponse response = RestAPI.getListInBackground();
if (response.isSuccessful()) {
mApp.setBackgroundList(JacksonMapper.deserBackgroundList(response.getResponseString()));
}
Intent broadcast = new Intent(ServiceBroadcasts.GET_LIST_FROM_API_RESULT.name());
broadcast.putExtra(ServiceBroadcasts.GET_LIST_FROM_API_RESULT.name(), response.isSuccessful());
mManager.sendBroadcast(broadcast);
}
Related
I have a registered BroadcastReceiver in my main activity. Activity sends a sticky in one of the tabs to trigger the broadcast receiver (TabActivity application).
Everything works fine, but when I restart the app the sticky is sent automatically (not triggered by user) and view is opened.
My question is: how is that possible? Did I misunderstand something? And how can I fix that?
MainActivity:
OnCreate:
registerReceiver(openOutgoingCall, new IntentFilter("OPENOUTGOINGCALL"));
BroadcastReceiver:
private BroadcastReceiver openOutgoingCall = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if(extras.isEmpty() == false) {
HashMap<String,String> callData = (HashMap<String, String>) extras.get("callData");
openOutgoingCall(callData);
}
}
};
Activity inside TabHost
public void openCall(View view) {
Intent i = new Intent("OPENOUTGOINGCALL");
i.putExtra("callData", detailInfo);
sendStickyBroadcast(i);
}
Sticky broadcasts are supposed to stay around (even they are received) so that they can be retrieved afterwards too. Perhaps you should try the simple way of broadcasting using:
sendBroadcast(i);
Read this.
I'm dealing with wearable, and my purpose is the next:
From my watch, I want to press a simple button, which send a simple message to the mobile. But I would like to handle all those behaviors :
when mobile app isn't yet launched, then launch the app and pass the message from wear, which can be handled in the launcher activity
when mobile app is launched but in the background, then just bring it to foreground and handle message from wear, which can be handled in the launcher activity
when mobile app is launched and in foreground, juste handle the message in the launcher activity
So far, I handle to launch the app when it isn't not yet launched, but I can't get the extra message in the launcher activity contained in the intent. Here the code.
the mobile service
public class MobileWearService extends WearableListenerService {
private static final String START_ACTIVITY = "/start_activity";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
String event = messageEvent.getPath();
String msg = new String(messageEvent.getData());
if (event.equals(START_ACTIVITY)) {
Intent intent = new Intent( this, MainActivity.class );
intent.putExtra("Data", msg);
intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity( intent );
}
}
}
However, if I use a broadcast to send the message from service to the main activity, it works only if the app is launched and foreground
public class MobileWearService extends WearableListenerService {
private static final String START_ACTIVITY = "/start_activity";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
String event = messageEvent.getPath();
String msg = new String(messageEvent.getData());
if (event.equals(START_ACTIVITY)) {
broadcastIntent.setAction("com.me.project.wear.to.app");
broadcastIntent.putExtra("Data", msg);
broadcastIntent.putExtras(intent);
sendBroadcast(broadcastIntent);
}
}
}
launcher activity
private IntentFilter mIntentFilter = new IntentFilter("com.me.project.wear.to.app");
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals("com.me.project.wear.to.app")) {
String msg = intent.getStringExtra("Data");
}
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
So I would to combine the fact to get the message from wear (I know how to) but pass this message to get it in the launcher activity regardless of the state of the app.
Just make the static BroadcastReceiver
public class WatchMessageReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null &&
intent.getAction().equals("com.me.project.wear.to.app")) {
String msg = intent.getStringExtra("Data");
Intent launcherIntent = new Intent(context, LauncherActivity.class);
launcherIntent.putExtra("Data",msg);
startActivity(launcherIntent);
}
}
}
in your manifest file
<receiver android:name ="WatchMessageReceiver"
<intent-filter>
<action android:name="com.me.project.wear.to.app"/>
</intent-filter>
</receiver>
In the Sending and Syncing Data training, there is a Handling Data Layer Events:
When you make a call to the Data Layer API, you can receive the status of the call when it completes. You also can listen for data events, resulting from data changes that your application makes anywhere on the Android Wear network.
Listen for Data Layer Events
Because the data layer synchronizes and sends data across the handheld and wearable, it is usually necessary to listen for important events. Examples of such events include creation of data items and receipt of messages.
To listen for data layer events, you have two options:
Create a service that extends WearableListenerService.
Create an activity that implements DataApi.DataListener.
With both these options, you override the data event callback methods for the events you are interested in handling.
Some of the events you can listen for using WearableListenerService are as follows:
onDataChanged(): Whenever a data item object is created, deleted, or changed, the system triggers this callback on all connected nodes.
onMessageReceived(): A message sent from a node triggers this callback on the target node.
onCapabilityChanged(): When a capability that an instance of your app advertises becomes available on the network, that event triggers this callback. If you're looking for a nearby node you can query the isNearby() method of the nodes provided in the callback.
According to the related SO post:
WearableListenerService does not run constantly - it is only started when a new message/node connection/data layer change is sent and stopped when there are no more messages.
Hope this helps.
I'm trying to get push notification working in my Android app, using parse.com's push notification service. They implement a Broadcast receiver, which I am extending in my own class:
public class MyPushBroadcastReceiver extends ParsePushBroadcastReceiver
{
#Override
protected void onPushReceive(Context context, Intent intent)
{
JSONObject data = getDataFromIntent(intent);
[...]
super.onPushReceive(context, intent);
}
#Override
protected void onPushOpen(Context context, Intent intent)
{
ParseAnalytics.trackAppOpenedInBackground(intent);
Intent i = new Intent(context, MyActivity.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
I'm over-riding two methods:
onPushReceive - this is called when a notification arrives
onPushOpen - this is called when the user clicks on a notification in the notification area
There are three things I need to do:
When a notification arrives, I need to save it
When the user clicks on a notification, I need to open the app to an activity that displays the notifications I've saved
If a notification arrives while I have the app open to the display notifications activity, I need to update the UI to include the new activity.
The first part was easy. I'm just writing some JSON to a file.
The second I've had no trouble with. I create an intent, and that opens my activity. It reads the JSON from the file, and Bob's your uncle.
I've not been able to find a clean way of handling the third part.
I think where I'm stuck is that I haven't a clear understanding of the lifecycle of Activities or BroadcastServices. I'm not creating either, in my app, they're declared in the manifest, and constructed whenever.
Does the Android framework create one of each, as it processes the manifest? Is it possible for an activity to find the instance of the BroadcastReceiver? If I could, it'd be easy enough for me to wire up a callback between them.
Or do I need to define my own BroadcastService, that the ParsePushBroadcastReceiver would use to publish events, and that the activity would consume? The examples I've seen on doing that seem excessively complicated for what should be a fairly simple thing.
Help would be appreciated.
The suggestion on using a static variable got me thinking, and I think I've found a workable solution.
There may be multiple instances of an Activity, but only one can be active at any time.
I spent some time playing around with setting various flags on the Intent I'd pass to startActivity(), and didn't like any of the behaviors I'd see. (Some combinations would crash, some would create multiple entries in the stack so that the back button returned you to an older instance of the activity, all of them created visual effects as the old activity was replaced by the new.)
So, why not create a static field that points to the currently active Activity?
public class MyActivity extends Activity implements ReceiveNotifications
{
public static ReceiveNotifications notificationReceiver = null;
#Override
protected void onResume()
{
super.onResume();
NotificationsActivity.notificationReceiver = this;
updateMessages();
}
#Override
protected void onPause()
{
NotificationsActivity.notificationReceiver = null;
super.onPause();
}
#Override
public void notificationReceived()
{
updateMessages();
}
private void updateMessages()
{
[...]
}
}
Whenever an instance of MyActivity is active, the static variable notificationReceiver will point to it. Of course, I'm using an interface to control how much of MyActivity is visible through that variable:
public interface ReceiveNotifications
{
void notificationReceived();
}
Then, when we receive a notification, if notificationReceiver is not null, we call notificationReceived():
public class MyPushBroadcastReceiver extends ParsePushBroadcastReceiver
{
#Override
protected void onPushReceive(Context context, Intent intent)
{
JSONObject data = getDataFromIntent(intent);
[...]
super.onPushReceive(context, intent);
if (MyActivity.notificationReceiver != null)
MyActivity.notificationReceiver.notificationReceived();
}
#Override
protected void onPushOpen(Context context, Intent intent)
{
ParseAnalytics.trackAppOpenedInBackground(intent);
Intent i = new Intent(context, MyActivity.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
You can use the onNewIntent() (docs) method of the Activity to send the new info about something happened and then display some prompt.
I have some problems working with Android Services. I already have a Service which downloads a file from a server. (The Service checks cyclic for new data) Aftwerwards it parses the file and adds values to an ArrayList wich will be saved to SharedPreferences.
In my Activity there are two methods. One will display the values from the ArrayList/SharedPreferences in UI and the second method sets a Notification if needed.
But how do I now when my Service completed its task so the two methods can be started?
Register a BroadcastReceiver in your Activity something like:
myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do my stuff
}
};
registerReceiver(myReceiver , new IntentFilter("com.myapp.DOWNLOADCOMPLETE"));
Then in your service send the broadcast:
Intent i = new Intent("com.myapp.DOWNLOADCOMPLETE");
sendBroadcast(i);
You can also putExtras on your intent if you need to pass some values:
Documentation BroadcastReceiver
I have a registered BroadcastReceiver in my main activity. Activity sends a sticky in one of the tabs to trigger the broadcast receiver (TabActivity application).
Everything works fine, but when I restart the app the sticky is sent automatically (not triggered by user) and view is opened.
My question is: how is that possible? Did I misunderstand something? And how can I fix that?
MainActivity:
OnCreate:
registerReceiver(openOutgoingCall, new IntentFilter("OPENOUTGOINGCALL"));
BroadcastReceiver:
private BroadcastReceiver openOutgoingCall = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if(extras.isEmpty() == false) {
HashMap<String,String> callData = (HashMap<String, String>) extras.get("callData");
openOutgoingCall(callData);
}
}
};
Activity inside TabHost
public void openCall(View view) {
Intent i = new Intent("OPENOUTGOINGCALL");
i.putExtra("callData", detailInfo);
sendStickyBroadcast(i);
}
Sticky broadcasts are supposed to stay around (even they are received) so that they can be retrieved afterwards too. Perhaps you should try the simple way of broadcasting using:
sendBroadcast(i);
Read this.