easyandroidgroup / updateplugin Goto Github PK
View Code? Open in Web Editor NEW可任意定制的app更新组件。
Home Page: https://juejin.im/post/5a32485851882504a35f007a
可任意定制的app更新组件。
Home Page: https://juejin.im/post/5a32485851882504a35f007a
你好,很高兴有这个框架,我在使用中遇到一个问题
下面代码我设置了true
@OverRide
public boolean isShowDownloadDialog() {
return true;
}
下载进度条显示了,但是进度不更新,一直为0,下载完成后结束
需要设置什么才能显示进度,还是跟某个策略冲突了?
参数什么都填好,发现没反应,最后发现是我的服务器是使用https
瞎折腾了一会,发现封装的很死。无从配置。
UpdateWorker 虽然可以继承,但是却不是回调式。而我使用的是Okhttp 两个在不同的线程。 这很尴尬。
建议把
private DefaultCheckCB checkCB;
private UpdateBuilder builder; 改成protected
sendHasUpdate,sendNoUpdate,sendOnErrorMsg,setRunning 也改成protected 会比较灵活些。不然没法搞
现在框架只有弹出框中显示现在进度的功能,对用户体验不是很好,希望增加通知栏显示下载进度的功能,用户可以变使用应用边下载。所谓的静默下载安装
开启通知栏更新下载进度后,app页面好卡,经常ANR
如题
再好的组件,没有混淆说明,还是要花很多时间去适配!
在弹出更新对话框前,能否得之前是否已经下载好App?我的想法是:用户点击版本检查时,如果得知App已经下载好,直接在更新对话框提示用户免流量更新。
应用第一次打开可以正常调接口获取更新内容并弹框
在主页面点击home键再进来也可以正常调用接口并弹框
但是进入二级页面再返回主页就只能正常调用接口无法弹框了
我的逻辑是在onResume里写的 请问哪里出问题了吗
DefaultDownloadWorker类54行:
if (checkIsDownAll(target,url,contentLength)) {
urlConn.disconnect();
urlConn = null;
return;
}
if条件成立后直接return回到 DownloadWorker类的run方法,然后现在结束,不再执行任何代码。
java.lang.ClassCastException: android.view.ContextThemeWrapper cannot be cast to android.app.Activity at org.lzh.framework.updatepluginlib.util.SafeDialogOper.safeShowDialog(SafeDialogOper.java:23) at org.lzh.framework.updatepluginlib.callback.DefaultCheckCB.hasUpdate(DefaultCheckCB.java:60) at org.lzh.framework.updatepluginlib.business.UpdateWorker$1.run(UpdateWorker.java:96)
创建dialog时的context我都试过了,都会出现这个错误
问题:强制更新,对话框返回空时会crash
场景:在使用自定义对话框时,需要返回一个dialog,这时候业务需要,需要在dialog里面点击按钮时需要处理业务逻辑,所以有时候需要返回dialog=null。这时候如果强制更新会crash
解决办法:在DefaultCheckCB类中多加一个判空条件。
Dialog dialog = creator.create(update, actRef.get());
if (update.isForced() && dialog != null) {
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
}
支持自定义提示对话框和下载对话框吗?是不是只能在本地lib库中更改?
希望能放开写东西 ,比如说自定义的弹窗 和返回的实体
update->断网->update,无法进行断电下载,也不能重新下载。只能退出 app 再进来重新下载
为post请求了,请求参数怎么配置呢?
应该是GET的请求,但是代码里设置了setDoOutput(true),变成POST请求了
while ((length = inputStream.read(buffer)) != -1) {
raf.write(buffer, 0, length);
offset += length;
UpdatePreference.saveDownloadSize(url,offset);//这里效率低
long end = System.currentTimeMillis();
if (end - start > 1000) {
sendUpdateProgress(offset,contentLength);
}
}
目前可以复写DownloadWorker来解决这个问题。但是还是想提醒下作者。
我们公司在网络请求的时候加入特定的请求头,有点不是很方便,修改了源码搞定了,谢谢
比如,刚开始下载的时候,是WIFI,后来切换到了4G,需要暂停下载任务,然后,通知用户是否继续下载
需要设置head,发现没有这个方法
public class DefaultDownloadWorker extends DownloadWorker {
HttpURLConnection urlConn;
private URL httpUrl;
@OverRide
protected void download(String url, File target) throws Exception{
httpUrl = new URL(url);
urlConn = (HttpURLConnection) httpUrl.openConnection();
setDefaultProperties();
urlConn.connect();
int responseCode = urlConn.getResponseCode();
if (responseCode < 200 || responseCode >= 300) {
throw new HttpException(responseCode,urlConn.getResponseMessage());
}
target.delete();//这里删除了原来的下载的文件
RandomAccessFile raf = new RandomAccessFile(target,"rw");
long contentLength = urlConn.getContentLength();
long offset = target.exists() ? (int) target.length() : 0;
InputStream inputStream = urlConn.getInputStream();
byte[] buffer = new byte[8 * 1024];
int length;
long start = System.currentTimeMillis();
while ((length = inputStream.read(buffer)) != -1) {
raf.write(buffer, 0, length);
offset += length;
long end = System.currentTimeMillis();
if (end - start > 1000) {
sendUpdateProgress(offset,contentLength);
}
}
urlConn.disconnect();
raf.close();
}
android:authorities="${applicationId}.provider"
将这里的provider更改为自定义的provider名称
ps:用起来真的很棒~
// 建议在Application中进行配置。
// UpdateConfig为全局配置。当在其他页面中。使用UpdateBuilder进行检查更新时。
// 对于没传的参数,会默认使用UpdateConfig中的全局配置
UpdateConfig.getConfig()
// 必填:数据更新接口
.url(url)
// 必填:用于从数据更新接口获取的数据response中。解析出Update实例。以便框架内部处理
.jsonParser(new UpdateParser() {
@OverRide
public Update parse(String response) {
// 此处根据上面url接口返回的数据response进行update类组装。
return update;
}
})
首先,我不知道这个的原理是怎样的,到底是app这版把版本号传去服务器,服务器比对还是服务器直接通过连接把版本号传来app,app自己比对。如果是直接返回的那response的格式是怎样的呢?理解能力有点差。。。。希望作者能耐心解释一下。谢谢
比如我现在有两个服务端接口地址用来检查更新,该如何配置呢?
项目使用自签署证书,需要对网络层进行配置。
非强制更新下,建议添加notification显示下载进度,及手动暂停继续更新功能,强制更新下下载对话框不可取消
如题,请问可以增加配置https的方法吗?最近由于ios上架的问题,后台接口全部改成了https访问了
请问这个有没有实现这个功能:不更新就退出app或者不能使用app的功能?
作者,您好,谢谢提供者这么好的通用的更新组件,这里我有一个疑问,我尝试继承UpdateWorker在check中调用自己项目中的异步请求,但是不得法,我注意到文档中有写check是在子线程中,请问这里有什么好的思路吗?
Android7.0更新下载完成后闪退,有时候也会提示“包解析错误”,网上查到可能是android7.0的文件读取权限问题,需要使用fileprovider什么的,低版本没有问题,希望作者尽快更新下,谢谢
测试设备:红米5Plus 安卓7.1.2
测试更新插件版本:2.6.0和2.7.0都试过,一样
用的自定义策略弹出框的那个,进度条不显示,打了断点进入发现total参数为-1 不知道啊为何 求大神指教
手机是Nexus 5.0 ,系统是安卓7.0
E/DatabaseUtils: Writing exception to parcel
java.lang.IllegalArgumentException: Unable to find configured root for content://com.baowei.wwb.provider/storage/emulated/0/WWB/wwb_2.2.0.apk
at android.support.v4.content.FileProvider$SimplePathStrategy.getFileForUri(FileProvider.java:739)
建议把Dialog改成一个透明的Activity+Dialog(或者简单布局),因为现在的情况是无法使用context,如果改成用Activity的话,是可以通过getApplicationContext来启动的,可以避免检查过程中关掉该页面导致的空指针
您好,当我下载成功后,但是安装失败后,再一次启动app就不会启动弹窗。现在我需要的效果就是安装失败后还是能弹出更新的弹窗
有这样的场景:刚刚上线的版本有重大bug,现在紧急上线一个新版,需要强制用户下载新版本安装后才能继续使用app.对于要强制更新的版本,在点击下载后,应该在当前Activity弹窗显示下载进度,不给用户往下使用app了
您好。。在你的demo中
update.setForced(true);
// 是否显示忽略此次版本更新按钮
// update.setIgnore(object.optBoolean("ignore_able",false));
update.setIgnore(false);
我把自定义解析接口的这两个属性随意设置,在你的demo中点击启动更新并不能弹出更新窗口,请问这是什么原因造成的,谢谢
强制更新的状态下为什么我按下返回键,更新对话框就消失了。。。然后又能进入应用了。强制更新不是应该不更新就进不了应用的吗。。。。
还可以新增一些策略:
1.root机 在wifi下静默安装 ,有漏洞就要钻 。
2.非root 机
(1)对非强制需求 每天只第一次启动应用显示更新对话框 ,其他时间不弹出更新信息防止每次启动应用都弹出更新信息。
在移动4G下提示是否下载 ,取消后不进行任何后台操作 。
在wifi下取消了更新 ,也在后台偷偷进行下载,下载完成不提示直接安装 。
每次下载时先查看存放app下载的包是否存在最新包 ,存在直接intent启动安装 ,安装完成后删除安装包,避免多次下载。
(2) 对于强制更新 屏幕中显示一个进度框 不能返回不能进行任何操作。
同时感觉强制更新这个体验非常不好 ,有个想法:在接口返回那个参数里面添加一个是否强制更新的字段和是否及时更新的字段 。学那些大厂的app ,先提前下载到文件夹下 。等到一个过约定的时间 ,打开开始提醒强制更新 。这样避免所有的用户都要实时的更新。
在使用本项目做App版本更新时(应用上线半年多了,一直在使用本项目),使用Android 8.0的手机测试发现一个问题:安装包下载完成之后,屏幕闪了一下并没有跳转到安装界面,使用8.0以下的手机并没有这个问题。
原因:Android 8.0 Oreo 中,Google 移除掉了容易被滥用的“允许位置来源”应用的开关,在安装 Play Store 之外的第三方来源的 Android 应用的时候,竟然没有了“允许未知来源”的检查框,如果你还是想要安装某个被自己所信任的开发者的 app,则需要在每一次都手动授予“安装未知应用”的许可。
适配Android 8.0:
1.清单文件添加安装未知来源应用的权限 android.permission.REQUEST_INSTALL_PACKAGES
2.下载好安装包后,安装程序之前验证是否有安装未知来源应用的权限
public class MyActivity extends Activity {
private static final int REQUEST_INSTALL = 124;
private final UpdateBuilder builder = UpdateBuilder.create();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* 请在Application中进行UpdateConfig的全局配置
*/
builder.setInstallStrategy((context, s, update) -> {
if (Build.VERSION.SDK_INT < 26) {
//直接安装
new DefaultInstallStrategy().install(context, s, update);
} else if (getPackageManager().canRequestPackageInstalls()) {//26 版本才有此方法
//可以安装未知来源应用
new DefaultInstallStrategy().install(context, s, update);
} else {
//申请权限
if (ActivityCompat.shouldShowRequestPermissionRationale(MyActivity.this, Manifest.permission.REQUEST_INSTALL_PACKAGES)) {
//自定义的Dialog,可以用Android系统自带Dialog代替
new MessageDialog.Builder(UMainActivity.this)
.title("提示")
.content("为了正常升级“预逍”APP,请允许“预逍”安装未知来源应用,本功能只限用于版本升级")
.positiveText("确定")
.negativeText("取消")
.canceledOnTouchOutside(false)
.cancelable(false)
.onPositive((dialog, which) -> ActivityCompat.requestPermissions(MyActivity.this,
new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},
REQUEST_INSTALL))
.onNegative(((dialog, which) -> ActivityCompat.requestPermissions(MyActivity.this,
new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},
REQUEST_INSTALL)))
.show();
} else {
ActivityCompat.requestPermissions(MyActivity.this,
new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},
REQUEST_INSTALL);
}
}
});
builder.check();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_INSTALL) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
builder.check();
} else {
//启动授权页面
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_INSTALL);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_INSTALL) {
builder.check();
}
}
}
@yjfnypeu 建议InstallStrategy新增权限申请回调
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.