Skip to content

Commit c485e09

Browse files
authored
Merge pull request #1 from hmueller01/homeoffice
Added home office button and database flag
2 parents 34ccb4a + e5cc9be commit c485e09

32 files changed

+666
-327
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ The Android App JobLogTimer keeps track of the time you work and alarms your to
44

55
# ChangeLog
66

7+
V0.19: versionCode 17, 05.11.2021 Mr
8+
- Added home office function (no forced breaks)
9+
- Optimized work per day calculation, if there is more than one work time per day
10+
- Fixed some errors raised with Android 12 (e.g. PendingIndent flag)
11+
- Switched from jcenter to mavenCentral repository
12+
713
V0.18: versionCode 16, 09.10.2021 Mr
814
- Updated targetSdkVersion to 31 (Android 12)
915

app/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ android {
2828
minSdkVersion 14
2929
targetSdkVersion 31
3030
versionCode 16
31-
versionName "0.18"
31+
versionName "0.19"
3232
}
3333

3434
signingConfigs {

app/src/main/AndroidManifest.xml

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55

66
<!-- needed to re-register the alarms after reboot -->
77
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
8-
<!-- needed to write database backup files -->
8+
<!-- needed to write database backup files,
9+
since Android 11 (API 30) MANAGE_EXTERNAL_STORAGE is needed -->
10+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
911
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
12+
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
13+
<!-- needed to set exact alarms -->
14+
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
1015

1116
<application
1217
android:allowBackup="true"
18+
android:fullBackupContent="@xml/backup_descriptor"
1319
android:icon="@drawable/ic_launcher_color"
1420
android:label="@string/app_name"
1521
android:theme="@style/AppTheme"

app/src/main/java/de/euhm/jlt/MainActivity.java

+48-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* @file MainActivity.java
3+
* @author Holger Mueller
34
*
45
* Main activity of JobLogTimer
56
*
@@ -9,6 +10,7 @@
910
package de.euhm.jlt;
1011

1112
import android.Manifest;
13+
import android.annotation.SuppressLint;
1214
import android.annotation.TargetApi;
1315
import android.app.AlertDialog;
1416
import android.content.BroadcastReceiver;
@@ -27,11 +29,13 @@
2729
import android.view.MenuItem;
2830
import android.view.MotionEvent;
2931
import android.view.View;
32+
import android.widget.CheckBox;
3033
import android.widget.ImageView;
3134
import android.widget.TextView;
3235
import android.widget.Toast;
3336

3437
import androidx.annotation.NonNull;
38+
import androidx.appcompat.app.ActionBar;
3539
import androidx.appcompat.app.ActionBarDrawerToggle;
3640
import androidx.appcompat.app.AppCompatActivity;
3741
import androidx.appcompat.widget.Toolbar;
@@ -164,7 +168,9 @@ public void onCreate(Bundle savedInstanceState) {
164168
registerReceiver(alarmReceiver, new IntentFilter(Constants.RECEIVER_MAX_WORK_ALARM));
165169

166170
// set path and name of backup database used by db export and import
167-
mBackupDbPath =
171+
// TODO: set to Android/data/de.euhm.jlt/files to avoid permission requests
172+
//mBackupDbPath = getExternalFilesDir(null).getAbsolutePath() + File.separatorChar + JobLogContract.DATABASE_NAME;
173+
mBackupDbPath =
168174
Environment.getExternalStorageDirectory().getAbsolutePath() +
169175
File.separatorChar + getResources().getString(R.string.app_name) +
170176
File.separatorChar + JobLogContract.DATABASE_NAME;
@@ -174,7 +180,7 @@ public void onCreate(Bundle savedInstanceState) {
174180
// initialize preferences with default settings
175181
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
176182
} else {
177-
if (mTimes == null) mTimes = new Times(0, 0, 0);
183+
if (mTimes == null) mTimes = new Times(0, 0, 0, false);
178184
mTimes.loadInstanceState(savedInstanceState);
179185
if (mTimes.getId() == 0 && mTimes.getTimeStart() == 0 && mTimes.getTimeEnd() == 0) {
180186
// no data loaded, remove mTimes
@@ -194,7 +200,7 @@ public void onCreate(Bundle savedInstanceState) {
194200
public void onClick(View v) {
195201
// prepare to add a new SQL row
196202
long currentTime = TimeUtil.getCurrentTimeInMillis();
197-
Times times = new Times(-1, currentTime, currentTime);
203+
Times times = new Times(-1, currentTime, currentTime, false);
198204

199205
// prepare to edit entry
200206
EditTimesFragment frag = new EditTimesFragment();
@@ -212,7 +218,10 @@ public void onClick(View v) {
212218
setSupportActionBar(supportToolbar);
213219

214220
// Specify that the Home/Up button should not be enabled, since there is no hierarchical parent.
215-
getSupportActionBar().setHomeButtonEnabled(false);
221+
ActionBar actionBar = getSupportActionBar();
222+
if (actionBar != null) {
223+
actionBar.setHomeButtonEnabled(false);
224+
}
216225

217226
// Setup the ViewPager.
218227
mViewPager = findViewById(R.id.pager);
@@ -269,6 +278,7 @@ public void onTabReselected(TabLayout.Tab tab) {
269278
Tab tab = tabLayout.newTab();
270279
tab.setCustomView(R.layout.custom_tab_title);
271280
View tab_view = tab.getCustomView();
281+
assert tab_view != null;
272282
TextView tab_title = tab_view.findViewById(R.id.title);
273283
ImageView img = tab_view.findViewById(R.id.icon);
274284
tab_title.setText(mAppSectionsPagerAdapter.getPageTitle(i));
@@ -298,7 +308,7 @@ public void onDrawerStateChanged(int newState) {
298308
}
299309

300310

301-
/* ******************************************************************
311+
/* ******************************************************************
302312
* FragmentPagerAdapter to handle tabs
303313
* ****************************************************************** */
304314

@@ -308,14 +318,15 @@ public void onDrawerStateChanged(int newState) {
308318
*/
309319
public static class AppSectionsPagerAdapter extends FragmentPagerAdapter {
310320

311-
private Context mContext;
321+
private final Context mContext;
312322

313323
public AppSectionsPagerAdapter(FragmentManager fm, Context context) {
314324
super(fm);
315325
mContext = context;
316326
}
317327

318328
@Override
329+
@NonNull
319330
public Fragment getItem(int position) {
320331
switch (position) {
321332
case 0: // Main tab
@@ -389,14 +400,11 @@ public boolean onPrepareOptionsMenu(Menu menu) {
389400
menu.findItem(R.id.action_end).setVisible(false);
390401
}
391402
// show special menu entries only on view tab
392-
if (mViewPager.getCurrentItem() == 1) {
393-
menu.findItem(R.id.action_filter).setVisible(true);
394-
} else {
395-
menu.findItem(R.id.action_filter).setVisible(false);
396-
}
403+
menu.findItem(R.id.action_filter).setVisible(mViewPager.getCurrentItem() == 1);
397404
return super.onPrepareOptionsMenu(menu);
398405
}
399406

407+
@SuppressLint("NonConstantResourceId")
400408
@Override
401409
public boolean onOptionsItemSelected(MenuItem item) {
402410
// Handle action bar item clicks here. The action bar will
@@ -406,9 +414,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
406414
// Handle presses on the action bar items
407415
switch (id) {
408416
case R.id.action_start:
409-
// make the broadcast Intent explicit by specifying the receiver class
410-
sendBroadcast(new Intent(Constants.RECEIVER_START_STOP, null, this, StartStopReceiver.class));
411-
return true;
412417
case R.id.action_end:
413418
// make the broadcast Intent explicit by specifying the receiver class
414419
sendBroadcast(new Intent(Constants.RECEIVER_START_STOP, null, this, StartStopReceiver.class));
@@ -449,6 +454,7 @@ public boolean onKeyUp(int keycode, KeyEvent event) {
449454
* Navigation drawer menu stuff (onNavigationItemSelected)
450455
* ****************************************************************** */
451456

457+
@SuppressLint("NonConstantResourceId")
452458
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
453459
@Override
454460
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
@@ -461,7 +467,7 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
461467
case R.id.nav_item_add_times:
462468
// prepare to add a new SQL row
463469
long currentTime = TimeUtil.getCurrentTimeInMillis();
464-
Times times = new Times(-1, currentTime, currentTime);
470+
Times times = new Times(-1, currentTime, currentTime, false);
465471

466472
// prepare to edit entry
467473
EditTimesFragment frag = new EditTimesFragment();
@@ -476,7 +482,7 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
476482
// backup internal database to external file
477483
// check if we have permission to write external storage
478484
if (ContextCompat.checkSelfPermission(this,
479-
Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
485+
Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
480486
PackageManager.PERMISSION_GRANTED) {
481487
// permission is not granted, ask for permission and wait for
482488
// callback method onRequestPermissionsResult gets the result of the request.
@@ -511,7 +517,7 @@ public void onClick(DialogInterface dialog, int id) {
511517
} else {
512518
// check if we have permission to read from external storage
513519
if (ContextCompat.checkSelfPermission(MainActivity.this,
514-
Manifest.permission.READ_EXTERNAL_STORAGE) !=
520+
Manifest.permission.READ_EXTERNAL_STORAGE) !=
515521
PackageManager.PERMISSION_GRANTED) {
516522
// permission is not granted, ask for permission and wait for
517523
// callback method onRequestPermissionsResult gets the result of the request.
@@ -693,6 +699,24 @@ public void onFinishFilterFragment(int id, int month, int year) {
693699
}
694700
}
695701

702+
public void onCheckboxClicked(View view) {
703+
// Check which checkbox was clicked
704+
switch(view.getId()) {
705+
case R.id.homeoffice_cb:
706+
// save the Home Office check box into mTW dataset
707+
if (mTW.getWorkStarted()) {
708+
mTW.setHomeOffice(((CheckBox) view).isChecked());
709+
mMainSectionFragment.updateTimesView();
710+
} else {
711+
((CheckBox) view).toggle();
712+
Toast.makeText(this, R.string.work_not_started, Toast.LENGTH_LONG).show();
713+
}
714+
break;
715+
default:
716+
throw new IllegalStateException("Unexpected value: " + view.getId());
717+
}
718+
}
719+
696720
public void showDatePickerDialog(View v) {
697721
if (mTW.getWorkStarted()) {
698722
// do not set mTW.timeStart to current time, otherwise we can not cancel ...
@@ -732,6 +756,7 @@ public void showTimePickerDialog_EndTime(View v) {
732756
}
733757
}
734758

759+
@SuppressLint("NonConstantResourceId")
735760
@Override
736761
public void onFinishTimePickerFragment(Calendar cal, int titleId) {
737762
// set time depending on titleId
@@ -756,6 +781,7 @@ public void onFinishTimePickerFragment(Calendar cal, int titleId) {
756781
AlarmUtils.setAlarms(this, mTW);
757782
}
758783

784+
@SuppressLint("NonConstantResourceId")
759785
@Override
760786
public void onFinishDatePickerFragment(Calendar cal, int titleId) {
761787
// set time depending on titleId
@@ -771,6 +797,8 @@ public void onFinishDatePickerFragment(Calendar cal, int titleId) {
771797
mTW.setCalEnd(calTimeEnd);
772798
}
773799
break;
800+
default:
801+
throw new IllegalStateException("Unexpected value: " + titleId);
774802
}
775803
// update view and alarms ...
776804
mMainSectionFragment.updateTimesView();
@@ -782,6 +810,7 @@ public void onFinishDatePickerFragment(Calendar cal, int titleId) {
782810
public void onRequestPermissionsResult(int requestCode,
783811
@NonNull String[] permissions,
784812
@NonNull int[] grantResults) {
813+
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
785814
// Handle the permissions request response.
786815
switch (requestCode) {
787816
case Constants.PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE:
@@ -800,12 +829,12 @@ public void onRequestPermissionsResult(int requestCode,
800829
mViewSectionFragment.importDatabase(mBackupDbPath);
801830
}
802831
break;
803-
}
832+
}
804833
}
805834

806835

807836
@Override
808-
public void onSaveInstanceState(Bundle savedInstanceState) {
837+
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
809838
// Always call the superclass so it can save the view hierarchy state
810839
super.onSaveInstanceState(savedInstanceState);
811840
if (mTimes != null) {

0 commit comments

Comments
 (0)