I have a BroadcastReceiver, and on its OnReceive I am supposed to call a method which is defined in the MainActivity. wherever I searched I found that I will have to write the following code.
Bundle bundle = intent.Extras;
Intent callingIntent = new Intent(context, typeof(MainActivity));
callingIntent.PutExtra("isSynched", true);
callingIntent.AddFlags(ActivityFlags.NewTask);
callingIntent.AddFlags(ActivityFlags.SingleTop);
context.StartActivity(callingIntent);
Now this calls my method, but the app keeps opening up. I don't want that to happen. I want the method to be called when the app is in background and want the app to be in background. What should I do? I am using xamarin to write the code.
I have created a service that gets the data but after I receive data I have to call a method in MainActivity to update the calendar. I am currently doing it in OnReceive like this, public override void
OnReceive(Context context, Android.Content.Intent intent)
{
if (context.GetType().Equals(typeof(MainActivity)))
{
((MainActivity)context).SyncCalendar();
}
}
this context is coming as restrictedaccess. So not able to call SyncCalendar Method
Depending on whether you need or not execute that code all the time your app lives, I'd recommend:
AsyncThread: This is somelike an improved version of a Thread as it already implements some of the mechanisms you would need to set manually with a Thread, but it's not recommended to execute all your app life, just for ending processes. You may find more info there
Service: Otherwise, if your function is intended to run all your app's life long, Service is the correct choice. It's a bit harder to understand than the AsyncThread, as it's a class that it's executed until you stop it paralelly to your main UI, but it's not a thread. You may find this useful and also this.
Related
Is it possible to send an intent from a service to an Application class? Not Activity?
I wouldn't know what activity would be running at a particular time, so I am adding a boolean flag in the activity class that detects the activity and sends the appropriate data based on the broadcast received.
If your Service is active, then your Application class is active as well.
Otherwise you wouldn't be able to use getApplicationContext().
Although I'm skeptic about a service that runs forever there is a very clean way to make the Service communicate with a certain Activity, should the last one be currently active.
Such clean way is called LocalBroadcastManager.
The Activity meant to receive the data should register a BroadcastReceiver in onResume() and unregister it in onPause().
You instantiate your BroadcastReceiver in your Activity's onCreate()
this.localBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Do what you have to do here if you receive data from the Service.
}
}
You create a Filter so your Activity only listens to a certain type of signals.
private IntentFilter notifIntentFilter new IntentFilter("com.you.yourapp.MY_SIGNAL");
in onResume()
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, notifIntentFilter);
in onPause()
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
Now whenever you want to send data to your Activity, your Service can call:
final Intent intent = new Intent();
intent.setAction("com.you.yourapp.MY_SIGNAL");
// put your data in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
If your Activity is awake, it will respond to the signal. Otherwise, if it's in the background, or it is not instantiated it won't.
You can apply this pattern to as many Activities as you wish.
Still, I have never used this inside the Application class. But you can try to register your receiver there. It might work, since if the Application class is destroyed, the BroadcastReceiver is destroyed too and thus probably unregistered as well.
The point is, if your Application gets destroyed, your Service will be killed as well. Unless you launched it in another process. But then it will have it's own instance of Application; and this is a complex thing you probably do not want to get into details now...
Important: since the Application class is not tied to any UI component, you can do whatever you need directly inside your service. If you need to manipulate the UI, then the pattern described above will work for you.
Please read about new Android's background limitations.
Edit:
Oh yeah right, if you need your Service to call a function declared in your Application class, you can just do
((MyApplication) getApplication()).myFunctionToHandleData(Intent intent);
I didn't really understand your question though, but either of the methods described above should work for you.
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)
#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);
}
};
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.
I'm using a running service to detect whether network is available or not. When it is not available, it calls an activity to start that displays a blank screen with "no network available" on it. When the network is back, it sends a broadcast to finish this activity.
The only problem is that this activity may start at any time (as a popup), even when using other apps. I want it to start (or be visible) only if the network is out and my app is in the foreground. Any help?
One option would be to have your foreground activity register for the broadcast, and then display the relevant notification from within the activity.
Alternatively you could start your service when your foreground activity starts/resumes (i.e, onResume), and stop it when your activity leaves the foreground.
You can use START_STICKY in your service to ensure it stays around until you stop it, like so:
#Override
public int onStartCommand(Intent intent, int flags, int startId){
//On start work here
return START_STICKY;
}
and then stop the service using stopService when your activity leaves the foreground (i.e onPause).
If you need the former behaviour across multiple activities you can register broadcast receivers programmatically:
BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(MY_ACTION.equals(intent.getAction()))
{
//show appropriate dialog
}
}
};
IntentFilter myIntentFilter = new IntentFilter();
myIntentFilter.addAction(MY_ACTION);
registerReceiver(myBroadcastReceiver,myIntentFilter);
You can unregister like so:
unregisterReceiver(myBroadcastReceiver);
You could extend Activity and make your own custom subclass that reuses similar code to register and unregister whilst entering/leaving the foreground. Or you can extract this into utility methods/classes and call from the appropriate places.
I think you need Shared Preference to do this. store one Boolean value on finish you activity (you can use onpause() or onStop()) and for showing popup check the value and do what you want
for understnding to use sharePreference see this and developer.android.com
Try the following:
Intent intent = new Intent(this, YourActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
This worked in the context of my own app already running, I'm not sure if it will start your app if it is not already running in the background
EDIT: Not sure if I understand your question entirely. If you only want this activity to come to the foreground while your app is in the foreground, get rid of the addFlags line, also you can do some boolean stuff to check if your app is in the foreground like so, this way your code won't even run if the app isn't in the foreground.
EDIT: There are a few ways to check if your app is in the foreground, the link I posted above has one such solution, another one is to create a static boolean isForeground variable: in the onResume() methods of your app set isForeground = true and in onPuase() set isForeground = false. This isn't the best practice, using ActivityManager is better, but for purposes of testing this should be ok.
Then have something like the following:
if(isForeground){
//Start your activity
}
This should be quick to write, if this is the behavior you want, I would recommend replacing the isForeground static variable with the test for foreground provided by ActivityManager in the link I posted.
How can I tell from my Application whether it was started/resumed from my BroadcastReceiver or not?
I intercept outgoing calls (android.intent.action.NEW_OUTGOING_CALL). If getString(Intent.EXTRA_PHONE_NUMBER) is one of a set of numbers, I abort that call (setResultData(null)) and instead startActivity my app, putExtraing the particular number. If (and only if) coming from the BroadcastReceiver, I want to be able to put up an alert that's basically "use this app with this number/return to call". However, sometimes when I return to the app from elsewhere, the number still seems to be in the extras of the intent, even though I haven't come from the BroadcastReceiver. I tried checking for the FLAG_ACTIVITY_NEW_TASK flag, but it shows up sometimes when not coming from the BroadcastReceiver.
As you said: you can pass any parameters to your activity, indicating that it was called from your BroadcastReceiver. However, when resuming to your activity some code might be executed again - potentially causing unwanted outcomes. When I had once a similar issue I stored/overwrote some information in the intent, e.g.
myActivity.getIntent().putExtra("phoneNumber", "nil");
What worked for me was, that I overwrote the extra in the intent after it has been processed while finishing an ActionMode (let's say with "nil"). So later I was able to evaluate that information in onResume(), e.g.:
#Override
public void onResume() {
super.onResume();
String phoneNumber = getIntent().getExtras().getString("phoneNumber")
if ("nil".equals(PhoneNumber)) {
...
}
}
Just did a small test and it works pretty well.
Hope this helps ... Cheers!
I have a Service that can be stopped in multiple ways. Whenever I call stopService(Intent), I pass an intent with some extras. How do you retrieve those extras?
Thanks.
You need to override onStartCommand() in your Service this is how you get a reference to the incoming intent from startService.
In this case you would have a special action in your intent to tell the service to stop itself. You add extras to this intend which can be read in the onStartCommand() method.
Sample Code
public class MyService extends Service {
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
final String yourExtra = intent.getStringExtra(YOUR_EXTRA_ID);
// now you can e.g. call the stopSelf() method but have the extra information
}
}
Explanation
Every time you call context.startService(Intent) onStartCommand() will be called. If the service is already running a new service isn't created but onStartCommand is still called. This is how you can get a new intent with extras to a running service.
I found that the extras are not passed with the intent when stopService is called. As a workaround, simply call startService(Intent) and stopService(Intent) right after one another.
Example code from Activity:
Intent j = new Intent(SocketToYa.this, AccelerometerDataSocket.class);
j.putExtra("com.christophergrabowski.sockettoya.DestroyService", true);
startService(j);
stopService(j);
In Service.onStartCommand,
intent.hasExtra("com.christophergrabowski.sockettoya.DestroyService")
will evaluate to true, and you will destroy your service the way intended by the API (i.e., by calling stopService, which will in turn call OnDestroy after onStartCommand is called).
My suggetion is that use static member in class that extends Activity for passing information to service & it in service as normal static member access in outside class
Please don't do this unless you have no other option. You should try to use the mechanisms built into the framework for passing data, and not use public static fields unless there is no other choice. Read the Service documentation for examples.
Are you able to use an Intent with a "shutdown" action with Context.startService()?
That is, send an Intent with a shutdown action and extras to Service.onStartCommand(), decide how to shutdown based on the extras, then use Service.stopSelf() to stop the service.
I agree this isn't a great solution, since it potentially starts the service in order to shut it down. I would still like to hear of the "correct" way (if one exists) of doing this with Context.stopService().
You can not write
getIntent()
method in a class extending Service. So I think using getExtra() won't work.
My suggetion is that use static member in class that extends Activity for passing information to service & it in service as normal static member access in outside class i.e.
Classname.yourobject
.
see this link for other option
http://developer.android.com/resources/faq/framework.html#3