After login i want to show dialog using AlertDialog for every 2 hours.
Tried below code :
private void ShowDialog() {
new SweetAlertDialog(getContext())
.setTitleText("Attention!")
.setContentText("Have You Checked Followup list? Check Here !!")
.setConfirmText("Followup List")
.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sweetAlertDialog) {
ShowFollowupList();
sweetAlertDialog.dismissWithAnimation();
}
})
.setCancelButton("Cancel", new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sDialog) {
sDialog.dismissWithAnimation();
}
})
.show();
}
By using Work Manager you can display it.
Refer link: https://developer.android.com/topic/libraries/architecture/workmanager
Schedule tasks with WorkManager
API makes it easy to schedule deferrable, asynchronous tasks that are expected to run even if the app exits or device restarts.
You can use AlarmManager to achieve it.
First, create your Receiver class that extends BroadcastReceiver as below.
public class YourReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// show your dialog here
}
}
After that, create an AlarmManager and PendingIntent instance to set the alarm, as below.
public void setAlarm(Context context, int requestCode) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, YourReceiver.class);
// different request code enable you to set alarm more than one
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
final long everyTwoHours = 2 * 60 * 60 * 1000; // in milliseconds
alarmManager.setInexactRepeating(
AlarmManager.RTC, calendar.getTimeInMillis(), everyTwoHours, pendingIntent);
}
Use WorkManager for Scheduling task in background and foreground
Example for Periodic Request
PeriodicWorkRequest request= new PeriodicWorkRequest.Builder(WorkerClass.class,
2, TimeUnit.HOURS).addTag("TAG").build()
WorkManager.getInstance().enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP, request);
Create a worker class
public class WorkerClass extends Worker {
#Override
public Worker.WorkerResult doWork() {
// Do the work here
// Indicate success or failure with your return value:
return WorkerResult.SUCCESS;
// (Returning RETRY tells WorkManager to try this task again
// later; FAILURE says not to try again.)
}
}
add this in build.gradle
implementation 'android.arch.work:work-runtime:2.1.0-alpha01'
check the latest release doc https://developer.android.com/jetpack/androidx/releases/work
Related
I am trying to set an alarm to call a method in MainActivity. I have used the method described here; the alarm fires but once it does it repeats about once a second.
I am using setExactAndAllowWhileIdle since the alarm is needed only every hour or so (actually it doesn't need to be exact, I could use setAndAllowWhileIdle instead but that gives the same problem).
My Alarm class is pretty simple:
public class Alarm extends BroadcastReceiver
{
static MainActivity main = null;
public Alarm()
{
}
public Alarm(MainActivity ctx)
{
main = ctx;
}
#Override
public void onReceive(Context context, Intent intent)
{
if (main != null)
main.alarmAction();
}
}
In OnCreate() for MainActivity I have
alarmReceiver = new Alarm(this);
IntentFilter alarmFilter = new IntentFilter("Alarm");
registerReceiver(alarmReceiver,alarmFilter);
and then I have methods:
public void SetAlarm() {
alarmStarted = true;
Intent i = new Intent(this, Alarm.class);
i.setAction("Alarm");
PendingIntent pi = PendingIntent.getBroadcast(this, 1001, i, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.cancel(pi); // tried this to solve the problem but probably not needed
am.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, 1000 * 60 * 10, pi);
}
public void alarmAction() {
if (!alarmStarted)
return;
SetAlarm();
// will be more stuff here but this is minimum required to show problem
}
The flag alarmStarted is set from a button press.
Android Studio is giving me a memory-leak warning about the use of static in static MainActivity main = null, but without this main is always null in onReceive. I don't know if the repeating alarm issue is connected with this or not.
I would like to check every so often if exists a new version of my app, and if it´s, show a message to user. I use Firebase, connecting and comparing version from remote config with current version of app. This isn´t the problem, my problem is how to show the dialog at any time, in any activity.
I have a BaseActivity, where I have methods to connect with firebase and to show the message when it answers. Furthermore, I have a method that executes every hour this update checking:
private void checkUpdate() {
handlerCheckUpdate.postDelayed(() -> {
getConfigFromFirebase(this);
checkUpdate();
}, 3600000);
}
And finally I have Activity1 and Activity2 that extends of BaseActivity. In my Activity1 I start the recursive checkUpdate method.
The problem is that, if user is in Activity2 currently, when the message shows, it do it in Activity1 and not in Activity2.
What is the best solution to do this?.
Thank you very much!
You need to create a dialog in your Application class and pass the context to it.
class App : Application() {
fun showAlert(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle(getString(R.string.your_title))
builder.setMessage(getString(R.string.your_message))
builder.setPositiveButton("OK") { dialog, _ ->
dialog.dismiss()
}
val dialog: AlertDialog = builder.create()
dialog.setCancelable(false) // make it true if you want to cancel
dialog.setCanceledOnTouchOutside(false)
dialog.show()
}
}
And you need to add this line in your manifest file under the application tag
<application
android:name=".App"
android:allowBackup="false"
......>
Call that function from any of your activity by passing context:
App().showAlert(YourActivity.this)
You can use Android LiveData check it here
The idea is - you add an observer in each of your Activities (or the BaseActivity). In the observer you add your logic for launching the Dialog. When you're ready with the update-check in the background, you notify the LiveData. The Activity that is currently in a resumed state will handle the update and show the Dialog.
class BaseActivity : AppCompatActivity() {
...
fun onCreate() {
//provide your liveData from app object
application.getVersionUpdateLiveData().(this, Observer {
//start your dialog here
})
}
}
Make sure you use the latest androidx lib.
Finally, I´ve found a solution. I use AlarmManager and BroadcastReceiver, and I´ve removed the recursive method checkUpdate and set an alarm that repeat every hour, and does the action getConfigFromFirebase(this):
Create broadcast receiver with the action of alarm:
public class CheckUpdateAppAlarmReceiver extends BroadcastReceiver {
public static CheckUpdateReceiverListener checkUpdateReceiverListener;
public static Boolean dialogShown = false;
#Override
public void onReceive(Context context, Intent intent) {
//Alarm!!
if (checkUpdateReceiverListener != null) {
checkUpdateReceiverListener.onCheckUpdateListenerChanged();
}
}
public interface CheckUpdateReceiverListener {
void onCheckUpdateListenerChanged();
}
}
In BaseActivity, add create and cancel alarm methods:
public void createAlarmCheckUpdate() {
try {
long firstAlarmTime = new Date().getTime();
Intent intentAlarmCheckUpdate = new Intent(this, CheckUpdateAppAlarmReceiver.class);
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 2000,
intentAlarmCheckUpdate,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmMgr.setInexactRepeating(AlarmManager.RTC, firstAlarmTime,
AlarmManager.INTERVAL_HOUR, alarmIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void cancelAlarmCheckUpdate(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, CheckUpdateAppAlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 2000, intent, PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null) {
alarmManager.cancel(pendingIntent);
}
}
Finally, implements the broadcastReceiver in BaseActivity, and override its method
public class BaseActivity extends AppCompatActivity implements CheckUpdateAppAlarmReceiver.CheckUpdateReceiverListener {
...
#Override
protected void onResume() {
super.onResume();
CheckUpdateAppAlarmReceiver.checkUpdateReceiverListener = this;
}
...
#Override
public void onCheckUpdateListenerChanged() {
if (this instanceof Activity1 || this instanceof Activity2) {
getConfigFromFirebase(this);
}
}
Use create and cancel alarm methods where necessary.
I'm working on an android app which requires a background task to be performed every hour(Job Scheduler or Service). Task gets executed when the app is running but as soon as I kill the app from foreground, service not work. Is there another way to achieve this?
1. Service
public class NotificationService extends JobService {
private void PrintLog()
{
Log.d("DGVCL", "PrintLog()");
}
#Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d("DGVCL", "onStartJob()");
PrintLog();
jobFinished(jobParameters, false);
return true;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Log.d("DGVCL", "onStopJob()");
return true;
}
}
2. Main Activity
JobScheduler jobScheduler = (JobScheduler)getApplicationContext().getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName componentName = new ComponentName(this, NotificationService.class);
JobInfo jobInfo = new JobInfo.Builder(1, componentName)
.setPeriodic(Global.NOTIFICATION_TIME_PERIOD)
.setBackoffCriteria(Global.NOTIFICATION_TIME_PERIOD, JobInfo.BACKOFF_POLICY_LINEAR)
.setPersisted(true).build();
jobScheduler.schedule(jobInfo);
3. manifest
<service android:name="com.hopesndreams.hiren.hd.service.NotificationService" android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
Use WorkManager it is build on top of JobScheduler and it is specifically build to take on all background services both foreground and background functionalities. https://developer.android.com/topic/libraries/architecture/workmanager
* Using AlarmManager*
Step 1:Create a Service
Do your Logic here in the service
public class AService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//do something
}
#Override
public void onCreate() {
//do somrthing
}
}
Step 2: Create a BroadCast receiver
Start your service with this.
public class AReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
Intent intent = new Intent(context, AService.class);
context.startService(intent);
} catch (Exception e) {
}
}
}
in MainActivity
Intent liveIntent = new Intent(getApplicationContext(), AReceiver.class);
PendingIntent recurring = PendingIntent.getBroadcast(getApplicationContext(), 0, liveIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 16 * 60 * 1000, recurring);
//wakeup and starts service in every 16 minutes.
This is the method working for me. Works fine even if you close the app. Works in Xiaomi devices.
Don't forget to add the service inside the manifest
Indeed, WorkManager is the way to go.
You can read up more on other work primitives to suit your task here, but the below implementation uses Worker for threading in WorkManager, which performs work synchronously on a background thread.
public class BackgroundWorker extends Worker {
public BackgroundWorker
(#NonNull Context context,
#NonNull WorkerParameters params) {
super(context, params);
}
#NonNull
#Override
public Worker.Result doWork() {
yourBackgroundTask(); // yourBackgroundTask() implementation
return Result.success();
}
public static void schedulePeriodicWork(Data data) {
// When multiple constraints are specified like below,
// your task will run only when all the constraints are met.
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.build();
PeriodicWorkRequest taskWork = new PeriodicWorkRequest.Builder(BackgroundWorker.class, 60,
TimeUnit.MINUTES)
.setConstraints(constraints)
.setInputData(data)
.build();
WorkManager.getInstance().enqueue(taskWork);
}
}
Later in your MainActivity file, inside onCreate():
Data data = workData();
BackgroundWorker.schedulePeriodicWork(data);
Then outside the onCreate() method,
private Data workData() {
return new Data.Builder() // to build Data objects
.build();
}
One small thing to note, is that though we set the above task to execute every 60 minutes, each iteration may not be executed at the same time interval.
According to Android documentation, WorkManager is meant for deferrable work, and some drift must be tolerated. However, you can check your log console for the update, "WM-WorkerWrapper: Worker result SUCCESS for Work".
Hope this is helpful.
I'm developing an app that synchronize your local date with the cloud. So I need to check automatically, each 10 minutes, my local data to get the new camera files to upload to the cloud.
So I have used an IntentService that works only when the app is running in foreground. If I close it, my service doesn't upload anything.And I WANT MY INTENTSERVICE WORKS IN BACKGROUND with the AlarmManager.
My IntentService is declared in Manifest.xml:
<!-- Uploader and Deleter Files Service -->
<service android:name=".receiver.UploadDeleteService" android:exported="false" />
<receiver
android:name=".receiver.AlarmReceiver"
android:process=":remote" >
</receiver>
My AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
public static final String ACTION = "com.codepath.example.servicesdemo.alarm";
// Triggered by the Alarm periodically (starts the service to run task)
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, UploadDeleteService.class);
context.startService(i);
}
}
My ServiceInteractor where I instance my AlarmReceiver inside AlarmManager:
public class ServiceInteractorImpl implements ServiceInteractor {
private Context context;
public ServiceInteractorImpl(Context context){
this.context = context;
}
#Override
public void launchService() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(context, AlarmReceiver.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(context, AlarmReceiver.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 5 seconds
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
// Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, 10);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
cal.getTimeInMillis(), pIntent);
}
}
My UploadDeleteService where I call to the retrofit implementation module:
public class UploadDeleteService extends IntentService implements ApiConnector.GetObjectListener {
private RemoteInteractor remoteInteractor;
public UploadDeleteService(String name) {
super(name);
}
public UploadDeleteService() {
super("UpdateDeleteService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.i("SERVICE", "Service running");
remoteInteractor = new RemoteInteractorImpl(getApplicationContext());
remoteInteractor.checkNews(this);
}
#Override
public void onImageUploaded(String type, JSONObject response) {
Log.d("SERVICE", " onImageUploaded ");
//REST OF THE STUFF....
}
}
Please I need a helping hand to solve that problem. I need it works each 10 minutes although the app is closed. Thanks!
For stopped Service:
change "cal.getTimeInMillis()" to "10*60*1000"
cal.add(Calendar.MINUTE, 10); //this will add 10 minute to current time
For Stopped open app when service start:
normally it will not open your app, you need to check what happened in RemoteInteractorImpl.class
you create new instance at onHandleIntent
remoteInteractor = new RemoteInteractorImpl(getApplicationContext());
remoteInteractor.checkNews(this);
I want to make a background running service (independent of an app) which would download weather data from server periodically every day. I already have code to download data from the server and store it in the database.
What I would like to know is, what is the best way to run the service periodically.
You can Create a Android Intent Service :-
public class BackendService extends IntentService {
public BackendService() {
super("BackendService");
}
#Override
protected void onHandleIntent(Intent intent) {
// Your Download code
}
}
Then set a Alarm Receiver to set the interval in which service will be called.
public void backendscheduleAlarm() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), BackendAlarm.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, BackendAlarm.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 1 hour
long firstMillis = System.currentTimeMillis(); // first run of alarm is immediate
int intervalMillis = 3000; //3600000; // 60 min
AlarmManager backendalarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
backendalarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, intervalMillis, pIntent);
}
And Create a Broadcast Receiver class to call that service:
public class BackendAlarm extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
// Triggered by the Alarm periodically (starts the service to run task)
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, BackendService.class);
i.putExtra("foo", "bar");
context.startService(i);
} }
read about Android Services which are mainly made for such background work:
http://developer.android.com/guide/components/services.html
all you need is to start the service on a certain time you set.