13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {2014} {Daniele Maddaluno}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #  Android Update Checker
2 |
3 | The project aims to provide a reusable instrument to check asynchronously if exists any newer released update of your app on the Store.
4 |
5 | It uses the Java HTML Parser [Jsoup](http://jsoup.org/) to test if a new update really exists parsing the app page on the Google Play Store.
6 |
7 | 
8 |
9 |
10 | ## Quick Setup
11 |
12 | ### 1. Include library
13 | #### Automatically ([  ](https://bintray.com/danielemaddaluno/maven/androidupdatechecker/_latestVersion)):
14 | **Automatically with Gradle**
15 | ``` gradle
16 | dependencies {
17 | compile 'com.github.danielemaddaluno.androidupdatechecker:library:1.0.2'
18 | }
19 | ```
20 | Remember to replace "1.0.2" with the latest version available.
21 | If you want to automatically take the latest version, you could use this:
22 | ``` gradle
23 | dependencies {
24 | repositories {
25 | mavenCentral()
26 | // maven {
27 | // url 'http://dl.bintray.com/danielemaddaluno/maven/'
28 | // }
29 | }
30 | compile 'com.github.danielemaddaluno.androidupdatechecker:library:+'
31 | }
32 | ```
33 | **Automatically with Maven**
34 | ``` xml
35 |
36 |
37 | ...
38 |
39 |
40 | danielemaddaluno
41 | Daniele Maddaluno Bintray Repository
42 | http://dl.bintray.com/danielemaddaluno/maven/
43 |
44 |
45 | ...
46 |
47 |
48 | com.github.danielemaddaluno.androidupdatechecker
49 | library
50 | LATEST
51 |
52 |
53 | ...
54 |
55 | ```
56 | #### Manual:
57 | **Manual - Using [Android Studio](https://developer.android.com/sdk/installing/studio.html):**
58 | * Download the UpdateCheckerLib folder and import to your root application folder.
59 | You can manually achieve this step with 3 steps:
60 | 1. Paste the folder UpdateCheckerLib into your application at the same level of your app, build and gradle folder
61 | 2. Add to your settings.gradle file the following code line:
62 | "include ':app', ':UpdateCheckerLib'"
63 | 3. Rebuild the project
64 | * File → Project Structure → in Modules section click on "app" → Click on tab "Dependecies" → Click on the green plus → Module Dependecy → Select ":UpdateCheckerLib"
65 | * Done =)
66 |
67 | or
68 |
69 | **Manual - Using [Eclipse ADT](http://developer.android.com/sdk/index.html)**
70 | * Download the UpdateCheckerLib folder and import into the workspace
71 | * Right click on the project imported → Properties → Android → Check the box "Is Library"
72 | * Right click on the Main Project → Properties → Android → Add → Select UpdateCheckerLib → OK
73 |
74 |
75 | ### 2. Android Manifest
76 | ``` xml
77 |
78 |
79 |
80 | ...
81 |
82 | ```
83 |
84 | ### 3. Activity class
85 | ``` java
86 | public class DemoUpdateCheckerActivity extends ActionBarActivity {
87 | @Override
88 | protected void onCreate(Bundle savedInstanceState) {
89 | super.onCreate(savedInstanceState);
90 | setContentView(R.layout.activity_demo_update_checker);
91 | /* Use this when you want to run a background update check */
92 | new UpdateRunnable(this, new Handler()).start();
93 | }
94 |
95 | /** Called when the user clicks the button */
96 | public void forceUpdateTest(View view) {
97 | if(view.getId() == R.id.button_force_update_test){
98 | /* Use this if an update check is explicitly requested by a user action */
99 | new UpdateRunnable(this, new Handler()).force(true).start();
100 | }
101 | }
102 | }
103 | ```
104 |
105 | ### 4. Proguard
106 | If you are using Proguard you have to add the following lines to your Proguard rules:
107 | ``` java
108 | -keep public class org.jsoup.** {
109 | public *;
110 | }
111 | ```
112 |
113 | ## Applications using Android Update Checker
114 | **[Indian Rail Salary Calculator](https://play.google.com/store/apps/details?id=com.cr.taxc.activity&hl=en)** | **[AutoVelox Fissi e Mobili Map](https://play.google.com/store/apps/details?id=com.italia.autovelox.autoveloxfissiemoibli)** | **[Školníček Gymspk](https://play.google.com/store/apps/details?id=cz.hoky.gympsk)** | **[amaze](https://play.google.com/store/apps/details?id=kongligit.amaze.android)** | **[Italia Notizie - IT News](https://play.google.com/store/apps/details?id=com.madx.pratonews)**
115 |
116 | ## License
117 |
118 | If you use Android Update Checker code in your application you should inform the author about it ( *email: daniele.maddaluno[at]gmail[dot]com* ) like this:
119 | > **Subject:** AUC usage notification
120 | > **Text:** I use Android Update Checker <lib_version> in <application_name> - http://link_to_google_play.
121 | > I [allow | don't allow] to mention my app in section "Applications using Android Update Checker" on GitHub.
122 |
123 | Also I'll be grateful if you mention AUC in application UI with string **"Using Android Update Checker (c) 2014, Daniele Maddaluno"** (e.g. in some "About" section).
124 |
125 | Copyright 2014 Daniele Maddaluno
126 |
127 | Licensed under the Apache License, Version 2.0 (the "License");
128 | you may not use this file except in compliance with the License.
129 | You may obtain a copy of the License at
130 |
131 | http://www.apache.org/licenses/LICENSE-2.0
132 |
133 | Unless required by applicable law or agreed to in writing, software
134 | distributed under the License is distributed on an "AS IS" BASIS,
135 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136 | See the License for the specific language governing permissions and
137 | limitations under the License.
138 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | *.apk
3 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | generateDebugSources
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 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion compileSdk
5 |
6 | defaultConfig {
7 | applicationId "com.madx.updatechecker"
8 | minSdkVersion minSdk
9 | targetSdkVersion targetSdk
10 | multiDexEnabled true
11 | versionCode 9
12 | versionName "1.0.8"
13 | }
14 |
15 | }
16 |
17 | dependencies {
18 | repositories {
19 | mavenCentral()
20 | // maven {
21 | // url 'http://dl.bintray.com/danielemaddaluno/maven/'
22 | // }
23 | }
24 |
25 | testImplementation 'junit:junit:4.12'
26 |
27 | implementation fileTree(include: ['*.jar'], dir: 'libs')
28 | implementation 'org.jsoup:jsoup:1.8.1'
29 | implementation "androidx.appcompat:appcompat:${androidXVersion}"
30 | compile project(':library')
31 |
32 | // implementation 'com.github.danielemaddaluno.androidupdatechecker:library:+'
33 | }
34 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Program Files (x86)\Android\android-studio\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | -keep public class org.jsoup.** {
20 | public *;
21 | }
22 |
23 | -keep public class com.google.android.gms.ads.** {
24 | public *;
25 | }
26 |
27 | -keep public class com.google.ads.** {
28 | public *;
29 | }
30 |
31 | -keep class * extends java.util.ListResourceBundle {
32 | protected Object[][] getContents();
33 | }
34 |
35 | -keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
36 | public static final *** NULL;
37 | }
38 |
39 | -keepnames @com.google.android.gms.common.annotation.KeepName class *
40 | -keepclassmembernames class * {
41 | @com.google.android.gms.common.annotation.KeepName *;
42 | }
43 |
44 | -keepnames class * implements android.os.Parcelable {
45 | public static final ** CREATOR;
46 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/madx/updatechecker/DemoUpdateCheckerActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Daniele Maddaluno
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.madx.updatechecker;
18 |
19 | import android.app.Activity;
20 | import android.os.Bundle;
21 | import android.os.Handler;
22 | import android.view.View;
23 |
24 | import com.madx.updatechecker.lib.UpdateRunnable;
25 |
26 |
27 | public class DemoUpdateCheckerActivity extends Activity {
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_demo_update_checker);
33 | new UpdateRunnable(this, new Handler()).start();
34 | }
35 |
36 | /**
37 | * Called when the user clicks the Send button
38 | */
39 | public void forceUpdateTest(View view) {
40 | if (view.getId() == R.id.button_force_update_test) {
41 | new UpdateRunnable(this, new Handler()).force(true).start();
42 | }
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_demo_update_checker.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
27 |
28 |
29 |
39 |
40 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
21 | 64dp
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | 16dp
20 | 16dp
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | UpdateChecker
19 | Demo Update Checker
20 | Source and Demo code at https://github.com/danielemaddaluno/Android-Update-Checker\n\n
21 | If the Update Check is requested by a user action you can call the following code line (you can test this function by clicking the button above):\n
22 | new UpdateRunnable(this, new Handler()).force(true).start();\n\n
23 | Otherwise if you want to use the Update Checker automatically, you can call from the onCreate() of your activity the following code line, which will test for updates automatically once a day:\n
24 | new UpdateRunnable(this, new Handler()).start();
25 |
26 | Settings
27 | Force Update Check
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/test/java/com/madx/updatechecker/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.madx.updatechecker;
2 |
3 | import android.util.Log;
4 |
5 | import org.jsoup.Jsoup;
6 | import org.jsoup.select.Elements;
7 | import org.junit.Test;
8 |
9 | import java.io.IOException;
10 |
11 | import static org.junit.Assert.assertEquals;
12 | import static org.junit.Assert.assertNotNull;
13 |
14 | /**
15 | * Example local unit test, which will execute on the development machine (host).
16 | *
17 | * @see Testing documentation
18 | */
19 | public class ExampleUnitTest {
20 |
21 | public static class Item {
22 | public String id;
23 | public String value;
24 |
25 | public Item(String id, String value) {
26 | this.id = id;
27 | this.value = value;
28 | }
29 | }
30 |
31 | private static final String APPLICATION_ID = "com.fireflystudios.strongholdkingdoms"; // BuildConfig.APPLICATION_ID
32 |
33 | @Test
34 | public void getStartTime() throws IOException {
35 | String new_version = Jsoup.connect("https://play.google.com/store/apps/details?id=" + APPLICATION_ID + "&hl=it")
36 | .timeout(30000)
37 | .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6")
38 | .referrer("http://www.google.com")
39 | .get()
40 | .select(".W4P4ne div.hAyfc span.htlgb span.htlgb")
41 | .get(3)
42 | .ownText();
43 | assertNotNull(new_version);
44 | System.out.println("new_version: " + new_version);
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | apply from: 'constants.gradle'
3 |
4 | buildscript {
5 | repositories {
6 | google()
7 | jcenter()
8 | apply plugin: 'maven'
9 | maven { url "http://jcenter.bintray.com"}
10 | }
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:3.4.0'
13 | //classpath 'com.github.dcendents:android-maven-plugin:1.2'
14 | //classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.1"
15 | // NOTE: Do not place your application dependencies here; they belong
16 | // in the individual module build.gradle files
17 | }
18 | }
19 |
20 | allprojects {
21 | repositories {
22 | google()
23 | jcenter()
24 | maven { url 'https://maven.fabric.io/public' }
25 | maven { url "https://jitpack.io" }
26 | maven { url "http://jcenter.bintray.com"}
27 | }
28 | }
29 |
30 | //task clean(type: Delete) {
31 | // delete rootProject.buildDir
32 | //}
33 |
--------------------------------------------------------------------------------
/constants.gradle:
--------------------------------------------------------------------------------
1 | project.ext {
2 |
3 | compileSdk = 28
4 | targetSdk = 28
5 | minSdk = 14
6 |
7 | androidXVersion = '1.0.0'
8 | androidXConstraintlayoutVersion = '1.1.3'
9 | androidXMultidexVersion = '2.0.0'
10 | androidXEspressoCoreVersion = '3.1.0'
11 | androidXRunnerVersion = '1.1.0'
12 |
13 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Apr 19 00:26:57 CEST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/images/.gitignore:
--------------------------------------------------------------------------------
1 | /store
--------------------------------------------------------------------------------
/images/ic_launcher/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/images/ic_launcher/ic_launcher.png
--------------------------------------------------------------------------------
/images/ic_launcher/ic_launcher.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/images/ic_launcher/ic_launcher.psd
--------------------------------------------------------------------------------
/images/readme_info/.gitignore:
--------------------------------------------------------------------------------
1 | *.graphml
2 | readme_info_light.png
--------------------------------------------------------------------------------
/images/readme_info/readme_info_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/images/readme_info/readme_info_dark.png
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | //apply plugin: 'com.github.dcendents.android-maven'
3 | //apply plugin: "com.jfrog.bintray"
4 |
5 | // This is the library version used when deploying the artifact
6 | version = "1.0.2"
7 |
8 | android {
9 | compileSdkVersion compileSdk
10 |
11 | defaultConfig {
12 | //applicationId "com.madx.updatechecker.lib"
13 | minSdkVersion minSdk
14 | targetSdkVersion targetSdk
15 | versionCode 4
16 | versionName "1.0.3"
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | }
25 |
26 | dependencies {
27 | implementation fileTree(dir: 'libs', include: ['*.jar'])
28 | implementation 'org.jsoup:jsoup:1.8.1'
29 | }
30 |
31 |
32 | //def siteUrl = 'https://github.com/danielemaddaluno/Android-Update-Checker' // Homepage URL of the library
33 | //def gitUrl = 'https://github.com/danielemaddaluno/Android-Update-Checker.git' // Git repository URL
34 | //group = "com.github.danielemaddaluno.androidupdatechecker" // Maven Group ID for the artifact
35 | //
36 | //
37 | //install {
38 | // repositories.mavenInstaller {
39 | // // This generates POM.xml with proper parameters
40 | // pom {
41 | // project {
42 | // packaging 'aar'
43 | //
44 | // // Add your description here
45 | // name 'Android Update Checker'
46 | // description = 'The project aims to provide a reusable instrument to check asynchronously if exists any newer released update of your Android app on the Store.'
47 | // url siteUrl
48 | //
49 | // // Set your license
50 | // licenses {
51 | // license {
52 | // name 'The Apache Software License, Version 2.0'
53 | // url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
54 | // }
55 | // }
56 | // developers {
57 | // developer {
58 | // id 'danielemaddaluno'
59 | // name 'Daniele Maddaluno'
60 | // email 'daniele.maddaluno@gmail.com'
61 | // }
62 | // }
63 | // scm {
64 | // connection gitUrl
65 | // developerConnection gitUrl
66 | // url siteUrl
67 | //
68 | // }
69 | // }
70 | // }
71 | // }
72 | //}
73 | //
74 | //task sourcesJar(type: Jar) {
75 | // from android.sourceSets.main.java.srcDirs
76 | // classifier = 'sources'
77 | //}
78 | //
79 | //task javadoc(type: Javadoc) {
80 | // source = android.sourceSets.main.java.srcDirs
81 | // classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
82 | //}
83 | //
84 | //task javadocJar(type: Jar, dependsOn: javadoc) {
85 | // classifier = 'javadoc'
86 | // from javadoc.destinationDir
87 | //}
88 | //artifacts {
89 | // archives javadocJar
90 | // archives sourcesJar
91 | //}
92 | //
93 | //Properties properties = new Properties()
94 | //properties.load(project.rootProject.file('local.properties').newDataInputStream())
95 | //
96 | //// https://github.com/bintray/gradle-bintray-plugin
97 | //bintray {
98 | // user = properties.getProperty("bintray.user")
99 | // key = properties.getProperty("bintray.apikey")
100 | //
101 | // configurations = ['archives']
102 | // pkg {
103 | // repo = "maven"
104 | // // it is the name that appears in bintray when logged
105 | // name = "androidupdatechecker"
106 | // websiteUrl = siteUrl
107 | // vcsUrl = gitUrl
108 | // licenses = ["Apache-2.0"]
109 | // publish = true
110 | // version {
111 | // gpg {
112 | // sign = true //Determines whether to GPG sign the files. The default is false
113 | // passphrase = properties.getProperty("bintray.gpg.password") //Optional. The passphrase for GPG signing'
114 | // }
115 | //// mavenCentralSync {
116 | //// sync = true //Optional (true by default). Determines whether to sync the version to Maven Central.
117 | //// user = properties.getProperty("bintray.oss.user") //OSS user token
118 | //// password = properties.getProperty("bintray.oss.password") //OSS user password
119 | //// close = '1' //Optional property. By default the staging repository is closed and artifacts are released to Maven Central. You can optionally turn this behaviour off (by puting 0 as value) and release the version manually.
120 | //// }
121 | // }
122 | // }
123 | //}
--------------------------------------------------------------------------------
/library/library.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | generateDebugSources
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 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:/Program Files (x86)/Android/android-studio/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/library/src/androidTest/java/com/madx/updatechecker/lib/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Daniele Maddaluno
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.madx.updatechecker.lib;
18 |
19 | import android.app.Application;
20 | import android.test.ApplicationTestCase;
21 |
22 | /**
23 | * Testing Fundamentals
24 | */
25 | public class ApplicationTest extends ApplicationTestCase {
26 | public ApplicationTest() {
27 | super(Application.class);
28 | }
29 | }
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/library/src/main/java/com/madx/updatechecker/lib/UpdateRunnable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Daniele Maddaluno
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.madx.updatechecker.lib;
18 |
19 | import android.app.Activity;
20 | import android.app.AlertDialog;
21 | import android.app.ProgressDialog;
22 | import android.content.Context;
23 | import android.content.DialogInterface;
24 | import android.content.Intent;
25 | import android.content.pm.PackageManager.NameNotFoundException;
26 | import android.net.Uri;
27 | import android.os.Handler;
28 | import android.preference.PreferenceManager;
29 |
30 | import com.madx.updatechecker.lib.utils.orientation.OrientationUtils;
31 | import com.madx.updatechecker.lib.utils.versioning.DefaultArtifactVersion;
32 |
33 | import org.jsoup.Jsoup;
34 |
35 |
36 | /**
37 | * It is used to verify if a new update exists.
38 | * In case {@link #force} is false a dialog is shown only if the update really exists.
39 | * In case {@link #force} is true a dialog is shown anyway.
40 | *
41 | * @author Daniele
42 | */
43 | public class UpdateRunnable implements Runnable {
44 |
45 | /**
46 | * The Activity from which the updater is called
47 | */
48 | private final Activity activity;
49 | /**
50 | * The Context from which the updater is called
51 | */
52 | private final Context context;
53 | /**
54 | * The Handler generated from the activity
55 | */
56 | private final Handler handler;
57 | /**
58 | * The package name of your app
59 | */
60 | private final String package_name;
61 | /**
62 | * The current version of your app
63 | */
64 | private final String current_version;
65 | /**
66 | * Each time you enter in an Activity which for example called: new UpdateRunnable(this, new Handler()).start();
67 | * this is the minimum time which has to pass between an automatic verification of an update and the next automatic verification.
68 | */
69 | private final long TIME_RETRY_TO_UPDATE;
70 |
71 | private static final long SEC = 1000;
72 | private static final long MIN = 60 * SEC;
73 | private static final long HOUR = 60 * MIN;
74 | private static final long DAY = 24 * HOUR;
75 |
76 | /**
77 | *
78 | *
true - use it when the user directly expressed the wish to verify if an update exists
79 | *
false - use it for automatic verification of new updates
80 | *
81 | */
82 | private boolean force = false;
83 | /**
84 | * Represents if a new update exists or not on the Google Play Store
85 | */
86 | private boolean update_available = false;
87 | /**
88 | * Is the theme used dark or not. It is used to specify different cloud drawable in the dialog.
89 | */
90 | private boolean light_theme = false;
91 | /**
92 | * A progress dialog to show in a waiting dialog
93 | */
94 | private ProgressDialog progress_dialog;
95 |
96 | /**
97 | * Updater Runnable constructor
98 | *
99 | * @param activity the activity from which the updater is called
100 | * @param handler the handler to manage the UI in the specified {@link #activity}
101 | * @param time_retry_to_update time in millis which represents the time after which the runnable called with force = false have to retry to check if an update exists
102 | */
103 | public UpdateRunnable(Activity activity, Handler handler, long time_retry_to_update) {
104 | this.activity = activity;
105 | this.context = activity.getApplicationContext();
106 | this.handler = handler;
107 | this.package_name = context.getPackageName();
108 | String current_version = new String();
109 | try {
110 | current_version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
111 | } catch (NameNotFoundException e) {
112 | } finally {
113 | this.current_version = current_version;
114 | }
115 | this.TIME_RETRY_TO_UPDATE = time_retry_to_update;
116 | }
117 |
118 | /**
119 | * Updater Runnable constructor, when called in automatic way it runs once a day
120 | *
121 | * @param activity the activity from which the updater is called
122 | * @param handler the handler to manage the UI in the specified {@link #activity}
123 | */
124 | public UpdateRunnable(Activity activity, Handler handler) {
125 | this(activity, handler, DAY);
126 | }
127 |
128 | /**
129 | * If true it means that the user has explicitly asked to verify if a new update exists so the runnable will show a dialog even if
130 | * the app is already updated (otherwise the user couldn't have a feedback from his explicit request).
131 | * If false it means that verification is started automatically (the user don't asked explicitly to verify), so a dialog is shown to the user
132 | * only if an update really exists.
133 | *
134 | * @param force if true it forces a dialog visualization (even if already updated)
135 | * @return an updater
136 | */
137 | public UpdateRunnable force(boolean force) {
138 | this.force = force;
139 | return this;
140 | }
141 |
142 | /**
143 | * @param light_theme if true uses drawables compatible with Light Themes
144 | * @return an updater
145 | */
146 | public UpdateRunnable lightTheme(boolean light_theme) {
147 | this.light_theme = light_theme;
148 | return this;
149 | }
150 |
151 | public void start() {
152 | new Thread(this).start();
153 | }
154 |
155 | /**
156 | * Runs the asynchronous web call and shows on the UI the Dialogs if required
157 | */
158 | @Override
159 | public void run() {
160 | // Shows a waiting dialog
161 | handler.post(new Runnable() {
162 | public void run() {
163 | if (force) {
164 | OrientationUtils.lockOrientation(activity);
165 | progress_dialog = ProgressDialog.show(activity,
166 | context.getResources().getText(R.string.please_wait),
167 | context.getResources().getText(R.string.update_test),
168 | true,
169 | false);
170 | }
171 | }
172 | });
173 | // Extract from the Internet if an update is needed or not
174 | update_available = update_available();
175 | // Manages the Dialog UI
176 | handler.post(new Runnable() {
177 | public void run() {
178 | if (progress_dialog != null) {
179 | progress_dialog.dismiss();
180 | }
181 |
182 | if (update_available) {
183 | OrientationUtils.lockOrientation(activity);
184 | show_dialog_you_are_not_updated();
185 | } else {
186 | if (force) {
187 | show_dialog_you_are_updated();
188 | }
189 | }
190 | }
191 | });
192 | }
193 |
194 | /**
195 | * Check if you are updated
196 | *
197 | * @return true if an update is needed false otherwise
198 | */
199 | private boolean update_available() {
200 | // I take the time in millis when you've checked the update for the last time
201 | long lastUpdateTime = getLastTimeTriedUpdate(activity);
202 | // If force = true skip this check, otherwise check if it has already checked within a {link #TIME_RETRY_TO_UPDATE}
203 | if (!force && (lastUpdateTime + TIME_RETRY_TO_UPDATE) > System.currentTimeMillis()) {
204 | return false;
205 | }
206 | // Sets new instant of time in which it has checked the update
207 | setLastTimeTriedUpdate(activity);
208 | // Check if there is really an update on the Google Play Store
209 | return web_update();
210 | }
211 |
212 | /**
213 | * Check if the Google Play version of the app match or less the current version installed
214 | *
215 | * @return true if an update is required, false otherwise
216 | */
217 | private boolean web_update() {
218 | try {
219 | String new_version = Jsoup.connect("https://play.google.com/store/apps/details?id=" + package_name + "&hl=en")
220 | .timeout(30000)
221 | .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6")
222 | .referrer("http://www.google.com")
223 | .get()
224 | .select(".W4P4ne div.hAyfc span.htlgb span.htlgb")
225 | .get(3)
226 | .ownText();
227 | return newer_version_available(current_version, new_version);
228 | } catch (Exception e) {
229 | return false;
230 | }
231 | }
232 |
233 | /**
234 | * Builds and shows the Dialog in case it is not updated
235 | */
236 | private void show_dialog_you_are_not_updated() {
237 | AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);
238 |
239 | alertDialogBuilder.setTitle(context.getString(R.string.you_are_not_updated_title));
240 | alertDialogBuilder.setMessage(context.getString(R.string.you_are_not_updated_message));
241 | alertDialogBuilder.setIcon(getCloudDrawable());
242 | alertDialogBuilder.setCancelable(false);
243 | alertDialogBuilder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
244 | public void onClick(DialogInterface dialog, int id) {
245 | dialog.cancel();
246 | OrientationUtils.unlockOrientation(activity);
247 | }
248 | });
249 | alertDialogBuilder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
250 | public void onClick(DialogInterface dialog, int id) {
251 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + package_name)));
252 | dialog.cancel();
253 | OrientationUtils.unlockOrientation(activity);
254 | }
255 | });
256 | alertDialogBuilder.show();
257 | }
258 |
259 | /**
260 | * Builds and shows the Dialog in case it is updated
261 | */
262 | private void show_dialog_you_are_updated() {
263 | AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);
264 |
265 | alertDialogBuilder.setTitle(context.getString(R.string.you_are_updated_title));
266 | alertDialogBuilder.setMessage(context.getString(R.string.you_are_updated_message));
267 | alertDialogBuilder.setIcon(getCloudDrawable());
268 | alertDialogBuilder.setCancelable(false);
269 | alertDialogBuilder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
270 | public void onClick(DialogInterface dialog, int id) {
271 | dialog.cancel();
272 | OrientationUtils.unlockOrientation(activity);
273 | }
274 | });
275 | alertDialogBuilder.show();
276 | }
277 |
278 | private int getCloudDrawable(){
279 | return light_theme ? R.drawable.ic_action_collections_cloud_light : R.drawable.ic_action_collections_cloud_dark;
280 | }
281 |
282 | /**
283 | * Used for comparing different versions of software
284 | * @param local_version_string the version name of the app installed on the system
285 | * @param online_version_string the version name of the app released on the Google Play
286 | * @return true if a the online_version_string is greater than the local_version_string
287 | */
288 | private static boolean newer_version_available(String local_version_string, String online_version_string){
289 | DefaultArtifactVersion local_version_mvn = new DefaultArtifactVersion(local_version_string);
290 | DefaultArtifactVersion online_version_mvn = new DefaultArtifactVersion(online_version_string);
291 | return local_version_mvn.compareTo(online_version_mvn) == -1 && !local_version_string.equals(new String());
292 | }
293 |
294 | /**
295 | * @param context
296 | * @return the value of preference which represents the last time you verify if an update exists
297 | */
298 | private static long getLastTimeTriedUpdate(Context context) {
299 | return PreferenceManager.getDefaultSharedPreferences(context).getLong(getLastUpdateTestKey(context), 0);
300 | }
301 |
302 | /**
303 | * Sets the value of preference which represents the last time you verify if an update exists = the currentTimeMillis in which that function is called
304 | *
305 | * @param context
306 | */
307 | private static void setLastTimeTriedUpdate(Context context) {
308 | PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(getLastUpdateTestKey(context), System.currentTimeMillis()).commit();
309 | }
310 |
311 | /**
312 | * @param context
313 | * @return the key String of the Last Update Preference
314 | */
315 | private static String getLastUpdateTestKey(Context context){
316 | return context.getString(R.string.last_update_test_preferences) + "_" + context.getPackageName();
317 | }
318 |
319 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/madx/updatechecker/lib/utils/orientation/OrientationUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Daniele Maddaluno
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.madx.updatechecker.lib.utils.orientation;
18 |
19 | import android.app.Activity;
20 | import android.content.Context;
21 | import android.content.pm.ActivityInfo;
22 | import android.content.pm.PackageManager;
23 | import android.content.res.Configuration;
24 | import android.os.Build;
25 | import android.view.Surface;
26 | import android.view.WindowManager;
27 |
28 | /** Static methods related to device orientation. */
29 | public class OrientationUtils {
30 | // See constant value of orientations on http://developer.android.com/reference/android/R.attr.html#screenOrientation
31 | private OrientationUtils() {}
32 |
33 | /** Locks the device window in landscape mode. */
34 | public static void lockOrientationLandscape(Activity activity) {
35 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
36 | }
37 |
38 | /** Locks the device window in portrait mode. */
39 | public static void lockOrientationPortrait(Activity activity) {
40 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
41 | }
42 |
43 | /** Locks the device window in actual screen mode. */
44 | public static void lockOrientation(Activity activity) {
45 | final int orientation = activity.getResources().getConfiguration().orientation;
46 | final int rotation = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
47 |
48 | // Copied from Android docs, since we don't have these values in Froyo 2.2
49 | int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
50 | int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;
51 |
52 | // Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO
53 | if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD)) {
54 | SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
55 | SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
56 | }
57 |
58 | if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90){
59 | if (orientation == Configuration.ORIENTATION_PORTRAIT){
60 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
61 | }
62 | else if (orientation == Configuration.ORIENTATION_LANDSCAPE){
63 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
64 | }
65 | }
66 | else if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270)
67 | {
68 | if (orientation == Configuration.ORIENTATION_PORTRAIT){
69 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
70 | }
71 | else if (orientation == Configuration.ORIENTATION_LANDSCAPE){
72 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
73 | }
74 | }
75 | }
76 |
77 | /** Unlocks the device window in user defined screen mode. */
78 | public static void unlockOrientation(Activity activity) {
79 | activity.setRequestedOrientation(getManifestOrientation(activity));
80 | }
81 |
82 | private static int getManifestOrientation(Activity activity){
83 | try {
84 | ActivityInfo app = activity.getPackageManager().getActivityInfo(activity.getComponentName(), PackageManager.GET_ACTIVITIES|PackageManager.GET_META_DATA);
85 | return app.screenOrientation;
86 | } catch (PackageManager.NameNotFoundException e) {
87 | return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
88 | }
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/library/src/main/java/com/madx/updatechecker/lib/utils/versioning/ArtifactVersion.java:
--------------------------------------------------------------------------------
1 | package com.madx.updatechecker.lib.utils.versioning;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | /**
23 | * Describes an artifact version in terms of its components, converts it to/from a string and
24 | * compares two versions.
25 | *
26 | * @author Brett Porter
27 | */
28 | interface ArtifactVersion extends Comparable {
29 | int getMajorVersion();
30 |
31 | int getMinorVersion();
32 |
33 | int getIncrementalVersion();
34 |
35 | int getBuildNumber();
36 |
37 | String getQualifier();
38 |
39 | void parseVersion(String version);
40 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/madx/updatechecker/lib/utils/versioning/ComparableVersion.java:
--------------------------------------------------------------------------------
1 | package com.madx.updatechecker.lib.utils.versioning;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | */
20 |
21 | import java.math.BigInteger;
22 | import java.util.ArrayList;
23 | import java.util.Arrays;
24 | import java.util.Iterator;
25 | import java.util.List;
26 | import java.util.ListIterator;
27 | import java.util.Locale;
28 | import java.util.Properties;
29 | import java.util.Stack;
30 |
31 | /**
32 | * Generic implementation of version comparison.
33 | *
34 | *
Features:
35 | *
36 | *
mixing of '-' (dash) and '.' (dot) separators,
37 | *
transition between characters and digits also constitutes a separator:
38 | * 1.0alpha1 => [1, 0, alpha, 1]
39 | *
unlimited number of version components,
40 | *
version components in the text can be digits or strings,
41 | *
strings are checked for well-known qualifiers and the qualifier ordering is used for version ordering.
42 | * Well-known qualifiers (case insensitive) are:
43 | *
alpha or a
44 | *
beta or b
45 | *
milestone or m
46 | *
rc or cr
47 | *
snapshot
48 | *
(the empty string) or ga or final
49 | *
sp
50 | *
51 | * Unknown qualifiers are considered after known qualifiers, with lexical order (always case insensitive),
52 | *
53 | *
a dash usually precedes a qualifier, and is always less important than something preceded with a dot.
54 | *
55 | *
56 | * @author Kenney Westerhof
57 | * @author Hervé Boutemy
58 | * @see "Versioning" on Maven Wiki
59 | */
60 | class ComparableVersion implements Comparable {
61 | private String value;
62 |
63 | private String canonical;
64 |
65 | private ListItem items;
66 |
67 | private interface Item {
68 | int INTEGER_ITEM = 0;
69 | int STRING_ITEM = 1;
70 | int LIST_ITEM = 2;
71 |
72 | int compareTo(Item item);
73 |
74 | int getType();
75 |
76 | boolean isNull();
77 | }
78 |
79 | /**
80 | * Represents a numeric item in the version item list.
81 | */
82 | private static class IntegerItem implements Item {
83 | private static final BigInteger BIG_INTEGER_ZERO = new BigInteger("0");
84 |
85 | private final BigInteger value;
86 |
87 | public static final IntegerItem ZERO = new IntegerItem();
88 |
89 | private IntegerItem() {
90 | this.value = BIG_INTEGER_ZERO;
91 | }
92 |
93 | public IntegerItem(String str) {
94 | this.value = new BigInteger(str);
95 | }
96 |
97 | public int getType() {
98 | return INTEGER_ITEM;
99 | }
100 |
101 | public boolean isNull() {
102 | return BIG_INTEGER_ZERO.equals(value);
103 | }
104 |
105 | public int compareTo(Item item) {
106 | if (item == null) {
107 | return BIG_INTEGER_ZERO.equals(value) ? 0 : 1; // 1.0 == 1, 1.1 > 1
108 | }
109 |
110 | switch (item.getType()) {
111 | case INTEGER_ITEM:
112 | return value.compareTo(((IntegerItem) item).value);
113 |
114 | case STRING_ITEM:
115 | return 1; // 1.1 > 1-sp
116 |
117 | case LIST_ITEM:
118 | return 1; // 1.1 > 1-1
119 |
120 | default:
121 | throw new RuntimeException("invalid item: " + item.getClass());
122 | }
123 | }
124 |
125 | public String toString() {
126 | return value.toString();
127 | }
128 | }
129 |
130 | /**
131 | * Represents a string in the version item list, usually a qualifier.
132 | */
133 | private static class StringItem implements Item {
134 | private static final String[] QUALIFIERS = {"alpha", "beta", "milestone", "rc", "snapshot", "", "sp"};
135 |
136 | @SuppressWarnings("checkstyle:constantname")
137 | private static final List _QUALIFIERS = Arrays.asList(QUALIFIERS);
138 |
139 | private static final Properties ALIASES = new Properties();
140 |
141 | static {
142 | ALIASES.put("ga", "");
143 | ALIASES.put("final", "");
144 | ALIASES.put("cr", "rc");
145 | }
146 |
147 | /**
148 | * A comparable value for the empty-string qualifier. This one is used to determine if a given qualifier makes
149 | * the version older than one without a qualifier, or more recent.
150 | */
151 | private static final String RELEASE_VERSION_INDEX = String.valueOf(_QUALIFIERS.indexOf(""));
152 |
153 | private String value;
154 |
155 | public StringItem(String value, boolean followedByDigit) {
156 | if (followedByDigit && value.length() == 1) {
157 | // a1 = alpha-1, b1 = beta-1, m1 = milestone-1
158 | switch (value.charAt(0)) {
159 | case 'a':
160 | value = "alpha";
161 | break;
162 | case 'b':
163 | value = "beta";
164 | break;
165 | case 'm':
166 | value = "milestone";
167 | break;
168 | default:
169 | }
170 | }
171 | this.value = ALIASES.getProperty(value, value);
172 | }
173 |
174 | public int getType() {
175 | return STRING_ITEM;
176 | }
177 |
178 | public boolean isNull() {
179 | return (comparableQualifier(value).compareTo(RELEASE_VERSION_INDEX) == 0);
180 | }
181 |
182 | /**
183 | * Returns a comparable value for a qualifier.
184 | *
185 | * This method takes into account the ordering of known qualifiers then unknown qualifiers with lexical
186 | * ordering.
187 | *
188 | * just returning an Integer with the index here is faster, but requires a lot of if/then/else to check for -1
189 | * or QUALIFIERS.size and then resort to lexical ordering. Most comparisons are decided by the first character,
190 | * so this is still fast. If more characters are needed then it requires a lexical sort anyway.
191 | *
192 | * @param qualifier
193 | * @return an equivalent value that can be used with lexical comparison
194 | */
195 | public static String comparableQualifier(String qualifier) {
196 | int i = _QUALIFIERS.indexOf(qualifier);
197 |
198 | return i == -1 ? (_QUALIFIERS.size() + "-" + qualifier) : String.valueOf(i);
199 | }
200 |
201 | public int compareTo(Item item) {
202 | if (item == null) {
203 | // 1-rc < 1, 1-ga > 1
204 | return comparableQualifier(value).compareTo(RELEASE_VERSION_INDEX);
205 | }
206 | switch (item.getType()) {
207 | case INTEGER_ITEM:
208 | return -1; // 1.any < 1.1 ?
209 |
210 | case STRING_ITEM:
211 | return comparableQualifier(value).compareTo(comparableQualifier(((StringItem) item).value));
212 |
213 | case LIST_ITEM:
214 | return -1; // 1.any < 1-1
215 |
216 | default:
217 | throw new RuntimeException("invalid item: " + item.getClass());
218 | }
219 | }
220 |
221 | public String toString() {
222 | return value;
223 | }
224 | }
225 |
226 | /**
227 | * Represents a version list item. This class is used both for the global item list and for sub-lists (which start
228 | * with '-(number)' in the version specification).
229 | */
230 | private static class ListItem extends ArrayList implements Item {
231 | public int getType() {
232 | return LIST_ITEM;
233 | }
234 |
235 | public boolean isNull() {
236 | return (size() == 0);
237 | }
238 |
239 | void normalize() {
240 | for (ListIterator iterator = listIterator(size()); iterator.hasPrevious(); ) {
241 | Item item = iterator.previous();
242 | if (item.isNull()) {
243 | iterator.remove(); // remove null trailing items: 0, "", empty list
244 | } else {
245 | break;
246 | }
247 | }
248 | }
249 |
250 | public int compareTo(Item item) {
251 | if (item == null) {
252 | if (size() == 0) {
253 | return 0; // 1-0 = 1- (normalize) = 1
254 | }
255 | Item first = get(0);
256 | return first.compareTo(null);
257 | }
258 | switch (item.getType()) {
259 | case INTEGER_ITEM:
260 | return -1; // 1-1 < 1.0.x
261 |
262 | case STRING_ITEM:
263 | return 1; // 1-1 > 1-sp
264 |
265 | case LIST_ITEM:
266 | Iterator left = iterator();
267 | Iterator right = ((ListItem) item).iterator();
268 |
269 | while (left.hasNext() || right.hasNext()) {
270 | Item l = left.hasNext() ? left.next() : null;
271 | Item r = right.hasNext() ? right.next() : null;
272 |
273 | // if this is shorter, then invert the compare and mul with -1
274 | int result = l == null ? (r == null ? 0 : -1 * r.compareTo(l)) : l.compareTo(r);
275 |
276 | if (result != 0) {
277 | return result;
278 | }
279 | }
280 |
281 | return 0;
282 |
283 | default:
284 | throw new RuntimeException("invalid item: " + item.getClass());
285 | }
286 | }
287 |
288 | public String toString() {
289 | StringBuilder buffer = new StringBuilder("(");
290 | for (Iterator iter = iterator(); iter.hasNext(); ) {
291 | buffer.append(iter.next());
292 | if (iter.hasNext()) {
293 | buffer.append(',');
294 | }
295 | }
296 | buffer.append(')');
297 | return buffer.toString();
298 | }
299 | }
300 |
301 | public ComparableVersion(String version) {
302 | parseVersion(version);
303 | }
304 |
305 | public final void parseVersion(String version) {
306 | this.value = version;
307 |
308 | items = new ListItem();
309 |
310 | version = version.toLowerCase(Locale.ENGLISH);
311 |
312 | ListItem list = items;
313 |
314 | Stack stack = new Stack();
315 | stack.push(list);
316 |
317 | boolean isDigit = false;
318 |
319 | int startIndex = 0;
320 |
321 | for (int i = 0; i < version.length(); i++) {
322 | char c = version.charAt(i);
323 |
324 | if (c == '.') {
325 | if (i == startIndex) {
326 | list.add(IntegerItem.ZERO);
327 | } else {
328 | list.add(parseItem(isDigit, version.substring(startIndex, i)));
329 | }
330 | startIndex = i + 1;
331 | } else if (c == '-') {
332 | if (i == startIndex) {
333 | list.add(IntegerItem.ZERO);
334 | } else {
335 | list.add(parseItem(isDigit, version.substring(startIndex, i)));
336 | }
337 | startIndex = i + 1;
338 |
339 | if (isDigit) {
340 | list.normalize(); // 1.0-* = 1-*
341 |
342 | if ((i + 1 < version.length()) && Character.isDigit(version.charAt(i + 1))) {
343 | // new ListItem only if previous were digits and new char is a digit,
344 | // ie need to differentiate only 1.1 from 1-1
345 | list.add(list = new ListItem());
346 |
347 | stack.push(list);
348 | }
349 | }
350 | } else if (Character.isDigit(c)) {
351 | if (!isDigit && i > startIndex) {
352 | list.add(new StringItem(version.substring(startIndex, i), true));
353 | startIndex = i;
354 | }
355 |
356 | isDigit = true;
357 | } else {
358 | if (isDigit && i > startIndex) {
359 | list.add(parseItem(true, version.substring(startIndex, i)));
360 | startIndex = i;
361 | }
362 |
363 | isDigit = false;
364 | }
365 | }
366 |
367 | if (version.length() > startIndex) {
368 | list.add(parseItem(isDigit, version.substring(startIndex)));
369 | }
370 |
371 | while (!stack.isEmpty()) {
372 | list = (ListItem) stack.pop();
373 | list.normalize();
374 | }
375 |
376 | canonical = items.toString();
377 | }
378 |
379 | private static Item parseItem(boolean isDigit, String buf) {
380 | return isDigit ? new IntegerItem(buf) : new StringItem(buf, false);
381 | }
382 |
383 | public int compareTo(ComparableVersion o) {
384 | return items.compareTo(o.items);
385 | }
386 |
387 | public String toString() {
388 | return value;
389 | }
390 |
391 | public boolean equals(Object o) {
392 | return (o instanceof ComparableVersion) && canonical.equals(((ComparableVersion) o).canonical);
393 | }
394 |
395 | public int hashCode() {
396 | return canonical.hashCode();
397 | }
398 | }
399 |
--------------------------------------------------------------------------------
/library/src/main/java/com/madx/updatechecker/lib/utils/versioning/DefaultArtifactVersion.java:
--------------------------------------------------------------------------------
1 | package com.madx.updatechecker.lib.utils.versioning;
2 |
3 | import java.util.NoSuchElementException;
4 |
5 | /*
6 | * Licensed to the Apache Software Foundation (ASF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | import java.util.StringTokenizer;
25 | import java.util.regex.Pattern;
26 |
27 | /**
28 | * Default implementation of artifact versioning.
29 | *
30 | * @author Brett Porter
31 | */
32 | public class DefaultArtifactVersion implements ArtifactVersion {
33 | private Integer majorVersion;
34 |
35 | private Integer minorVersion;
36 |
37 | private Integer incrementalVersion;
38 |
39 | private Integer buildNumber;
40 |
41 | private String qualifier;
42 |
43 | private ComparableVersion comparable;
44 |
45 | public DefaultArtifactVersion(String version) {
46 | parseVersion(version);
47 | }
48 |
49 | @Override
50 | public int hashCode() {
51 | return 11 + comparable.hashCode();
52 | }
53 |
54 | @Override
55 | public boolean equals(Object other) {
56 | if (this == other) {
57 | return true;
58 | }
59 |
60 | if (!(other instanceof ArtifactVersion)) {
61 | return false;
62 | }
63 |
64 | return compareTo((ArtifactVersion) other) == 0;
65 | }
66 |
67 | public int compareTo(ArtifactVersion otherVersion) {
68 | if (otherVersion instanceof DefaultArtifactVersion) {
69 | return this.comparable.compareTo(((DefaultArtifactVersion) otherVersion).comparable);
70 | } else {
71 | return compareTo(new DefaultArtifactVersion(otherVersion.toString()));
72 | }
73 | }
74 |
75 | public int getMajorVersion() {
76 | return majorVersion != null ? majorVersion : 0;
77 | }
78 |
79 | public int getMinorVersion() {
80 | return minorVersion != null ? minorVersion : 0;
81 | }
82 |
83 | public int getIncrementalVersion() {
84 | return incrementalVersion != null ? incrementalVersion : 0;
85 | }
86 |
87 | public int getBuildNumber() {
88 | return buildNumber != null ? buildNumber : 0;
89 | }
90 |
91 | public String getQualifier() {
92 | return qualifier;
93 | }
94 |
95 | public final void parseVersion(String version) {
96 | comparable = new ComparableVersion(version);
97 |
98 | int index = version.indexOf("-");
99 |
100 | String part1;
101 | String part2 = null;
102 |
103 | if (index < 0) {
104 | part1 = version;
105 | } else {
106 | part1 = version.substring(0, index);
107 | part2 = version.substring(index + 1);
108 | }
109 |
110 | if (part2 != null) {
111 | try {
112 | if ((part2.length() == 1) || !part2.startsWith("0")) {
113 | buildNumber = Integer.valueOf(part2);
114 | } else {
115 | qualifier = part2;
116 | }
117 | } catch (NumberFormatException e) {
118 | qualifier = part2;
119 | }
120 | }
121 |
122 | if ((!part1.contains(".")) && !part1.startsWith("0")) {
123 | try {
124 | majorVersion = Integer.valueOf(part1);
125 | } catch (NumberFormatException e) {
126 | // qualifier is the whole version, including "-"
127 | qualifier = version;
128 | buildNumber = null;
129 | }
130 | } else {
131 | boolean fallback = false;
132 |
133 | StringTokenizer tok = new StringTokenizer(part1, ".");
134 | try {
135 | majorVersion = getNextIntegerToken(tok);
136 | if (tok.hasMoreTokens()) {
137 | minorVersion = getNextIntegerToken(tok);
138 | }
139 | if (tok.hasMoreTokens()) {
140 | incrementalVersion = getNextIntegerToken(tok);
141 | }
142 | if (tok.hasMoreTokens()) {
143 | qualifier = tok.nextToken();
144 | fallback = Pattern.compile("\\d+").matcher(qualifier).matches();
145 | }
146 |
147 | // string tokenzier won't detect these and ignores them
148 | if (part1.contains("..") || part1.startsWith(".") || part1.endsWith(".")) {
149 | fallback = true;
150 | }
151 | } catch (NumberFormatException e) {
152 | fallback = true;
153 | }
154 |
155 | if (fallback) {
156 | // qualifier is the whole version, including "-"
157 | qualifier = version;
158 | majorVersion = null;
159 | minorVersion = null;
160 | incrementalVersion = null;
161 | buildNumber = null;
162 | }
163 | }
164 | }
165 |
166 | private static Integer getNextIntegerToken(StringTokenizer tok) {
167 | try {
168 | String s = tok.nextToken();
169 | if ((s.length() > 1) && s.startsWith("0")) {
170 | throw new NumberFormatException("Number part has a leading 0: '" + s + "'");
171 | }
172 | return Integer.valueOf(s);
173 | } catch (NoSuchElementException e) {
174 | throw new NumberFormatException("Number is invalid");
175 | }
176 | }
177 |
178 | @Override
179 | public String toString() {
180 | return comparable.toString();
181 | }
182 | }
--------------------------------------------------------------------------------
/library/src/main/res/drawable-hdpi/ic_action_collections_cloud_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/library/src/main/res/drawable-hdpi/ic_action_collections_cloud_dark.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-hdpi/ic_action_collections_cloud_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/library/src/main/res/drawable-hdpi/ic_action_collections_cloud_light.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-mdpi/ic_action_collections_cloud_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/library/src/main/res/drawable-mdpi/ic_action_collections_cloud_dark.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-mdpi/ic_action_collections_cloud_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/library/src/main/res/drawable-mdpi/ic_action_collections_cloud_light.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xhdpi/ic_action_collections_cloud_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/library/src/main/res/drawable-xhdpi/ic_action_collections_cloud_dark.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xhdpi/ic_action_collections_cloud_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/library/src/main/res/drawable-xhdpi/ic_action_collections_cloud_light.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxhdpi/ic_action_collections_cloud_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/library/src/main/res/drawable-xxhdpi/ic_action_collections_cloud_dark.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxhdpi/ic_action_collections_cloud_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielemaddaluno/Android-Update-Checker/1d4e4f51855b3871a881431a44a4e272175e82f6/library/src/main/res/drawable-xxhdpi/ic_action_collections_cloud_light.png
--------------------------------------------------------------------------------
/library/src/main/res/values-al/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | PO
22 | JO
23 |
24 | Ju lutem prisni
25 | Duke ngarkuar…
26 | Duke kontrolluar për azhurnime…
27 |
28 | App tashmë është azhurnuar
29 | App nuk është azhurnuar
30 | App juaj është tashmë azhurnuar në versionin e fundit i disponueshëm.\nShtypni OK për të dalur.
31 | Shtypni PO për të azhurnuar app në Google Play, shtypni JO për të dalur.
32 |
--------------------------------------------------------------------------------
/library/src/main/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | JA
22 | NEIN
23 |
24 | Warten Sie bitte
25 | Laden…
26 | Aktualisierungen suchen…
27 |
28 | Ihre App ist bereits aktualisiert
29 | Ihre App ist nicht aktualisiert
30 | Ihre App ist bereits auf die neueste verfügbare Version aktualisiert.\nDrücken Sie OK zum beenden.
31 | Drücken Sie auf JA um die App über Google Play zu aktualisieren, drücken Sie NEIN zum beenden.
32 |
--------------------------------------------------------------------------------
/library/src/main/res/values-en/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | YES
22 | NO
23 |
24 | Please Wait
25 | Loading…
26 | Checking for updates…
27 |
28 | The app is already updated
29 | The app is not updated
30 | Your app is already updated to the latest version available.\nPress OK to exit.
31 | Press YES to update the app on Google Play, press NO to exit.
32 |
--------------------------------------------------------------------------------
/library/src/main/res/values-es/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | SI
22 | NO
23 |
24 | Espera por favor
25 | Cargando…
26 | Comprobación de actualizaciones…
27 |
28 | La app ya está actualizada
29 | La app no está actualizada
30 | La app ya está actualizada a la última versión disponible.\nPulse OK para salir.
31 | Presione SI para actualizar la aplicación en Google Play, pulse NO para salir.
32 |
--------------------------------------------------------------------------------
/library/src/main/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | OUI
22 | NON
23 |
24 | Attendez, s\'il vous plaît
25 | Chargement en cours…
26 | Vérification des mises à jour…
27 |
28 | L\'application est déjà à jour
29 | L\'application n\'est pas mise à jour
30 | Votre application est déjà mise à jour à la dernière version disponible.\nAppuyez sur OK pour quitter.
31 | Appuyez sur OUI pour mettre à jour l\'application sur Google Play, appuyez sur NON pour quitter.
32 |
--------------------------------------------------------------------------------
/library/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | SI
22 | NO
23 |
24 | Attendere prego
25 | Sto caricando…
26 | Verifico aggiornamenti…
27 |
28 | La tua app è già aggiornata
29 | La tua app non è aggiornata
30 | La tua app risulta essere già aggiornata alla ultima versione disponibile.\nPremi OK per uscire.
31 | Premi SI per aggiornare la applicazione su Google Play, premi NO per uscire.
32 |
--------------------------------------------------------------------------------
/library/src/main/res/values-ro/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | DA
22 | NO
23 |
24 | Vă rugăm să așteptați
25 | Se încarcă…
26 | Verificare pentru actualizări…
27 |
28 | Aplicatia este deja actualizată
29 | Aplicația nu este actualizată
30 | Cererea dumneavoastră este deja actualizată la cea mai recentă versiune disponibilă.\nApăsați OK pentru a ieși.
31 | Apăsați DA pentru a actualiza aplicația pe Google Play, apăsați pe NO pentru a ieși.
32 |
--------------------------------------------------------------------------------
/library/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | ДА
22 | НЕТ
23 |
24 | Пожалуйста, подождите
25 | Загрузка…
26 | Проверка обновлений…
27 |
28 | Приложение уже обновлено
29 | Доступна новая версия приложения
30 | Ваше приложение уже обновлено до последней версии.\nНажмите OK, чтобы выйти.
31 | Нажмите ДА, чтобы обновить приложение на Google Play, нажмите НЕТ для выхода.
32 |
33 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Last_Update_Check
19 |
20 | OK
21 | YES
22 | NO
23 |
24 | Please Wait
25 | Loading…
26 | Checking for updates…
27 |
28 | The app is already updated
29 | The app is not updated
30 | Your app is already updated to the latest version available.\nPress OK to exit.
31 | Press YES to update the app on Google Play, press NO to exit.
32 |
33 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library'
2 |
--------------------------------------------------------------------------------