Repository files navigation

CheckUpdateLibrary

检查更新库

一个Android专用检查软件更新的库
##效果图: 非强制更新:
非强制更新
强制更新:
强制更新 ##简介:
####该库的功能:
1,get/post方式检查更新,下载更新操作
2,有更新时,弹出升级对话框
3,可以根据各种参数设置是否强制更新,是否在通知栏显示进度条等,具体用法请参考demo
4,该库同时提供相关工具类,方便下载和安装软件等操作
####该库的特点: 1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary具有超强扩展性,下面会单独一个标题细说.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
##扩展性:
CheckUpdateLibrary具有超强扩展性:
1,CheckUpdateLibrary有两种方式进行检查更新,对应着两种回调方式:CheckUpdateCallback和CheckUpdateCallback2,前者为了使用方便,所以需要开发者必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,而如果开发者想完全自定义实体,那么可以使用后者,即CheckUpdateCallback2,但是需要自己进行判断是否软件有更新.
2,可自定义Dialog.虽然CheckUpdateLibrary中提供了两种Dialog:ForceUpdateDialog和UpdateDialg用来展示强制更新和非强制更新对话框,但还是会有很多开发者想使用自己自定义的Dialog,然后借助于CheckUpdateLibrary中的后台下载功能和通知展示功能来实现后台下载,而CheckUpdateLibrary也考虑到开发者的这种需求,开发者只需要继承CheckUpdateLibrary中的BaseService,然后实现相关方法即可实现自己的需求,具体的使用方式请参考下面的教程.
##用法: ####Android Studio添加依赖:

 dependencies { compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.3' }

####Eclipse:
使用eclipse的小伙伴只能下载library文件,然后引入到项目中使用了

####检查更新:

Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", newCheckUpdateCallback() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult, booleanhasUpdate) {
//result:服务端返回的jsonCheckUpdateInfocheckUpdateInfo = newGson().fromJson(result, CheckUpdateInfo.class);
//有更新,显示dialog等if (hasUpdate) {
//强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可if (checkUpdateInfo.getIsForceUpdate() == 0) {
//show ForceUpdateDialog
}
//非强制更新else {
//show UpdateDialog
}
} else {
//无更新,提示已是最新版等
}
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage, interrorCode) {
//failureMessage:一般为try{}catch(){}捕获的异常信息//errorCode:暂时没什么用
}
});

Q.checkUpdate("post", "checkUpdateUrl", newCheckUpdateCallback2() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult) {
//result:服务端返回的json,需要自己判断有无更新,解析成自己的实体类进行判断是否有版本更新
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage) {
}
}); 

####强制更新对话框:

ForceUpdateDialogdialog = newForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
.show();

####非强制更新对话框:

UpdateDialogdialog = newUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName())
.show();

####使用自定义Dialog:
#####对于强制更新方式: **step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**在自定义的dialog中,比如button1是用来下载文件的,那么可以使用HttpRequest类中提供的download方法,然后在各个回调中实现自己的逻辑,比如进度条监听,下载完成后安装等,示例代码如下:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于500ms都return;if (System.currentTimeMillis() - timeRange < 500) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
if ("点击安装".equals(button1.getText().toString().trim())) {
Filefile = newFile(mFilePath, mFileName);
if (file.exists()) {
ApplicationUtil.installApk(context, file);
} else {
download();
}
return;
}
download();
}
}); privatevoiddownload() {
forceUpdateProgress.setVisibility(View.VISIBLE);
HttpRequest.download(mDownloadUrl, mFilePath, mFileName, newDownloadCallback() {
@OverridepublicvoidonDownloadSuccess(Filefile) {
button1.setEnabled(true);
button1.setText("点击安装");
ApplicationUtil.installApk(context, file);
}
@OverridepublicvoidonProgress(longcurrentProgress, longtotalProgress) {
button1.setEnabled(false);
button1.setText("正在下载");
forceUpdateProgress.setProgress((int) (currentProgress));
forceUpdateProgress.setMax((int) (totalProgress));
}
@OverridepublicvoidonDownloadFailure(StringfailureMessage) {
button1.setEnabled(true);
button1.setText("重新下载");
}
});
} 

#####对于非强制更新方式:
**step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**继承CheckUpdateLibrary中的BaseService,实现相关方法,其中Service中自带的方法onStartCommand必须重写,一会说为什么.
示例代码如下:

publicclassDownloadServiceextendsBaseService {
privateinticonResId;
privateStringappName;
privateIntentmIntent;
@Nullable@OverridepublicIBinderonBind(Intentintent) {
returnnull;
}
@OverridepublicintonStartCommand(Intentintent, intflags, intstartId) {
if (null == intent) {
returnSTART_NOT_STICKY;
}
mIntent = intent;
appName = intent.getStringExtra("appName");
iconResId = intent.getIntExtra("iconResId", -1);
if (iconResId == -1) {
iconResId = R.drawable.icon_downloading;
}
download(intent.getStringExtra("downloadUrl"), intent.getStringExtra("filePath"), intent.getStringExtra("fileName"), true);
returnsuper.onStartCommand(intent, flags, startId);
}
@OverridepublicvoiddownloadFailure(StringfailureMessage) {
NotificationUtil.showDownloadFailureNotification(this, mIntent, iconResId, appName, "下载失败,点击重新下载", true);
}
@OverridepublicvoiddownloadSuccess(Filefile) {
NotificationUtil.showDownloadSuccessNotification(this, file, iconResId, appName, "下载完成,点击安装", false);
}
@Overridepublicvoiddownloading(intcurrentProgress, inttotalProgress) {
NotificationUtil.showDownloadingNotification(this, currentProgress, totalProgress, iconResId, appName, false);
}
}

step3:在自定义的dialog中,比如button1是用来下载文件的,那么可以这么写:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于1s都return;if (System.currentTimeMillis() - timeRange < 1000) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
Intentintent = newIntent(context, DownloadService.class);
intent.putExtra("downloadUrl", mDownloadUrl);
intent.putExtra("filePath", mFilePath);
intent.putExtra("fileName", mFileName);
intent.putExtra("iconResId", mIconResId);
intent.putExtra("isShowProgress", isShowProgress);
intent.putExtra("appName", mAppName);
context.startService(intent);
dismiss();
Toast.makeText(context, "正在后台为您下载", Toast.LENGTH_SHORT).show();
}
}); 

ok,到此,自定义非强制更新Dialog的后台下载功能就实现了.
######下面说一说为什么必须要重写onStartCommand方法,主要有两点原因:
**1,**其实从上面的代码也可以看出,启动Service采用的是context.startService(intent);方法,而不是bind方法,所以在Service中接收intent必须重写onStartCommand方法才行.
**2,**如果下载失败时,点击通知是可以重新下载应用的,其中应用到PendingIntent.getService()方法,而该方法启动Service就是通过context.startService(intent);方式启动的,所以从这一点出发,仍然必须重写onStartCommand方法才行.
##Issues
各位小伙伴使用过程中有任何问题或发现什么bug或有什么好的意见或建议,请通过上面的issue提交给我,谢谢啦~~
另外,跪求Star或Fork,这是对开发者最好的激励!!!

About

AndroidApp检查更新库

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

CheckUpdateLibrary

检查更新库

一个Android专用检查软件更新的库
##效果图: 非强制更新:
非强制更新
强制更新:
强制更新 ##简介:
####该库的功能:
1,get/post方式检查更新,下载更新操作
2,有更新时,弹出升级对话框
3,可以根据各种参数设置是否强制更新,是否在通知栏显示进度条等,具体用法请参考demo
4,该库同时提供相关工具类,方便下载和安装软件等操作
####该库的特点: 1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary具有超强扩展性,下面会单独一个标题细说.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
##扩展性:
CheckUpdateLibrary具有超强扩展性:
1,CheckUpdateLibrary有两种方式进行检查更新,对应着两种回调方式:CheckUpdateCallback和CheckUpdateCallback2,前者为了使用方便,所以需要开发者必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,而如果开发者想完全自定义实体,那么可以使用后者,即CheckUpdateCallback2,但是需要自己进行判断是否软件有更新.
2,可自定义Dialog.虽然CheckUpdateLibrary中提供了两种Dialog:ForceUpdateDialog和UpdateDialg用来展示强制更新和非强制更新对话框,但还是会有很多开发者想使用自己自定义的Dialog,然后借助于CheckUpdateLibrary中的后台下载功能和通知展示功能来实现后台下载,而CheckUpdateLibrary也考虑到开发者的这种需求,开发者只需要继承CheckUpdateLibrary中的BaseService,然后实现相关方法即可实现自己的需求,具体的使用方式请参考下面的教程.
##用法: ####Android Studio添加依赖:

 dependencies { compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.3' }

####Eclipse:
使用eclipse的小伙伴只能下载library文件,然后引入到项目中使用了

####检查更新:

Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", newCheckUpdateCallback() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult, booleanhasUpdate) {
//result:服务端返回的jsonCheckUpdateInfocheckUpdateInfo = newGson().fromJson(result, CheckUpdateInfo.class);
//有更新,显示dialog等if (hasUpdate) {
//强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可if (checkUpdateInfo.getIsForceUpdate() == 0) {
//show ForceUpdateDialog
}
//非强制更新else {
//show UpdateDialog
}
} else {
//无更新,提示已是最新版等
}
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage, interrorCode) {
//failureMessage:一般为try{}catch(){}捕获的异常信息//errorCode:暂时没什么用
}
});

Q.checkUpdate("post", "checkUpdateUrl", newCheckUpdateCallback2() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult) {
//result:服务端返回的json,需要自己判断有无更新,解析成自己的实体类进行判断是否有版本更新
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage) {
}
}); 

####强制更新对话框:

ForceUpdateDialogdialog = newForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
.show();

####非强制更新对话框:

UpdateDialogdialog = newUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName())
.show();

####使用自定义Dialog:
#####对于强制更新方式: **step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**在自定义的dialog中,比如button1是用来下载文件的,那么可以使用HttpRequest类中提供的download方法,然后在各个回调中实现自己的逻辑,比如进度条监听,下载完成后安装等,示例代码如下:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于500ms都return;if (System.currentTimeMillis() - timeRange < 500) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
if ("点击安装".equals(button1.getText().toString().trim())) {
Filefile = newFile(mFilePath, mFileName);
if (file.exists()) {
ApplicationUtil.installApk(context, file);
} else {
download();
}
return;
}
download();
}
}); privatevoiddownload() {
forceUpdateProgress.setVisibility(View.VISIBLE);
HttpRequest.download(mDownloadUrl, mFilePath, mFileName, newDownloadCallback() {
@OverridepublicvoidonDownloadSuccess(Filefile) {
button1.setEnabled(true);
button1.setText("点击安装");
ApplicationUtil.installApk(context, file);
}
@OverridepublicvoidonProgress(longcurrentProgress, longtotalProgress) {
button1.setEnabled(false);
button1.setText("正在下载");
forceUpdateProgress.setProgress((int) (currentProgress));
forceUpdateProgress.setMax((int) (totalProgress));
}
@OverridepublicvoidonDownloadFailure(StringfailureMessage) {
button1.setEnabled(true);
button1.setText("重新下载");
}
});
} 

#####对于非强制更新方式:
**step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**继承CheckUpdateLibrary中的BaseService,实现相关方法,其中Service中自带的方法onStartCommand必须重写,一会说为什么.
示例代码如下:

publicclassDownloadServiceextendsBaseService {
privateinticonResId;
privateStringappName;
privateIntentmIntent;
@Nullable@OverridepublicIBinderonBind(Intentintent) {
returnnull;
}
@OverridepublicintonStartCommand(Intentintent, intflags, intstartId) {
if (null == intent) {
returnSTART_NOT_STICKY;
}
mIntent = intent;
appName = intent.getStringExtra("appName");
iconResId = intent.getIntExtra("iconResId", -1);
if (iconResId == -1) {
iconResId = R.drawable.icon_downloading;
}
download(intent.getStringExtra("downloadUrl"), intent.getStringExtra("filePath"), intent.getStringExtra("fileName"), true);
returnsuper.onStartCommand(intent, flags, startId);
}
@OverridepublicvoiddownloadFailure(StringfailureMessage) {
NotificationUtil.showDownloadFailureNotification(this, mIntent, iconResId, appName, "下载失败,点击重新下载", true);
}
@OverridepublicvoiddownloadSuccess(Filefile) {
NotificationUtil.showDownloadSuccessNotification(this, file, iconResId, appName, "下载完成,点击安装", false);
}
@Overridepublicvoiddownloading(intcurrentProgress, inttotalProgress) {
NotificationUtil.showDownloadingNotification(this, currentProgress, totalProgress, iconResId, appName, false);
}
}

step3:在自定义的dialog中,比如button1是用来下载文件的,那么可以这么写:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于1s都return;if (System.currentTimeMillis() - timeRange < 1000) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
Intentintent = newIntent(context, DownloadService.class);
intent.putExtra("downloadUrl", mDownloadUrl);
intent.putExtra("filePath", mFilePath);
intent.putExtra("fileName", mFileName);
intent.putExtra("iconResId", mIconResId);
intent.putExtra("isShowProgress", isShowProgress);
intent.putExtra("appName", mAppName);
context.startService(intent);
dismiss();
Toast.makeText(context, "正在后台为您下载", Toast.LENGTH_SHORT).show();
}
}); 

ok,到此,自定义非强制更新Dialog的后台下载功能就实现了.
######下面说一说为什么必须要重写onStartCommand方法,主要有两点原因:
**1,**其实从上面的代码也可以看出,启动Service采用的是context.startService(intent);方法,而不是bind方法,所以在Service中接收intent必须重写onStartCommand方法才行.
**2,**如果下载失败时,点击通知是可以重新下载应用的,其中应用到PendingIntent.getService()方法,而该方法启动Service就是通过context.startService(intent);方式启动的,所以从这一点出发,仍然必须重写onStartCommand方法才行.
##Issues
各位小伙伴使用过程中有任何问题或发现什么bug或有什么好的意见或建议,请通过上面的issue提交给我,谢谢啦~~
另外,跪求Star或Fork,这是对开发者最好的激励!!!

About

AndroidApp检查更新库

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

CheckUpdateLibrary

检查更新库

一个Android专用检查软件更新的库
##效果图: 非强制更新:
非强制更新
强制更新:
强制更新 ##简介:
####该库的功能:
1,get/post方式检查更新,下载更新操作
2,有更新时,弹出升级对话框
3,可以根据各种参数设置是否强制更新,是否在通知栏显示进度条等,具体用法请参考demo
4,该库同时提供相关工具类,方便下载和安装软件等操作
####该库的特点: 1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary具有超强扩展性,下面会单独一个标题细说.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
##扩展性:
CheckUpdateLibrary具有超强扩展性:
1,CheckUpdateLibrary有两种方式进行检查更新,对应着两种回调方式:CheckUpdateCallback和CheckUpdateCallback2,前者为了使用方便,所以需要开发者必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,而如果开发者想完全自定义实体,那么可以使用后者,即CheckUpdateCallback2,但是需要自己进行判断是否软件有更新.
2,可自定义Dialog.虽然CheckUpdateLibrary中提供了两种Dialog:ForceUpdateDialog和UpdateDialg用来展示强制更新和非强制更新对话框,但还是会有很多开发者想使用自己自定义的Dialog,然后借助于CheckUpdateLibrary中的后台下载功能和通知展示功能来实现后台下载,而CheckUpdateLibrary也考虑到开发者的这种需求,开发者只需要继承CheckUpdateLibrary中的BaseService,然后实现相关方法即可实现自己的需求,具体的使用方式请参考下面的教程.
##用法: ####Android Studio添加依赖:

 dependencies { compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.3' }

####Eclipse:
使用eclipse的小伙伴只能下载library文件,然后引入到项目中使用了

####检查更新:

Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", newCheckUpdateCallback() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult, booleanhasUpdate) {
//result:服务端返回的jsonCheckUpdateInfocheckUpdateInfo = newGson().fromJson(result, CheckUpdateInfo.class);
//有更新,显示dialog等if (hasUpdate) {
//强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可if (checkUpdateInfo.getIsForceUpdate() == 0) {
//show ForceUpdateDialog
}
//非强制更新else {
//show UpdateDialog
}
} else {
//无更新,提示已是最新版等
}
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage, interrorCode) {
//failureMessage:一般为try{}catch(){}捕获的异常信息//errorCode:暂时没什么用
}
});

Q.checkUpdate("post", "checkUpdateUrl", newCheckUpdateCallback2() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult) {
//result:服务端返回的json,需要自己判断有无更新,解析成自己的实体类进行判断是否有版本更新
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage) {
}
}); 

####强制更新对话框:

ForceUpdateDialogdialog = newForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
.show();

####非强制更新对话框:

UpdateDialogdialog = newUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName())
.show();

####使用自定义Dialog:
#####对于强制更新方式: **step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**在自定义的dialog中,比如button1是用来下载文件的,那么可以使用HttpRequest类中提供的download方法,然后在各个回调中实现自己的逻辑,比如进度条监听,下载完成后安装等,示例代码如下:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于500ms都return;if (System.currentTimeMillis() - timeRange < 500) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
if ("点击安装".equals(button1.getText().toString().trim())) {
Filefile = newFile(mFilePath, mFileName);
if (file.exists()) {
ApplicationUtil.installApk(context, file);
} else {
download();
}
return;
}
download();
}
}); privatevoiddownload() {
forceUpdateProgress.setVisibility(View.VISIBLE);
HttpRequest.download(mDownloadUrl, mFilePath, mFileName, newDownloadCallback() {
@OverridepublicvoidonDownloadSuccess(Filefile) {
button1.setEnabled(true);
button1.setText("点击安装");
ApplicationUtil.installApk(context, file);
}
@OverridepublicvoidonProgress(longcurrentProgress, longtotalProgress) {
button1.setEnabled(false);
button1.setText("正在下载");
forceUpdateProgress.setProgress((int) (currentProgress));
forceUpdateProgress.setMax((int) (totalProgress));
}
@OverridepublicvoidonDownloadFailure(StringfailureMessage) {
button1.setEnabled(true);
button1.setText("重新下载");
}
});
} 

#####对于非强制更新方式:
**step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**继承CheckUpdateLibrary中的BaseService,实现相关方法,其中Service中自带的方法onStartCommand必须重写,一会说为什么.
示例代码如下:

publicclassDownloadServiceextendsBaseService {
privateinticonResId;
privateStringappName;
privateIntentmIntent;
@Nullable@OverridepublicIBinderonBind(Intentintent) {
returnnull;
}
@OverridepublicintonStartCommand(Intentintent, intflags, intstartId) {
if (null == intent) {
returnSTART_NOT_STICKY;
}
mIntent = intent;
appName = intent.getStringExtra("appName");
iconResId = intent.getIntExtra("iconResId", -1);
if (iconResId == -1) {
iconResId = R.drawable.icon_downloading;
}
download(intent.getStringExtra("downloadUrl"), intent.getStringExtra("filePath"), intent.getStringExtra("fileName"), true);
returnsuper.onStartCommand(intent, flags, startId);
}
@OverridepublicvoiddownloadFailure(StringfailureMessage) {
NotificationUtil.showDownloadFailureNotification(this, mIntent, iconResId, appName, "下载失败,点击重新下载", true);
}
@OverridepublicvoiddownloadSuccess(Filefile) {
NotificationUtil.showDownloadSuccessNotification(this, file, iconResId, appName, "下载完成,点击安装", false);
}
@Overridepublicvoiddownloading(intcurrentProgress, inttotalProgress) {
NotificationUtil.showDownloadingNotification(this, currentProgress, totalProgress, iconResId, appName, false);
}
}

step3:在自定义的dialog中,比如button1是用来下载文件的,那么可以这么写:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于1s都return;if (System.currentTimeMillis() - timeRange < 1000) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
Intentintent = newIntent(context, DownloadService.class);
intent.putExtra("downloadUrl", mDownloadUrl);
intent.putExtra("filePath", mFilePath);
intent.putExtra("fileName", mFileName);
intent.putExtra("iconResId", mIconResId);
intent.putExtra("isShowProgress", isShowProgress);
intent.putExtra("appName", mAppName);
context.startService(intent);
dismiss();
Toast.makeText(context, "正在后台为您下载", Toast.LENGTH_SHORT).show();
}
}); 

ok,到此,自定义非强制更新Dialog的后台下载功能就实现了.
######下面说一说为什么必须要重写onStartCommand方法,主要有两点原因:
**1,**其实从上面的代码也可以看出,启动Service采用的是context.startService(intent);方法,而不是bind方法,所以在Service中接收intent必须重写onStartCommand方法才行.
**2,**如果下载失败时,点击通知是可以重新下载应用的,其中应用到PendingIntent.getService()方法,而该方法启动Service就是通过context.startService(intent);方式启动的,所以从这一点出发,仍然必须重写onStartCommand方法才行.
##Issues
各位小伙伴使用过程中有任何问题或发现什么bug或有什么好的意见或建议,请通过上面的issue提交给我,谢谢啦~~
另外,跪求Star或Fork,这是对开发者最好的激励!!!

About

AndroidApp检查更新库

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

CheckUpdateLibrary

检查更新库

一个Android专用检查软件更新的库
##效果图: 非强制更新:
非强制更新
强制更新:
强制更新 ##简介:
####该库的功能:
1,get/post方式检查更新,下载更新操作
2,有更新时,弹出升级对话框
3,可以根据各种参数设置是否强制更新,是否在通知栏显示进度条等,具体用法请参考demo
4,该库同时提供相关工具类,方便下载和安装软件等操作
####该库的特点: 1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary具有超强扩展性,下面会单独一个标题细说.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
##扩展性:
CheckUpdateLibrary具有超强扩展性:
1,CheckUpdateLibrary有两种方式进行检查更新,对应着两种回调方式:CheckUpdateCallback和CheckUpdateCallback2,前者为了使用方便,所以需要开发者必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,而如果开发者想完全自定义实体,那么可以使用后者,即CheckUpdateCallback2,但是需要自己进行判断是否软件有更新.
2,可自定义Dialog.虽然CheckUpdateLibrary中提供了两种Dialog:ForceUpdateDialog和UpdateDialg用来展示强制更新和非强制更新对话框,但还是会有很多开发者想使用自己自定义的Dialog,然后借助于CheckUpdateLibrary中的后台下载功能和通知展示功能来实现后台下载,而CheckUpdateLibrary也考虑到开发者的这种需求,开发者只需要继承CheckUpdateLibrary中的BaseService,然后实现相关方法即可实现自己的需求,具体的使用方式请参考下面的教程.
##用法: ####Android Studio添加依赖:

 dependencies { compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.3' }

####Eclipse:
使用eclipse的小伙伴只能下载library文件,然后引入到项目中使用了

####检查更新:

Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", newCheckUpdateCallback() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult, booleanhasUpdate) {
//result:服务端返回的jsonCheckUpdateInfocheckUpdateInfo = newGson().fromJson(result, CheckUpdateInfo.class);
//有更新,显示dialog等if (hasUpdate) {
//强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可if (checkUpdateInfo.getIsForceUpdate() == 0) {
//show ForceUpdateDialog
}
//非强制更新else {
//show UpdateDialog
}
} else {
//无更新,提示已是最新版等
}
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage, interrorCode) {
//failureMessage:一般为try{}catch(){}捕获的异常信息//errorCode:暂时没什么用
}
});

Q.checkUpdate("post", "checkUpdateUrl", newCheckUpdateCallback2() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult) {
//result:服务端返回的json,需要自己判断有无更新,解析成自己的实体类进行判断是否有版本更新
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage) {
}
}); 

####强制更新对话框:

ForceUpdateDialogdialog = newForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
.show();

####非强制更新对话框:

UpdateDialogdialog = newUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName())
.show();

####使用自定义Dialog:
#####对于强制更新方式: **step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**在自定义的dialog中,比如button1是用来下载文件的,那么可以使用HttpRequest类中提供的download方法,然后在各个回调中实现自己的逻辑,比如进度条监听,下载完成后安装等,示例代码如下:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于500ms都return;if (System.currentTimeMillis() - timeRange < 500) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
if ("点击安装".equals(button1.getText().toString().trim())) {
Filefile = newFile(mFilePath, mFileName);
if (file.exists()) {
ApplicationUtil.installApk(context, file);
} else {
download();
}
return;
}
download();
}
}); privatevoiddownload() {
forceUpdateProgress.setVisibility(View.VISIBLE);
HttpRequest.download(mDownloadUrl, mFilePath, mFileName, newDownloadCallback() {
@OverridepublicvoidonDownloadSuccess(Filefile) {
button1.setEnabled(true);
button1.setText("点击安装");
ApplicationUtil.installApk(context, file);
}
@OverridepublicvoidonProgress(longcurrentProgress, longtotalProgress) {
button1.setEnabled(false);
button1.setText("正在下载");
forceUpdateProgress.setProgress((int) (currentProgress));
forceUpdateProgress.setMax((int) (totalProgress));
}
@OverridepublicvoidonDownloadFailure(StringfailureMessage) {
button1.setEnabled(true);
button1.setText("重新下载");
}
});
} 

#####对于非强制更新方式:
**step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**继承CheckUpdateLibrary中的BaseService,实现相关方法,其中Service中自带的方法onStartCommand必须重写,一会说为什么.
示例代码如下:

publicclassDownloadServiceextendsBaseService {
privateinticonResId;
privateStringappName;
privateIntentmIntent;
@Nullable@OverridepublicIBinderonBind(Intentintent) {
returnnull;
}
@OverridepublicintonStartCommand(Intentintent, intflags, intstartId) {
if (null == intent) {
returnSTART_NOT_STICKY;
}
mIntent = intent;
appName = intent.getStringExtra("appName");
iconResId = intent.getIntExtra("iconResId", -1);
if (iconResId == -1) {
iconResId = R.drawable.icon_downloading;
}
download(intent.getStringExtra("downloadUrl"), intent.getStringExtra("filePath"), intent.getStringExtra("fileName"), true);
returnsuper.onStartCommand(intent, flags, startId);
}
@OverridepublicvoiddownloadFailure(StringfailureMessage) {
NotificationUtil.showDownloadFailureNotification(this, mIntent, iconResId, appName, "下载失败,点击重新下载", true);
}
@OverridepublicvoiddownloadSuccess(Filefile) {
NotificationUtil.showDownloadSuccessNotification(this, file, iconResId, appName, "下载完成,点击安装", false);
}
@Overridepublicvoiddownloading(intcurrentProgress, inttotalProgress) {
NotificationUtil.showDownloadingNotification(this, currentProgress, totalProgress, iconResId, appName, false);
}
}

step3:在自定义的dialog中,比如button1是用来下载文件的,那么可以这么写:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于1s都return;if (System.currentTimeMillis() - timeRange < 1000) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
Intentintent = newIntent(context, DownloadService.class);
intent.putExtra("downloadUrl", mDownloadUrl);
intent.putExtra("filePath", mFilePath);
intent.putExtra("fileName", mFileName);
intent.putExtra("iconResId", mIconResId);
intent.putExtra("isShowProgress", isShowProgress);
intent.putExtra("appName", mAppName);
context.startService(intent);
dismiss();
Toast.makeText(context, "正在后台为您下载", Toast.LENGTH_SHORT).show();
}
}); 

ok,到此,自定义非强制更新Dialog的后台下载功能就实现了.
######下面说一说为什么必须要重写onStartCommand方法,主要有两点原因:
**1,**其实从上面的代码也可以看出,启动Service采用的是context.startService(intent);方法,而不是bind方法,所以在Service中接收intent必须重写onStartCommand方法才行.
**2,**如果下载失败时,点击通知是可以重新下载应用的,其中应用到PendingIntent.getService()方法,而该方法启动Service就是通过context.startService(intent);方式启动的,所以从这一点出发,仍然必须重写onStartCommand方法才行.
##Issues
各位小伙伴使用过程中有任何问题或发现什么bug或有什么好的意见或建议,请通过上面的issue提交给我,谢谢啦~~
另外,跪求Star或Fork,这是对开发者最好的激励!!!

About

AndroidApp检查更新库

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

CheckUpdateLibrary

检查更新库

一个Android专用检查软件更新的库
##效果图: 非强制更新:
非强制更新
强制更新:
强制更新 ##简介:
####该库的功能:
1,get/post方式检查更新,下载更新操作
2,有更新时,弹出升级对话框
3,可以根据各种参数设置是否强制更新,是否在通知栏显示进度条等,具体用法请参考demo
4,该库同时提供相关工具类,方便下载和安装软件等操作
####该库的特点: 1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary具有超强扩展性,下面会单独一个标题细说.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
##扩展性:
CheckUpdateLibrary具有超强扩展性:
1,CheckUpdateLibrary有两种方式进行检查更新,对应着两种回调方式:CheckUpdateCallback和CheckUpdateCallback2,前者为了使用方便,所以需要开发者必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,而如果开发者想完全自定义实体,那么可以使用后者,即CheckUpdateCallback2,但是需要自己进行判断是否软件有更新.
2,可自定义Dialog.虽然CheckUpdateLibrary中提供了两种Dialog:ForceUpdateDialog和UpdateDialg用来展示强制更新和非强制更新对话框,但还是会有很多开发者想使用自己自定义的Dialog,然后借助于CheckUpdateLibrary中的后台下载功能和通知展示功能来实现后台下载,而CheckUpdateLibrary也考虑到开发者的这种需求,开发者只需要继承CheckUpdateLibrary中的BaseService,然后实现相关方法即可实现自己的需求,具体的使用方式请参考下面的教程.
##用法: ####Android Studio添加依赖:

 dependencies { compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.3' }

####Eclipse:
使用eclipse的小伙伴只能下载library文件,然后引入到项目中使用了

####检查更新:

Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", newCheckUpdateCallback() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult, booleanhasUpdate) {
//result:服务端返回的jsonCheckUpdateInfocheckUpdateInfo = newGson().fromJson(result, CheckUpdateInfo.class);
//有更新,显示dialog等if (hasUpdate) {
//强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可if (checkUpdateInfo.getIsForceUpdate() == 0) {
//show ForceUpdateDialog
}
//非强制更新else {
//show UpdateDialog
}
} else {
//无更新,提示已是最新版等
}
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage, interrorCode) {
//failureMessage:一般为try{}catch(){}捕获的异常信息//errorCode:暂时没什么用
}
});

Q.checkUpdate("post", "checkUpdateUrl", newCheckUpdateCallback2() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult) {
//result:服务端返回的json,需要自己判断有无更新,解析成自己的实体类进行判断是否有版本更新
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage) {
}
}); 

####强制更新对话框:

ForceUpdateDialogdialog = newForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
.show();

####非强制更新对话框:

UpdateDialogdialog = newUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName())
.show();

####使用自定义Dialog:
#####对于强制更新方式: **step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**在自定义的dialog中,比如button1是用来下载文件的,那么可以使用HttpRequest类中提供的download方法,然后在各个回调中实现自己的逻辑,比如进度条监听,下载完成后安装等,示例代码如下:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于500ms都return;if (System.currentTimeMillis() - timeRange < 500) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
if ("点击安装".equals(button1.getText().toString().trim())) {
Filefile = newFile(mFilePath, mFileName);
if (file.exists()) {
ApplicationUtil.installApk(context, file);
} else {
download();
}
return;
}
download();
}
}); privatevoiddownload() {
forceUpdateProgress.setVisibility(View.VISIBLE);
HttpRequest.download(mDownloadUrl, mFilePath, mFileName, newDownloadCallback() {
@OverridepublicvoidonDownloadSuccess(Filefile) {
button1.setEnabled(true);
button1.setText("点击安装");
ApplicationUtil.installApk(context, file);
}
@OverridepublicvoidonProgress(longcurrentProgress, longtotalProgress) {
button1.setEnabled(false);
button1.setText("正在下载");
forceUpdateProgress.setProgress((int) (currentProgress));
forceUpdateProgress.setMax((int) (totalProgress));
}
@OverridepublicvoidonDownloadFailure(StringfailureMessage) {
button1.setEnabled(true);
button1.setText("重新下载");
}
});
} 

#####对于非强制更新方式:
**step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**继承CheckUpdateLibrary中的BaseService,实现相关方法,其中Service中自带的方法onStartCommand必须重写,一会说为什么.
示例代码如下:

publicclassDownloadServiceextendsBaseService {
privateinticonResId;
privateStringappName;
privateIntentmIntent;
@Nullable@OverridepublicIBinderonBind(Intentintent) {
returnnull;
}
@OverridepublicintonStartCommand(Intentintent, intflags, intstartId) {
if (null == intent) {
returnSTART_NOT_STICKY;
}
mIntent = intent;
appName = intent.getStringExtra("appName");
iconResId = intent.getIntExtra("iconResId", -1);
if (iconResId == -1) {
iconResId = R.drawable.icon_downloading;
}
download(intent.getStringExtra("downloadUrl"), intent.getStringExtra("filePath"), intent.getStringExtra("fileName"), true);
returnsuper.onStartCommand(intent, flags, startId);
}
@OverridepublicvoiddownloadFailure(StringfailureMessage) {
NotificationUtil.showDownloadFailureNotification(this, mIntent, iconResId, appName, "下载失败,点击重新下载", true);
}
@OverridepublicvoiddownloadSuccess(Filefile) {
NotificationUtil.showDownloadSuccessNotification(this, file, iconResId, appName, "下载完成,点击安装", false);
}
@Overridepublicvoiddownloading(intcurrentProgress, inttotalProgress) {
NotificationUtil.showDownloadingNotification(this, currentProgress, totalProgress, iconResId, appName, false);
}
}

step3:在自定义的dialog中,比如button1是用来下载文件的,那么可以这么写:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于1s都return;if (System.currentTimeMillis() - timeRange < 1000) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
Intentintent = newIntent(context, DownloadService.class);
intent.putExtra("downloadUrl", mDownloadUrl);
intent.putExtra("filePath", mFilePath);
intent.putExtra("fileName", mFileName);
intent.putExtra("iconResId", mIconResId);
intent.putExtra("isShowProgress", isShowProgress);
intent.putExtra("appName", mAppName);
context.startService(intent);
dismiss();
Toast.makeText(context, "正在后台为您下载", Toast.LENGTH_SHORT).show();
}
}); 

ok,到此,自定义非强制更新Dialog的后台下载功能就实现了.
######下面说一说为什么必须要重写onStartCommand方法,主要有两点原因:
**1,**其实从上面的代码也可以看出,启动Service采用的是context.startService(intent);方法,而不是bind方法,所以在Service中接收intent必须重写onStartCommand方法才行.
**2,**如果下载失败时,点击通知是可以重新下载应用的,其中应用到PendingIntent.getService()方法,而该方法启动Service就是通过context.startService(intent);方式启动的,所以从这一点出发,仍然必须重写onStartCommand方法才行.
##Issues
各位小伙伴使用过程中有任何问题或发现什么bug或有什么好的意见或建议,请通过上面的issue提交给我,谢谢啦~~
另外,跪求Star或Fork,这是对开发者最好的激励!!!

About

AndroidApp检查更新库

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

CheckUpdateLibrary

检查更新库

一个Android专用检查软件更新的库
##效果图: 非强制更新:
非强制更新
强制更新:
强制更新 ##简介:
####该库的功能:
1,get/post方式检查更新,下载更新操作
2,有更新时,弹出升级对话框
3,可以根据各种参数设置是否强制更新,是否在通知栏显示进度条等,具体用法请参考demo
4,该库同时提供相关工具类,方便下载和安装软件等操作
####该库的特点: 1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary具有超强扩展性,下面会单独一个标题细说.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
##扩展性:
CheckUpdateLibrary具有超强扩展性:
1,CheckUpdateLibrary有两种方式进行检查更新,对应着两种回调方式:CheckUpdateCallback和CheckUpdateCallback2,前者为了使用方便,所以需要开发者必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,而如果开发者想完全自定义实体,那么可以使用后者,即CheckUpdateCallback2,但是需要自己进行判断是否软件有更新.
2,可自定义Dialog.虽然CheckUpdateLibrary中提供了两种Dialog:ForceUpdateDialog和UpdateDialg用来展示强制更新和非强制更新对话框,但还是会有很多开发者想使用自己自定义的Dialog,然后借助于CheckUpdateLibrary中的后台下载功能和通知展示功能来实现后台下载,而CheckUpdateLibrary也考虑到开发者的这种需求,开发者只需要继承CheckUpdateLibrary中的BaseService,然后实现相关方法即可实现自己的需求,具体的使用方式请参考下面的教程.
##用法: ####Android Studio添加依赖:

 dependencies { compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.3' }

####Eclipse:
使用eclipse的小伙伴只能下载library文件,然后引入到项目中使用了

####检查更新:

Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", newCheckUpdateCallback() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult, booleanhasUpdate) {
//result:服务端返回的jsonCheckUpdateInfocheckUpdateInfo = newGson().fromJson(result, CheckUpdateInfo.class);
//有更新,显示dialog等if (hasUpdate) {
//强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可if (checkUpdateInfo.getIsForceUpdate() == 0) {
//show ForceUpdateDialog
}
//非强制更新else {
//show UpdateDialog
}
} else {
//无更新,提示已是最新版等
}
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage, interrorCode) {
//failureMessage:一般为try{}catch(){}捕获的异常信息//errorCode:暂时没什么用
}
});

Q.checkUpdate("post", "checkUpdateUrl", newCheckUpdateCallback2() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult) {
//result:服务端返回的json,需要自己判断有无更新,解析成自己的实体类进行判断是否有版本更新
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage) {
}
}); 

####强制更新对话框:

ForceUpdateDialogdialog = newForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
.show();

####非强制更新对话框:

UpdateDialogdialog = newUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName())
.show();

####使用自定义Dialog:
#####对于强制更新方式: **step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**在自定义的dialog中,比如button1是用来下载文件的,那么可以使用HttpRequest类中提供的download方法,然后在各个回调中实现自己的逻辑,比如进度条监听,下载完成后安装等,示例代码如下:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于500ms都return;if (System.currentTimeMillis() - timeRange < 500) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
if ("点击安装".equals(button1.getText().toString().trim())) {
Filefile = newFile(mFilePath, mFileName);
if (file.exists()) {
ApplicationUtil.installApk(context, file);
} else {
download();
}
return;
}
download();
}
}); privatevoiddownload() {
forceUpdateProgress.setVisibility(View.VISIBLE);
HttpRequest.download(mDownloadUrl, mFilePath, mFileName, newDownloadCallback() {
@OverridepublicvoidonDownloadSuccess(Filefile) {
button1.setEnabled(true);
button1.setText("点击安装");
ApplicationUtil.installApk(context, file);
}
@OverridepublicvoidonProgress(longcurrentProgress, longtotalProgress) {
button1.setEnabled(false);
button1.setText("正在下载");
forceUpdateProgress.setProgress((int) (currentProgress));
forceUpdateProgress.setMax((int) (totalProgress));
}
@OverridepublicvoidonDownloadFailure(StringfailureMessage) {
button1.setEnabled(true);
button1.setText("重新下载");
}
});
} 

#####对于非强制更新方式:
**step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**继承CheckUpdateLibrary中的BaseService,实现相关方法,其中Service中自带的方法onStartCommand必须重写,一会说为什么.
示例代码如下:

publicclassDownloadServiceextendsBaseService {
privateinticonResId;
privateStringappName;
privateIntentmIntent;
@Nullable@OverridepublicIBinderonBind(Intentintent) {
returnnull;
}
@OverridepublicintonStartCommand(Intentintent, intflags, intstartId) {
if (null == intent) {
returnSTART_NOT_STICKY;
}
mIntent = intent;
appName = intent.getStringExtra("appName");
iconResId = intent.getIntExtra("iconResId", -1);
if (iconResId == -1) {
iconResId = R.drawable.icon_downloading;
}
download(intent.getStringExtra("downloadUrl"), intent.getStringExtra("filePath"), intent.getStringExtra("fileName"), true);
returnsuper.onStartCommand(intent, flags, startId);
}
@OverridepublicvoiddownloadFailure(StringfailureMessage) {
NotificationUtil.showDownloadFailureNotification(this, mIntent, iconResId, appName, "下载失败,点击重新下载", true);
}
@OverridepublicvoiddownloadSuccess(Filefile) {
NotificationUtil.showDownloadSuccessNotification(this, file, iconResId, appName, "下载完成,点击安装", false);
}
@Overridepublicvoiddownloading(intcurrentProgress, inttotalProgress) {
NotificationUtil.showDownloadingNotification(this, currentProgress, totalProgress, iconResId, appName, false);
}
}

step3:在自定义的dialog中,比如button1是用来下载文件的,那么可以这么写:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于1s都return;if (System.currentTimeMillis() - timeRange < 1000) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
Intentintent = newIntent(context, DownloadService.class);
intent.putExtra("downloadUrl", mDownloadUrl);
intent.putExtra("filePath", mFilePath);
intent.putExtra("fileName", mFileName);
intent.putExtra("iconResId", mIconResId);
intent.putExtra("isShowProgress", isShowProgress);
intent.putExtra("appName", mAppName);
context.startService(intent);
dismiss();
Toast.makeText(context, "正在后台为您下载", Toast.LENGTH_SHORT).show();
}
}); 

ok,到此,自定义非强制更新Dialog的后台下载功能就实现了.
######下面说一说为什么必须要重写onStartCommand方法,主要有两点原因:
**1,**其实从上面的代码也可以看出,启动Service采用的是context.startService(intent);方法,而不是bind方法,所以在Service中接收intent必须重写onStartCommand方法才行.
**2,**如果下载失败时,点击通知是可以重新下载应用的,其中应用到PendingIntent.getService()方法,而该方法启动Service就是通过context.startService(intent);方式启动的,所以从这一点出发,仍然必须重写onStartCommand方法才行.
##Issues
各位小伙伴使用过程中有任何问题或发现什么bug或有什么好的意见或建议,请通过上面的issue提交给我,谢谢啦~~
另外,跪求Star或Fork,这是对开发者最好的激励!!!

About

AndroidApp检查更新库

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

CheckUpdateLibrary

检查更新库

一个Android专用检查软件更新的库
##效果图: 非强制更新:
非强制更新
强制更新:
强制更新 ##简介:
####该库的功能:
1,get/post方式检查更新,下载更新操作
2,有更新时,弹出升级对话框
3,可以根据各种参数设置是否强制更新,是否在通知栏显示进度条等,具体用法请参考demo
4,该库同时提供相关工具类,方便下载和安装软件等操作
####该库的特点: 1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary具有超强扩展性,下面会单独一个标题细说.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
##扩展性:
CheckUpdateLibrary具有超强扩展性:
1,CheckUpdateLibrary有两种方式进行检查更新,对应着两种回调方式:CheckUpdateCallback和CheckUpdateCallback2,前者为了使用方便,所以需要开发者必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,而如果开发者想完全自定义实体,那么可以使用后者,即CheckUpdateCallback2,但是需要自己进行判断是否软件有更新.
2,可自定义Dialog.虽然CheckUpdateLibrary中提供了两种Dialog:ForceUpdateDialog和UpdateDialg用来展示强制更新和非强制更新对话框,但还是会有很多开发者想使用自己自定义的Dialog,然后借助于CheckUpdateLibrary中的后台下载功能和通知展示功能来实现后台下载,而CheckUpdateLibrary也考虑到开发者的这种需求,开发者只需要继承CheckUpdateLibrary中的BaseService,然后实现相关方法即可实现自己的需求,具体的使用方式请参考下面的教程.
##用法: ####Android Studio添加依赖:

 dependencies { compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.3' }

####Eclipse:
使用eclipse的小伙伴只能下载library文件,然后引入到项目中使用了

####检查更新:

Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", newCheckUpdateCallback() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult, booleanhasUpdate) {
//result:服务端返回的jsonCheckUpdateInfocheckUpdateInfo = newGson().fromJson(result, CheckUpdateInfo.class);
//有更新,显示dialog等if (hasUpdate) {
//强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可if (checkUpdateInfo.getIsForceUpdate() == 0) {
//show ForceUpdateDialog
}
//非强制更新else {
//show UpdateDialog
}
} else {
//无更新,提示已是最新版等
}
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage, interrorCode) {
//failureMessage:一般为try{}catch(){}捕获的异常信息//errorCode:暂时没什么用
}
});

Q.checkUpdate("post", "checkUpdateUrl", newCheckUpdateCallback2() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult) {
//result:服务端返回的json,需要自己判断有无更新,解析成自己的实体类进行判断是否有版本更新
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage) {
}
}); 

####强制更新对话框:

ForceUpdateDialogdialog = newForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
.show();

####非强制更新对话框:

UpdateDialogdialog = newUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName())
.show();

####使用自定义Dialog:
#####对于强制更新方式: **step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**在自定义的dialog中,比如button1是用来下载文件的,那么可以使用HttpRequest类中提供的download方法,然后在各个回调中实现自己的逻辑,比如进度条监听,下载完成后安装等,示例代码如下:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于500ms都return;if (System.currentTimeMillis() - timeRange < 500) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
if ("点击安装".equals(button1.getText().toString().trim())) {
Filefile = newFile(mFilePath, mFileName);
if (file.exists()) {
ApplicationUtil.installApk(context, file);
} else {
download();
}
return;
}
download();
}
}); privatevoiddownload() {
forceUpdateProgress.setVisibility(View.VISIBLE);
HttpRequest.download(mDownloadUrl, mFilePath, mFileName, newDownloadCallback() {
@OverridepublicvoidonDownloadSuccess(Filefile) {
button1.setEnabled(true);
button1.setText("点击安装");
ApplicationUtil.installApk(context, file);
}
@OverridepublicvoidonProgress(longcurrentProgress, longtotalProgress) {
button1.setEnabled(false);
button1.setText("正在下载");
forceUpdateProgress.setProgress((int) (currentProgress));
forceUpdateProgress.setMax((int) (totalProgress));
}
@OverridepublicvoidonDownloadFailure(StringfailureMessage) {
button1.setEnabled(true);
button1.setText("重新下载");
}
});
} 

#####对于非强制更新方式:
**step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**继承CheckUpdateLibrary中的BaseService,实现相关方法,其中Service中自带的方法onStartCommand必须重写,一会说为什么.
示例代码如下:

publicclassDownloadServiceextendsBaseService {
privateinticonResId;
privateStringappName;
privateIntentmIntent;
@Nullable@OverridepublicIBinderonBind(Intentintent) {
returnnull;
}
@OverridepublicintonStartCommand(Intentintent, intflags, intstartId) {
if (null == intent) {
returnSTART_NOT_STICKY;
}
mIntent = intent;
appName = intent.getStringExtra("appName");
iconResId = intent.getIntExtra("iconResId", -1);
if (iconResId == -1) {
iconResId = R.drawable.icon_downloading;
}
download(intent.getStringExtra("downloadUrl"), intent.getStringExtra("filePath"), intent.getStringExtra("fileName"), true);
returnsuper.onStartCommand(intent, flags, startId);
}
@OverridepublicvoiddownloadFailure(StringfailureMessage) {
NotificationUtil.showDownloadFailureNotification(this, mIntent, iconResId, appName, "下载失败,点击重新下载", true);
}
@OverridepublicvoiddownloadSuccess(Filefile) {
NotificationUtil.showDownloadSuccessNotification(this, file, iconResId, appName, "下载完成,点击安装", false);
}
@Overridepublicvoiddownloading(intcurrentProgress, inttotalProgress) {
NotificationUtil.showDownloadingNotification(this, currentProgress, totalProgress, iconResId, appName, false);
}
}

step3:在自定义的dialog中,比如button1是用来下载文件的,那么可以这么写:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于1s都return;if (System.currentTimeMillis() - timeRange < 1000) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
Intentintent = newIntent(context, DownloadService.class);
intent.putExtra("downloadUrl", mDownloadUrl);
intent.putExtra("filePath", mFilePath);
intent.putExtra("fileName", mFileName);
intent.putExtra("iconResId", mIconResId);
intent.putExtra("isShowProgress", isShowProgress);
intent.putExtra("appName", mAppName);
context.startService(intent);
dismiss();
Toast.makeText(context, "正在后台为您下载", Toast.LENGTH_SHORT).show();
}
}); 

ok,到此,自定义非强制更新Dialog的后台下载功能就实现了.
######下面说一说为什么必须要重写onStartCommand方法,主要有两点原因:
**1,**其实从上面的代码也可以看出,启动Service采用的是context.startService(intent);方法,而不是bind方法,所以在Service中接收intent必须重写onStartCommand方法才行.
**2,**如果下载失败时,点击通知是可以重新下载应用的,其中应用到PendingIntent.getService()方法,而该方法启动Service就是通过context.startService(intent);方式启动的,所以从这一点出发,仍然必须重写onStartCommand方法才行.
##Issues
各位小伙伴使用过程中有任何问题或发现什么bug或有什么好的意见或建议,请通过上面的issue提交给我,谢谢啦~~
另外,跪求Star或Fork,这是对开发者最好的激励!!!

About

AndroidApp检查更新库

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

CheckUpdateLibrary

检查更新库

一个Android专用检查软件更新的库
##效果图: 非强制更新:
非强制更新
强制更新:
强制更新 ##简介:
####该库的功能:
1,get/post方式检查更新,下载更新操作
2,有更新时,弹出升级对话框
3,可以根据各种参数设置是否强制更新,是否在通知栏显示进度条等,具体用法请参考demo
4,该库同时提供相关工具类,方便下载和安装软件等操作
####该库的特点: 1,零耦合:CheckUpdateLibrary从检查更新到下载更新全部采用HttpURLConnection,Dialog同样自定义,没有引入任何其他第三方库,而其他库要么是用的第三方网络请求框架,要么用的是别人封装好的dialog.所以开发者可能会吐槽,这只是一个单纯的检查更新和下载更新功能,我却需要多引入很多第三方库,这无形之中增加了我APK的体积,我很不爽!!!而用这个库,开发者完全不用担心这些.
2,体积小:基于第一点,所以CheckUpdateLibrary库体积超小,只有10多kb
3,兼容6.0:因为使用的是HttpURLConnection,所以6.0系统同样适配
4,可扩展性:CheckUpdateLibrary具有超强扩展性,下面会单独一个标题细说.
5,其他功能:比如可以自定义apk文件的存储路径,文件名,后台下载时是否在通知栏显示实时下载进度等.
##扩展性:
CheckUpdateLibrary具有超强扩展性:
1,CheckUpdateLibrary有两种方式进行检查更新,对应着两种回调方式:CheckUpdateCallback和CheckUpdateCallback2,前者为了使用方便,所以需要开发者必须保证自定义的实体类中包含newAppVersionCode字段,该字段在库中用来判断是否有更新,而如果开发者想完全自定义实体,那么可以使用后者,即CheckUpdateCallback2,但是需要自己进行判断是否软件有更新.
2,可自定义Dialog.虽然CheckUpdateLibrary中提供了两种Dialog:ForceUpdateDialog和UpdateDialg用来展示强制更新和非强制更新对话框,但还是会有很多开发者想使用自己自定义的Dialog,然后借助于CheckUpdateLibrary中的后台下载功能和通知展示功能来实现后台下载,而CheckUpdateLibrary也考虑到开发者的这种需求,开发者只需要继承CheckUpdateLibrary中的BaseService,然后实现相关方法即可实现自己的需求,具体的使用方式请参考下面的教程.
##用法: ####Android Studio添加依赖:

 dependencies { compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.0.3' }

####Eclipse:
使用eclipse的小伙伴只能下载library文件,然后引入到项目中使用了

####检查更新:

Q.checkUpdate("post", getVersionCode(), "checkUpdateUrl", newCheckUpdateCallback() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult, booleanhasUpdate) {
//result:服务端返回的jsonCheckUpdateInfocheckUpdateInfo = newGson().fromJson(result, CheckUpdateInfo.class);
//有更新,显示dialog等if (hasUpdate) {
//强制更新,这里用0表示强制更新,实际情况中可与服务端商定什么数字代表强制更新即可if (checkUpdateInfo.getIsForceUpdate() == 0) {
//show ForceUpdateDialog
}
//非强制更新else {
//show UpdateDialog
}
} else {
//无更新,提示已是最新版等
}
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage, interrorCode) {
//failureMessage:一般为try{}catch(){}捕获的异常信息//errorCode:暂时没什么用
}
});

Q.checkUpdate("post", "checkUpdateUrl", newCheckUpdateCallback2() {
@OverridepublicvoidonCheckUpdateSuccess(Stringresult) {
//result:服务端返回的json,需要自己判断有无更新,解析成自己的实体类进行判断是否有版本更新
}
@OverridepublicvoidonCheckUpdateFailure(StringfailureMessage) {
}
}); 

####强制更新对话框:

ForceUpdateDialogdialog = newForceUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
.show();

####非强制更新对话框:

UpdateDialogdialog = newUpdateDialog(MainActivity.this);
dialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
.setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
.setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
.setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
.setVersionName(mCheckUpdateInfo.getNewAppVersionName())
.setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
.setFileName("这是QQ.apk")
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib")
//该方法需设为true,才会在通知栏显示下载进度,默认为false,即不显示//该方法只会控制下载进度的展示,当下载完成或下载失败时展示的通知不受该方法影响//即不管该方法是置为false还是true,当下载完成或下载失败时都会在通知栏展示一个通知
.setShowProgress(true)
.setIconResId(R.mipmap.ic_launcher)
.setAppName(mCheckUpdateInfo.getAppName())
.show();

####使用自定义Dialog:
#####对于强制更新方式: **step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**在自定义的dialog中,比如button1是用来下载文件的,那么可以使用HttpRequest类中提供的download方法,然后在各个回调中实现自己的逻辑,比如进度条监听,下载完成后安装等,示例代码如下:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于500ms都return;if (System.currentTimeMillis() - timeRange < 500) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
if ("点击安装".equals(button1.getText().toString().trim())) {
Filefile = newFile(mFilePath, mFileName);
if (file.exists()) {
ApplicationUtil.installApk(context, file);
} else {
download();
}
return;
}
download();
}
}); privatevoiddownload() {
forceUpdateProgress.setVisibility(View.VISIBLE);
HttpRequest.download(mDownloadUrl, mFilePath, mFileName, newDownloadCallback() {
@OverridepublicvoidonDownloadSuccess(Filefile) {
button1.setEnabled(true);
button1.setText("点击安装");
ApplicationUtil.installApk(context, file);
}
@OverridepublicvoidonProgress(longcurrentProgress, longtotalProgress) {
button1.setEnabled(false);
button1.setText("正在下载");
forceUpdateProgress.setProgress((int) (currentProgress));
forceUpdateProgress.setMax((int) (totalProgress));
}
@OverridepublicvoidonDownloadFailure(StringfailureMessage) {
button1.setEnabled(true);
button1.setText("重新下载");
}
});
} 

#####对于非强制更新方式:
**step1:**自定义自己的Dialog,这个就不贴代码了,大家应该都会
**step2:**继承CheckUpdateLibrary中的BaseService,实现相关方法,其中Service中自带的方法onStartCommand必须重写,一会说为什么.
示例代码如下:

publicclassDownloadServiceextendsBaseService {
privateinticonResId;
privateStringappName;
privateIntentmIntent;
@Nullable@OverridepublicIBinderonBind(Intentintent) {
returnnull;
}
@OverridepublicintonStartCommand(Intentintent, intflags, intstartId) {
if (null == intent) {
returnSTART_NOT_STICKY;
}
mIntent = intent;
appName = intent.getStringExtra("appName");
iconResId = intent.getIntExtra("iconResId", -1);
if (iconResId == -1) {
iconResId = R.drawable.icon_downloading;
}
download(intent.getStringExtra("downloadUrl"), intent.getStringExtra("filePath"), intent.getStringExtra("fileName"), true);
returnsuper.onStartCommand(intent, flags, startId);
}
@OverridepublicvoiddownloadFailure(StringfailureMessage) {
NotificationUtil.showDownloadFailureNotification(this, mIntent, iconResId, appName, "下载失败,点击重新下载", true);
}
@OverridepublicvoiddownloadSuccess(Filefile) {
NotificationUtil.showDownloadSuccessNotification(this, file, iconResId, appName, "下载完成,点击安装", false);
}
@Overridepublicvoiddownloading(intcurrentProgress, inttotalProgress) {
NotificationUtil.showDownloadingNotification(this, currentProgress, totalProgress, iconResId, appName, false);
}
}

step3:在自定义的dialog中,比如button1是用来下载文件的,那么可以这么写:

button1.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(Viewv) {
//防抖动,两次点击间隔小于1s都return;if (System.currentTimeMillis() - timeRange < 1000) {
return;
}
timeRange = System.currentTimeMillis();
setNetWorkState();
if (!NetWorkUtil.hasNetConnection(context)) {
Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
return;
}
Intentintent = newIntent(context, DownloadService.class);
intent.putExtra("downloadUrl", mDownloadUrl);
intent.putExtra("filePath", mFilePath);
intent.putExtra("fileName", mFileName);
intent.putExtra("iconResId", mIconResId);
intent.putExtra("isShowProgress", isShowProgress);
intent.putExtra("appName", mAppName);
context.startService(intent);
dismiss();
Toast.makeText(context, "正在后台为您下载", Toast.LENGTH_SHORT).show();
}
}); 

ok,到此,自定义非强制更新Dialog的后台下载功能就实现了.
######下面说一说为什么必须要重写onStartCommand方法,主要有两点原因:
**1,**其实从上面的代码也可以看出,启动Service采用的是context.startService(intent);方法,而不是bind方法,所以在Service中接收intent必须重写onStartCommand方法才行.
**2,**如果下载失败时,点击通知是可以重新下载应用的,其中应用到PendingIntent.getService()方法,而该方法启动Service就是通过context.startService(intent);方式启动的,所以从这一点出发,仍然必须重写onStartCommand方法才行.
##Issues
各位小伙伴使用过程中有任何问题或发现什么bug或有什么好的意见或建议,请通过上面的issue提交给我,谢谢啦~~
另外,跪求Star或Fork,这是对开发者最好的激励!!!

About

AndroidApp检查更新库

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages