diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml deleted file mode 100644 index 1d1e989..0000000 --- a/.idea/assetWizardSettings.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 4efb1d7..4f4e779 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/encodings.xml b/.idea/encodings.xml index c2bae49..97626ba 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/markdown-navigator.xml b/.idea/markdown-navigator.xml new file mode 100644 index 0000000..7758d01 --- /dev/null +++ b/.idea/markdown-navigator.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index c0f68ed..e0d5b93 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,27 +5,31 @@ - + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 939e9e3..7b0adca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ language: android jdk: oraclejdk8 before_install: -- yes | sdkmanager "platforms;android-27" +- yes | sdkmanager "platforms;android-28" env: global: - - ANDROID_API_LEVEL=27 - - ANDROID_BUILD_TOOLS_VERSION=27.0.3 + - ANDROID_API_LEVEL=28 + - ANDROID_BUILD_TOOLS_VERSION=28.0.3 - TRAVIS_SECURE_ENV_VARS=true android: diff --git a/LICENSE b/LICENSE index 1861d82..5dc1cac 100644 --- a/LICENSE +++ b/LICENSE @@ -1,23 +1,21 @@ +The MIT License (MIT) - The MIT License (MIT) - Copyright (c) 2017 Jenly Yu - https://github.com/jenly1314 +Copyright (c) 2018 Jenly Yu - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the - following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 01bed42..a73a1f7 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,8 @@ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/mit-license.php) [![Blog](https://img.shields.io/badge/blog-Jenly-9933CC.svg)](http://blog.csdn.net/jenly121) -AppUpdater for Android 是一个专注于App更新一键傻瓜式集成的开源库,主要包括app-updater和app-dialog。 +AppUpdater for Android 是一个专注于App更新,一键傻瓜式集成App版本升级的开源库。(无需担心通知栏适配;无需担心重复点击下载;无需担心App安装等问题;这些AppUpdater都已帮您处理好。) + 核心库主要包括app-updater和app-dialog。 > 下载更新和弹框提示分开,是因为这本来就是两个逻辑。完全独立开来能有效的解耦。 * app-updater 主要负责后台下载更新App,无需担心下载时各种配置相关的细节,一键傻瓜式升级。 * app-dialog 主要是提供常用的Dialog和DialogFragment,简化弹框提示,样式支持高度自定义。 @@ -36,7 +37,7 @@ AppUpdater for Android 是一个专注于App更新一键傻瓜式集成的开源 com.king.app app-updater - 1.0 + 1.0.1 pom @@ -44,27 +45,27 @@ AppUpdater for Android 是一个专注于App更新一键傻瓜式集成的开源 com.king.app app-dialog - 1.0 + 1.0.1 pom ``` ### Gradle: ```gradle //app-updater - compile 'com.king.app:app-updater:1.0' + compile 'com.king.app:app-updater:1.0.1' //app-dialog - compile 'com.king.app:app-dialog:1.0' + compile 'com.king.app:app-dialog:1.0.1' ``` ### Lvy: ```lvy //app-updater - + //app-dialog - + ``` diff --git a/app-dialog/bintray.gradle b/app-dialog/bintray.gradle index 94c2c6a..04e46f0 100644 --- a/app-dialog/bintray.gradle +++ b/app-dialog/bintray.gradle @@ -4,7 +4,8 @@ publish { userOrg = 'jenly'//bintray.com用户名 groupId = 'com.king.app'//jcenter上的路径 artifactId = 'app-dialog'//项目名称 - publishVersion = '1.0'//版本号 + publishVersion = app_version.versionName//版本号 desc = 'AppDialog for Android'//描述 website = 'https://github.com/jenly1314/AppUpdater'//网站 + licences = ['MIT']//开源协议 } \ No newline at end of file diff --git a/app-dialog/build.gradle b/app-dialog/build.gradle index cc80d34..b838768 100644 --- a/app-dialog/build.gradle +++ b/app-dialog/build.gradle @@ -2,16 +2,15 @@ apply plugin: 'com.android.library' apply from: 'bintray.gradle' android { - compileSdkVersion 27 - + compileSdkVersion build_versions.compileSdk + buildToolsVersion build_versions.buildTools defaultConfig { - minSdkVersion 15 - targetSdkVersion 27 - versionCode 1 - versionName "1.0" - + minSdkVersion build_versions.minSdk + targetSdkVersion build_versions.targetSdk + versionCode app_version.versionCode + versionName app_version.versionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -23,15 +22,21 @@ android { } } + lintOptions { + abortOnError false + warning 'InvalidPackage' + } + } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) + testImplementation deps.test.junit + androidTestImplementation deps.test.runner + androidTestImplementation deps.test.espresso + //support + compileOnly deps.support.appcompat - compileOnly 'com.android.support:appcompat-v7:27.1.1' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } diff --git a/app-dialog/src/main/java/com/king/app/dialog/AppDialog.java b/app-dialog/src/main/java/com/king/app/dialog/AppDialog.java index b25f000..8b14d96 100644 --- a/app-dialog/src/main/java/com/king/app/dialog/AppDialog.java +++ b/app-dialog/src/main/java/com/king/app/dialog/AppDialog.java @@ -32,6 +32,12 @@ public enum AppDialog { //------------------------------------------- + /** + * 通过{@link AppDialogConfig} 创建一个视图 + * @param context + * @param config 弹框配置 {@link AppDialogConfig} + * @return + */ public View createAppDialogView(Context context,AppDialogConfig config){ View view = null; if(config!=null){ @@ -99,6 +105,11 @@ public enum AppDialog { //------------------------------------------- + /** + * 显示DialogFragment + * @param fragmentManager + * @return + */ public String showDialogFragment(FragmentManager fragmentManager,AppDialogConfig config){ AppDialogFragment dialogFragment = AppDialogFragment.newInstance(config); String tag = dialogFragment.getTag() !=null ? dialogFragment.getTag() : dialogFragment.getClass().getSimpleName(); @@ -107,6 +118,12 @@ public enum AppDialog { return tag; } + /** + * 显示DialogFragment + * @param fragmentManager + * @param dialogFragment + * @return + */ public String showDialogFragment(FragmentManager fragmentManager,DialogFragment dialogFragment){ String tag = dialogFragment.getTag() !=null ? dialogFragment.getTag() : dialogFragment.getClass().getSimpleName(); showDialogFragment(fragmentManager,dialogFragment,tag); @@ -114,6 +131,13 @@ public enum AppDialog { return tag; } + /** + * 显示DialogFragment + * @param fragmentManager + * @param dialogFragment + * @param tag + * @return + */ public String showDialogFragment(FragmentManager fragmentManager,DialogFragment dialogFragment, String tag) { dialogFragment.show(fragmentManager,tag); mTag = tag; @@ -122,36 +146,82 @@ public enum AppDialog { //------------------------------------------- + /** + * 显示弹框 + * @param context + * @param config 弹框配置 {@link AppDialogConfig} + */ public void showDialog(Context context,AppDialogConfig config){ - showDialog(context,createAppDialogView(context,config)); + showDialog(context,config,true); + } + + /** + * 显示弹框 + * @param context + * @param config 弹框配置 {@link AppDialogConfig} + * @param isCancel 是否可取消(默认为true,false则拦截back键) + */ + public void showDialog(Context context,AppDialogConfig config,boolean isCancel){ + showDialog(context,createAppDialogView(context,config),R.style.app_dialog,DEFAULT_WIDTH_RATIO,isCancel); } + /** + * 显示弹框 + * @param context + * @param contentView 弹框内容视图 + */ public void showDialog(Context context,View contentView){ showDialog(context,contentView,DEFAULT_WIDTH_RATIO); } + /** + * 显示弹框 + * @param context + * @param contentView 弹框内容视图 + * @param isCancel 是否可取消(默认为true,false则拦截back键) + */ public void showDialog(Context context,View contentView,boolean isCancel){ showDialog(context,contentView,R.style.app_dialog,DEFAULT_WIDTH_RATIO,isCancel); } + /** + * 显示弹框 + * @param context + * @param contentView 弹框内容视图 + * @param widthRatio 宽度比例,根据屏幕宽度计算得来 + */ public void showDialog(Context context,View contentView,float widthRatio){ showDialog(context,contentView,widthRatio,true); } + /** + * 显示弹框 + * @param context + * @param contentView 弹框内容视图 + * @param widthRatio 宽度比例,根据屏幕宽度计算得来 + * @param isCancel 是否可取消(默认为true,false则拦截back键) + */ public void showDialog(Context context,View contentView,float widthRatio,boolean isCancel){ showDialog(context,contentView,R.style.app_dialog,widthRatio,isCancel); } + /** + * 显示弹框 + * @param context + * @param contentView 弹框内容视图 + * @param resId Dialog样式 + * @param widthRatio 宽度比例,根据屏幕宽度计算得来 + */ public void showDialog(Context context, View contentView, @StyleRes int resId, float widthRatio){ showDialog(context,contentView,resId,widthRatio,true); } /** - * + * 显示弹框 * @param context - * @param contentView + * @param contentView 弹框内容视图 * @param resId Dialog样式 - * @param widthRatio + * @param widthRatio 宽度比例,根据屏幕宽度计算得来 * @param isCancel 是否可取消(默认为true,false则拦截back键) */ public void showDialog(Context context, View contentView, @StyleRes int resId, float widthRatio,final boolean isCancel){ diff --git a/app-dialog/src/main/java/com/king/app/dialog/AppDialogConfig.java b/app-dialog/src/main/java/com/king/app/dialog/AppDialogConfig.java index cdb4c32..a2f619b 100644 --- a/app-dialog/src/main/java/com/king/app/dialog/AppDialogConfig.java +++ b/app-dialog/src/main/java/com/king/app/dialog/AppDialogConfig.java @@ -8,38 +8,60 @@ import android.view.View; * @author Jenly Jenly */ public class AppDialogConfig { - + /** + * 布局ID + */ private @LayoutRes int layoutId = R.layout.app_dialog; - + /** + * 标题视图ID + */ private @IdRes int titleId = R.id.tvDialogTitle; - + /** + * 内容视图ID + */ private @IdRes int contentId = R.id.tvDialogContent; - + /** + * 取消视图ID(左边按钮) + */ private @IdRes int cancelId = R.id.btnDialogCancel; - + /** + * 确定视图ID(右边按钮) + */ private @IdRes int okId = R.id.btnDialogOK; - + /** + * 按钮中间分割线ID + */ private @IdRes int line = R.id.line; - + /** + * 标题文本 + */ private CharSequence title; - + /** + * 内容文本 + */ private CharSequence content; - + /** + * 取消按钮文本 + */ private CharSequence cancel; - + /** + * 确定按钮文本 + */ private CharSequence ok; - + /** + * 是否隐藏取消按钮,如果取消则底部只显示一个按钮 + */ private boolean isHideCancel; private View.OnClickListener onClickCancel; private View.OnClickListener onClickOk; - public int getLayoutId() { + public @LayoutRes int getLayoutId() { return layoutId; } - public AppDialogConfig setLayoutId(int layoutId) { + public AppDialogConfig setLayoutId(@LayoutRes int layoutId) { this.layoutId = layoutId; return this; } @@ -48,43 +70,43 @@ public class AppDialogConfig { return titleId; } - public AppDialogConfig setTitleId(int titleId) { + public AppDialogConfig setTitleId(@IdRes int titleId) { this.titleId = titleId; return this; } - public int getContentId() { + public @IdRes int getContentId() { return contentId; } - public AppDialogConfig setContentId(int contentId) { + public AppDialogConfig setContentId(@IdRes int contentId) { this.contentId = contentId; return this; } - public int getCancelId() { + public @IdRes int getCancelId() { return cancelId; } - public AppDialogConfig setCancelId(int cancelId) { + public AppDialogConfig setCancelId(@IdRes int cancelId) { this.cancelId = cancelId; return this; } - public int getOkId() { + public @IdRes int getOkId() { return okId; } - public AppDialogConfig setOkId(int okId) { + public AppDialogConfig setOkId(@IdRes int okId) { this.okId = okId; return this; } - public int getLine() { + public @IdRes int getLine() { return line; } - public AppDialogConfig setLine(int line) { + public AppDialogConfig setLine(@IdRes int line) { this.line = line; return this; } diff --git a/app-dialog/src/main/java/com/king/app/dialog/fragment/BaseDialogFragment.java b/app-dialog/src/main/java/com/king/app/dialog/fragment/BaseDialogFragment.java index 4e9b2b3..50863b6 100644 --- a/app-dialog/src/main/java/com/king/app/dialog/fragment/BaseDialogFragment.java +++ b/app-dialog/src/main/java/com/king/app/dialog/fragment/BaseDialogFragment.java @@ -1,5 +1,7 @@ package com.king.app.dialog.fragment; +import android.app.Dialog; +import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; @@ -11,13 +13,18 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; +import android.view.WindowManager; import android.widget.TextView; +import com.king.app.dialog.R; + /** * @author Jenly Jenly */ public abstract class BaseDialogFragment extends DialogFragment { + protected static final float DEFAULT_WIDTH_RATIO = 0.85f; + private View mRootView; @Nullable @@ -31,6 +38,21 @@ public abstract class BaseDialogFragment extends DialogFragment { return mRootView; } + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + super.getDialog().getWindow().getAttributes().windowAnimations = R.style.app_dialog_animation; + getDialog().setCanceledOnTouchOutside(false); + setDialogWindow(getContext(),getDialog(),DEFAULT_WIDTH_RATIO); + } + + private void setDialogWindow(Context context, Dialog dialog, float widthRatio){ + Window window = dialog.getWindow(); + WindowManager.LayoutParams lp = window.getAttributes(); + lp.width = (int)(context.getResources().getDisplayMetrics().widthPixels * widthRatio); + window.setAttributes(lp); + } + protected View getRootView(){ return mRootView; } diff --git a/app-dialog/src/main/res/drawable/app_dialog_bg.xml b/app-dialog/src/main/res/drawable/app_dialog_bg.xml index 0c984ca..ea1fd30 100644 --- a/app-dialog/src/main/res/drawable/app_dialog_bg.xml +++ b/app-dialog/src/main/res/drawable/app_dialog_bg.xml @@ -4,9 +4,9 @@ + android:bottomLeftRadius="@dimen/app_dialog_radius" + android:bottomRightRadius="@dimen/app_dialog_radius" + android:topLeftRadius="@dimen/app_dialog_radius" + android:topRightRadius="@dimen/app_dialog_radius" /> \ No newline at end of file diff --git a/app-dialog/src/main/res/layout/app_dialog.xml b/app-dialog/src/main/res/layout/app_dialog.xml index f5431f5..f5d09a8 100644 --- a/app-dialog/src/main/res/layout/app_dialog.xml +++ b/app-dialog/src/main/res/layout/app_dialog.xml @@ -14,7 +14,7 @@ android:minHeight="40dp" android:padding="6dp" android:lines="1" - android:textSize="16sp" + android:textSize="@dimen/app_dialog_title_text_size" android:textColor="@color/app_dialog_title_color" android:text="@string/app_dialog_title"/> diff --git a/app-dialog/src/main/res/values/colors.xml b/app-dialog/src/main/res/values/colors.xml index 9bd2129..7605999 100644 --- a/app-dialog/src/main/res/values/colors.xml +++ b/app-dialog/src/main/res/values/colors.xml @@ -1,10 +1,13 @@ + #FF4081 + #333333 #666666 #333333 - #FF4081 + @color/colorAccent #d2d2d2 + diff --git a/app-dialog/src/main/res/values/dimens.xml b/app-dialog/src/main/res/values/dimens.xml index 6e2c5b3..90f2a0a 100644 --- a/app-dialog/src/main/res/values/dimens.xml +++ b/app-dialog/src/main/res/values/dimens.xml @@ -1,5 +1,10 @@ - 0.4dp + 0.5dp + 10dp + + 16sp + 16sp + 18sp \ No newline at end of file diff --git a/app-updater/bintray.gradle b/app-updater/bintray.gradle index 68d83b5..75eff66 100644 --- a/app-updater/bintray.gradle +++ b/app-updater/bintray.gradle @@ -5,7 +5,8 @@ publish { userOrg = 'jenly'//bintray.com用户名 groupId = 'com.king.app'//jcenter上的路径 artifactId = 'app-updater'//项目名称 - publishVersion = '1.0'//版本号 + publishVersion = app_version.versionName//版本号 desc = 'AppUpdater for Android'//描述 website = 'https://github.com/jenly1314/AppUpdater'//网站 + licences = ['MIT']//开源协议 } \ No newline at end of file diff --git a/app-updater/build.gradle b/app-updater/build.gradle index 2d08d8b..952d0f8 100644 --- a/app-updater/build.gradle +++ b/app-updater/build.gradle @@ -2,16 +2,15 @@ apply plugin: 'com.android.library' apply from: 'bintray.gradle' android { - compileSdkVersion 27 - + compileSdkVersion build_versions.compileSdk + buildToolsVersion build_versions.buildTools defaultConfig { - minSdkVersion 15 - targetSdkVersion 27 - versionCode 1 - versionName "1.0" - + minSdkVersion build_versions.minSdk + targetSdkVersion build_versions.targetSdk + versionCode app_version.versionCode + versionName app_version.versionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -23,13 +22,19 @@ android { } } + lintOptions { + abortOnError false + warning 'InvalidPackage' + } + } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) + testImplementation deps.test.junit + androidTestImplementation deps.test.runner + androidTestImplementation deps.test.espresso + //support + compileOnly deps.support.appcompat - compileOnly 'com.android.support:appcompat-v7:27.1.1' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } diff --git a/app-updater/src/main/java/com/king/app/updater/AppUpdater.java b/app-updater/src/main/java/com/king/app/updater/AppUpdater.java index 9b6228b..877465b 100644 --- a/app-updater/src/main/java/com/king/app/updater/AppUpdater.java +++ b/app-updater/src/main/java/com/king/app/updater/AppUpdater.java @@ -9,6 +9,7 @@ import android.os.IBinder; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.text.TextUtils; +import android.util.Log; import com.king.app.updater.callback.UpdateCallback; import com.king.app.updater.constant.Constants; @@ -21,13 +22,21 @@ import com.king.app.updater.util.PermissionUtils; * @author Jenly Jenly */ public class AppUpdater { - + /** + * {@link #mContext}不强制要求是{@link Activity},但能传{@link Activity}尽量传。AppUpdater本应该只专注于App更新,尽量不涉及动态权限相关的处理。如果mContext传的是{@link Activity},则默认会校验一次动态权限。 + */ private Context mContext; - + /** + * 配置信息 + */ private UpdateConfig mConfig; - + /** + * 更新回调 + */ private UpdateCallback mCallback; - + /** + * http管理接口,可自定义实现。如:使用okHttp + */ private IHttpManager mHttpManager; private ServiceConnection mServiceConnection; @@ -59,10 +68,15 @@ public class AppUpdater { */ public void start(){ if(mConfig!=null && !TextUtils.isEmpty(mConfig.getUrl())){ - //mContext不强制要求是Activity,能传Activity尽量传。AppUpdater本应该只专注于App更新,尽量不涉及动态权限相关的处理。如果mContext不强制要求是Activity是Activity默认会优先校验一次动态权限。 + //如果mContext是Activity,则默认会校验一次动态权限。 if(mContext instanceof Activity){ PermissionUtils.INSTANCE.verifyReadAndWritePermissions((Activity) mContext,Constants.RE_CODE_STORAGE_PERMISSION); } + + if(mConfig.isShowNotification() && !PermissionUtils.INSTANCE.isNotificationEnabled(mContext)){ + Log.w(Constants.TAG,"Notification permission not enabled."); + } + startDownloadService(); }else{ throw new NullPointerException("url = null"); diff --git a/app-updater/src/main/java/com/king/app/updater/UpdateConfig.java b/app-updater/src/main/java/com/king/app/updater/UpdateConfig.java index 3152e9e..7e25b04 100644 --- a/app-updater/src/main/java/com/king/app/updater/UpdateConfig.java +++ b/app-updater/src/main/java/com/king/app/updater/UpdateConfig.java @@ -1,6 +1,7 @@ package com.king.app.updater; +import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.DrawableRes; @@ -24,20 +25,35 @@ public class UpdateConfig implements Parcelable { */ private String mFilename; + /** + * 是否显示通知栏 + */ private boolean isShowNotification = true; /** * 下载完成后是否自动弹出安装 */ private boolean isInstallApk = true; - + /** + * 通知栏图标:默认取app图标 + */ private int mNotificationIcon; + /** + * 通知栏ID + */ private int mNotificationId = Constants.DEFAULT_NOTIFICATION_ID; + /** + * 通知栏渠道ID + */ private String mChannelId; - + /** + * 通知栏渠道名称 + */ private String mChannelName; - + /** + * 默认{@link Context#getPackageName() + ".fileProvider"} + */ private String mAuthority; /** * 下载失败是否支持点击通知栏重复下载 diff --git a/app-updater/src/main/java/com/king/app/updater/service/DownloadService.java b/app-updater/src/main/java/com/king/app/updater/service/DownloadService.java index 6204bf7..236cee2 100644 --- a/app-updater/src/main/java/com/king/app/updater/service/DownloadService.java +++ b/app-updater/src/main/java/com/king/app/updater/service/DownloadService.java @@ -77,7 +77,7 @@ public class DownloadService extends Service { startDownload(config,null,null); } }else{ - Log.w(Constants.TAG,"已经在下载中,请勿重复下载。"); + Log.w(Constants.TAG,"Please do not repeat the download."); } } @@ -105,7 +105,7 @@ public class DownloadService extends Service { } if(isDownloading){ - Log.w(Constants.TAG,"已经在下载中,请勿重复下载。"); + Log.w(Constants.TAG,"Please do not repeat the download."); return; } @@ -154,6 +154,9 @@ public class DownloadService extends Service { return context.getCacheDir().getAbsolutePath(); } + /** + * 停止服务 + */ private void stopService(){ mCount = 0; stopSelf(); @@ -300,17 +303,9 @@ public class DownloadService extends Service { } } - - @Override - public boolean onUnbind(Intent intent) { - Log.d(Constants.TAG,"onUnbind"); - return super.onUnbind(intent); - } - @Override public void onDestroy() { isDownloading = false; - Log.d(Constants.TAG,"onDestroy"); super.onDestroy(); } diff --git a/app-updater/src/main/java/com/king/app/updater/util/PermissionUtils.java b/app-updater/src/main/java/com/king/app/updater/util/PermissionUtils.java index c5a8807..f6cd5b8 100644 --- a/app-updater/src/main/java/com/king/app/updater/util/PermissionUtils.java +++ b/app-updater/src/main/java/com/king/app/updater/util/PermissionUtils.java @@ -1,15 +1,24 @@ package com.king.app.updater.util; import android.Manifest; +import android.annotation.TargetApi; import android.app.Activity; +import android.app.AppOpsManager; +import android.app.NotificationManager; +import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.os.Build; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + /** * @author Jenly Jenly */ -public enum PermissionUtils { +public enum PermissionUtils { INSTANCE; @@ -18,12 +27,18 @@ public enum PermissionUtils { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE}; + /** + * 校验权限 + * @param activity + * @param requestCode + * @return + */ public boolean verifyReadAndWritePermissions(@NonNull Activity activity,int requestCode){ int readResult = checkPermission(activity,Manifest.permission.READ_EXTERNAL_STORAGE); int writeResult = checkPermission(activity,Manifest.permission.WRITE_EXTERNAL_STORAGE); int readPhoneState = checkPermission(activity,Manifest.permission.READ_PHONE_STATE); - if( readResult != PackageManager.PERMISSION_GRANTED || writeResult != PackageManager.PERMISSION_GRANTED || readPhoneState != PackageManager.PERMISSION_GRANTED){ + if(readResult != PackageManager.PERMISSION_GRANTED || writeResult != PackageManager.PERMISSION_GRANTED || readPhoneState != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(activity,PERMISSIONS_STORAGE,requestCode); return false; } @@ -33,4 +48,45 @@ public enum PermissionUtils { public int checkPermission(@NonNull Activity activity,@NonNull String permission){ return ActivityCompat.checkSelfPermission(activity,permission); } + + /** + * 获取通知权限 + * @param context + */ + public boolean isNotificationEnabled(Context context) { + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); + if (notificationManager.getImportance() == NotificationManager.IMPORTANCE_NONE) { + return false; + } + } + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ + String CHECK_OP_NO_THROW = "checkOpNoThrow"; + String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION"; + + AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + ApplicationInfo appInfo = context.getApplicationInfo(); + String pkg = context.getApplicationContext().getPackageName(); + int uid = appInfo.uid; + + try { + Class appOpsClass = Class.forName(AppOpsManager.class.getName()); + Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String.class); + Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION); + + int value = (Integer) opPostNotificationValue.get(Integer.class); + return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED); + + } catch (Exception e) { + e.printStackTrace(); + } + + return false; + } + + return true; + } + } diff --git a/app/build.gradle b/app/build.gradle index 808d354..414c9d9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,15 +1,19 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 27 + compileSdkVersion build_versions.compileSdk + buildToolsVersion build_versions.buildTools + defaultConfig { applicationId "com.king.appupdater" - minSdkVersion 15 - targetSdkVersion 27 - versionCode 1 - versionName "1.0" + minSdkVersion build_versions.minSdk + targetSdkVersion build_versions.targetSdk + versionCode app_version.versionCode + versionName app_version.versionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { release { minifyEnabled false @@ -20,11 +24,13 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support.constraint:constraint-layout:1.1.2' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + testImplementation deps.test.junit + androidTestImplementation deps.test.runner + androidTestImplementation deps.test.espresso + //support + implementation deps.support.appcompat + implementation deps.support.constraintlayout + implementation project(':app-updater') implementation project(':app-dialog') } diff --git a/app/release/app-release.apk b/app/release/app-release.apk index c702d17..322dec7 100644 Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ diff --git a/app/release/output.json b/app/release/output.json index 9f0c959..bd004be 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":2,"versionName":"1.0.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/src/main/java/com/king/appupdater/MainActivity.java b/app/src/main/java/com/king/appupdater/MainActivity.java index fe60dea..ae549e6 100644 --- a/app/src/main/java/com/king/appupdater/MainActivity.java +++ b/app/src/main/java/com/king/appupdater/MainActivity.java @@ -29,7 +29,6 @@ public class MainActivity extends AppCompatActivity { public final String TAG = this.getClass().getSimpleName(); private String mUrl = "https://raw.githubusercontent.com/jenly1314/AppUpdater/master/app/release/app-release.apk"; -// private String mUrl = "https://pro-app-qn.fir.im/1ddfe25998acd3d861d746101e6e079e1611b666.apk?attname=app-release.apk_1.2.apk"; private ProgressBar progressBar; @@ -154,11 +153,7 @@ public class MainActivity extends AppCompatActivity { .setOnClickOk(new View.OnClickListener() { @Override public void onClick(View v) { - new AppUpdater.Builder() - .serUrl(mUrl) - .setFilename("AppUpdater.apk") - .build(getContext()) - .start(); + new AppUpdater(getContext(),mUrl).start(); AppDialog.INSTANCE.dismissDialog(); } }); @@ -180,14 +175,12 @@ public class MainActivity extends AppCompatActivity { public void onClick(View v) { new AppUpdater.Builder() .serUrl(mUrl) - .setFilename(Environment.getExternalStorageDirectory() + "/.AppUpdater") - .setFilename("AppUpdater.apk") .build(getContext()) .start(); AppDialog.INSTANCE.dismissDialog(); } }); - AppDialog.INSTANCE.showDialog(getContext(),AppDialog.INSTANCE.createAppDialogView(getContext(),config),false); + AppDialog.INSTANCE.showDialog(getContext(),AppDialog.INSTANCE.createAppDialogView(getContext(),config),true); } /** @@ -214,6 +207,7 @@ public class MainActivity extends AppCompatActivity { public void onClick(View v) { new AppUpdater.Builder() .serUrl(mUrl) + .setFilename(Environment.getExternalStorageDirectory() + "/.AppUpdater") .setFilename("AppUpdater.apk") .build(getContext()) .start(); diff --git a/build.gradle b/build.gradle index fee5b64..97c430d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,17 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - + + apply from: 'versions.gradle' + addRepos(repositories) repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.2' + classpath 'com.android.tools.build:gradle:3.2.1' - classpath 'com.novoda:bintray-release:0.8.1' + classpath 'com.novoda:bintray-release:0.9' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -33,5 +35,8 @@ allprojects { charSet 'UTF-8' links "http://docs.oracle.com/javase/8/docs/api" } + + options.addStringOption('Xdoclint:none', '-quiet') + failOnError false } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8ac7ca2..46f9ecd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Jun 25 18:24:14 CST 2018 +#Thu Jan 10 09:17:54 CST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/settings.gradle b/settings.gradle index c0a46f6..c9fbda6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':app-updater', ':app-updater', ':app-dialog' +include ':app', ':app-updater', ':app-dialog' diff --git a/versions.gradle b/versions.gradle new file mode 100644 index 0000000..b2180eb --- /dev/null +++ b/versions.gradle @@ -0,0 +1,49 @@ +//App +def app_version = [:] +app_version.versionCode = 2 +app_version.versionName = "1.0.1" +ext.app_version = app_version + +//build version +def build_versions = [:] +build_versions.minSdk = 15 +build_versions.targetSdk = 28 +build_versions.compileSdk = 28 +build_versions.buildTools = "28.0.3" +ext.build_versions = build_versions + +// App dependencies +def versions = [:] +//support +versions.supportLibrary = "28.0.0" +versions.constraintLayout = "1.1.3" + +//test +versions.junit = "4.12" +versions.runner = "1.0.2" +versions.espresso = "3.0.2" +ext.versions = versions + +ext.deps = [:] + +//support +def support = [:] +support.appcompat = "com.android.support:appcompat-v7:$versions.supportLibrary" +support.constraintlayout = "com.android.support.constraint:constraint-layout:$versions.constraintLayout" +deps.support = support + +//test +def test = [:] +test.junit = "junit:junit:$versions.junit" +test.runner = "com.android.support.test:runner:$versions.runner" +test.espresso = "com.android.support.test.espresso:espresso-core:$versions.espresso" +deps.test = test + + +ext.deps = deps + +def addRepos(RepositoryHandler handler) { + handler.google() + handler.jcenter() +} +ext.addRepos = this.&addRepos \ No newline at end of file