diff --git a/.gitignore b/.gitignore
index c9c2248a..536999a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,9 @@ proguard/
# Android Studio captures folder
captures/
+
+# Directory-based project format
+.idea/
+
+# IntelliJ
+*.iml
diff --git a/README.md b/README.md
index a0073510..952669ec 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,76 @@
-# AppUpdater
-Library that checks for new app updates using Google Play, GitHub and Amazon. API 8+ required.
+
AppUpdater
+Android Library
+
+
+
+
+
+
+
+Android Library that checks for new app updates using Google Play, GitHub and Amazon.
+
+## How to include
+Add the repository to your project **build.gradle**:
+```Java
+repositories {
+ maven {
+ url "https://jitpack.io"
+ }
+}
+```
+
+And add the library to your module **build.gradle**:
+```Java
+dependencies {
+ compile 'com.github.javiersantos:AppUpdater:1.0'
+}
+```
+
+## Usage
+Add **INTERNET** and **ACCESS_NETWORK_STATE** permissions to your app's Manifest:
+```Java
+
+
+```
+
+### Activity
+```Java
+AppUpdater appUpdater = new AppUpdater(this);
+appUpdater.init();
+```
+
+## Customization
+
+### Display dialog only once
+Use the builder and add following:
+```Java
+// (Optional) Provide a Display mode (DIALOG, SNACKBAR, NOTIFICATION)
+.setDisplay(Display.DIALOG)
+// (Optional) Provide a duration for the Snackbars (NORMAL, INDEFINITE)
+.setDuration(Duration.NORMAL)
+// (Optional) Provide a source for the updates (GOOGLE_PLAY, GITHUB, AMAZON)
+.setUpdateFrom(UpdateFrom.GOOGLE_PLAY)
+// (Required for GITHUB, optional otherwise) Provide the GitHub user and repo where releases are available
+.setGitHubUserAndRepo("javiersantos", "AppUpdater")
+// (Optional) Updates will be displayed only every X times the app ascertains that a new update is availabl
+.showEvery(5)
+// (Optional) Show dialog, snackbar or notification although there aren't updates
+.showAppUpdated(false);
+```
+
+![ML Manager](https://raw.githubusercontent.com/javiersantos/AppUpdater/master/Screenshots/banner.png)
+
+## License
+ Copyright 2016 Javier Santos
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/Screenshots/banner.png b/Screenshots/banner.png
new file mode 100755
index 00000000..9df5c15b
Binary files /dev/null and b/Screenshots/banner.png differ
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 00000000..67e5bd98
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.2"
+
+ defaultConfig {
+ applicationId "com.github.javiersantos.appupdater.demo"
+ minSdkVersion 11
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+
+ applicationVariants.all { variant ->
+ variant.outputs.each { output ->
+ output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace("app-release.apk", applicationId + "_" + versionName + "_" + versionCode + ".apk"))
+ }
+ }
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:23.1.1'
+ compile 'com.android.support:design:23.1.1'
+ compile 'com.android.support:cardview-v7:23.1.1'
+ compile 'com.mikepenz:iconics-core:2.5.5@aar'
+ compile 'com.mikepenz:material-design-iconic-typeface:2.2.0.1@aar'
+ compile project(':library')
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 00000000..dee88bfe
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/javiersantos/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/app/src/androidTest/java/com/github/javiersantos/demo/ApplicationTest.java b/app/src/androidTest/java/com/github/javiersantos/demo/ApplicationTest.java
new file mode 100644
index 00000000..9592fa08
--- /dev/null
+++ b/app/src/androidTest/java/com/github/javiersantos/demo/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.github.javiersantos.demo;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..39d57ec0
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/github/javiersantos/demo/MainActivity.java b/app/src/main/java/com/github/javiersantos/demo/MainActivity.java
new file mode 100644
index 00000000..08b6617f
--- /dev/null
+++ b/app/src/main/java/com/github/javiersantos/demo/MainActivity.java
@@ -0,0 +1,88 @@
+package com.github.javiersantos.demo;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.CardView;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+
+import com.github.javiersantos.appupdater.AppUpdater;
+import com.github.javiersantos.appupdater.demo.R;
+import com.github.javiersantos.appupdater.enums.Display;
+import com.github.javiersantos.appupdater.enums.UpdateFrom;
+import com.mikepenz.iconics.IconicsDrawable;
+import com.mikepenz.material_design_iconic_typeface_library.MaterialDesignIconic;
+
+public class MainActivity extends AppCompatActivity {
+ private Context context;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ this.context = this;
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ CardView dialog = (CardView) findViewById(R.id.dialog);
+ CardView snackbar = (CardView) findViewById(R.id.snackbar);
+ CardView notification = (CardView) findViewById(R.id.notification);
+
+ fab.setImageDrawable(new IconicsDrawable(this).icon(MaterialDesignIconic.Icon.gmi_github).color(Color.WHITE).sizeDp(24));
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/javiersantos/AppUpdater")));
+ }
+ });
+
+ dialog.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ AppUpdater appUpdater = new AppUpdater(context);
+ appUpdater.setUpdateFrom(UpdateFrom.GOOGLE_PLAY);
+ // appUpdater.setUpdateFrom(UpdateFrom.AMAZON);
+ // appUpdater.setUpdateFrom(UpdateFrom.GITHUB);
+ // appUpdater.setGitHubUserAndRepo("javiersantos", "AppUpdater");
+ appUpdater.setDisplay(Display.DIALOG);
+ appUpdater.showAppUpdated(true);
+ appUpdater.init();
+ }
+ });
+
+ snackbar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ AppUpdater appUpdater = new AppUpdater(context);
+ appUpdater.setUpdateFrom(UpdateFrom.GOOGLE_PLAY);
+ // appUpdater.setUpdateFrom(UpdateFrom.AMAZON);
+ // appUpdater.setUpdateFrom(UpdateFrom.GITHUB);
+ // appUpdater.setGitHubUserAndRepo("javiersantos", "AppUpdater");
+ appUpdater.setDisplay(Display.SNACKBAR);
+ appUpdater.showAppUpdated(true);
+ appUpdater.init();
+ }
+ });
+
+ notification.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ AppUpdater appUpdater = new AppUpdater(context);
+ appUpdater.setUpdateFrom(UpdateFrom.GOOGLE_PLAY);
+ // appUpdater.setUpdateFrom(UpdateFrom.AMAZON);
+ // appUpdater.setUpdateFrom(UpdateFrom.GITHUB);
+ // appUpdater.setGitHubUserAndRepo("javiersantos", "AppUpdater");
+ appUpdater.setDisplay(Display.NOTIFICATION);
+ appUpdater.showAppUpdated(true);
+ appUpdater.init();
+ }
+ });
+ }
+}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..9567fe41
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
new file mode 100644
index 00000000..edf92310
--- /dev/null
+++ b/app/src/main/res/layout/content_main.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..cde69bcc
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..c133a0cb
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..bfa42f0e
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..324e72cd
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..aee44e13
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 00000000..251fb9fb
--- /dev/null
+++ b/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,9 @@
+>
+
+
+
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..63fc8164
--- /dev/null
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..3ab3e9cb
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..41ee0756
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,8 @@
+
+
+ 16dp
+ 16dp
+ 16dp
+ 240dp
+ 16dp
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..e59a7161
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+
+ AppUpdater Library (Demo)
+
+ A library that checks for new app updates using Google Play, GitHub and Amazon.
+ Show dialog
+ Show snackbar
+ Show notification
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 00000000..78ec711b
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/test/java/com/github/javiersantos/appupdater/ExampleUnitTest.java b/app/src/test/java/com/github/javiersantos/appupdater/ExampleUnitTest.java
new file mode 100644
index 00000000..0c3a06e2
--- /dev/null
+++ b/app/src/test/java/com/github/javiersantos/appupdater/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.github.javiersantos.appupdater;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 00000000..f83b67d5
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.5.0'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ maven { url "https://jitpack.io" }
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 00000000..1d3591c8
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..05ef575b
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..f23df6e4
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Oct 21 11:34:03 PDT 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 00000000..9d82f789
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 00000000..aec99730
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/library/.gitignore b/library/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/library/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/library/build.gradle b/library/build.gradle
new file mode 100644
index 00000000..2720fbc6
--- /dev/null
+++ b/library/build.gradle
@@ -0,0 +1,28 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.2"
+ useLibrary 'org.apache.http.legacy'
+
+ defaultConfig {
+ minSdkVersion 8
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:23.1.1'
+ compile 'com.android.support:design:23.1.1'
+ compile('com.github.afollestad.material-dialogs:core:0.8.5.3@aar') { transitive = true }
+}
diff --git a/library/proguard-rules.pro b/library/proguard-rules.pro
new file mode 100644
index 00000000..dee88bfe
--- /dev/null
+++ b/library/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/javiersantos/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/library/src/androidTest/java/com/github/javiersantos/appupdater/ApplicationTest.java b/library/src/androidTest/java/com/github/javiersantos/appupdater/ApplicationTest.java
new file mode 100644
index 00000000..0cd9d9d8
--- /dev/null
+++ b/library/src/androidTest/java/com/github/javiersantos/appupdater/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.github.javiersantos.appupdater;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..60f72a55
--- /dev/null
+++ b/library/src/main/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/AppUpdater.java b/library/src/main/java/com/github/javiersantos/appupdater/AppUpdater.java
new file mode 100644
index 00000000..2c611318
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/AppUpdater.java
@@ -0,0 +1,57 @@
+package com.github.javiersantos.appupdater;
+
+import android.content.Context;
+
+import com.github.javiersantos.appupdater.enums.Display;
+import com.github.javiersantos.appupdater.enums.Duration;
+import com.github.javiersantos.appupdater.enums.UpdateFrom;
+import com.github.javiersantos.appupdater.objects.GitHub;
+
+public class AppUpdater {
+ private Context context;
+ private Display display;
+ private UpdateFrom updateFrom;
+ private Duration duration;
+ private GitHub gitHub;
+ private Integer showEvery;
+ private Boolean showAppUpdated;
+
+ public AppUpdater(Context context) {
+ this.context = context;
+ this.display = Display.DIALOG;
+ this.updateFrom = UpdateFrom.GOOGLE_PLAY;
+ this.duration = Duration.NORMAL;
+ this.showEvery = 5;
+ this.showAppUpdated = false;
+ }
+
+ public void setDisplay(Display display) {
+ this.display = display;
+ }
+
+ public void setUpdateFrom(UpdateFrom updateFrom) {
+ this.updateFrom = updateFrom;
+ }
+
+ public void setDuration(Duration duration) {
+ this.duration = duration;
+ }
+
+ public void setGitHubUserAndRepo(String user, String repo) {
+ this.gitHub = new GitHub(user, repo);
+ }
+
+ public void showEvery(Integer times) {
+ this.showEvery = times;
+ }
+
+ public void showAppUpdated(Boolean res) {
+ this.showAppUpdated = res;
+ }
+
+ public void init() {
+ UtilsAsync.LatestAppVersion latestAppVersion = new UtilsAsync.LatestAppVersion(context, showEvery, showAppUpdated, updateFrom, display, duration, gitHub);
+ latestAppVersion.execute();
+ }
+
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/Config.java b/library/src/main/java/com/github/javiersantos/appupdater/Config.java
new file mode 100644
index 00000000..9c20c096
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/Config.java
@@ -0,0 +1,12 @@
+package com.github.javiersantos.appupdater;
+
+class Config {
+ static final String PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=";
+ static final String GITHUB_URL = "https://github.com/";
+ static final String AMAZON_URL = "http://www.amazon.com/gp/mas/dl/android?p=";
+
+ static final String PLAY_STORE_TAG_RELEASE = "itemprop=\"softwareVersion\"> ";
+ static final String GITHUB_TAG_RELEASE = "/tree/";
+ static final String AMAZON_TAG_RELEASE = "Version:";
+
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/LibraryPreferences.java b/library/src/main/java/com/github/javiersantos/appupdater/LibraryPreferences.java
new file mode 100644
index 00000000..5f541fe6
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/LibraryPreferences.java
@@ -0,0 +1,37 @@
+package com.github.javiersantos.appupdater;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+class LibraryPreferences {
+ private SharedPreferences sharedPreferences;
+ private SharedPreferences.Editor editor;
+
+ static final String KeyAppUpdaterShow = "prefAppUpdaterShow";
+ static final String KeySuccessfulChecks = "prefSuccessfulChecks";
+
+ public LibraryPreferences(Context context) {
+ this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+ this.editor = sharedPreferences.edit();
+ }
+
+ public Boolean getAppUpdaterShow() {
+ return sharedPreferences.getBoolean(KeyAppUpdaterShow, true);
+ }
+
+ public void setAppUpdaterShow(Boolean res) {
+ editor.putBoolean(KeyAppUpdaterShow, res);
+ editor.commit();
+ }
+
+ public Integer getSuccessfulChecks() {
+ return sharedPreferences.getInt(KeySuccessfulChecks, 0);
+ }
+
+ public void setSuccessfulChecks(Integer checks) {
+ editor.putInt(KeySuccessfulChecks, checks);
+ editor.commit();
+ }
+
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/UtilsAsync.java b/library/src/main/java/com/github/javiersantos/appupdater/UtilsAsync.java
new file mode 100644
index 00000000..eccbd6d9
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/UtilsAsync.java
@@ -0,0 +1,92 @@
+package com.github.javiersantos.appupdater;
+
+import android.content.Context;
+import android.os.AsyncTask;
+
+import com.github.javiersantos.appupdater.enums.Display;
+import com.github.javiersantos.appupdater.enums.Duration;
+import com.github.javiersantos.appupdater.enums.UpdateFrom;
+import com.github.javiersantos.appupdater.objects.GitHub;
+
+class UtilsAsync {
+
+ static class LatestAppVersion extends AsyncTask {
+ private Context context;
+ private LibraryPreferences libraryPreferences;
+ private Integer showEvery;
+ private Boolean showAppUpdated;
+ private UpdateFrom updateFrom;
+ private Display display;
+ private Duration duration;
+ private GitHub gitHub;
+
+ public LatestAppVersion(Context context, Integer showEvery, Boolean showAppUpdated, UpdateFrom updateFrom, Display display, Duration duration, GitHub gitHub) {
+ this.context = context;
+ this.libraryPreferences = new LibraryPreferences(context);
+ this.showEvery = showEvery;
+ this.showAppUpdated = showAppUpdated;
+ this.updateFrom = updateFrom;
+ this.display = display;
+ this.duration = duration;
+ this.gitHub = gitHub;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+
+ if (UtilsLibrary.isNetworkAvailable(context) && libraryPreferences.getAppUpdaterShow()) {
+ switch (updateFrom) {
+ case GITHUB:
+ if (gitHub == null) {
+ throw new NullPointerException("GitHub user and repo are not set!!");
+ }
+ break;
+ }
+ } else {
+ cancel(true);
+ }
+ }
+
+ @Override
+ protected String doInBackground(Void... voids) {
+ return UtilsLibrary.getLatestAppVersion(context, updateFrom, gitHub);
+ }
+
+ @Override
+ protected void onPostExecute(String version) {
+ super.onPostExecute(version);
+
+ if (UtilsLibrary.isUpdateAvailable(UtilsLibrary.getAppInstalledVersion(context), version)) {
+ Integer successfulChecks = libraryPreferences.getSuccessfulChecks();
+ libraryPreferences.setSuccessfulChecks(successfulChecks++);
+ if (UtilsLibrary.isAbleToShow(context, showEvery)) {
+ switch (display) {
+ case DIALOG:
+ UtilsDisplay.showUpdateAvailableDialog(context, context.getResources().getString(R.string.appupdater_update_available), String.format(context.getResources().getString(R.string.appupdater_update_available_description_dialog), version, UtilsLibrary.getAppName(context)), updateFrom, gitHub);
+ break;
+ case SNACKBAR:
+ UtilsDisplay.showUpdateAvailableSnackbar(context, String.format(context.getResources().getString(R.string.appupdater_update_available_description_snackbar), UtilsLibrary.getAppInstalledVersion(context)), UtilsLibrary.getDurationEnumToBoolean(duration), updateFrom, gitHub);
+ break;
+ case NOTIFICATION:
+ UtilsDisplay.showUpdateAvailableNotification(context, context.getResources().getString(R.string.appupdater_update_available), String.format(context.getResources().getString(R.string.appupdater_update_available_description_notification), version, UtilsLibrary.getAppName(context)), updateFrom, gitHub);
+ break;
+ }
+ }
+ } else if (showAppUpdated) {
+ switch (display) {
+ case DIALOG:
+ UtilsDisplay.showUpdateNotAvailableDialog(context, context.getResources().getString(R.string.appupdater_update_not_available), String.format(context.getResources().getString(R.string.appupdater_update_not_available_description), UtilsLibrary.getAppName(context)));
+ break;
+ case SNACKBAR:
+ UtilsDisplay.showUpdateNotAvailableSnackbar(context, context.getResources().getString(R.string.appupdater_update_not_available_description), UtilsLibrary.getDurationEnumToBoolean(duration));
+ break;
+ case NOTIFICATION:
+ UtilsDisplay.showUpdateNotAvailableNotification(context, context.getResources().getString(R.string.appupdater_update_not_available), String.format(context.getResources().getString(R.string.appupdater_update_not_available_description), UtilsLibrary.getAppName(context)));
+ break;
+ }
+ }
+ }
+ }
+
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/UtilsDisplay.java b/library/src/main/java/com/github/javiersantos/appupdater/UtilsDisplay.java
new file mode 100644
index 00000000..e42e6f02
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/UtilsDisplay.java
@@ -0,0 +1,129 @@
+package com.github.javiersantos.appupdater;
+
+import android.app.Activity;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.media.RingtoneManager;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.NotificationCompat;
+import android.view.View;
+
+import com.afollestad.materialdialogs.DialogAction;
+import com.afollestad.materialdialogs.MaterialDialog;
+import com.github.javiersantos.appupdater.enums.UpdateFrom;
+import com.github.javiersantos.appupdater.objects.GitHub;
+
+class UtilsDisplay {
+
+ static void showUpdateAvailableDialog(final Context context, String title, String content, final UpdateFrom updateFrom, final GitHub gitHub) {
+ final LibraryPreferences libraryPreferences = new LibraryPreferences(context);
+
+ MaterialDialog materialDialog = new MaterialDialog.Builder(context)
+ .title(title)
+ .content(content)
+ .positiveText(context.getResources().getString(R.string.appupdater_btn_update))
+ .negativeText(context.getResources().getString(android.R.string.cancel))
+ .neutralText(context.getResources().getString(R.string.appupdater_btn_disable))
+ .onPositive(new MaterialDialog.SingleButtonCallback() {
+ @Override
+ public void onClick(MaterialDialog dialog, DialogAction which) {
+ UtilsLibrary.goToUpdate(context, updateFrom, gitHub);
+ }
+ })
+ .onNeutral(new MaterialDialog.SingleButtonCallback() {
+ @Override
+ public void onClick(MaterialDialog dialog, DialogAction which) {
+ libraryPreferences.setAppUpdaterShow(false);
+ }
+ }).show();
+ }
+
+ static void showUpdateNotAvailableDialog(final Context context, String title, String content) {
+ MaterialDialog materialDialog = new MaterialDialog.Builder(context)
+ .title(title)
+ .content(content)
+ .positiveText(context.getResources().getString(android.R.string.ok))
+ .show();
+ }
+
+ static void showUpdateAvailableSnackbar(final Context context, String content, Boolean indefinite, final UpdateFrom updateFrom, final GitHub gitHub) {
+ Activity activity = (Activity) context;
+ int snackbarTime;
+
+ if (indefinite) {
+ snackbarTime = Snackbar.LENGTH_INDEFINITE;
+ } else {
+ snackbarTime = Snackbar.LENGTH_LONG;
+ }
+
+ Snackbar snackbar = Snackbar.make(activity.getWindow().getDecorView().getRootView(), content, snackbarTime);
+ snackbar.setAction(context.getResources().getString(R.string.appupdater_btn_update), new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ UtilsLibrary.goToUpdate(context, updateFrom, gitHub);
+ }
+ }).show();
+ }
+
+ static void showUpdateNotAvailableSnackbar(final Context context, String content, Boolean indefinite) {
+ Activity activity = (Activity) context;
+ int snackbarTime;
+
+ if (indefinite) {
+ snackbarTime = Snackbar.LENGTH_INDEFINITE;
+ } else {
+ snackbarTime = Snackbar.LENGTH_LONG;
+ }
+
+ Snackbar.make(activity.getWindow().getDecorView().getRootView(), content, snackbarTime).show();
+ }
+
+ static void showUpdateAvailableNotification(Context context, String title, String content, UpdateFrom updateFrom, GitHub gitHub) {
+ PendingIntent contentIntent = PendingIntent.getActivity(context, 0, context.getPackageManager().getLaunchIntentForPackage(UtilsLibrary.getAppPackageName(context)), PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent pendingIntentUpdate = PendingIntent.getActivity(context, 0, UtilsLibrary.intentToUpdate(context, updateFrom, gitHub), PendingIntent.FLAG_CANCEL_CURRENT);
+ NotificationCompat.Style style = new NotificationCompat.BigTextStyle().bigText(content);
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+ .setContentIntent(contentIntent)
+ .setContentTitle(title)
+ .setContentText(content)
+ .setStyle(style)
+ .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
+ .setOnlyAlertOnce(true)
+ .setAutoCancel(true)
+ .addAction(R.drawable.ic_system_update_white_24dp, context.getResources().getString(R.string.appupdater_btn_update), pendingIntentUpdate);
+
+ try {
+ ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
+ builder.setSmallIcon(applicationInfo.icon);
+ } catch (PackageManager.NameNotFoundException ignore) {}
+
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.notify(0, builder.build());
+ }
+
+ static void showUpdateNotAvailableNotification(Context context, String title, String content) {
+ PendingIntent contentIntent = PendingIntent.getActivity(context, 0, context.getPackageManager().getLaunchIntentForPackage(UtilsLibrary.getAppPackageName(context)), PendingIntent.FLAG_CANCEL_CURRENT);
+ NotificationCompat.Style style = new NotificationCompat.BigTextStyle().bigText(content);
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+ .setContentIntent(contentIntent)
+ .setContentTitle(title)
+ .setContentText(content)
+ .setStyle(style)
+ .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
+ .setOnlyAlertOnce(true)
+ .setAutoCancel(true);
+ try {
+ ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
+ builder.setSmallIcon(applicationInfo.icon);
+ } catch (PackageManager.NameNotFoundException ignore) {}
+
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.notify(0, builder.build());
+ }
+
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/UtilsLibrary.java b/library/src/main/java/com/github/javiersantos/appupdater/UtilsLibrary.java
new file mode 100644
index 00000000..bb769261
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/UtilsLibrary.java
@@ -0,0 +1,218 @@
+package com.github.javiersantos.appupdater;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.util.Log;
+
+import com.github.javiersantos.appupdater.enums.Duration;
+import com.github.javiersantos.appupdater.enums.UpdateFrom;
+import com.github.javiersantos.appupdater.objects.GitHub;
+import com.github.javiersantos.appupdater.objects.Version;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+class UtilsLibrary {
+
+ static String getAppName(Context context) {
+ return context.getString(context.getApplicationInfo().labelRes);
+ }
+
+ static String getAppPackageName(Context context) {
+ return context.getPackageName();
+ }
+
+ static String getAppInstalledVersion(Context context) {
+ String version = "0.0.0.0";
+
+ try {
+ version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+
+ return version;
+ }
+
+ static Boolean isUpdateAvailable(String installedVersion, String latestVersion) {
+ Boolean res = false;
+
+ if (!installedVersion.equals("0.0.0.0") && !latestVersion.equals("0.0.0.0")) {
+ Version installed = new Version(installedVersion);
+ Version latest = new Version(latestVersion);
+ res = installed.compareTo(latest) < 0;
+ }
+
+ return res;
+ }
+
+ static Boolean getDurationEnumToBoolean(Duration duration) {
+ Boolean res = false;
+
+ switch (duration) {
+ case INDEFINITE:
+ res = true;
+ break;
+ }
+
+ return res;
+ }
+
+ static String getUpdateURL(Context context, UpdateFrom updateFrom, GitHub gitHub) {
+ String res;
+
+ switch (updateFrom) {
+ default:
+ res = Config.PLAY_STORE_URL + getAppPackageName(context);
+ break;
+ case GITHUB:
+ res = Config.GITHUB_URL + gitHub.getGithubUser() + "/" + gitHub.getGithubRepo() + "/releases";
+ break;
+ case AMAZON:
+ res = Config.AMAZON_URL + getAppPackageName(context);
+ break;
+ }
+
+ return res;
+ }
+
+ static String getLatestAppVersion(Context context, UpdateFrom updateFrom, GitHub gitHub) {
+ Boolean notAvailable = false;
+ String res = "0.0.0.0";
+ String source = "";
+
+ try {
+ HttpParams params = new BasicHttpParams();
+ HttpConnectionParams.setConnectionTimeout(params, 4000);
+ HttpConnectionParams.setSoTimeout(params, 5000);
+
+ HttpClient client = new DefaultHttpClient(params);
+ HttpGet request = new HttpGet(getUpdateURL(context, updateFrom, gitHub));
+
+ HttpResponse response = client.execute(request);
+
+ InputStream in = response.getEntity().getContent();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ StringBuilder str = new StringBuilder();
+ String line;
+ while((line = reader.readLine()) != null) {
+ switch (updateFrom) {
+ default:
+ if (line.contains(Config.PLAY_STORE_TAG_RELEASE)) {
+ str.append(line);
+ }
+ break;
+ case GITHUB:
+ if (line.contains(Config.GITHUB_TAG_RELEASE)) {
+ str.append(line);
+ }
+ break;
+ case AMAZON:
+ if (line.contains(Config.AMAZON_TAG_RELEASE)) {
+ str.append(line);
+ }
+ break;
+ }
+ }
+
+ if (str.length() == 0) {
+ notAvailable = true;
+ Log.e("AppUpdater", "Cannot retrieve latest version. Is it configured properly?");
+ }
+
+ in.close();
+ source = str.toString();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ if (!notAvailable) {
+ switch (updateFrom) {
+ default:
+ String[] splitPlayStore = source.split(Config.PLAY_STORE_TAG_RELEASE);
+ splitPlayStore = splitPlayStore[1].split("(<)");
+ res = splitPlayStore[0].trim();
+ break;
+ case GITHUB:
+ String[] splitGitHub = source.split(Config.GITHUB_TAG_RELEASE);
+ splitGitHub = splitGitHub[1].split("(\")");
+ res = splitGitHub[0].trim();
+ if (res.contains("v")) { // Some repo uses vX.X.X
+ splitGitHub = res.split("(v)");
+ res = splitGitHub[1].trim();
+ }
+ break;
+ case AMAZON:
+ String[] splitAmazon = source.split(Config.AMAZON_TAG_RELEASE);
+ splitAmazon = splitAmazon[1].split("(<)");
+ res = splitAmazon[0].trim();
+ break;
+ }
+ }
+
+ return res;
+ }
+
+ static Intent intentToUpdate(Context context, UpdateFrom updateFrom, GitHub gitHub) {
+ String updateURL = getUpdateURL(context, updateFrom, gitHub);
+ Intent intent;
+
+ if (updateFrom.equals(UpdateFrom.GOOGLE_PLAY)) {
+ intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getAppPackageName(context)));
+ } else {
+ intent = new Intent(Intent.ACTION_VIEW, Uri.parse(updateURL));
+ }
+
+ return intent;
+ }
+
+ static void goToUpdate(Context context, UpdateFrom updateFrom, GitHub gitHub) {
+ Intent intent = intentToUpdate(context, updateFrom, gitHub);
+ String updateURL = getUpdateURL(context, updateFrom, gitHub);
+
+ if (updateFrom.equals(UpdateFrom.GOOGLE_PLAY)) {
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ intent = new Intent(Intent.ACTION_VIEW, Uri.parse(updateURL));
+ context.startActivity(intent);
+ }
+ } else {
+ context.startActivity(intent);
+ }
+ }
+
+ static Boolean isAbleToShow(Context context, Integer showEvery) {
+ LibraryPreferences libraryPreferences = new LibraryPreferences(context);
+ return libraryPreferences.getSuccessfulChecks() % showEvery == 0;
+ }
+
+ static Boolean isNetworkAvailable(Context context) {
+ Boolean res = false;
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (cm != null) {
+ NetworkInfo networkInfo = cm.getActiveNetworkInfo();
+ if (networkInfo != null) {
+ res = networkInfo.isConnected();
+ }
+ }
+
+ return res;
+ }
+
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/enums/Display.java b/library/src/main/java/com/github/javiersantos/appupdater/enums/Display.java
new file mode 100644
index 00000000..1b77efa1
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/enums/Display.java
@@ -0,0 +1,7 @@
+package com.github.javiersantos.appupdater.enums;
+
+public enum Display {
+ DIALOG,
+ SNACKBAR,
+ NOTIFICATION
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/enums/Duration.java b/library/src/main/java/com/github/javiersantos/appupdater/enums/Duration.java
new file mode 100644
index 00000000..d08c2b1d
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/enums/Duration.java
@@ -0,0 +1,6 @@
+package com.github.javiersantos.appupdater.enums;
+
+public enum Duration {
+ NORMAL,
+ INDEFINITE
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/enums/UpdateFrom.java b/library/src/main/java/com/github/javiersantos/appupdater/enums/UpdateFrom.java
new file mode 100644
index 00000000..c2d6cb74
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/enums/UpdateFrom.java
@@ -0,0 +1,7 @@
+package com.github.javiersantos.appupdater.enums;
+
+public enum UpdateFrom {
+ GOOGLE_PLAY,
+ GITHUB,
+ AMAZON
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/objects/GitHub.java b/library/src/main/java/com/github/javiersantos/appupdater/objects/GitHub.java
new file mode 100644
index 00000000..e971360a
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/objects/GitHub.java
@@ -0,0 +1,35 @@
+package com.github.javiersantos.appupdater.objects;
+
+public class GitHub {
+ private String githubUser;
+ private String githubRepo;
+
+ public GitHub(String githubUser, String githubRepo) {
+ checkGithub(githubUser, githubRepo);
+ this.githubUser = githubUser;
+ this.githubRepo = githubRepo;
+ }
+
+ public String getGithubUser() {
+ return githubUser;
+ }
+
+ public void setGithubUser(String user) {
+ this.githubUser = user;
+ }
+
+ public String getGithubRepo() {
+ return githubRepo;
+ }
+
+ public void setGithubRepo(String repo) {
+ this.githubRepo = repo;
+ }
+
+ private void checkGithub(String user, String repo) {
+ if (user.length() == 0 || repo.length() == 0) {
+ throw new IllegalArgumentException("GitHub user or repo is empty");
+ }
+ }
+
+}
diff --git a/library/src/main/java/com/github/javiersantos/appupdater/objects/Version.java b/library/src/main/java/com/github/javiersantos/appupdater/objects/Version.java
new file mode 100644
index 00000000..3cb85569
--- /dev/null
+++ b/library/src/main/java/com/github/javiersantos/appupdater/objects/Version.java
@@ -0,0 +1,50 @@
+package com.github.javiersantos.appupdater.objects;
+
+import android.util.Log;
+
+public class Version implements Comparable {
+ private String TAG = "AppUpdater";
+ private String version;
+
+ public final String get() {
+ return this.version;
+ }
+
+ public Version(String version) {
+ if(version == null)
+ Log.e(TAG, "Version can not be null");
+ if(!version.matches("[0-9]+(\\.[0-9]+)*"))
+ Log.e(TAG, "Invalid version format");
+ this.version = version;
+ }
+
+ @Override public int compareTo(Version that) {
+ if(that == null)
+ return 1;
+ String[] thisParts = this.get().split("\\.");
+ String[] thatParts = that.get().split("\\.");
+ int length = Math.max(thisParts.length, thatParts.length);
+ for(int i = 0; i < length; i++) {
+ int thisPart = i < thisParts.length ?
+ Integer.parseInt(thisParts[i]) : 0;
+ int thatPart = i < thatParts.length ?
+ Integer.parseInt(thatParts[i]) : 0;
+ if(thisPart < thatPart)
+ return -1;
+ if(thisPart > thatPart)
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override public boolean equals(Object that) {
+ if(this == that)
+ return true;
+ if(that == null)
+ return false;
+ if(this.getClass() != that.getClass())
+ return false;
+ return this.compareTo((Version) that) == 0;
+ }
+
+}
\ No newline at end of file
diff --git a/library/src/main/res/drawable-hdpi/ic_clear_all_white_24dp.png b/library/src/main/res/drawable-hdpi/ic_clear_all_white_24dp.png
new file mode 100644
index 00000000..e23d886c
Binary files /dev/null and b/library/src/main/res/drawable-hdpi/ic_clear_all_white_24dp.png differ
diff --git a/library/src/main/res/drawable-hdpi/ic_system_update_white_24dp.png b/library/src/main/res/drawable-hdpi/ic_system_update_white_24dp.png
new file mode 100644
index 00000000..04b8e521
Binary files /dev/null and b/library/src/main/res/drawable-hdpi/ic_system_update_white_24dp.png differ
diff --git a/library/src/main/res/drawable-mdpi/ic_clear_all_white_24dp.png b/library/src/main/res/drawable-mdpi/ic_clear_all_white_24dp.png
new file mode 100644
index 00000000..dca30487
Binary files /dev/null and b/library/src/main/res/drawable-mdpi/ic_clear_all_white_24dp.png differ
diff --git a/library/src/main/res/drawable-mdpi/ic_system_update_white_24dp.png b/library/src/main/res/drawable-mdpi/ic_system_update_white_24dp.png
new file mode 100644
index 00000000..cccf9b3e
Binary files /dev/null and b/library/src/main/res/drawable-mdpi/ic_system_update_white_24dp.png differ
diff --git a/library/src/main/res/drawable-xhdpi/ic_clear_all_white_24dp.png b/library/src/main/res/drawable-xhdpi/ic_clear_all_white_24dp.png
new file mode 100644
index 00000000..fef5dcd2
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/ic_clear_all_white_24dp.png differ
diff --git a/library/src/main/res/drawable-xhdpi/ic_system_update_white_24dp.png b/library/src/main/res/drawable-xhdpi/ic_system_update_white_24dp.png
new file mode 100644
index 00000000..531eac6a
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/ic_system_update_white_24dp.png differ
diff --git a/library/src/main/res/drawable-xxhdpi/ic_clear_all_white_24dp.png b/library/src/main/res/drawable-xxhdpi/ic_clear_all_white_24dp.png
new file mode 100644
index 00000000..51d2d3da
Binary files /dev/null and b/library/src/main/res/drawable-xxhdpi/ic_clear_all_white_24dp.png differ
diff --git a/library/src/main/res/drawable-xxhdpi/ic_system_update_white_24dp.png b/library/src/main/res/drawable-xxhdpi/ic_system_update_white_24dp.png
new file mode 100644
index 00000000..f88d6108
Binary files /dev/null and b/library/src/main/res/drawable-xxhdpi/ic_system_update_white_24dp.png differ
diff --git a/library/src/main/res/drawable-xxxhdpi/ic_clear_all_white_24dp.png b/library/src/main/res/drawable-xxxhdpi/ic_clear_all_white_24dp.png
new file mode 100644
index 00000000..9dbccf36
Binary files /dev/null and b/library/src/main/res/drawable-xxxhdpi/ic_clear_all_white_24dp.png differ
diff --git a/library/src/main/res/drawable-xxxhdpi/ic_system_update_white_24dp.png b/library/src/main/res/drawable-xxxhdpi/ic_system_update_white_24dp.png
new file mode 100644
index 00000000..ac4ce15e
Binary files /dev/null and b/library/src/main/res/drawable-xxxhdpi/ic_system_update_white_24dp.png differ
diff --git a/library/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml
new file mode 100644
index 00000000..22cbf89d
--- /dev/null
+++ b/library/src/main/res/values/strings.xml
@@ -0,0 +1,15 @@
+
+ AppUpdater
+
+ New update available!
+ Update %1$s is available to download. Downloading the latest update you will get the latest features, improvements and bug fixes of %2$s.
+ Update %1$s is available!
+ Update %1$s of %2$s is available to download
+
+ No update available
+ You\'ve the latest version available of %s!
+
+ Update
+ Don\'t show again
+ Dismiss
+
diff --git a/library/src/test/java/com/github/javiersantos/appupdater/ExampleUnitTest.java b/library/src/test/java/com/github/javiersantos/appupdater/ExampleUnitTest.java
new file mode 100644
index 00000000..0c3a06e2
--- /dev/null
+++ b/library/src/test/java/com/github/javiersantos/appupdater/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.github.javiersantos.appupdater;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 00000000..33069973
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':library'