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
Related
I am stuck with the problem of Activity + Service in that I have following number of Activities and Services.
Activities:
LoginActivity => OrderListActivity => AddOrderActivity => ConfirmOrderActivity
Services:
ReceivingOrderService - Receiving New Data From Server
SendingOrderService - Sending new Data to Server
Above both Service Calling from another Separate Service on duration of some interval.
CheckAutoSyncReceivingOrder - To call ReceivingOrderService (Interval 15Mins)
CheckAutoSyncSendingOrder - To call SendingOrderService (Interval 3Mins)
CheckAutoSyncReceivingOrder:
public class CheckAutoSyncReceivingOrder extends Service {
Timer timer;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
if(timer != null) {
timer.cancel();
Log.i(TAG, "RECEIVING OLD TIMER CANCELLED>>>");
}
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if(InternetConnection.checkConnection(getApplicationContext())) {
if(getDatabasePath(DatabaseHelper.DATABASE_NAME).exists())
startService(new Intent(CheckAutoSyncReceivingOrder.this, ReceivingOrderService.class));
} else {
Log.d(TAG, "Connection not available");
}
}
}, 0, 60000); // 1000*60*15 = 9,00,000 = 15 minutes
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if(timer != null)
timer.cancel();
Log.d(TAG, "Stopping Receiving...");
}
}
CheckAutoSyncSendingOrder:
public class CheckAutoSyncSendingOrder extends Service {
Timer timer;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
if(timer != null) {
timer.cancel();
Log.i(TAG, "OLD TIMER CANCELLED>>>");
}
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Log.i(TAG, ">>>>>>>> SENDING AUTO SYNC SERVICE >>>>>>>>");
if(InternetConnection.checkConnection(getApplicationContext())) {
if(getDatabasePath(DatabaseHelper.DATABASE_NAME).exists())
startService(new Intent(CheckAutoSyncSendingOrder.this, SendingOrderService.class));
} else {
Log.d(TAG, "connection not available");
}
}
}, 0, 120000); // 1000*120*15 = 1,800,000 = 15 minutes
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if(timer != null)
timer.cancel();
Log.d(TAG, "Stopping Sending...");
}
}
ConfirmOrderActivity#Final Task which i have called for Insert Data:
new AsyncTask<Void, Void, Integer>() {
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
progressDialog = new ProgressDialog(
ConfirmOrderProductActivity.this);
progressDialog.setMessage("Inserting "
+ (isInquiry ? "Inquiry" : "Order") + "...");
progressDialog.setCancelable(false);
progressDialog
.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
}
#Override
protected Integer doInBackground(Void... params) {
// TODO Auto-generated method stub
int account_id = context.getSharedPreferences(PREF_DATA,
MODE_APPEND).getInt(DATA_ACCOUNT_ID, 0);
/**
* Check Whether isInquiry or not...
*/
product_type = isWeight ? 1 : 0;
if (isInquiry) {
/*
* INSERTING DATA IN INQUIRY TABLE
*/
return m_inquiry_id;
} else {
/*
* INSERTING DATA IN ORDER TABLE
*/
return m_order_id;
}
}
#Override
protected void onPostExecute(Integer m_order_id) {
// TODO Auto-generated method stub
super.onPostExecute(m_order_id);
progressDialog.dismiss();
if (dbHelper.db.isOpen())
dbHelper.close();
String title = "Retry";
String message = "There is some problem, Go Back and Try Again";
AlertDialog.Builder alert = new AlertDialog.Builder(
ConfirmOrderProductActivity.this);
if (m_order_id != -1) {
title = isInquiry ? "New Inquiry" : "New Order";
message = isInquiry ? "Your Inquiry Send Successfully." : "Your Order Saved Successfully.";
alert.setIcon(R.drawable.success).setCancelable(false);
} else {
alert.setIcon(R.drawable.fail).setCancelable(false);
}
alert.setTitle(title).setMessage(message)
.setPositiveButton("OK", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
// TODO Auto-generated method stub
dialog.dismiss();
startActivity(new Intent(
ConfirmOrderProductActivity.this,
FragmentChangeActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
/* Opening Left to Right Animation */
overridePendingTransition(R.anim.right_out,
R.anim.right_in);
}
});
AlertDialog alertDialog = alert.create();
alertDialog.show();
}
}.execute();
Everything is working fine as per flow of inserting records in database.
After Adding Inquiry:
Destroying Activity and Getting following Logcat:
Main Problem:
When I placed order successfully from ConfirmOrderActivity, It is displaying AlertDialog of Success Message which is cancellable false. When I Stop application from this Activity, Its calling both CheckAutoSyncReceivingOrder and CheckAutoSyncSendingOrder automatically.
Edited:
I am calling both Service from LoginActivity only, after that it
will called automatically after given intervals But Problem occurs
when I destroy ConfirmOrderActivity when dialog is shown.
I didn't know why it happens that Why its running automatically when I stop Activity Directly.
I have tried onStartCommand() with START_NON_STICKY in Service but not working. (as START_STICKY is default.)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Is there any solution?
You need to either run your service in the foreground so when the activity is destroyed so will the service or use a bound service and manage the binding with the activity lifecycle, so it is not continually restarted when the activity is destroyed.
From this android docs tutorial Bound Services
You need to do this for each service.
public class CheckAutoSyncReceivingOrder extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
CheckAutoSyncReceivingOrder getService() {
return CheckAutoSyncReceivingOrder.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
From your activity that creates and calls the service, that when it is destroyed you want your service destroyed.
public class BindingActivity extends Activity {
CheckAutoSyncReceivingOr mService;
boolean mBound = false;
#Override
protected void onStart() {
super.onStart();
// Bind to CheckAutoSyncReceivingOr
Intent intent = new Intent(this, CheckAutoSyncReceivingOr.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to CheckAutoSyncReceivingOr, cast the IBinder and get CheckAutoSyncReceivingOr instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
And manage the service lifecycle. Restart the same service with your timer, do not create a new service.
public class ExampleService extends Service {
int mStartMode; // indicates how to behave if the service is killed
IBinder mBinder; // interface for clients that bind
boolean mAllowRebind; // indicates whether onRebind should be used
#Override
public void onCreate() {
// The service is being created
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The service is starting, due to a call to startService()
return mStartMode;
}
#Override
public IBinder onBind(Intent intent) {
// A client is binding to the service with bindService()
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// All clients have unbound with unbindService()
return mAllowRebind;
}
#Override
public void onRebind(Intent intent) {
// A client is binding to the service with bindService(),
// after onUnbind() has already been called
}
#Override
public void onDestroy() {
// The service is no longer used and is being destroyed
}
}
Note START_NOT_STICKY will only prevent the service from restarting if the device is low on memory.
Be mindful that you where you are starting services, just start it once and allow the service to maintain it's own lifecycle until you destroy it with your activity.
This is in reply to your original unedited question, when the app was mysteriously crashing:
You need to destroy the dialog before the context window the dialog is attached to. That will cause a problem. So this is where program flow and the order of closing and cleaning up resources is important. They, frequently have to be destroyed in the reverse order they were created if they are dependent upon parent windows (which is often in the form of a particular activity).
It's difficult to trace your code, so this is a generic answer.
Make use of onPause and onDestroy in your activities.
In all your activities, manage any resources you have created within that activity and with a null check, close them down. Like you have in your service class. If you want to override the parent onDestroy, place your custom code before super.onDestroy.
protected void onDestroy() {
if(timer != null)
timer.cancel();
Log.d(TAG, "Stopping Sending...");
super.onDestroy();
}
(1)For Your Dialog:
The solution is to call dismiss() on the Dialog you created before exiting the Activity, e.g. in onDestroy(). All Windows & Dialog should be closed before leaving an Activity.
(2)For Your service autostart:
you have to look at the value the service returns from its onStartCommand method. The default value is START_STICKY which will restart the service after it is destroyed. Take a look at the onStartCommand documentation for more details:
If the process that runs your service gets killed, the Android system will restart it automatically it is default behavior.
This behavior is defined by the return value of onStartCommand() in your Service implementation. The constant START_NOT_STICKY tells Android not to restart the service if it s running while the process is "killed".
You need to Override method onStartCommand() in your service class and move all your code from onStart() method to onStartCommand() method.
According to the Android Documentation:
For started services, there are two additional major modes of
operation they can decide to run in, depending on the value they
return from onStartCommand(): START_STICKY is used for services that
are explicitly started and stopped as needed, while START_NOT_STICKY
or START_REDELIVER_INTENT are used for services that should only
remain running while processing any commands sent to them
onStart() method calls each time when service is restarted but onStartCommand() method will not called if you return START_NON_STICKY.
Don't use onStart() anymore, it's deprecated.
I hope it helps you.
Services got killed when application got killed (add logs in service onStartCommand() and onDestroy() function and try clearing app from recent list and you will see onDestroy() is called. Android will re-start service if you have returned START_STICKY intent in onStartCommand()).
There are two approaches to fix your problem.
Either make your two services as foreground service.
Instead of using CheckAutoSyncReceivingOrder and CheckAutoSyncSendingOrder to schedule start of another services, you should use AlarmManager to schedule your task.
I have an IntentService that does the following:
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Hello, World!");
}
}
The above is a sample of the code I am using. I intend to replace the println() with a HTTP Request sent to a server, but for now I am using this as a test. I call startService() as such:
#Override
public void onPause() {
ConnectionUtility.getInstance().startService(this);
super.onPause();
}
#Override
public void onDestroy() {
ConnectionUtility.getInstance().startService(this);
super.onDestroy();
}
#Override
public void onStop() {
ConnectionUtility.getInstance().startService(this);
super.onStop();
}
where my custom startService method does this:
public void startService(Activity activity) {
if (!isMyServiceRunning(activity)) {
Intent intent = new Intent(activity, BackgroundUpdateService.class);
activity.startService(intent);
}
}
Note: the isMyServiceRunning() method is a custom method I found elsewhere to determine if the Service is running. The method works as far as I know.
Now, the purpose of this Service is to trigger the println() whenever the particular Activity exits (either via onPause(), onDestroy() or onStop()), and when onCreate() or onResume() runs, the Service is to be stopped like so:
#Override
public void onResume() {
ConnectionUtility.getInstance().stopServiceIfRunning(this);
super.onResume();
}
Going one step deeper into stopServiceIfRunning():
public void stopServiceIfRunning(Activity activity) {
if (isMyServiceRunning(activity)) {
Intent intent = new Intent(activity, BackgroundUpdateService.class);
activity.stopService(intent);
}
}
Now here's the problem: I can start the Service alright, when I back out of the Activity via the Home/Back button or when I switch to a different Activity, the startService() method kicks in and it runs perfectly; that is to say, "Hello, World!" is printed every 5seconds as needed. But when I navigate back to the Activity, I can determine that my custom stopServiceIfRunning() method runs and the code enters the IF block fine (confirmed), but the service doesn't stop and the "Hello, World!"s just keep coming. What am I doing wrong?
---EDIT---
In response to Seraphim's comment:
private boolean isMyServiceRunning(Activity activity) {
ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (BackgroundUpdateService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
But again, this method is returning true and false values accurately thus far, so I don't think this is the problem.
Finally figured out a way to do it, really really thankful to Seraphim for helping me out so much though.
I ended up overriding the onDestroy() method of my custom IntentService class. This is what I came up with:
public class BackgroundUpdateService extends IntentService {
private boolean status;
public BackgroundUpdateService() {
super("BackgroundUpdateService");
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent intent) {
status = true;
// TODO Auto-generated method stub
while (status) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Hello, World!");
}
}
#Override
public void onDestroy() {
status = false;
super.onDestroy();
}
}
Evidently, the onDestroy() method is called whenever .stopService(intent) is called, so I made use of this fact to stop the while loop while I'm at it. This circumvents the reliability issue because each Service gets its own boolean variable and is not dependent on a static variable, and doesn't require any additional variables to be passed through the Intent.
Again, thanks to Seraphim for taking the time to help me out so much.
Stopping services is not a synchronous operation. If your check for service termination is close to the previous "service stop" call, you may find your service is still running.
In my app when I need to stop services (when exiting app) I enter in a loop cycle (using AsyncTask) and wait for service termination.
I see you call
#Override
public void onDestroy() {
ConnectionUtility.getInstance().startService(this);
super.onDestroy();
}
I suggest to use Application Context for starting and stopping your service and not the Activity as a context. Because you're starting your service when the activity is going to be destroyed!
Also the part
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Hello, World!");
}
}
A infinite loop when handling an intent? Sounds not very good to me.
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);
}
}
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.