I try to get the calling Intent from within a Service.
The method Service.getIntent() is deprecated and the method parseUri(String uri, int flags) is suggested as its substitute.
I do not know what to pass as the uri-string.
Where to get the URI of the Intent?
(I wonder why the method toUri() is suggested in the API to get the URI of an Intent you can not access yet...)
I try to get the calling Intent from within a Service
It is passed into onStartCommand() and/or onBind(). In some cases, it is passed along to you later (e.g., IntentService gives you the Intent in onHandleIntent(), based on its built-in implementation of onStartCommand()).
If you need the Intent outside of those methods, it is your job to hold onto it (e.g., as part of some "job" object that represents some work that the service is executing on a background thread).
Related
I am using IntentService in my application. I want to know that, Is this Necessary to putExtras() before calling to startService(intentService) Method. Or can i call the startService(intentService) without providing data to intent. I want to know the reason behind this concept.
Thanks in advance.
Is this Necessary to putExtras() before calling to startService(intentService)??
Answer is No.
putExtras() is used to pass the data between Activitys and Services.if you want send some data to Service then Use putExtras()
The same intent here in IntenetService will received onStartCommand(Intent intent, int flags, int startId) get the data from the intent using getExtras() method
No. It is not needed. If you want to pass some values to the activity which is started by Intent then only you need to use putExtras(). Otherwise use can start activity using startActivity(intent) without implementing putExtras()
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.
The projcet involves modifying Android to block/deny launching of particular apps. So if user tries to launch any of the pre-listed apps by any means, that app shouldn't get launched.
I'll be modifying Android source code. What are the different ways to do it? Suggestions are welcome.
I think one of the possible ways to do that is to modify Process.java in frameworks/base/core/java/android/os.
This class has start function which receives uid as an input paramenter. I think from this parameter we can get to know that for which app new process is being created. Is this the correct way to do it?
Also, as the apps are launched using intents, is it possible (by modifying any class) to remove particular intents?
In general, when an intent can be handled by an application(its activity, service), and the user prefers that application to handle it. The ActivityManagerService(Ams) in Android framework will first see whether the corresponding application of the target activity/service is still alive. If it hasn't been started yet or killed, the Ams will start that application by calling startProcessLocked method.
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated) {
//you can get the uid from ApplicationInfo.uid
...
startProcessLocked(app, hostingType, hostingNameStr);
...
}
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
//prepare its uid, gid, gids for starting that process
...
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, null, null);
...
}
So in that method, it start a new process. The Process.start is what you have mentioned in your question, and it finally calls Zygote to fork a new process.
I think intercepting the application startup process in Ams is a better way. You can get more information about this application and it is also the upstream of your Process.start method.
UPDATE:
Just noticed that you were thinking about restricting intent. An intent can be handled by multiple applications, so we cannot restrict applications from sending a particular intent. But we can modify the resolving process. Resolving means the Android framework need to determine which activity/service can handle this intent. If there are multiple choices and the user haven't set any preference, then the following dialog will appear:
So it is possible to modify the resolving process to let the Android framework discard the fact that your specific application is able to handle that intent. I think this is also a way to do your work but it is much more compilicated because Android resolves intent differently for activity, service and receiver. For activity, Ams will call resolveIntent in PackageManagerService to get which activity to start. For service, it is the resolveService method in PackageManagerService get called. So you need to handle them differently. But since they will all get a list of ResolveInfo in their implementation, you can just filter out your application easily. For example, in resolveIntent in PackageManagerService:
#Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");
List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
//filter out here!!!!
return chooseBestActivity(intent, resolvedType, flags, query, userId);
}
You can easily get the ApplicationInfo from the ResolveInfo if you take a look at ResolveInfo.java.
For receiver, it is even more complicated because receivers registered in AndroidManifest.xml and by registerReceiver(...) are different. If the intent in broadcastIntent hasn't set the flag FLAG_RECEIVER_REGISTERED_ONLY(common case), then the resolving result would be a list of receivers that listen to that broadcast, which may contain two kinds of receivers. For those in AndroidManifest.xml, Ams will call queryIntentReceiver in PackageManagerService to get a list of receivers that listen to a broadcast. For those registered dynamically by registerReciever(...), they are managed by ActivityManagerService not PackageManagerService, so Ams will directly call mReceiverResolver.queryIntent to get those receivers. The mReceiverResolver is defined as:
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {
...
}
So what you need to do is override the queryIntent method to filter out the receivers in your application. For ContentProvider, the method is resolveContentProvider in PackageManagerService. Same way to handle it.
I have a questions here. I wanted to communicate to my service from my broadcast receiver. So I used the StartSevice(intent) method. In the service side the OnStartCommand() is called everytime I called StartService(). I just need to know how can i recognize in the onStartCommand() from where it is called from?
I hope I am clear in my question. If not please let me clarify...
You can't really check where you're called from, but you can do something a little bit related. You can specify certain tags in the Intent that you pass to the onStartCommand(). Notice that onStartCommand() takes an intent as its argument, this will be the intent that you sent. Whenever you send an intent to start the service from your broadcast receiver, you can specify certain "extras" in your intent and then use get those in your service.
http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int)
By the way, the use case you give seems to line up more with an IntentService than a regular service. This is a service which does what you're doing already: it sits there and waits for intents to be fired at it, and then reacts accordingly:
http://developer.android.com/reference/android/app/IntentService.html
In the onStartCommand method, the Intent you used to start service is passed as an argument.
onStartCommand(Intent intent, int flags, int startId)
So you can add Extras to intent to distinct where from it is called.
intent.putExtra("From", "MainScreen");
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