UPDATE:
After adding the suggested methodes (doBindService() and doUnbindService()) along with calls to no avail) From here suggested by #Nick Campion
I've been trying for a while to get this service running but nothing seems to be working - I know I'm probably missing a semicolon or something :)
The program calls startNotificationService(), then the Log shows the log message... and the app continues to run without the Service showing up. I can't find the Service in Advance Task Killer. HELP!!!
XML (In Manifest) :
<service
android:icon="#drawable/icon"
android:label="Smart Spdate Service"
android:name="notifyService">
<intent-filter
android:label="FULL_PATH_NAME_HERE.updateService">
</intent-filter>
</service>
Service Call
Log.v("NOTICE", "Notification Service was not found running - starting");
//startService(new Intent(this, notifyService.class));
startService(new Intent(notifyService.class.getName()));
//startService(new Intent(TweetCollectorService.class.getName()));
/* FROM GOOGLE */
void doBindService() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
this.bindService(new Intent(this, updateService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
/* END OF GOOGLE CODE */
#Override
public void onDestroy() {
web.close();
doUnbindService(); // Added to `onDestroy` - suggested by Google page
super.onDestroy();
Log.v("NOTICE", "PROGRAM TERMINATED");
}
updateService.java
public class updateService extends Service {
private String TAG = "SERVICE";
public static final int INTERVAL = 60000;
private Timer timer = new Timer();
private static updateService Pointer;
public updateService() {
Pointer = updateService.this;
}
public static class LocalBinder extends Binder {
static updateService getService() {
return Pointer;
}
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
if (timer != null) {
timer.cancel();
}
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
doStuff();
}
}, 0, INTERVAL);
super.onStart(intent, startId);
}
public void doStuff() {
Log.v(TAG, "doStuff");
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new LocalBinder();
}
I don't see anywhere where your client binds to your service. Take a look at the local service example.. The reason for using the bind pattern even though you call startService is because the startService call is asynchronous. You need to make an additional call to bind the service to make sure you get a call back once the startup is complete.
I've found that a really great example of a service client and service are available in the NPR Open Source App for you to learn from!
Related
I am working on a wallpaper application in which i am setting a gallery of images on wallpaper with shuffle effect for 5 min, 10 min etc. I am using service for this task. My service works well when app remains in background, but service get stopped when app get stopped.This is my code for service class:
public class WallpaperService extends Service {
ArrayList<String> arrayList;int counter = 0;
boolean serviceStopped;
private IBinder binder = new WallpaperServiceBinder();
public WallpaperService() {
}
private Handler mHandler;
private Runnable updateRunnable = new Runnable() {
#Override
public void run() {
if (serviceStopped == false)
{
createNotificationIcon();
}
queueRunnable();
}
};
public class WallpaperServiceBinder extends Binder {
public WallpaperService getService() {
return WallpaperService.this;
}
}
private void queueRunnable() {
// 600000 : cada 10 minutos, comprueba si hay nuevas notificaciones y actualiza la
// notification BAR
mHandler.postDelayed(updateRunnable, 5000);
}
#Override
public int onStartCommand(Intent intent,int flag, int start_id){
super.onStartCommand(intent,flag,start_id);
arrayList = intent.getStringArrayListExtra("image_url");
return START_STICKY;
}
#Override
public void onRebind(Intent intent) {
Log.v("Service","in onRebind");
super.onRebind(intent);
}
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public void onCreate() {
serviceStopped = false;
mHandler = new Handler();
queueRunnable();
}
#Override
public void onStart(Intent intent, int startid) {
}
public void createNotificationIcon()
{
counter += 1;
Toast.makeText(this, "Hello", Toast.LENGTH_SHORT).show();
Picasso.with(getApplicationContext()).load(arrayList.get(counter)).into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
try {
final WallpaperManager wallpaperManager =
WallpaperManager.getInstance(getApplicationContext());
wallpaperManager.setBitmap(bitmap);
wallpaperManager.suggestDesiredDimensions(1080, 1920);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
//Here you should place a loading gif in the ImageView to
//while image is being obtained.
}
});
}}
This is the code i am using to start service:
Intent intent = new Intent(CategoryActivity.this,WallpaperService.class);
intent.putExtra("image_url",img_urls);
intent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(intent);
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
Have you added these lines in manifest file
<application> <service android:name=".ExampleService" /></application>
Important Fact about the bindService
If a component calls bindService() to create the service and onStartCommand() is not called, the service runs only as long as the component is bound to it. After the service is unbound from all of its clients, the system destroys it.
Try using Started Service
A started service is one that another component starts by calling
startService(), which results in a call to the service's
onStartCommand() method.
When a service is started, it has a lifecycle that's independent of
the component that started it. The service can run in the background
indefinitely, even if the component that started it is destroyed. As
such, the service should stop itself when its job is complete by
calling stopSelf(), or another component can stop it by calling
stopService().
An application component such as an activity can start the service by
calling startService() and passing an Intent that specifies the
service and includes any data for the service to use. The service
receives this Intent in the onStartCommand() method.
Handling onStartCommand
Notice that the onStartCommand() method must return an integer. The
integer is a value that describes how the system should continue the
service in the event that the system kills it. The default
implementation for IntentService handles this for you, but you are
able to modify it. The return value from onStartCommand() must be one
of the following constants:
START_NOT_STICKY If the system kills the service after onStartCommand() returns, do not recreate the service unless there are
pending intents to deliver. This is the safest option to avoid running
your service when not necessary and when your application can simply
restart any unfinished jobs.
START_STICKY If the system kills the service after onStartCommand() returns, recreate the service and call
onStartCommand(), but do not redeliver the last intent. Instead, the
system calls onStartCommand() with a null intent unless there are
pending intents to start the service. In that case, those intents are
delivered. This is suitable for media players (or similar services)
that are not executing commands but are running indefinitely and
waiting for a job.
START_REDELIVER_INTENT If the system kills the service after onStartCommand() returns, recreate the service and call
onStartCommand() with the last intent that was delivered to the
service. Any pending intents are delivered in turn. This is suitable
for services that are actively performing a job that should be
immediately resumed, such as downloading a file.
Note: In your case you should use Started Service and return START_STICKY or START_REDELIVER_INTENT (based on your requirement) in onStartCommand()
Check Official Documentation for detailed description of the Services.
I am Referring this Application https://github.com/hzitoun/android-camera2-secret-picture-taker.
In this Application there are two classes(APictureCapturingService.java & PictureCapturingServiceImpl.java) that takes pictures without preview can these two classes be converted to Background Service that runs always never dies.
Is this possible to have camera capturing process as a background service if yes how to proceed?
I don't know how you are taking picture in your activity but i can guide you to run your app in background even your close your app and you can able to run your camera code in every second..
public class SampleService extends Service {
public SampleService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
#Override
public int onStartCommand(final Intent inten, int flags, int startId) {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
// Make use your method here..
}
});
}
}, 5000, 2000);
return super.onStartCommand(inten, flags, startId);
}
#Override
public void onCreate() {
super.onCreate();
}}
And you need to start the service form activity..
startService(new Intent(this, SampleService.class));
I have used this for monitoring the foreground app it will work..
I am not sure if I have this right or not, but I have some code that I need to run in the background of my android application, and once that is complete, I would like to wait 10 seconds, and then run the code again.
I currently have this working, but I am sure it ain't the right way to go about it and wondered if someone can give me a simple example, or tell me what I need to change to make this "the right way" to do it.
First I have my ScheduleService.java file. This is where my code that I want to run it, and as you can see, once it is finished, it puts the thread to sleep for 10 seconds and then calls itself again, but this means that the code never actually completes (you should see the length of the stack trace if I get an error!)
ScheduleService.java
public class ScheduleService extends Service {
private static final String TAG = "ScheduleService";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
startJob();
}
});
t.start();
return Service.START_STICKY;
}
private void startJob(){
// all my code is here, and i do what i need
// job completed. Rest for 10 seconds before doing another one
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//do job again
startJob();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy(){
super.onDestroy();
}
}
Now to start the service code, I have the following when my application starts (in my MainActivity.java file)
// stop just encase its already started
context.stopService(new Intent(context, ScheduleService.class));
// start service
context.startService(new Intent(context, ScheduleService.class));
In order to make sure that the service is started when the device restarts, I also have my StartOnBootReciever.java code
public class StartOnBootReciever extends BroadcastReceiver {
private static final String TAG = "Autostart";
/**
* Listens for Android's BOOT_COMPLETED broadcast and then executes
* the onReceive() method.
*/
#Override
public void onReceive(Context context, Intent arg1) {
Log.d(TAG, "BOOT_COMPLETED broadcast received. Executing starter service.");
// upload in background
Intent intent = new Intent(context, ScheduleService.class);
context.startService(intent);
// This code will start the application once the device has been restarted
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
Then in my AndroidManifest.xml file, I have the following
<receiver android:enabled="true" android:exported="true" android:name="StartOnBootReciever" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:enabled="true" android:exported="false" android:name="com.idamigo.ticketmachine.ScheduleService" />
This all works, but I feel that have code that is self-calling, and "never ending"
In your Service, you have used Thread.Sleep which is unnecessary. Because Service will run continuously in the background until you stop it or System stops it.
Example:
public class ScheduleService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Timer timer = new Timer();
timer.schedule(task,1,10000);
return Service.START_STICKY;
}
TimerTask task= new TimerTask() {
#Override
public void run() {
//do your task here.
}
};
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Go for Service only if you need to run a task continuously in the background. Otherwise, use IntentService. IntentService will be stopped when there is no work for it so you don't need to manage its state by yourself.
i just use service to make something like chathead and this is my result
but only i have two problem
first some time my service killed i notice that's on weak device so how can i prevent it from killed in same time the facebook messenger never killed
second my class animation not smooth i think i must run the class on new thread
xxx = new classanimation (mContext);
i tried this
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
xxx = new classanimation (mContext);
}
});
but i see it same no different
and this is my service code
public class MyCustomService extends Service {
private volatile HandlerThread mHandlerThread;
private ServiceHandler mServiceHandler;
private static Context mContext;
Handler mHandler;
IBinder mBinder = new LocalBinder();
public static Socket client;
public classanimation xxx;
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public class LocalBinder extends Binder {
public MyCustomService getServerInstance() {
return MyCustomService.this;
}
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
// Define how to handle any incoming messages here
#Override
public void handleMessage(Message message) {
// ...
// When needed, stop the service with
// stopSelf();
}
}
public void onCreate() {
super.onCreate();
this.mContext = this;
xxx= new classanimation(mContext); //class i run it but its not smooth
mHandler = new Handler(Looper.getMainLooper());
// An Android handler thread internally operates on a looper.
mHandlerThread = new HandlerThread("MyCustomService.HandlerThread");
mHandlerThread.start();
// An Android service handler is a handler running on a specific background thread.
mServiceHandler = new ServiceHandler(mHandlerThread.getLooper());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Send empty message to background thread
mServiceHandler.sendEmptyMessageDelayed(0, 500);
// or run code in background
mServiceHandler.post(new Runnable() {
#Override
public void run() {
// Do something here in background!
SessionManager session = new SessionManager(mContext);
// If desired, stop the service
//stopSelf();
}
});
// Keep service around "sticky"
return START_STICKY;
}
#Override
public void onDestroy() {
// Cleanup service before destruction
mHandlerThread.quit();
}
}
To ensure that your service is never killed, you can make your service a foreground service by using a notifiaction. This means that there will always be a notification icon when the service is running, but it will never be killed. For example :
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
You can't prevent from killing,Yes but you can minimize probability of killing by starting service in different process than your app process.
Please see edits before answering!
I have an app which contains a BackgroundService class:
public class BackgroundService extends Service {
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter();
filter.addAction("com.spotify.music.playbackstatechanged");
filter.addAction("com.spotify.music.metadatachanged");
filter.addAction("com.spotify.music.queuechanged");
registerReceiver(receiver, filter);
Log.e("Playing:", "APP IS PLAYING");
Notification notification = new Notification();
startForeground(1, notification);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long timeSentInMs = intent.getLongExtra("timeSent", 0L);
String action = intent.getAction();
if (action.equals(BroadcastTypes.METADATA_CHANGED)) {
String trackId = intent.getStringExtra("id");
String artistName = intent.getStringExtra("artist");
String albumName = intent.getStringExtra("album");
String trackName = intent.getStringExtra("track");
int trackLengthInSec = intent.getIntExtra("length", 0);
// Do something with extracted information...
} else if (action.equals(BroadcastTypes.PLAYBACK_STATE_CHANGED)) {
boolean playing = intent.getBooleanExtra("playing", false);
Log.e("Playing:","TRUE");
}
}
};
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
static final class BroadcastTypes {
static final String SPOTIFY_PACKAGE = "com.spotify.music";
static final String PLAYBACK_STATE_CHANGED = SPOTIFY_PACKAGE + ".playbackstatechanged";
static final String METADATA_CHANGED = SPOTIFY_PACKAGE + ".metadatachanged";
}
}
and this is declared in my manifest:
<service
android:name=".BackgroundService"
android:enabled="true" >
<intent-filter>
<action android:name="com.spotify.music.playbackstatechanged" />
<action android:name="com.spotify.music.metadatachanged" />
<action android:name="com.spotify.music.queuechanged" />
</intent-filter>
</service>
So essentially my objective is to have my BackgroundService initialized when my app is opened, and to have it continue to run in the Background doing whatever I need it to do. As of now, I am using logs to determine whether my "setup" is working, but when I run my app, I am unable to see an logs even after I tested all actions that should have triggered my BroadCastReceiver. Furthermore, my persistent notification should have changed had my service been running, but it does not...
Edit::
So, I added logs to my BackgroundService's onCreate() and onReceive() methods, however, neither seem to be appearing. Im wondering, do I need to do something in my launcher activity to initialize the service? Furthermore, no notification is shown so I assume the Service is not being started for some reason...
Latest Edit:
So I added the following code to my Main activity to see if it would make a difference:
startService(new Intent(this,BackgroundService.class));
And after debugging my app, I began to see the following error:
java.lang.RuntimeException: Unable to create service com.aurum.mutify.BackgroundService: java.lang.SecurityException: Isolated process not allowed to call registerReceiver
pointing to my BroadCast Receiver class.
Intent services are designed for short tasks. And your intent handling method is empty.
If you need long running task in the background use standard service and call start foreground. This will minimize chance of system destroying your service.
To learn more go here
EDIT
Try overriding onStartCommand method. this method is called when service is started and usually you do all stuff here. Remember that there are 3 options to return.
Edit 2:
try something like this
in on create
PendingIntent pi;
BroadcastReceiver br;
Intent myIntent;
#Override
public void onCreate()
{
super.onCreate();
myIntent = new Intent("something")
if(Build.Version.SDK_INT >= 16) //The flag we used here was only added at API 16
myIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//use myIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); if you want to add more than one flag to this intent;
pi = PendingIntent.getBroadcast(context, 1, myIntent, 0);
br = new BroadcastReceiver ()
{
public void onReceive (Context context, Intent i) {
new thread(new Runnable()
{
public void run()
{
//do something
}
}).start();
}
};
And then in on start command
this.registerReceiver(br, new IntentFilter("something"));