I create Service and call it from MainActivity.class with put string extra to intent but when I call getStringExtra in onStartCommand, it returns NullPointerException
Here is my code:
MainService.class :
public class MainService extends Service {
private WindowManager wm;
private WindowManager.LayoutParams params;
#Override
public IBinder onBind(Intent i) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
if (mView != null) {
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.removeView(mView);
}
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String quote = intent.getStringExtra("quote");
Log.d("datastring",quote);
return super.onStartCommand(intent, flags, startId);
}
}
In MainActivity.class I called :
Intent i=new Intent(MainActivity.this, MainService.class);
i.putExtra("quote", "dataquote");
stopService(i);
How I can get string from MainActivity in MainService?
If you want to provide more data to your Service you need to use something like:
Intent intent = new Intent(MainActivity.this, MainService.class);
intent.putExtra("quote", "dataquote");
startService(intent);
This will start the service and you should be able to get the data intent in the onStartCommand(). If the Service is already running, onStartCommand() will still be called with the new intent. This is because Service components are inherently singleton, so only one instance of a particular service run at a time.
In your case, you are providing the data via stopService(intent). Not only its not possible to get this intent, your Service will also stop after this statement so, you cannot really do much with the data even if you could have read it.
If you still need to stop your Service and pass data at the same time, you should check this post.
Related
So I have code that I want called when my application is closed. Not just when it is sent to the background or the surface is destroyed. How do I do this? Is there a method that I can override in a SurfaceView or Activity class?
New Edit - current BackgroundService class:
public class BackgroundService extends Service {
private String savedString;
public void onCreate() {
System.out.println("Service created");
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("start command: ");
savedString = intent.getStringExtra("myString);
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent intent) {
return null;
}
public void onTaskRemoved(Intent rootIntent) {
System.out.println("the saved string was: " + savedString);
super.onTaskRemoved(rootIntent);
}
public void onDestroy() {
System.out.println("destroyed service");
super.onDestroy();
}
}
Where I then have this in my other class:
Intent serviceIntent = new Intent(activity.getApplicationContext(), BackgroundService.class);
serviceIntent.putExtra("myString", "this is my saved string");
activity.startService(serviceIntent);
you need to add a background service
public class BackgroundServices extends Service
{
#Override
public void onCreate() {
Toast.makeText(this, "start", Toast.LENGTH_SHORT).show();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
then in your activity. where you want to trigger this service
use
startService(new Intent(getBaseContext(), BackgroundServices.class));
in your case it will be call on onDestory function of that activity
Yes when the process is terminated
That is not possible in general. Nothing in your app is called when the process is terminated.
For example when you open the running apps screen, and swipe away the app to stop it from running
That is a task removal. It may result in your process being terminated, and there are many ways in which your process can be terminated that has nothing to do with task removal.
To detect task removal, override onTaskRemoved() in a Service.
I can't stop my service.
I have two services. Service1 starts Service2 with startService(intent).
I stop service1 with stopSelf();
Then I'm doing something in Service2 and start Service1 again and stop Service2.
So they are always starting each other again.
The behavior of the services are different after the first start.
I write some log messages and I can see that the information are multiply times in log cat.
I also tried to stop the activities in the onStartCommand of the other activty with stopService. (In onStartCommand of Service1 I call stopService service2)
Here is a Part of my Code:
Service1:
public class Service1 extends Service{
private int startId;
#Override
public void onCreate(){
super.onCreate();
}
private void doSomething(){
...
...
Intent intent = new Intent(getApplicationContext(), Service2.class);
startService(intent);
this.stopSelf(startId);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.startId=startId;
Intent beaconIntent = new Intent(getApplicationContext(), Service2.class);
stopService(beaconIntent);
doSomething();
return START_STICKY;
}
}
Service2:
public class Service2 extends Service implements BeaconConsumer, RangeNotifier{
private BeaconManager mBeaconManager;
private int startId;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent service1 = new Intent(getApplicationContext(), Service1.class);
stopService(service1);
mBeaconManager = BeaconManager.getInstanceForApplication(this);
mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
mBeaconManager.bind(this);
this.startId = startId;
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mBeaconManager.unbind(this);
}
#Override
public void onBeaconServiceConnect() {
region = new Region("all-beacons-region", null, null, null);
try {
mBeaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
mBeaconManager.addRangeNotifier(this);
}
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if(!beacons.isEmpty()){
doSomething...
...
...
Intent intent = new Intent(getApplicationContext(), Service1.class);
startService(intent);
this.stopSelf();
}
}
}
What am I doing wrong?
Edit: I didn't mention, that I'm working with altbeacon library. I thought that doesn't make any impact.
But when I'm looking at the services which are running when I start the app and after I stop the Service2 there are always two altbeacon services running(BeaconIntentProcessor and BeaconService).
Maybe they calling my service mutlipy times.
I got what I did wrong.
The problem was not the service it self, it was the altbeacon library. More concrete the BeaconManager which was still searching in the background for a beacon, even when the service was destroyed.
In the logs it looked like the service is running multiple times.
The solution was to not only unbind, also to stop Ranging and remove the range notifier.
mBeaconManager.stopRangingBeaconsInRegion(region);
mBeaconManager.removeAllRangeNotifiers();
mBeaconManager.unbind(this);
I have a function in a service as follows:
public class ServiceA extends Service {
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
private final IBinder mBinder = new LocalBinder();
public void readFunc() {
//I have a function in here
}
}
I want to call the readFunc() in the service B. Could I do it in Android? Thank all. This is my service B
public class serviceB extends Service {
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("A");
intentFilter.addAction("B");
registerReceiver(broadcastReceiver, intentFilter);
return START_STICKY;
}
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case "A":
Log.d(TAG,"A");
//Call the function here
break;
case "B":
Log.d(TAG,"B");
break;
}
}
};
}
Well, you COULD do it, just instancing a new ServiceA and calling the function, but you should not do it like that. Services are not meant to be instantiated just to call a function which is not even part of the Service functionality. You have different options:
You could make readFunc() static if it does not modify variables of the class and you think it should belong to ServiceA and not to ServiceB. I don't think this is a goog approach in your case.
You could create a class ServiceAB which has readFunc(), and the define both ServiceA and B as "extends ServiceAB". Then both classes would inherit this function and you could just call readFunc() in both of them. I think this would be the correct approach in your case: both classes need some common functionality.
You could have readFunc() in a different class, and the instantiate it to use it in each of your services.
The way I would do it:
public class ServiceAB extends Service {
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
public void readFunc() {
//I have a function in here
}
}
Then:
public class serviceB extends ServiceAB {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("A");
intentFilter.addAction("B");
registerReceiver(broadcastReceiver, intentFilter);
return START_STICKY;
}
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case "A":
Log.d(TAG,"A");
readFunc(); //Just call the function
break;
case "B":
Log.d(TAG,"B");
break;
}
}
};
}
And ServiceA:
public class ServiceA extends ServiceAB {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
private final IBinder mBinder = new LocalBinder();
}
Quoting #Kingfisher Phuoc here and #Mr Snowflake here
there are three obvious ways to communicate with services and EventBus:
Using Intents
Using AIDL
Using the service object itself (as singleton)
EventBus
In your case, I'd go with option 3. Make a static reference to the service it self and populate it in onCreate():
void onCreate(Intent i) {
sInstance = this;
}
Make a static function MyService getInstance(), which returns the static sInstance.
Then in Activity.onCreate() you start the service,
asynchronously wait until the service is actually started (you could have your service notify your app it's ready by sending an Intent to the activity.) and get its instance.
When you have the instance, register your service listener object to you service and you are set.
NOTE: when editing Views inside the Activity you should modify them in the UI thread, the service will probably run its own Thread, so you need to call Activity.runOnUiThread().
The last thing you need to do is to remove the reference to you listener object in Activity.onPause(), otherwise an instance of your activity context will leak, not good.
NOTE: This method is only useful when your application/Activity/task is the only process that will access your service. If this is not the case you have to use option 1. or 2.
I hava a simple service with data - ArrayList < MyObject > , when I close the app - service is restarted, called onCreate method and data is losing. This is my onStartCommand method:
public int onStartCommand(Intent intent, int flags, int startId) {
.....
return START_STICKY;
}
Service start in Application class
Intent serviceIntent = new Intent(this, ChatNotificationService.class);
startService(serviceIntent);
I not called stopService method.
I need after closing the application, the service continued to work and the data saved in it.
How I can do it?
In activity:
#Override
protected void onCreate() {
super.onCreate();
bindService(serviceIntent, sConn, 0);
}
#Override
public void onDestroy(){
super.onDestroy();
chatNotificationService.closeConnections();
unbindService(sConn);
}
I have two services:
a provider of data and a receiver.
i try to do this way:
PROVIDER:
Intent i1 = new Intent(feasibilityEngine.this, SOSFeeder.class);
i1.putExtra(SENSOR_STRING, "f[i]");
startService(i1);
RECEIVER
Intent intent = getIntent();
Bundle b = new Bundle();
int i = b.getInt(SENSRO_STRING);
but i can't use the getIntent().
Someone can help me?
TNKS
You can retrieve the value of SENSRO_STRING as:
Bundle b = getIntent().getExtras();
int i = b.getInt(SENSRO_STRING);
If you are in a BroadcastReceiver for example, in the overwritten onReceived method, you can call as:
#Override
public void onReceive(Context context, Intent intent)
{
Bundle b = intent.getExtras();
int i = b.getInt(SENSRO_STRING);
No need to call getInent(), Your intent will be handed to the receiver service in the onStartCommand(), which will be your entry point from a startService() call.
sample code modified from here.
Receiver Service:
// This is the old onStart method that will be called on the pre-2.0
// platform. On 2.0 or later we override onStartCommand() so this
// method will not be called.
#Override
public void onStart(Intent intent, int startId) {
handleCommand(intent);
}
#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;
}
private void handleCommand(Intent intent) {
// should this be getStringExtra instead?
int i = intent.getIntExtra(SENSRO_STRING, -1);
}