I need to start a service and end it under some condition. I previously used IntentService which I found to be incorrect for the purpose(if I am right). I have started using service with BroadcastReciever. But still can't get the desired result. I may elaborate or even paste my code if needed. But for now, I just need something like a flow chart or pseudocode.
The condition would be checked from Preference settings. If checked, I would like to run the service in background else stop the service. Please, can any one out here help me.
EDITED:
My MainActivity:
public class MainActivity extends ListActivity {
private LocalWorldService s;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(this, LocalWorldService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onPause() {
super.onPause();
unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
LocalWorldService.MyBinder b = (LocalWorldService.MyBinder) binder;
s = b.getService();
Toast.makeText(MainActivity.this, "Connected", Toast.LENGTH_SHORT)
.show();
}
public void onServiceDisconnected(ComponentName className) {
s = null;
Toast.makeText(MainActivity.this, "Disconnected", Toast.LENGTH_SHORT)
.show();
}
};
My Service:
public class LocalWorldService extends Service {
private final IBinder mBinder = new MyBinder();
private ArrayList<String> list = new ArrayList<String>();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "Magnet is on", Toast.LENGTH_LONG).show();
return Service.START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mBinder;
}
public class MyBinder extends Binder{
LocalWorldService getService(){
return LocalWorldService.this;
}
}
public List<String> getWordList(){
return list;
}
Following are two class for BroadCastReceiver:
public class MyScheduleReceiver extends BroadcastReceiver{
private static final long REPEAT_TIME = 15 * 1000;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyStartServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast( context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 15);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), REPEAT_TIME, pending);
}
And:
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent service = new Intent(context, LocalWorldService.class);
SharedPreferences pref = PreferenceManager
.getDefaultSharedPreferences(context);
Map<String, ?> x = pref.getAll();
boolean momoMagnetIsOn = (Boolean) x.get("key_momo_magnet");
if (momoMagnetIsOn){
context.startService(service);
}
else{
context.stopService(service);
}
}
CORRECTION:
I need to override onDestroy().
override onDestroy method in Service
When ever you want to start a service all you need is
startService(new Intent(this, MainService.class));
And to Stop a service anytime just call
stopService(new Intent(this, MainService.class));
Remember service needs to be declared in AndroidManifest.xml. As you said that your service is working. I'm sure you have done that. Still AndroidManifest.xml
<service android:enabled="true" android:name=".MainService" />
Related
I made an service that triggers every 10 sec. How to connect service to activity when it triggers. Example i refresh my local DB, when appears an update Activity send an Toast.
AlarmService.class
#SuppressLint("SimpleDateFormat")
public class AlarmService extends Service {
Handler mHandler;
private PendingIntent pendingIntent;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
}
public void f() {
Toast t = Toast.makeText(this, "Service is still running",
Toast.LENGTH_SHORT);
t.show();
}
#Override
#Deprecated
public void onStart(Intent intent, int startId) {
Toast t = Toast.makeText(this, "Service started", Toast.LENGTH_SHORT);
t.show();
// TODO Auto-generated method stub
super.onStart(intent, startId);
mHandler = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
f();
mHandler.postDelayed(this,10000);
}
};
mHandler.postDelayed(r, 10000);
}
}
MainActivity.class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent serviceIntent = new Intent(this,AlarmService.class);
startService(serviceIntent);
}
}
Use broadcast receiver like this
public static class MyExtBroadcastReceiver extends BroadcastReceiver {
public MyExtBroadcastReceiver() {
super();
}
#Override
public void onReceive(Context context, Intent intent) {
//Call your activity here
}
Make a method for setting the alarm
public void setAlarm(){
f(); // call your method f() here
AlarmManager am=(AlarmManager)getSystemService(ALARM_SERVICE);
Intent alarmintent1 = new Intent(this, MyExtBroadcastReceiver.class);
PendingIntent sender1=PendingIntent.getBroadcast(this, 100, alarmintent1, PendingIntent.FLAG_UPDATE_CURRENT | Intent.FILL_IN_DATA);
try {
am.cancel(sender1);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("ex....."+e);
}
Calendar cal=Calendar.getInstance();
cal.add(Calendar.Seconds,10);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000*10*60, sender1);
Call this method from OnCreate()
#Override
public void onCreate() {
setAlarm();
}
}
You can use LocalBroadcastManager, Messenger, ResultReceiver to send data from service to Activity.
Here is an example that uses ResultReceiver to send updated data from Service to Activity.
public class myserveclass extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
#Override
public void onCreate() {
super.onCreate();
}
}
.
public class MainActivity extends ActionBarActivity {
CheckinternetConnection internet;
TextView textview;
int tempint = 100;
private static final long REPEAT_TIME = 1000 * 5;
private PendingIntent pendingIntent;
Button button1;
Button button2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview = (TextView) findViewById(R.id.textview);
internet = new CheckinternetConnection();
schedueService();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(internet, filter);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
unregisterReceiver(internet);
}
class CheckinternetConnection extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (Utils.isNetworkAvailable(MainActivity.this)) {
textview.setVisibility(View.GONE);
startService(new Intent(getBaseContext(), myserveclass.class));
} else {
textview.setVisibility(View.VISIBLE);
textview.setText("It Seems Internet Connection is off");
stopService(new Intent(getBaseContext(), myserveclass.class));
}
}
}
public void schedueService() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(MainActivity.this, myserveclass.class);
PendingIntent pintent = PendingIntent.getService(MainActivity.this, 0,
intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
1000 * 10, pintent);
}
}
this is my code for start service and stop service am able to start service when app is connected with internet and stop when internet is off but after 10 second again service becomes start please check my issue where am doing wrong i have used alarm manger please check please suggest me where am doing wrong .
You need to CANCEL the alarm to stop the service
Intent intent = new Intent(MainActivity.this, myserveclass.class);
PendingIntent pintent = PendingIntent.getService(MainActivity.this, 0,
intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pintent);
Hope it helps ツ
I have defined REPEAT_TIME = 15 * 1000; but the message is displayed in 3 seconds or so.
My MainActivity:
public class MainActivity extends ListActivity {
private LocalWorldService s;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(this, LocalWorldService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onPause() {
super.onPause();
unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
LocalWorldService.MyBinder b = (LocalWorldService.MyBinder) binder;
s = b.getService();
Toast.makeText(MainActivity.this, "Connected", Toast.LENGTH_SHORT)
.show();
}
public void onServiceDisconnected(ComponentName className) {
s = null;
Toast.makeText(MainActivity.this, "Disconnected", Toast.LENGTH_SHORT)
.show();
}
};
My Service:
public class LocalWorldService extends Service {
private final IBinder mBinder = new MyBinder();
private ArrayList<String> list = new ArrayList<String>();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
system.out.println("Message");
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("On destroy used");
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mBinder;
}
public class MyBinder extends Binder{
LocalWorldService getService(){
return LocalWorldService.this;
}
}
public List<String> getWordList(){
return list;
}
Following are two class for BroadCastReceiver:
public class MyScheduleReceiver extends BroadcastReceiver{
private static final long REPEAT_TIME = 15 * 1000;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyStartServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast( context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 15);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), REPEAT_TIME, pending);
}
And:
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent service = new Intent(context, LocalWorldService.class);
SharedPreferences pref = PreferenceManager
.getDefaultSharedPreferences(context);
Map<String, ?> x = pref.getAll();
boolean momoMagnetIsOn = (Boolean) x.get("key_momo_magnet");
if (momoMagnetIsOn){
context.startService(service);
}
else{
context.stopService(service);
}
}
Umm, did you notice that you actually tell it to be inexact? You should use setExact()
OK I got it myself. Because I am following this
I don't even know why to restart the system. But restarting the system changed the time interval.I previously had restarted phone with REPEAT_TIME = 3 * 1000 and thus message being displayed every 3 seconds. Any explanation would be welcomed. I am new to this topic. Thank you..
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);
}
}
Below is my code which is working very fine. I am calling service after 10 seconds on click of button using Alarm Manager. I want to automate this process say every 10 minutes it should trigger on its own and call service irrespective of device in SCREEN_OFF or SCREEN_ON. Currently i also suspect call is from "Activity" due to which if I close the application it would not trigger.
/*MainActivity.java*/
package com.example.alarmservice;
public class MainActivity extends Activity implements OnClickListener{
final static private long ONE_SECOND = 1000;
final static private long TEN_SECONDS = ONE_SECOND * 10;
PendingIntent pi;
BroadcastReceiver br;
AlarmManager am;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setup();
findViewById(R.id.the_button).setOnClickListener(this);
}
private void setup() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent i) {
Toast.makeText(c, "Rise and Shine!", Toast.LENGTH_LONG).show();
}
};
registerReceiver(br, new IntentFilter("com.example.alarmservice"));
//pi = PendingIntent.getBroadcast( this, 0, new Intent("com.authorwjf.wakeywakey"),0);
//am = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
Intent intent = new Intent(MainActivity.this, ServiceClass.class);
pi = PendingIntent.getService(MainActivity.this, 0, intent, 0);
am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
am.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + TEN_SECONDS, pi);
}
#Override
protected void onDestroy() {
am.cancel(pi);
unregisterReceiver(br);
super.onDestroy();
}
}
Service Class
/*ServiceClass.java*/
package com.example.alarmservice;
public class ServiceClass extends Service {
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d("Testing", "Service got created");
Toast.makeText(this, "ServiceClass.onCreate()", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Toast.makeText(this, "ServiceClass.onStart()", Toast.LENGTH_LONG).show();
Log.d("Testing", "Service got started");
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}