Pass String from activity to service? - android

I am familiar with the method of passing arrays from one activity to another activity using putExtra and getExtra methods. However, whenever I try to get it from a service the following code doesn't work:
Bundle b = this.getIntent().getExtras();
String Array = b.getStringArray("paths");
It is not recognizing the following:
this.getIntent().getExtras();
Any ideas?
EDIT
in the activity class I have the following:
toService = new Intent();
toService.setClass(this, Service.class);
toService.putExtra("paths",Array);
in the service class:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Bundle extras = intent.getExtras();
if(extras!=null)
{
Paths = extras.getStringArray("paths");
Toast.makeText(protectionService.this, Paths[0], Toast.LENGTH_SHORT).show();
}
return 0;
}
Nothing is appearing since Paths is not being assigned apparently.
Paths = extras.getStringArray("paths");
Doesn't seem to work.

Where are you trying to access getIntent?
Here is a snippet from a program I have written which uses the getExtras:
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Bundle extras = intent.getExtras();
if (extras != null) {
// Do what you want
}
}
However, onStart is now deprecated so you should really use onStartCommand.
You get the intent as one of the parameters.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
Otherwise you could use AIDL, Preferences or any other example answered here: How to access a variable present in a service
Same question has already been answered Android: how to get the intent received by a service?
Edit:
If you use this
toService = new Intent();
toService.setClass(this, Service.class);
toService.putExtra("array",Array);
You need to get the extras with the same key, here the key is "array"
Paths = extras.getStringArray("array");

Related

NullPointer Exception in Service.onStartCommand after APK being closed. How to deal with it?

There is a service which has to process data from Intent in its Handler.
Snippet below:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle bundle = intent.getExtras();
Message msg = new Message();
msg.setData(bundle);
mServiceHadler.sendMessage(msg);
return START_STICKY;
}
After invocation of Intent to start service and removing APK from overview screen in consequence one gets NullPointerException because of null Intent has came.
java.lang.RuntimeException: Unable to start service com.example.intentservicetest01.ServiceExt#750547a with null: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Bundle android.content.Intent.getExtras()' on a null object reference
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4021)
at android.app.ActivityThread.access$2400(ActivityThread.java:209)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1841)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7014)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:731)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:621)
Is there canonical clear (without adding conditional null check) way to deal with null Intent?
Will this callback method (Service.onStartCommand) survive if the service will be started in another process? Any suitable ideas are appreciated.
I like to coding like this, use #Nullable Annotation.
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: " + intent.getCategories());
return super.onStartCommand(intent, flags, startId);
}
If intent is used but is not checked, there is a warning like this:
warning info
then you may do it easyly.
Try stop your service like this
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
stopSelf();
}
or start it in this way
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// your code
return START_REDELIVER_INTENT;
}

Substring of the intent extra is being changed when passing it to Service class

I am facing problem that is driving me crazy. I hope someone can explain me this strange behaviour of my intent. So I want to pass JSON string {"latitude":53.86907815,"longitude":10.66554789,"formatted":"23.04.2015 10:16:49","route":4} to my Service class "PostData" but I am getting null as well as the JSON string in the onStartCommand() method at the same time where the formatted value is always a old one and not of the current time which I am passing to the class.
The calling part in the inner class of the MainActivity:
String jSONString = convertToJSON(pLong, pLat, formatted);
Intent intentJson = new Intent(MainActivity.this, PostData.class);
intentJson.putExtra("json_data", jSONString);
startService(intentJson);
The PostData class:
public class PostData extends IntentService {
public PostData() {
super("someone");
// TODO Auto-generated constructor stub
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
String jSONString = intent.getStringExtra("json_data");
if(jSONString != null){
System.out.println("Output from onStartCommand "+jSONString);
}
}
}
I tried to debugg it too but always when the debuger is in onStartCommand I am getting null as output!!
This screenshot was captured when the debugger was at this line 'startService(intentJson);' :
This is some of the output I am getting in onStartCommand method. Here formatted has always the same timeStamp: 23.04.2015 18:37:49 In the debugging mod I am always getting null as output!!
04-24 11:29:22.785: I/System.out(23721): Output from onStartCommand {"latitude":53.86898202,"longitude":10.66561591,"formatted":"24.04.2015 11:29:23","route":1}
04-24 11:29:22.805: I/System.out(23721): Output from onStartCommand {"latitude":53.86907815,"longitude":10.66554789,"formatted":"23.04.2015 18:37:49","route":4}
04-24 11:29:23.766: I/System.out(23721): Output from onStartCommand {"latitude":53.86898202,"longitude":10.66561589,"formatted":"24.04.2015 11:29:24","route":1}
04-24 11:29:23.806: I/System.out(23721): Output from onStartCommand {"latitude":53.86907815,"longitude":10.66554789,"formatted":"23.04.2015 18:37:49","route":4}
04-24 11:29:24.787: I/System.out(23721): Output from onStartCommand {"latitude":53.868982,"longitude":10.66561591,"formatted":"24.04.2015 11:29:25","route":1}
04-24 11:29:24.807: I/System.out(23721): Output from onStartCommand {"latitude":53.86907815,"longitude":10.66554789,"formatted":"23.04.2015 18:37:49","route":4}
04-24 11:29:25.758: I/System.out(23721): Output from onStartCommand {"latitude":53.868982,"longitude":10.66561591,"formatted":"24.04.2015 11:29:26","route":1}
04-24 11:29:25.818: I/System.out(23721): Output from onStartCommand {"latitude":53.86907815,"longitude":10.66554789,"formatted":"23.04.2015 18:37:49","route":4}
04-24 11:29:26.809: I/System.out(23721): Output from onStartCommand {"latitude":53.86907815,"longitude":10.66554789,"formatted":"23.04.2015 18:37:49","route":4}
The error must be somewhere else.
Intent and bundle works correctly. You can relay on that!
Do you start multiple times the PostData Service? May this cause confusion, since intent service works like a queue? It handles one intent after each other and starts with the new intent when the previous work is done.
Additionally, you should handle the intents data in onHandleIntent and not in onStartCommand.
There is no need to override onStartCommand. Probably this will cause an error, since I'm not sure which Intent is passed here as parameter if the IntentService is already running and takes a new Intent from the queue.
You have to set the values in intent and pass that intent while starting the service, and you can get the values in serivce onStartCommand(Intent intent, int flags, int startId).
This is how you have to pass that integer through intent.
private class StartClick implements View.OnClickListener {
public void onClick(View v) {
Intent intent = new Intent(main_activity,ServiceMP3.class);
intent.putExtras("position",4);
main_activity.startService(intent);
}
}
You can get the values is service like this
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null){
int position = intent.getIntExtra("position", 0);
}
}

Check if activity is running from service of same package

This is more of a doubt. Currently, my code works fine, but I want to make sure I'm doing it the right way.
I have a service, which checks if the activity is running on the foreground. If it is, it sends a broadcast to the activity, so the activity updates some stuff on the screen.
I created an IntentFilter on the service:
com.harkdev.ServerStatus.SERVER_UPDATED
Here the service needs to know if the activity is on the foreground, so it uses the IsActivityRunning() method, which reads the running tasks from the ApplicationManager. This means that I need to set the GET_TASKS permission.
Being that both, the SERVICE and the ACTIVITY are on the same package, is there a better way to get this info?? And maybe try and avoid setting the GET_TASKS permission??
This is the code in my service:
if (IsActivityRunning()) {
Intent localIntent = new Intent(SERVER_UPDATED);
SendBroadcast(localIntent, null);
}
The IsActivityRunning() Method:
public bool IsActivityRunning() {
ActivityManager manager = (ActivityManager) GetSystemService(ActivityService);
IList<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.GetRunningTasks(1);
ComponentName componentInfo = runningTaskInfo[0].TopActivity;
if (componentInfo.PackageName == "com.harkdev.ServerStatus")
return true;
return false;
}
And this is the code in my activity:
protected override void OnCreate (Bundle bundle) {
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
IntentFilter filter = new IntentFilter(ServerStatusCheckService.SERVER_UPDATED);
_receiver = new ServiceBroadcastReceiver ();
_receiver.Received += Receiver_Received;
RegisterReceiver(_receiver, filter);
}
First you're doing the wrong way to compare strings:
if (componentInfo.PackageName == "com.harkdev.ServerStatus")
It should be:
if ("com.harkdev.ServerStatus".equals(componentInfo.PackageName))
Second, if the service and the activity are in your app then I think the requirement to check for "same package" is not necessary.
To send information from the service to the activity, you can use ResultReceiver (available in API 3+):
When starting your service from the activity, you create a ResultReceiver, put it into the intent which starts the service.
In the service, extract the ResultReceiver and keep it. When you want to send information, use send().
In the activity, for example in onDestroy() you can trigger a command to notify the service that the ResultReceiver is invalid and it should be removed.
Edied
For example:
In your activity:
// Global variable.
private ResultReceiver mResultReceiver = new ResultReceiver() {
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Update the UI here...
}
}
When you start the service:
Intent i = new Intent(this, TheService.class);
// You can use different action names for different commands.
i.setAction("REGISTER_RECEIVER");
i.putExtra("ResultReceiver", mResultReceiver);
i.putExtra("ResultReceiver_ID", hashCode());
startService(i);
And in onDestroy():
Intent i = new Intent(this, TheService.class);
i.setAction("UNREGISTER_RECEIVER");
i.putExtra("ResultReceiver_ID", hashCode());
startService(i);
In your service:
import android.util.SparseArray;
// ...
private SparseArray<ResultReceiver> mReceiverMap = new SparseArray<ResultReceiver>();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if ("REGISTER_RECEIVER".equals(intent.getAction())) {
// Extract the ResultReceiver and store it into the map
ResultReceiver receiver = intent.getParcelableExtra("ResultReceiver");
int id = intent.getIntExtra("ResultReceiver_ID", 0);
mReceiverMap.put(id, receiver);
} else if ("UNREGISTER_RECEIVER".equals(intent.getAction())) {
// Extract the ResultReceiver ID and remove it from the map
int id = intent.getIntExtra("ResultReceiver_ID", 0);
mReceiverMap.remove(id);
}
// ...
}

Android Service Activity Intent

I want to pass a string from activiy to service.
Bundle mBundle = new Bundle();
mBundle.putString("MyString", string);
mIntent.putExtras(mBundle);
startService(mIntent);
this is in Activity class
Intent myIntent = getIntent();
String value = myIntent.getExtras().getString(key);
and this is in Service class
It doesn't accept getIntent() method :S I don't know what I'll do
The code in the service must be placed in onStart(Intent intent, int startid) method and the code becomes String value = intent.getExtras().getString(key);
When you start the service using startService(mIntent) the service's onStartCommand is called which is good place to handle the intent.
Move the part of your code that depends on the intent to onStartCommand: http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int)
OnStartCommand was called OnStart before api version 5, follow link to documentation for further information about backwards compatibility in your app.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String value = intent.getExtras().getString(key);
}
Also remember to move heavy code into a background thread that you start in onStartCommand, as otherwise you will run into an Application Not Responding error.

Android: how to get the intent received by a service?

I'm starting a service with an intent where I put extra information.
How can I get the intent in the code of my service?
There isn't a function like getIntent().getExtras() in service like in activity.
onStart() is deprecated now. You should use onStartCommand(Intent, int, int) instead.
Override onStart() -- you receive the Intent as a parameter.
To pass the extras:
Intent intent = new Intent(this, MyService.class);
intent.putExtra(MyService.NAME, name);
...
startService(intent);
To retrieve the extras in the service:
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
String name = intent.getExtras().getString(NAME);
...
}
...
}

Categories

Resources