diff --git a/.gitignore b/.gitignore
index c7a0250..baf518f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,10 @@
-library/build
-library/library.iml
-sample/build
-sample/sample.iml
-.idea
-build
-android-auto-update.iml
-local.properties
\ No newline at end of file
+/.gradle/
+/.idea/
+/build/
+/library/build/
+/library/library.iml
+/sample/build/
+/sample/sample.iml
+/android-auto-update.iml
+/local.properties
diff --git a/README.md b/README.md
index 7d42584..11f9abb 100644
--- a/README.md
+++ b/README.md
@@ -2,54 +2,38 @@ Android应用自动更新库(android-auto-update)
===================
-该library项目实现了软件版本检查,apk文件下载,软件安装(Android app update checker,download and install apk)支持API 8+
+该library项目实现了软件版本检查,apk文件下载,软件安装(Android app update checker,download and install apk)支持API 14+
-#### 1.导入library项目 ####
+#### 1.导入library项目
提供2种版本检查方式,在你的项目中添加以下代码即可
- 使用Dialog
- `UpdateChecker.checkForDialog(this);`
+ UpdateChecker.checkForDialog(this);
- 使用Notification
- `UpdateChecker.checkForNotification(this);`
+ UpdateChecker.checkForNotification(this);
-#### 2.添加权限 ####
+#### 2.截图
-- 添加访问网络的权限
-
- ``
-
-- 添加写SDCard权限(可选,非必须)
-
- 如果添加这个权限 apk下载在sdcard中的Android/data/包名/cache目录下 否则下载到 内存中的 /data/data/包名/cache中
-
- ``
-
-#### 3.截图 ####

-
-
-
-
-
-
-
+
-#### 4.使用与参考的开源项目 ####
+
+
+
-1. [android-styled-dialogs](https://github.com/inmite/android-styled-dialogs "https://github.com/inmite/android-styled-dialogs") 使用该项目,可以在api 8+上显示 holo 风格的对话框,其它选择
-,当然你也可以使用其它的开源项目比如:[ActionBarSherlock](https://github.com/JakeWharton/ActionBarSherlock "https://github.com/JakeWharton/ActionBarSherlock") 和 [HoloEverywhere](https://github.com/Prototik/HoloEverywhere "https://github.com/Prototik/HoloEverywhere")
+
+
-2. [UpdateChecker](https://github.com/rampo/UpdateChecker "https://github.com/rampo/UpdateChecker") 该项目检查的是google play上的应用,如果有更新打开google Play,不提供下载apk的功能
+
-
diff --git a/build.gradle b/build.gradle
index 49357e9..7c3502c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,16 +1,20 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.1.0'
+ classpath 'com.android.tools.build:gradle:3.1.0'
}
}
allprojects {
repositories {
jcenter()
+ google()
}
}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/extras/android-auto-update-v1.1.apk b/extras/android-auto-update-v1.1.apk
new file mode 100644
index 0000000..b70ed8a
Binary files /dev/null and b/extras/android-auto-update-v1.1.apk differ
diff --git a/extras/android-auto-update-v1.2.apk b/extras/android-auto-update-v1.2.apk
new file mode 100644
index 0000000..b2050f8
Binary files /dev/null and b/extras/android-auto-update-v1.2.apk differ
diff --git a/extras/android-auto-update-v1.3.apk b/extras/android-auto-update-v1.3.apk
new file mode 100644
index 0000000..10b6101
Binary files /dev/null and b/extras/android-auto-update-v1.3.apk differ
diff --git a/extras/demo.jks b/extras/demo.jks
new file mode 100644
index 0000000..0b01653
Binary files /dev/null and b/extras/demo.jks differ
diff --git a/extras/update.json b/extras/update.json
new file mode 100644
index 0000000..f77795a
--- /dev/null
+++ b/extras/update.json
@@ -0,0 +1,5 @@
+{
+ "url":"https://raw.githubusercontent.com/feicien/android-auto-update/develop/extras/android-auto-update-v1.3.apk",
+ "versionCode":4,
+ "updateMessage":"1. 适配 Android 8.0\n2. 适配 Android 9.0\n3. 更新说明"
+}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index c97a8bd..f6b961f 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 51c68cb..6851569 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sat Feb 28 13:34:31 CST 2015
+#Sat Apr 07 16:35:01 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
index 91a7e26..cccdd3d
--- a/gradlew
+++ b/gradlew
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
##############################################################################
##
@@ -6,20 +6,38 @@
##
##############################################################################
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# 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
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
-warn ( ) {
+warn () {
echo "$*"
}
-die ( ) {
+die () {
echo
echo "$*"
echo
@@ -30,6 +48,7 @@ die ( ) {
cygwin=false
msys=false
darwin=false
+nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
@@ -40,31 +59,11 @@ case "`uname`" in
MINGW* )
msys=true
;;
+ NONSTOP* )
+ nonstop=true
+ ;;
esac
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
- [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
-# 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\"`/" >&-
-APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -90,7 +89,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -114,6 +113,7 @@ fi
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`
@@ -154,11 +154,19 @@ if $cygwin ; then
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=("$@")
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index 8a0b282..f955316 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -8,14 +8,14 @@
@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 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=
+
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -46,10 +46,9 @@ echo location of your Java installation.
goto fail
:init
-@rem Get command-line arguments, handling Windowz variants
+@rem Get command-line arguments, handling Windows 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.
@@ -60,11 +59,6 @@ set _SKIP=2
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
diff --git a/library/build.gradle b/library/build.gradle
index 9dca35c..86fb526 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -1,21 +1,25 @@
apply plugin: 'com.android.library'
-dependencies {
- compile 'com.android.support:support-v4:21.0.3'
-}
android {
- compileSdkVersion 21
- buildToolsVersion '21.1.2'
+ compileSdkVersion 27
+ buildToolsVersion '27.0.3'
defaultConfig {
- minSdkVersion 8
- targetSdkVersion 21
- versionCode 2
- versionName '1.1'
+ minSdkVersion 14
+ targetSdkVersion 27
+ versionCode 3
+ versionName '1.2'
}
-}
+ //库项目不生成 BuildConfig
+ libraryVariants.all {
+ it.generateBuildConfig.enabled = false
+ }
+}
+dependencies {
+ implementation 'com.android.support:support-v4:27.1.0'
+}
diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml
index fcc4bde..d91cb3b 100644
--- a/library/src/main/AndroidManifest.xml
+++ b/library/src/main/AndroidManifest.xml
@@ -3,4 +3,26 @@
package="com.loveplusplus.update">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/main/java/com/loveplusplus/update/ApkUtils.java b/library/src/main/java/com/loveplusplus/update/ApkUtils.java
new file mode 100644
index 0000000..79891fb
--- /dev/null
+++ b/library/src/main/java/com/loveplusplus/update/ApkUtils.java
@@ -0,0 +1,58 @@
+package com.loveplusplus.update;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.support.v4.content.FileProvider;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author feicien (ithcheng@gmail.com)
+ * @since 2018-04-07 16:49
+ */
+public class ApkUtils {
+
+
+ public static void installAPk(Context context, File apkFile) {
+
+ Intent installAPKIntent = getApkInStallIntent(context, apkFile);
+ context.startActivity(installAPKIntent);
+
+ }
+
+
+ public static Intent getApkInStallIntent(Context context, File apkFile) {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
+ Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".update.provider", apkFile);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setDataAndType(uri, "application/vnd.android.package-archive");
+ } else {
+ Uri uri = getApkUri(apkFile);
+ intent.setDataAndType(uri, "application/vnd.android.package-archive");
+ }
+ return intent;
+ }
+
+
+ private static Uri getApkUri(File apkFile) {
+ Log.d(Constants.TAG, apkFile.toString());
+ //如果没有设置 SDCard 写权限,或者没有 SDCard,apk 文件保存在内存中,需要授予权限才能安装
+ try {
+ String[] command = {"chmod", "777", apkFile.toString()};
+ ProcessBuilder builder = new ProcessBuilder(command);
+ builder.start();
+ } catch (IOException ignored) {
+ }
+ Uri uri = Uri.fromFile(apkFile);
+ Log.d(Constants.TAG, uri.toString());
+ return uri;
+ }
+
+}
diff --git a/library/src/main/java/com/loveplusplus/update/AppUtils.java b/library/src/main/java/com/loveplusplus/update/AppUtils.java
new file mode 100644
index 0000000..383c6f5
--- /dev/null
+++ b/library/src/main/java/com/loveplusplus/update/AppUtils.java
@@ -0,0 +1,33 @@
+package com.loveplusplus.update;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+/**
+ * @author feicien (ithcheng@gmail.com)
+ * @since 2016-07-05 17:41
+ */
+
+public class AppUtils {
+
+ public static int getVersionCode(Context mContext) {
+ if (mContext != null) {
+ try {
+ return mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionCode;
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+ }
+ return 0;
+ }
+
+ public static String getVersionName(Context mContext) {
+ if (mContext != null) {
+ try {
+ return mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+ }
+
+ return "";
+ }
+}
diff --git a/library/src/main/java/com/loveplusplus/update/CheckUpdateTask.java b/library/src/main/java/com/loveplusplus/update/CheckUpdateTask.java
new file mode 100644
index 0000000..4fde8f4
--- /dev/null
+++ b/library/src/main/java/com/loveplusplus/update/CheckUpdateTask.java
@@ -0,0 +1,94 @@
+package com.loveplusplus.update;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+/**
+ * @author feicien (ithcheng@gmail.com)
+ * @since 2016-07-05 19:21
+ */
+class CheckUpdateTask extends AsyncTask {
+
+ private ProgressDialog dialog;
+ private Context mContext;
+ private int mType;
+ private boolean mShowProgressDialog;
+ private static final String url = Constants.UPDATE_URL;
+
+ CheckUpdateTask(Context context, int type, boolean showProgressDialog) {
+
+ this.mContext = context;
+ this.mType = type;
+ this.mShowProgressDialog = showProgressDialog;
+
+ }
+
+
+ protected void onPreExecute() {
+ if (mShowProgressDialog) {
+ dialog = new ProgressDialog(mContext);
+ dialog.setMessage(mContext.getString(R.string.android_auto_update_dialog_checking));
+ dialog.show();
+ }
+ }
+
+
+ @Override
+ protected void onPostExecute(String result) {
+
+ if (dialog != null && dialog.isShowing()) {
+ dialog.dismiss();
+ }
+
+ if (!TextUtils.isEmpty(result)) {
+ parseJson(result);
+ }
+ }
+
+ private void parseJson(String result) {
+ try {
+
+ JSONObject obj = new JSONObject(result);
+ String updateMessage = obj.getString(Constants.APK_UPDATE_CONTENT);
+ String apkUrl = obj.getString(Constants.APK_DOWNLOAD_URL);
+ int apkCode = obj.getInt(Constants.APK_VERSION_CODE);
+
+ int versionCode = AppUtils.getVersionCode(mContext);
+
+ if (apkCode > versionCode) {
+ if (mType == Constants.TYPE_NOTIFICATION) {
+ new NotificationHelper(mContext).showNotification(updateMessage, apkUrl);
+ } else if (mType == Constants.TYPE_DIALOG) {
+ showDialog(mContext, updateMessage, apkUrl);
+ }
+ } else if (mShowProgressDialog) {
+ Toast.makeText(mContext, mContext.getString(R.string.android_auto_update_toast_no_new_update), Toast.LENGTH_SHORT).show();
+ }
+
+ } catch (JSONException e) {
+ Log.e(Constants.TAG, "parse json error");
+ }
+ }
+
+
+ /**
+ * Show dialog
+ */
+ private void showDialog(Context context, String content, String apkUrl) {
+ UpdateDialog.show(context, content, apkUrl);
+ }
+
+
+ @Override
+ protected String doInBackground(Void... args) {
+ return HttpUtils.get(url);
+ }
+}
diff --git a/library/src/main/java/com/loveplusplus/update/Constants.java b/library/src/main/java/com/loveplusplus/update/Constants.java
index ddc7d0d..dc29302 100644
--- a/library/src/main/java/com/loveplusplus/update/Constants.java
+++ b/library/src/main/java/com/loveplusplus/update/Constants.java
@@ -1,13 +1,20 @@
package com.loveplusplus.update;
-public class Constants {
+class Constants {
-// protected static final String APP_UPDATE_SERVER_URL = "http://192.168.205.33:8080/Hello/api/update";
-
- // json {"url":"http://192.168.205.33:8080/Hello/medtime_v3.0.1_Other_20150116.apk","versionCode":2,"updateMessage":"版本更新信息"}
- //我这里服务器返回的json数据是这样的,可以根据实际情况修改下面参数的名称
- public static final String APK_DOWNLOAD_URL = "url";
- public static final String APK_UPDATE_CONTENT = "updateMessage";
- public static final String APK_VERSION_CODE = "versionCode";
+ // json {"url":"http://192.168.205.33:8080/Hello/app_v3.0.1_Other_20150116.apk","versionCode":2,"updateMessage":"版本更新信息"}
+
+ static final String APK_DOWNLOAD_URL = "url";
+ static final String APK_UPDATE_CONTENT = "updateMessage";
+ static final String APK_VERSION_CODE = "versionCode";
+
+
+ static final int TYPE_NOTIFICATION = 2;
+
+ static final int TYPE_DIALOG = 1;
+
+ static final String TAG = "UpdateChecker";
+
+ static final String UPDATE_URL = "https://raw.githubusercontent.com/feicien/android-auto-update/develop/extras/update.json";
}
diff --git a/library/src/main/java/com/loveplusplus/update/DownloadService.java b/library/src/main/java/com/loveplusplus/update/DownloadService.java
index f6a30ad..4eb7254 100644
--- a/library/src/main/java/com/loveplusplus/update/DownloadService.java
+++ b/library/src/main/java/com/loveplusplus/update/DownloadService.java
@@ -1,5 +1,9 @@
package com.loveplusplus.update;
+import android.app.IntentService;
+import android.content.Intent;
+import android.util.Log;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -7,127 +11,86 @@
import java.net.HttpURLConnection;
import java.net.URL;
-import android.app.IntentService;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.NotificationCompat.Builder;
-import android.util.Log;
-
public class DownloadService extends IntentService {
- // 10-10 19:14:32.618: D/DownloadService(1926): 测试缓存:41234 32kb
- // 10-10 19:16:10.892: D/DownloadService(2069): 测试缓存:41170 1kb
- // 10-10 19:18:21.352: D/DownloadService(2253): 测试缓存:39899 10kb
- private static final int BUFFER_SIZE = 10 * 1024; // 8k ~ 32K
- private static final String TAG = "DownloadService";
- private NotificationManager mNotifyManager;
- private Builder mBuilder;
-
- public DownloadService() {
- super("DownloadService");
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
-
- mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- mBuilder = new NotificationCompat.Builder(this);
-
- String appName=getString(getApplicationInfo().labelRes);
- int icon=getApplicationInfo().icon;
-
- mBuilder.setContentTitle(appName).setSmallIcon(icon);
- String urlStr = intent.getStringExtra(Constants.APK_DOWNLOAD_URL);
- InputStream in=null;
- FileOutputStream out = null;
- try {
- URL url = new URL(urlStr);
- HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
-
- urlConnection.setRequestMethod("GET");
- urlConnection.setDoOutput(false);
- urlConnection.setConnectTimeout(10 * 1000);
- urlConnection.setReadTimeout(10 * 1000);
- urlConnection.setRequestProperty("Connection", "Keep-Alive");
- urlConnection.setRequestProperty("Charset", "UTF-8");
- urlConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
-
- urlConnection.connect();
- long bytetotal = urlConnection.getContentLength();
- long bytesum = 0;
- int byteread = 0;
- in = urlConnection.getInputStream();
- File dir = StorageUtils.getCacheDirectory(this);
- String apkName=urlStr.substring(urlStr.lastIndexOf("/")+1, urlStr.length());
- File apkFile = new File(dir, apkName);
- out = new FileOutputStream(apkFile);
- byte[] buffer = new byte[BUFFER_SIZE];
-
- int oldProgress = 0;
-
- while ((byteread = in.read(buffer)) != -1) {
- bytesum += byteread;
- out.write(buffer, 0, byteread);
-
- int progress = (int) (bytesum * 100L / bytetotal);
- // 如果进度与之前进度相等,则不更新,如果更新太频繁,否则会造成界面卡顿
- if (progress != oldProgress) {
- updateProgress(progress);
- }
- oldProgress = progress;
- }
- // 下载完成
- mBuilder.setContentText(getString(R.string.download_success)).setProgress(0, 0, false);
-
- Intent installAPKIntent = new Intent(Intent.ACTION_VIEW);
- //如果没有设置SDCard写权限,或者没有sdcard,apk文件保存在内存中,需要授予权限才能安装
- String[] command = {"chmod","777",apkFile.toString()};
- ProcessBuilder builder = new ProcessBuilder(command);
- builder.start();
-
- installAPKIntent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
- //installAPKIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- //installAPKIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- //installAPKIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
- PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, installAPKIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- mBuilder.setContentIntent(pendingIntent);
- Notification noti = mBuilder.build();
- noti.flags = android.app.Notification.FLAG_AUTO_CANCEL;
- mNotifyManager.notify(0, noti);
-
- } catch (Exception e) {
- Log.e(TAG, "download apk file error", e);
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if(in!=null){
- try {
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- private void updateProgress(int progress) {
- //"正在下载:" + progress + "%"
- mBuilder.setContentText(this.getString(R.string.download_progress, progress)).setProgress(100, progress, false);
- //setContentInent如果不设置在4.0+上没有问题,在4.0以下会报异常
- PendingIntent pendingintent = PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_CANCEL_CURRENT);
- mBuilder.setContentIntent(pendingintent);
- mNotifyManager.notify(0, mBuilder.build());
- }
+ // 10-10 19:14:32.618: D/DownloadService(1926): 测试缓存:41234 32kb
+ // 10-10 19:16:10.892: D/DownloadService(2069): 测试缓存:41170 1kb
+ // 10-10 19:18:21.352: D/DownloadService(2253): 测试缓存:39899 10kb
+ private static final int BUFFER_SIZE = 10 * 1024; // 8k ~ 32K
+ private static final String TAG = "DownloadService";
+
+
+ public DownloadService() {
+ super("DownloadService");
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+
+ NotificationHelper notificationHelper = new NotificationHelper(this);
+ String urlStr = intent.getStringExtra(Constants.APK_DOWNLOAD_URL);
+ InputStream in = null;
+ FileOutputStream out = null;
+ try {
+ URL url = new URL(urlStr);
+ HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+
+ urlConnection.setRequestMethod("GET");
+ urlConnection.setDoOutput(false);
+ urlConnection.setConnectTimeout(10 * 1000);
+ urlConnection.setReadTimeout(10 * 1000);
+ urlConnection.setRequestProperty("Connection", "Keep-Alive");
+ urlConnection.setRequestProperty("Charset", "UTF-8");
+ urlConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
+
+ urlConnection.connect();
+ long bytetotal = urlConnection.getContentLength();
+ long bytesum = 0;
+ int byteread = 0;
+ in = urlConnection.getInputStream();
+ File dir = StorageUtils.getCacheDirectory(this);
+ String apkName = urlStr.substring(urlStr.lastIndexOf("/") + 1, urlStr.length());
+ File apkFile = new File(dir, apkName);
+ out = new FileOutputStream(apkFile);
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ int oldProgress = 0;
+
+ while ((byteread = in.read(buffer)) != -1) {
+ bytesum += byteread;
+ out.write(buffer, 0, byteread);
+
+ int progress = (int) (bytesum * 100L / bytetotal);
+ // 如果进度与之前进度相等,则不更新,如果更新太频繁,否则会造成界面卡顿
+ if (progress != oldProgress) {
+ notificationHelper.updateProgress(progress);
+ }
+ oldProgress = progress;
+ }
+ // 下载完成
+
+ ApkUtils.installAPk(this, apkFile);
+
+ notificationHelper.cancel();
+
+ } catch (Exception e) {
+ Log.e(TAG, "download apk file error:" + e.getMessage());
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ignored) {
+
+ }
+ }
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ignored) {
+
+ }
+ }
+ }
+ }
+
}
diff --git a/library/src/main/java/com/loveplusplus/update/HttpUtils.java b/library/src/main/java/com/loveplusplus/update/HttpUtils.java
new file mode 100644
index 0000000..6c04380
--- /dev/null
+++ b/library/src/main/java/com/loveplusplus/update/HttpUtils.java
@@ -0,0 +1,61 @@
+package com.loveplusplus.update;
+
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+
+/**
+ * @author feicien (ithcheng@gmail.com)
+ * @since 2016-07-05 19:25
+ */
+public class HttpUtils {
+
+
+ public static String get(String urlStr) {
+ HttpURLConnection uRLConnection = null;
+ InputStream is = null;
+ BufferedReader buffer = null;
+ String result = null;
+ try {
+ URL url = new URL(urlStr);
+ uRLConnection = (HttpURLConnection) url.openConnection();
+ uRLConnection.setRequestMethod("GET");
+
+ is = uRLConnection.getInputStream();
+ buffer = new BufferedReader(new InputStreamReader(is));
+ StringBuilder strBuilder = new StringBuilder();
+ String line;
+ while ((line = buffer.readLine()) != null) {
+ strBuilder.append(line);
+ }
+ result = strBuilder.toString();
+ } catch (Exception e) {
+ Log.e(Constants.TAG, "http error");
+ } finally {
+ if (buffer != null) {
+ try {
+ buffer.close();
+ } catch (IOException ignored) {
+
+ }
+ }
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ignored) {
+
+ }
+ }
+ if (uRLConnection != null) {
+ uRLConnection.disconnect();
+ }
+ }
+ return result;
+ }
+}
diff --git a/library/src/main/java/com/loveplusplus/update/NotificationHelper.java b/library/src/main/java/com/loveplusplus/update/NotificationHelper.java
new file mode 100644
index 0000000..a39ce35
--- /dev/null
+++ b/library/src/main/java/com/loveplusplus/update/NotificationHelper.java
@@ -0,0 +1,111 @@
+package com.loveplusplus.update;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Build;
+import android.support.v4.app.NotificationCompat;
+
+/**
+ * @author feicien (ithcheng@gmail.com)
+ * @since 2018-04-07 16:49
+ */
+public class NotificationHelper extends ContextWrapper {
+
+ private NotificationManager manager;
+
+ private static String CHANNEL_ID = "dxy_app_update";
+
+ private static final int NOTIFICATION_ID = 0;
+
+ public NotificationHelper(Context base) {
+ super(base);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+
+ NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, "应用更新", NotificationManager.IMPORTANCE_LOW);
+ mChannel.setDescription("应用有新版本");
+ mChannel.enableLights(true); //是否在桌面icon右上角展示小红点
+ getManager().createNotificationChannel(mChannel);
+ }
+ }
+
+ /**
+ * Show Notification
+ */
+ public void showNotification(String content, String apkUrl) {
+
+ Intent myIntent = new Intent(this, DownloadService.class);
+ myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ myIntent.putExtra(Constants.APK_DOWNLOAD_URL, apkUrl);
+ PendingIntent pendingIntent = PendingIntent.getService(this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ NotificationCompat.Builder builder = getNofity(content)
+ .setContentIntent(pendingIntent);
+
+ getManager().notify(NOTIFICATION_ID, builder.build());
+ }
+
+
+ public void updateProgress(int progress) {
+
+
+ String text = this.getString(R.string.android_auto_update_download_progress, progress);
+
+ PendingIntent pendingintent = PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);
+
+
+ NotificationCompat.Builder builder = getNofity(text)
+ .setProgress(100, progress, false)
+ .setContentIntent(pendingintent);
+
+ getManager().notify(NOTIFICATION_ID, builder.build());
+ }
+
+ private NotificationCompat.Builder getNofity(String text) {
+ return new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
+ .setTicker(getString(R.string.android_auto_update_notify_ticker))
+ .setContentTitle("应用更新")
+ .setContentText(text)
+ .setSmallIcon(getSmallIcon())
+ .setLargeIcon(getLargeIcon())
+ .setAutoCancel(true)
+ .setPriority(NotificationCompat.PRIORITY_LOW);
+
+ }
+
+ public void cancel() {
+ getManager().cancel(NOTIFICATION_ID);
+ }
+
+
+ private int getSmallIcon() {
+ //设置 nofication 的图标 直接读取小米推送配置的图标
+ int icon = getResources().getIdentifier("mipush_small_notification", "drawable", getPackageName());
+ if (icon == 0) {
+ icon = getApplicationInfo().icon;
+ }
+
+ return icon;
+ }
+
+ private Bitmap getLargeIcon() {
+ int bigIcon = getResources().getIdentifier("mipush_notification", "drawable", getPackageName());
+ if (bigIcon != 0) {
+ return BitmapFactory.decodeResource(getResources(), bigIcon);
+ }
+ return null;
+ }
+
+ private NotificationManager getManager() {
+ if (manager == null) {
+ manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+ return manager;
+ }
+}
diff --git a/library/src/main/java/com/loveplusplus/update/StorageUtils.java b/library/src/main/java/com/loveplusplus/update/StorageUtils.java
index 9200f26..19e877b 100644
--- a/library/src/main/java/com/loveplusplus/update/StorageUtils.java
+++ b/library/src/main/java/com/loveplusplus/update/StorageUtils.java
@@ -1,88 +1,21 @@
-/*******************************************************************************
- * Copyright 2011-2013 Sergey Tarasevich
- *
- * 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.
- *******************************************************************************/
package com.loveplusplus.update;
-import static android.os.Environment.MEDIA_MOUNTED;
-
-import java.io.File;
-import java.io.IOException;
-
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Environment;
import android.util.Log;
-/**
- * Provides application storage paths
- *
- * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
- * @since 1.0.0
- */
-public final class StorageUtils {
-
- private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";
- //private static final String INDIVIDUAL_DIR_NAME = "uil-images";
- private static final String TAG = "StorageUtils";
-
- private StorageUtils() {
- }
-
- /**
- * Returns application cache directory. Cache directory will be created on SD card
- * ("/Android/data/[app_package_name]/cache") if card is mounted and app has appropriate permission. Else -
- * Android defines cache directory on device's file system.
- *
- * @param context Application context
- * @return Cache {@link File directory}
- */
- public static File getCacheDirectory(Context context) {
- File appCacheDir = null;
- if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
- appCacheDir = getExternalCacheDir(context);
- }
- if (appCacheDir == null) {
- appCacheDir = context.getCacheDir();
- }
- if (appCacheDir == null) {
- Log.w(TAG,"Can't define system cache directory! The app should be re-installed.");
- }
- return appCacheDir;
- }
+import java.io.File;
-
+final class StorageUtils {
- private static File getExternalCacheDir(Context context) {
- File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
- File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
- if (!appCacheDir.exists()) {
- if (!appCacheDir.mkdirs()) {
- Log.w(TAG,"Unable to create external cache directory");
- return null;
- }
- try {
- new File(appCacheDir, ".nomedia").createNewFile();
- } catch (IOException e) {
- Log.i(TAG,"Can't create \".nomedia\" file in application external cache directory");
- }
- }
- return appCacheDir;
- }
+ /**
+ * 获取应用的缓存目录
+ */
+ public static File getCacheDirectory(Context context) {
+ File appCacheDir = context.getCacheDir();
+ if (appCacheDir == null) {
+ Log.w("StorageUtils", "Can't define system cache directory! The app should be re-installed.");
+ }
+ return appCacheDir;
+ }
- private static boolean hasExternalStoragePermission(Context context) {
- int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);
- return perm == PackageManager.PERMISSION_GRANTED;
- }
}
diff --git a/library/src/main/java/com/loveplusplus/update/UpdateApkFileProvider.java b/library/src/main/java/com/loveplusplus/update/UpdateApkFileProvider.java
new file mode 100644
index 0000000..c772e55
--- /dev/null
+++ b/library/src/main/java/com/loveplusplus/update/UpdateApkFileProvider.java
@@ -0,0 +1,11 @@
+package com.loveplusplus.update;
+
+import android.support.v4.content.FileProvider;
+
+/**
+ * @author feicien (ithcheng@gmail.com)
+ * @since 2017-10-19 19:11
+ */
+
+public class UpdateApkFileProvider extends FileProvider {
+}
diff --git a/library/src/main/java/com/loveplusplus/update/UpdateChecker.java b/library/src/main/java/com/loveplusplus/update/UpdateChecker.java
index 80a2bb4..209b8bd 100644
--- a/library/src/main/java/com/loveplusplus/update/UpdateChecker.java
+++ b/library/src/main/java/com/loveplusplus/update/UpdateChecker.java
@@ -1,268 +1,28 @@
package com.loveplusplus.update;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.zip.GZIPInputStream;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.Bundle;
-import android.os.Looper;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.app.NotificationCompat;
import android.util.Log;
-public class UpdateChecker extends Fragment {
-
- //private static final String NOTIFICATION_ICON_RES_ID_KEY = "resId";
- private static final String NOTICE_TYPE_KEY = "type";
- private static final String APP_UPDATE_SERVER_URL = "app_update_server_url";
- //private static final String SUCCESSFUL_CHECKS_REQUIRED_KEY = "nChecks";
- private static final int NOTICE_NOTIFICATION = 2;
- private static final int NOTICE_DIALOG = 1;
- private static final String TAG = "UpdateChecker";
-
- private FragmentActivity mContext;
- private Thread mThread;
- private int mTypeOfNotice;
-
- /**
- * Show a Dialog if an update is available for download. Callable in a
- * FragmentActivity. Number of checks after the dialog will be shown:
- * default, 5
- *
- * @param fragmentActivity
- * Required.
- */
- public static void checkForDialog(FragmentActivity fragmentActivity,String url) {
- FragmentTransaction content = fragmentActivity.getSupportFragmentManager().beginTransaction();
- UpdateChecker updateChecker = new UpdateChecker();
- Bundle args = new Bundle();
- args.putInt(NOTICE_TYPE_KEY, NOTICE_DIALOG);
- args.putString(APP_UPDATE_SERVER_URL,url);
- //args.putInt(SUCCESSFUL_CHECKS_REQUIRED_KEY, 5);
- updateChecker.setArguments(args);
- content.add(updateChecker, null).commit();
- }
-
-
-
- /**
- * Show a Notification if an update is available for download. Callable in a
- * FragmentActivity Specify the number of checks after the notification will
- * be shown.
- *
- * @param fragmentActivity
- * Required.
- */
- public static void checkForNotification(FragmentActivity fragmentActivity,String url) {
- FragmentTransaction content = fragmentActivity.getSupportFragmentManager().beginTransaction();
- UpdateChecker updateChecker = new UpdateChecker();
- Bundle args = new Bundle();
- args.putInt(NOTICE_TYPE_KEY, NOTICE_NOTIFICATION);
- args.putString(APP_UPDATE_SERVER_URL,url);
- //args.putInt(NOTIFICATION_ICON_RES_ID_KEY, notificationIconResId);
- //args.putInt(SUCCESSFUL_CHECKS_REQUIRED_KEY, 5);
- updateChecker.setArguments(args);
- content.add(updateChecker, null).commit();
- }
-
-
- /**
- * This class is a Fragment. Check for the method you have chosen.
- */
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mContext = (FragmentActivity) activity;
- Bundle args = getArguments();
- mTypeOfNotice = args.getInt(NOTICE_TYPE_KEY);
- String url = args.getString(APP_UPDATE_SERVER_URL);
- //mSuccessfulChecksRequired = args.getInt(SUCCESSFUL_CHECKS_REQUIRED_KEY);
- //mNotificationIconResId = args.getInt(NOTIFICATION_ICON_RES_ID_KEY);
- checkForUpdates(url);
- }
-
- /**
- * Heart of the library. Check if an update is available for download
- * parsing the desktop Play Store page of the app
- */
- private void checkForUpdates(final String url) {
- mThread = new Thread() {
- @Override
- public void run() {
- //if (isNetworkAvailable(mContext)) {
-
- String json = sendPost(url);
- if(json!=null){
- parseJson(json);
- }else{
- Log.e(TAG, "can't get app update json");
- }
- //}
- }
-
- };
- mThread.start();
- }
-
- protected String sendPost(String urlStr) {
- HttpURLConnection uRLConnection = null;
- InputStream is = null;
- BufferedReader buffer = null;
- String result = null;
- try {
- URL url = new URL(urlStr);
- uRLConnection = (HttpURLConnection) url.openConnection();
- uRLConnection.setDoInput(true);
- uRLConnection.setDoOutput(true);
- uRLConnection.setRequestMethod("POST");
- uRLConnection.setUseCaches(false);
- uRLConnection.setConnectTimeout(10 * 1000);
- uRLConnection.setReadTimeout(10 * 1000);
- uRLConnection.setInstanceFollowRedirects(false);
- uRLConnection.setRequestProperty("Connection", "Keep-Alive");
- uRLConnection.setRequestProperty("Charset", "UTF-8");
- uRLConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
- uRLConnection.setRequestProperty("Content-Type", "application/json");
-
- uRLConnection.connect();
-
-
- is = uRLConnection.getInputStream();
-
- String content_encode = uRLConnection.getContentEncoding();
-
- if (null != content_encode && !"".equals(content_encode) && content_encode.equals("gzip")) {
- is = new GZIPInputStream(is);
- }
-
- buffer = new BufferedReader(new InputStreamReader(is));
- StringBuilder strBuilder = new StringBuilder();
- String line;
- while ((line = buffer.readLine()) != null) {
- strBuilder.append(line);
- }
- result = strBuilder.toString();
- } catch (Exception e) {
- Log.e(TAG, "http post error", e);
- } finally {
- if(buffer!=null){
- try {
- buffer.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if(is!=null){
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if(uRLConnection!=null){
- uRLConnection.disconnect();
- }
- }
- return result;
- }
-
-
- private void parseJson(String json) {
- mThread.interrupt();
- Looper.prepare();
- try {
-
- JSONObject obj = new JSONObject(json);
- String updateMessage = obj.getString(Constants.APK_UPDATE_CONTENT);
- String apkUrl = obj.getString(Constants.APK_DOWNLOAD_URL);
- int apkCode = obj.getInt(Constants.APK_VERSION_CODE);
-
- int versionCode = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionCode;
-
- if (apkCode > versionCode) {
- if (mTypeOfNotice == NOTICE_NOTIFICATION) {
- showNotification(updateMessage,apkUrl);
- } else if (mTypeOfNotice == NOTICE_DIALOG) {
- showDialog(updateMessage,apkUrl);
- }
- } else {
- //Toast.makeText(mContext, mContext.getString(R.string.app_no_new_update), Toast.LENGTH_SHORT).show();
- }
-
- } catch (PackageManager.NameNotFoundException ignored) {
- } catch (JSONException e) {
- Log.e(TAG, "parse json error", e);
- }
- }
+public class UpdateChecker {
- /**
- * Show dialog
- *
- */
- public void showDialog(String content,String apkUrl) {
- UpdateDialog d = new UpdateDialog();
- Bundle args = new Bundle();
- args.putString(Constants.APK_UPDATE_CONTENT, content);
- args.putString(Constants.APK_DOWNLOAD_URL, apkUrl);
- d.setArguments(args);
- d.show(mContext.getSupportFragmentManager(), null);
- }
- /**
- * Show Notification
- *
- */
- public void showNotification(String content,String apkUrl) {
- android.app.Notification noti;
- Intent myIntent = new Intent(mContext, DownloadService.class);
- myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- myIntent.putExtra(Constants.APK_DOWNLOAD_URL, apkUrl);
- PendingIntent pendingIntent = PendingIntent.getService(mContext, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ public static void checkForDialog(Context context) {
+ if (context != null) {
+ new CheckUpdateTask(context, Constants.TYPE_DIALOG, true).execute();
+ } else {
+ Log.e(Constants.TAG, "The arg context is null");
+ }
+ }
- int smallIcon = mContext.getApplicationInfo().icon;
- noti = new NotificationCompat.Builder(mContext).setTicker(getString(R.string.newUpdateAvailable))
- .setContentTitle(getString(R.string.newUpdateAvailable)).setContentText(content).setSmallIcon(smallIcon)
- .setContentIntent(pendingIntent).build();
- noti.flags = android.app.Notification.FLAG_AUTO_CANCEL;
- NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.notify(0, noti);
- }
+ public static void checkForNotification(Context context) {
+ if (context != null) {
+ new CheckUpdateTask(context, Constants.TYPE_NOTIFICATION, false).execute();
+ } else {
+ Log.e(Constants.TAG, "The arg context is null");
+ }
-
+ }
- /**
- * Check if a network available
- */
- public static boolean isNetworkAvailable(Context context) {
- boolean connected = false;
- ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (cm != null) {
- NetworkInfo ni = cm.getActiveNetworkInfo();
- if (ni != null) {
- connected = ni.isConnected();
- }
- }
- return connected;
- }
-
}
diff --git a/library/src/main/java/com/loveplusplus/update/UpdateDialog.java b/library/src/main/java/com/loveplusplus/update/UpdateDialog.java
index 4740214..84b4640 100644
--- a/library/src/main/java/com/loveplusplus/update/UpdateDialog.java
+++ b/library/src/main/java/com/loveplusplus/update/UpdateDialog.java
@@ -1,42 +1,41 @@
package com.loveplusplus.update;
+import android.app.Activity;
import android.app.AlertDialog;
-import android.app.Dialog;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-public class UpdateDialog extends DialogFragment {
+class UpdateDialog {
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- // Use the Builder class for convenient dialog construction
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.newUpdateAvailable);
- builder.setMessage(getArguments().getString(Constants.APK_UPDATE_CONTENT))
- .setPositiveButton(R.string.dialogPositiveButton, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- // FIRE ZE MISSILES!
- goToDownload();
- dismiss();
- }
- })
- .setNegativeButton(R.string.dialogNegativeButton, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- // User cancelled the dialog
- dismiss();
- }
- });
- // Create the AlertDialog object and return it
- return builder.create();
+ static void show(final Context context, String content, final String downloadUrl) {
+ if (isContextValid(context)) {
+ new AlertDialog.Builder(context)
+ .setTitle(R.string.android_auto_update_dialog_title)
+ .setMessage(content)
+ .setPositiveButton(R.string.android_auto_update_dialog_btn_download, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ goToDownload(context, downloadUrl);
+ }
+ })
+ .setNegativeButton(R.string.android_auto_update_dialog_btn_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ }
+ })
+ .setCancelable(false)
+ .show();
+ }
+ }
+
+ private static boolean isContextValid(Context context) {
+ return context instanceof Activity && !((Activity) context).isFinishing();
}
- private void goToDownload() {
- Intent intent=new Intent(getActivity().getApplicationContext(),DownloadService.class);
- intent.putExtra(Constants.APK_DOWNLOAD_URL, getArguments().getString(Constants.APK_DOWNLOAD_URL));
- getActivity().startService(intent);
+ private static void goToDownload(Context context, String downloadUrl) {
+ Intent intent = new Intent(context.getApplicationContext(), DownloadService.class);
+ intent.putExtra(Constants.APK_DOWNLOAD_URL, downloadUrl);
+ context.startService(intent);
}
}
diff --git a/library/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml
index 21194f4..fcf571e 100644
--- a/library/src/main/res/values/strings.xml
+++ b/library/src/main/res/values/strings.xml
@@ -1,12 +1,19 @@
- 发现新版本
- 立即下载
- 以后再说
- 没有发现新版本
- 正在下载:%1$d%%
- 下载完成,点击安装
-
-
+ 发现新版本
+
+ 发现新版本,点击进行升级
+ 发现新版本,点击进行升级
+
+ 立即下载
+ 以后再说
+
+ 已经是最新版本
+
+ 正在下载:%1$d%%
+
+ 正在检查版本
+
+
\ No newline at end of file
diff --git a/library/src/main/res/xml/update_apk_paths.xml b/library/src/main/res/xml/update_apk_paths.xml
new file mode 100644
index 0000000..7145f3a
--- /dev/null
+++ b/library/src/main/res/xml/update_apk_paths.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/sample/build.gradle b/sample/build.gradle
index 1623408..e218acb 100644
--- a/sample/build.gradle
+++ b/sample/build.gradle
@@ -1,27 +1,60 @@
apply plugin: 'com.android.application'
+
+dependencies {
+ implementation project(':library')
+ implementation "com.android.support:appcompat-v7:27.1.0"
+}
+
+
android {
- compileSdkVersion 21
- buildToolsVersion "21.1.2"
+ compileSdkVersion 27
+ buildToolsVersion '27.0.3'
defaultConfig {
applicationId "com.loveplusplus.update.sample"
- minSdkVersion 8
- targetSdkVersion 21
- versionCode 2
- versionName "1.1"
+ minSdkVersion 14
+ targetSdkVersion 27
+ versionCode 3
+ versionName "1.2"
}
- buildTypes {
+
+ signingConfigs {
+ debug {
+ storeFile file("../extras/demo.jks")
+ storePassword "android"
+ keyAlias "android"
+ keyPassword "android"
+ }
+
release {
+ storeFile file("../extras/demo.jks")
+ storePassword "android"
+ keyAlias "android"
+ keyPassword "android"
+ }
+ }
+
+ buildTypes {
+ debug {
+ debuggable true
+ signingConfig signingConfigs.debug
minifyEnabled false
}
+
+ release {
+ signingConfig signingConfigs.release
+ minifyEnabled true
+ shrinkResources false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
+ zipAlignEnabled true
+ }
}
+
+
lintOptions {
abortOnError false
}
}
-dependencies {
- compile project(':library')
- compile "com.android.support:appcompat-v7:21.0.3"
-}
+
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index 810a179..776a418 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -3,11 +3,6 @@
package="com.loveplusplus.update.sample">
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/sample/src/main/java/com/loveplusplus/update/sample/MainActivity.java b/sample/src/main/java/com/loveplusplus/update/sample/MainActivity.java
index 498e89e..fdc0a38 100644
--- a/sample/src/main/java/com/loveplusplus/update/sample/MainActivity.java
+++ b/sample/src/main/java/com/loveplusplus/update/sample/MainActivity.java
@@ -1,41 +1,45 @@
package com.loveplusplus.update.sample;
import android.os.Bundle;
-import android.support.v4.app.FragmentActivity;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
+import android.widget.TextView;
+import com.loveplusplus.update.AppUtils;
import com.loveplusplus.update.UpdateChecker;
-public class MainActivity extends ActionBarActivity {
+public class MainActivity extends AppCompatActivity {
- protected static final String APP_UPDATE_SERVER_URL = "http://192.168.205.33:8080/Hello/api/update";
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
- Button btn1 = (Button) findViewById(R.id.button1);
- Button btn2 = (Button) findViewById(R.id.button2);
+ Button btn1 = (Button) findViewById(R.id.button1);
+ Button btn2 = (Button) findViewById(R.id.button2);
- btn1.setOnClickListener(new OnClickListener() {
+ btn1.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- UpdateChecker.checkForDialog(MainActivity.this,APP_UPDATE_SERVER_URL);
- }
- });
- btn2.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ UpdateChecker.checkForDialog(MainActivity.this);
+ }
+ });
+ btn2.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- UpdateChecker.checkForNotification(MainActivity.this,APP_UPDATE_SERVER_URL);
- }
- });
+ @Override
+ public void onClick(View v) {
+ UpdateChecker.checkForNotification(MainActivity.this);
+ }
+ });
- }
+
+ TextView textView = (TextView) findViewById(R.id.textView1);
+
+ textView.setText("当前版本信息: versionName = " + AppUtils.getVersionName(this) + " versionCode = " + AppUtils.getVersionCode(this));
+ }
}
diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml
index 9876c6e..980b762 100644
--- a/sample/src/main/res/layout/activity_main.xml
+++ b/sample/src/main/res/layout/activity_main.xml
@@ -1,12 +1,13 @@
-
+ tools:context=".MainActivity">
-
\ No newline at end of file
+
\ No newline at end of file