I put up a Jobservice to do some things. For test purpose I let it run every thirty seconds. To find the problem I reduced the service down to do nothing(!).
I know, that a job can be stopped by the system; if the onStopJob method returns true it will be restarted. This happens and works well, although I am wondering, how often and at which time (in the middle of the night, while the phone is just laying on the table!).
To check all these, I am using SharedPreferences, keeping track of stops and restarts.
I found out however, that the job is not only stopped, but sometimes completely being destroyed.
I then put up a restart routine in the OnDestroy method. This does not work. The job is being restarted, but immediately being destroyed again.
So I have some questions:
Why is it destroyed in the first place?
And why isnt it possible to restart it?
And what can I do to make it more stable?
Tried on a Galaxy S4 under Android 5.0.1 and XPeria Z2 under 6.0
Compiled against MinSDK 5.0, TargetSDK 6.0.
Here is the code of my JobSchedulerService:
public class JobSchedulerService extends JobService implements
DataApi.DataListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
private boolean stoppedByUser = false;
public DateFormat formatter;
String stoptimeText;
public GregorianCalendar apptTime;
public Context myCnt;
#Override
public boolean onStartJob(JobParameters params){
doJob(this);
jobFinished(params, false );
return true;
}
public void doJob(Context context){
myCnt = context;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(myCnt);
SharedPreferences.Editor editor = prefs.edit();
stoptimeText = prefs.getString("stopped","not yet stopped");
editor.putString("started", "Job was running at " + timeNow());
editor.apply();
// do something here
}
#Override
public boolean onStopJob(JobParameters params){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
stoppedByUser = prefs.getBoolean("stoppedByUser", false);
SharedPreferences.Editor editor = prefs.edit();
stoptimeText += "Job stopped autom. at " + timeNow();
editor.putString("stopped", stoptimeText);
editor.apply();
if (stoppedByUser){
stoppedByUser = false;
editor.putBoolean("stoppedByUser", false);
stoptimeText += "OnStopJob called by user-stop at " + timeNow();
editor.putString("stopped", stoptimeText);
editor.apply();
return false;
}
else return true;
}
#Override
public void onDestroy() {
super.onDestroy();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
stoppedByUser = prefs.getBoolean("stoppedByUser", false);
SharedPreferences.Editor editor = prefs.edit();
stoptimeText += "Job was destroyed at "+ timeNow();
editor.putString("stopped", stoptimeText);
editor.apply();
if (!stoppedByUser){
JobInfo.Builder builder = new JobInfo.Builder(1,
new ComponentName(getPackageName(), JobSchedulerService.class.getName()));
builder.setPeriodic(30 * 1000);
builder.setPersisted(true);
stoptimeText += "Job rest. after dstr. at " + timeNow();
editor.putString("stopped", stoptimeText);
editor.putString("started", "Auto update started after destroy! Check if really running!");
editor.apply();
}
else {
stoptimeText += "OnDestroy called by user-stop at " + timeNow();
editor.putString("stopped", stoptimeText);
editor.apply();
}
}
public String timeNow(){
apptTime = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));
formatter = new SimpleDateFormat("EEE, dd./HH:mm", Locale.ENGLISH);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
return formatter.format(apptTime.getTimeInMillis());
}
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
}
#Override
public void onConnected(Bundle connectionHint) {
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
}
#Override
public void onConnectionSuspended(int arg0) {
}
}
And here is my MainActivity (shortened):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myCnt = this;
initGoogleApiClient();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
if (tabLayout != null)
tabLayout.setupWithViewPager(viewPager);
mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
//.......
public void startJob(){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("started", "auto updates started by user!");
editor.putBoolean("stoppedByUser", false);
editor.apply();
JobSchedulerService jss = new JobSchedulerService(); // used to "first run" the job, so there is no waiting time for the user
jss.doJob(myCnt);
JobInfo.Builder builder = new JobInfo.Builder(1,
new ComponentName(getPackageName(), JobSchedulerService.class.getName()));
builder.setPeriodic(30 * 1000);
builder.setPersisted(true);
if (mJobScheduler.schedule(builder.build()) <= 0) {
Toast.makeText(MainActivity.this, "Failure starting Jobservice!", Toast.LENGTH_LONG).show();
}
}
After long research I found the following to be the problem:
In my
// do something here
I had an Async Task. However, according to Google, this is only working in the UI Thread (see: https://developer.android.com/reference/android/os/AsyncTask.html).
Having this in my JobSchedulerService caused it to be destroyed after some time.
I am now using a (regular) separate thread to "do something" in the Service, and it works.
Related
I've wrote an app for creating and reminding task which uses local SqliteDatabase.
I wrote a jobScheduler service to check the device time and date with tasks on the database and if matches shows a push notification.
What I want also is service to run in background and check the data every 5 seconds .
but when I write
builder.setPeriodic(5000);
builder.setPersisted(true);
the service stops checking data.
Here's my code
MainActivity
public class MainActivity extends AppCompatActivity {
ImageButton plusImageBtn;
DatabaseHelper databaseHelper;
BottomNavigationView navigation;
Toolbar toolbar;
private ComponentName mServiceComponent;
private int jobId=0;
private static final String TAG = MainActivity.class.getSimpleName();
public static final String WORK_DURATION_KEY =
BuildConfig.APPLICATION_ID + ".WORK_DURATION_KEY";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
navigation = (BottomNavigationView) findViewById(R.id.navigation);
plusImageBtn = (ImageButton) findViewById(R.id.plusImagBtn);
toolbar= (Toolbar) findViewById(R.id.toolbar_main);
setSupportActionBar(toolbar);
mServiceComponent = new ComponentName(this, JobSchedulerService.class);
databaseHelper= new DatabaseHelper(this);
navigation.setOnNavigationItemSelectedListener
(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.navigation_calendar:
selectedFragment = new CalendarFragment();
break;
case R.id.navigation_home:
selectedFragment = new ViewListContents();
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, selectedFragment);
transaction.commit();
return true;
}
});
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout,new ViewListContents());
transaction.commit();
scheduleJob();
}
#Override
protected void onStart() {
super.onStart();
// Start service and provide it a way to communicate with this class.
Intent startServiceIntent = new Intent(this, JobSchedulerService.class);
startService(startServiceIntent);
}
#Override
protected void onStop() {
stopService(new Intent(this,JobSchedulerService.class));
super.onStop();
}
public void scheduleJob() {
JobInfo.Builder builder = new JobInfo.Builder(jobId++, mServiceComponent);
// builder.setPeriodic(5000);
// builder.setPersisted(true);
builder.setMinimumLatency(1000);
builder.setOverrideDeadline(1000);
// Extras, work duration.
PersistableBundle extras = new PersistableBundle();
extras.putLong("",5000);
builder.setExtras(extras);
// Schedule job
Log.d(TAG, "Scheduling job");
JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
tm.schedule(builder.build());
Toast.makeText(this, "Scheduling job ", Toast.LENGTH_SHORT).show();
}}
JobSchedulerService
public class JobSchedulerService extends JobService {
int id;
String stringId;
String date;
String taskDate,taskTitle,taskTime,sepYear,sepMonth,
sepDay,convert,DeviceDate;
Cursor taskDateCursor;
DatabaseHelper databaseHelper;
Roozh roozh;
String[] seperatedString;
int iYear,iMonth, iDay;
SimpleDateFormat dateFormat, timeFormat;
private static final String TAG = JobSchedulerService.class.getSimpleName();
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service created");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Service destroyed"); }
#Override
public boolean onStartJob(final JobParameters params) {
stringId = String.valueOf(params.getJobId());
id = params.getJobId();
final long duration = params.getExtras().getLong(WORK_DURATION_KEY);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
databaseHelper= new DatabaseHelper(getApplicationContext());
taskDateCursor=databaseHelper.getDateForNotification();
if (taskDateCursor.moveToFirst()){
do {
taskTitle=taskDateCursor.getString(taskDateCursor.getColumnIndex(DatabaseHelper.COL2));
taskDate=taskDateCursor.getString(taskDateCursor.getColumnIndex(DatabaseHelper.COL3));
taskTime=taskDateCursor.getString(taskDateCursor.getColumnIndex(DatabaseHelper.COL4));
roozh= new Roozh();
seperatedString=taskDate.split("/");
sepYear= seperatedString[0];
sepMonth= seperatedString[1];
sepDay= seperatedString[2].trim();
iYear= Integer.parseInt(sepYear);
iMonth= Integer.parseInt(sepMonth);
iDay= Integer.parseInt(sepDay);
roozh.PersianToGregorian(iYear,iMonth,iDay);
convert= roozh.toString();
dateFormat= new SimpleDateFormat(
"yyyy-MM-dd", Locale.getDefault());
DeviceDate= dateFormat.format(new Date());
timeFormat=new SimpleDateFormat("HH:m",Locale.getDefault());
String deviceTime=timeFormat.format(new Date());
RemoteViews remoteViews= new RemoteViews(getPackageName(),R.layout.notification);
remoteViews.setImageViewResource(R.id.notif_image, R.mipmap.ic_launcher);
remoteViews.setTextViewText(R.id.title,taskTitle);
remoteViews.setTextViewText(R.id.text,taskTime);
if (DeviceDate.equals(convert) && deviceTime.equals(taskTime) ){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.drawable.drawable_circle)
.setContent(remoteViews)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setColor(ContextCompat.getColor(getApplication(), R.color.primaryDarkColor))
.setShowWhen(true)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext());
notificationManager.notify(0, mBuilder.build());
}
Log.i(TAG, "data " + DeviceDate+ "task" + convert+ " " + "dd" + " "+ taskTime + "dt" + "" + deviceTime);
}while (taskDateCursor.moveToNext());
} }
}, duration);
Log.i(TAG, "on start job: " + params.getJobId());
return true; }
#Override
public boolean onStopJob(JobParameters params) {
Log.i(TAG, "on stop job: " + params.getJobId());
return true; }
I think your problem is the frequency you would like to execute your job. The minimum period for a job is 15 minutes in the standard AOSP. So it probably isn't the right API for you. Alarm Manager would probably be what you want, but setting an alarm for every 5 seconds is expensive. Google has also been restricting background services more and more with each release. Just something to keep in mind.
See:
JobScheduler not repeating job
setPeriodic(long intervalMillis) only works on devices lower than Nougat change it with this setPeriodic (long intervalMillis, long flexMillis) for devices having android version Nougat and above.
ScheduledThreadPoolExecutor is a better option.
Tasks can be scheduled by scheduleAtFixedRate or scheduleWithFixedDelay.
Reference:
https://developer.android.com/reference/kotlin/java/util/concurrent/ScheduledThreadPoolExecutor#schedule
Refer this answer of mine:
https://stackoverflow.com/a/60295377/9166855
The minimum period is 15minutes!
I am trying to run an accounting calculator in the background using JobScheduler, but somehow, it won't do the calculation. The program runs smoothly, thats why it confuses me why it doesn't work. I appreciate your help.
Here's my Job Service class:
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyJobService extends JobService {
private JobParameters params;
int num1a;
int num1b;
int num2a;
int num2b;
int num3a;
int num3b;
int num4a;
int num4b;
int num5a;
int num5b;
int sum1;
int sum2;
int sum3;
int sum4;
int sum5;
SharedPreferences preferences;
SharedPreferences.Editor editor;
#Override
public boolean onStartJob(JobParameters params) {
this.params = params;
Toast.makeText(getApplicationContext(), "Start", Toast.LENGTH_LONG).show();
new MonthlyTask().execute();
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
return false;
}
private class MonthlyTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPostExecute(Void xVoid) {
super.onPostExecute(xVoid);
jobFinished(params, false);
Toast.makeText(getApplicationContext(), "Finish", Toast.LENGTH_LONG).show();
}
#Override
protected Void doInBackground(Void... params) {
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
editor = preferences.edit();
try {
num1a = preferences.getInt("expense1", 0);
num1b = preferences.getInt("subtotal1", 0);
num2a = preferences.getInt("expense2", 0);
num2b = preferences.getInt("subtotal2", 0);
num3a = preferences.getInt("expense3", 0);
num3b = preferences.getInt("subtotal3", 0);
num4a = preferences.getInt("expense4", 0);
num4b = preferences.getInt("subtotal4", 0);
num5a = preferences.getInt("expense5", 0);
num5b = preferences.getInt("subtotal5", 0);
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
sum1 = num1a + num1b;
sum2 = num2a + num2b;
sum3 = num3a + num3b;
sum4 = num4a + num4b;
sum5 = num5a + num5b;
editor.putInt("subtotal1", sum1);
editor.putInt("subtotal2", sum2);
editor.putInt("subtotal3", sum3);
editor.putInt("subtotal4", sum4);
editor.putInt("subtotal5", sum5);
return null;
}
}
}
Here's my Main Activity
public class MainActivity extends AppCompatActivity implements android.view.View.OnClickListener{
//Do stuffs
public void onClick(View view) {
if (view == findViewById(R.id.btnSave)) {
JobInfo.Builder builder = new JobInfo.Builder(1, new ComponentName(getPackageName(),
MyJobService.class.getName()));
//run job service after every 5 seconds, which put back to 15 mins...but thats fine
builder.setPeriodic(5000);
builder.setPersisted(true);
jobScheduler.schedule(builder.build());
finish();
}}
I am trying to run an accounting calculator in the background using JobScheduler
This example is really strange.
but somehow, it won't do the calculation
Um, well, if by "the calculation", you mean addition, it is doing the addition. However, you then throw away the results. You edit() the SharedPreferences without calling apply() or commit() to save the changes.
I'm coding an app, where there is a PrefereceActivity which contains a SwitchPreference that start or stop a service when the user switches on or off it, and it saves the status of the switch in to SharedPreference.
Then in the MainActivity I registered A On SharedPreferenceChangeListener, which read the status of the switch, then based on the it start or Stop the service.
// This is the code in MainATY:
preferences= getPreferences(Activity.MODE_PRIVATE);
editor= preferences.edit();
preferences.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
boolean pushNotification= sharedPreferences.getBoolean(MyPreferences.pushNotificationKey,true);
if (pushNotification)
{
if (!NotificationService.isRunning){
Intent i = new Intent(MainActivity.this, NotificationService.class);
bindService(i,MainActivity.this,Context.BIND_AUTO_CREATE);
}
}
else{
if (NotificationService.isRunning){
unbindService(MainActivity.this);
}
}
}
});
and this is PreferenceATY code:
pushNotification.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object o) {
pushNotification= (SwitchPreference) preference;
editor.putBoolean(pushNotificationKey,pushNotification.isChecked());
if (!editor.commit())
{
Toast.makeText(MyPreferences.this, R.string.changes_saved,Toast.LENGTH_SHORT).show();
}
return true;
}
});
But it doesn't work, can you help me?
One last thing, how can I make Notifications with more than one line of the content?
This is my notification function:
String thingsToDo=new String();
while (c.moveToNext())
{
thingsToDo+=String.format("%s: %s: %s "
,c.getString(c.getColumnIndex("subject"))
,c.getString(c.getColumnIndex("typeOfEvent"))
,c.getString(c.getColumnIndex("what"))
);
thingsToDo+="/n";
}
thingsToDo.substring(0,4);
NotificationCompat.Builder mBuilder=new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.small_icon_diary)
.setContentTitle(getString(R.string.homework_for_tomorrow))
.setContentText(thingsToDo);
mBuilder.setShowWhen(true);
Intent i= new Intent(MainActivity.this,NotificationViewActivity.class);
Bundle b= new Bundle();
b.putString("time",time);
i.putExtra("b",b);
i.putExtra("time",time);
mBuilder.addAction(R.drawable.small_icon_diary,"Open",PendingIntent.getActivity(MainActivity.this,0,i,0));
I have solved the Question about Notification in this way:
NotificationCompat.Builder mBuilder=new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.small_icon_diary)
.setContentTitle(getString(R.string.homework_for_tomorrow))
.setContentText(thingsToDo)
.setStyle(new NotificationCompat.BigTextStyle().bigText(thingsTodo));
I need to call the Google activity recognition service through a service (not activity) and run it in the background, of course when the user starts the app, which has an activity (But the service does not called directly from activity).
Therefore I have created a service class (ActivitySensor) and another class (ActivityRecognitionScan).
When I install the app on my Galaxy Nexus S device, the service starts calling onCreate and onDestroy automatically. Even without doing anything in the GUI
It is very strange behaviour. Does anybody has the same experience or solution for it?
I mean I get something as follows in the debug console:
Activity-Logging --- onCreate
Activity-Logging --- onDestroy
Activity-Logging --- onCreate
Activity-Logging --- onDestroy
Activity-Logging --- onCreate
Activity-Logging --- onDestroy
...
Here are my two classes:
public class ActivitySensor extends IntentService {
private ActivityRecognitionScan myascan;
private Intent inIntent;
private static long ACTIVITY_LOG_INTERVAL = 30000L;
private static JsonEncodeDecode jsonencoder = new JsonEncodeDecode();
public ActivitySensor() {
super("ActivitySensor");
}
#Override
public void onCreate(){
super.onCreate();
Log.d("Activity-Logging", "--- onCreate");
try {
myascan = new ActivityRecognitionScan(getApplicationContext());
myascan.startActivityRecognitionScan();
} catch (Exception e) {
Log.e("[Activity-Logging]","----------Error:"+e.getLocalizedMessage());
e.printStackTrace();
}
}
#Override
public void readSensor() {
// Log.e("Activity-Logging", "ActivityRecognitionResult.hasResult: "+String.valueOf(ActivityRecognitionResult.hasResult(inIntent)));
if (ActivityRecognitionResult.hasResult(inIntent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(inIntent);
DetectedActivity activity = result.getMostProbableActivity();
final int type = activity.getType();
String strType = new String();
switch(type){
case DetectedActivity.IN_VEHICLE:
strType = "invehicle";
break;
case DetectedActivity.ON_BICYCLE:
strType ="onbicycle";
break;
case DetectedActivity.ON_FOOT:
strType = "onfoot";
break;
case DetectedActivity.STILL:
strType = "still";
break;
case DetectedActivity.TILTING:
strType ="tilting";
break;
case DetectedActivity.UNKNOWN:
strType ="unknown";
break;
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Editor edt = prefs.edit();
String previousActv = prefs.getString("PREVIOUS_ACTIVIY","");
long previousDate = prefs.getLong("PREVIOUS_DATE", 0);
if (previousActv.length()==0){ // nothing was in the string and it is the first time just initialize
previousActv = strType;
previousDate = new Date().getTime();
// Log.e("-----FIRST TIME: type:", previousActv+" date:"+String.valueOf(previousDate));
edt.putString("PREVIOUS_ACTIVIY", strType);
edt.putLong("PREVIOUS_DATE", previousDate);
edt.commit();
}else {
if (!strType.equalsIgnoreCase(previousActv)){
Date readablePrevDate = new Date(previousDate);
Date nowDate = new Date();
String jsonstr = jsonencoder.EncodeActivity("Activity", readablePrevDate, nowDate, strType, activity.getConfidence());
// Log.e("[Activity-Logging] ----->",jsonstr);
edt.putString("PREVIOUS_ACTIVIY", strType);
edt.putLong("PREVIOUS_DATE", nowDate.getTime());
edt.commit();
DataAcquisitor.dataBuff.add(jsonstr);
}
}
}
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("Activity-Logging", "--- onHandleIntent"+ "---"+intent.getAction());
intent.putExtra("LOG_INTERVAL",ACTIVITY_LOG_INTERVAL );
intent.putExtra("STOP",false);
inIntent = intent;
readSensor();
}
#Override
public void onDestroy(){
Log.d("Activity-Logging", "--- onDestroy");
myascan.stopActivityRecognitionScan();
myascan=null;
//super.onDestroy();
}
}
This is the class that calls the Google Activity Recognition Service:
ActivityRecognitionScan implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener {
private Context ctx;
private static final String TAG = "ActivityRecognition";
private static ActivityRecognitionClient actrecClient;
private static PendingIntent callbackIntent;
private long ACTIVITY_LOG_INTERVAL=30000;
public ActivityRecognitionScan(Context context) {
ctx=context;
}
public void startActivityRecognitionScan(){
int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(ctx);
if(resp == ConnectionResult.SUCCESS){
actrecClient = new ActivityRecognitionClient(ctx, this, this);
if (!actrecClient.isConnected()){
actrecClient.connect();
} else{
Log.e("ActivityRecognitionScan"," ---Activity recognition client is already connected");
}
}else{
Log.e("[Activity-Logging]", "Google Play Service hasn't installed");
}
}
public void stopActivityRecognitionScan(){
try{
if (actrecClient.isConnected() || actrecClient.isConnecting() ){
actrecClient.removeActivityUpdates(callbackIntent);
actrecClient.disconnect();
}
} catch (Exception e){
e.printStackTrace();
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.e("[ActivityRecognitionScan]", "Connection Failed");
}
#Override
public void onConnected(Bundle connectionHint) {
try{
Intent intent = new Intent(ctx, ActivitySensor.class);
Bundle bundle = intent.getExtras();
callbackIntent = PendingIntent.getService(ctx, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
long interval = 5000;
if ( null!= bundle && bundle.containsKey("LOG_INTERVAL") ){
interval = bundle.getLong("LOG_INTERVAL");
}
actrecClient.requestActivityUpdates(interval, callbackIntent);
actrecClient.disconnect();
}catch(Exception ex){
Log.e("[Activity-Logging]","Error in requesting Activity update "+ex.getMessage());
ex.printStackTrace();
}
}
#Override
public void onDisconnected() {
callbackIntent.cancel();
actrecClient = null;
Log.e("[ActivityRecognitionScan]","---onDisconnected");
}
}
IntentService automatically stops itself on completion of onHandleIntent as per the source code (see ServiceHandler.handleMessage()) as per the description of an IntentService:
Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
Use a Service if you want it to run continuously in the background.
You have 2 issues with your code that is causing the problem you are experiencing.
When activity is detected, the pending intent that is called calls (and creates, since it is an IntentService) ActivitySensor. The onCreate will connect another ActivityRecognitionClient, which is unnecessary. This causes another activity to be detected which causes your logging loop.
You should separate the creation of the ActivityRecognitionClient from the handling of the detected activity. You don't need to keep recreating it as subsequent detections will use the same PendingIntent. This will prevent the logging loop.
Im having issues with the below code on making a checkbox preference, That by default is checked. My first activity is a simple splash screen, and simply before show my imageview thread i want to check if the checkbox has been disable if so then i want to intent directly to the main activity and by default i show my image thread, or in reversed order of that.
Currently my splashscreen is launching no matter if its checked or now, Any help would be greatly appreciated
XML
<CheckBoxPreference
android:title="#string/category_tools_startupscreen"
android:summary="#string/category_tools_startupscreen_summary"
android:key="boot_animation" android:order="5" android:enabled="true"/>
SplashScreen
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
if (settings.getBoolean("boot_animation", true)) {
setContentView(R.layout.splash_screen);
Thread splashThread = new Thread() {
#Override
public void run() {
try {
int waited = 0;
// changed from 5000 to 4000 11.29
while (waited < 3000) {
sleep(100);
waited += 100;
}
} catch (InterruptedException e) {
// do nothing
} finally {
Intent i = new Intent();
i.setClassName("com.example.app",
"com.example.app.MainActivity");
startActivity(i);
finish();
}
}
};
splashThread.start();
}
else {
Intent i = new Intent();
i.setClassName("com.example.app",
"com.example.app.MainActivity");
startActivity(i);
finish();
}
}
Settings
final CheckBoxPreference checkboxPref2 = (CheckBoxPreference) getPreferenceManager().findPreference("boot_animation");
checkboxPref2.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(newValue instanceof Boolean){
Boolean boolVal = (Boolean)newValue;
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("checked", boolVal);
editor.commit();
}
return true;
}
});
In your splash screen
PreferenceManager.setDefaultValues(this, R.xml.your_setting_xml, false);
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
if (settings.getBoolean("boot_animation", true)) {
.........
You do not even need the code you posted for the Settings