I want to create a service which will run on a separate thread (not on UI Thread), so I implemented a class which will extend IntentService. But I haven't got any luck. Here is the code.
public class MyService extends IntentService {
public MyService(String name) {
super(name);
// TODO Auto-generated constructor stub
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.e("Service Example", "Service Started.. ");
// pushBackground();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.e("Service Example", "Service Destroyed.. ");
}
#Override
protected void onHandleIntent(Intent arg0) {
// TODO Auto-generated method stub
for (long i = 0; i <= 1000000; i++) {
Log.e("Service Example", " " + i);
try {
Thread.sleep(700);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Service Consumption in an Activity Button click:
public void onclick(View view) {
Intent svc = new Intent(this, MyService.class);
startService(svc);
}
In your concrete implementation you have to declare a default constructor which calls the public IntentService (String name) super constructor of the abstract IntentService class you extend:
public MyService () {
super("MyServerOrWhatever");
}
You do not need to overwrite onStartCommand if the super implementation fits for you (what I expect).
In your current case you should get an exception (Unable to instantiate service...) - it is always worth to put this in the question.
Not the case here but this might help someone:
Check that your service class is not abstract. I had this problem because I had copied IntentService implementation from SDK and modified it to better suit my needs.
I resolved the "Unable to instantiate the service" issue, by adding the default parameterless constructor.
ServiceDemo.java:
public class ServicesDemo extends Activity implements OnClickListener {
private static final String TAG = "ServicesDemo";
Button buttonStart, buttonStop;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStart = (Button) findViewById(R.id.buttonStart);
buttonStop = (Button) findViewById(R.id.buttonStop);
buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
public void onClick(View src) {
switch (src.getId()) {
case R.id.buttonStart:
Log.w(TAG, "onClick: starting srvice");
startService(new Intent(this, MyService.class));
startActivity(new Intent(getApplicationContext(),Second.class));
break;
case R.id.buttonStop:
Log.w(TAG, "onClick: stopping srvice");
stopService(new Intent(this, MyService.class));
break;
}
}
}
MyService.java:
package com.example;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;
#Override
public IBinder onBind(Intent intent) {
Log.w(" ibinder ","");
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created",0).show();
Log.w(TAG, "onCreate");
player = MediaPlayer.create(this,R.raw.frm7v1);
player.setLooping(true); // Set looping
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped",0).show();
Log.w(TAG, "onDestroy");
player.stop();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started :"+intent+" start id :"+startid,0).show();
Log.d(TAG, "onStart");
player.start();
}
}
Declare the following attribute in manifest file:
<service android:enabled="true" android:name=".MyService" />
This answer has been updated. Here is the updated, correct answer:
According to the documentation you do not have to override onStartCommand() for IntentServices, instead the documentation says the following about onStartCommand() for IntentServices: You should not override this method for your IntentService. Instead, override onHandleIntent(Intent), which the system calls when the IntentService receives a start request. (Thanks to Ready4Android).
Below is the original incorrect answer (left in so the comments make sense):
According to documentation you should override OnStartCommand() (or deprecated OnStart()) in order to process intent service start-up. Have you tried it? And as K. Claszen wrote - you need to implement default constructor.
Related
I've looked at several examples, but I can't figure out what I'm doing wrong.
Auto logout after 15 minutes due to inactivity in android
After looking at that example, I created a LogoutService class that extends Service. Also, do I still have to have an intent that calls my login activity? Something like this:
Intent intent = new Intent(getBaseContext(), LoginActivity.class);
startActivity(intent);
My LogoutService Class
public class LogoutService extends Service {
public static CountDownTimer timer;
private final String TAG="Service";
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
timer = new CountDownTimer(1 * 60 * 1000, 1000) {
public void onTick(long millisUntilFinished) {
//Some code
Log.v(TAG, "Service Started");
}
public void onFinish() {
Log.v(TAG, "Call Logout by Service");
// TODO should I create an Intent
// my Login method here?
stopSelf();
}
};
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
And put this in all my other classes:
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
try {
LogoutService.timer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
LogoutService.timer.cancel();
}
But I keep getting a null pointer exception due to
LogoutService.timer.cancel();
I surrounded it with an if statement that checks if it's null, but then nothing happens, not sure what I should do.
getting a null pointer exception due to LogoutService.timer.cancel();
Because LogoutService extends Service class but not starting it using startService method so onCreate method is not called and timer is null.
Do following :
Start/Stop service using startService and stopService methods
cancel timer in onDestory() of Service.
Add LogoutService class as service in AndroidManifest.xml
I am feeling strange behaviour with service when i close my app or my app is destoyed. Service starts from beggining means onStartCommand() method calls again. If service runs in background it should not be called again please help me why its happening
This is my service code
package gcmtutorial.androidbegin.com.socket;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
/**
* Created by shuser on 21-07-2016.
*/
public class Services extends Service {
public static boolean status;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public class Hello implements Runnable{
public void run(){
synchronized (this){
int i=0;
while (i<100){
try {
wait(1000);
Log.e("Status:", "value "+i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
stopSelf();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
status = true;
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
Thread thread = new Thread(new Hello());
thread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
status = false;
super.onDestroy();
Log.e("Status:","Service Destroyed");
}
}
This is my MainActivity code
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, Services.class);
if (Services.status == true) {
Log.e("Check:","Service is Running");
}else {
Log.e("Check:","Service Will run now");
startService(intent);
}
}
}
Please help me why such thing is happening with service. I get Toast as well Service Started and LogCat also shows value from 0
Per START_STICKY:
if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service. Because it is in the started state, it will guarantee to call onStartCommand(Intent, int, int) after creating the new service instance;
If you'd like your Service to not automatically restart when your process is destroyed, return START_NOT_STICKY
I have created a simple service which will increment a counter and log it.
public class AudioService extends Service {
int i=0;
private final IAudioInterface.Stub mBinder = new IAudioInterface.Stub() {
public int getI()
{
return i;
}
};
#Override
public IBinder onBind(Intent intent) {
Log.d("onBind from service","****");
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
Log.d("onCreate from service","***");
Log.d("i=","="+i);
i=i+1;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("OnDestroy Called from service","***");
}
public void onStartCommand(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d("onStartCommand from service","***");
}
#Override
public boolean onUnbind(Intent intent) {
Log.d("onUnbind from service","***");
return super.onUnbind(intent);
}
i am incrementing the i value in the oncreate method of he service.
The Client Activity is as shown below
public class AidlInterfaceServiceActivity extends Activity implements OnClickListener {
/** Called when the activity is first created. */
private static final String TAG = "Audio:Service";
IAudioInterface mService = null;
boolean connected = false;
ServiceConnection mConnection = new ServiceConnection(){
public void onServiceConnected(ComponentName arg0, IBinder service) {
// TODO Auto-generated method stub
connected = true;
Log.d("Service connected","**");
mService = IAudioInterface.Stub.asInterface(service);
try {
Log.d("i from client","="+mService.getI());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
Log.i(TAG, "Service disConnected");
connected = false;
mService= null;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("on created ","**********");
Intent music = new Intent();
music.setClass(this,AudioService.class);
startService(music);
bindService(music, mConnection, Context.BIND_AUTO_CREATE);
}
The AIDL file is as below
interface IAudioInterface
{
int getI();
}
The problem is when i run the client activity every time the value of i is "0".
i value is not getting incremented.
I have these queries.
1.what happens when the service is started multiple time.
2.what happens when the service is bounded multiple times.
3.what happens to the data members inside the service class when it is started multiple times.Does those data members get reinitialized.
I am really confused ..Any one please help.
Does it help if you declare your counter variable as static?
I guess I have more like a design issue than a "how to bind a service" issue. What I'm trying to do is to have a service running in a separate process that handles bluetooth communication. Further I have several tabs, within each another activity. The processing and UI events from each activity results in simple commands which have to be passed over bluetooth like "up", "down", "left" or "right". As the results in each tab activity are the same, I don't wnat to connect each with the service, and use the same message handler. So I created my own Handler object and a "connector" object. However I'm not sure how to connect this connector object with my service as it requries a context. Does it make sense to simply pass the application context to my connector object and bind it that way???
I'm open for any suggestions or hints
I'd suggest against using binding in this case. Actually, I'd suggest against binding in most use cases. Try to handle all communication between you Activities and the service running in another thread using intents only.
That means:
Send commands to the service from the activities by the .startActivity() method, passing the details of the actual command in the Intent's extras.
Receive events and result from the service in your activities by dynamically registered BroadcastReceivers. You register a listener in onResume() and unregister it in onPause() in you Activity. The service sends stuff only by broadcasting it (sendBroadcast()).
I prefer this architecture. It's loosely coupled and you can skip the annoying part where you're wondering if every one of your Activities unbinds correctly from you service when they're not using it. Also, you skip the pain of using IPC, which is a huge plus I think.
Here you are, my example .. will make you clear about that LOL
// My MyServiceInterface.aidl
package com.mad.exam;
interface MyServiceInterface{
int getNumber();
}
//MyService
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(this, "Service OnBind()", Toast.LENGTH_LONG).show();
return mBinder;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "Service Destroyed ", Toast.LENGTH_SHORT).show();
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Toast.makeText(this, "Service Started ", Toast.LENGTH_SHORT).show();
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}
private final MyServiceInterface.Stub mBinder = new MyServiceInterface.Stub() {
public int getNumber() {
return new Random().nextInt(100);
}
};
}
//My Activity
public class ServiceDemo extends Activity implements OnClickListener {
MyServiceInterface mService;
ServiceConnection mConnection;
Button retreive;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.service);
retreive = (Button) findViewById(R.id.retreive);
retreive.setOnClickListener(this);
mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mService = MyServiceInterface.Stub.asInterface(service);
try {
int i;
i = mService.getNumber();
Toast.makeText(ServiceDemo.this, "The service value is: " + String.valueOf(i),
Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("My Tag", "Clicked");
Button btn = (Button) v;
Intent callService = new Intent(this, MyService.class);
bindService(callService, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Intent callService = new Intent(this, MyService.class);
bindService(callService, mConnection, Context.BIND_AUTO_CREATE);
}
}
I have a question which is related to this question that was asked by #mnish about a year ago.
Please have a look at his question and code. He implements a ServiceConnection() and passes it to bindService(). This follows the Local Service Sample in the Service documentation near the top.
I want to implement the Local Service Sample, so I am trying to add some details from #mnish question/answer. In ServiceConnection() #mnish has this line that confuses me:
mService = ILocService.Stub.asInterface(iservice);
I understand #mnish wrote this code, but does anybody have any idea what ILocService is and any idea how I might go about creating my own ILocService? Where is this construct documented and do I need it? Also where does the value for IBinder iservice come from?
He is probably using Android Interface Definition Language (AIDL)
http://developer.android.com/guide/components/aidl.html
Therefore he has to use a stub of the server side implementation like documented:
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
mService = IRemoteService.Stub.asInterface(service);
The iservice reference is coming from the onServiceConnected method which is called after binding the service to your activity. The call bindService gets passed the ServiceConnection which implements the onServiceConnected method.
You don't need the "IRemoteService.Stub.asInterface(service)" when your implementation of the service is local, then you can just cast the service to you local service.
The local service sample does this in the service:
public class LocalService extends Service {
private NotificationManager mNM;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
private int NOTIFICATION = R.string.local_service_started;
/**
* Class for clients to access. Because we know this service always
* runs in the same process as its clients, we don't need to deal with
* IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
...
}
And this in the Activity in the ServiceConnection class:
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
mBoundService = ((LocalService.LocalBinder)service).getService();
// Tell the user about this for our demo.
Toast.makeText(Binding.this, R.string.local_service_connected,
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
mBoundService = null;
Toast.makeText(Binding.this, R.string.local_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};
Here you are, my example .. will make you clear about that LOL
// My MyServiceInterface.aidl
package com.mad.exam;
interface MyServiceInterface {
int getNumber();
}
//MyService
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(this, "Service OnBind()", Toast.LENGTH_LONG).show();
return mBinder;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "Service Destroyed ", Toast.LENGTH_SHORT).show();
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Toast.makeText(this, "Service Started ", Toast.LENGTH_SHORT).show();
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}
private final MyServiceInterface.Stub mBinder = new MyServiceInterface.Stub() {
public int getNumber() {
return new Random().nextInt(100);
}
};
}
//My Activity
public class ServiceDemo extends Activity implements OnClickListener {
MyServiceInterface mService;
ServiceConnection mConnection;
Button retreive;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.service);
retreive = (Button) findViewById(R.id.retreive);
retreive.setOnClickListener(this);
mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mService = MyServiceInterface.Stub.asInterface(service);
try {
int i;
i = mService.getNumber();
Toast.makeText(ServiceDemo.this, "The service value is: " + String.valueOf(i), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("My Tag", "Clicked");
Button btn = (Button) v;
Intent callService = new Intent(this, MyService.class);
bindService(callService, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Intent callService = new Intent(this, MyService.class);
bindService(callService, mConnection, Context.BIND_AUTO_CREATE);
}
}