I am creating the following thread in my onCreate but realized that this call needs to execute every 20 minutes or so:
Thread t = new Thread() {
public void run(){
setTopUsers();
}
};
t.start();
private void setTopUsers() {
...
for(Map.Entry<Double,String> entry : myMap.entrySet()) {
key = entry.getKey();
value = entry.getValue();
if(...)
view.setText(...)
}
}
The method that's being called simply processes information from a TreeMap and displays the results to the UI. I'm trying to figure out what is the best way to handle this: 1) Create a Timer that runs on a separate thread (but I've read that's not a good idea), 2) Create a service Intent that processes every 20 minutes (seems like overkill).
Any suggestions?
http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating%28int,%20long,%20long,%20android.app.PendingIntent%29
Something like this should work:
Intent intent = new Intent(this, ProcessService.class);
PendingIntent pIntent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.cancel(pIntent);
am.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), INTERVAL, pIntent);
Let the user decide. Implement both, there's nothing worse than a repeating process the user can't control.
Related
I'm trying to get a process timer to run and keep it running in the background on android (starts with a button click).
The timer must be on 30 seconds and should even continue growing application in the background (with home button and power / screen off).
How can I do this? I tried with service and handler but not working ...
EDIT
My service tracking (process with 30 sec)
public class TrackingService extends IntentService {
private Handler mHandler;
private Runnable mRunnable;
public TrackingService() {
super("TrackingService");
}
public TrackingService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
long timer = 30000;
mHandler = new Handler();
mRunnable = new Runnable() {
#Override
public void run() {
//TODO - process with update timer for new 30 sec
mHandler.postDelayed(this, timer);
}
};
mHandler.postDelayed(mRunnable, timer);
}
}
My click button:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//TODO - start first time and it continued every 30 seconds and continue in the background
startService(Intent intent = new Intent(this, TrackingService.class));
}
});
Ok, first of all, I really don't know if I got your question quite right.
But I think you want a timer that's being executed every 30 seconds ,if i'm not mistaken.
If so, do as following:
AlarmManager
Note: This class provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running. Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted.
Example:
in your onClick() register your timer:
int repeatTime = 30; //Repeat alarm time in seconds
AlarmManager processTimer = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, processTimerReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//Repeat alarm every second
processTimer.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),repeatTime*1000, pendingIntent);
And your processTimerReceiver class:
//This is called every second (depends on repeatTime)
public class processTimerReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//Do something every 30 seconds
}
}
Don't forget to register your receiver in your Manifest.XML
<receiver android:name="processTimer" >
<intent-filter>
<action android:name="processTimerReceiver" >
</action>
</intent-filter>
</receiver>
If you ever want to cancel the alarm:
use this to do so:
//Cancel the alarm
Intent intent = new Intent(this, processTimerReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
Hope this helps you out.
PS: if this is not exactly what u want, please leave it in the comments, or if someone wants to edit this, please do so.
Oh god, don't ever use AlarmManager for 30s timers. It's kind of an overkill and also put a significant drain on device resources (battery, CPU...).
Perhaps you could try using a real background Service instead of IntentService as IntentService tends to shut itself down when it runs out of work. Not sure if this is the case here, but it's worth a try.
I'm very inexperienced with Android and having trouble trying to get an AlarmManager to basically run a small activity that spawns a notification every hour (for testing purposes I lowered it to every 10 seconds.
However it doesn't seem like the activity gets called at all. Logcat shows nothing and no Toast appears, let alone notifications being created.
Context may be the issue, I didn't entirely understand what I was meant to be passing there so I might have made a mistake by passing in MainActivity.this but I couldn't figure out what would be more appropriate when I tried to Google it.
This code is contained in my MainActivity's OnCreate method
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
task = enterTask.getText().toString();
if (!task.equals("Enter task here...") &&
!task.equals("")) {
Toast.makeText(getApplicationContext(),
"Saved task " + task,
Toast.LENGTH_LONG).show();
SharedPreferences.Editor editor = prefs.edit();
editor.putString("Current_Task", task);
editor.commit();
Context context = MainActivity.this;
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Notify.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
//AlarmManager.INTERVAL_HOUR,
10000,
pi);
}
}
});
And this is my Notify activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_notify);
Toast.makeText(getApplicationContext(),
"Notifying",
Toast.LENGTH_LONG).show();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
try {
task = prefs.getString("Current_Task", "");
} catch (Exception e) {
e.printStackTrace();
}
if (!task.equals("")){
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Current task")
.setContentText("Hey! Have you " + task + "?");
mNotificationManager.notify(1, mBuilder.build());
}
}
Can anyone help me understand my mistake?
for testing purposes I lowered it to every 10 seconds
Note that depending on your Android version, it may not occur that frequently. Starting with Android 5.1, the minimum period is one minute.
However it doesn't seem like the activity gets called at all.
Starting an activity periodically via AlarmManager is akin to shooting your users in the face with a shotgun: yes, it gets their attention, but not a very nice way.
In fact, your code to set up the alarms has it right: you are using getBroadcast() for the PendingIntent. This will trigger a BroadcastReceiver, not an Activity. Using a BroadcastReceiver is a far better solution for raising your Notification, as the BroadcastReceiver itself does not have any UI and therefore will not interrupt the user by taking over the foreground.
I recommend that you set up a manifest-registered BroadcastReceiver and put your code from onCreate() (from the preferences onwards) into onReceive() of the BroadcastReceiver.
If you really want to start an activity periodically, and you don't mind your users threatening to do unfortunate things to you, use getActivity() instead of getBroadcast() when creating your PendingIntent.
I am running a code, where the user selects a date and time. The user can select any date and time in the future. These dates and time are stored in sqlite database. After the user selects those dates and time, the activity calls a service class, where I am running a new thread in the following way
public int onStartCommand(Intent intent, int flags, int startId) {
final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
final SqliteController db = new SqliteController(getApplicationContext());
new Thread(new Runnable() {
#Override
public void run() {
List<Greetings> greetings = db.getAllGreetings();
if (db.getGreetingsCount() >= 0) {
do {
for (Greetings g : greetings) {
Calendar cal = Calendar.getInstance();
.........
.........//other codes
This thread access the data from the database and matches the time and date with the system time and date. One the date and time matches, I am using alarm manager with broadcast receiver like this
if (dnt.equals(cdt)) {
Intent aint = new Intent(getApplicationContext(), AlarmReceiver.class);
aint.putExtra("msg", msg);
aint.putExtra("phone", phone);
aint.putExtra("id", id);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), id, aint, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
db.deleteGreetings(g);
}
I wanted to know, Is this the correct way to do it? When I run the program in emulator, sometimes it runs fine, but other times it shows "Application doing too much work in the main thread". So, am I doing something wrong? or is there a better way to do it?
Since nearly all of your posted code is running in a background thread, this would not cause your application to be doing too much work in the main thread. Your problem is likely coming from another source.
You could try profiling your app using traceview as described in the Android documentation here. Try to find which methods are consuming the most time to narrow down your search.
As an aside, you should use an IntentService instead of a Service if your service is just creating a single thread running this task in the background. You then implement the onHandleIntent method instead of the onStartCommand method. The IntentService will handle all operations it receives in a single background Looper.
I have an android application where I am storing user's data on database when he/she activates the app. My app requires the user to stop the application manually in order to remove its entry from the database and along with that other services which keep running when the app is activated.
So I want to write a function which will be executed after every hour (when the app is activated) and will give a notification to user just to remind him/her about the service which is running .If the user had forgot to stop the service then they can stop it or continue with service.
What is the best efficient way of doing this. I dont want to drain too much of battery with thihs 1 hour basis check if the user considers it to run for a day or so. Please advice. Thanks :)
I suggest the code will be like this.
// the scheduler
protected FunctionEveryHour scheduler;
// method to schedule your actions
private void scheduleEveryOneHour(){
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
new Intent(WAKE_UP_AFTER_ONE_HOUR),
PendingIntent.FLAG_UPDATE_CURRENT);
// wake up time every 1 hour
Calendar wakeUpTime = Calendar.getInstance();
wakeUpTime.add(Calendar.SECOND, 60 * 60);
AlarmManager aMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
aMgr.set(AlarmManager.RTC_WAKEUP,
wakeUpTime.getTimeInMillis(),
pendingIntent);
}
//put this in the creation of service or if service is running long operations put this in onStartCommand
scheduler = new FunctionEveryHour();
registerReceiver(scheduler , new IntentFilter(WAKE_UP_AFTER_ONE_HOUR));
// broadcastreceiver to handle your work
class FunctionEveryHour extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// if phone is lock use PowerManager to acquire lock
// your code to handle operations every one hour...
// after that call again your method to schedule again
// if you have boolean if the user doesnt want to continue
// create a Preference or store it and retrieve it here like
boolean mContinue = getUserPreference(USER_CONTINUE_OR_NOT);//
if(mContinue){
scheduleEveryOneHour();
}
}
}
hope that helps :)
Use AlarmManager refer this and tutorial with PendingIntent
Try this way,hope this will help you to solve your problem.
new Timer().scheduleAtFixedRate(task, after, interval);
I have an android activity where there is an EditText and as user types in, it calls the service on every key typed. I believe this is not efficient because more than required calls are being made. So the solution is to have some sort of pause checking there.
if (PauseOfThreeSeconds) {
// call the service here
}
How can I sense a pause and then only call the service?
Start a handler with post delayed for 3 seconds every time the key stroke is made. When ever you get a key store, cancel the runnable that is already in the queue and start a new runnable like i mentioned above.
You should schedule an alarm to start the service on each button press, but also to cancel any previously scheduled alarms so they don't go off as well:
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
long alarmWaitTime = 3000;
onButtonClicked(View v){
Intent i = new Intent(AndroidAlarmService.this, MyAlarmService.class);
PendingIntent pi = PendingIntent.getService(AndroidAlarmService.this, 0, i, 0);
// Cancel any previously set alarms
alarmManager.cancel(pi);
// set a new alarm
alarmManager.set(AlarmManager.RTC, System.getTimeInMillis() + alarmWaitTime , pi);
}