I'm trying to call a service class to update the value of a variable from my widget but it doesn't ever seem to get to the service class. I've had a look at some examples and I can't figure out what I'm doing wrong, and I don't really know very much about services yet. All help appreciated.
Service class
public class toggleMonitoringService extends Service{
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate()
{
Log.d("Me","creating service");
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int startId, int something) {
// TODO Auto-generated method stub
String toggle = intent.getExtras().getString("Toggle");
Log.d("Me","Toggle : " + toggle);
if (toggle.equals("app1"))
{
UpdateWidgetService.monitorApp1 = !UpdateWidgetService.monitorApp1;
}
else if (toggle.equals("app2"))
{
UpdateWidgetService.monitorApp2 = !UpdateWidgetService.monitorApp2;
}
super.onStartCommand(intent, startId, something);
return 0;
}
}
Where I set up the intent and pending intent to handle the button click from the widget
Intent monitor1toggle = new Intent(this.getApplicationContext(),toggleMonitoringService.class);
monitor1toggle.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
monitor1toggle.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,allWidgetIds);
monitor1toggle.putExtra("Toggle","app1");
PendingIntent monitor1 = PendingIntent.getService(getApplicationContext(), 0 , monitor1toggle,0);
remoteViews.setOnClickPendingIntent(R.id.firstappstatus, monitor1);
Try start service manually, wihtout using PendingIntent.
Better way is not to start service each time you need to do something, but to start it once, bind to it and use common method calls when you need something from the service.
For your example even a simple Thread would be more appropriate.
Related
I have seen the default behaviour of many services, that they are restarted when killed by system or user.
Is it possible that if my service is killed or crashed the android device is rebooted instead of my service itself being restarted.
If so, then have android provided some mechanism that we can use to achieve the above.
First of all, it is really very bad pattern to reboot device on service destroy.
Anyways, you can achieve this using below code
public class demoService extends Service
{
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
}
#Override
public void onDestroy() {
super.onDestroy();
// this won't restart your phone instead it will ask for action
Intent i = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN");
i.putExtra("android.intent.extra.KEY_CONFIRM", true);
startActivity(i);
}
}
Simply, I want to upload files over the net using a service.
I have created a service with both: binding and startService. I create a foreground service that displays the progress.
The issue is, after the upload is complete, I call stopForeground(true) and then stopSelf but the notification is not removed and (probably) the service is not killed.
Code of the service class:
public class UploaderService extends Service {
// ...
public void finishUpload(File audioFile, File eventsData) {
LogWrapper.d(TAG, "finishUpload");
mUploadHelper.upload(audioFile, eventsData)
// consider this just a callback:
.subscribe(uuid -> {
// Log is printed but service is not stopped
LogWrapper.d(TAG, "finishUpload.subscribe");
stopForeground(true);
stopSelf();
}, LogWrapper::fatalError);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
NotificationCompat.Builder builder = NotificationsManager.getDefaultBuilder(this)
.setProgress(0, 0, true)
.setContentText(intent.getStringExtra(EXTRA_TOPIC_NAME))
.setContentTitle("Uploading data to server");
// first creating a notification with uuid,
// after POST /post call, post.uid will be used.
startForeground(DEAFULT_NOTIFICATION_ID, builder.build());
return START_REDELIVER_INTENT;
}
#Override
public IBinder onBind(Intent intent) {
LogWrapper.d(TAG, "onBind " + intent);
return mUploaderBinder;
}
#Override
public boolean onUnbind(Intent intent) {
LogWrapper.d(TAG, "onUnbind " + intent);
intent.putExtra(EXTRA_TOPIC_NAME, mUploadHelper.getTopic().name);
startService(intent);
return false;
}
#Override
public void onCreate() {
super.onCreate();
mUploaderBinder = new UploaderBinder();
}
public class UploaderBinder extends Binder {
public UploaderService getService() {
return UploaderService.this;
}
}
}
Though I could not find it in docs, the startService command should be called from outside the service i.e. from an Activity. I called it from my activity just before binding to it and it worked as expected.
I was probably experiencing an undefined behavior- the service was starting but not stopping. I wish someone could give me a better explanation of why that was happening, and that this indeed is the correct way to do stuff.
Great thanks to #pskink for pointing me in the right direction.
I intended to work like this:
user switches on a feature: let say weather.
now weather data will come from server every 6 hours and will be shown to widget(remoteview), Now user switches off the feature. then widget should not show the weather or even refresh the data every 6 hours.
there are also 3-4 more features like that.
Now i had created a service to get all required data and than i have passed them to remoteview. For starting service i had used this in TimeOut Activity:
i = new Intent(TimeOut.this, TimeService.class);
i.setAction("com.example.Weather.Idle");
startService(i);
same for stopping service in switch off code:
stopService(i)
This code was working fine in API <=19. But in Lollipop it crashes at starting or stoping service.
I searched a lot in SO and also tried code for Binding or unbinding service but didn't help any.
Please help me with some code rather than just links...
Thanks in advance :)
Starting a service from any activity class
Intent intent = new Intent(MainActivity.this, BackgroundService.class);
startService(intent);
Here is service class code
public class BackgroundService extends Service{
public static Context appContext = null;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
if (appContext == null) {
appContext = getBaseContext();
}
Toast.makeText(appContext, "Services Started", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
Add your logic here. You can do some work here using a thread. You can stop service whenever you want and i hope you will not find any crash.
I have faced similar issue with Service in 5.0. This is probably not the correct answer, but it works. You could try. I use EventBus to communicate with my services. So when I want to stop the service I'd send,
EventBus.getDefault().post(new ServiceEvent(ServiceEvent.STOP_SERVICE));
In the service,
public void onEvent(ServiceEvent event) {
if (event.getEvent() == ServiceEvent.STOP_SERVICE) {
methodToStopService();
}
}
private void methodToStopService() {
// do some stuff
stopSelf();
}
Make sure you register your service for events.
private void registerEventBus() {
EventBus eventBus = EventBus.getDefault();
if (!eventBus.isRegistered(this)) {
eventBus.register(this);
}
}
ServiceEvent class - It's my own class which I use with EventBus.
public class ServiceEvent {
private int event;
public static final int STOP_SERVICE = -1;
public ServiceEvent(int event) {
this.event = event;
}
public int getEvent() {
return event;
}
}
I am implementing in my Android app a splash screen which:
dowloads a sqlite database from a server
loads urls to get JSONs
creates a sqlite database in the device and execute several queries
I am using AsyncTask to do everything, my problem will occur if the user close the app in the middle of the process or turn off the device because the app:
could be creating a database or executing crucial queries in the device
could be downloading the sqlite db from a server
could be running several important process
etc
Definitely, the entire process (3-5 seconds) is important.
So... How could I avoid this? should I use handlers, loaders, on-(pause, stop, destroy) methods in order to get my objective? Can you give me an example?
As mentioned in the comment above, you should use a service as their lifecycle is separate to that of the activity.
Create the service like so:
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Do everything you need to here, then call stop:
Log.d("DEBUG", "Started...");
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
Intent intent = new Intent("com.example.androidexample.SERVICE_STOPPING");
sendBroadcast(intent);
super.onDestroy();
}
}
Then in the activity:
public class MainActivity extends Activity {
private ServiceCompleteReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter;
receiver = new ServiceCompleteReceiver();
filter = new IntentFilter("com.example.androidexample.SERVICE_STOPPING");
startService(new Intent(this, MyService.class));
registerReceiver(receiver, filter);
}
public class ServiceCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do whatever needs to be done here
unregisterReceiver(receiver);
}
}
}
EDIT :
Don't forget to add it to your manifest as well
<service
android:name="com.example.androidexample.MyService"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
</service>
I am trying to run a service, whem i stop my app that service still run means it's continuing its task. What is the way to stop service when we stop our app? Plese help me how can i stop this service. One more thing is also there if i use intent in this class to move back to that class from where service is calling i moved back but when i press back button on emulator to go back then it display that service screen also.
I am showing the code of service class
public class SetMovableBG_Inbuilt_SetImage extends Service
{
Timer mytimer;
int interval = 2000;
int interval1 = 4000;
Drawable drawable;
WallpaperManager wpm;
int prev = 0;
int numImage;
private ArrayList<Integer> imgId;
#Override
public void onCreate()
{
super.onCreate();
mytimer = new Timer();
wpm = WallpaperManager.getInstance(this);
}
// here i am geting intent from the class from where i am calling this class.
//everything works fine but service not stops even after stop the app
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
imgId = intent.getIntegerArrayListExtra("ImgId");
numImage = imgId.size();
mytimer.schedule(new TimerTask()
{
#Override
public void run()
{
// TODO Auto-generated method stub
if ( prev >= numImage )
{
prev = 0;
}
try
{
wpm.setResource(imgId.get(prev));
}
catch ( IOException e )
{
e.printStackTrace();
}
prev++;
}
}, interval, interval1);
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
}
you can use Service.stopService method to stop the service from other component like activities. You can use Service.stopSelf method to stop the service from the service itself. according to doc
A started service must manage its own lifecycle. That is, the system
does not stop or destroy the service unless it must recover system
memory and the service continues to run after onStartCommand()
returns. So, the service must stop itself by calling stopSelf() or
another component can stop it by calling stopService().
To know more about Services see here