The title may seem duplicate but the question not about how to make the request, im sending a HTTP Get request from my android application to a web server after a specified interval using a service, the problem is it is stopped after i perform any other action on the device like play a video. The service looks like
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final Context ctx=this;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//perform GET here
}, 0, 5000);
return Service.START_STICKY;
}
any idea why such behaviour im experiencing even though im returning the Service.START_STICKY
Regards.
As mentioned in comment you can take the approach of PendingIntents and BroadcastReceiver in which you can leave a pending intent at specified time and register a receiver and in onreceive you can perform you operation whether to start service or hit a werbservice.
Please go through http://code.tutsplus.com/tutorials/android-fundamentals-scheduling-recurring-tasks--mobile-5788
also http://www.sitepoint.com/scheduling-background-tasks-android/ for better understanding
Try running your service in the 'foreground'. This way it is less likely to get killed.
Check out: http://developer.android.com/guide/components/services.html#Foreground
Related
I have an android app and a server application written in Java. I basically want the app to connect to the server every few seconds to get the newest information, and if neccessary display a push notification, like a Messenger App. I'm new to this, and I've tried multiple ways, but nothing of what I tried seems to work.
I've used a Service which connects to the server every X seconds and gets the newest information from it. The service restarts when It gets destroyed, so it even runs in the background when the app is terminated, but after a while it just stops working and doesn't restart with the error message Not allowed to start service Intent {snip}: app is in background. I have no idea if this approach is even a good idea, and I've tried some other things too, but I don't get anywhere, so any advice on how an application like this should be done would be really helpful!
This is my Service class:
public int counter=0;
public ConnectionService(Context applicationContext) {
super();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Intent broadcastIntent = new Intent(this, BootBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
stoptimertask();
}
private Timer timer;
private TimerTask timerTask;
public void startTimer() {
timer = new Timer();
initializeTimerTask();
timer.schedule(timerTask, 1000, 1000); //
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
counter++;
ConnectionManager.oneWayCall(new DebugPacket("Debug Packet: " + counter));
}
};
}
I don't neccessarily need help with this exact code, if apps like these should be done in a completely different way, please point me into the right direction.
now you can not run services in background forever . system will terminate it after sometime even if you use foreground service.
instead of fetching data every x seconds i would recommend ask your backend guy to send data in fcm notification if data is not large.
if you can wait for 15 minutes for fetching new data you can use workmanager.
there is one ugly way of keeping services alive for longer time i will suggest not to use it .
you can start service every x seconds when you receive notification your app is considered in foreground when you receive notification in this window you can start service. catch is you have to send notifications every x seconds.
Hi guys I'm facing this problem with no success in tests, I have been looking for info but can't find any solution at the moment. I followed the guide for services, and did all the guide says, but am still having issues.
My code for the service:
[Service(Label="MyService")]
public class MyService : Service{
protected override StartCommandResult onStartCommand(Intent intent, StartCommandFlags flags, int startId){
var t = new Task(() => {
Looper.prepare();
do{
DoServiceWork();
while(running);
});
t.Start();
return StartCommandResult.Sticky;
}
}
And in my main activity:
protected override void OnCreate(Bundle bundle){
new Task(StartService).Start();
}
void StartService(){
var intent = new Intent(Application.Context, typeof(MyService));
Application.Context.StartService(intent);
}
I can't get my service continue working when my app is killed, I hope you guys can help me with this, thanks in advance for those that can help me.
I can't get my service continue working when my app is killed
Please refer to this, in this article, you can find this:
Note that services, like other application objects, run in the main thread of their hosting process.
"Service run in the main thread", that means if your app/main-process/main-thread has been killed, your service will been killed. If you want your service to run, your app must be alive. No custom Service can always run.
You can use IntentService to do heavyweight calculation, and at the same time, it will improve the priority of your app so that your app can't been killed.
In my app I need to update an object if the user didn't refresh it for 30 days. I tried several things to approach this, but none of them worked
1. Using System.currentTimeMillies()
My first try was to just store the time when the object was updated and compare it to the current time. Everything worked fine, but the problem was, that the user could change the os time and then the time check would be useless...
2. Using AlarmManager
Here I had the same problem as above
3. Implementing a Service that contains a timer
Here I implemented a Service with a Timer that just counts up to 30 days. This seemed to be the best solution, but the Service stops when I close the app.
the onCreate and onStartCommand of my Service look like this (I just changed 30 days to 2 minutes for testing and it contains multiple timers for multiple objects):
#Override
public void onCreate() {
Log.i(TAG, "[onCreate]");
super.onCreate();
registerReceiver(new StopServiceReceiver(), new IntentFilter(STOP_SERVICE_REQUEST));
context = this;
//retrieveTimers();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
Log.i(TAG, "[onStartCommand] intent = null");
return super.onStartCommand(intent, flags, startId);
}
//prevent starting 2 timers for the same id
String id = intent.getStringExtra(KEY_CARD_ID);
if (timerHashMap.containsKey(id)) {
Log.i(TAG, "[onStartCommand] timer already exists");
return super.onStartCommand(intent, flags, startId);
}
//create and start timer
Log.i(TAG, "[onStartCommand] schedule timer");
Timer timer = new Timer();
timer.schedule(new CounterTask(id), MAX_MILLIES_WITHOUT_UPDATE);
timerHashMap.put(id, timer);
// storeTimers();
return super.onStartCommand(intent, flags, startId);
}
I also tried to store the timer map in the shared preferences but later on I realized that thsi was kind of stupid because the timers should continue and serializing a timer to store it was also not possible (and as I said kind of stupid ;-))
Thanks for your help!
You can use JobScheduler (or some variations of it).
There are Minimum Latency and Periodic options to schedule the Job to run after 30 days.
Refer this article for more info: Scheduling jobs like a pro with JobScheduler
There is JobIntentService in the latest Support Library and Firebase JobDispatcher for backward compatibility.
I have an intent service which downloads several gigabytes of videos. I have a "Stop" button, to stop the download if accidentally hit "Start" or whatever. I know this has been asked a couple of times but with no working answer for me.
I try to call stopService(), doesn't work. That just calls IntentService.OnDestroy().
I tried to call stopSelf() inside onDestroy, doesn't work either.
I tried to have something like a flag, but onHandleIntent doesn't get called if its already running, it waits till current work is finished and executes then. And even if this would have worked, I would have to have something like a giant if statement, that sucks
Is my only option really to rewrite it to a regular Service?
//Answer
public class SyncService extends IntentService {
boolean isCanceled;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.hasExtra("action")) {
// Set the canceling flag
isCanceled= intent.getStringExtra("action").equals("cancel");
}
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void onHandleIntent(Intent intent) {
// Clean up the possible queue
if (intent.hasExtra ("action")) {
boolean cancel = intent.getStringExtra ("action"). Equals ("cancel");
if (cancel) {
return;
}
}
...
Get your inputStream from HttpUrlConnection or whatever
...
while ((bytesRead = in.read(buffer)) > 0) {
if (isCanceled) {
isCanceled = false;
break;
}
...
}
}
}
And trigger it with
Intent intent = new Intent(context, SyncService.class);
intent.putExtra("action", "cancel");
context.startService(intent);
You have two separate issues, I would think:
How to stop the current download
How to stop queued up downloads, that should execute after the current one completes
The first one is going to have to be "something like a flag", that you check as you download the data. Otherwise, nothing is going to stop your download operation. If you are using a typical HttpUrlConnection recipe, you check that flag in your loop where you read from the HTTP InputStream and write to your FileOutputStream. You set that flag via a call to startService() with a particular Intent structure, identifying it as a "cancel" operation. You would need to override onStartCommand() in your IntentService, look at the Intent, use it to set the flag if it is the cancel Intent, or chain to the superclass for any other sort of Intent.
If you also may have other commands queued up (scenario #2), you would need to check that flag at the top of onHandleIntent() as well.
Given that you haven't posted how you're handling the video download exactly, this may not work (there would be some sort of loop inside onHandleIntent where the downloads are executed). You can use a static class variable inside the IntentService that holds the Stop/Start state of the download, so that it can be set by an Activity. Then, inside onHandleIntent, you would have to routinely check the state so it would know when to cancel the operations.
There are a class of Android applications that enable password protection on certain user-specified apps; for example, Android Protector. I need to approach this problem from a different direction.
Is it possible to create an application that blocks all activity launches unless they are on a predefined whitelist? Will there be unintended consequences with this approach? I am familiar with Android basics and have written a few reasonably simple apps, but I'm still trying to figure out how these "Protector" apps intercept the launch intents correctly. Would someone mind giving me a brief overview on the correct way to do this?
The basic problem is that we have a generic Android phone that needs to be locked down so that our clients (internal only) can access our custom applications without being able to play "Need for Speed", etc. I would like to remove the carrier bloatware, but rooting the device seems like it would be a maintenance headache. We want the setup for each phone to be as simple as installing a few custom applications.
Edited to elaborate on the solution
Overview
My simple solution was to add a new service and activity to my application. The service uses Handler and postDelayed to continuously schedule the monitoring task. The monitoring task checks that the current activity is on the whitelist. Getting the currently running activity involves ActivityManager and a call to getRunningTasks. After finishing the check, the monitoring task schedules itself to run again after X seconds (1, in my case).
If the activity on top is not on the whitelist, we launch the blocking activity which pops up over whatever is currently running. The key part of the blocking activity is that it overrides onBackPressed, preventing the user from simply going back to the "bad" activity. Pressing the Home key is the only way (to my knowledge) to leave this screen.
Tips
Build a backdoor into the lock screen. For example, my solution prompts for a password on a long-press of the back key. After entering the correct password, the monitor service goes to sleep for 5 minutes so I can do my administrative work
Display the name of the blocked activity
Gather a good whitelist before turning this on! Activities you should definitely whitelist: the launcher, package installer, your own app (obviously), the browser, if your app has a web-based component
I don't like that my service is constantly looping in the background; it seems wasteful. I'd like to find some way to be notified when a new task is being launched, but I couldn't find a way to do that. The battery usage for my particular value of the monitor period and my particular phone is acceptable; though you should definitely test before adopting this yourself.
an efective solution,and here is the code from author's opinion
public class MonitorService extends Service {
private Handler handler;
Runnable runnable;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
new Thread(new Runnable() {
#Override
public void run() {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am
.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
String currentActivityName=componentInfo.getClassName();
String packageName=componentInfo.getPackageName();
if(whitelist.contains(currentActivityName)){
Intent launchIntent = new Intent();
launchIntent.setComponent(new ComponentName(blockActivityPackageName,
blockActivityName));
launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(launchIntent);
}
}
}).start();
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Intent intent = new Intent(this, MonitorService.class);
startService(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
As you suggest, writing a custom launcher is probably would be cleaner; check out this open source launcher for reference http://code.google.com/p/adw-launcher-android/