Hi friends i have a one problem to solve...I want to destroy the service completely, once i call onDestroy() method from Activity. But my problem is that i am unable to destroy it completely.. in background its keep on running, i am sharing the sample code what i tried..
//Activity Class
public class ServiceToAct extends Activity {
private static final String TAG = "BroadcastEvent";
private Intent intent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
intent = new Intent(this, BroadcastService.class);
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(myService.BROADCAST_ACTION));
}
/*#Override
protected void onResume() {
super.onResume();
}*/
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
#Override
protected void onDestroy() {
stopService(intent);
Toast.makeText(this, "Destroy Completely", Toast.LENGTH_LONG).show();
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
};
}
// service class
public class myService extends Service {
private static final String TAG = "BroadcastEvent";
public static final String BROADCAST_ACTION = "com.service.activity.myService";
private final Handler handler = new Handler();
Intent intent;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "created", Toast.LENGTH_LONG).show();
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this, "start", Toast.LENGTH_LONG).show();
handler.removeCallbacks(sendToUI);
handler.postDelayed(sendToUI, 1000);
}
#Override
public void onDestroy() {
super.onDestroy();
stopSelf();
//stopService(intent);
Toast.makeText(this, "Destroy", Toast.LENGTH_LONG).show();
}
private Runnable sendToUI = new Runnable() {
#Override
public void run() {
myData();
handler.postDelayed(this, 10000);
}
};
private void myData() {
Log.d(TAG, "keep on entering");
Toast.makeText(this, "Keep on despling in UI", Toast.LENGTH_LONG).show();
sendBroadcast(intent);
}
}
Here Actually i want to update my UI from service, Mine everything is working, but if i destroy the service its keep on calling myData() method, and i am getting the Toast msg if i close the application also.
My issue is i don't want that toast msg once the service is desroyed
I used stopService(intent) method, which destroy the service, but background method myData() is keep on calling
for stop service completely use this ..
myActivity.java
#Override
public void onDestroy() {
stopService(intent);
super.onDestroy();
Toast.makeText(this, "Destroy", Toast.LENGTH_LONG).show();
}
service.java
#Override
public void onDestroy()
{
stopSelf();
super.onDestroy();
}
You'd better never call onXxx() derectly.
Use stopService(Intent i) in your activity and stopSelf() in you service to stop instead.
use stopService() method after updating UI
or
Instead of using startService use bindService in the activity. When activity destroys, service also destroys
Related
I have started an Intent activity from a service. Now, how I can stop that intent activity from service itself?
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService (View view) {
Intent intent = new Intent(this,MainService.class);
startService(intent);
}
public void stopService (View view) {
Intent intent = new Intent(this,MainService.class);
stopService(intent);
}
}
startService, stopService have buttons associated.
public class MainService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service started",Toast.LENGTH_LONG).show();
Intent dialogIntent = new Intent(this, calledActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(dialogIntent);
return START_STICKY;
//return super.onStartCommand(intent,flags,startId);
}
#Override
public void onDestroy() {
//super.onDestroy();
Toast.makeText(this, "Service stopped",Toast.LENGTH_LONG).show();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
//Intent dialogIntent = new Intent(this, MainActivity.class);
//dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//startActivity(dialogIntent);
return null;
}
}
public class calledActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "I am here", Toast.LENGTH_LONG).show();
displayNumber();
}
#Override
protected void onStop() {
super.onStop();
Toast.makeText(this, "I am stopping", Toast.LENGTH_LONG).show();
finish();
}
#Override
protected void onDestroy () {
super.onDestroy();
Toast.makeText(this, "I am being destroyed", Toast.LENGTH_LONG).show();
finish();
}
public void displayNumber () {
TextView tv = (TextView)findViewById(R.id.textView);
Integer counter = 10;
while (counter > 0) {
//tv.setText("Here you go" + String.valueOf(counter));
tv.setText("Here you go" + counter);
counter = counter - 1 ;
Toast.makeText(this, "I am there "+counter, Toast.LENGTH_LONG).show();
}
}
}
When service invokes the intent activity, I think intent activity is on the foreground. Now, whenever I press stop service button, application crashes. I believe as stopService is associated with the service class but not in the intent activity. Is there any way to stop the intent activity from the service?
Service works on UI thread. Try using IntentService. It runs on background thread.
I have one activity and one service. My requirement is to start service from activity and in activity countdown timer will start, but problem is that I'm unable to get value from service to my activity. Please help me out.
Is any code,tutorial,example which will help me for this.
TIMER SERVICE
public class TimerService extends Service {
MyCounter timer;
#Override
public void onCreate() {
timer = new MyCounter(1 * 60 * 1000, 1000);
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
timer.start();
return super.onStartCommand(intent, flags, startId);
}
private class MyCounter extends CountDownTimer {
public MyCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
Toast.makeText(getApplicationContext(), "death", Toast.LENGTH_LONG)
.show();
stopSelf();
}
#Override
public void onTick(long millisUntilFinished) {
Toast.makeText(getApplicationContext(),
(millisUntilFinished / 1000) + "", Toast.LENGTH_SHORT)
.show();
}
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
timer.cancel();
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
what should i write in this service so i will get toast message value in my activity
Read about broadcast receivers.
Create a broadcast receiver in activity and register it with some IntentFilter(Set action in a string value).
private BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(android.content.Context context, Intent intent) {
Toast.makeText(context, "death", Toast.LENGTH_LONG)
.show();
}}
Register in onResume
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("Your Action");
this.registerReceiver(receiver, intentFilter);
And in your service just call setBroadcast
#Override
public void onFinish() {
Intent intent = new Intent();
intent.setAction("YourAction");
sendBroadcast(intent);
stopSelf();
}
You can achieve this in many ways.
A elegant one would be to have a controller class which sends events to your activity.
You could register your Activity as observable in your onResume method and unregister it in the onPause method. Then, send the data from your service to the controller, and it pass the data to your Activity from there. For example:
//Let your activity implement this interface
interface MyObservableActivity{
public receiveData(Data yourData);
}
//Your observer controller
class MyController{
Vector<MyObservableActivity> observedItems;
public void registerObservable(MyObservableActivity a){
if(!observedItems.contains(a))
observedItems.add(a);
}
public void unregisterObservable(MyObservableActivity a){
if(observedItems.contains(a))
observedItems.remove(a);
}
public void sendDataToObservers(Data d){
for(MyObservableActivity a: observedItems){
a.receiveData(d);
}
}
}
So from your service, you should call the sendDataToObservers method and you'll get it from your activity.
How can I use AlarmManager to call a specific method of an Activity, in my case I need to stop a service by calling KillMyServer method of my Activity 2 hours later from know.
I can't use Timer or postDelayed, because if an app goes to background Android may close it after a while, but AlarmManager will survive.
why to use Alarm here? you can stop service by calling stopself() method on Service.
public class MyService extends Service {
public static final String ACTION_START_TIMER = "com.sample.myapp.action.ACTION_START_TIMER";
private TimerReceiver receiver;
#Override
public void onCreate() {
super.onCreate();
receiver = new TimerReceiver();
IntentFilter filter = new IntentFilter(ACTION_START_TIMER);
registerReceiver(receiver, filter);
}
public void runKillTimer() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
stopSelf();
}
}, 2 * 60 * 60 * 1000);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
private class TimerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
runKillTimer();
}
}
}
public class MyActivity extends Activity {
#Override
protected void onStop() {
super.onStop();
Intent intent = new Intent(MyService.ACTION_START_TIMER);
sendBroadcast(intent);
}
}
I need to implement such a procedure:
Start a background service
Update the service with parameters (from UI - user input)
After activity ended the service should keep on running and preform requests to HTTP server every minute. in this stage i still need the parameters I updated in the second stage - I send them to the server.
The service should store the server last response and compere each with the last. if there is a change, notify the user.
Finally, when the activity starts again, the service should update UI with latest the server response.
What I tried:
BroadcastReciver - The problem is after onRecive ended all the arguments which aren't declared as final will wipe out, as well as I didn't found a way to update the Intent being sent automatically every minute.
Service - Using startService() - The problem is when the activity ended the service like stops and starts , flushing all it's arguments. and once again I didn't figured out how to update the arguments after the service is already started.
So how to handle such a situation?
Thanks.
It sounds like what you need to do is to be able to "bind" to your service. What I have posted below is a simple template of how to do that. For your purposes you will need to store variables in your Service class and create getters so that when you re-launch your activity you can get the most up to date variables. Also - please note that I start and stop the Service example below in onResume and onPause. You will no doubt want to do this differently.
//Activity
//Bind to Service Example
public class ExampleActivity extends Activity implements OnClickListener {
// UI
private Button binderButton;
// service
private MyService myService;
private Intent serviceIntent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
// binder button
binderButton = (Button) findViewById(R.id.button1);
binderButton.setOnClickListener(this);
binderButton.setText("start");
serviceIntent = new Intent(this, MyService.class);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
myService = ((MyService.MyBinder) service).getService();
}
#Override
public void onServiceDisconnected(ComponentName name) {
myService = null;
}
};
#Override
protected void onResume() {
super.onResume();
// start the service
startService(serviceIntent);
// bind to the service
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
// call method within the service
myService.doServiceStuff();
break;
}
}
#Override
protected void onPause() {
super.onPause();
stopService(serviceIntent);
unbindService(serviceConnection);
}
}
//Service
public class MyService extends Service {
private final IBinder binder = new MyBinder();
#Override
public IBinder onBind(Intent arg0) {
return binder;
}
public void doServiceStuff() {
task.execute();
}
// create an inner Binder class
public class MyBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
Log.d("yourTag", "long running service task");
return null;
}
};
}
Thanks javaJoe, although your answer didn't solved my problem it gave me some a good ideas.
What I did:
in the Activity onCreate, check if my service is running, if so bind it else, create new one and bind it.
Transferring arguments between the Service and the Activity using setters and getters.
in the Activity onDestroy (the problem was that the service calls self Destory) the Activity sends the final arguments through Intent to a Broadcastreciver. The Broadcastreciver than starts the Service again, initiating it with the correct arguments.
I don't know if this architecture is ideal, i'd like to get some feedback.
Here is the code:
Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Set Service Intent
serviceIntent = new Intent(this, UpdateService.class);
if (isMyServiceRunning()) {
//Bind to the service
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}else{
updateService=new UpdateService();
//Start the service
startService(serviceIntent);
//Bind to the service
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (UpdateService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
updateService = ((UpdateService.MyBinder) service).getService();
//Set Initial Args
updateService.setParams(int arg0);
}
#Override
public void onServiceDisconnected(ComponentName name) {
updateService = null;
}
};
#Override
protected void onDestroy() {
//UnBind from service
unbindService(serviceConnection);
//Stop Service
stopService(serviceIntent);
//Prepare intent to broadcast reciver
Intent intent = new Intent(MainActivity.this,ServiceRunnerBCR.class);
intent.setAction(ServiceRunnerBCR.ACTION_SET_UpdateService);
intent.putExtra(ServiceRunnerBCR.keyVal_arg0, arg0);
intent.putExtra(ServiceRunnerBCR.keyVal_arg1, arg1);
//Send broadcast to start UpdateService after the activity ended
sendBroadcast(intent);
super.onStop();
}
Broadcastreciver:
public class ServiceRunnerBCR extends BroadcastReceiver {
public static final String ACTION_SET_UpdateService = "ACTION_ALARM";
public static final String keyVal_arg0="ARG0";
public static final String keyVal_arg1="ARG1";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_SET_UpdateService)){
updateIntent(context, intent.getDoubleExtra(keyVal_arg0, 0.02), intent.getStringExtra(keyVal_arg1));
}
}
private void updateIntent(Context context, double arg0, String arg1){
Intent intent = new Intent(context,UpdateService.class);
intent.setAction(ACTION_SET_UpdateService);
intent.putExtra(keyVal_arg0, arg0);
intent.putExtra(keyVal_arg1, arg1);
synchronized (this){
try {
this.wait(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
context.startService(intent);
Log.d("OREN","ServiceRunner");
}
}
Service:
public class UpdateService extends Service {
private final IBinder binder = new MyBinder();
public static final String keyVal_arg0="ARG0";
public static final String keyVal_arg1="ARG1";
private Timer timer;
private HTTPHandler http = new HTTPHandler();
private int test=0;
double arg0=0;
String arg1= "";
private TimerTask updateTask = new TimerTask() {
#Override
public void run() {
test++;
Log.d("OREN", "Timer task doing work " + test + " arg0: " + arg0);
//Do some work here
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent!=null){
arg0=intent.getDoubleExtra(keyVal_arg0, 0.002);
arg1=intent.getStringExtra(keyVal_arg1);
timer = new Timer("UpdateTimer");
timer.schedule(updateTask, 1000L, 10 * 1000L);
Log.d("OREN", "ServiceStarted" + test);
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
Log.d("OREN", "OnBind" + test);
return binder;
}
public void setArg0(double d){
arg0=d;
}
// create an inner Binder class
public class MyBinder extends Binder {
public UpdateService getService() {
return UpdateService.this;
}
}
#Override
public void onDestroy() {
Log.d("OREN", "OnDestroy" + test);
super.onDestroy();
}
#Override
public boolean onUnbind(Intent intent) {
Log.d("OREN", "OnUnBind" + test);
return super.onUnbind(intent);
}
}
I have a service and an activity that communicate.
When I click the button(I have galaxy s3 there is only one button) then my activity of course disapear and my service is keep running but if I click the back (touch) button then my service is destroyed.
How can I change that?I want the service to keep running untill the activity destroys it.
EDIT
Here is the code:
Service:
public class MyService extends Service
{
private static final String TAG = "BroadcastService";
public static final String BROADCAST_ACTION = "com.websmithing.broadcasttest.displayevent";
private final Handler handler = new Handler();
private Intent intent;
int counter = 0;
#Override
public void onCreate()
{
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId)
{
// handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, 1000); // 10 seconds
}
};
private void DisplayLoggingInfo() {
intent.putExtra("counter", String.valueOf(++counter));
sendBroadcast(intent);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
}
}
Activity:
public class MainActivity extends Activity {
private static final String TAG = "BroadcastTest";
private Intent intent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, MyService.class);
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(MyService.BROADCAST_ACTION));
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
#Override
public void onDestroy() {
super.onPause();
unregisterReceiver(broadcastReceiver);
stopService(intent);
}
private void updateUI(Intent intent)
{
String counter = intent.getStringExtra("counter");
Log.d(TAG, counter);
TextView txtCounter = (TextView) findViewById(R.id.textView1);
txtCounter.setText(counter);
}
}
you can put your app in the background instead off finishing it.
#Override
public void onBackPressed() {
moveTaskToBack(true);
// super.onBackPressed();
}
Ofcourse your service stops, when you press the back button. The back button most calls finish() on the activity, and it is destroyed. When you press the other button (the home button), it just minimizes your app, and it will be only destroyed later, when the OS wants to free up space.
If you want to keep your service running, make it a foreground service, and dont stop it on activity destroy.