Firebase Job Dispatcher is not calling from Thread.setDefaultUncaughtExceptionHandler - android

I am creating a Firebase Job Dispatcher for sending Error crash report to the server. My Service is not starting with dispatcher's mustSchedule method. It might be due to I am starting my job, not on any activity.
Here is my code...
Code for start Service:
public void scheduleJobForUploadCrashReport(Context context, Bundle serviceBundle) {
Logs.i(TAG, "scheduleJobForUploadCrashReport");
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
try {
Job job = createJobForuploadCrashReport(dispatcher, serviceBundle);
dispatcher.mustSchedule(job);
Logs.i(TAG, "dispatcher is scheduled---->");
} catch (FirebaseJobDispatcher.ScheduleFailedException e) {
Logs.e(TAG, "FirebaseJobDispatcher.ScheduleFailedException : " + e.getMessage());
e.printStackTrace();
}
}
Code for create a Job:
public Job createJobForuploadCrashReport(FirebaseJobDispatcher dispatcher, Bundle serviceBundle) {
Logs.i(TAG, "createJobForuploadCrashReport");
Job job = dispatcher.newJobBuilder()
.setLifetime(Lifetime.FOREVER)
.setService(UploadApkCrashReportService.class)
.setTag(mAppName + mModuleName)
.setReplaceCurrent(false)
.setRecurring(false)
.setTrigger(Trigger.executionWindow(0, 30))
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
.setConstraints(Constraint.ON_ANY_NETWORK)
.setExtras(serviceBundle)
.build();
return job;
}
Thanks in advance.

I have found the problem on the same day but I was quite busy.i am changing my Simple Service to JobService. The problem is in passing a Bundle to my JobService. My JobService is not able to do so much task as I am creating and sending the crash file to the server. But, Service is not able to handle so much after an application crash. The only difference is Simple Service is able to perform the same task after an application crash.

Related

Firebase job service started with big delay

I am testing an application that receives Firebase cloud data messages and processes them in the Firebase job service. Receiving messages in the FirebaseMessagingService occurs instantly and without problems, but the Firebase job service sometimes starts with a long delay (5-10 minutes), and sometimes it does not start at all. The dispatcher.schedule (myJob) method always gives the result SCHEDULE_RESULT_SUCCESS. This is the job scheduling functionality:
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
Bundle bundle = new Bundle();
bundle.putInt(WatchDogService.REQUEST_ID, request.ordinal());
bundle.putString(REQUEST_PARAM, parameter);
FirebaseJobDispatcher dispatcher =
new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(LongJobService.class)
.setTag("ua.ers.LongJobService")
.setTrigger(Trigger.NOW)
.setReplaceCurrent(true)
.setExtras(bundle)
.build();
int result = dispatcher.schedule(myJob);
Log.d(TAG, "Schedule result: " + result);
Here is a Firebase Job Service class:
public class LongJobService extends JobService {
private static final String TAG = "LongJobService";
#Override
public boolean onStartJob(final JobParameters jobParameters) {
Log.d(TAG, "LongJobService started");
return true;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Log.d(TAG, "LongJobService stopped");
return false;
}
}
Tell me, please, what could be the cause of the problem?
According to documentation, this is just the usual behaviour
The scheduler backend is encouraged to use the windowEnd value as a signal that the job should be run, but this is not an enforced behavior.
But for a better execution try
Trigger.executionWindow(0, 0)
instead of
Trigger.NOW
So it will look like
Job myJob = dispatcher.newJobBuilder()
.setService(Service.class)
.setRecurring(true) // if task is periodic, else pass "false"
.setTrigger(Trigger.executionWindow(0, 0))
.setTag("tag")
.build();

Is there any way to do async operation in an Android Oreo geofence trigger?

I have an app that has a Service being triggered by geofence transitions. In that Service, I start a LocationClient to get the clients latest location. After that, I do an async HTTP operation to talk to my server.
In Oreo, I get the "Background start not allowed" when the Geofence is triggered, so it doesn't work. Same with Broadcast receiver.
From what I can gather, my only option is an IntentService? But that can't do any async operations since it is killed as soon as the method exits.
My question: Is there any way for me to do an async operation/location lookup when a geofence is triggered in Oreo?
Either use Foreground Services (with ongoing Notification) and call a background thread there.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}
Make sure you return something sensefull in onStartCommand use stopSelf(startId) after your async task finished, to prevent the service from beeing re-launched rather randomly. Also make sure you call stopForeground(true) to cancel the ongoing notification as soon as you are done.
Or use Firebase Job Dispatcher. Your JobService should extend SimpleJobService as this allready provides you with an async method! Simple Job Service
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new
GooglePlayDriver(getBaseContext()));
myExtrasBundle.putString(SetStatusService.MESSAGE, message);
Job myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(StatusJobService.class)
// uniquely identifies the job
.setTag(StatusJobService.UNIQUE_ID)
// one-off job
.setRecurring(false)
// don't persist past a device reboot
.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
// start between 0 and 60 seconds from now
.setTrigger(Trigger.executionWindow(0, 15))
// don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.setExtras(myExtrasBundle)
.build();
dispatcher.mustSchedule(myJob);
And all you need to make your method async:
public class JobService extends SimpleJobService {
#Override
public int onRunJob(JobParameters job) {
if (job != null) {
Bundle extras = job.getExtras();
if (extras != null) {
callServer(extras)
}
}
return RESULT_FAIL_NORETRY;
}}

android: scheduling job every hour forever

I have a web service on my server that needs to be pinged every hour. For this, I am using an Android app to ping it every hour. I have tried using Alarm manager but it stops working after few hours and if I swipe exit it. I have tried using service but for some reason, that doesn't seem to work and my app keeps crashing. I have am thinking about using Firebase Job dispatcher. My requirement is that the app needs to ping the web service on my server every hour. This should go on for at least next 3-4 months. Is there a way to accomplish this ? Thanks in advance!
EDIT: I have tried broadcast receiver with Alarm Manager but have not been able to sustain the firing for more then 4 hours.
I second Anantha's answer but seems like job parameters are little off for your needs.
You can go over this article to learn about the subtle differences between various Job schedulers.
As a matter of fact, even Google recommends using Firebase Job Schedular if the app needs to do a network communication due to various reasons. Please watch the attached video on the Github page for more info on the same. This also gives you basic code to kickstart your application. You can just change the job parameters to suit your needs
Hopefully, this below code should suit your requirement of triggering every one hour with a tolerance of 15 minutes
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(getContext()));
final int periodicity = (int)TimeUnit.HOURS.toSeconds(1); // Every 1 hour periodicity expressed as seconds
final int toleranceInterval = (int)TimeUnit.MINUTES.toSeconds(15); // a small(ish) window of time when triggering is OK
Job myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(yourJobService.class)
// uniquely identifies the job
.setTag("my-unique-tag")
// recurring job
.setRecurring(true)
// persist past a device reboot
.setLifetime(Lifetime.FOREVER)
// start between 0 and 60 seconds from now
.setTrigger(Trigger.executionWindow(periodicity, toleranceInterval))
// overwrite an existing job with the same tag
.setReplaceCurrent(true)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
// constraints that need to be satisfied for the job to run
.setConstraints(
// only run on an unmetered network
Constraint.ON_ANY_NETWORK
)
.setExtras(schedulerextras)
.build();
dispatcher.mustSchedule(myJob);
Jhon you can use firebase jobdispatcher. because it will support from api level 9. you can see below how to create job dispatcher and how to call it.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scheduleJob(this);
}
public static void scheduleJob(Context context) {
//creating new firebase job dispatcher
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
//creating new job and adding it with dispatcher
Job job = createJob(dispatcher);
dispatcher.mustSchedule(job);
}
public static Job createJob(FirebaseJobDispatcher dispatcher){
Job job = dispatcher.newJobBuilder()
//persist the task across boots
.setLifetime(Lifetime.FOREVER)
//.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
//call this service when the criteria are met.
.setService(ScheduledJobService.class)
//unique id of the task
.setTag("UniqueTagForYourJob")
//don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// We are mentioning that the job is periodic.
.setRecurring(true)
// Run between 30 - 60 seconds from now.
.setTrigger(Trigger.executionWindow(30, 60))
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
//.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
//Run this job only when the network is available.
.setConstraints(Constraint.ON_ANY_NETWORK, Constraint.DEVICE_CHARGING)
.build();
return job;
}
public static Job updateJob(FirebaseJobDispatcher dispatcher) {
Job newJob = dispatcher.newJobBuilder()
//update if any task with the given tag exists.
.setReplaceCurrent(true)
//Integrate the job you want to start.
.setService(ScheduledJobService.class)
.setTag("UniqueTagForYourJob")
// Run between 30 - 60 seconds from now.
.setTrigger(Trigger.executionWindow(30, 60))
.build();
return newJob;
}
public void cancelJob(Context context){
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
//Cancel all the jobs for this package
dispatcher.cancelAll();
// Cancel the job for this tag
dispatcher.cancel("UniqueTagForYourJob");
}}
ScheduledJobService.java
public class ScheduledJobService extends JobService {
private static final String TAG = ScheduledJobService.class.getSimpleName();
#Override
public boolean onStartJob(final JobParameters params) {
//Offloading work to a new thread.
new Thread(new Runnable() {
#Override
public void run() {
codeYouWantToRun(params);
}
}).start();
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
return false;
}
public void codeYouWantToRun(final JobParameters parameters) {
try {
Log.d(TAG, "completeJob: " + "jobStarted");
//This task takes 2 seconds to complete.
Thread.sleep(2000);
Log.d(TAG, "completeJob: " + "jobFinished");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//Tell the framework that the job has completed and doesnot needs to be reschedule
jobFinished(parameters, true);
}
}}
You will need to use JobScheduler(api >21 ) and GcmNetworkManager (api<21) depending on the api level of android. Check out this library from evernote which takes care of it.
Do you try broadcast receiver? I use Broadcast Receiver with Alarm Manager to vibrate every minute and it work fine. The only problem is that when device turn off or restarted, it not vibrate till I enter my application.
My test code.
public void setAlarm() {
alarmMgr =(AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(AlarmManagerActivity.this, AlarmManagerBroadcastReceiver.class);
intent.setAction("a.b.c.d");
PendingIntent pi = PendingIntent.getBroadcast( getApplicationContext(), 0, intent, 0);
//After after 5 seconds
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 13);
calendar.set(Calendar.MINUTE, 40);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis()
, (1000) * (60)
, pi);
}
My receiver
#Override
public void onReceive(Context context, Intent intent) {
Log.d(getClass().getSimpleName(), Intent.ACTION_BOOT_COMPLETED);
if ( intent.getAction().equals("a.b.c.d")) {
Log.d(getClass().getSimpleName(), "Custom Broadcast01");
Vibrator vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(10000);
}
else
Log.d(getClass().getSimpleName(), "no this action for intent!");
}
Broadcast receiver to start Alarm when device restart
<receiver
android:name=".OnBootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class OnBootBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
setAlarm();
}
}

FirebaseJobDispatcher is not executing for every 5 seconds

I am trying to hit the server every 5 seconds.Previously I am using Alarm manager. After that I am used Job Scheduler. But when I install my app in Nougat devices this Job Scheduler is not running. So I am switching to FirebaseJobDispatcher. But FirebaseJobDispatcher is not executing for every 5 seconds. Herewith I attached the code which I am using.
public Job createJob(FirebaseJobDispatcher dispatcher){
Job job = dispatcher.newJobBuilder()
.setLifetime(Lifetime.FOREVER)
.setService(ScheduledJobService.class)
.setTag("getTask")
.setReplaceCurrent(false)
.setRecurring(true)
.setTrigger(Trigger.executionWindow(0, 5))
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
.setConstraints(Constraint.ON_ANY_NETWORK)
.build();
return job;
}
public void scheduleJob(Context context) {
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
Job job = createJob(dispatcher);
dispatcher.mustSchedule(job);
}
Please help me to resolve this issue.
make sure that you register your service in Manifest Firebase JobDispatcher

Firebase JobDispatcher-Scheduled jobs are lost on device reboot

I am using Firebase-JobDispatcher.I have scheduled some jobs and its working fine if i keep the device switch on.But if i reboot my device then the scheduled jobs doesn't execute or it doesn't get rescheduled?I have used setLifetime(Lifetime.FOREVER).Still jobs are lost on device reboot.Below is the code i m using-
Job myJob = dispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTag("DataSend")
.setRecurring(false)
.setLifetime(Lifetime.FOREVER)
.setTrigger(Trigger.executionWindow(0, 0))
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.setConstraints(Constraint.ON_ANY_NETWORK)
.setExtras(myExtrasBundle)
.build();
After setting Lifetime.FOREVER you have add the following permission in AndroidManifest.xml file
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
And below is the code to schedule a job
Job job = jobDispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTrigger(Trigger.executionWindow(windowStartTime, 3600))
.setTag(PENDING_AUTH_JOB) //identifier for the job
.setRecurring(false) // should not recur
.setLifetime(Lifetime.FOREVER) // should persist device reboot
.setReplaceCurrent(false) // no need to replace previous job
.setConstraints(Constraint.ON_ANY_NETWORK) // set network availability constraint
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.build();
try {
jobDispatcher.mustSchedule(job);
} catch (FirebaseJobDispatcher.ScheduleFailedException e) {
if (retryCount-- > 0) {
scheduleJob(0);
}
}
One more thing to check is not set execution window to 0,0. always set a windowEnd greater that windowStart
I think in your MyJobService should return false so that the job can be rescheduled after executing;
public boolean onStartJob(final com.firebase.jobdispatcher.JobParameters jobParameters) {
//Offloading work to a new thread.
new Thread(new Runnable() {
#Override
public void run() {
realm=Realm.getDefaultInstance();
codeYouWantToRun(jobParameters);
}
}).start();
return true;
}
public void codeYouWantToRun(final JobParameters parameters) {
Log.d(TAG, "completeJob: " + "jobStarted");
//bla bla super code doing its linga linga ling
Log.d(TAG, "completeJob: " + "jobFinished");
//Tell the framework that the job has completed and doesnot needs to be reschedule. Set jobFinished false so that it can rescheduled on a change of network
jobFinished(parameters, false);
}
Try setPersisted(boolean) method.

Categories

Resources