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.
Related
Here I attached my code,I created a service which runs both cases while my app is in background and killed state. It is not running on android marshmallow devices, but it works on other devices. When I check other devices, Log will be executed when the app is kill state, only version 6 , not executed.
public class SensorService extends Service {
public int counter=0;
public SensorService(Context applicationContext) {
super();
Log.e("HERE", "here I am!");
}
public SensorService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
When comes to destroy again I will call the service, It will go to broadcast receive, and then start service function will call.
#Override
public void onDestroy() {
super.onDestroy();
Log.e("EXIT", "ondestroy!");
Intent broadcastIntent = new Intent("sales.com.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
stoptimertask();
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
timer = new Timer();
initializeTimerTask();
timer.schedule(timerTask, 1000, 1000); //
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
Log.e("in timer", "in timer ++++ "+ (counter++));
}
};
}
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
Below code for Broadcast Receiver code : app works, when i click back button, if the app was killed state, it is not working, other devices services running.
public class SensorRestarterBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e(SensorRestarterBroadcastReceiver.class.getSimpleName(), "Service Stops! Oooooooooooooppppssssss!!!!");
// context.startService(new Intent(context, SensorService.class));
Intent i = new Intent(context, SensorService.class);
context.startService(i);
}
}
I have seen many posts in SO regarding this but could not get the exact and most easy way to call an activity method from service class. Is broadcast receiver only the option? No easy way out ? I just need to call the following method in Activity class after the media player is prepared in Service class .
Activity class:
public void updateProgress() {
// set Progress bar values
songProgressBar.setProgress(0);
songProgressBar.setMax(100);
// Updating progress bar
updateProgressBar();
}
Service class:
#Override
public IBinder onBind(Intent intent) {
Log.d(this.getClass().getName(), "BIND");
return musicBind;
}
#Override
public boolean onUnbind(Intent intent) {
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
try {
mp.start();
} catch (IllegalStateException e) {
e.printStackTrace();
}
// updateProgress();// Need to call the Activity method here
}
Define an interface your Service will use to communicate events:
public interface ServiceCallbacks {
void doSomething();
}
Write your Service class. Your Activity will bind to this service, so follow the sample shown here. In addition, we will add a method to set the ServiceCallbacks.
public class MyService extends Service {
// Binder given to clients
private final IBinder binder = new LocalBinder();
// Registered callbacks
private ServiceCallbacks serviceCallbacks;
// Class used for the client Binder.
public class LocalBinder extends Binder {
MyService getService() {
// Return this instance of MyService so clients can call public methods
return MyService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return binder;
}
public void setCallbacks(ServiceCallbacks callbacks) {
serviceCallbacks = callbacks;
}
}
Write your Activity class following the same guide, but also make it implement your ServiceCallbacks interface. When you bind/unbind from the Service, you will register/unregister it by calling setCallbacks on the Service.
public class MyActivity extends Activity implements ServiceCallbacks {
private MyService myService;
private boolean bound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(...);
}
#Override
protected void onStart() {
super.onStart();
// bind to Service
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from service
if (bound) {
myService.setCallbacks(null); // unregister
unbindService(serviceConnection);
bound = false;
}
}
/** Callbacks for service binding, passed to bindService() */
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
// cast the IBinder and get MyService instance
LocalBinder binder = (LocalBinder) service;
myService = binder.getService();
bound = true;
myService.setCallbacks(MyActivity.this); // register
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
bound = false;
}
};
/* Defined by ServiceCallbacks interface */
#Override
public void doSomething() {
...
}
}
Now when your service wants to communicate back to the activity, just call one of the interface methods from earlier. Inside your service:
if (serviceCallbacks != null) {
serviceCallbacks.doSomething();
}
Use Broadcast receiver with service for updating your view from the service class.
For example:
In my activity class
public class ServiceDemoActivity extends Activity {
Intent intent;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView notification = (TextView) findViewById(R.id.notification);
if (CheckIfServiceIsRunning()) {
} else {
startService(new Intent(this, MyService.class));
}
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateDate(intent);
}
};
private void updateDate(Intent intent) {
String time = intent.getStringExtra("time");
Toast.makeText(getApplicationContext(), "Yea!!! Service called", Toast.LENGTH_SHORT).show();
TextView date = (TextView) findViewById(R.id.date);
date.setText(time);
}
#Override
public void onResume() {
super.onResume();
registerReceiver(broadcastReceiver, new IntentFilter(
MyService.BROADCAST_ACTION));
}
}
And in my service class I am calling my update ui after a few interval of time which updates my UI.
public class MyService extends Service {
public static final String
BROADCAST_ACTION = "com.mukesh.service";
private final Handler handler = new Handler();
#Override
public void onCreate() {
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onDestroy() {
stopService(intent);
}
#Override
public void onStart(Intent intent, int startid) {
int i = 0;
while (i <= 2) {
if (i > 1) {
i++;
this.onDestroy();
} else {
counter = i;
i++;
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1 * 1000); // 1 sec
}
}
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, 7 * 1000); // 7 sec
}
};
private void DisplayLoggingInfo() {
intent.putExtra("time", new Date().toLocaleString());
intent.putExtra("counter", String.valueOf(counter));
sendBroadcast(intent);
stopService(intent);
}
}
For complete code check this link
I created a general class called Delegate (it's not a special name, you can name it John) and passed MainActivity class into it as a static field. Then I can access it from the service since its global now. I am not sure if it is cost-effective but it solved the problem for me simple.
My service:
package com.some.package;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class FirebaseInstanceIDService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
Delegate.theMainActivity.onDeviceTokenChange(token);
}
}
Delegate class:
package com.some.package;
public class Delegate {
static MainActivity theMainActivity;
}
What I did in MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Delegate.theMainActivity = this;
//rest of the code...
}
public void onDeviceTokenChange(String token){
Log.e("updated token:", token);
}
You can't call your sevices method direcly from your activity or vise versa. There are 3 ways to communicate with a service; using broadcasters and receivers, using Messenger or binding to the service. For further information look at http://developer.android.com/guide/components/bound-services.html
You can call from your service
getContentResolver().notifyChange(uri, null);
and in your activity you set up a
getContentResolver().registerContentObserver(uri, false, new ContentObserver(getHandler())
{
public void onChange(boolean selfChange)
{
updateProgress()
}
};
the onChange method will ba called on the UI thread
You can call a method of activity from service by implementing your own listener like this
https://stackoverflow.com/a/18585247/5361964
You might consider running your activity method in runOnUiThread like this:
// method will be called from service
override fun callback(activity: Activity, result: String) {
runOnUiThread{
Toast.makeText(activity, result, Toast.LENGTH_LONG).show()
}
}
I would prefer to use some very easy and cleaner solution provided by
EventBus
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);
}
}
For a demo I print a Toast after Evert 10 sec. using Service class.
It works fine, I'm getting the Toast after every 10 sec if I am on the Activity when I leave the app, Service is not giving the o/p.
But I want to that toast either I'll kill the App or back press Here is code snippet :
ServiceDemo.java
public class ServiceDemo extends Activity {
private Handler myHandler = new Handler();
private Runnable drawRunnable = new Runnable() {
#Override
public void run() {
as();
myHandler.postDelayed(this, 10000);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_demo);
myHandler.postDelayed(drawRunnable, 10000);
startService(new Intent(this, MyService.class));
}
public void as(){
startService(new Intent(this, MyService.class));
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
}
Service.java
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "HOHO Service Created...", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "Service Started...", Toast.LENGTH_LONG).show();
}
}
Edit 1
moveTaskToBack(true);
I put this into the onBackPressed method I Service give the o/p if I am not on the screen but When I kill the App, Service not responding
I think you need to override onStartCommand instead of onStart()
like:
public int onStartCommand(Intent intent, int flags, int startid)
{
Toast.makeText(this, "Service Started...", Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}
i think AlarmManager is what you want.
You have to user AlarmManager, here's an example : Alarm Manager Example
Your task will be executed even if the application is terminated.
But if the application is killed by the user, the Alarm will be canceled. See this discussion How to create a persistent AlarmManager
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