Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
A
apk_update
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
openSourceLibrary
apk_update
Commits
c976bf41
提交
c976bf41
authored
7月 31, 2025
作者:
祁增奎
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
1.Android增加OSS本地进行STS认证
2.增加配置参数以及方法
上级
68b1a2a9
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
232 行增加
和
42 行删除
+232
-42
CHANGELOG.md
CHANGELOG.md
+6
-1
ApkUpdatePlugin.kt
...oid/src/main/kotlin/com/clx/apk_update/ApkUpdatePlugin.kt
+31
-0
DownloadApp.kt
android/src/main/kotlin/com/clx/apk_update/DownloadApp.kt
+28
-7
apk_update_method_channel.dart
lib/apk_update_method_channel.dart
+22
-2
apk_update_platform_interface.dart
lib/apk_update_platform_interface.dart
+22
-2
app_upgrade_factory.dart
lib/app_upgrade_factory.dart
+9
-8
app_upgrade_config.dart
lib/core/common/app_upgrade_config.dart
+62
-0
download_service_factory.dart
...e/services/download_service/download_service_factory.dart
+12
-0
oss_download_impl.dart
...ore/services/download_service/impl/oss_download_impl.dart
+39
-21
pubspec.yaml
pubspec.yaml
+1
-1
没有找到文件。
CHANGELOG.md
浏览文件 @
c976bf41
##
0.0.1
##
1.0.0
*
TODO: Describe initial release.
*
TODO: Describe initial release.
## 1.0.1
*
MAINTENANCE: 增加外部控制,使用OSS模式还是普通模式
\ No newline at end of file
android/src/main/kotlin/com/clx/apk_update/ApkUpdatePlugin.kt
浏览文件 @
c976bf41
...
@@ -6,6 +6,7 @@ import android.content.Intent
...
@@ -6,6 +6,7 @@ import android.content.Intent
import
android.util.Log
import
android.util.Log
import
androidx.annotation.NonNull
import
androidx.annotation.NonNull
import
com.clx.apk_update.DownloadAppUtil.aliDownload
import
com.clx.apk_update.DownloadAppUtil.aliDownload
import
com.clx.apk_update.DownloadAppUtil.downloadApkWithoutSTS
import
io.flutter.embedding.engine.plugins.FlutterPlugin
import
io.flutter.embedding.engine.plugins.FlutterPlugin
import
io.flutter.plugin.common.MethodCall
import
io.flutter.plugin.common.MethodCall
...
@@ -85,6 +86,36 @@ class ApkUpdatePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHan
...
@@ -85,6 +86,36 @@ class ApkUpdatePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHan
}
}
"downloadApkWithoutSTS"
->
{
val
data
=
call
.
arguments
<
Map
<
String
,
String
>>()
val
ak
=
data
?.
get
(
"ak"
)
val
sk
=
data
?.
get
(
"sk"
)
val
endpoint
=
data
?.
get
(
"endpoint"
)
val
bucketName
=
data
?.
get
(
"bucketName"
)
val
objectKey
=
data
?.
get
(
"objectKey"
)
val
localPath
=
data
?.
get
(
"localPath"
)
val
localFileName
=
data
?.
get
(
"localFileName"
)
if
(
ak
==
null
||
sk
==
null
||
endpoint
==
null
||
bucketName
==
null
||
objectKey
==
null
||
localPath
==
null
||
localFileName
==
null
)
{
result
.
error
(
"error"
,
"data is null"
,
null
)
return
}
Log
.
d
(
"InstallAPKPlugin"
,
"setupMethodChannel: $ak $sk $endpoint $bucketName $objectKey $localPath"
)
downloadApkWithoutSTS
(
mContext
,
ak
,
sk
,
endpoint
,
bucketName
,
objectKey
,
localPath
,
localFileName
,
this
)
}
else
->
{
else
->
{
result
.
notImplemented
()
result
.
notImplemented
()
}
}
...
...
android/src/main/kotlin/com/clx/apk_update/DownloadApp.kt
浏览文件 @
c976bf41
...
@@ -2,12 +2,14 @@ package com.clx.apk_update
...
@@ -2,12 +2,14 @@ package com.clx.apk_update
import
android.content.Context
import
android.content.Context
import
android.util.Log
import
android.util.Log
import
com.alibaba.sdk.android.oss.ClientConfiguration
import
com.alibaba.sdk.android.oss.ClientException
import
com.alibaba.sdk.android.oss.ClientException
import
com.alibaba.sdk.android.oss.OSSClient
import
com.alibaba.sdk.android.oss.OSSClient
import
com.alibaba.sdk.android.oss.ServiceException
import
com.alibaba.sdk.android.oss.ServiceException
import
com.alibaba.sdk.android.oss.callback.OSSCompletedCallback
import
com.alibaba.sdk.android.oss.callback.OSSCompletedCallback
import
com.alibaba.sdk.android.oss.callback.OSSProgressCallback
import
com.alibaba.sdk.android.oss.callback.OSSProgressCallback
import
com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider
import
com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider
import
com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider
import
com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider
import
com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider
import
com.alibaba.sdk.android.oss.internal.OSSAsyncTask
import
com.alibaba.sdk.android.oss.internal.OSSAsyncTask
import
com.alibaba.sdk.android.oss.model.ResumableDownloadRequest
import
com.alibaba.sdk.android.oss.model.ResumableDownloadRequest
...
@@ -30,9 +32,33 @@ object DownloadAppUtil {
...
@@ -30,9 +32,33 @@ object DownloadAppUtil {
localFileName
:
String
,
localFileName
:
String
,
progressCallback
:
ProgressCallback
progressCallback
:
ProgressCallback
)
{
)
{
downloadApkFile
(
context
,
OSSStsTokenCredentialProvider
(
ak
,
sk
,
token
),
endpoint
,
bucketName
,
objectKey
,
localPath
,
localFileName
,
progressCallback
)
}
val
credentialProvider
:
OSSCredentialProvider
=
OSSStsTokenCredentialProvider
(
ak
,
sk
,
token
)
fun
downloadApkWithoutSTS
(
val
oss
=
OSSClient
(
context
,
endpoint
,
credentialProvider
)
context
:
Context
,
ak
:
String
,
sk
:
String
,
endpoint
:
String
,
bucketName
:
String
,
objectKey
:
String
,
localPath
:
String
,
localFileName
:
String
,
progressCallback
:
ProgressCallback
)
{
// 使用AccessKey和SecretKey创建凭证提供者
downloadApkFile
(
context
,
OSSPlainTextAKSKCredentialProvider
(
ak
,
sk
),
endpoint
,
bucketName
,
objectKey
,
localPath
,
localFileName
,
progressCallback
)
}
private
fun
downloadApkFile
(
context
:
Context
,
provider
:
OSSCredentialProvider
,
endpoint
:
String
,
bucketName
:
String
,
objectKey
:
String
,
localPath
:
String
,
localFileName
:
String
,
progressCallback
:
ProgressCallback
)
{
val
oss
=
OSSClient
(
context
,
endpoint
,
provider
)
// 填写下载到本地文件所在的完整路径。
// 填写下载到本地文件所在的完整路径。
...
@@ -77,9 +103,5 @@ object DownloadAppUtil {
...
@@ -77,9 +103,5 @@ object DownloadAppUtil {
Log
.
d
(
TAG
,
"aliDownload: task.isCompleted = ${task.isCompleted}"
)
Log
.
d
(
TAG
,
"aliDownload: task.isCompleted = ${task.isCompleted}"
)
}
}
}
}
\ No newline at end of file
lib/apk_update_method_channel.dart
浏览文件 @
c976bf41
...
@@ -24,7 +24,7 @@ class MethodChannelApkUpdate extends ApkUpdatePlatform {
...
@@ -24,7 +24,7 @@ class MethodChannelApkUpdate extends ApkUpdatePlatform {
@override
@override
void
downloadApk
(
String
ak
,
String
sk
,
String
token
,
String
objectKey
,
void
downloadApk
(
String
ak
,
String
sk
,
String
token
,
String
objectKey
,
String
endpoint
,
String
bucketName
,
String
localPath
,
localFileName
)
{
String
endpoint
,
String
bucketName
,
String
localPath
,
localFileName
)
{
methodChannel
.
invokeMethod
<
String
>(
'downloadInstall'
,
{
methodChannel
.
invokeMethod
<
String
>(
'downloadInstall'
,
{
"ak"
:
ak
,
"ak"
:
ak
,
"sk"
:
sk
,
"sk"
:
sk
,
...
@@ -33,7 +33,27 @@ class MethodChannelApkUpdate extends ApkUpdatePlatform {
...
@@ -33,7 +33,27 @@ class MethodChannelApkUpdate extends ApkUpdatePlatform {
"endpoint"
:
endpoint
,
"endpoint"
:
endpoint
,
"bucketName"
:
bucketName
,
"bucketName"
:
bucketName
,
"localPath"
:
localPath
,
"localPath"
:
localPath
,
"localFileName"
:
localFileName
,
"localFileName"
:
localFileName
,
});
}
@override
void
downloadApkWithoutSTS
(
String
ak
,
String
sk
,
String
objectKey
,
String
endpoint
,
String
bucketName
,
String
localPath
,
String
localFileName
)
{
methodChannel
.
invokeMethod
<
String
>(
'downloadApkWithoutSTS'
,
{
"ak"
:
ak
,
"sk"
:
sk
,
"objectKey"
:
objectKey
,
"endpoint"
:
endpoint
,
"bucketName"
:
bucketName
,
"localPath"
:
localPath
,
"localFileName"
:
localFileName
,
});
});
}
}
...
...
lib/apk_update_platform_interface.dart
浏览文件 @
c976bf41
...
@@ -32,11 +32,31 @@ abstract class ApkUpdatePlatform extends PlatformInterface {
...
@@ -32,11 +32,31 @@ abstract class ApkUpdatePlatform extends PlatformInterface {
}
}
//支持断点下载并安装
//支持断点下载并安装
void
downloadApk
(
String
ak
,
String
sk
,
String
token
,
String
objectKey
,
void
downloadApk
(
String
endpoint
,
String
bucketName
,
String
localPath
,
String
localFileName
)
{
String
ak
,
String
sk
,
String
token
,
String
objectKey
,
String
endpoint
,
String
bucketName
,
String
localPath
,
String
localFileName
)
{
throw
UnimplementedError
(
'downloadApk() has not been implemented.'
);
throw
UnimplementedError
(
'downloadApk() has not been implemented.'
);
}
}
// 支持断点下载安装(不通过服务器验证STS)
void
downloadApkWithoutSTS
(
String
ak
,
String
sk
,
String
objectKey
,
String
endpoint
,
String
bucketName
,
String
localPath
,
String
localFileName
)
{
throw
UnimplementedError
(
'downloadApkWithoutSTS() has not been implemented.'
);
}
// 添加下载进度监听
// 添加下载进度监听
Stream
<
Map
<
String
,
Object
>>
addDownloadListener
()
{
Stream
<
Map
<
String
,
Object
>>
addDownloadListener
()
{
throw
UnimplementedError
(
'addDownloadListener() has not been implemented.'
);
throw
UnimplementedError
(
'addDownloadListener() has not been implemented.'
);
...
...
lib/app_upgrade_factory.dart
浏览文件 @
c976bf41
...
@@ -12,20 +12,21 @@ class AppUpgradeFactory {
...
@@ -12,20 +12,21 @@ class AppUpgradeFactory {
assert
(
config
.
token
!=
null
&&
config
.
token
!.
isNotEmpty
,
"请传递token参数"
);
assert
(
config
.
token
!=
null
&&
config
.
token
!.
isNotEmpty
,
"请传递token参数"
);
assert
(
config
.
productCode
!=
null
,
"请传递productCode参数"
);
assert
(
config
.
productCode
!=
null
,
"请传递productCode参数"
);
DioUpdateUtil
.
dio
.
options
.
headers
=
{
DioUpdateUtil
.
dio
.
options
.
headers
=
{...
config
.
headers
??
{}};
...
config
.
headers
??
{}
};
// 配置版本服务
// 配置版本服务
VersionService
versionService
=
VersionServiceFactory
.
create
(
VersionService
versionService
=
VersionServiceFactory
.
create
(
config:
config
,
config:
config
,
type:
config
.
type
??
"pm"
,
type:
config
.
type
??
"pm"
,
);
);
// 配置下载服务
// 配置下载服务
DownloadService
downloadService
=
DownloadServiceFactory
.
create
(
DownloadService
downloadService
=
config
.
needSTS
==
true
baseUrl:
config
.
baseUrl
,
?
DownloadServiceFactory
.
create
(
token:
config
.
token
!,
baseUrl:
config
.
baseUrl
,
productCode:
config
.
productCode
!,
token:
config
.
token
!,
);
productCode:
config
.
productCode
!,
)
:
DownloadServiceFactory
.
createWithoutToken
(
baseUrl:
config
.
baseUrl
,
productCode:
config
.
productCode
!);
return
AppUpgradeControl
(
return
AppUpgradeControl
(
versionService:
versionService
,
versionService:
versionService
,
...
...
lib/core/common/app_upgrade_config.dart
浏览文件 @
c976bf41
...
@@ -32,6 +32,11 @@ class AppUpgradeConfig {
...
@@ -32,6 +32,11 @@ class AppUpgradeConfig {
/// 顶部图片
/// 顶部图片
final
ImageProvider
?
topImageProvider
;
final
ImageProvider
?
topImageProvider
;
/// 是否需要请求STS鉴权
final
bool
?
needSTS
;
@Deprecated
(
'请使用AppUpgradeConfig.msl、AppUpgradeConfig.carrier、msl、AppUpgradeConfig.pm、AppUpgradeConfig.pmOSS代替'
)
const
AppUpgradeConfig
({
const
AppUpgradeConfig
({
required
this
.
baseUrl
,
required
this
.
baseUrl
,
this
.
onceDay
=
false
,
this
.
onceDay
=
false
,
...
@@ -43,5 +48,62 @@ class AppUpgradeConfig {
...
@@ -43,5 +48,62 @@ class AppUpgradeConfig {
this
.
type
,
this
.
type
,
this
.
headers
,
this
.
headers
,
this
.
topImageProvider
,
this
.
topImageProvider
,
this
.
needSTS
=
true
,
});
});
/// 老马上来(建议走这个配置)
const
AppUpgradeConfig
.
msl
({
required
this
.
baseUrl
,
required
this
.
productNo
,
this
.
onceDay
=
false
,
this
.
token
,
this
.
productCode
,
this
.
appleId
,
this
.
versionNumber
,
this
.
headers
,
this
.
topImageProvider
,
this
.
needSTS
=
true
,
})
:
type
=
'msl'
;
/// 承运(建议走这个配置)
const
AppUpgradeConfig
.
carrier
({
required
this
.
baseUrl
,
this
.
onceDay
=
false
,
this
.
token
,
this
.
productCode
,
this
.
appleId
,
this
.
versionNumber
,
this
.
headers
,
this
.
topImageProvider
,
this
.
needSTS
=
true
,
})
:
type
=
'carrier'
,
productNo
=
null
;
/// 项目管理工具(自动配置走OSS还是普通下载,需要Token鉴权)
const
AppUpgradeConfig
.
pm
({
required
this
.
baseUrl
,
this
.
onceDay
=
false
,
this
.
token
,
this
.
productCode
,
this
.
appleId
,
this
.
versionNumber
,
this
.
headers
,
this
.
topImageProvider
,
})
:
type
=
'pm'
,
productNo
=
null
,
needSTS
=
true
;
/// 项目管理工具(自动配置走OSS还是普通下载,不需要Token鉴权)
const
AppUpgradeConfig
.
pmOSS
({
required
this
.
baseUrl
,
this
.
onceDay
=
false
,
this
.
productCode
,
this
.
appleId
,
this
.
versionNumber
,
this
.
headers
,
this
.
topImageProvider
,
})
:
type
=
'pm'
,
token
=
'此Token无效,只为了兼容'
,
productNo
=
null
,
needSTS
=
false
;
}
}
lib/core/services/download_service/download_service_factory.dart
浏览文件 @
c976bf41
...
@@ -18,4 +18,16 @@ class DownloadServiceFactory {
...
@@ -18,4 +18,16 @@ class DownloadServiceFactory {
return
NormalDownloadImpl
();
return
NormalDownloadImpl
();
}
}
}
}
static
DownloadService
createWithoutToken
({
required
String
baseUrl
,
required
String
productCode
,
})
{
if
(
baseUrl
.
startsWith
(
"https://gateway."
))
{
return
OSSDownloadImpl
.
withoutToken
(
baseUrl:
baseUrl
,
productCode:
productCode
);
}
else
{
return
NormalDownloadImpl
();
}
}
}
}
lib/core/services/download_service/impl/oss_download_impl.dart
浏览文件 @
c976bf41
...
@@ -17,13 +17,20 @@ class OSSDownloadImpl implements DownloadService {
...
@@ -17,13 +17,20 @@ class OSSDownloadImpl implements DownloadService {
final
String
baseUrl
;
final
String
baseUrl
;
final
String
token
;
final
String
token
;
final
String
productCode
;
final
String
productCode
;
final
bool
needSTS
;
StreamSubscription
<
Map
<
String
,
Object
>>?
_subscription
;
StreamSubscription
<
Map
<
String
,
Object
>>?
_subscription
;
OSSDownloadImpl
({
OSSDownloadImpl
({
required
this
.
baseUrl
,
required
this
.
baseUrl
,
required
this
.
token
,
required
this
.
token
,
required
this
.
productCode
,
required
this
.
productCode
,
});
})
:
needSTS
=
true
;
OSSDownloadImpl
.
withoutToken
({
required
this
.
baseUrl
,
required
this
.
productCode
,
})
:
token
=
""
,
needSTS
=
false
;
@override
@override
Future
<
void
>
download
({
Future
<
void
>
download
({
...
@@ -47,17 +54,7 @@ class OSSDownloadImpl implements DownloadService {
...
@@ -47,17 +54,7 @@ class OSSDownloadImpl implements DownloadService {
}
}
// 删除历史下载文件
// 删除历史下载文件
await
deleteFiles
(
Directory
(
path
));
await
deleteFiles
(
Directory
(
path
));
var
ossInfo
=
await
getOssInfo
();
if
(
ossInfo
==
null
)
{
onError
?.
call
(
Exception
(
"oss信息获取失败,请稍后重新"
));
return
;
}
// 使用OSS下载
var
ak
=
ossInfo
?[
'onceAccessKeyId'
];
var
sk
=
ossInfo
?[
"onceAccessKeySecret"
];
var
token
=
ossInfo
?[
"onceSecurityToken"
];
var
objectKey
=
getObjectKey
(
url
);
var
localPathFileName
=
getFileName
(
objectKey
);
_subscription
=
_subscription
=
ApkUpdatePlatform
.
instance
.
addDownloadListener
().
listen
((
event
)
{
ApkUpdatePlatform
.
instance
.
addDownloadListener
().
listen
((
event
)
{
var
count
=
event
[
'currentSize'
]
as
num
;
var
count
=
event
[
'currentSize'
]
as
num
;
...
@@ -78,15 +75,36 @@ class OSSDownloadImpl implements DownloadService {
...
@@ -78,15 +75,36 @@ class OSSDownloadImpl implements DownloadService {
onProgress
?.
call
(
progress
);
// 下载进度
onProgress
?.
call
(
progress
);
// 下载进度
});
});
ApkUpdatePlatform
.
instance
.
downloadApk
(
final
objectKey
=
getObjectKey
(
url
);
ak
,
if
(
needSTS
)
{
sk
,
var
ossInfo
=
await
getOssInfo
();
token
,
if
(
ossInfo
==
null
)
{
objectKey
,
onError
?.
call
(
Exception
(
"oss信息获取失败,请稍后重新"
));
Constants
.
ossEndpoint
,
return
;
getOssBucketName
(),
}
path
,
// 使用OSS下载
localPathFileName
);
var
ak
=
ossInfo
?[
'onceAccessKeyId'
];
var
sk
=
ossInfo
?[
"onceAccessKeySecret"
];
var
token
=
ossInfo
?[
"onceSecurityToken"
];
ApkUpdatePlatform
.
instance
.
downloadApk
(
ak
,
sk
,
token
,
objectKey
,
Constants
.
ossEndpoint
,
getOssBucketName
(),
path
,
getFileName
(
objectKey
));
}
else
{
ApkUpdatePlatform
.
instance
.
downloadApkWithoutSTS
(
'LTAI5t9tqPPGM2g8YE8g899t'
,
'ENGYeR4r5TQdeYz7C51KBsrwE89g7d'
,
objectKey
,
Constants
.
ossEndpoint
,
getOssBucketName
(),
path
,
getFileName
(
objectKey
));
}
}
catch
(
e
)
{
}
catch
(
e
)
{
debugPrint
(
e
.
toString
());
debugPrint
(
e
.
toString
());
onError
?.
call
(
Exception
(
e
.
toString
()));
onError
?.
call
(
Exception
(
e
.
toString
()));
...
...
pubspec.yaml
浏览文件 @
c976bf41
name
:
apk_update
name
:
apk_update
description
:
A new Flutter project.
description
:
A new Flutter project.
version
:
1.0.
0
version
:
1.0.
1
homepage
:
homepage
:
environment
:
environment
:
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论