├── .classpath
├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── misc.xml
├── modules.xml
├── scopes
│ └── scope_settings.xml
├── vcs.xml
└── workspace.xml
├── .project
├── .settings
└── org.eclipse.jdt.core.prefs
├── AndroidManifest.xml
├── LICENSE
├── README.md
├── ServiceDroid-release.apk
├── ServiceDroid.iml
├── build.gradle
├── gen
└── com
│ └── monstarlab
│ └── servicedroid
│ └── R.java
├── gradlew.bat
├── lint.xml
├── local.properties
├── manifest-merger-release-report.txt
├── project.properties
├── res
├── drawable-hdpi
│ ├── btn_carry.png
│ ├── menu_add.png
│ ├── menu_calendar.png
│ ├── menu_delete.png
│ ├── menu_directions.png
│ ├── menu_edit.png
│ ├── menu_pause.png
│ ├── menu_placement.png
│ ├── menu_play.png
│ ├── menu_sort.png
│ └── menu_visit.png
├── drawable-mdpi
│ ├── btn_carry.png
│ ├── menu_add.png
│ ├── menu_calendar.png
│ ├── menu_delete.png
│ ├── menu_directions.png
│ ├── menu_edit.png
│ ├── menu_pause.png
│ ├── menu_placement.png
│ ├── menu_play.png
│ ├── menu_sort.png
│ └── menu_visit.png
├── drawable
│ ├── book.png
│ ├── btn_callbook.png
│ ├── btn_stats.png
│ ├── btn_time.png
│ ├── header_bar.xml
│ └── icon.png
├── layout
│ ├── call_edit.xml
│ ├── call_row.xml
│ ├── call_show.xml
│ ├── calls.xml
│ ├── footer_buttons.xml
│ ├── main.xml
│ ├── place_book.xml
│ ├── place_magazine.xml
│ ├── placement_row.xml
│ ├── return_visit.xml
│ ├── stats.xml
│ ├── time.xml
│ ├── time_edit.xml
│ └── time_row.xml
├── menu
│ ├── call_show.xml
│ ├── call_show_anon.xml
│ ├── calls.xml
│ ├── stats.xml
│ └── time.xml
├── values-da
│ └── strings.xml
├── values-de
│ └── strings.xml
├── values-es
│ └── strings.xml
├── values-fr
│ └── strings.xml
├── values-it
│ └── strings.xml
├── values-ko
│ └── strings.xml
├── values-nl
│ └── strings.xml
├── values-pt
│ └── strings.xml
└── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── ids.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── com
└── monstarlab
└── servicedroid
├── activity
├── CallEditActivity.java
├── CallShowActivity.java
├── CallsActivity.java
├── PlacementActivity.java
├── ReturnVisitActivity.java
├── ServiceDroidActivity.java
├── StatisticsActivity.java
├── TimeActivity.java
└── TimeEditActivity.java
├── model
├── BackupWorker.java
├── Models.java
├── ServiceDroidBackupAgent.java
├── ServiceProvider.java
└── WrapManager.java
├── receiver
├── BootReceiver.java
└── NotificationReceiver.java
├── service
├── BackupService.java
├── ReminderService.java
└── TimerService.java
└── util
├── Changelog.java
├── ServiceDroidDocument.java
└── TimeUtil.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/*
2 | gen/*
3 | .gradle
4 | .idea/*
5 | build/
6 | gradle/
7 | *.apk
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | ServiceDroid
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ServiceDroid
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.6
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.6
12 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
13 |
14 |
16 |
17 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
29 |
30 |
32 |
33 |
35 |
36 |
38 |
39 |
41 |
42 |
44 |
45 |
47 |
48 |
50 |
51 |
52 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010-2016 Sean McArthur
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ServiceDroid
2 | ==================
3 |
4 | ServiceDroid is an Android application built to assist Jehovah's Witnesses doing volunteer work.
5 |
6 | Features
7 | -------
8 |
9 | _Version 1.4_
10 |
11 | * Design improvements
12 | * Added combination placement of Watchtower & Awake
13 | * Bible studies received a mahor change. They are now recorded when
14 | making a return visit.
15 | * Time Entries and Return Visits can have notes.
16 | * Backup will always use the SD card when available.
17 | * New Translations: Italian (thanks to Stefano Rinolfi)
18 |
19 | _Version 1.3_
20 |
21 | * Back up your data to your Google account
22 | * Edit Return Visit details
23 | * Change the month of the Time view
24 | * Translated into Spanish, Portuguese, German, French, and Danish (thanks to Dunnia Lempert, Ruben Reis, Manuel Haas, David V., and Flemming Jacobsen).
25 |
26 | _Version 1.2_
27 |
28 | * Anonymous Placements
29 | * Get directions to an RV
30 | * View Service Year stats
31 |
32 | _Version 1.1_
33 |
34 | * Start a timer and automatic insert when timer stopped.
35 | * Sort RVs alphabetically, by last visited
36 | * See Bible Study status in list of Calls
37 | * Offer to Round Up or Carry Over minutes when sending in time.
38 |
39 | _Version 1.0_
40 |
41 | * Insert time manually
42 | * See stats for the month
43 | * Insert Calls
44 | * Return on a Call
45 | * Email monthly stats (to your Group Overseer)
46 | * Add placements to RVs
47 | * Notification at month's end to send in Time.
48 |
49 | Planned
50 | -------
51 |
52 | _Future Versions_
53 |
54 | * Transfer Calls to other ServiceDroid users
55 | * View map of all RVs
56 | * Sort calls by distance
57 |
58 |
59 | Copyright
60 | ---------
61 |
62 | MIT License. Copyright 2010-2011 [Sean McArthur](http://seanmonstar.com).
63 |
--------------------------------------------------------------------------------
/ServiceDroid-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/ServiceDroid-release.apk
--------------------------------------------------------------------------------
/ServiceDroid.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | import java.util.regex.Pattern
2 |
3 | buildscript {
4 | repositories {
5 | mavenCentral()
6 | //maven { url 'http://download.crashlytics.com/maven' }
7 |
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:1.0.0'
11 | //classpath 'com.crashlytics.tools.gradle:crashlytics-gradle:1.+'
12 |
13 | }
14 | }
15 | apply plugin: 'com.android.application'
16 | //apply plugin: 'crashlytics'
17 |
18 | repositories {
19 | mavenCentral()
20 | //maven { url 'http://download.crashlytics.com/maven' }
21 |
22 | }
23 |
24 | dependencies {
25 |
26 | //compile 'com.crashlytics.android:crashlytics:1.+'
27 | compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
28 | compile 'com.android.support:support-v4:21.0.3'
29 | //compile 'com.google.android.gms:play-services:4.+'
30 |
31 | //instrumentTestCompile files('libs/espresso-1.0-SNAPSHOT-bundled.jar')
32 |
33 | }
34 |
35 | android {
36 | compileSdkVersion 21
37 | buildToolsVersion "19.1.0"
38 |
39 | defaultConfig {
40 | minSdkVersion 7
41 | targetSdkVersion 21
42 |
43 | }
44 |
45 | compileOptions {
46 | sourceCompatibility JavaVersion.VERSION_1_7
47 | targetCompatibility JavaVersion.VERSION_1_7
48 | }
49 |
50 | sourceSets {
51 | main {
52 | manifest.srcFile 'AndroidManifest.xml'
53 | java.srcDirs = ['src']
54 |
55 | resources.srcDirs = ['src']
56 | aidl.srcDirs = ['src']
57 |
58 | renderscript.srcDirs = ['src']
59 |
60 | res.srcDirs = ['res']
61 | assets.srcDirs = ['assets']
62 |
63 | }
64 | }
65 |
66 | /*
67 | signingConfigs {
68 | debug {
69 | storeFile file("C:\\Users\\Sean\\.android\\debug.keystore")
70 | }
71 | release {
72 | storeFile file("D:\\Users\\Sean\\Dropbox\\android\\keystore\\sean_android_key.keystore")
73 | storePassword "boo"
74 | keyAlias "sean_android_key"
75 | keyPassword "boo"
76 | }
77 | }
78 | */
79 |
80 | buildTypes {
81 | debug {
82 | versionNameSuffix = "-dev"
83 | //zipAlign = true
84 | }
85 | release {
86 | //runProguard true
87 | //proguardFile file('proguard-project.txt')
88 | //signingConfig signingConfigs.release
89 | }
90 | }
91 | }
92 |
93 | task('increaseVersionName') << {
94 | def manifestFile = file('AndroidManifest.xml')
95 | def patternBuildNumber = Pattern.compile("versionName=\"(\\d+\\.\\d+\\.\\d+\\.)(\\d+)(-.+)?\"")
96 | def manifestText = manifestFile.getText()
97 | def matcherBuilderNumber = patternBuildNumber.matcher(manifestText)
98 | matcherBuilderNumber.find()
99 | def versionName = matcherBuilderNumber.group(1)
100 | def buildNumber = Integer.parseInt(matcherBuilderNumber.group(2))
101 | def buildType = matcherBuilderNumber.group(3)
102 | def manifestContent = matcherBuilderNumber.replaceAll("versionName=\"" + versionName + (++buildNumber) + ((buildType == null) ? "" : buildType) + "\"");
103 | manifestFile.write(manifestContent)
104 | }
105 |
106 | task('increaseVersionCode') << {
107 | def manifestFile = file('AndroidManifest.xml')
108 | def patternBuildNumber = Pattern.compile("versionCode=\"(\\d+)\"")
109 | def manifestText = manifestFile.getText()
110 | def matcherBuilderNumber = patternBuildNumber.matcher(manifestText)
111 | matcherBuilderNumber.find()
112 | def versionCode = Integer.parseInt(matcherBuilderNumber.group(1)) + 1;
113 | def manifestContent = matcherBuilderNumber.replaceAll("versionCode=\"${versionCode}\"");
114 | manifestFile.write(manifestContent)
115 | }
116 |
117 | /*
118 | task('askForPasswords') << {
119 | // Must create String because System.readPassword() returns char[]
120 | // (and assigning that below fails silently)
121 | def storePw = new String(System.console().readPassword("Keystore password: "))
122 | def keyPw = new String(System.console().readPassword("Key password: "))
123 |
124 | android.signingConfigs.release.storePassword = storePw
125 | android.signingConfigs.release.keyPassword = keyPw
126 | }
127 | */
128 |
129 | android.applicationVariants.all { variant ->
130 | variant.generateBuildConfig.dependsOn "increaseVersionName"
131 | if (variant.buildType.name == 'release' || variant.buildType.name == 'beta') {
132 | variant.generateBuildConfig.dependsOn "increaseVersionCode"
133 | }
134 | }
135 |
136 | /*
137 | tasks.whenTaskAdded { theTask ->
138 | if (theTask.name.equals("packageRelease")) {
139 | theTask.dependsOn "askForPasswords"
140 | }
141 | }
142 | */
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | ## This file is automatically generated by Android Studio.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 | #
7 | # Location of the SDK. This is only used by Gradle.
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | #Wed Jan 13 18:07:49 PST 2016
11 | sdk.dir=D\:\\Users\\Sean\\AppData\\Local\\Android\\sdk
12 |
--------------------------------------------------------------------------------
/manifest-merger-release-report.txt:
--------------------------------------------------------------------------------
1 | -- Merging decision tree log ---
2 | manifest
3 | ADDED from AndroidManifest.xml:2:1
4 | xmlns:android
5 | ADDED from AndroidManifest.xml:2:11
6 | package
7 | ADDED from AndroidManifest.xml:3:2
8 | android:versionName
9 | ADDED from AndroidManifest.xml:3:40
10 | android:versionCode
11 | ADDED from AndroidManifest.xml:3:71
12 | INJECTED from AndroidManifest.xml:0:0
13 | INJECTED from AndroidManifest.xml:0:0
14 | uses-permission#android.permission.WRITE_EXTERNAL_STORAGE
15 | ADDED from AndroidManifest.xml:5:2
16 | android:name
17 | ADDED from AndroidManifest.xml:5:19
18 | uses-permission#android.permission.RECEIVE_BOOT_COMPLETED
19 | ADDED from AndroidManifest.xml:6:2
20 | android:name
21 | ADDED from AndroidManifest.xml:6:19
22 | application
23 | ADDED from AndroidManifest.xml:8:2
24 | MERGED from com.actionbarsherlock:actionbarsherlock:4.4.0:4:3
25 | MERGED from com.android.support:support-v4:21.0.3:16:5
26 | android:label
27 | ADDED from AndroidManifest.xml:8:45
28 | android:allowBackup
29 | ADDED from AndroidManifest.xml:9:9
30 | android:icon
31 | ADDED from AndroidManifest.xml:8:15
32 | android:fullBackupOnly
33 | ADDED from AndroidManifest.xml:10:9
34 | android:theme
35 | ADDED from AndroidManifest.xml:11:3
36 | android:installLocation
37 | ADDED from AndroidManifest.xml:12:3
38 | meta-data#com.google.android.backup.api_key
39 | ADDED from AndroidManifest.xml:14:3
40 | android:name
41 | ADDED from AndroidManifest.xml:14:14
42 | android:value
43 | ADDED from AndroidManifest.xml:15:7
44 | activity#com.monstarlab.servicedroid.activity.ServiceDroidActivity
45 | ADDED from AndroidManifest.xml:20:3
46 | android:label
47 | ADDED from AndroidManifest.xml:21:4
48 | android:name
49 | ADDED from AndroidManifest.xml:20:13
50 | intent-filter#android.intent.action.MAIN+android.intent.category.LAUNCHER
51 | ADDED from AndroidManifest.xml:22:4
52 | action#android.intent.action.MAIN
53 | ADDED from AndroidManifest.xml:23:5
54 | android:name
55 | ADDED from AndroidManifest.xml:23:13
56 | category#android.intent.category.LAUNCHER
57 | ADDED from AndroidManifest.xml:24:5
58 | android:name
59 | ADDED from AndroidManifest.xml:24:15
60 | activity#com.monstarlab.servicedroid.activity.TimeActivity
61 | ADDED from AndroidManifest.xml:27:3
62 | android:label
63 | ADDED from AndroidManifest.xml:28:4
64 | android:name
65 | ADDED from AndroidManifest.xml:27:13
66 | activity#com.monstarlab.servicedroid.activity.TimeEditActivity
67 | ADDED from AndroidManifest.xml:30:3
68 | android:label
69 | ADDED from AndroidManifest.xml:31:4
70 | android:name
71 | ADDED from AndroidManifest.xml:30:13
72 | activity#com.monstarlab.servicedroid.activity.CallsActivity
73 | ADDED from AndroidManifest.xml:33:3
74 | android:label
75 | ADDED from AndroidManifest.xml:34:4
76 | android:name
77 | ADDED from AndroidManifest.xml:33:13
78 | activity#com.monstarlab.servicedroid.activity.CallShowActivity
79 | ADDED from AndroidManifest.xml:36:3
80 | android:label
81 | ADDED from AndroidManifest.xml:37:4
82 | android:name
83 | ADDED from AndroidManifest.xml:36:13
84 | activity#com.monstarlab.servicedroid.activity.CallEditActivity
85 | ADDED from AndroidManifest.xml:39:3
86 | android:label
87 | ADDED from AndroidManifest.xml:40:4
88 | android:name
89 | ADDED from AndroidManifest.xml:39:13
90 | activity#com.monstarlab.servicedroid.activity.ReturnVisitActivity
91 | ADDED from AndroidManifest.xml:42:3
92 | android:label
93 | ADDED from AndroidManifest.xml:43:4
94 | android:name
95 | ADDED from AndroidManifest.xml:42:13
96 | activity#com.monstarlab.servicedroid.activity.PlacementActivity
97 | ADDED from AndroidManifest.xml:45:3
98 | android:label
99 | ADDED from AndroidManifest.xml:46:4
100 | android:name
101 | ADDED from AndroidManifest.xml:45:13
102 | activity#com.monstarlab.servicedroid.activity.StatisticsActivity
103 | ADDED from AndroidManifest.xml:48:3
104 | android:label
105 | ADDED from AndroidManifest.xml:49:4
106 | android:name
107 | ADDED from AndroidManifest.xml:48:13
108 | provider#com.monstarlab.servicedroid.model.ServiceProvider
109 | ADDED from AndroidManifest.xml:52:3
110 | android:exported
111 | ADDED from AndroidManifest.xml:53:13
112 | android:authorities
113 | ADDED from AndroidManifest.xml:54:7
114 | android:name
115 | ADDED from AndroidManifest.xml:52:13
116 | service#com.monstarlab.servicedroid.service.ReminderService
117 | ADDED from AndroidManifest.xml:56:3
118 | android:name
119 | ADDED from AndroidManifest.xml:56:12
120 | service#com.monstarlab.servicedroid.service.TimerService
121 | ADDED from AndroidManifest.xml:57:3
122 | android:name
123 | ADDED from AndroidManifest.xml:57:12
124 | service#com.monstarlab.servicedroid.service.BackupService
125 | ADDED from AndroidManifest.xml:58:3
126 | android:name
127 | ADDED from AndroidManifest.xml:58:12
128 | receiver#com.monstarlab.servicedroid.receiver.NotificationReceiver
129 | ADDED from AndroidManifest.xml:60:3
130 | android:name
131 | ADDED from AndroidManifest.xml:60:13
132 | receiver#com.monstarlab.servicedroid.receiver.BootReceiver
133 | ADDED from AndroidManifest.xml:61:3
134 | android:permission
135 | ADDED from AndroidManifest.xml:62:4
136 | android:name
137 | ADDED from AndroidManifest.xml:61:13
138 | intent-filter#android.intent.action.BOOT_COMPLETED+android.intent.category.DEFAULT
139 | ADDED from AndroidManifest.xml:63:4
140 | action#android.intent.action.BOOT_COMPLETED
141 | ADDED from AndroidManifest.xml:64:5
142 | android:name
143 | ADDED from AndroidManifest.xml:64:13
144 | category#android.intent.category.DEFAULT
145 | ADDED from AndroidManifest.xml:65:5
146 | android:name
147 | ADDED from AndroidManifest.xml:65:15
148 | uses-sdk
149 | INJECTED from AndroidManifest.xml:0:0 reason: use-sdk injection requested
150 | MERGED from com.actionbarsherlock:actionbarsherlock:4.4.0:3:3
151 | MERGED from com.android.support:support-v4:21.0.3:15:5
152 | android:targetSdkVersion
153 | INJECTED from AndroidManifest.xml:0:0
154 | INJECTED from AndroidManifest.xml:0:0
155 | android:minSdkVersion
156 | INJECTED from AndroidManifest.xml:0:0
157 | INJECTED from AndroidManifest.xml:0:0
158 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Indicates whether an apk should be generated for each density.
14 | split.density=false
15 | # Project target.
16 | target=android-19
17 |
18 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_carry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/btn_carry.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_add.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_calendar.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_delete.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_directions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_directions.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_edit.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_pause.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_placement.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_placement.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_play.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_sort.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_sort.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/menu_visit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-hdpi/menu_visit.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_carry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/btn_carry.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_add.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_calendar.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_delete.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_directions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_directions.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_edit.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_pause.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_placement.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_placement.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_play.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_sort.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_sort.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/menu_visit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable-mdpi/menu_visit.png
--------------------------------------------------------------------------------
/res/drawable/book.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable/book.png
--------------------------------------------------------------------------------
/res/drawable/btn_callbook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable/btn_callbook.png
--------------------------------------------------------------------------------
/res/drawable/btn_stats.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable/btn_stats.png
--------------------------------------------------------------------------------
/res/drawable/btn_time.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable/btn_time.png
--------------------------------------------------------------------------------
/res/drawable/header_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 | -
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/res/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanmonstar/ServiceDroid/008b511c022b067a3be6304dfcc11cc1eea4999c/res/drawable/icon.png
--------------------------------------------------------------------------------
/res/layout/call_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
16 |
22 |
23 |
29 |
30 |
35 |
36 |
44 |
45 |
46 |
47 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/res/layout/call_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
21 |
34 |
35 |
44 |
--------------------------------------------------------------------------------
/res/layout/call_show.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
25 |
26 |
27 |
40 |
41 |
42 |
43 |
44 |
53 |
54 |
61 |
65 |
70 |
71 |
--------------------------------------------------------------------------------
/res/layout/calls.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
12 |
21 |
22 |
23 |
24 |
27 |
32 |
33 |
--------------------------------------------------------------------------------
/res/layout/footer_buttons.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
18 |
19 |
20 |
25 |
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
21 |
22 |
29 |
30 |
31 |
32 |
36 |
37 |
44 |
45 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/res/layout/place_book.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
16 |
17 |
20 |
22 |
23 |
26 |
27 |
29 |
30 |
33 |
34 |
37 |
42 |
52 |
57 |
58 |
59 |
60 |
61 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/res/layout/place_magazine.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
17 |
18 |
25 |
31 |
32 |
41 |
44 |
51 |
58 |
59 |
60 |
69 |
70 |
74 |
75 |
76 |
79 |
80 |
83 |
88 |
98 |
103 |
104 |
105 |
106 |
107 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/res/layout/placement_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
25 |
26 |
27 |
41 |
42 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/res/layout/return_visit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
12 |
15 |
16 |
20 |
21 |
23 |
24 |
28 |
29 |
36 |
37 |
38 |
39 |
40 |
42 |
43 |
--------------------------------------------------------------------------------
/res/layout/stats.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
22 |
23 |
24 |
29 |
30 |
37 |
38 |
44 |
45 |
46 |
51 |
56 |
57 |
58 |
59 |
64 |
69 |
70 |
71 |
72 |
77 |
82 |
83 |
84 |
85 |
86 |
91 |
96 |
97 |
98 |
99 |
104 |
109 |
110 |
111 |
112 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/res/layout/time.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
22 |
23 |
24 |
25 |
28 |
33 |
34 |
--------------------------------------------------------------------------------
/res/layout/time_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
10 |
13 |
17 |
18 |
22 |
23 |
27 |
28 |
32 |
33 |
37 |
38 |
43 |
44 |
45 |
46 |
47 |
49 |
50 |
--------------------------------------------------------------------------------
/res/layout/time_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
33 |
34 |
35 |
48 |
--------------------------------------------------------------------------------
/res/menu/call_show.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
--------------------------------------------------------------------------------
/res/menu/call_show_anon.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/res/menu/calls.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
--------------------------------------------------------------------------------
/res/menu/stats.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
--------------------------------------------------------------------------------
/res/menu/time.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
--------------------------------------------------------------------------------
/res/values-da/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tilføj genbesøg
4 | Tilføj tid
5 | Adresse
6 | Uformelle besøg
7 | ServiceDroid
8 | Vågn op!
9 | Bibel
10 | Bibelstudier
11 | Bibelstudium
12 | Hvad er det Bibelen virkelig lærer?
13 | Bog
14 | Bøger
15 | Brochure
16 | Brochurer
17 | Besøg
18 | Fortryd
19 | Bekræft
20 | Vagttårnet & Vågn op!
21 | Når man mister en han holder af
22 | Afsat litteratur
23 | Dato
24 | Slet besøg
25 | Vil du gerne slette alt afsat litteratur og besøg ved dette genbesøg?
26 | Slet afsat litteratur
27 | Slet besøg
28 | Slet tid
29 | Vis vej
30 | Rediger
31 | Overskydende minutter
32 | Timer
33 | t
34 | t
35 | Udgave
36 | Sidst besøgt d. %s
37 | Tid i tjenesten
38 | Blad
39 | Blade
40 | Besøgt igen
41 | min
42 | min
43 | Måned
44 | Månedligt
45 |
46 | - Januar
47 | - Februar
48 | - Marts
49 | - April
50 | - Maj
51 | - Juni
52 | - Juli
53 | - August
54 | - September
55 | - Oktober
56 | - November
57 | - December
58 |
59 | Navn
60 | Nej
61 | Tryk MENU for at oprette et nyt genbesøg.
62 | Tryk MENU for at markere afsætning af litteratur.
63 | Tryk MENU for at registrere tid for denne måned.
64 | Noter
65 | Cool!
66 | Andet...
67 | Afsæt
68 | Afsette publikationer
69 | Kvantitet
70 | Hvad kræver Gud af os?
71 | Du har foretaget et genbesøg d. %s.
72 | Vil du runde din tid op, eller overføre overskydende minutter til næste måned?
73 | Overfør overskydende
74 | Rund op
75 | Genbesøg
76 | Genbesøg
77 | Send
78 | Sendt af...
79 | Send din tjenesterapport
80 | Tjenesteår
81 | Tjenestetid for %s
82 | Sorter
83 | Alfabetisk
84 | Ældste af mine besøg
85 | Start tid
86 | Rapport
87 | Stop tid
88 | Traktat
89 | Traktater
90 | Tid
91 | Din tid er overskredet
92 | Tid i tjenesten: %s
93 | Svirp til venstre eller højre for at ændre tidsperioden.
94 | Tjeneste-Timer Aktiv
95 | Tips
96 | Video
97 | Filmvisninger
98 | Vagttårnet
99 | År
100 | Ja
101 |
102 |
--------------------------------------------------------------------------------
/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Neues Gespräch
4 | Zeit eintragen
5 | Adresse
6 | Anonyme Literatur
7 | ServiceDroid
8 | Erwachet!
9 | Bibel
10 | Heimbibelstudien
11 | Heimbibelstudium
12 | Was lehrt die Bibel wirklich?
13 | Buch
14 | Bücher
15 | Broschüre
16 | Broschüren
17 | Gesprächsnotizen
18 | Abbrechen
19 | Bestätigen
20 | Wachtturm & Erwachet!
21 | Wenn ein geliebter Mensch gestorben ist
22 | Neue Literatur
23 | Datum
24 | Gespräch entfernen
25 | Willst du alle Besuchs- und Literaturnotizen zu diesem Gespräch löschen?
26 | Literatur entfernen
27 | Besuch entfernen
28 | Predigtdienststunden löschen
29 | Navigation
30 | Bearbeiten
31 | Extra Minuten
32 | Stunden
33 | St
34 | St
35 | Ausgabe
36 | Zuletzt besucht: %s
37 | Predigtdienststunden
38 | Zeitschrift
39 | Zeitschriften
40 | Besucht am
41 | min
42 | min
43 | Monat
44 | Monatlich
45 |
46 | - Januar
47 | - Februar
48 | - März
49 | - April
50 | - Mai
51 | - Juni
52 | - Juli
53 | - August
54 | - September
55 | - Oktober
56 | - November
57 | - Dezember
58 |
59 | Name
60 | Nein
61 | MENÜ drücken um eine Gesprächsnotiz anzulegen.
62 | MENÜ drücken um abgegebene Literatur zu speichern.
63 | MENÜ drücken um Predigtdienststunden für diesen Monat hinzuzufügen.
64 | Bemerkungen
65 | Cool!
66 | Andere
67 | Literatur
68 | Literaturen
69 | Menge
70 | Was erwartet Gott von uns?
71 | Du hast bei %s einen Rückbesuch gemacht.
72 | Möchtest du deine Zeit aufrunden, oder die übrigen Minuten in den nächsten Monat übernehmen?
73 | Übernehmen
74 | Aufrunden
75 | Rückbesuch
76 | Rückbesuche
77 | Senden
78 | Gesendet von ...
79 | Versende deinen Bericht!
80 | Dienstjahr
81 | Predigtdienststunden für %s
82 | sortieren
83 | Alphabetisch
84 | Ältester Besuch
85 | Timer starten
86 | Übersicht
87 | Timer stoppen
88 | Zeit
89 | Timer abgelaufen
90 | Predigtdienststunden: %s
91 | Swipe nach links oder rechts ändern den Zeitraum.
92 | Timer aktiviert
93 | Tipps
94 | Video
95 | Videos
96 | Wachtturm
97 | What\'s New!
98 | Jahr
99 | Ja
100 | Faltblatt
101 | Faltblätter
102 |
103 |
--------------------------------------------------------------------------------
/res/values-es/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Añadir Revisita
4 | Añadir Tiempo
5 | Dirección
6 | Literatura
7 | ServicioDroid
8 | ¡Despertad!
9 | Biblia
10 | Estudios Bíblicos
11 | Estudio Bíblico
12 | ¿Qué enseña realmente la Biblia?
13 | Libro
14 | Libros
15 | Folleto
16 | Folletos
17 | Datos de Revisitas
18 | Cancelar
19 | Confirmar
20 | Atalaya y Despertad
21 | Cuando muere un ser querido
22 | Cree Colocación de Literatura
23 | Fecha
24 | Borre Revisita
25 | Le gustaría borrar todas las visitas y literatura asociadas con esta revisita?
26 | Borre Colocación
27 | Borre Revisita
28 | Borre Tiempo
29 | Direcciones
30 | Editar
31 | Minutos extras
32 | Horas
33 | hr
34 | hrs
35 | Numero
36 | Ultima Visita: %s
37 | Tiempo en el servicio
38 | Revista
39 | Revistas
40 | Volví a la Revisita
41 | min
42 | mins
43 | Mes
44 | Mensualmente
45 |
46 | - Enero
47 | - Febrero
48 | - Marzo
49 | - Abril
50 | - Mayo
51 | - Junio
52 | - Julio
53 | - Agosto
54 | - Septiembre
55 | - Octubre
56 | - Noviembre
57 | - Diciembre
58 |
59 | Nombre
60 | Presione MENU para registrar una nueva revisita.
61 | Presione MENU para registrar una nueva colocación.
62 | Presione MENU para registrar el tiempo del mes.
63 | Notas
64 | ¡Qué bien!
65 | Otros...
66 | Colocación
67 | Publicaciones
68 | Cantidad
69 | Que exige Dios de nosotros
70 | Hizo una revisita a %s.
71 | ¿Le gustaría que los minutos que tienen se aproximen a la hora o pasarlos para el próximo mes?
72 | Pasar al próximo mes
73 | Aproximar
74 | Revisita
75 | Revisitas
76 | Enviar
77 | Enviado por...
78 | Envié su informe de servicio
79 | Año de Servicio
80 | Informe de Servicio para el Mes de %s
81 | Ordene
82 | Alfabéticamente
83 | La visita más antigua
84 | Empiece el Tiempo
85 | Estadística
86 | Pare el Tiempo
87 | Tiempo
88 | ¡Recuerde entregar su informe!
89 | Tiempo en el servicio: %s
90 | Pase a la izquierda o derecha para cambiar el período de tiempo.
91 | Cronometro Activo
92 | Sugerencias
93 | Tratado
94 | Tratados
95 | Video
96 | Videos
97 | Atalaya
98 | Que es nuevo
99 | Año
100 | Sí
101 | No
102 | Borre informacion associada?
103 | Borre Revisita
104 | Borre Todas
105 |
--------------------------------------------------------------------------------
/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Ajout visite
4 | Ajout temps
5 | Addresse
6 | Placements anonymes
7 | ServiceDroid
8 | Reveillez-vous !
9 | Bible
10 | Études
11 | Étude
12 | Qu\'enseigne réellement la bible ?
13 | Livre
14 | Livress
15 | Brochure
16 | Brochures
17 | Visites
18 | Annuler
19 | Tour de garde & Réveillez-vous!
20 | Quand on perd un être cher
21 | Veuillez confirmer
22 | Nouveau placement
23 | Date
24 | Supprimer visite
25 | Supprimer tous les placements et visites associés à cette personne?
26 | Supprimer placement
27 | Supprimer nouvelle visite
28 | Supprimer temps
29 | Itinéraire
30 | Modifier
31 | Heures
32 | hr
33 | hrs
34 | Numéro
35 | Dernière visite : %s
36 | Temps de prédication
37 | Périodique
38 | Périodiques
39 | Nouvelle visite
40 | min
41 | min
42 | Mois
43 | Mensuel
44 |
45 | - Janvier
46 | - Février
47 | - Mars
48 | - Avril
49 | - Mai
50 | - Juin
51 | - Juillet
52 | - Août
53 | - Septembre
54 | - Octobre
55 | - Novembre
56 | - Décembre
57 |
58 | Nom
59 | Non
60 | Appuyez sur MENU pour ajouter une visite.
61 | Appuyez sur MENU pour ajouter un placement.
62 | Appuyez sur MENU pour ajouter des heures à ce mois.
63 | Notes
64 | Cool !
65 | Autres...
66 | Placement
67 | Placements
68 | Quantité
69 | Qu\'est-ce que Dieu attend de nous ?
70 | Vous avez fait une nouvelle visite à %s.
71 | Voulez-vous arrondir votre temps à l\'heure suppérieure, ou reporter les minutes en plus au mois suivant ?
72 | Reporter
73 | Arrondir
74 | Nouvelle visite
75 | Nouvelles visites
76 | Envoyer
77 | Envoyer par...
78 | Envoyez votre rapport de service
79 | Année de service
80 | Rapport de service pour %s
81 | Trier
82 | Ordre alphabétique
83 | Plus ancienne visite
84 | Heure de début
85 | Statistiques
86 | Heure de fin
87 | Temps
88 | Souvenez-vous d\'envoyer votre rapport !
89 | Temps de prédication : %s
90 | Glissez vers la gauche ou à droite pour changer la période de temps.
91 | Chrono prédic actif
92 | Astuces
93 | Vidéo
94 | Vidéos
95 | Tour de Garde
96 | Quoi de neuf !
97 | Année
98 | Oui
99 | Tract
100 | Tracts
101 |
102 |
--------------------------------------------------------------------------------
/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Aggiungere Visita
4 | Aggiungere Servizio
5 | Indirizzo
6 | Distribuzioni Anonime
7 | ServiceDroid
8 | Svegliatevi!
9 | Bibbia
10 | Studi Bibblici
11 | Studio Bibblico
12 | Cosa insegna realmente la Bibbia?
13 | Libro
14 | Libri
15 | Opuscolo
16 | Opuscoli
17 | Nota
18 | Cancella
19 | Confermare
20 | Torre di Guardia e Svegliatevi!
21 | Quando muore una persona cara
22 | Creare Itinerario delle riviste
23 | Data
24 | Cancella Nota
25 | Vuoi cancellare tutte le pubblicazioni e le visite ulteriori associate a questa nota?
26 | Cancella Itinerario
27 | Cancella Visita
28 | Cancella Ore
29 | Percorso
30 | Edit
31 | Ore
32 | hr
33 | hrs
34 | Numero
35 | Ultima Visita: %s
36 | Tempo nel Servizio
37 | Rivista
38 | Riviste
39 | Rivisitato
40 | min
41 | mins
42 | Mese
43 | Mensilmente
44 |
45 | - Gennaio
46 | - Febbraio
47 | - Marzo
48 | - Aprile
49 | - Maggio
50 | - Giugno
51 | - Luglio
52 | - Agosto
53 | - Settembre
54 | - Ottobre
55 | - Novembre
56 | - Dicembre
57 |
58 | Nome
59 | Premere MENU per creare una nuova Visita.
60 | Premere MENU per creare un nuovo itinerario delle riviste.
61 | Premere MENU per registrare un nuovo orario di servizio.
62 | Note
63 | Ottimo!
64 | Other...
65 | Distribuzione
66 | Distribuzioni
67 | Cosa richiede Dio da noi?
68 | Hai fatto una visita ulteriore il %s.
69 | Si preferisce arrotondare le ore di servizio o riportare i minuti extra al mese successivo?
70 | Riportare
71 | Arrotondare
72 | Visita Ulteriore
73 | Visite Ulteriori
74 | Email
75 | Inviato da...
76 | Inviare nel proprio orario di servizio
77 | Servizio Anno
78 | Tempo di servizio per %s
79 | Ordina
80 | Ordine alfabetico
81 | Visite più vecchie
82 | Avvia il tempo
83 | Statistiche
84 | Ferma il tempo
85 | Tempo
86 | Preparare rapporto di servizio!
87 | Tempo nel servizio: %s
88 | Swipe sinistra oa destra per modificare il periodo di tempo.
89 | Timer di servizio attivo
90 | Tips
91 | Video
92 | Video
93 | Torre di Guardia
94 | Cosa c\'� di nuovo!
95 | Anno
96 | Si
97 | No
98 | Volantino
99 | Volantini
100 | Quantità
101 |
102 |
--------------------------------------------------------------------------------
/res/values-ko/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 방문 기록 추가
4 | 시간 기록
5 | 주소
6 | 익명 제공 출판물
7 | ServiceDroid
8 | 남은 분 단위 시간은 자동으로 다음 달로 이월 됩니다.
9 | 깨어라!
10 | 백업
11 | SD카드에 백업 완료
12 | 성서
13 | 성서연구
14 | 성서연구
15 | 성서는 실제로 무엇을 가르치는가?
16 | 서적
17 | 서적
18 | 팜플렛
19 | 팜플렛
20 | 방문 기록
21 | 취소
22 | 이월
23 | 파수대와 깨어라!
24 | 저장
25 | 사랑하는 사람이 사망했을 때
26 | 제공 출판물 기록
27 | 날짜
28 | 삭제
29 | 이 방문기록과 관련된 모든 데이터, 제공 출판물 및 재방문 기록을 삭제 하시겠습니까?
30 | 관련된 모든 데이터를 삭제 하시겠습니까?
31 | 관련된 모든 데이터 삭제
32 | 방문기록 만 삭제
33 | 삭제
34 | 삭제
35 | 삭제
36 | 위치
37 | 편집
38 | 남은 시간
39 | 시간
40 | 시간
41 | 시간
42 | 호수
43 | 마지막 방문: %s
44 | 봉사 시간
45 | 잡지
46 | 잡지
47 | 재방문
48 | 분
49 | 분
50 | 달
51 | 달
52 |
53 | - 1월
54 | - 2월
55 | - 3월
56 | - 4월
57 | - 5월
58 | - 6월
59 | - 7월
60 | - 8월
61 | - 9월
62 | - 10월
63 | - 11월
64 | - 12월
65 |
66 | 이름
67 | 아니오
68 | 이것은 방문기록 입니다. 모든 제공 출판물, 재방문 기록들을 각각의 관심자들 방문기록에 저장할 수 있습니다. 그런 기록들은 각각의 관심자 이름 안에 저장 될것 입니다.
69 | 제공 출판물과 재방문 기록을 위해 메뉴 버튼을 누르세요.
70 | 이번 달 봉사시간을 기록하거나, 야외봉사 타이머를 사용할 수 있습니다.
71 | 메모
72 | 좋습니다!
73 | 그 외의 것들
74 | 출판물
75 | 출판물
76 | 수량
77 | 하느님은 우리에게 무엇을 요구하시는가?
78 | 개발자에게 이메일을 보내보세요.
79 | 재방문 기록을 만드셨습니다.
80 | 당신의 잔여 시간(분 단위)을 반올림하여 기록하시겠습니까, 아니면 다음달로 이월 하시겠습니까?
81 | 이월
82 | 반올림
83 | 재방문
84 | 재방문
85 | 이메일
86 | 무엇으로 보내시겠습니까?
87 | 봉사기록 보내기
88 | 봉사연도
89 | 월 봉사기록
90 | 분류
91 | 알파벳순, ㄱㄴ순
92 | 오래된 방문순
93 | 시간 시작
94 | 통계
95 | 시간 멈추기
96 | 시간
97 | 봉사 기록을 정산할 시간입니다.
98 | 봉사시간: %s
99 | 오른쪽이나 왼쪽으로 밀어서 원하는 월로 이동할 수 있습니다.
100 | 봉사 타이머 실행 중
101 | 팁
102 | 전도지
103 | 전도지
104 | 비디오
105 | 비디오
106 | 파수대
107 | 새로워진 것들!
108 | 년
109 | 예
110 |
--------------------------------------------------------------------------------
/res/values-nl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Nabezoek toevoegen
4 | Tijdstip toevoegen
5 | Adres
6 | Anoniem verspreide lectuur
7 | ServiceDroid
8 | Extra minuten zijn automatisch meegenomen naar de volgende maand.
9 | Ontwaakt!
10 | Backup
11 | Gegevens succesvol gebackupt naar \"%s\" op SD-kaart.
12 | Bijbel
13 | Bijbelstudies
14 | Bijbelstudie
15 | Wat leert de Bijbel echt?
16 | Boek
17 | Boeken
18 | Brochure
19 | Brochures
20 | Nabezoeken
21 | Annuleren
22 | Meegenomen
23 | Wachttoren & Ontwaakt!
24 | Opslaan
25 | When Someone You Love Dies
26 | Create Placement
27 | Datum
28 | Nabezoek toevoegen
29 | Alle verspreide lectuur en nabezoek-momenten verwijderen voor dit nabezoek?
30 | Gerelateerde gegevens verwijderen?
31 | Ja, ook gerelateerde gegevens
32 | Nee, alleen nabezoek
33 | Verspreide lectuur verwijderen
34 | Verwijder nabezoek
35 | Delete Time
36 | Navigatie
37 | Bewerken
38 | Uren
39 | uur
40 | uur
41 | Uitgave
42 | Laatst bezocht: %s
43 | Tijd in velddienst
44 | Tijdschrift
45 | Tijdschriften
46 | Teruggeweest op
47 | min
48 | minuten
49 | Maand
50 | Maandelijks
51 |
52 | - Januari
53 | - Februari
54 | - Maart
55 | - April
56 | - Mei
57 | - Juni
58 | - Juli
59 | - Augustus
60 | - September
61 | - Oktober
62 | - November
63 | - December
64 |
65 | Naam
66 | Nee
67 | Dit is de lijst met nabezoeken. Alle verspreide lectuur en nabezoek-momenten worden bijbehouden per nabezoek. De aantallen worden voor je bijgehouden.
68 | Druk op MENU om een nabezoek-moment of verspreide lectuur toe te voegen.
69 | Voeg velddienst-tijd toe, of start de stopwatch.
70 | Notities
71 | Leuk!
72 | Anders...
73 | Verspreide lectuur
74 | Hoeveelheid
75 | Wat verlangt God van ons?
76 | Neem contact op met de ontwikkelaar.
77 | Je hebt een nabezoek gebracht op %s.
78 | Extra tijd
79 | Tijd naar boven afronden of minuten meenemen naar volgende maand?
80 | Meenemen
81 | Afronden
82 | Nabezoek-moment
83 | Nabezoek-momenten
84 | E-mail
85 | Verzenden via...
86 | Verstuur je velddienstbericht
87 | Dienstjaar
88 | Velddienstbericht voor %s
89 | Sorteer
90 | Alfabetisch
91 | Oudste nabezoek
92 | Start Stopwatch
93 | Aantallen
94 | Stop Stopwatch
95 | Tijd
96 | Je tijd is om!
97 | Time in de dienst: %s
98 | Swipe naar lings of rechts om de tijdsperiode aan te passen.
99 | Stopwatch voor velddiensttijd actief
100 | Tips
101 | Tractaat
102 | Tractaten
103 | Wachttoren
104 | Wat is nieuw?
105 | Jaar
106 | Ja
107 | Video
108 | Video\'s
109 |
110 |
--------------------------------------------------------------------------------
/res/values-pt/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Adicionar Visita
4 | Adicionar Tempo
5 | Endereço
6 | Colocações Anónimas
7 | ServiçoDroid
8 | Despertai!
9 | Bíblia
10 | Estudos Bíblicos
11 | Estudo Bíblico
12 | O Que a Bíblia Realmente Ensina?
13 | Livro
14 | Livros
15 | Brochura
16 | Brochuras
17 | Livro de Visitas
18 | Cancelar
19 | Confirmar
20 | A Sentinela & Despertai!
21 | Quando Morre Alguém Que Amamos
22 | Criar Colocação
23 | Data
24 | Apagar Visita
25 | Would you like to delete all placements and visits associated with this call?
26 | Remover Colocação
27 | Apagar Tempo
28 | Apagar Revisita
29 | Locais
30 | Editar
31 | Horas
32 | hora
33 | horas
34 | Edição
35 | Última visita: %s
36 | Tempo no serviço
37 | Revista
38 | Revistas
39 | Revisita a
40 | min
41 | mins
42 | Mês
43 | Mensalmente
44 |
45 | - Janeiro
46 | - Fevereiro
47 | - Março
48 | - Abril
49 | - Maio
50 | - Junho
51 | - Julho
52 | - Agosto
53 | - Setembro
54 | - Outubro
55 | - Novembro
56 | - Dezembro
57 |
58 | Nome
59 | Não
60 | Clique no MENU para adicionar uma nova visita.
61 | Clique no MENU para adicionar uma colocação.
62 | Clique no MENU para adicionar tempo a este mês.
63 | Notas
64 | Boa!
65 | Outros...
66 | Colocação
67 | Colocações
68 | O Que Deus Requer de Nós?
69 | Voçê fez uma revisita a %s.
70 | Deseja manter o seu tempo, ou arredondar minutos extras para o próximo mês?
71 | Manter
72 | Arredondar
73 | Revisita
74 | Revisitas
75 | Enviar
76 | Enviar por...
77 | Enviar o seu Tempo de Serviço
78 | Ano de Serviço
79 | Ano de Serviço para %s
80 | Ordenar
81 | Alfabeticamente
82 | Visita mais antiga
83 | Começar Tempo
84 | Estatísticas
85 | Parar Tempo
86 | Tempo
87 | O seu tempo é devido!
88 | Tempo no serviço: %s
89 | Swipe esquerda ou direita para alterar o período de tempo.
90 | Tempo activo no serviço
91 | Dicas
92 | Tratado
93 | Tratados
94 | Vídeo
95 | Vídeos
96 | A Sentinela
97 | Novidades
98 | Ano
99 | Sim
100 |
101 |
--------------------------------------------------------------------------------
/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #fb3
4 | #33b5e5
5 | #9c0
6 |
7 |
--------------------------------------------------------------------------------
/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | 48dp
19 | 48dp
20 | 56dp
21 |
22 |
--------------------------------------------------------------------------------
/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Add Call
4 | Add Time
5 | Address
6 | Anonymous Placements
7 | ServiceDroid
8 | Extra minutes were automatically carried over to the next month.
9 | Awake!
10 | Backup
11 | Successfully backed up data to \"%s\" on your SD card.
12 | Bible
13 | Bible Studies
14 | Bible Study
15 | What Does the Bible Really Teach?
16 | Book
17 | Books
18 | Brochure
19 | Brochures
20 | Call Book
21 | Cancel
22 | Carried Over
23 | Watchtower & Awake!
24 | Save
25 | When Someone You Love Dies
26 | Create Placement
27 | Date
28 | Delete Call
29 | Would you like to delete all placements and visits associated with this call?
30 | Delete Related Data?
31 | Delete Related Data
32 | Call Only
33 | Delete Placement
34 | Delete Visit
35 | Delete Time
36 | Directions
37 | Edit
38 | Extra time
39 | Hours
40 | hr
41 | hrs
42 | Issue
43 | Last Visited: %s
44 | Time in Service
45 | Magazine
46 | Mags
47 | %1$s %2$s/%3$s
48 | Returned On
49 | min
50 | mins
51 | Month
52 | Monthly
53 |
54 | - January
55 | - February
56 | - March
57 | - April
58 | - May
59 | - June
60 | - July
61 | - August
62 | - September
63 | - October
64 | - November
65 | - December
66 |
67 | Name
68 | No
69 | This is the Call Book. All placements and return visits should be recorded on individual calls. The stats will keep count for you.
70 | Press MENU to record a placement or return visit.
71 | Add time for this month, or start the timer.
72 | Notes
73 | Cool!
74 | Other...
75 | Placement
76 | Placements
77 | Quantity
78 | What Does God Require of Us?
79 | Contact the developer.
80 | You made a return visit on %s.
81 | Would you like to round your time up, or carry over the extra minutes to the next month?
82 | Carry Over
83 | Round Up
84 | Return Visit
85 | Return Visits
86 | Email
87 | Send by...
88 | Send in your Service Time
89 | Service Year
90 | Service Report for %s
91 | Sort
92 | Alphabetically
93 | Oldest Visit
94 | Start Time
95 | Stats
96 | Stop Time
97 | Time
98 | Your time is due!
99 | Time in service: %s
100 | Swipe left or right to change the time period.
101 | Service Timer Active
102 | Tips
103 | Tract
104 | Tracts
105 | Video
106 | Videos
107 | Watchtower
108 | What\'s New!
109 | Year
110 | Yes
111 |
112 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/activity/CallEditActivity.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.activity;
2 |
3 | import android.app.Activity;
4 | import android.content.ContentValues;
5 | import android.content.Intent;
6 | import android.database.Cursor;
7 | import android.net.Uri;
8 | import android.os.Bundle;
9 | import android.text.TextUtils;
10 | import android.util.Log;
11 | import android.view.View;
12 | import android.widget.Button;
13 | import android.widget.EditText;
14 |
15 | import com.actionbarsherlock.app.SherlockActivity;
16 | import com.actionbarsherlock.view.MenuItem;
17 | import com.monstarlab.servicedroid.R;
18 | import com.monstarlab.servicedroid.model.Models.Calls;
19 | import com.monstarlab.servicedroid.util.TimeUtil;
20 |
21 | public class CallEditActivity extends SherlockActivity {
22 |
23 | private static final String TAG = "CallEditActivity";
24 |
25 | private static final int STATE_EDIT = 0;
26 | private static final int STATE_INSERT = 1;
27 |
28 | private EditText mNameText;
29 | private EditText mAddressText;
30 | private EditText mNotesText;
31 | //private Long mRowId;
32 | private Uri mUri;
33 | private int mState;
34 | private boolean mIsCancelled;
35 |
36 | private Cursor mCursor;
37 |
38 | private static final String[] PROJECTION = new String[] { Calls._ID, Calls.NAME, Calls.ADDRESS, Calls.NOTES };
39 | private static final int NAME_COLUMN = 1;
40 | private static final int ADDRESS_COLUMN = 2;
41 | private static final int NOTES_COLUMN = 3;
42 |
43 | @Override
44 | public void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 |
47 | //load in the values, if editting
48 | final Intent intent = getIntent();
49 | final String action = intent.getAction();
50 | if(Intent.ACTION_EDIT.equals(action)) {
51 | mState = STATE_EDIT;
52 | mUri = intent.getData();
53 | } else if (Intent.ACTION_INSERT.equals(action)) {
54 | mState = STATE_INSERT;
55 | ContentValues v = new ContentValues();
56 | v.put(Calls.DATE, TimeUtil.getCurrentDateSQLText());
57 | mUri = getContentResolver().insert(intent.getData(), v);
58 |
59 | if(mUri == null) {
60 | Log.e(TAG, "Failed to insert a blank row into " + getIntent().getData());
61 | finish();
62 | return;
63 | }
64 |
65 | setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
66 | } else {
67 | Log.e(TAG, "Unknown action, exiting");
68 | finish();
69 | return;
70 | }
71 |
72 | setContentView(R.layout.call_edit);
73 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
74 |
75 | mNameText = (EditText) findViewById(R.id.name);
76 | mAddressText = (EditText) findViewById(R.id.address);
77 | mNotesText = (EditText) findViewById(R.id.notes);
78 |
79 | mCursor = managedQuery(mUri, PROJECTION, null, null, null);
80 |
81 |
82 | Button confirmButton = (Button) findViewById(R.id.confirm);
83 | confirmButton.setOnClickListener(new View.OnClickListener() {
84 |
85 | public void onClick(View arg0) {
86 | finish();
87 | }
88 |
89 | });
90 |
91 | Button cancelButton = (Button) findViewById(R.id.cancel);
92 | cancelButton.setOnClickListener(new View.OnClickListener() {
93 |
94 | public void onClick(View v) {
95 | mIsCancelled = true;
96 | finish();
97 |
98 | }
99 | });
100 | }
101 |
102 | @Override
103 | protected void onResume() {
104 | super.onResume();
105 |
106 | if(mCursor != null) {
107 | mCursor.moveToFirst(); //make sure we're on the only position
108 |
109 | // somehow, our Cursor has nothing, so accessing it would throw
110 | if (mCursor.isAfterLast()) return;
111 |
112 | String name = mCursor.getString(NAME_COLUMN);
113 | String address = mCursor.getString(ADDRESS_COLUMN);
114 | String notes = mCursor.getString(NOTES_COLUMN);
115 |
116 | mNameText.setText(name);
117 | mAddressText.setText(address);
118 | mNotesText.setText(notes);
119 | }
120 |
121 |
122 | }
123 |
124 | @Override
125 | protected void onPause() {
126 | super.onPause();
127 | //this happens whenever the Activity is losing focus, like hitting the Home button,
128 | //or when the user has clicked Confirm
129 |
130 |
131 | if(mCursor != null) {
132 | String name = mNameText.getText().toString();
133 | String address = mAddressText.getText().toString();
134 | String notes = mNotesText.getText().toString();
135 |
136 |
137 | if(isFinishing() && TextUtils.isEmpty(name)) {
138 | //when finishing, if no Name, its useless anyways
139 | setResult(RESULT_CANCELED);
140 | deleteRV();
141 | } else if (isFinishing() && mIsCancelled) {
142 | //if we cancelled, just dont save the changes
143 | setResult(RESULT_CANCELED);
144 | } else {
145 | //save the current changes to the Provider
146 | ContentValues values = new ContentValues();
147 | values.put(Calls.NAME, name);
148 | values.put(Calls.ADDRESS, address);
149 | values.put(Calls.NOTES, notes);
150 |
151 | getContentResolver().update(mUri, values, null, null);
152 |
153 | // set data on Intent in case the orientation has changed
154 | // https://github.com/seanmonstar/ServiceDroid/issues/issue/43
155 | Intent i = getIntent();
156 | i.setAction(Intent.ACTION_EDIT);
157 | i.setData(mUri);
158 | }
159 | }
160 | }
161 |
162 | @Override
163 | public boolean onOptionsItemSelected(MenuItem item) {
164 | switch(item.getItemId()) {
165 | case android.R.id.home:
166 | Intent i = new Intent(this, CallShowActivity.class);
167 | i.setData(mUri);
168 | i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
169 | startActivity(i);
170 | return true;
171 | }
172 |
173 | return super.onOptionsItemSelected(item);
174 | }
175 |
176 | private void deleteRV() {
177 | if(mCursor != null) {
178 | mCursor.close();
179 | mCursor = null;
180 | getContentResolver().delete(mUri, null, null);
181 | }
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/activity/CallsActivity.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.activity;
2 |
3 | import android.app.AlertDialog;
4 | import android.app.Dialog;
5 | import android.app.ListActivity;
6 | import android.content.ContentUris;
7 | import android.content.ContentValues;
8 | import android.content.DialogInterface;
9 | import android.content.Intent;
10 | import android.content.SharedPreferences;
11 | import android.content.SharedPreferences.Editor;
12 | import android.database.Cursor;
13 | import android.net.Uri;
14 | import android.os.Bundle;
15 | import android.util.Log;
16 | import android.view.ContextMenu;
17 | import android.view.View;
18 | import android.view.ContextMenu.ContextMenuInfo;
19 | import android.view.View.OnClickListener;
20 | import android.widget.ImageButton;
21 | import android.widget.ImageView;
22 | import android.widget.ListView;
23 | import android.widget.SimpleCursorAdapter;
24 | import android.widget.TextView;
25 | import android.widget.Toast;
26 | import android.widget.AdapterView.AdapterContextMenuInfo;
27 |
28 | import com.actionbarsherlock.app.SherlockListActivity;
29 | import com.actionbarsherlock.view.Menu;
30 | import com.actionbarsherlock.view.MenuItem;
31 | import com.monstarlab.servicedroid.R;
32 | import com.monstarlab.servicedroid.model.Models.Calls;
33 | import com.monstarlab.servicedroid.model.Models.Placements;
34 | import com.monstarlab.servicedroid.model.Models.ReturnVisits;
35 | import com.monstarlab.servicedroid.util.TimeUtil;
36 |
37 | public class CallsActivity extends SherlockListActivity {
38 |
39 | private static final String TAG = "CallsActivity";
40 |
41 | private static final int MENU_ADD = Menu.FIRST;
42 | private static final int MENU_SORT_ALPHA = Menu.FIRST + 1;
43 | private static final int MENU_SORT_TIME = Menu.FIRST + 2;
44 | private static final int MENU_ADD_ANON_PLACEMENTS = Menu.FIRST + 3;
45 |
46 | private static final int EDIT_ID = Menu.FIRST + 4;
47 | private static final int RETURN_ID = Menu.FIRST + 5;
48 | private static final int DIRECTIONS_ID = Menu.FIRST + 6;
49 | private static final int DELETE_ID = Menu.FIRST + 7;
50 |
51 | private static final int DELETE_CALL_DIALOG = 0;
52 |
53 | private static final String[] PROJECTION = new String[] { Calls._ID, Calls.NAME, Calls.ADDRESS, Calls.IS_STUDY, Calls.LAST_VISITED, Calls.TYPE };
54 |
55 | private static final int SORT_ALPHA = 0;
56 | private static final int SORT_TIME = 1;
57 |
58 | private static final String PREFS_NAME = "Calls";
59 | private static final String PREFS_SORT_KEY = "sortOrder";
60 |
61 | private int mSortState;
62 | private long mJustDeletedCall;
63 |
64 | private boolean mHasAnonCall = false;
65 | private Cursor mListCursor;
66 |
67 | private TextView mHeaderText;
68 |
69 | @Override
70 | public void onCreate(Bundle savedInstanceState) {
71 | super.onCreate(savedInstanceState);
72 |
73 | Intent intent = getIntent();
74 | if(intent.getData() == null) {
75 | intent.setData(Calls.CONTENT_URI);
76 | }
77 |
78 | setContentView(R.layout.calls);
79 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
80 |
81 | mHeaderText = (TextView)findViewById(R.id.header);
82 |
83 | // default sort state will be alphabetically, unless set otherwise
84 | loadSortState();
85 |
86 | fillData();
87 | registerForContextMenu(getListView());
88 | }
89 |
90 |
91 | protected void fillData() {
92 | String sortBy = null;
93 | String sortText = getString(R.string.sorted_alpha);
94 | if(mSortState == SORT_ALPHA) {
95 | sortBy = Calls.NAME;
96 | } else if (mSortState == SORT_TIME) {
97 | sortBy = Calls.LAST_VISITED;
98 | sortText = getString(R.string.sorted_time);
99 | }
100 |
101 | mHeaderText.setText(sortText);
102 |
103 | mListCursor = managedQuery(getIntent().getData(), PROJECTION, null, null, sortBy);
104 |
105 | String[] from = new String[]{ Calls.NAME, Calls.ADDRESS, Calls.IS_STUDY };
106 | int[] to = new int[]{ R.id.name, R.id.address, R.id.icon };
107 |
108 | SimpleCursorAdapter rvs = new SimpleCursorAdapter(this, R.layout.call_row, mListCursor, from, to) {
109 |
110 | @Override
111 | public void setViewImage(ImageView v, String value) {
112 | if(Integer.parseInt(value) > 0) {
113 | v.setVisibility(View.VISIBLE);
114 | } else {
115 | v.setVisibility(View.GONE);
116 | }
117 | }
118 |
119 | };
120 |
121 | setListAdapter(rvs);
122 |
123 | getAnonCall();
124 | }
125 |
126 | protected void loadSortState() {
127 | SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
128 | mSortState = settings.getInt(PREFS_SORT_KEY, SORT_ALPHA);
129 | }
130 |
131 | protected void saveSortState() {
132 | SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
133 | Editor editor = settings.edit();
134 | editor.putInt(PREFS_SORT_KEY, mSortState);
135 | editor.apply();
136 | }
137 |
138 | private Dialog makeDeleteCallDialog() {
139 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
140 |
141 | builder.setTitle(getString(R.string.delete_call_title))
142 | .setMessage(getString(R.string.delete_call_prompt))
143 | .setCancelable(false)
144 | .setPositiveButton(R.string.delete_call_prompt_yes, new DialogInterface.OnClickListener() {
145 | public void onClick(DialogInterface dialog, int id) {
146 | deleteCallRelatedData();
147 | }
148 | })
149 | .setNegativeButton(R.string.delete_call_prompt_no, new DialogInterface.OnClickListener() {
150 | public void onClick(DialogInterface dialog, int id) {
151 | //do nothing
152 | }
153 | });
154 | return builder.create();
155 | }
156 |
157 | private void deleteCallRelatedData() {
158 | if (mJustDeletedCall == 0) {
159 | return;
160 | }
161 |
162 | String[] whereArgs = new String[] { String.valueOf(mJustDeletedCall) };
163 | getContentResolver().delete(ReturnVisits.CONTENT_URI, ReturnVisits.CALL_ID+"=?", whereArgs);
164 | getContentResolver().delete(Placements.CONTENT_URI, Placements.CALL_ID+"=?", whereArgs);
165 | }
166 |
167 | @Override
168 | public boolean onCreateOptionsMenu(Menu menu) {
169 | boolean result = super.onCreateOptionsMenu(menu);
170 | getSupportMenuInflater().inflate(R.menu.calls, menu);
171 | return result;
172 | }
173 |
174 | @Override
175 | protected Dialog onCreateDialog(int id) {
176 | Dialog dialog;
177 | switch(id) {
178 | case DELETE_CALL_DIALOG:
179 | dialog = makeDeleteCallDialog();
180 | break;
181 | default:
182 | dialog = null;
183 | }
184 | return dialog;
185 | }
186 |
187 |
188 | @Override
189 | public boolean onPrepareOptionsMenu(Menu menu) {
190 | super.onPrepareOptionsMenu(menu);
191 |
192 | //adding Anonymous Placements depends on Cursor
193 | if(mHasAnonCall) {
194 | menu.removeItem(MENU_ADD_ANON_PLACEMENTS);
195 | } else {
196 | if(menu.findItem(MENU_ADD_ANON_PLACEMENTS) == null) {
197 | menu.add(0, MENU_ADD_ANON_PLACEMENTS, 3, R.string.anon_placement).setIcon(R.drawable.menu_add);
198 | }
199 | }
200 |
201 | return true;
202 | }
203 |
204 | @Override
205 | public boolean onOptionsItemSelected(MenuItem item) {
206 | switch (item.getItemId()) {
207 | case android.R.id.home:
208 | Intent i = new Intent(this, ServiceDroidActivity.class);
209 | i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
210 | startActivity(i);
211 | return true;
212 | case R.id.menu_add:
213 | createCall();
214 | break;
215 | case R.id.menu_sort:
216 | toggleSortOrder();
217 | break;
218 | case MENU_ADD_ANON_PLACEMENTS:
219 | createAnonCall();
220 | break;
221 | }
222 |
223 | return super.onOptionsItemSelected(item);
224 | }
225 |
226 | protected void toggleSortOrder() {
227 | if (mSortState == SORT_ALPHA) {
228 | mSortState = SORT_TIME;
229 | } else if (mSortState == SORT_TIME) {
230 | mSortState = SORT_ALPHA;
231 | }
232 | saveSortState();
233 | fillData();
234 | }
235 |
236 | protected void createAnonCall() {
237 | if(!mHasAnonCall) {
238 | ContentValues values = new ContentValues();
239 | values.put(Calls.NAME, getString(R.string.anon_placement));
240 | values.put(Calls.TYPE, Calls.TYPE_ANONYMOUS);
241 | values.put(Calls.DATE, TimeUtil.getCurrentTimeSQLText());
242 | getContentResolver().insert(getIntent().getData(), values);
243 |
244 | getAnonCall();
245 | }
246 | }
247 |
248 | protected void getAnonCall() {
249 | mHasAnonCall = false;
250 | Cursor c = getContentResolver().query(getIntent().getData(), PROJECTION, Calls.TYPE + "=?", new String[] { ""+Calls.TYPE_ANONYMOUS }, null);
251 | if (c != null) {
252 | if(c.getCount() > 0) {
253 | mHasAnonCall = true;
254 | }
255 |
256 | c.close();
257 | }
258 | c = null;
259 | }
260 |
261 |
262 | @Override
263 | public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
264 | super.onCreateContextMenu(menu, v, menuInfo);
265 |
266 | AdapterContextMenuInfo info = ((AdapterContextMenuInfo)menuInfo);
267 | Log.d(TAG, "Menu position id is " + info.position);
268 | mListCursor.moveToPosition(info.position);
269 |
270 |
271 | String name = mListCursor.getString(1);
272 | int type = mListCursor.getInt(5);
273 |
274 | menu.setHeaderTitle(name);
275 |
276 | switch(type) {
277 |
278 | default:
279 | menu.add(0, RETURN_ID, 1, R.string.make_return);
280 | menu.add(0, DIRECTIONS_ID, 2, R.string.directions);
281 | //falls through
282 |
283 | case Calls.TYPE_ANONYMOUS:
284 | menu.add(0, EDIT_ID, 0, R.string.edit);
285 | menu.add(0, DELETE_ID, 3, R.string.delete_call);
286 | }
287 |
288 | }
289 |
290 | @Override
291 | public boolean onContextItemSelected(android.view.MenuItem item) {
292 | AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
293 |
294 | switch(item.getItemId()) {
295 | case EDIT_ID:
296 | editCall(info.id);
297 | return true;
298 | case RETURN_ID:
299 | returnOnCall(info.id);
300 | return true;
301 |
302 | case DIRECTIONS_ID:
303 | getDirections(info.position);
304 | return true;
305 |
306 | case DELETE_ID:
307 | deleteCall(info.id);
308 |
309 | //fillData();
310 | return true;
311 | }
312 |
313 |
314 | return super.onContextItemSelected(item);
315 | }
316 |
317 | @Override
318 | protected void onListItemClick(ListView l, View v, int position, long id) {
319 | //super.onListItemClick(l, v, position, id);
320 | editCall(id);
321 | }
322 |
323 | protected void getDirections(int index) {
324 | if(mListCursor != null) {
325 | if(mListCursor.getCount() > 0) {
326 |
327 | mListCursor.moveToPosition(index);
328 | String addr = mListCursor.getString(2);
329 | Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://maps.google.com/maps?daddr="+addr));
330 | startActivity(i);
331 | }
332 | }
333 |
334 |
335 | }
336 |
337 | protected void deleteCall(long id) {
338 | Uri callUri = ContentUris.withAppendedId(getIntent().getData(), id);
339 | getContentResolver().delete(callUri, null, null);
340 | mJustDeletedCall = id;
341 | showDialog(DELETE_CALL_DIALOG);
342 |
343 | getAnonCall();
344 | }
345 |
346 | protected void editCall(long id) {
347 | Uri uri = ContentUris.withAppendedId(getIntent().getData(), id);
348 | Intent i = new Intent(Intent.ACTION_EDIT, uri, this, CallShowActivity.class);
349 | startActivity(i);
350 | }
351 |
352 |
353 | protected void createCall() {
354 | Intent i = new Intent(Intent.ACTION_INSERT, getIntent().getData(), this, CallEditActivity.class);
355 | startActivity(i);
356 | }
357 |
358 | protected void returnOnCall(long id) {
359 | ContentValues values = new ContentValues();
360 | values.put(ReturnVisits.CALL_ID, id);
361 | getContentResolver().insert(ReturnVisits.CONTENT_URI, values);
362 |
363 | String name = getCallName(id);
364 | String text = getString(R.string.return_visit_success, name);
365 | Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
366 | }
367 |
368 | protected String getCallName(long id) {
369 | Uri uri = ContentUris.withAppendedId(getIntent().getData(), id);
370 | Cursor c = getContentResolver().query(uri, new String[] { Calls.NAME }, null, null, null);
371 | if(c != null) {
372 | c.moveToFirst();
373 | String name = c.getString(0);
374 | c.close();
375 | return name;
376 | }
377 | return "";
378 | }
379 |
380 |
381 | }
382 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/activity/ReturnVisitActivity.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.activity;
2 |
3 | import java.text.ParseException;
4 | import java.util.Date;
5 |
6 | import com.actionbarsherlock.app.SherlockActivity;
7 | import com.actionbarsherlock.view.MenuItem;
8 | import com.monstarlab.servicedroid.R;
9 | import com.monstarlab.servicedroid.model.Models.Calls;
10 | import com.monstarlab.servicedroid.model.Models.ReturnVisits;
11 | import com.monstarlab.servicedroid.util.TimeUtil;
12 |
13 | import android.app.DatePickerDialog;
14 | import android.app.Dialog;
15 | import android.content.ContentUris;
16 | import android.content.ContentValues;
17 | import android.content.Intent;
18 | import android.database.Cursor;
19 | import android.net.Uri;
20 | import android.os.Bundle;
21 | import android.util.Log;
22 | import android.view.View;
23 | import android.widget.Button;
24 | import android.widget.CheckBox;
25 | import android.widget.DatePicker;
26 | import android.widget.EditText;
27 | import android.widget.Toast;
28 |
29 | public class ReturnVisitActivity extends SherlockActivity {
30 |
31 | private static final String TAG = "CallShowActivity";
32 |
33 | private static final int STATE_INSERT = 1;
34 | private static final int STATE_EDIT = 2;
35 |
36 | private static final int DIALOG_DATE = 1;
37 |
38 | private static final String[] PROJECTION = new String[]{ ReturnVisits._ID, ReturnVisits.CALL_ID, ReturnVisits.DATE, ReturnVisits.IS_BIBLE_STUDY, ReturnVisits.NOTE };
39 |
40 | private int mState;
41 | private Uri mUri;
42 | private int mCallId;
43 | private boolean mIsCancelled = false;
44 | private TimeUtil mTimeHelper;
45 | private Cursor mCursor;
46 | private Button mDateBtn;
47 | private CheckBox mBibleStudyCheckbox;
48 | private EditText mNotesText;
49 |
50 | private String mDate;
51 |
52 |
53 | @Override
54 | protected void onCreate(Bundle savedInstanceState) {
55 | super.onCreate(savedInstanceState);
56 |
57 | mTimeHelper = new TimeUtil(this);
58 |
59 | //load in the values, if editting
60 | final Intent intent = getIntent();
61 | final String action = intent.getAction();
62 | if (Intent.ACTION_EDIT.equals(action)) {
63 | mState = STATE_EDIT;
64 | mUri = intent.getData();
65 | mCallId = intent.getIntExtra(Calls._ID, 0);
66 | } else if (Intent.ACTION_INSERT.equals(action)) {
67 | mState = STATE_INSERT;
68 | mCallId = intent.getIntExtra(Calls._ID, 0);
69 | if(mCallId == 0) {
70 | Log.e(TAG, "Call ID wasn't passed, exiting");
71 | finish();
72 | return;
73 | }
74 | ContentValues values = new ContentValues();
75 | values.put(ReturnVisits.CALL_ID, mCallId);
76 | values.put(ReturnVisits.DATE, TimeUtil.getCurrentDateSQLText());
77 | mUri = getContentResolver().insert(intent.getData(), values);
78 |
79 | if(mUri == null) {
80 | Log.e(TAG, "Failed to insert a blank row into " + getIntent().getData());
81 | finish();
82 | return;
83 | }
84 |
85 | setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
86 | } else {
87 | mState = -1;
88 | Log.e(TAG, "Unknown action, exiting");
89 | finish();
90 | return;
91 | }
92 |
93 | setContentView(R.layout.return_visit);
94 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
95 |
96 | mDateBtn = (Button) findViewById(R.id.date);
97 | mDateBtn.setOnClickListener(new View.OnClickListener() {
98 |
99 | public void onClick(View v) {
100 | showDialog(DIALOG_DATE);
101 | }
102 |
103 | });
104 |
105 | mBibleStudyCheckbox = (CheckBox) findViewById(R.id.is_bible_study);
106 | mNotesText = (EditText) findViewById(R.id.notes);
107 |
108 | Button confirm = (Button) findViewById(R.id.confirm);
109 | confirm.setOnClickListener(new View.OnClickListener() {
110 |
111 | public void onClick(View view) {
112 | finish();
113 | }
114 |
115 | });
116 |
117 | Button cancel = (Button) findViewById(R.id.cancel);
118 | cancel.setOnClickListener(new View.OnClickListener() {
119 |
120 | public void onClick(View view) {
121 | mIsCancelled = true;
122 | finish();
123 | }
124 | });
125 | }
126 |
127 | @Override
128 | protected void onResume() {
129 | super.onResume();
130 | mCursor = managedQuery(mUri, PROJECTION, null, null, null);
131 | if(mCursor != null) {
132 |
133 | //grab date
134 | if(mCursor.getCount() > 0) {
135 | mCursor.moveToFirst();
136 | setDate(mCursor.getString(2));
137 | mBibleStudyCheckbox.setChecked(mCursor.getInt(3) == 1);
138 | mNotesText.setText(mCursor.getString(4));
139 |
140 |
141 | }
142 |
143 | } else {
144 | setDate(TimeUtil.getCurrentDateSQLText());
145 | }
146 | }
147 |
148 | @Override
149 | protected void onPause() {
150 | super.onPause();
151 |
152 | if(mCursor != null) {
153 |
154 |
155 | if(isFinishing() && (mState == STATE_INSERT) && mIsCancelled) {
156 | //they pressed the Cancel button when this a new visit, so delete
157 | setResult(RESULT_CANCELED);
158 | deleteEntry();
159 |
160 | } else if (isFinishing() && mIsCancelled) {
161 | //they pressed the Cancel button for editing a visit, just dont update
162 | setResult(RESULT_CANCELED);
163 | } else {
164 | //save the current changes to the Provider
165 | ContentValues values = new ContentValues();
166 | values.put(ReturnVisits.DATE, getDate());
167 | values.put(ReturnVisits.IS_BIBLE_STUDY, mBibleStudyCheckbox.isChecked());
168 | values.put(ReturnVisits.NOTE, mNotesText.getText().toString());
169 | getContentResolver().update(mUri, values, null, null);
170 |
171 | // make a toast if creating a new Return Visit
172 | if(mState == STATE_INSERT) {
173 | Cursor c = getContentResolver().query(ContentUris.withAppendedId(Calls.CONTENT_URI, mCallId), new String[]{ Calls._ID, Calls.NAME }, null, null, null);
174 | if (c.getCount() > 0) {
175 | c.moveToFirst();
176 | String name = c.getString(1);
177 | String text = getString(R.string.return_visit_success, name);
178 | Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
179 | }
180 | c.close();
181 | c = null;
182 | }
183 |
184 | // set data on Intent in case the orientation has changed
185 | // https://github.com/seanmonstar/ServiceDroid/issues/issue/58
186 | Intent i = getIntent();
187 | i.setAction(Intent.ACTION_EDIT);
188 | i.setData(mUri);
189 |
190 | }
191 | }
192 | }
193 |
194 | @Override
195 | protected Dialog onCreateDialog(int id) {
196 | Dialog dialog;
197 | switch(id) {
198 | case DIALOG_DATE:
199 | dialog = makeDateDialog();
200 | break;
201 | default:
202 | dialog = null;
203 | }
204 | return dialog;
205 | }
206 |
207 | private Dialog makeDateDialog() {
208 | int year = 0, month = 0, day = 0;
209 | if(mDate != null) {
210 |
211 | try {
212 | Date d = mTimeHelper.parseDateText(mDate);
213 | year = d.getYear() + 1900;
214 | month = d.getMonth();
215 | day = d.getDate();
216 | } catch (ParseException e) {
217 | // oh well, default to today
218 | }
219 | }
220 |
221 | if (year == 0) {
222 | year = TimeUtil.getCurrentYear();
223 | month = TimeUtil.getCurrentMonth() - 1;
224 | day = TimeUtil.getCurrentDay();
225 | }
226 |
227 | return new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {
228 |
229 | public void onDateSet(DatePicker view, int y, int m, int d) {
230 | String date = y + "-" + TimeUtil.pad(m+1) + "-" + TimeUtil.pad(d);
231 | setDate(date);
232 | }
233 |
234 | }, year, month, day);
235 | }
236 |
237 | @Override
238 | public boolean onOptionsItemSelected(MenuItem item) {
239 | switch (item.getItemId()) {
240 | case android.R.id.home:
241 | Intent i = new Intent(this, CallShowActivity.class);
242 | i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
243 | Uri uri = ContentUris.withAppendedId(Calls.CONTENT_URI, mCallId);
244 | i.setData(uri);
245 | startActivity(i);
246 | return true;
247 | }
248 |
249 | return super.onOptionsItemSelected(item);
250 | }
251 |
252 | private String getDate() {
253 | return mDate;
254 | }
255 |
256 | private void setDate(String date) {
257 | mDate = date;
258 | mDateBtn.setText(date);
259 | }
260 |
261 | private void deleteEntry() {
262 | if(mCursor != null) {
263 | mCursor.close();
264 | mCursor = null;
265 | getContentResolver().delete(mUri, null, null);
266 | }
267 | }
268 |
269 | }
270 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/activity/ServiceDroidActivity.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.activity;
2 |
3 | import com.actionbarsherlock.app.SherlockActivity;
4 | import com.monstarlab.servicedroid.R;
5 | import com.monstarlab.servicedroid.service.ReminderService;
6 |
7 | import android.view.View;
8 | import android.content.Intent;
9 | import android.os.Bundle;
10 |
11 |
12 | public class ServiceDroidActivity extends SherlockActivity implements View.OnClickListener {
13 |
14 |
15 | @Override
16 | public void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 |
19 | setContentView(R.layout.main);
20 |
21 | findViewById(R.id.time).setOnClickListener(this);
22 | findViewById(R.id.calls).setOnClickListener(this);
23 | findViewById(R.id.stats).setOnClickListener(this);
24 |
25 | //setup reminders
26 | setupReminderService();
27 | }
28 |
29 | public void onClick(View view) {
30 | Intent i = null;
31 |
32 | switch (view.getId()) {
33 |
34 | case R.id.time:
35 | i = new Intent(this, TimeActivity.class);
36 | break;
37 |
38 | case R.id.calls:
39 | i = new Intent(this, CallsActivity.class);
40 | break;
41 |
42 | case R.id.stats:
43 | i = new Intent(this, StatisticsActivity.class);
44 | break;
45 |
46 | default:
47 | // tapped something else? whatevs...
48 | }
49 |
50 | if (i != null) {
51 | startActivity(i);
52 | }
53 | }
54 |
55 | private void setupReminderService() {
56 | Intent i = new Intent(this, ReminderService.class);
57 | startService(i);
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/activity/TimeEditActivity.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.activity;
2 |
3 | import java.text.ParseException;
4 | import java.util.Date;
5 |
6 | import android.app.Activity;
7 | import android.app.DatePickerDialog;
8 | import android.app.Dialog;
9 | import android.app.TimePickerDialog;
10 | import android.content.ContentValues;
11 | import android.content.Context;
12 | import android.content.Intent;
13 | import android.content.res.Resources;
14 | import android.database.Cursor;
15 | import android.net.Uri;
16 | import android.os.Bundle;
17 | import android.util.Log;
18 | import android.view.View;
19 | import android.view.WindowManager;
20 | import android.widget.Button;
21 | import android.widget.DatePicker;
22 | import android.widget.EditText;
23 | import android.widget.TimePicker;
24 |
25 | import com.actionbarsherlock.app.SherlockActivity;
26 | import com.actionbarsherlock.view.Menu;
27 | import com.actionbarsherlock.view.MenuItem;
28 | import com.monstarlab.servicedroid.R;
29 | import com.monstarlab.servicedroid.model.Models.TimeEntries;
30 | import com.monstarlab.servicedroid.util.TimeUtil;
31 |
32 | public class TimeEditActivity extends SherlockActivity {
33 |
34 | private static final String TAG = "TimeEditActivity";
35 |
36 | private static final int STATE_EDIT = 0;
37 | private static final int STATE_INSERT = 1;
38 |
39 | private static final int MENU_DELETE = Menu.FIRST;
40 |
41 | private static final int DIALOG_DATE = 0;
42 | private static final int DIALOG_LENGTH = 1;
43 |
44 | private boolean mIsCancelled;
45 |
46 | private Button mDateBtn;
47 | private Button mLengthBtn;
48 | private EditText mNoteText;
49 |
50 | private int mLength;
51 | private String mDate;
52 |
53 | private TimeUtil mTimeHelper;
54 | private int mState;
55 | private Uri mUri;
56 |
57 | private Cursor mCursor;
58 |
59 | private static final String[] PROJECTION = new String[] { TimeEntries._ID, TimeEntries.LENGTH, TimeEntries.DATE, TimeEntries.NOTE };
60 | private static final int LENGTH_COLUMN = 1;
61 | private static final int DATE_COLUMN = 2;
62 | private static final int NOTE_COLUMN = 3;
63 |
64 | @Override
65 | protected void onCreate(Bundle savedInstanceState) {
66 | super.onCreate(savedInstanceState);
67 |
68 | //load in the values, if editting
69 | final Intent intent = getIntent();
70 | final String action = intent.getAction();
71 | if(Intent.ACTION_EDIT.equals(action)) {
72 | mState = STATE_EDIT;
73 | mUri = intent.getData();
74 | } else if (Intent.ACTION_INSERT.equals(action)) {
75 | mState = STATE_INSERT;
76 | ContentValues v = new ContentValues();
77 | v.put(TimeEntries.DATE, TimeUtil.getCurrentDateSQLText());
78 | mUri = getContentResolver().insert(intent.getData(), v);
79 |
80 | if(mUri == null) {
81 | Log.e(TAG, "Failed to insert a blank row into " + getIntent().getData());
82 | finish();
83 | return;
84 | }
85 |
86 | setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
87 | } else {
88 | Log.e(TAG, "Unknown action, exiting");
89 | finish();
90 | return;
91 | }
92 |
93 | this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
94 | setContentView(R.layout.time_edit);
95 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
96 |
97 | mTimeHelper = new TimeUtil(this);
98 |
99 | mDateBtn = (Button) findViewById(R.id.date);
100 | mDateBtn.setOnClickListener(new View.OnClickListener() {
101 |
102 | public void onClick(View view) {
103 |
104 | showDialog(DIALOG_DATE);
105 | }
106 |
107 | });
108 |
109 | mLengthBtn = (Button) findViewById(R.id.length);
110 | mLengthBtn.setOnClickListener(new View.OnClickListener() {
111 |
112 | public void onClick(View view) {
113 |
114 | showDialog(DIALOG_LENGTH);
115 | }
116 |
117 | });
118 |
119 | //mLengthText.setIs24HourView(true);
120 | mNoteText = (EditText) findViewById(R.id.notes);
121 |
122 | Button confirmButton = (Button) findViewById(R.id.confirm);
123 | confirmButton.setOnClickListener(new View.OnClickListener() {
124 |
125 | public void onClick(View view) {
126 |
127 | finish();
128 | }
129 |
130 | });
131 |
132 | Button cancelButton = (Button) findViewById(R.id.cancel);
133 | cancelButton.setOnClickListener(new View.OnClickListener() {
134 |
135 |
136 |
137 | public void onClick(View v) {
138 | mIsCancelled = true;
139 | finish();
140 | }
141 | });
142 |
143 | mCursor = managedQuery(mUri, PROJECTION, null, null, null);
144 | }
145 |
146 | @Override
147 | protected void onResume() {
148 | super.onResume();
149 |
150 | //this happens on wakeup. even at startup.
151 |
152 | if(mCursor != null) {
153 | mCursor.moveToFirst();
154 |
155 | Integer length = mCursor.getInt(LENGTH_COLUMN);
156 | String date = mCursor.getString(DATE_COLUMN);
157 | String note = mCursor.getString(NOTE_COLUMN);
158 |
159 | setDate(date);
160 | setLength(length);
161 |
162 |
163 | mNoteText.setText(note);
164 | } else {
165 | setDate(TimeUtil.getCurrentDateSQLText());
166 | setLength(0);
167 | }
168 | }
169 |
170 | @Override
171 | protected void onPause() {
172 | super.onPause();
173 | //this happens whenever the Activity is losing focus, like hitting the Home button,
174 | //or when the user has clicked Confirm
175 |
176 |
177 | if(mCursor != null) {
178 | int length = getTime();
179 | String date = getDate();
180 | String note = getNote();
181 |
182 | boolean finished = isFinishing();
183 |
184 | if(finished && (length == 0)) {
185 | //when finishing, if no time was spent, just ditch the time period. its useless anyways
186 | setResult(RESULT_CANCELED);
187 | deleteEntry();
188 | } else if(finished && mIsCancelled) {
189 | // if the cancel button was pressed, don't delete, but don't save either.
190 | setResult(RESULT_CANCELED);
191 |
192 | } else {
193 | //save the current changes to the Provider
194 | ContentValues values = new ContentValues();
195 | values.put(TimeEntries.LENGTH, length);
196 | values.put(TimeEntries.DATE, date);
197 | values.put(TimeEntries.NOTE, note);
198 |
199 | getContentResolver().update(mUri, values, null, null);
200 |
201 | // set data on Intent in case the orientation has changed
202 | // https://github.com/seanmonstar/ServiceDroid/issues/issue/58
203 | Intent i = getIntent();
204 | i.setAction(Intent.ACTION_EDIT);
205 | i.setData(mUri);
206 | }
207 | }
208 | }
209 |
210 | @Override
211 | public boolean onCreateOptionsMenu(Menu menu) {
212 | boolean result = super.onCreateOptionsMenu(menu);
213 |
214 | menu.add(0, MENU_DELETE, 1, R.string.delete_time).setIcon(android.R.drawable.ic_menu_delete);
215 |
216 | return result;
217 | }
218 |
219 | @Override
220 | public boolean onOptionsItemSelected(MenuItem item) {
221 | switch (item.getItemId()) {
222 | case android.R.id.home:
223 | Intent i = new Intent(this, TimeActivity.class);
224 | i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
225 | startActivity(i);
226 | return true;
227 | case MENU_DELETE:
228 | setLength(0);
229 | finish();
230 | break;
231 | }
232 |
233 | return super.onOptionsItemSelected(item);
234 | }
235 |
236 | @Override
237 | protected Dialog onCreateDialog(int id) {
238 | Dialog dialog;
239 | switch(id) {
240 | case DIALOG_DATE:
241 | dialog = makeDateDialog();
242 | break;
243 | case DIALOG_LENGTH:
244 | dialog = makeLengthDialog();
245 | break;
246 | default:
247 | dialog = null;
248 | }
249 | return dialog;
250 | }
251 |
252 | private Dialog makeLengthDialog() {
253 | int hrs = 0, mins = 0;
254 | if (mLength > 0) {
255 | hrs = TimeUtil.getHours(mLength);
256 | if (hrs > 23) {
257 | hrs = 23;
258 | }
259 | mins = TimeUtil.getMins(mLength);
260 | }
261 |
262 | final Resources r = getResources();
263 |
264 | return new TimeLengthPickerDialog(this, new TimePickerDialog.OnTimeSetListener() {
265 |
266 | public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
267 | setLength(TimeUtil.toTimeInt(hourOfDay, minute));
268 | }
269 |
270 | }, hrs, mins, r);
271 | }
272 |
273 | private Dialog makeDateDialog() {
274 | int year = 0, month = 0, day = 0;
275 | if(mDate != null) {
276 |
277 | try {
278 | Date d = mTimeHelper.parseDateText(mDate);
279 | year = d.getYear() + 1900;
280 | month = d.getMonth();
281 | day = d.getDate();
282 | } catch (ParseException e) {
283 | // oh well, default to today
284 | }
285 | }
286 |
287 | if (year == 0) {
288 | year = TimeUtil.getCurrentYear();
289 | month = TimeUtil.getCurrentMonth() - 1;
290 | day = TimeUtil.getCurrentDay();
291 | }
292 |
293 | return new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {
294 |
295 | public void onDateSet(DatePicker view, int y, int m, int d) {
296 | String date = y + "-" + pad(m+1) + "-" + pad(d);
297 | setDate(date);
298 | }
299 |
300 | }, year, month, day);
301 | }
302 |
303 | private void deleteEntry() {
304 | if(mCursor != null) {
305 | mCursor.close();
306 | mCursor = null;
307 | getContentResolver().delete(mUri, null, null);
308 | }
309 | }
310 |
311 | private void setDate(String date) {
312 | mDate = date;
313 | mDateBtn.setText(date);
314 | }
315 |
316 | private void setLength(int length) {
317 | mLength = length;
318 | mLengthBtn.setText(TimeUtil.toTimeString(length, getResources()));
319 | }
320 |
321 | private String getDate() {
322 | return mDate;
323 | }
324 |
325 | private int getTime() {
326 | /*mLengthText.clearFocus();
327 | int hours = mLengthText.getCurrentHour();
328 | int mins = mLengthText.getCurrentMinute();
329 | return TimeUtil.toTimeInt(hours, mins);*/
330 | return mLength;
331 | }
332 |
333 | private String getNote() {
334 | return mNoteText.getText().toString();
335 | }
336 |
337 | private static String pad(int c) {
338 | if(c >= 10)
339 | return String.valueOf(c);
340 | else
341 | return "0" + String.valueOf(c);
342 | }
343 |
344 |
345 | class TimeLengthPickerDialog extends TimePickerDialog {
346 |
347 | private Resources mResources;
348 |
349 | public TimeLengthPickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) {
350 | super(context, callBack, hourOfDay, minute, is24HourView);
351 | }
352 |
353 | public TimeLengthPickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, Resources r) {
354 | this(context, callBack, hourOfDay, minute, true);
355 | mResources = r;
356 | updateTitle(hourOfDay, minute);
357 | }
358 |
359 | @Override
360 | public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
361 | updateTitle(hourOfDay, minute);
362 | }
363 |
364 | private void updateTitle(int h, int m) {
365 | this.setTitle(TimeUtil.toTimeString(TimeUtil.toTimeInt(h, m), mResources));
366 | }
367 |
368 |
369 | }
370 |
371 | }
372 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/model/BackupWorker.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.model;
2 |
3 | import java.util.HashMap;
4 |
5 | import com.monstarlab.servicedroid.model.Models.Calls;
6 | import com.monstarlab.servicedroid.model.Models.Literature;
7 | import com.monstarlab.servicedroid.model.Models.Placements;
8 | import com.monstarlab.servicedroid.model.Models.ReturnVisits;
9 | import com.monstarlab.servicedroid.model.Models.TimeEntries;
10 | import com.monstarlab.servicedroid.util.ServiceDroidDocument;
11 |
12 | import android.content.ContentResolver;
13 | import android.content.ContentValues;
14 | import android.database.Cursor;
15 | import android.net.Uri;
16 | import android.provider.BaseColumns;
17 | import android.text.TextUtils;
18 | import android.util.Log;
19 |
20 |
21 | /**
22 | *
23 | * @author Sean McArthur
24 | * @description BackupWorker does the work of serializing data to and from the database to
25 | * a BackupAgent or BackupService.
26 | *
27 | */
28 | public class BackupWorker {
29 |
30 | private static final String TAG = "BackupWorker";
31 |
32 | private static final String TIME_ENTRY_TAG = "TimeEntry";
33 | private static final String CALL_TAG = "Call";
34 | private static final String RETURN_VISIT_TAG = "ReturnVisit";
35 | private static final String LITERATURE_TAG = "Literature";
36 | private static final String PLACEMENT_TAG = "Placement";
37 |
38 | private static final String[] TIME_ENTRIES_PROJECTION = new String[] { TimeEntries._ID, TimeEntries.LENGTH, TimeEntries.DATE, TimeEntries.NOTE };
39 | private static final String[] CALLS_PROJECTION = new String[] { Calls._ID, Calls.NAME, Calls.ADDRESS, Calls.NOTES, Calls.DATE, Calls.TYPE };
40 | private static final String[] RETURN_VISITS_PROJECTION = new String[] { ReturnVisits._ID, ReturnVisits.DATE, ReturnVisits.IS_BIBLE_STUDY, ReturnVisits.NOTE, ReturnVisits.CALL_ID };
41 | private static final String[] LITERATURE_PROJECTION = new String[] { Literature._ID, Literature.PUBLICATION, Literature.TITLE, Literature.TYPE, Literature.WEIGHT };
42 | private static final String[] PLACEMENTS_PROJECTION = new String[] { Placements._ID, Placements.CALL_ID, Placements.LITERATURE_ID, Placements.DATE };
43 |
44 | private HashMap mCallIDReplacements;
45 | private HashMap mLiteratureIDReplacements;
46 |
47 | public BackupWorker() {
48 |
49 | }
50 |
51 | public String backup(ContentResolver resolver) {
52 | //get all time entries, calls, return visits, placements, and bible studies
53 | //convert them to XML
54 | ServiceDroidDocument doc = new ServiceDroidDocument();
55 |
56 | pushDataOntoDocument(doc, TIME_ENTRY_TAG, resolver, TimeEntries.CONTENT_URI, TIME_ENTRIES_PROJECTION, "not("+ TimeEntries.LENGTH + " is null)", null, TimeEntries._ID);
57 | pushDataOntoDocument(doc, CALL_TAG, resolver, Calls.CONTENT_URI, CALLS_PROJECTION, null, null, Calls._ID);
58 | pushDataOntoDocument(doc, RETURN_VISIT_TAG, resolver, ReturnVisits.CONTENT_URI, RETURN_VISITS_PROJECTION, null, null, ReturnVisits._ID);
59 | pushDataOntoDocument(doc, LITERATURE_TAG, resolver, Literature.CONTENT_URI, LITERATURE_PROJECTION, Literature._ID + "> 4", null, Literature._ID); // IDs 1-4 are inserted on DB creation.
60 | pushDataOntoDocument(doc, PLACEMENT_TAG, resolver, Placements.CONTENT_URI, PLACEMENTS_PROJECTION, null, null, Placements._ID);
61 |
62 |
63 | return doc.toString();
64 | }
65 |
66 | protected void pushDataOntoDocument(ServiceDroidDocument doc, String tag, ContentResolver resolver,
67 | Uri uri, String[] projection, String where, String[] whereArgs, String order) {
68 |
69 | Cursor c = resolver.query(uri, projection, where, whereArgs, order);
70 | if(c.getCount() > 0) {
71 | c.moveToFirst();
72 | while(!c.isAfterLast()) {
73 | String[] values = new String[projection.length];
74 | for (int i = 0; i < values.length; i++) {
75 | values[i] = c.getString(c.getColumnIndex(projection[i]));
76 | }
77 | doc.addNode(tag, projection, values);
78 | c.moveToNext();
79 | }
80 | }
81 | c.close();
82 | }
83 |
84 | public boolean restore(ContentResolver resolver, String xml) {
85 | if (TextUtils.isEmpty(xml)) {
86 | // There is no file at first install, so this is a "success".
87 | Log.i(TAG, "Backup file was empty (if existed).");
88 | return true;
89 | }
90 |
91 | ServiceDroidDocument doc = new ServiceDroidDocument(xml);
92 | if (!doc.isValid()) {
93 | Log.e(TAG, "Backup file is invalid XML.");
94 | return false;
95 | }
96 |
97 | mCallIDReplacements = new HashMap();
98 | mLiteratureIDReplacements = new HashMap();
99 |
100 | // IDs 1-4 are pre-inserted brochures and books
101 | for (int i = 1; i < 5; i++) {
102 | mLiteratureIDReplacements.put(""+i, ""+i);
103 | }
104 |
105 | //insert into DB
106 | // IMPORTANT: order matters here!
107 | insertDataFromDocument(doc, TIME_ENTRY_TAG, resolver, TimeEntries.CONTENT_URI);
108 | insertDataFromDocument(doc, CALL_TAG, resolver, Calls.CONTENT_URI);
109 | insertDataFromDocument(doc, RETURN_VISIT_TAG, resolver, ReturnVisits.CONTENT_URI);
110 | insertDataFromDocument(doc, LITERATURE_TAG, resolver, Literature.CONTENT_URI);
111 | insertDataFromDocument(doc, PLACEMENT_TAG, resolver, Placements.CONTENT_URI);
112 |
113 | return true;
114 |
115 | }
116 |
117 | protected void insertDataFromDocument(ServiceDroidDocument doc, String tag, ContentResolver resolver, Uri contentUri) {
118 | boolean isCall = (tag == CALL_TAG);
119 | boolean isLiterature = (tag == LITERATURE_TAG);
120 |
121 | for (int nodeIndex = 0, numOfNodes = doc.getNumberOfTag(tag); nodeIndex < numOfNodes; nodeIndex++) {
122 | String[][] data = doc.getDataFromNode(tag, nodeIndex);
123 | ContentValues values = new ContentValues();
124 | String oldID = null;
125 |
126 |
127 | for (int attrIndex = 0, numOfAttrs = data[0].length; attrIndex < numOfAttrs; attrIndex++) {
128 | String key = data[0][attrIndex];
129 | String value = data[1][attrIndex];
130 | String newID = null;
131 |
132 | //always strip the ID away, we dont want it on insert
133 | if (key.equals(BaseColumns._ID)) { /* BaseColumns._ID is null, but _i is the same on all Models */
134 | oldID = value;
135 | continue;
136 | }
137 |
138 | //CALL_ID and LITERATURE_ID should be replaced
139 | if(key.equals(ReturnVisits.CALL_ID)) {
140 | newID = mCallIDReplacements.get(value);
141 | if (newID == null) {
142 | newID = makeDeadCall(resolver, value);
143 | }
144 | } else if (key.equals(Placements.LITERATURE_ID)) {
145 | newID = mLiteratureIDReplacements.get(value);
146 | }
147 |
148 | if (newID != null) {
149 | value = newID;
150 | }
151 |
152 |
153 | values.put(key, value);
154 | }
155 |
156 |
157 | //keep track of inserted Calls and Literature to replace foreign keys above
158 | Uri insertedUri = resolver.insert(contentUri, values);
159 | if (oldID != null) {
160 | if (isCall) {
161 | mCallIDReplacements.put(oldID, insertedUri.getPathSegments().get(1));
162 | } else if (isLiterature) {
163 | mLiteratureIDReplacements.put(oldID, insertedUri.getPathSegments().get(1));
164 | }
165 | }
166 | }
167 | }
168 |
169 | protected String makeDeadCall(ContentResolver resolver, String id) {
170 | //this was an RV on a call that since got deleted
171 | //so make and then delete a call
172 | ContentValues values = new ContentValues();
173 | Uri inserted = resolver.insert(Calls.CONTENT_URI, values);
174 | resolver.delete(inserted, null, null);
175 | String newID = inserted.getPathSegments().get(1);
176 | mCallIDReplacements.put(id, newID);
177 | return newID;
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/model/Models.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.model;
2 |
3 | import android.net.Uri;
4 | import android.provider.BaseColumns;
5 |
6 | public final class Models {
7 |
8 | public static final String AUTHORITY = "com.monstarlab.servicedroid";
9 |
10 | private Models() {}
11 |
12 | public static final class TimeEntries implements BaseColumns {
13 |
14 | private TimeEntries() {}
15 |
16 | public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/time_entries");
17 |
18 | public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.monstarlab.timeentry";
19 |
20 | public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.monstarlab.timeentry";
21 |
22 | public static final String DEFAULT_SORT_ORDER = "date ASC";
23 |
24 | public static final long MAX_LENGTH = (24 * 60 * 60) - 1;
25 |
26 | /**
27 | * type: date
28 | */
29 | public static final String DATE = "date";
30 |
31 | /**
32 | * type: integer
33 | */
34 | public static final String LENGTH = "length";
35 |
36 | /**
37 | * type: text
38 | */
39 | public static final String NOTE = "note";
40 | }
41 |
42 | public static final class Calls implements BaseColumns {
43 |
44 | private Calls() {}
45 |
46 | public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/calls");
47 |
48 | public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.monstarlab.call";
49 |
50 | public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.monstarlab.call";
51 |
52 | public static final String DEFAULT_SORT_ORDER = "name ASC";
53 |
54 | /**
55 | * type: varchar(128)
56 | */
57 | public static final String NAME = "name";
58 |
59 | /**
60 | * type: varchar(128)
61 | */
62 | public static final String ADDRESS = "address";
63 |
64 | /**
65 | * type: text
66 | */
67 | public static final String NOTES = "notes";
68 |
69 | /**
70 | * type: date
71 | */
72 | public static final String DATE = "date";
73 |
74 | /**
75 | * type: int
76 | */
77 | public static final String TYPE = "type";
78 |
79 | /**
80 | * type: Enum
81 | */
82 | public static final int TYPE_ADDED = 1;
83 | public static final int TYPE_ANONYMOUS = 2;
84 | public static final int TYPE_TRANSFERED = 3;
85 |
86 | /**
87 | * type: JOIN
88 | */
89 | public static final String IS_STUDY = "is_study";
90 |
91 | /**
92 | * type: JOIN
93 | */
94 | public static final String LAST_VISITED = "last_visited";
95 |
96 | }
97 |
98 | public static final class ReturnVisits implements BaseColumns {
99 |
100 | private ReturnVisits() {}
101 |
102 | public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/returnvisits");
103 |
104 | public static final Uri BIBLE_STUDIES_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/returnvisits/biblestudies");
105 |
106 | public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.monstarlab.returnvisit";
107 |
108 | public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.monstarlab.returnvisit";
109 |
110 | public static final String DEFAULT_SORT_ORDER = "date DESC";
111 |
112 | /**
113 | * type: date
114 | */
115 | public static final String DATE = "date";
116 |
117 | /**
118 | * type: varchar(128)
119 | */
120 | public static final String CALL_ID = "call_id";
121 |
122 | /**
123 | * type: text
124 | */
125 | public static final String NOTE = "note";
126 |
127 | /**
128 | * type: boolean
129 | */
130 | public static final String IS_BIBLE_STUDY = "is_bible_study";
131 | }
132 |
133 | public static final class Placements implements BaseColumns {
134 |
135 | private Placements() {}
136 |
137 | public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/placements");
138 |
139 | public static final Uri DETAILS_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/placements/details");
140 | public static final Uri MAGAZINES_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/placements/magazines");
141 | public static final Uri BROCHURES_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/placements/brochures");
142 | public static final Uri TRACTS_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/placements/tracts");
143 | public static final Uri BOOKS_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/placements/books");
144 | public static final Uri VIDEOS_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/placements/videos");
145 |
146 | public static final Uri NON_VIDEOS_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/placements/non-videos");
147 |
148 | public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.monstarlab.placement";
149 |
150 | public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.monstarlab.placement";
151 |
152 | public static final String DEFAULT_SORT_ORDER = "date ASC";
153 |
154 | /**
155 | * type: date
156 | */
157 | public static final String DATE = "date";
158 |
159 | /**
160 | * type: date
161 | */
162 | public static final String CALL_ID = "call_id";
163 |
164 | /**
165 | * type: date
166 | */
167 | public static final String LITERATURE_ID = "literature_id";
168 |
169 |
170 | /**
171 | * type: int
172 | */
173 | public static final String QUANTITY = "quantity";
174 |
175 | }
176 |
177 | public static final class Literature implements BaseColumns {
178 |
179 | private Literature() {}
180 |
181 | public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/literature");
182 |
183 | public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.monstarlab.literature";
184 |
185 | public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.monstarlab.literature";
186 |
187 | public static final String DEFAULT_SORT_ORDER = "_id ASC";
188 |
189 | public static final int TYPE_MAGAZINE = 0;
190 | public static final int TYPE_BROCHURE = 1;
191 | public static final int TYPE_BOOK = 2;
192 | public static final int TYPE_TRACT = 3;
193 | public static final int TYPE_VIDEO = 4;
194 |
195 | /**
196 | * type: varchar
197 | */
198 | public static final String TITLE = "title";
199 |
200 | /**
201 | * type: int
202 | */
203 | public static final String TYPE = "type";
204 |
205 | /**
206 | * type: varchar
207 | */
208 | public static final String PUBLICATION = "publication";
209 |
210 | /**
211 | * type: int
212 | */
213 | public static final String WEIGHT = "weight";
214 |
215 | public static final class Periodical {
216 | public String publication;
217 | public int month;
218 | public int year;
219 |
220 | public Periodical() {}
221 |
222 | }
223 |
224 | public static Periodical parseName(String name) {
225 | int lastSpaceIndex = name.lastIndexOf(" ");
226 | Periodical periodical = new Periodical();
227 | periodical.publication = name.substring(0, lastSpaceIndex);
228 | periodical.month = Integer.parseInt(name.substring(lastSpaceIndex+1, name.indexOf("/")));
229 | periodical.year = Integer.parseInt(name.substring(name.indexOf("/")+1));
230 | return periodical;
231 | }
232 |
233 | }
234 |
235 |
236 |
237 | }
238 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/model/ServiceDroidBackupAgent.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.model;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.DataInputStream;
6 | import java.io.DataOutputStream;
7 | import java.io.IOException;
8 |
9 | import android.annotation.TargetApi;
10 | import android.app.backup.BackupAgent;
11 | import android.app.backup.BackupDataInput;
12 | import android.app.backup.BackupDataOutput;
13 | import android.os.ParcelFileDescriptor;
14 |
15 | @TargetApi(8)
16 | public class ServiceDroidBackupAgent extends BackupAgent {
17 |
18 | private static final String APP_DATA_KEY = "alldata";
19 |
20 | @Override
21 | public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException {
22 | //determine if backup should happen based on oldState
23 | boolean doBackup = (oldState == null); //no old state means first time backing up
24 | if (!doBackup) {
25 | //is an old state, so find out if old state is the same as current state
26 | doBackup = true;
27 | }
28 |
29 | //do backup
30 | if (doBackup) {
31 | BackupWorker bw = new BackupWorker();
32 | String serializedData = bw.backup(getContentResolver());
33 |
34 | ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
35 |
36 | // We use a DataOutputStream to write structured data into
37 | // the buffering stream
38 | DataOutputStream outWriter = new DataOutputStream(bufStream);
39 | outWriter.writeChars(serializedData);
40 |
41 | // Okay, we've flattened the data for transmission. Pull it
42 | // out of the buffering stream object and send it off.
43 | byte[] buffer = bufStream.toByteArray();
44 | int len = buffer.length;
45 | data.writeEntityHeader(APP_DATA_KEY, len);
46 | data.writeEntityData(buffer, len);
47 | }
48 |
49 | //record a newState
50 | }
51 |
52 | @Override
53 | public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException {
54 | while (data.readNextHeader()) {
55 | String key = data.getKey();
56 | int dataSize = data.getDataSize();
57 |
58 | if (APP_DATA_KEY.equals(key)) {
59 | byte[] dataBuf = new byte[dataSize];
60 | data.readEntityData(dataBuf, 0, dataSize);
61 | ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
62 | DataInputStream in = new DataInputStream(baStream);
63 |
64 | StringBuilder sb = new StringBuilder();
65 | String line = null;
66 | while ((line = in.readLine()) != null) {
67 | sb.append(line);
68 | }
69 | String serializedData = sb.toString();
70 |
71 | //import data into the DB via BackupWorker
72 | BackupWorker bw = new BackupWorker();
73 | bw.restore(getContentResolver(), serializedData);
74 | }
75 | }
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/model/WrapManager.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.model;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.backup.BackupManager;
5 | import android.content.Context;
6 |
7 | @TargetApi(8)
8 | public class WrapManager {
9 |
10 | private BackupManager mBackupManager;
11 |
12 | static {
13 | try {
14 | Class.forName("android.app.backup.BackupManager");
15 | } catch (Exception ex) {
16 | throw new RuntimeException(ex);
17 | }
18 | }
19 |
20 | public static void checkAvailable() {}
21 |
22 | public WrapManager(Context ctx) {
23 | mBackupManager = new BackupManager(ctx);
24 | }
25 |
26 | public void dataChanged() {
27 | mBackupManager.dataChanged();
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/receiver/BootReceiver.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.receiver;
2 |
3 | import com.monstarlab.servicedroid.service.ReminderService;
4 |
5 | import android.content.BroadcastReceiver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.util.Log;
9 |
10 | public class BootReceiver extends BroadcastReceiver {
11 |
12 | private static final String TAG = "BootReceiver";
13 |
14 | @Override
15 | public void onReceive(Context context, Intent intent) {
16 | Log.d(TAG, "Boot received. Starting Reminder Service.");
17 | Intent i = new Intent(context, ReminderService.class);
18 | context.startService(i);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/receiver/NotificationReceiver.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.receiver;
2 |
3 | import com.monstarlab.servicedroid.R;
4 | import com.monstarlab.servicedroid.activity.StatisticsActivity;
5 | import com.monstarlab.servicedroid.util.TimeUtil;
6 |
7 | import android.app.Notification;
8 | import android.app.NotificationManager;
9 | import android.app.PendingIntent;
10 | import android.content.BroadcastReceiver;
11 | import android.content.Context;
12 | import android.content.Intent;
13 |
14 | public class NotificationReceiver extends BroadcastReceiver {
15 |
16 | public static final int TYPE_REMINDER = 0;
17 |
18 | @Override
19 | public void onReceive(Context context, Intent intent) {
20 | switch(Integer.parseInt(intent.getType())) {
21 |
22 | case TYPE_REMINDER:
23 | showReminder(context);
24 | default:
25 | break;
26 |
27 | }
28 |
29 | }
30 |
31 | private void showReminder(Context context) {
32 | NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
33 |
34 | CharSequence tickerText = context.getString(R.string.send_reminder);
35 | long when = TimeUtil.getCurrentTime();
36 |
37 | Notification notification = new Notification(R.drawable.icon, tickerText, when);
38 | Intent intent = new Intent(context, StatisticsActivity.class);
39 | PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
40 |
41 | CharSequence contentText = context.getString(R.string.time_due);
42 |
43 | notification.setLatestEventInfo(context, tickerText, contentText, pendingIntent);
44 |
45 | notification.flags |= Notification.FLAG_AUTO_CANCEL;
46 |
47 | nm.notify(TYPE_REMINDER, notification);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/service/BackupService.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.service;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileOutputStream;
6 | import java.io.FileReader;
7 | import java.io.IOException;
8 |
9 | import com.monstarlab.servicedroid.R;
10 | import com.monstarlab.servicedroid.activity.ServiceDroidActivity;
11 | import com.monstarlab.servicedroid.model.BackupWorker;
12 | import com.monstarlab.servicedroid.util.TimeUtil;
13 |
14 | import android.app.Notification;
15 | import android.app.NotificationManager;
16 | import android.app.PendingIntent;
17 | import android.app.Service;
18 | import android.content.Context;
19 | import android.content.Intent;
20 | import android.os.Environment;
21 | import android.os.Handler;
22 | import android.os.IBinder;
23 | import android.util.Log;
24 | import android.widget.Toast;
25 |
26 | public class BackupService extends Service {
27 |
28 | public static final String ACTION_BACKUP = "Backup";
29 | public static final String ACTION_BACKUP_IMMEDIATELY = "BackupImmediately";
30 | public static final String ACTION_RESTORE = "Restore";
31 |
32 | private static final String TAG = "BackupService";
33 |
34 | private static final String FILE_NAME = "ServiceDroidBackup.sdml";
35 | private static final String DIRECTORY = "backups";
36 |
37 | private static final long SCHEDULE_DELAY = 1000 * 60 * 5;
38 |
39 | private static final boolean DO_NOTIFY = true;
40 | private static final boolean DONT_NOTIFY = false;
41 |
42 | private static boolean USE_DRIVE = false;
43 |
44 | private Handler mHandler = new Handler();
45 | private Runnable mScheduler = new Runnable() {
46 | public void run() {
47 | doBackup();
48 | }
49 | };
50 |
51 |
52 | @Override
53 | public void onStart(Intent intent, int startId) {
54 | handleCommand(intent);
55 | }
56 |
57 | @Override
58 | public int onStartCommand(Intent intent, int flags, int startId) {
59 | handleCommand(intent);
60 | return 1; // START_STICKY
61 | }
62 |
63 | protected void handleCommand(Intent intent) {
64 | if (intent == null) {
65 | Log.e(TAG, "Intent was null. Need an intent to determine backup or restore action.");
66 | stopSelf();
67 | return;
68 | }
69 |
70 | final String action = intent.getAction();
71 | if (ACTION_BACKUP.equals(action)) {
72 | onBackup();
73 | } else if (ACTION_BACKUP_IMMEDIATELY.equals(action)) {
74 | backupImmediately();
75 | } else if (ACTION_RESTORE.equals(action)) {
76 | onRestore();
77 | }
78 | }
79 |
80 | protected void onBackup() {
81 | //schedule a backup for shortly in the future, allowing for any more DB writes
82 | //to keep pushing the backup forward
83 | mHandler.removeCallbacks(mScheduler);
84 | mHandler.postDelayed(mScheduler, SCHEDULE_DELAY);
85 | }
86 |
87 | protected void doBackup() {
88 | doBackup(DONT_NOTIFY);
89 | }
90 |
91 | protected void doBackup(final boolean notifyOnSuccess) {
92 |
93 | //actually doing the backup should be in a separate thread, so we don't bog down the UI at all
94 | new Thread(new Runnable() {
95 |
96 | public void run() {
97 | if (USE_DRIVE) {
98 |
99 | } else {
100 | backupToSDCard(notifyOnSuccess);
101 | }
102 | }
103 |
104 | }).start();
105 | }
106 |
107 | protected void backupImmediately() {
108 | doBackup(DO_NOTIFY);
109 | }
110 |
111 | protected void notifySuccess() {
112 | final Context ctx = getApplicationContext();
113 | final String text = getString(R.string.backup_success, "/" + DIRECTORY + "/" + FILE_NAME);
114 | mHandler.post(new Runnable() {
115 |
116 | public void run() {
117 | Toast.makeText(ctx, text, Toast.LENGTH_LONG).show();
118 | }
119 |
120 | });
121 |
122 | }
123 |
124 | protected void backupToSDCard(boolean notify) {
125 | //find backup file on SD card
126 | //write SDML to backup file, overwriting if need be
127 | writeToSDCard(new BackupWorker().backup(getContentResolver()));
128 |
129 | if (notify) {
130 | notifySuccess();
131 | }
132 |
133 | stopSelf();
134 | }
135 |
136 | protected void writeToSDCard(String raw) {
137 | File root = Environment.getExternalStorageDirectory();
138 | File dir = new File(root, DIRECTORY);
139 | File file = new File(dir, FILE_NAME);
140 |
141 | try {
142 | dir.mkdirs();
143 | FileOutputStream os = new FileOutputStream(file);
144 | os.write(raw.getBytes());
145 | os.close();
146 |
147 | } catch (IOException e) {
148 | // likely because SD card is mounted, otherwise unwriteable...
149 | // oh well, so the backup doesn't happen *this* time. we'll live.
150 | Log.w(TAG, "error writing to file");
151 | }
152 | }
153 |
154 | protected void onRestore() {
155 | // no need to schedule Restore, in fact we want it done ASAP
156 | doRestore();
157 | }
158 |
159 | protected void doRestore() {
160 |
161 | //actually doing the restore should be in a separate thread, so we don't bog down the UI at all
162 | new Thread(new Runnable() {
163 |
164 | public void run() {
165 | //find backup file on SD card
166 | //read SDML from backup file
167 |
168 | boolean success = new BackupWorker().restore(getContentResolver(), readFromSDCard());
169 | if (!success) {
170 | notifyRestoreFailure();
171 | }
172 | stopSelf();
173 | }
174 |
175 | }).start();
176 | }
177 |
178 | protected void notifyRestoreFailure() {
179 | final Context ctx = getApplicationContext();
180 | final String text = getString(R.string.restore_failure);
181 | mHandler.post(new Runnable() {
182 |
183 | public void run() {
184 | NotificationManager nm = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
185 |
186 | CharSequence tickerText = "Restore failed";
187 | long when = TimeUtil.getCurrentTime();
188 |
189 | Notification notification = new Notification(R.drawable.icon, tickerText, when);
190 | Intent intent = new Intent(ctx, ServiceDroidActivity.class);
191 | PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, intent, 0);
192 |
193 | CharSequence contentText = text;
194 |
195 | notification.setLatestEventInfo(ctx, tickerText, contentText, pendingIntent);
196 |
197 | notification.flags |= Notification.FLAG_AUTO_CANCEL;
198 |
199 | nm.notify(2, notification);
200 | }
201 |
202 | });
203 | }
204 |
205 | protected String readFromSDCard() {
206 | File root = Environment.getExternalStorageDirectory();
207 | File dir = new File(root, DIRECTORY);
208 | File file = new File(dir, FILE_NAME);
209 | StringBuilder sb = new StringBuilder();
210 | try {
211 | BufferedReader in = new BufferedReader(new FileReader(file));
212 | String line = null;
213 | while ((line = in.readLine()) != null) {
214 | sb.append(line);
215 | }
216 |
217 | in.close();
218 | } catch (IOException e) {
219 | // likely because SD card is mounted, otherwise unwriteable...
220 | // Restore failing, but there *might* be a restore file there,
221 | // should we try again a little later? much later and we risk data
222 | // contamination
223 | Log.e(TAG, "error reading ServiceDroidBackup.sdml");
224 | }
225 | return sb.toString();
226 | }
227 |
228 | @Override
229 | public IBinder onBind(Intent arg0) {
230 | return null;
231 | }
232 |
233 | }
234 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/service/ReminderService.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.service;
2 |
3 | import java.util.Calendar;
4 | import com.monstarlab.servicedroid.receiver.NotificationReceiver;
5 |
6 | import android.app.AlarmManager;
7 | import android.app.PendingIntent;
8 | import android.app.Service;
9 | import android.content.Intent;
10 | import android.os.IBinder;
11 |
12 | public class ReminderService extends Service {
13 |
14 | private static final String TAG = "ReminderService";
15 |
16 | /*@Override
17 | public void onStart(Intent intent, int startId) {
18 | handleCommand(intent);
19 | }*/
20 |
21 | public int onStartCommand(Intent intent, int flags, int startId) {
22 | return 2; // START_NOT_STICKY
23 | }
24 |
25 | @Override
26 | public void onCreate() {
27 | scheduleReminderNotification();
28 | stopSelf();
29 | }
30 |
31 | private void scheduleReminderNotification() {
32 | Intent intent = new Intent(this, NotificationReceiver.class);
33 | intent.setType(Integer.toString(NotificationReceiver.TYPE_REMINDER));
34 | intent.setAction(Integer.toString(NotificationReceiver.TYPE_REMINDER));
35 |
36 |
37 | AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
38 | PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
39 |
40 | //first day of the month, around 5pm
41 | long time = getFirstDayOfMonth();
42 |
43 | am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
44 | }
45 |
46 | private long getFirstDayOfMonth() {
47 | long time = 0L;
48 |
49 | Calendar c = Calendar.getInstance();
50 |
51 |
52 | if ((c.get(Calendar.DATE) == 1) && (c.get(Calendar.HOUR_OF_DAY) < 17)) {
53 | //if its the 1st, schedule for today
54 | } else {
55 | //else schedule for next month
56 | c.add(Calendar.MONTH, 1); //next month
57 | c.set(Calendar.DATE, 1); //beginning of month
58 | }
59 |
60 | c.set(Calendar.HOUR_OF_DAY, 17); //at 5pm
61 | c.set(Calendar.MINUTE, 0);
62 |
63 | time = c.getTimeInMillis();
64 |
65 | return time;
66 | }
67 |
68 | @Override
69 | public IBinder onBind(Intent arg0) {
70 | return null;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/service/TimerService.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.service;
2 |
3 | import java.text.ParseException;
4 |
5 | import com.monstarlab.servicedroid.R;
6 | import com.monstarlab.servicedroid.activity.TimeActivity;
7 | import com.monstarlab.servicedroid.model.Models.TimeEntries;
8 | import com.monstarlab.servicedroid.util.TimeUtil;
9 |
10 | import android.app.Notification;
11 | import android.app.NotificationManager;
12 | import android.app.PendingIntent;
13 | import android.app.Service;
14 | import android.content.ContentUris;
15 | import android.content.ContentValues;
16 | import android.content.Context;
17 | import android.content.Intent;
18 | import android.content.res.Resources;
19 | import android.database.Cursor;
20 | import android.os.Handler;
21 | import android.os.IBinder;
22 |
23 | public class TimerService extends Service {
24 |
25 | private static final int SHOW_TIMER_NOTIFICATION = 21;
26 | //private TimeUtil mTimeHelper;
27 | private Handler mHandler = new Handler();
28 | private long mStartTime;
29 | private long mRunTime = 0L;
30 | private TimeUtil mTimeHelper;
31 | private Notification mNotification;
32 | private int mEntryID;
33 | private Resources mResources;
34 |
35 | private static final String[] PROJECTION = new String[]{ TimeEntries._ID, TimeEntries.DATE, TimeEntries.LENGTH };
36 |
37 | public static boolean isRunning = false;
38 |
39 |
40 | @Override
41 | public void onStart(Intent intent, int startId) {
42 |
43 | }
44 |
45 | public int onStartCommand(Intent intent, int flags, int startId) {
46 | return 1; // START_STICKY
47 | }
48 |
49 | @Override
50 | public void onCreate() {
51 | isRunning = true;
52 |
53 | mTimeHelper = new TimeUtil(this);
54 | mResources = getResources();
55 | //show a notification
56 | createNotification();
57 | showTimerNotification();
58 | //create a timer
59 | createTimer();
60 |
61 | //update timer with time
62 | }
63 |
64 | @Override
65 | public void onDestroy() {
66 | removeTimer();
67 | ((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).cancel(SHOW_TIMER_NOTIFICATION);
68 |
69 | saveTime();
70 | isRunning = false;
71 | }
72 |
73 | private void createNotification() {
74 | int icon = R.drawable.icon; // icon from resources
75 | CharSequence tickerText = getString(R.string.timer_active); // ticker-text
76 | long when = System.currentTimeMillis(); // notification time
77 |
78 | mNotification = new Notification(icon, tickerText, when);
79 | }
80 |
81 | private void showTimerNotification() {
82 |
83 | CharSequence contentText = getString(R.string.time_in_service, TimeUtil.toTimeString((int) mRunTime, mResources)); // expanded message text
84 | CharSequence contentTitle = getString(R.string.app_name); // expanded message title
85 |
86 | Intent notificationIntent = new Intent(this, TimeActivity.class);
87 | PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
88 |
89 | // the next two lines initialize the Notification, using the configurations above
90 |
91 |
92 | mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
93 | mNotification.flags |= Notification.FLAG_NO_CLEAR;
94 |
95 | mNotification.setLatestEventInfo(getApplicationContext(), contentTitle, contentText, contentIntent);
96 |
97 | ((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).notify(SHOW_TIMER_NOTIFICATION, mNotification);
98 | }
99 |
100 |
101 | private void createTimer() {
102 | //find a TimeEntry with 0 length
103 | mStartTime = getStartOfEmptyEntry();
104 | if(mStartTime == 0) {
105 | return;
106 | }
107 | mHandler.removeCallbacks(mUpdateTimeTask);
108 | mHandler.postDelayed(mUpdateTimeTask, 100);
109 |
110 | }
111 |
112 | private long getStartOfEmptyEntry() {
113 | Cursor c = getContentResolver().query(TimeEntries.CONTENT_URI, PROJECTION, TimeEntries.LENGTH + " is null or " + TimeEntries.LENGTH + "=0", null, null);
114 | long time = 0;
115 |
116 | if(c.getCount() > 0) {
117 | c.moveToFirst();
118 | mEntryID = c.getInt(0);
119 | try {
120 | time = mTimeHelper.parseDateText(c.getString(1)).getTime();
121 | } catch (ParseException e) {
122 | time = 0;
123 | }
124 | }
125 | c.close();
126 |
127 | if(time == 0L) {
128 | stopSelf();
129 | }
130 |
131 | return time;
132 |
133 | }
134 |
135 | private void removeTimer() {
136 | mHandler.removeCallbacks(mUpdateTimeTask);
137 | }
138 |
139 | private void saveTime() {
140 |
141 | if(mRunTime >= 60) {
142 | ContentValues values = new ContentValues();
143 | values.put(TimeEntries.LENGTH, mRunTime);
144 | values.put(TimeEntries.DATE, TimeUtil.getCurrentDateSQLText());
145 | getContentResolver().update(ContentUris.withAppendedId(TimeEntries.CONTENT_URI, mEntryID), values, null, null);
146 | } else {
147 |
148 | // be sure to delete the entry so timer doesn't start back up later
149 | getContentResolver().delete(ContentUris.withAppendedId(TimeEntries.CONTENT_URI, mEntryID), null, null);
150 | }
151 |
152 | }
153 |
154 | @Override
155 | public IBinder onBind(Intent intent) {
156 | return null;
157 | }
158 |
159 | private Runnable mUpdateTimeTask = new Runnable() {
160 | public void run() {
161 | final long start = mStartTime;
162 | int newTime = (int)( System.currentTimeMillis() - start) / 1000;
163 |
164 | if(newTime >= mRunTime + 60) {
165 | //every 60 seconds, update notification
166 | mRunTime = newTime;
167 | showTimerNotification();
168 | }
169 |
170 | //if timer goes over 24 hours, go ahead and stop it.
171 | if (mRunTime > TimeEntries.MAX_LENGTH) {
172 | mRunTime = TimeEntries.MAX_LENGTH;
173 | stopSelf();
174 | return;
175 | }
176 |
177 | mHandler.postDelayed(this, 15000); // every 15 seconds...
178 | }
179 | };
180 |
181 | }
182 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/util/Changelog.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.util;
2 |
3 | import com.monstarlab.servicedroid.R;
4 |
5 | import android.app.AlertDialog;
6 | import android.content.Context;
7 | import android.content.DialogInterface;
8 | import android.content.SharedPreferences;
9 | import android.content.SharedPreferences.Editor;
10 | import android.text.TextUtils;
11 | import android.webkit.WebView;
12 |
13 | public class Changelog {
14 |
15 | //private static final int V_1_0 = 1;
16 | //private static final int V_1_1 = 2;
17 | //private static final int V_1_2 = 3;
18 | //private static final int V_1_2_1 = 4; //just bug fixes, no changelog needed
19 | //private static final int V_1_2_2 = 5; //just bug fixes, no changelog needed
20 | private static final int V_1_3 = 6;
21 | //private static final int V_1_3_1 = 7; //just bug fixes, no changelog needed
22 | //private static final int V_1_3_2 = 8; //just bug fixes, no changelog needed
23 | //private static final int V_1_3_3 = 9; //just bug fixes, no changelog needed
24 | //private static final int V_1_3_4 = 10; //just bug fixes, no changelog needed
25 | //private static final int V_1_3_5 = 11; //just bug fixes, no changelog needed
26 | private static final int V_1_4 = 12;
27 | //private static final int V_1_4_1 = 13; //just bug fixes, no changelog needed
28 | //private static final int V_1_4_2 = 14; //just bug fixes, no changelog needed
29 | //private static final int V_1_4_3 = 15; //just bug fixes, no changelog needed
30 | //private static final int V_1_4_4 = 16; //just bug fixes, no changelog needed
31 | //private static final int V_1_4_5 = 15; //just bug fixes, no changelog needed
32 |
33 | private static final int CURRENT_VERSION = V_1_4;
34 |
35 | private static final String PREFS_NAME = "Changelog";
36 | private static final String PREFS_CHANGELOG_VERSION = "lastSeenChangelogVersion";
37 |
38 | public static void showFirstTime(final Context c) {
39 | if (hasSeenMessage(c)) {
40 | // do nothing
41 | } else {
42 | final AlertDialog.Builder builder = new AlertDialog.Builder(c);
43 | final WebView webView = new WebView(c);
44 |
45 | int title = R.string.whats_new;
46 |
47 | builder.setTitle(title);
48 | builder.setView(webView);
49 | builder.setCancelable(false);
50 |
51 | builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
52 | public void onClick(DialogInterface dialog, int which) {
53 | markMessageSeen(c);
54 | }
55 | });
56 | String message = getMessage(c);
57 | if(TextUtils.isEmpty(message)) {
58 | return;
59 | }
60 |
61 | webView.loadDataWithBaseURL(null, message, "text/html", "UTF-8", "about:blank");
62 | builder.show();
63 | }
64 | }
65 |
66 | private static boolean hasSeenMessage(Context c) {
67 | SharedPreferences settings = c.getSharedPreferences(PREFS_NAME, 0);
68 | return settings.getInt(PREFS_CHANGELOG_VERSION, 0) >= CURRENT_VERSION;
69 | }
70 |
71 | private static void markMessageSeen(Context c) {
72 | SharedPreferences settings = c.getSharedPreferences(PREFS_NAME, 0);
73 | Editor editor=settings.edit();
74 | editor.putInt(PREFS_CHANGELOG_VERSION, CURRENT_VERSION);
75 | editor.commit();
76 | }
77 |
78 | private static String getMessage(Context c) {
79 | StringBuilder message = new StringBuilder();
80 |
81 | /*String[] features = c.getResources().getStringArray(R.array.changelog);
82 | message.append("");
83 |
84 | message.append("v1.4.0");
85 | message.append("");
86 | for(int i = 0; i < features.length; i++) {
87 | message.append("- " + features[i] + "
");
88 | }
89 | message.append("
");
90 |
91 | message.append("" + c.getString(R.string.enjoy_servicedroid) + "");
92 | message.append("");
93 | message.append("- " + c.getString(R.string.give_review) + "
");
94 | message.append("
");
95 |
96 | message.append("");*/
97 | return message.toString();
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/util/ServiceDroidDocument.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.util;
2 |
3 | import java.io.IOException;
4 | import java.io.StringReader;
5 |
6 | import javax.xml.parsers.DocumentBuilder;
7 | import javax.xml.parsers.DocumentBuilderFactory;
8 | import javax.xml.parsers.ParserConfigurationException;
9 |
10 | import org.w3c.dom.Document;
11 | import org.w3c.dom.Element;
12 | import org.w3c.dom.NamedNodeMap;
13 | import org.w3c.dom.Node;
14 | import org.w3c.dom.Text;
15 | import org.w3c.dom.NodeList;
16 | import org.xml.sax.InputSource;
17 | import org.xml.sax.SAXException;
18 |
19 | import android.text.Html;
20 | import android.text.TextUtils;
21 | import android.util.Log;
22 |
23 | public class ServiceDroidDocument {
24 |
25 | private static final String TAG = "ServiceDroidDocument";
26 |
27 | protected static final int SCHEMA_ATTRS = 1;
28 | protected static final int SCHEMA_ELS = 2;
29 |
30 | protected Document mDoc;
31 | protected int mSchema = 0;
32 |
33 | public ServiceDroidDocument() {
34 | this("");
35 | }
36 |
37 | public ServiceDroidDocument(String xml) {
38 | try {
39 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
40 | DocumentBuilder builder = factory.newDocumentBuilder();
41 |
42 | mDoc = builder.parse(new InputSource(new StringReader(xml)));
43 |
44 | } catch (ParserConfigurationException e) {
45 | e.printStackTrace();
46 | Log.e(TAG, "Failed parsing backup file.");
47 | Log.e(TAG, e.toString());
48 | } catch (SAXException e) {
49 | e.printStackTrace();
50 | Log.e(TAG, "Failed parsing backup file.");
51 | Log.e(TAG, e.toString());
52 | } catch (IOException e) {
53 | e.printStackTrace();
54 | Log.e(TAG, "Failed reading backup file from SD card.");
55 | Log.e(TAG, e.toString());
56 | } finally {
57 | if (mDoc == null) {
58 |
59 | } else {
60 | mSchema = getSchema();
61 | }
62 | }
63 | }
64 |
65 | public boolean isValid() {
66 | return mDoc != null;
67 | }
68 |
69 | public int getSchema() {
70 | String schema = mDoc.getDocumentElement().getAttribute("schema");
71 |
72 | if (TextUtils.isEmpty(schema)) {
73 | return SCHEMA_ATTRS;
74 | } else {
75 | return Integer.parseInt(schema);
76 | }
77 | }
78 |
79 |
80 | public void addNode(String tagName, String[] attributes, String[] values) {
81 | Element el = mDoc.createElement(tagName);
82 | for (int i = 0; i < attributes.length; i++) {
83 | //el.setAttribute(attributes[i], TextUtils.htmlEncode(values[i]));
84 | String content = values[i];
85 | if (content != null) {
86 | Element attr = mDoc.createElement(attributes[i]);
87 |
88 | setTextContent(attr, TextUtils.htmlEncode(content));
89 | el.appendChild(attr);
90 | }
91 |
92 | }
93 | mDoc.getDocumentElement().appendChild(el);
94 | }
95 |
96 | public int getNumberOfTag(String tagName) {
97 | return mDoc.getElementsByTagName(tagName).getLength();
98 | }
99 |
100 | public String[][] getDataFromNode(String tagName, int index) {
101 | Node node = mDoc.getElementsByTagName(tagName).item(index);
102 |
103 | switch (mSchema) {
104 | case SCHEMA_ATTRS:
105 | return getDataFromAttributes(node);
106 | case SCHEMA_ELS:
107 | default:
108 | return getDataFromChildren(node);
109 | }
110 | }
111 |
112 | private String[][] getDataFromAttributes(Node node) {
113 | NamedNodeMap attrs = node.getAttributes();
114 | int numOfAttrs = attrs.getLength();
115 |
116 | String[][] data = new String[2][numOfAttrs];
117 | for (int i = 0; i < numOfAttrs; i++) {
118 | data[0][i] = attrs.item(i).getNodeName();
119 | data[1][i] = Html.fromHtml(attrs.item(i).getNodeValue()).toString();
120 | }
121 |
122 | return data;
123 | }
124 |
125 | private String[][] getDataFromChildren(Node node) {
126 | NodeList children = node.getChildNodes();
127 |
128 | // since getChildNodes returns ALL childNodes, include whitespace nodes,
129 | // we need to do a first loop just to see how many ELEMENT nodes there are
130 | int numOfChildEls = 0;
131 | int length = children.getLength();
132 | for (int i = 0; i < length; i++) {
133 | if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
134 | numOfChildEls++;
135 | }
136 | }
137 |
138 |
139 | String[][] data = new String[2][numOfChildEls];
140 | for (int i = 0; i < length; i++) {
141 | Node child = children.item(i);
142 | if (child.getNodeType() == Node.ELEMENT_NODE) {
143 | data[0][i] = child.getNodeName();
144 | data[1][i] = Html.fromHtml(getTextContent(child).trim()).toString();
145 | }
146 | }
147 |
148 |
149 | return data;
150 | }
151 |
152 | protected String getTextContent(Node node) {
153 | StringBuffer buffer = new StringBuffer();
154 | NodeList childList = node.getChildNodes();
155 | for (int i = 0; i < childList.getLength(); i++) {
156 | Node child = childList.item(i);
157 | if (child.getNodeType() == Node.TEXT_NODE)
158 | buffer.append(child.getNodeValue());
159 | else if (child.getNodeType() == Node.ELEMENT_NODE)
160 | buffer.append(getTextContent(child));
161 | }
162 | return buffer.toString();
163 | }
164 |
165 | protected void setTextContent(Node node, String value) {
166 | Text txt = mDoc.createTextNode(value);
167 | node.appendChild(txt);
168 | }
169 |
170 | protected String getStringFromNode(Node root) {
171 | StringBuilder result = new StringBuilder();
172 |
173 | if (root.getNodeType() == Node.TEXT_NODE)
174 | result.append(root.getNodeValue());
175 | else {
176 | if (root.getNodeType() != Node.DOCUMENT_NODE) {
177 | StringBuffer attrs = new StringBuffer();
178 | for (int k = 0; k < root.getAttributes().getLength(); ++k) {
179 | attrs.append(" ").append(
180 | root.getAttributes().item(k).getNodeName()).append(
181 | "=\"").append(
182 | root.getAttributes().item(k).getNodeValue())
183 | .append("\" ");
184 | }
185 | result.append("<").append(root.getNodeName()).append(" ")
186 | .append(attrs);
187 | } else {
188 | result.append("");
189 | }
190 |
191 | NodeList nodes = root.getChildNodes();
192 | if (nodes.getLength() > 0) {
193 | if (root.getNodeType() != Node.DOCUMENT_NODE) {
194 | result.append(">");
195 | }
196 | for (int i = 0, j = nodes.getLength(); i < j; i++) {
197 | Node node = nodes.item(i);
198 | result.append(getStringFromNode(node));
199 | }
200 | if (root.getNodeType() != Node.DOCUMENT_NODE) {
201 | result.append("").append(root.getNodeName()).append(">");
202 | }
203 | } else {
204 | if (root.getNodeType() != Node.DOCUMENT_NODE) {
205 | result.append("/>");
206 | }
207 | }
208 |
209 |
210 | }
211 | return result.toString();
212 | }
213 |
214 | public String toString() {
215 |
216 | return getStringFromNode(mDoc);
217 | //return null;
218 | }
219 |
220 | }
221 |
--------------------------------------------------------------------------------
/src/com/monstarlab/servicedroid/util/TimeUtil.java:
--------------------------------------------------------------------------------
1 | package com.monstarlab.servicedroid.util;
2 |
3 | import java.text.DateFormat;
4 | import java.text.ParseException;
5 | import java.text.SimpleDateFormat;
6 | import java.util.Calendar;
7 | import java.util.Date;
8 |
9 | import com.monstarlab.servicedroid.R;
10 |
11 | import android.content.Context;
12 | import android.content.res.Resources;
13 |
14 | public class TimeUtil {
15 |
16 | //SQLite will return format like "2010-04-16 20:56:21"
17 | private DateFormat mDateTimeParser;
18 | private DateFormat mDateParser;
19 | private DateFormat mDateFormatter;
20 |
21 | public static final int HOUR = 3600;
22 | public static final int MIN = 60;
23 |
24 |
25 | // Month Constants, to be compared against .getCurrentMonth()
26 | public static final int JANUARY = 1;
27 | public static final int FEBRUARY = 2;
28 | public static final int MARCH = 3;
29 | public static final int APRIL = 4;
30 | public static final int MAY = 5;
31 | public static final int JUNE = 6;
32 | public static final int JULY = 7;
33 | public static final int AUGUST = 8;
34 | public static final int SEPTEMBER = 9;
35 | public static final int OCTOBER = 10;
36 | public static final int NOVEMBER = 11;
37 | public static final int DECEMBER = 12;
38 |
39 | public TimeUtil(Context ctx) {
40 | mDateParser = new SimpleDateFormat("yyyy-MM-dd");
41 | mDateTimeParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
42 | mDateFormatter = android.text.format.DateFormat.getDateFormat(ctx);
43 | }
44 |
45 | /**
46 | *
47 | * @param text String A date in "yyyy-MM-dd HH:mm:ss" format.
48 | * @return String A the date formatted to the user's preferences, or the untouched date if errored.
49 | */
50 | public String normalizeDate(String text) {
51 | try {
52 | return formatDate(parseDateText(text));
53 | } catch (ParseException e) {
54 | return text;
55 | }
56 |
57 | }
58 |
59 | public Date parseDateText(String text) throws ParseException {
60 | try {
61 | return mDateTimeParser.parse(text);
62 | } catch(ParseException e) {
63 | return mDateParser.parse(text);
64 | }
65 | }
66 |
67 | public String formatDate(Date d) {
68 | return mDateFormatter.format(d);
69 | }
70 |
71 | public static String toTimeString(int time, Resources r) {
72 | StringBuilder out = new StringBuilder();
73 |
74 | int hours = getHours(time);
75 | if(hours > 0) {
76 | out.append(hours);
77 | if(hours > 1) {
78 | out.append(r.getString(R.string.hrs));
79 | } else {
80 | out.append(r.getString(R.string.hr));
81 | }
82 | }
83 |
84 | int mins = getMins(time);
85 | if(mins > 0) {
86 | if(hours > 0) {
87 | out.append(" ");
88 | }
89 | out.append(mins);
90 | if(mins > 1) {
91 | out.append(r.getString(R.string.mins));
92 | } else {
93 | out.append(r.getString(R.string.min));
94 | }
95 | }
96 |
97 | if(out.toString() == "") {
98 | out.append("0mins");
99 | }
100 |
101 | return out.toString();
102 | }
103 |
104 | public static int toTimeInt(int hours, int mins) {
105 | return (hours * HOUR) + (mins * MIN);
106 | }
107 |
108 | public static int getHours(int time) {
109 | return time / HOUR;
110 | }
111 |
112 | public static int getMins(int time) {
113 | return (time - (getHours(time) * HOUR)) / MIN;
114 | }
115 |
116 | public static String pad(int number) {
117 | if(number < 10) {
118 | return "0"+number;
119 | } else {
120 | return ""+number;
121 | }
122 | }
123 |
124 | /*
125 | * returns Year after 2000. Ex: 12.
126 | */
127 | public static int getCurrentYear() {
128 | Calendar c = Calendar.getInstance();
129 | return c.get(Calendar.YEAR);
130 | }
131 |
132 | /*
133 | * returns Month (1-12)
134 | */
135 | public static int getCurrentMonth() {
136 | Calendar c = Calendar.getInstance();
137 | return c.get(Calendar.MONTH) + 1;
138 | }
139 |
140 | public static int getCurrentDay() {
141 | Calendar c = Calendar.getInstance();
142 | return c.get(Calendar.DATE);
143 | }
144 |
145 | public static Date getCurrentDate() {
146 | Calendar c = Calendar.getInstance();
147 | return c.getTime();
148 | }
149 |
150 | public static int getCurrentHour() {
151 | Calendar c = Calendar.getInstance();
152 | return c.get(Calendar.HOUR_OF_DAY);
153 | }
154 |
155 | public static int getCurrentMinute() {
156 | Calendar c = Calendar.getInstance();
157 | return c.get(Calendar.MINUTE);
158 | }
159 |
160 | public static int getCurrentSecond() {
161 | Calendar c = Calendar.getInstance();
162 | return c.get(Calendar.SECOND);
163 | }
164 |
165 | public static String getCurrentDateSQLText() {
166 | return new StringBuilder()
167 | .append(getCurrentYear())
168 | .append("-")
169 | .append(pad(getCurrentMonth()))
170 | .append("-")
171 | .append(pad(getCurrentDay()))
172 | .toString();
173 | }
174 |
175 | public static String getCurrentTimeSQLText() {
176 | return new StringBuilder()
177 | .append(getCurrentYear())
178 | .append("-")
179 | .append(pad(getCurrentMonth()))
180 | .append("-")
181 | .append(pad(getCurrentDay()))
182 | .append(" ")
183 | .append(pad(getCurrentHour()))
184 | .append(":")
185 | .append(pad(getCurrentMinute()))
186 | .append(":")
187 | .append(pad(getCurrentSecond()))
188 | .toString();
189 | }
190 |
191 | public static long getCurrentTime() {
192 | Calendar c = Calendar.getInstance();
193 | return c.getTimeInMillis();
194 | }
195 |
196 | public static String getSQLTextFromDate(Date d) {
197 | return new StringBuilder()
198 | .append(d.getYear() + 1900)
199 | .append("-")
200 | .append(pad(d.getMonth() + 1))
201 | .append("-")
202 | .append(pad(d.getDate()))
203 | .toString();
204 | }
205 |
206 | public static String getSQLTextFromTime(Date d) {
207 | return new StringBuilder()
208 | .append(getSQLTextFromDate(d))
209 | .append(" ")
210 | .append(pad(d.getHours()))
211 | .append(":")
212 | .append(pad(d.getMinutes()))
213 | .append(":")
214 | .append(pad(d.getSeconds()))
215 | .toString();
216 | }
217 | }
218 |
--------------------------------------------------------------------------------