laoyuyu 6 years ago
parent 15978cd2b6
commit a7d3f149a1
  1. 4
      Aria/src/main/java/com/arialyy/aria/core/command/normal/ReStartCmd.java
  2. 4
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpInterceptHandler.java
  3. 49
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/IFtpUploadInterceptor.java
  4. 32
      Aria/src/main/java/com/arialyy/aria/exception/FileNotFoundException.java
  5. 5
      app/build.gradle
  6. 1
      app/src/main/AndroidManifest.xml
  7. 1
      app/src/main/java/com/arialyy/simple/core/download/DownloadActivity.java
  8. 241
      app/src/main/java/com/arialyy/simple/core/download/KotlinDownloadActivity.kt
  9. 6
      app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java
  10. 239
      app/src/main/java/com/arialyy/simple/core/upload/FtpUploadActivity.java
  11. 1
      app/src/main/java/com/arialyy/simple/modlue/CommonModule.java
  12. 4
      app/src/main/res/drawable/ic_kotlin.xml
  13. 1
      app/src/main/res/values/strings.xml

@ -0,0 +1,4 @@
package com.arialyy.aria.core.command.normal;
public class ReStartCmd {
}

@ -0,0 +1,4 @@
package com.arialyy.aria.core.common.ftp;
public class FtpInterceptHandler {
}

@ -0,0 +1,49 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.upload.UploadEntity;
import java.util.List;
/**
* FTP文件上传拦截器如果远端已有同名文件可使用该拦截器控制覆盖文件或修改该文件上传到服务器端端文件名
*/
public interface IFtpUploadInterceptor {
/**
* 如果ftp服务器端已经有同名文件控制是否覆盖远端的同名文件
* 如果你不希望覆盖远端文件可以使用{@link #resetFileName(UploadEntity, List)}
* 如果使用者同时实现{@link #resetFileName(UploadEntity, List)}{@link #coverServerFile(UploadEntity,
* List)}将优先使用{@link #resetFileName(UploadEntity, List)}
*
* @param entity 上传信息实体
* @param fileList ftp服务器端remotePath下的文件列表
* @return {@code true} 如果ftp服务器端已经有同名文件覆盖服务器端的同名文件
*/
boolean coverServerFile(UploadEntity entity, List<String> fileList);
/**
* 如果ftp服务器端已经有同名文件修改该文件上传到远端的文件名该操作不会修改本地文件名
* 如果你希望覆盖远端的同名文件可以使用{@link #coverServerFile(UploadEntity, List)}
* 如果使用者同时实现{@link #resetFileName(UploadEntity, List)}{@link #coverServerFile(UploadEntity,
* List)}将优先使用{@link #resetFileName(UploadEntity, List)}
*
* @param entity 上传信息实体
* @param fileList ftp服务器端remotePath下的文件列表
* @return 该文件上传到远端的新的文件名
*/
String resetFileName(UploadEntity entity, List<String> fileList);
}

@ -0,0 +1,32 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.exception;
/**
* Created by lyy on 2017/1/18.
* Aria 文件异常
*/
public class FileNotFoundException extends BaseException {
private static final String ARIA_FILE_EXCEPTION = "Aria File Exception:";
public FileNotFoundException(String tag, String detailMessage) {
super(tag, String.format("%s%s", ARIA_FILE_EXCEPTION, detailMessage));
}
public FileNotFoundException(String tag, String message, Exception e){
super(tag, message, e);
}
}

@ -1,7 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
//apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
@ -46,8 +46,9 @@ dependencies {
testImplementation 'junit:junit:4.12'
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "com.android.support:design:${rootProject.ext.supportLibVersion}"
implementation "org.jetbrains.kotlin:kotlin-stdlib:${rootProject.ext.kotlin_version}"
api project(':Aria')
annotationProcessor project(':AriaCompiler')
kapt project(':AriaCompiler')
// compile 'com.arialyy.aria:aria-core:3.4.0'
// annotationProcessor 'com.arialyy.aria:aria-compiler:3.4'

@ -41,6 +41,7 @@
<activity android:name=".core.download.group.FTPDirDownloadActivity"/>
<activity android:name=".core.upload.HttpUploadActivity"/>
<activity android:name=".core.upload.FtpUploadActivity"/>
<activity android:name=".core.download.KotlinDownloadActivity"/>
<service android:name=".core.download.service_download.DownloadService"/>
</application>

@ -72,6 +72,7 @@ public class DownloadActivity extends BaseActivity<ActivityDownloadMeanBinding>
module.startNextActivity(data.get(position), HighestPriorityActivity.class);
break;
case 3:
module.startNextActivity(data.get(position), KotlinDownloadActivity.class);
break;
case 4:
break;

@ -1,75 +1,166 @@
//package com.arialyy.simple.core.download
//
//import android.os.Bundle
//import android.os.Environment
//import android.support.v7.app.AppCompatActivity
//import android.util.Log
//import android.view.View
//import com.arialyy.annotations.Download
//import com.arialyy.aria.core.Aria
//import com.arialyy.aria.core.download.DownloadTask
//import com.arialyy.simple.R
//import com.arialyy.simple.base.BaseActivity
//
///**
// * Created by lyy on 2017/10/23.
// */
//class KotlinDownloadActivity : AppCompatActivity() {
//
// private val DOWNLOAD_URL = "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"
//
// private val TAG = "KotlinDownloadActivity";
//
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
// setContentView(setLayoutId())
// }
//
// fun setLayoutId(): Int {
// return R.layout.activity_single
// }
//
// fun init(savedInstanceState: Bundle?) {
// title = "单任务下载"
//// val target = Aria.download(this).load(DOWNLOAD_URL)
//// binding.progress = target.getPercent()
//// if (target.getTaskState() == IEntity.STATE_STOP) {
//// mStart.setText("恢复")
//// mStart.setTextColor(resources.getColor(android.R.color.holo_blue_light))
//// setBtState(true)
//// } else if (target.isDownloading()) {
//// setBtState(false)
//// }
//// binding.fileSize = target.getConvertFileSize()
// Aria.get(this).downloadConfig.maxTaskNum = 2
// Aria.download(this).register()
// }
//
// @Download.onTaskRunning
// protected fun running(task: DownloadTask) {
// Log.d(TAG, task.percent.toString() + "")
//// val len = task.fileSize
//// if (len == 0L) {
//// binding.progress = 0
//// } else {
//// binding.progress = task.percent
//// }
//// binding.speed = task.convertSpeed
// }
//
// fun onClick(view: View) {
// when (view.id) {
// R.id.start -> startD()
// R.id.stop -> Aria.download(this).load(DOWNLOAD_URL).stop()
// R.id.cancel -> Aria.download(this).load(DOWNLOAD_URL).cancel()
// }
// }
//
// private fun startD() {
// Aria.download(this)
// .load(DOWNLOAD_URL)
// .addHeader("groupHash", "value")
// .setDownloadPath(Environment.getExternalStorageDirectory().path + "/hhhhhhhh.apk")
// .start()
// }
//}
package com.arialyy.simple.core.download
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.Toast
import com.arialyy.annotations.Download
import com.arialyy.aria.core.Aria
import com.arialyy.aria.core.download.DownloadTarget
import com.arialyy.aria.core.download.DownloadTask
import com.arialyy.aria.core.inf.IEntity
import com.arialyy.frame.util.show.T
import com.arialyy.simple.R
import com.arialyy.simple.base.BaseActivity
import com.arialyy.simple.databinding.ActivitySingleBinding
/**
* Created by lyy on 2017/10/23.
*/
class KotlinDownloadActivity : BaseActivity<ActivitySingleBinding>() {
private val DOWNLOAD_URL =
"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"
private lateinit var mStart: Button
private lateinit var mStop: Button
private lateinit var mCancel: Button
private lateinit var target: DownloadTarget
override fun setLayoutId(): Int {
return R.layout.activity_single
}
override fun init(savedInstanceState: Bundle?) {
title = "kotlin测试"
Aria.get(this)
.downloadConfig.maxTaskNum = 2
Aria.download(this)
.register()
mStart = findViewById(R.id.start)
mStop = findViewById(R.id.stop)
mCancel = findViewById(R.id.cancel)
mStop.visibility = View.GONE
target = Aria.download(this)
.load(DOWNLOAD_URL)
binding.progress = target.percent
if (target.taskState == IEntity.STATE_STOP) {
mStart.text = "恢复"
} else if (target.isRunning) {
mStart.text = "停止"
}
binding.fileSize = target.convertFileSize
}
/**
* 注解方法不能添加internal修饰符否则会出现e: [kapt] An exception occurred: java.lang.IllegalArgumentException: index 1 for '$a' not in range (received 0 arguments)错误
*/
@Download.onTaskRunning
fun running(task: DownloadTask) {
Log.d(TAG, task.percent.toString())
val len = task.fileSize
if (len == 0L) {
binding.progress = 0
} else {
binding.progress = task.percent
}
binding.speed = task.convertSpeed
}
@Download.onWait
fun onWait(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
Log.d(TAG, "wait ==> " + task.downloadEntity.fileName)
}
}
@Download.onPre
fun onPre(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
mStart.text = "停止"
}
}
@Download.onTaskStart
fun taskStart(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
binding.fileSize = task.convertFileSize
}
}
@Download.onTaskComplete
fun complete(task: DownloadTask) {
Log.d(TAG, "完成")
}
@Download.onTaskResume
fun taskResume(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
mStart.text = "停止"
}
}
@Download.onTaskStop
fun taskStop(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
mStart.text = "恢复"
binding.speed = ""
}
}
@Download.onTaskCancel
fun taskCancel(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
binding.progress = 0
Toast.makeText(this@KotlinDownloadActivity, "取消下载", Toast.LENGTH_SHORT)
.show()
mStart.text = "开始"
binding.speed = ""
Log.d(TAG, "cancel")
}
}
@Download.onTaskFail
fun taskFail(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
Toast.makeText(this@KotlinDownloadActivity, "下载失败", Toast.LENGTH_SHORT)
.show()
mStart.text = "开始"
}
}
@Download.onNoSupportBreakPoint
fun onNoSupportBreakPoint(task: DownloadTask) {
Log.d(TAG, "该下载链接不支持断点")
if (task.key == DOWNLOAD_URL) {
T.showShort(this@KotlinDownloadActivity, "该下载链接不支持断点")
}
}
fun onClick(view: View) {
when (view.id) {
R.id.start -> {
if (target.isRunning) {
Aria.download(this)
.load(DOWNLOAD_URL)
.stop()
} else {
startD()
}
}
R.id.stop -> Aria.download(this).load(DOWNLOAD_URL).stop()
R.id.cancel -> Aria.download(this).load(DOWNLOAD_URL).cancel()
}
}
private fun startD() {
Aria.download(this)
.load(DOWNLOAD_URL)
.addHeader("groupHash", "value")
.setFilePath(Environment.getExternalStorageDirectory().path + "/kotlin.apk")
.start()
}
}

@ -64,9 +64,10 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
//"http://kotlinlang.org/docs/kotlin-docs.pdf";
//"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe";
//"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apks";
"http://hzdown.muzhiwan.com/2017/05/08/nl.noio.kingdom_59104935e56f0.apk";
//"http://120.55.95.61:8811/ghcg/zg/武义总规纲要成果.zip";
//"https://yizi-kejian.oss-cn-beijing.aliyuncs.com/qimeng/package1/qmtable11.zip";
"http://rs.0.gaoshouyou.com/d/04/1e/400423a7551e1f3f0eb1812afa1f9b44.apk";
//"http://rs.0.gaoshouyou.com/d/04/1e/400423a7551e1f3f0eb1812afa1f9b44.apk";
//"http://chargepile2.techsum.net/car-manage/file/download?path=2019-04-26/c0242efd18be4ecbb23911b1c509dcad--掌通各系统汇总.xls"; // 无长度的chunked
//"http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载
//"http://apk500.bce.baidu-mgame.com/game/67000/67734/20170622040827_oem_5502845.apk?r=1";
@ -299,7 +300,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
Aria.download(this).load(DOWNLOAD_URL).stop();
break;
case R.id.cancel:
Aria.download(this).load(DOWNLOAD_URL).cancel(true);
Aria.download(this).load(DOWNLOAD_URL).reStart();
//Aria.download(this).load(DOWNLOAD_URL).cancel(true);
//Aria.download(this).load(DOWNLOAD_URL).removeRecord();
break;
}

@ -1,113 +1,126 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.simple.core.upload;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.arialyy.annotations.Upload;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.util.FileUtil;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityFtpUploadBinding;
import java.io.File;
/**
* Created by lyy on 2017/7/28. Ftp 文件上传demo
*/
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar";
private final String URL = "ftp://9.9.9.205:2121/aa/你好";
@Override protected void init(Bundle savedInstanceState) {
setTile("D_FTP 文件上传");
super.init(savedInstanceState);
Aria.upload(this).register();
UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH);
if (entity != null) {
getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize()));
getBinding().setProgress(entity.isComplete() ? 100
: (int) (entity.getCurrentProgress() * 100 / entity.getFileSize()));
}
}
@Override protected int setLayoutId() {
return R.layout.activity_ftp_upload;
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).login("lao", "123456").start();
break;
case R.id.stop:
Aria.upload(this).loadFtp(FILE_PATH).stop();
break;
case R.id.cancel:
Aria.upload(this).loadFtp(FILE_PATH).cancel();
break;
}
}
@Upload.onWait void onWait(UploadTask task) {
Log.d(TAG, task.getTaskName() + "_wait");
}
@Upload.onPre public void onPre(UploadTask task) {
getBinding().setFileSize(task.getConvertFileSize());
}
@Upload.onTaskStart public void taskStart(UploadTask task) {
Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath())));
}
@Upload.onTaskResume public void taskResume(UploadTask task) {
Log.d(TAG, "恢复上传");
}
@Upload.onTaskStop public void taskStop(UploadTask task) {
getBinding().setSpeed("");
Log.d(TAG, "停止上传");
}
@Upload.onTaskCancel public void taskCancel(UploadTask task) {
getBinding().setSpeed("");
getBinding().setFileSize("");
getBinding().setProgress(0);
Log.d(TAG, "删除任务");
}
@Upload.onTaskFail public void taskFail(UploadTask task) {
Log.d(TAG, "上传失败");
}
@Upload.onTaskRunning public void taskRunning(UploadTask task) {
Log.d(TAG, "PP = " + task.getPercent());
getBinding().setProgress(task.getPercent());
getBinding().setSpeed(task.getConvertSpeed());
}
@Upload.onTaskComplete public void taskComplete(UploadTask task) {
getBinding().setProgress(100);
getBinding().setSpeed("");
T.showShort(this, "文件:" + task.getEntity().getFileName() + ",上传完成");
}
}
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.simple.core.upload;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.arialyy.annotations.Upload;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.ftp.FtpInterceptHandler;
import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.util.FileUtil;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityFtpUploadBinding;
import java.io.File;
import java.util.List;
/**
* Created by lyy on 2017/7/28. Ftp 文件上传demo
*/
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar";
private final String URL = "ftp://9.9.9.205:2121/aa/你好";
@Override protected void init(Bundle savedInstanceState) {
setTile("D_FTP 文件上传");
super.init(savedInstanceState);
Aria.upload(this).register();
UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH);
if (entity != null) {
getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize()));
getBinding().setProgress(entity.isComplete() ? 100
: (int) (entity.getCurrentProgress() * 100 / entity.getFileSize()));
}
}
@Override protected int setLayoutId() {
return R.layout.activity_ftp_upload;
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).setUploadInterceptor(
new IFtpUploadInterceptor() {
@Override
public FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList) {
FtpInterceptHandler.Builder builder = new FtpInterceptHandler.Builder();
builder.coverServerFile();
//builder.resetFileName("test");
return builder.build();
}
}).login("lao", "123456").start();
break;
case R.id.stop:
Aria.upload(this).loadFtp(FILE_PATH).stop();
break;
case R.id.cancel:
Aria.upload(this).loadFtp(FILE_PATH).cancel();
break;
}
}
@Upload.onWait void onWait(UploadTask task) {
Log.d(TAG, task.getTaskName() + "_wait");
}
@Upload.onPre public void onPre(UploadTask task) {
getBinding().setFileSize(task.getConvertFileSize());
}
@Upload.onTaskStart public void taskStart(UploadTask task) {
Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath())));
}
@Upload.onTaskResume public void taskResume(UploadTask task) {
Log.d(TAG, "恢复上传");
}
@Upload.onTaskStop public void taskStop(UploadTask task) {
getBinding().setSpeed("");
Log.d(TAG, "停止上传");
}
@Upload.onTaskCancel public void taskCancel(UploadTask task) {
getBinding().setSpeed("");
getBinding().setFileSize("");
getBinding().setProgress(0);
Log.d(TAG, "删除任务");
}
@Upload.onTaskFail public void taskFail(UploadTask task) {
Log.d(TAG, "上传失败");
}
@Upload.onTaskRunning public void taskRunning(UploadTask task) {
Log.d(TAG, "PP = " + task.getPercent());
getBinding().setProgress(task.getPercent());
getBinding().setSpeed(task.getConvertSpeed());
}
@Upload.onTaskComplete public void taskComplete(UploadTask task) {
getBinding().setProgress(100);
getBinding().setSpeed("");
T.showShort(this, "文件:" + task.getEntity().getFileName() + ",上传完成");
}
}

@ -65,6 +65,7 @@ public class CommonModule extends AbsModule {
R.drawable.ic_http,
R.drawable.ic_http_group,
R.drawable.ic_top,
R.drawable.ic_kotlin,
R.drawable.ic_server,
R.drawable.ic_windows
};

@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="1024"
android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/icon_color" android:pathData="M863.1,914.43a116.03,116.03 0,0 1,-166.4 8.32L419.9,665.6q-2.18,-1.79 -4.29,-3.9L633.6,537.98l221.31,205.63a123.01,123.01 0,0 1,8.19 170.82zM381.82,280.83v-23.49A128,128 0,0 0,255.62 128a128,128 0,0 0,-126.21 129.34L129.41,424.32zM128,822.02v7.23A129.22,129.22 0,0 0,255.62 960a129.22,129.22 0,0 0,127.62 -130.75L383.23,677.25zM881.22,196.35a116.54,116.54 0,0 0,-160.38 -47.17l-587.52,333.44v276.48l701.82,-398.34a122.5,122.5 0,0 0,46.08 -164.42z"/>
</vector>

@ -24,6 +24,7 @@
<item>单任务下载</item>
<item>多任务下载</item>
<item>高优先级任务</item>
<item>kotlin</item>
<item>Service中使用</item>
<item>组件中使用</item>
</string-array>

Loading…
Cancel
Save